1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
40 #define BETTER_LITERAL_SHIFT
42 char *aopLiteral (value * val, int offset);
45 /* this is the down and dirty file with all kinds of
46 kludgy & hacky stuff. This is what it is all about
47 CODE GENERATION for a specific MCU . some of the
48 routines may be reusable, will have to see */
50 static char *zero = "#0";
51 static char *one = "#1";
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
59 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
87 static char *rb1regs[] = {
88 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
91 static void saveRBank (int, iCode *, bool);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG "_ap"
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112 0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
121 #define PROTECT_SP {if (options.protect_sp_update) { \
122 symbol *lbl = newiTempLabel(NULL); \
123 emitcode ("setb","F1"); \
124 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
125 emitcode ("clr","F1"); \
126 emitcode ("","!tlabeldef",lbl->key+100); \
128 #define UNPROTECT_SP { if (options.protect_sp_update) { \
129 symbol *lbl = newiTempLabel(NULL); \
130 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
131 emitcode ("setb","EA"); \
132 emitcode ("","!tlabeldef",lbl->key+100); \
135 static int _currentDPS; /* Current processor DPS. */
136 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, char *fmt,...)
146 char lb[INITIAL_INLINEASM];
155 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
159 SNPRINTF (lb, sizeof(lb), "%s", inst);
162 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
167 tvsprintf (lb, sizeof(lb), fmt, ap);
171 while (isspace (*lbp))
178 lineCurr = (lineCurr ?
179 connectLine (lineCurr, newLineNode (lb)) :
180 (lineHead = newLineNode (lb)));
183 lineCurr->isInline = _G.inLine;
184 lineCurr->isDebug = _G.debugLine;
185 lineCurr->ic = _G.current_iCode;
186 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
191 // Move the passed value into A unless it is already there.
196 if (strcmp(s,"a") && strcmp(s,"acc"))
198 emitcode("mov","a,%s",s);
203 // Move the passed value into B unless it is already there.
210 emitcode("mov","b,%s",s);
214 /*-----------------------------------------------------------------*/
215 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
216 /*-----------------------------------------------------------------*/
218 getFreePtr (iCode * ic, asmop ** aopp, bool result)
223 /* the logic: if r0 & r1 used in the instruction
224 then we are in trouble otherwise */
226 /* first check if r0 & r1 are used by this
227 instruction, in which case we are in trouble */
228 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
229 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
234 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
235 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
237 /* if no usage of r0 then return it */
240 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
241 (*aopp)->type = AOP_R0;
243 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
246 /* if no usage of r1 then return it */
249 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
250 (*aopp)->type = AOP_R1;
252 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
255 /* now we know they both have usage */
256 /* if r0 not used in this instruction */
259 /* push it if not already pushed */
262 emitcode ("push", "%s",
263 ds390_regWithIdx (R0_IDX)->dname);
267 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
268 (*aopp)->type = AOP_R0;
270 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
273 /* if r1 not used then */
277 /* push it if not already pushed */
280 emitcode ("push", "%s",
281 ds390_regWithIdx (R1_IDX)->dname);
285 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
286 (*aopp)->type = AOP_R1;
287 return ds390_regWithIdx (R1_IDX);
291 /* I said end of world but not quite end of world yet */
292 /* if this is a result then we can push it on the stack */
295 (*aopp)->type = AOP_STK;
299 /* other wise this is true end of the world */
300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
301 "getFreePtr should never reach here");
304 return NULL; // notreached, but makes compiler happy.
307 /*-----------------------------------------------------------------*/
308 /* newAsmop - creates a new asmOp */
309 /*-----------------------------------------------------------------*/
311 newAsmop (short type)
315 aop = Safe_calloc (1, sizeof (asmop));
321 /*-----------------------------------------------------------------*/
322 /* genSetDPTR: generate code to select which DPTR is in use (zero */
323 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
324 /* alternate DPTR (DPL1/DPH1/DPX1). */
325 /*-----------------------------------------------------------------*/
330 /* If we are doing lazy evaluation, simply note the desired
331 * change, but don't emit any code yet.
341 emitcode ("mov", "dps,#0");
346 emitcode ("mov", "dps,#1");
350 /*-----------------------------------------------------------------*/
351 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
353 /* Any code that operates on DPTR (NB: not on the individual */
354 /* components, like DPH) *must* call _flushLazyDPS() before using */
355 /* DPTR within a lazy DPS evaluation block. */
357 /* Note that aopPut and aopGet already contain the proper calls to */
358 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
359 /* DPS evaluation block. */
361 /* Also, _flushLazyDPS must be called before any flow control */
362 /* operations that could potentially branch out of the block. */
364 /* Lazy DPS evaluation is simply an optimization (though an */
365 /* important one), so if in doubt, leave it out. */
366 /*-----------------------------------------------------------------*/
368 _startLazyDPSEvaluation (void)
372 #ifdef BETTER_LITERAL_SHIFT
379 /*-----------------------------------------------------------------*/
380 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
381 /* desired one. Call before using DPTR within a lazy DPS evaluation */
383 /*-----------------------------------------------------------------*/
393 if (_desiredDPS != _currentDPS)
397 emitcode ("inc", "dps");
401 emitcode ("dec", "dps");
403 _currentDPS = _desiredDPS;
407 /*-----------------------------------------------------------------*/
408 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
410 /* Forces us back to the safe state (standard DPTR selected). */
411 /*-----------------------------------------------------------------*/
413 _endLazyDPSEvaluation (void)
415 #ifdef BETTER_LITERAL_SHIFT
434 /*-----------------------------------------------------------------*/
435 /* pointerCode - returns the code for a pointer type */
436 /*-----------------------------------------------------------------*/
438 pointerCode (sym_link * etype)
441 return PTR_TYPE (SPEC_OCLS (etype));
445 /*-----------------------------------------------------------------*/
446 /* leftRightUseAcc - returns size of accumulator use by operands */
447 /*-----------------------------------------------------------------*/
449 leftRightUseAcc(iCode *ic)
458 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
459 "null iCode pointer");
466 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
469 size = getSize (OP_SYMBOL (op)->type);
474 else if (ic->op == JUMPTABLE)
477 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
480 size = getSize (OP_SYMBOL (op)->type);
488 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
491 size = getSize (OP_SYMBOL (op)->type);
496 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
499 size = getSize (OP_SYMBOL (op)->type);
511 /*-----------------------------------------------------------------*/
512 /* aopForSym - for a true symbol */
513 /*-----------------------------------------------------------------*/
515 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
518 memmap *space = SPEC_OCLS (sym->etype);
519 int accuse = leftRightUseAcc (ic);
521 /* if already has one */
524 if ((sym->aop->type == AOP_DPTR && useDP2)
525 || (sym->aop->type == AOP_DPTR2 && !useDP2))
531 /* assign depending on the storage class */
532 /* if it is on the stack or indirectly addressable */
533 /* space we need to assign either r0 or r1 to it */
534 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
536 sym->aop = aop = newAsmop (0);
537 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
538 aop->size = getSize (sym->type);
540 /* now assign the address of the variable to
541 the pointer register */
542 if (aop->type != AOP_STK)
547 if (_G.accInUse || accuse)
548 emitcode ("push", "acc");
550 if (_G.bInUse || (accuse>1))
551 emitcode ("push", "b");
553 emitcode ("mov", "a,_bp");
554 emitcode ("add", "a,#!constbyte",
556 ((char) (sym->stack - _G.nRegsSaved)) :
557 ((char) sym->stack)) & 0xff);
558 emitcode ("mov", "%s,a",
559 aop->aopu.aop_ptr->name);
561 if (_G.bInUse || (accuse>1))
562 emitcode ("pop", "b");
564 if (_G.accInUse || accuse)
565 emitcode ("pop", "acc");
568 emitcode ("mov", "%s,#%s",
569 aop->aopu.aop_ptr->name,
571 aop->paged = space->paged;
574 aop->aopu.aop_stk = sym->stack;
578 if (sym->onStack && options.stack10bit)
580 short stack_val = -((sym->stack < 0) ?
581 ((short) (sym->stack - _G.nRegsSaved)) :
582 ((short) sym->stack)) ;
583 if (useDP2 && _G.dptr1InUse) {
584 emitcode ("push","dpl1");
585 emitcode ("push","dph1");
586 emitcode ("push","dpx1");
587 } else if (_G.dptrInUse ) {
588 emitcode ("push","dpl");
589 emitcode ("push","dph");
590 emitcode ("push","dpx");
592 /* It's on the 10 bit stack, which is located in
595 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
597 if (options.model == MODEL_FLAT24)
599 emitcode ("mov", "dpx1,#!constbyte",
600 (options.stack_loc >> 16) & 0xff);
602 emitcode ("mov", "dph1,_bpx+1");
604 emitcode ("mov", "dpl1,_bpx");
605 emitcode ("mov","dps,#1");
607 if (options.model == MODEL_FLAT24)
609 emitcode ("mov", "dpx,#!constbyte",
610 (options.stack_loc >> 16) & 0xff);
612 emitcode ("mov", "dph,_bpx+1");
613 emitcode ("mov", "dpl,_bpx");
615 stack_val = -stack_val;
616 while (stack_val--) {
617 emitcode ("inc","dptr");
620 emitcode("mov","dps,#0");
623 if (_G.accInUse || accuse)
624 emitcode ("push", "acc");
626 if (_G.bInUse || (accuse>1))
627 emitcode ("push", "b");
629 emitcode ("mov", "a,_bpx");
630 emitcode ("clr","c");
631 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
632 emitcode ("mov","b,a");
633 emitcode ("mov","a,_bpx+1");
634 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
636 if (options.model == MODEL_FLAT24)
638 emitcode ("mov", "dpx1,#!constbyte",
639 (options.stack_loc >> 16) & 0xff);
641 emitcode ("mov", "dph1,a");
642 emitcode ("mov", "dpl1,b");
644 if (options.model == MODEL_FLAT24)
646 emitcode ("mov", "dpx,#!constbyte",
647 (options.stack_loc >> 16) & 0xff);
649 emitcode ("mov", "dph,a");
650 emitcode ("mov", "dpl,b");
653 if (_G.bInUse || (accuse>1))
654 emitcode ("pop", "b");
656 if (_G.accInUse || accuse)
657 emitcode ("pop", "acc");
659 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
660 aop->size = getSize (sym->type);
664 /* if in bit space */
665 if (IN_BITSPACE (space))
667 sym->aop = aop = newAsmop (AOP_CRY);
668 aop->aopu.aop_dir = sym->rname;
669 aop->size = getSize (sym->type);
672 /* if it is in direct space */
673 if (IN_DIRSPACE (space))
675 sym->aop = aop = newAsmop (AOP_DIR);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
681 /* special case for a function */
682 if (IS_FUNC (sym->type) && !(sym->isitmp))
684 sym->aop = aop = newAsmop (AOP_IMMD);
685 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
686 aop->size = FPTRSIZE;
690 /* only remaining is far space */
691 /* in which case DPTR gets the address */
692 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
697 emitcode ("mov", "dptr,#%s", sym->rname);
702 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = DCL_TYPE(from_type);
735 if (ptr_type == IPOINTER) {
742 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
747 SNPRINTF (buffer, sizeof(buffer),
749 OP_SYMBOL (IC_LEFT (ic))->rname,
750 val >= 0 ? '+' : '-',
751 abs (val) & 0xffffff);
755 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
757 SNPRINTF(buffer, sizeof(buffer),
758 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
762 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
766 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
767 /* set immd2 field if required */
768 if (aop->aopu.aop_immd.from_cast_remat)
770 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
771 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
777 /*-----------------------------------------------------------------*/
778 /* aopHasRegs - returns true if aop has regs between from-to */
779 /*-----------------------------------------------------------------*/
780 static int aopHasRegs(asmop *aop, int from, int to)
784 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
786 for (; size < aop->size ; size++) {
788 for (reg = from ; reg <= to ; reg++)
789 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
794 /*-----------------------------------------------------------------*/
795 /* regsInCommon - two operands have some registers in common */
796 /*-----------------------------------------------------------------*/
798 regsInCommon (operand * op1, operand * op2)
803 /* if they have registers in common */
804 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
807 sym1 = OP_SYMBOL (op1);
808 sym2 = OP_SYMBOL (op2);
810 if (sym1->nRegs == 0 || sym2->nRegs == 0)
813 for (i = 0; i < sym1->nRegs; i++)
819 for (j = 0; j < sym2->nRegs; j++)
824 if (sym2->regs[j] == sym1->regs[i])
832 /*-----------------------------------------------------------------*/
833 /* operandsEqu - equivalent */
834 /*-----------------------------------------------------------------*/
836 operandsEqu (operand * op1, operand * op2)
840 /* if they not symbols */
841 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
844 sym1 = OP_SYMBOL (op1);
845 sym2 = OP_SYMBOL (op2);
847 /* if both are itemps & one is spilt
848 and the other is not then false */
849 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
850 sym1->isspilt != sym2->isspilt)
853 /* if they are the same */
857 if (strcmp (sym1->rname, sym2->rname) == 0)
861 /* if left is a tmp & right is not */
862 if (IS_ITEMP (op1) &&
865 (sym1->usl.spillLoc == sym2))
868 if (IS_ITEMP (op2) &&
872 (sym2->usl.spillLoc == sym1))
875 /* are they spilt to the same location */
876 if (IS_ITEMP (op2) &&
880 (sym1->usl.spillLoc == sym2->usl.spillLoc))
886 /*-----------------------------------------------------------------*/
887 /* sameRegs - two asmops have the same registers */
888 /*-----------------------------------------------------------------*/
890 sameRegs (asmop * aop1, asmop * aop2)
896 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
903 if (aop1->type != AOP_REG ||
904 aop2->type != AOP_REG)
907 if (aop1->size != aop2->size)
910 for (i = 0; i < aop1->size; i++)
911 if (aop1->aopu.aop_reg[i] !=
912 aop2->aopu.aop_reg[i])
918 /*-----------------------------------------------------------------*/
919 /* aopOp - allocates an asmop for an operand : */
920 /*-----------------------------------------------------------------*/
922 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
931 /* if this a literal */
932 if (IS_OP_LITERAL (op))
934 op->aop = aop = newAsmop (AOP_LIT);
935 aop->aopu.aop_lit = op->operand.valOperand;
936 aop->size = getSize (operandType (op));
940 /* if already has a asmop then continue */
943 if ((op->aop->type == AOP_DPTR && useDP2)
944 || (op->aop->type == AOP_DPTR2 && !useDP2))
950 /* if the underlying symbol has a aop */
951 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
953 op->aop = OP_SYMBOL (op)->aop;
954 if ((op->aop->type == AOP_DPTR && useDP2)
955 || (op->aop->type == AOP_DPTR2 && !useDP2))
961 /* if this is a true symbol */
962 if (IS_TRUE_SYMOP (op))
964 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
968 /* this is a temporary : this has
974 e) can be a return use only */
976 sym = OP_SYMBOL (op);
979 /* if the type is a conditional */
980 if (sym->regType == REG_CND)
982 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
987 /* if it is spilt then two situations
989 b) has a spill location */
990 if (sym->isspilt || sym->nRegs == 0)
993 /* rematerialize it NOW */
996 sym->aop = op->aop = aop =
998 aop->size = getSize (sym->type);
1005 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1006 aop->size = getSize (sym->type);
1007 for (i = 0; i < 2; i++)
1008 aop->aopu.aop_str[i] = accUse[i];
1018 /* a AOP_STR uses DPTR, but DPTR is already in use;
1021 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1024 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1025 aop->size = getSize (sym->type);
1026 for (i = 0; i < (int) fReturnSizeDS390; i++)
1027 aop->aopu.aop_str[i] = fReturn[i];
1031 if (sym->dptr) { /* has been allocated to a DPTRn */
1032 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1033 aop->size = getSize (sym->type);
1034 aop->aopu.dptr = sym->dptr;
1038 if (sym->usl.spillLoc)
1040 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1042 /* force a new aop if sizes differ */
1043 sym->usl.spillLoc->aop = NULL;
1045 sym->aop = op->aop = aop =
1046 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1047 aop->size = getSize (sym->type);
1051 /* else must be a dummy iTemp */
1052 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1053 aop->size = getSize (sym->type);
1057 /* must be in a register */
1058 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1059 aop->size = sym->nRegs;
1060 for (i = 0; i < sym->nRegs; i++)
1061 aop->aopu.aop_reg[i] = sym->regs[i];
1064 /*-----------------------------------------------------------------*/
1065 /* freeAsmop - free up the asmop given to an operand */
1066 /*----------------------------------------------------------------*/
1068 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1085 /* depending on the asmop type only three cases need work AOP_RO
1086 , AOP_R1 && AOP_STK */
1094 emitcode ("pop", "ar0");
1098 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 emitcode ("pop", "ar1");
1110 bitVectUnSetBit (ic->rUsed, R1_IDX);
1116 int stk = aop->aopu.aop_stk + aop->size;
1117 bitVectUnSetBit (ic->rUsed, R0_IDX);
1118 bitVectUnSetBit (ic->rUsed, R1_IDX);
1120 getFreePtr (ic, &aop, FALSE);
1122 if (options.stack10bit)
1124 /* I'm not sure what to do here yet... */
1127 "*** Warning: probably generating bad code for "
1128 "10 bit stack mode.\n");
1133 emitcode ("mov", "a,_bp");
1134 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1135 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1144 emitcode ("pop", "acc");
1145 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1148 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1151 freeAsmop (op, NULL, ic, TRUE);
1154 emitcode ("pop", "ar0");
1160 emitcode ("pop", "ar1");
1165 if (_G.dptr1InUse) {
1166 emitcode ("pop","dpx1");
1167 emitcode ("pop","dph1");
1168 emitcode ("pop","dpl1");
1173 emitcode ("pop","dpx");
1174 emitcode ("pop","dph");
1175 emitcode ("pop","dpl");
1180 /* all other cases just dealloc */
1186 OP_SYMBOL (op)->aop = NULL;
1187 /* if the symbol has a spill */
1189 SPIL_LOC (op)->aop = NULL;
1194 #define DEFAULT_ACC_WARNING 0
1195 static int saveAccWarn = DEFAULT_ACC_WARNING;
1197 /*-------------------------------------------------------------------*/
1198 /* aopGet - for fetching value of the aop */
1200 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1201 /* in the accumulator. Set it to the name of a free register */
1202 /* if acc must be preserved; the register will be used to preserve */
1203 /* acc temporarily and to return the result byte. */
1204 /*-------------------------------------------------------------------*/
1213 /* offset is greater than
1215 if (offset > (aop->size - 1) &&
1216 aop->type != AOP_LIT)
1219 /* depending on type */
1227 /* if we need to increment it */
1228 while (offset > aop->coff)
1230 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1234 while (offset < aop->coff)
1236 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1243 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1244 return (dname ? "acc" : "a");
1246 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1247 return Safe_strdup(buffer);
1250 assert(offset <= 3);
1251 return dptrn[aop->aopu.dptr][offset];
1256 if (aop->type == AOP_DPTR2)
1264 // if (aop->type != AOP_DPTR2)
1266 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1267 // emitcode(";", "spanky: saveAcc for DPTR");
1270 emitcode ("xch", "a, %s", saveAcc);
1275 while (offset > aop->coff)
1277 emitcode ("inc", "dptr");
1281 while (offset < aop->coff)
1283 emitcode ("lcall", "__decdptr");
1290 emitcode ("clr", "a");
1291 emitcode ("movc", "a,@a+dptr");
1295 emitcode ("movx", "a,@dptr");
1298 if (aop->type == AOP_DPTR2)
1306 emitcode ("xch", "a, %s", saveAcc);
1307 // if (strcmp(saveAcc, "_ap"))
1309 // emitcode(";", "spiffy: non _ap return from aopGet.");
1314 return (dname ? "acc" : "a");
1317 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1319 SNPRINTF(buffer, sizeof(buffer),
1320 "%s",aop->aopu.aop_immd.aop_immd2);
1324 SNPRINTF(buffer, sizeof(buffer),
1325 "#%s", aop->aopu.aop_immd.aop_immd1);
1331 tsprintf(buffer, sizeof(buffer),
1332 "#!his",aop->aopu.aop_immd.aop_immd1);
1335 tsprintf(buffer, sizeof(buffer),
1336 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1339 tsprintf(buffer, sizeof(buffer),
1340 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1342 default: /* should not need this (just in case) */
1343 SNPRINTF (buffer, sizeof(buffer),
1345 aop->aopu.aop_immd.aop_immd1,
1351 SNPRINTF (buffer, sizeof(buffer),
1352 "#%s", aop->aopu.aop_immd.aop_immd1);
1354 return Safe_strdup(buffer);
1359 SNPRINTF (buffer, sizeof(buffer),
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "%s", aop->aopu.aop_dir);
1370 return Safe_strdup(buffer);
1374 return aop->aopu.aop_reg[offset]->dname;
1376 return aop->aopu.aop_reg[offset]->name;
1379 emitcode ("clr", "a");
1380 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1381 emitcode ("rlc", "a");
1382 return (dname ? "acc" : "a");
1385 if (!offset && dname)
1387 return aop->aopu.aop_str[offset];
1390 return aopLiteral (aop->aopu.aop_lit, offset);
1394 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1398 return aop->aopu.aop_str[offset];
1402 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1403 "aopget got unsupported aop->type");
1406 return NULL; // not reached, but makes compiler happy.
1408 /*-----------------------------------------------------------------*/
1409 /* aopPut - puts a string for a aop */
1410 /*-----------------------------------------------------------------*/
1412 aopPut (asmop * aop, char *s, int offset)
1414 if (aop->size && offset > (aop->size - 1))
1416 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1417 "aopPut got offset > aop->size");
1421 /* will assign value to value */
1422 /* depending on where it is ofcourse */
1426 MOVA (s); /* read s in case it was volatile */
1432 SNPRINTF (buffer, sizeof(buffer),
1434 aop->aopu.aop_dir, offset);
1438 SNPRINTF (buffer, sizeof(buffer),
1439 "%s", aop->aopu.aop_dir);
1443 if (strcmp (buffer, s))
1445 emitcode ("mov", "%s,%s", buffer, s);
1450 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1451 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1454 strcmp (s, "r0") == 0 ||
1455 strcmp (s, "r1") == 0 ||
1456 strcmp (s, "r2") == 0 ||
1457 strcmp (s, "r3") == 0 ||
1458 strcmp (s, "r4") == 0 ||
1459 strcmp (s, "r5") == 0 ||
1460 strcmp (s, "r6") == 0 ||
1461 strcmp (s, "r7") == 0)
1463 emitcode ("mov", "%s,%s",
1464 aop->aopu.aop_reg[offset]->dname, s);
1468 emitcode ("mov", "%s,%s",
1469 aop->aopu.aop_reg[offset]->name, s);
1475 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1481 if (aop->type == AOP_DPTR2)
1489 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1490 "aopPut writting to code space");
1494 while (offset > aop->coff)
1497 emitcode ("inc", "dptr");
1500 while (offset < aop->coff)
1503 emitcode ("lcall", "__decdptr");
1508 /* if not in accumulater */
1511 emitcode ("movx", "@dptr,a");
1513 if (aop->type == AOP_DPTR2)
1521 while (offset > aop->coff)
1524 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1526 while (offset < aop->coff)
1529 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1536 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1542 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1544 else if (strcmp (s, "r0") == 0 ||
1545 strcmp (s, "r1") == 0 ||
1546 strcmp (s, "r2") == 0 ||
1547 strcmp (s, "r3") == 0 ||
1548 strcmp (s, "r4") == 0 ||
1549 strcmp (s, "r5") == 0 ||
1550 strcmp (s, "r6") == 0 ||
1551 strcmp (s, "r7") == 0)
1554 SNPRINTF(buff, sizeof(buff),
1556 emitcode ("mov", "@%s,%s",
1557 aop->aopu.aop_ptr->name, buff);
1561 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1566 if (strcmp (s, "a") == 0)
1567 emitcode ("push", "acc");
1571 emitcode ("push", "acc");
1573 emitcode ("push", s);
1579 /* if bit variable */
1580 if (!aop->aopu.aop_dir)
1582 emitcode ("clr", "a");
1583 emitcode ("rlc", "a");
1588 emitcode ("clr", "%s", aop->aopu.aop_dir);
1590 emitcode ("setb", "%s", aop->aopu.aop_dir);
1591 else if (!strcmp (s, "c"))
1592 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1595 if (strcmp (s, "a"))
1600 /* set C, if a >= 1 */
1601 emitcode ("add", "a,#!constbyte",0xff);
1602 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1610 if (strcmp (aop->aopu.aop_str[offset], s))
1611 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1616 if (!offset && (strcmp (s, "acc") == 0))
1619 if (strcmp (aop->aopu.aop_str[offset], s))
1620 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1624 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1625 "aopPut got unsupported aop->type");
1632 /*--------------------------------------------------------------------*/
1633 /* reAdjustPreg - points a register back to where it should (coff==0) */
1634 /*--------------------------------------------------------------------*/
1636 reAdjustPreg (asmop * aop)
1638 if ((aop->coff==0) || (aop->size <= 1)) {
1647 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1651 if (aop->type == AOP_DPTR2)
1658 emitcode ("lcall", "__decdptr");
1661 if (aop->type == AOP_DPTR2)
1671 #define AOP(op) op->aop
1672 #define AOP_TYPE(op) AOP(op)->type
1673 #define AOP_SIZE(op) AOP(op)->size
1674 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1675 AOP_TYPE(x) == AOP_R0))
1677 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1678 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1681 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1682 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1683 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1684 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1685 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1686 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1688 // The following two macros can be used even if the aop has not yet been aopOp'd.
1689 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1690 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1692 /* Workaround for DS80C390 bug: div ab may return bogus results
1693 * if A is accessed in instruction immediately before the div.
1695 * Will be fixed in B4 rev of processor, Dallas claims.
1698 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1699 if (!AOP_NEEDSACC(RIGHT)) \
1701 /* We can load A first, then B, since \
1702 * B (the RIGHT operand) won't clobber A, \
1703 * thus avoiding touching A right before the div. \
1705 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1706 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1708 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1713 /* Just stuff in a nop after loading A. */ \
1714 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1715 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1717 emitcode("nop", "; workaround for DS80C390 div bug."); \
1721 /*-----------------------------------------------------------------*/
1722 /* opIsGptr: returns non-zero if the passed operand is */
1723 /* a generic pointer type. */
1724 /*-----------------------------------------------------------------*/
1726 opIsGptr (operand * op)
1728 sym_link *type = operandType (op);
1730 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1737 /*-----------------------------------------------------------------*/
1738 /* getDataSize - get the operand data size */
1739 /*-----------------------------------------------------------------*/
1741 getDataSize (operand * op)
1744 size = AOP_SIZE (op);
1745 if (size == GPTRSIZE)
1747 sym_link *type = operandType (op);
1748 if (IS_GENPTR (type))
1750 /* generic pointer; arithmetic operations
1751 * should ignore the high byte (pointer type).
1759 /*-----------------------------------------------------------------*/
1760 /* outAcc - output Acc */
1761 /*-----------------------------------------------------------------*/
1763 outAcc (operand * result)
1766 size = getDataSize (result);
1769 aopPut (AOP (result), "a", 0);
1772 /* unsigned or positive */
1775 aopPut (AOP (result), zero, offset++);
1780 /*-----------------------------------------------------------------*/
1781 /* outBitC - output a bit C */
1782 /*-----------------------------------------------------------------*/
1784 outBitC (operand * result)
1786 /* if the result is bit */
1787 if (AOP_TYPE (result) == AOP_CRY)
1789 aopPut (AOP (result), "c", 0);
1793 emitcode ("clr", "a");
1794 emitcode ("rlc", "a");
1799 /*-----------------------------------------------------------------*/
1800 /* toBoolean - emit code for orl a,operator(sizeop) */
1801 /*-----------------------------------------------------------------*/
1803 toBoolean (operand * oper)
1805 int size = AOP_SIZE (oper) - 1;
1809 /* The generic part of a generic pointer should
1810 * not participate in it's truth value.
1812 * i.e. 0x10000000 is zero.
1814 if (opIsGptr (oper))
1816 D (emitcode (";", "toBoolean: generic ptr special case."););
1820 _startLazyDPSEvaluation ();
1821 if (AOP_NEEDSACC (oper) && size)
1826 emitcode ("push", "b");
1828 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1832 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1839 emitcode ("orl", "b,%s",
1840 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1844 emitcode ("orl", "a,%s",
1845 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1848 _endLazyDPSEvaluation ();
1852 emitcode ("mov", "a,b");
1855 emitcode ("pop", "b");
1862 /*-----------------------------------------------------------------*/
1863 /* genNot - generate code for ! operation */
1864 /*-----------------------------------------------------------------*/
1870 D (emitcode (";", "genNot "););
1872 /* assign asmOps to operand & result */
1873 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1874 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1876 /* if in bit space then a special case */
1877 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1879 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1880 emitcode ("cpl", "c");
1881 outBitC (IC_RESULT (ic));
1885 toBoolean (IC_LEFT (ic));
1887 tlbl = newiTempLabel (NULL);
1888 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1889 emitcode ("", "!tlabeldef", tlbl->key + 100);
1890 outBitC (IC_RESULT (ic));
1893 /* release the aops */
1894 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1895 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1899 /*-----------------------------------------------------------------*/
1900 /* genCpl - generate code for complement */
1901 /*-----------------------------------------------------------------*/
1909 D (emitcode (";", "genCpl "););
1912 /* assign asmOps to operand & result */
1913 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1914 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1916 /* special case if in bit space */
1917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1918 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1919 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1920 emitcode ("cpl", "c");
1921 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1924 tlbl=newiTempLabel(NULL);
1925 emitcode ("cjne", "%s,#0x01,%05d$",
1926 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1927 emitcode ("", "%05d$:", tlbl->key+100);
1928 outBitC (IC_RESULT(ic));
1932 size = AOP_SIZE (IC_RESULT (ic));
1933 _startLazyDPSEvaluation ();
1936 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1937 emitcode ("cpl", "a");
1938 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1940 _endLazyDPSEvaluation ();
1944 /* release the aops */
1945 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1946 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1949 /*-----------------------------------------------------------------*/
1950 /* genUminusFloat - unary minus for floating points */
1951 /*-----------------------------------------------------------------*/
1953 genUminusFloat (operand * op, operand * result)
1955 int size, offset = 0;
1957 D(emitcode (";", "genUminusFloat"););
1959 /* for this we just copy and then flip the bit */
1961 _startLazyDPSEvaluation ();
1962 size = AOP_SIZE (op) - 1;
1966 aopPut (AOP (result),
1967 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1972 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1974 emitcode ("cpl", "acc.7");
1975 aopPut (AOP (result), "a", offset);
1976 _endLazyDPSEvaluation ();
1979 /*-----------------------------------------------------------------*/
1980 /* genUminus - unary minus code generation */
1981 /*-----------------------------------------------------------------*/
1983 genUminus (iCode * ic)
1988 D (emitcode (";", "genUminus "););
1991 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1994 /* if both in bit space then special
1996 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1997 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2000 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2001 emitcode ("cpl", "c");
2002 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2006 optype = operandType (IC_LEFT (ic));
2008 /* if float then do float stuff */
2009 if (IS_FLOAT (optype))
2011 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2015 /* otherwise subtract from zero */
2016 size = AOP_SIZE (IC_LEFT (ic));
2018 _startLazyDPSEvaluation ();
2021 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2022 if (!strcmp (l, "a"))
2026 emitcode ("cpl", "a");
2027 emitcode ("addc", "a,#0");
2033 emitcode ("clr", "a");
2034 emitcode ("subb", "a,%s", l);
2036 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2038 _endLazyDPSEvaluation ();
2040 /* if any remaining bytes in the result */
2041 /* we just need to propagate the sign */
2042 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2044 emitcode ("rlc", "a");
2045 emitcode ("subb", "a,acc");
2047 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2051 /* release the aops */
2052 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2056 /*-----------------------------------------------------------------*/
2057 /* savermask - saves registers in the mask */
2058 /*-----------------------------------------------------------------*/
2059 static void savermask(bitVect *rs_mask)
2062 if (options.useXstack) {
2063 if (bitVectBitValue (rs_mask, R0_IDX))
2064 emitcode ("mov", "b,r0");
2065 emitcode ("mov", "r0,%s", spname);
2066 for (i = 0; i < ds390_nRegs; i++) {
2067 if (bitVectBitValue (rs_mask, i)) {
2069 emitcode ("mov", "a,b");
2071 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2072 emitcode ("movx", "@r0,a");
2073 emitcode ("inc", "r0");
2076 emitcode ("mov", "%s,r0", spname);
2077 if (bitVectBitValue (rs_mask, R0_IDX))
2078 emitcode ("mov", "r0,b");
2080 for (i = 0; i < ds390_nRegs; i++) {
2081 if (bitVectBitValue (rs_mask, i))
2082 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2087 /*-----------------------------------------------------------------*/
2088 /* saveRegisters - will look for a call and save the registers */
2089 /*-----------------------------------------------------------------*/
2091 saveRegisters (iCode * lic)
2097 for (ic = lic; ic; ic = ic->next)
2098 if (ic->op == CALL || ic->op == PCALL)
2103 fprintf (stderr, "found parameter push with no function call\n");
2107 /* if the registers have been saved already then
2110 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2113 /* special case if DPTR alive across a function call then must save it
2114 even though callee saves */
2115 if (IS_SYMOP(IC_LEFT(ic)) &&
2116 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2118 rsave = newBitVect(ic->rMask->size);
2119 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2120 if (bitVectBitValue(ic->rMask,i))
2121 rsave = bitVectSetBit(rsave,i);
2123 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2125 /* safe the registers in use at this time but skip the
2126 ones for the result */
2127 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128 ds390_rUmaskForOp (IC_RESULT(ic)));
2134 /*-----------------------------------------------------------------*/
2135 /* usavermask - restore registers with mask */
2136 /*-----------------------------------------------------------------*/
2137 static void unsavermask(bitVect *rs_mask)
2140 if (options.useXstack) {
2141 emitcode ("mov", "r0,%s", spname);
2142 for (i = ds390_nRegs; i >= 0; i--) {
2143 if (bitVectBitValue (rs_mask, i)) {
2144 emitcode ("dec", "r0");
2145 emitcode ("movx", "a,@r0");
2147 emitcode ("mov", "b,a");
2149 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2152 emitcode ("mov", "%s,r0", spname);
2153 if (bitVectBitValue (rs_mask, R0_IDX))
2154 emitcode ("mov", "r0,b");
2156 for (i = ds390_nRegs; i >= 0; i--) {
2157 if (bitVectBitValue (rs_mask, i))
2158 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2163 /*-----------------------------------------------------------------*/
2164 /* unsaveRegisters - pop the pushed registers */
2165 /*-----------------------------------------------------------------*/
2167 unsaveRegisters (iCode * ic)
2171 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2173 rsave = newBitVect(ic->rMask->size);
2174 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2175 if (bitVectBitValue(ic->rMask,i))
2176 rsave = bitVectSetBit(rsave,i);
2178 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2180 /* restore the registers in use at this time but skip the
2181 ones for the result */
2182 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2183 ds390_rUmaskForOp (IC_RESULT(ic)));
2189 /*-----------------------------------------------------------------*/
2191 /*-----------------------------------------------------------------*/
2193 pushSide (operand * oper, int size)
2196 _startLazyDPSEvaluation ();
2199 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2200 if (AOP_TYPE (oper) != AOP_REG &&
2201 AOP_TYPE (oper) != AOP_DIR &&
2204 emitcode ("mov", "a,%s", l);
2205 emitcode ("push", "acc");
2208 emitcode ("push", "%s", l);
2210 _endLazyDPSEvaluation ();
2213 /*-----------------------------------------------------------------*/
2214 /* assignResultValue - */
2215 /*-----------------------------------------------------------------*/
2217 assignResultValue (operand * oper)
2220 int size = AOP_SIZE (oper);
2221 bool pushedAcc = FALSE;
2223 if (size == fReturnSizeDS390)
2225 /* I don't think this case can ever happen... */
2226 /* ACC is the last part of this. If writing the result
2227 * uses AC, we must preserve it.
2229 if (AOP_NEEDSACC(oper))
2231 emitcode(";", "assignResultValue special case for ACC.");
2232 emitcode("push", "acc");
2239 _startLazyDPSEvaluation ();
2242 aopPut (AOP (oper), fReturn[offset], offset);
2245 _endLazyDPSEvaluation ();
2249 emitcode("pop", "acc");
2250 aopPut(AOP(oper), "a", offset);
2255 /*-----------------------------------------------------------------*/
2256 /* genXpush - pushes onto the external stack */
2257 /*-----------------------------------------------------------------*/
2259 genXpush (iCode * ic)
2261 asmop *aop = newAsmop (0);
2263 int size, offset = 0;
2265 D (emitcode (";", "genXpush ");
2268 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2269 r = getFreePtr (ic, &aop, FALSE);
2272 emitcode ("mov", "%s,_spx", r->name);
2274 size = AOP_SIZE (IC_LEFT (ic));
2275 _startLazyDPSEvaluation ();
2279 MOVA (aopGet (AOP (IC_LEFT (ic)),
2280 offset++, FALSE, FALSE, NULL));
2281 emitcode ("movx", "@%s,a", r->name);
2282 emitcode ("inc", "%s", r->name);
2285 _endLazyDPSEvaluation ();
2288 emitcode ("mov", "_spx,%s", r->name);
2290 freeAsmop (NULL, aop, ic, TRUE);
2291 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2294 /*-----------------------------------------------------------------*/
2295 /* genIpush - generate code for pushing this gets a little complex */
2296 /*-----------------------------------------------------------------*/
2298 genIpush (iCode * ic)
2300 int size, offset = 0;
2303 D (emitcode (";", "genIpush ");
2306 /* if this is not a parm push : ie. it is spill push
2307 and spill push is always done on the local stack */
2311 /* and the item is spilt then do nothing */
2312 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2315 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2316 size = AOP_SIZE (IC_LEFT (ic));
2317 /* push it on the stack */
2318 _startLazyDPSEvaluation ();
2321 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2327 emitcode ("push", "%s", l);
2329 _endLazyDPSEvaluation ();
2333 /* this is a paramter push: in this case we call
2334 the routine to find the call and save those
2335 registers that need to be saved */
2338 /* if use external stack then call the external
2339 stack pushing routine */
2340 if (options.useXstack)
2346 /* then do the push */
2347 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2349 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2350 size = AOP_SIZE (IC_LEFT (ic));
2352 _startLazyDPSEvaluation ();
2355 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2356 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2357 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2360 emitcode ("mov", "a,%s", l);
2361 emitcode ("push", "acc");
2365 emitcode ("push", "%s", l);
2368 _endLazyDPSEvaluation ();
2370 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2373 /*-----------------------------------------------------------------*/
2374 /* genIpop - recover the registers: can happen only for spilling */
2375 /*-----------------------------------------------------------------*/
2377 genIpop (iCode * ic)
2381 D (emitcode (";", "genIpop ");
2385 /* if the temp was not pushed then */
2386 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2389 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2390 size = AOP_SIZE (IC_LEFT (ic));
2391 offset = (size - 1);
2392 _startLazyDPSEvaluation ();
2395 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2396 FALSE, TRUE, NULL));
2398 _endLazyDPSEvaluation ();
2400 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2403 /*-----------------------------------------------------------------*/
2404 /* unsaveRBank - restores the resgister bank from stack */
2405 /*-----------------------------------------------------------------*/
2407 unsaveRBank (int bank, iCode * ic, bool popPsw)
2413 if (options.useXstack)
2417 /* Assume r0 is available for use. */
2418 r = ds390_regWithIdx (R0_IDX);;
2423 r = getFreePtr (ic, &aop, FALSE);
2425 emitcode ("mov", "%s,_spx", r->name);
2430 if (options.useXstack)
2432 emitcode ("movx", "a,@%s", r->name);
2433 emitcode ("mov", "psw,a");
2434 emitcode ("dec", "%s", r->name);
2438 emitcode ("pop", "psw");
2442 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2444 if (options.useXstack)
2446 emitcode ("movx", "a,@%s", r->name);
2447 emitcode ("mov", "(%s+%d),a",
2448 regs390[i].base, 8 * bank + regs390[i].offset);
2449 emitcode ("dec", "%s", r->name);
2453 emitcode ("pop", "(%s+%d)",
2454 regs390[i].base, 8 * bank + regs390[i].offset);
2457 if (options.useXstack)
2459 emitcode ("mov", "_spx,%s", r->name);
2464 freeAsmop (NULL, aop, ic, TRUE);
2468 /*-----------------------------------------------------------------*/
2469 /* saveRBank - saves an entire register bank on the stack */
2470 /*-----------------------------------------------------------------*/
2472 saveRBank (int bank, iCode * ic, bool pushPsw)
2478 if (options.useXstack)
2482 /* Assume r0 is available for use. */
2483 r = ds390_regWithIdx (R0_IDX);;
2488 r = getFreePtr (ic, &aop, FALSE);
2490 emitcode ("mov", "%s,_spx", r->name);
2493 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2495 if (options.useXstack)
2497 emitcode ("inc", "%s", r->name);
2498 emitcode ("mov", "a,(%s+%d)",
2499 regs390[i].base, 8 * bank + regs390[i].offset);
2500 emitcode ("movx", "@%s,a", r->name);
2503 emitcode ("push", "(%s+%d)",
2504 regs390[i].base, 8 * bank + regs390[i].offset);
2509 if (options.useXstack)
2511 emitcode ("mov", "a,psw");
2512 emitcode ("movx", "@%s,a", r->name);
2513 emitcode ("inc", "%s", r->name);
2514 emitcode ("mov", "_spx,%s", r->name);
2518 emitcode ("push", "psw");
2521 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2526 freeAsmop (NULL, aop, ic, TRUE);
2535 /*-----------------------------------------------------------------*/
2536 /* genSend - gen code for SEND */
2537 /*-----------------------------------------------------------------*/
2538 static void genSend(set *sendSet)
2542 static int rb1_count = 0;
2544 for (sic = setFirstItem (sendSet); sic;
2545 sic = setNextItem (sendSet)) {
2546 int size, offset = 0;
2548 size=getSize(operandType(IC_LEFT(sic)));
2549 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2550 if (sendCount == 0) { /* first parameter */
2551 // we know that dpl(hxb) is the result, so
2553 _startLazyDPSEvaluation ();
2555 aopOp (IC_LEFT (sic), sic, FALSE,
2556 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2558 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2561 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2562 FALSE, FALSE, NULL);
2563 if (strcmp (l, fReturn[offset])) {
2564 emitcode ("mov", "%s,%s",
2570 _endLazyDPSEvaluation ();
2571 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2573 } else { /* if more parameter in registers */
2574 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2576 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2577 FALSE, FALSE, NULL));
2579 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2586 adjustEsp(const char *reg)
2588 emitcode ("anl","%s,#3", reg);
2589 if (TARGET_IS_DS400)
2591 emitcode ("orl","%s,#!constbyte",
2593 (options.stack_loc >> 8) & 0xff);
2597 /*-----------------------------------------------------------------*/
2598 /* genCall - generates a call statement */
2599 /*-----------------------------------------------------------------*/
2601 genCall (iCode * ic)
2604 bool restoreBank = FALSE;
2605 bool swapBanks = FALSE;
2607 D (emitcode (";", "genCall "););
2609 /* if we are calling a not _naked function that is not using
2610 the same register bank then we need to save the
2611 destination registers on the stack */
2612 dtype = operandType (IC_LEFT (ic));
2613 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2614 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2615 IFFUNC_ISISR (currFunc->type))
2619 /* This is unexpected; the bank should have been saved in
2622 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2628 /* if caller saves & we have not saved then */
2632 /* if send set is not empty the assign */
2633 /* We've saved all the registers we care about;
2634 * therefore, we may clobber any register not used
2635 * in the calling convention (i.e. anything not in
2640 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2641 genSend(reverseSet(_G.sendSet));
2643 genSend(_G.sendSet);
2650 emitcode ("mov", "psw,#!constbyte",
2651 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2655 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2656 OP_SYMBOL (IC_LEFT (ic))->rname :
2657 OP_SYMBOL (IC_LEFT (ic))->name));
2661 emitcode ("mov", "psw,#!constbyte",
2662 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2665 /* if we need assign a result value */
2666 if ((IS_ITEMP (IC_RESULT (ic)) &&
2667 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2668 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2669 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2670 IS_TRUE_SYMOP (IC_RESULT (ic)))
2672 if (isOperandInFarSpace (IC_RESULT (ic))
2673 && getSize (operandType (IC_RESULT (ic))) <= 2)
2675 int size = getSize (operandType (IC_RESULT (ic)));
2677 /* Special case for 1 or 2 byte return in far space. */
2681 emitcode ("mov", "b,%s", fReturn[1]);
2686 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2692 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2696 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2698 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2703 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2706 assignResultValue (IC_RESULT (ic));
2708 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2712 /* adjust the stack for parameters if
2714 if (ic->parmBytes) {
2716 if (options.stack10bit) {
2717 if (ic->parmBytes <= 10) {
2718 emitcode(";","stack adjustment for parms");
2719 for (i=0; i < ic->parmBytes ; i++) {
2720 emitcode("pop","acc");
2724 emitcode ("clr","c");
2725 emitcode ("mov","a,sp");
2726 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2727 emitcode ("mov","sp,a");
2728 emitcode ("mov","a,esp");
2730 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2731 emitcode ("mov","esp,a");
2735 if (ic->parmBytes > 3) {
2736 emitcode ("mov", "a,%s", spname);
2737 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2738 emitcode ("mov", "%s,a", spname);
2740 for (i = 0; i < ic->parmBytes; i++)
2741 emitcode ("dec", "%s", spname);
2745 /* if we hade saved some registers then unsave them */
2747 unsaveRegisters (ic);
2749 /* if register bank was saved then pop them */
2751 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2754 /*-----------------------------------------------------------------*/
2755 /* genPcall - generates a call by pointer statement */
2756 /*-----------------------------------------------------------------*/
2758 genPcall (iCode * ic)
2761 symbol *rlbl = newiTempLabel (NULL);
2762 bool restoreBank=FALSE;
2764 D (emitcode (";", "genPcall ");
2768 /* if caller saves & we have not saved then */
2772 /* if we are calling a function that is not using
2773 the same register bank then we need to save the
2774 destination registers on the stack */
2775 dtype = operandType (IC_LEFT (ic));
2776 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2777 IFFUNC_ISISR (currFunc->type) &&
2778 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2779 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2783 /* push the return address on to the stack */
2784 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2785 emitcode ("push", "acc");
2786 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2787 emitcode ("push", "acc");
2789 if (options.model == MODEL_FLAT24)
2791 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2792 emitcode ("push", "acc");
2795 /* now push the calling address */
2796 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2798 pushSide (IC_LEFT (ic), FPTRSIZE);
2800 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2802 /* if send set is not empty the assign */
2805 genSend(reverseSet(_G.sendSet));
2809 emitcode ("ret", "");
2810 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2813 /* if we need assign a result value */
2814 if ((IS_ITEMP (IC_RESULT (ic)) &&
2815 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2816 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2817 IS_TRUE_SYMOP (IC_RESULT (ic)))
2821 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2824 assignResultValue (IC_RESULT (ic));
2826 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2829 /* adjust the stack for parameters if
2834 if (options.stack10bit) {
2835 if (ic->parmBytes <= 10) {
2836 emitcode(";","stack adjustment for parms");
2837 for (i=0; i < ic->parmBytes ; i++) {
2838 emitcode("pop","acc");
2842 emitcode ("clr","c");
2843 emitcode ("mov","a,sp");
2844 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2845 emitcode ("mov","sp,a");
2846 emitcode ("mov","a,esp");
2848 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2849 emitcode ("mov","esp,a");
2853 if (ic->parmBytes > 3) {
2854 emitcode ("mov", "a,%s", spname);
2855 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2856 emitcode ("mov", "%s,a", spname);
2859 for (i = 0; i < ic->parmBytes; i++)
2860 emitcode ("dec", "%s", spname);
2864 /* if register bank was saved then unsave them */
2866 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2868 /* if we hade saved some registers then
2871 unsaveRegisters (ic);
2875 /*-----------------------------------------------------------------*/
2876 /* resultRemat - result is rematerializable */
2877 /*-----------------------------------------------------------------*/
2879 resultRemat (iCode * ic)
2881 if (SKIP_IC (ic) || ic->op == IFX)
2884 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2886 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2887 if (sym->remat && !POINTER_SET (ic))
2894 #if defined(__BORLANDC__) || defined(_MSC_VER)
2895 #define STRCASECMP stricmp
2897 #define STRCASECMP strcasecmp
2900 /*-----------------------------------------------------------------*/
2901 /* inExcludeList - return 1 if the string is in exclude Reg list */
2902 /*-----------------------------------------------------------------*/
2904 regsCmp(void *p1, void *p2)
2906 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2910 inExcludeList (char *s)
2912 const char *p = setFirstItem(options.excludeRegsSet);
2914 if (p == NULL || STRCASECMP(p, "none") == 0)
2918 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2921 /*-----------------------------------------------------------------*/
2922 /* genFunction - generated code for function entry */
2923 /*-----------------------------------------------------------------*/
2925 genFunction (iCode * ic)
2929 bool switchedPSW = FALSE;
2931 D (emitcode (";", "genFunction "););
2934 /* create the function header */
2935 emitcode (";", "-----------------------------------------");
2936 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2937 emitcode (";", "-----------------------------------------");
2939 emitcode ("", "%s:", sym->rname);
2940 ftype = operandType (IC_LEFT (ic));
2942 if (IFFUNC_ISNAKED(ftype))
2944 emitcode(";", "naked function: no prologue.");
2948 if (options.stack_probe)
2949 emitcode ("lcall","__stack_probe");
2951 /* here we need to generate the equates for the
2952 register bank if required */
2953 if (FUNC_REGBANK (ftype) != rbank)
2957 rbank = FUNC_REGBANK (ftype);
2958 for (i = 0; i < ds390_nRegs; i++)
2960 if (regs390[i].print) {
2961 if (strcmp (regs390[i].base, "0") == 0)
2962 emitcode ("", "%s !equ !constbyte",
2964 8 * rbank + regs390[i].offset);
2966 emitcode ("", "%s !equ %s + !constbyte",
2969 8 * rbank + regs390[i].offset);
2974 /* if this is an interrupt service routine then
2975 save acc, b, dpl, dph */
2976 if (IFFUNC_ISISR (sym->type))
2978 if (!inExcludeList ("acc"))
2979 emitcode ("push", "acc");
2980 if (!inExcludeList ("b"))
2981 emitcode ("push", "b");
2982 if (!inExcludeList ("dpl"))
2983 emitcode ("push", "dpl");
2984 if (!inExcludeList ("dph"))
2985 emitcode ("push", "dph");
2986 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2988 emitcode ("push", "dpx");
2989 /* Make sure we're using standard DPTR */
2990 emitcode ("push", "dps");
2991 emitcode ("mov", "dps,#0");
2992 if (options.stack10bit)
2994 /* This ISR could conceivably use DPTR2. Better save it. */
2995 emitcode ("push", "dpl1");
2996 emitcode ("push", "dph1");
2997 emitcode ("push", "dpx1");
2998 emitcode ("push", DP2_RESULT_REG);
3001 /* if this isr has no bank i.e. is going to
3002 run with bank 0 , then we need to save more
3004 if (!FUNC_REGBANK (sym->type))
3008 /* if this function does not call any other
3009 function then we can be economical and
3010 save only those registers that are used */
3011 if (!IFFUNC_HASFCALL(sym->type))
3014 /* if any registers used */
3017 /* save the registers used */
3018 for (i = 0; i < sym->regsUsed->size; i++)
3020 if (bitVectBitValue (sym->regsUsed, i))
3021 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3027 /* this function has a function call cannot
3028 determines register usage so we will have to push the
3030 saveRBank (0, ic, FALSE);
3031 if (options.parms_in_bank1) {
3032 for (i=0; i < 8 ; i++ ) {
3033 emitcode ("push","%s",rb1regs[i]);
3040 /* This ISR uses a non-zero bank.
3042 * We assume that the bank is available for our
3045 * However, if this ISR calls a function which uses some
3046 * other bank, we must save that bank entirely.
3048 unsigned long banksToSave = 0;
3050 if (IFFUNC_HASFCALL(sym->type))
3053 #define MAX_REGISTER_BANKS 4
3058 for (i = ic; i; i = i->next)
3060 if (i->op == ENDFUNCTION)
3062 /* we got to the end OK. */
3070 dtype = operandType (IC_LEFT(i));
3072 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3074 /* Mark this bank for saving. */
3075 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3077 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3081 banksToSave |= (1 << FUNC_REGBANK(dtype));
3084 /* And note that we don't need to do it in
3092 /* This is a mess; we have no idea what
3093 * register bank the called function might
3096 * The only thing I can think of to do is
3097 * throw a warning and hope.
3099 werror(W_FUNCPTR_IN_USING_ISR);
3103 if (banksToSave && options.useXstack)
3105 /* Since we aren't passing it an ic,
3106 * saveRBank will assume r0 is available to abuse.
3108 * So switch to our (trashable) bank now, so
3109 * the caller's R0 isn't trashed.
3111 emitcode ("push", "psw");
3112 emitcode ("mov", "psw,#!constbyte",
3113 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3117 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3119 if (banksToSave & (1 << ix))
3121 saveRBank(ix, NULL, FALSE);
3125 // TODO: this needs a closer look
3126 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3131 /* if callee-save to be used for this function
3132 then save the registers being used in this function */
3133 if (IFFUNC_CALLEESAVES(sym->type))
3137 /* if any registers used */
3140 /* save the registers used */
3141 for (i = 0; i < sym->regsUsed->size; i++)
3143 if (bitVectBitValue (sym->regsUsed, i))
3145 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3153 /* set the register bank to the desired value */
3154 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3157 emitcode ("push", "psw");
3158 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3161 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3162 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3163 if (options.stack10bit) {
3164 emitcode ("push","_bpx");
3165 emitcode ("push","_bpx+1");
3166 emitcode ("mov","_bpx,%s",spname);
3167 emitcode ("mov","_bpx+1,esp");
3168 adjustEsp("_bpx+1");
3170 if (options.useXstack) {
3171 emitcode ("mov", "r0,%s", spname);
3172 emitcode ("mov", "a,_bp");
3173 emitcode ("movx", "@r0,a");
3174 emitcode ("inc", "%s", spname);
3176 /* set up the stack */
3177 emitcode ("push", "_bp"); /* save the callers stack */
3179 emitcode ("mov", "_bp,%s", spname);
3183 /* adjust the stack for the function */
3186 if (options.stack10bit) {
3187 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3188 assert (sym->recvSize <= 4);
3189 if (sym->stack <= 8) {
3190 while (i--) emitcode ("push","acc");
3193 emitcode ("mov","a,sp");
3194 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3195 emitcode ("mov","sp,a");
3196 emitcode ("mov","a,esp");
3198 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3199 emitcode ("mov","esp,a");
3204 werror (W_STACK_OVERFLOW, sym->name);
3206 if (i > 3 && sym->recvSize < 4) {
3208 emitcode ("mov", "a,sp");
3209 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3210 emitcode ("mov", "sp,a");
3214 emitcode ("inc", "sp");
3221 emitcode ("mov", "a,_spx");
3222 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3223 emitcode ("mov", "_spx,a");
3226 /* if critical function then turn interrupts off */
3227 if (IFFUNC_ISCRITICAL (ftype))
3229 symbol *tlbl = newiTempLabel (NULL);
3230 emitcode ("setb", "c");
3231 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3232 emitcode ("clr", "c");
3233 emitcode ("", "%05d$:", (tlbl->key + 100));
3234 emitcode ("push", "psw"); /* save old ea via c in psw */
3239 /*-----------------------------------------------------------------*/
3240 /* genEndFunction - generates epilogue for functions */
3241 /*-----------------------------------------------------------------*/
3243 genEndFunction (iCode * ic)
3245 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3246 lineNode *lnp = lineCurr;
3248 bitVect *regsUsedPrologue;
3249 bitVect *regsUnneeded;
3252 D (emitcode (";", "genEndFunction "););
3254 if (IFFUNC_ISNAKED(sym->type))
3256 emitcode(";", "naked function: no epilogue.");
3260 if (IFFUNC_ISCRITICAL (sym->type))
3262 emitcode ("pop", "psw"); /* restore ea via c in psw */
3263 emitcode ("mov", "ea,c");
3266 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3267 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3269 if (options.stack10bit) {
3271 emitcode ("mov", "sp,_bpx", spname);
3272 emitcode ("mov", "esp,_bpx+1", spname);
3275 emitcode ("mov", "%s,_bp", spname);
3279 /* if use external stack but some variables were
3280 added to the local stack then decrement the
3282 if (options.useXstack && sym->stack) {
3283 emitcode ("mov", "a,sp");
3284 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3285 emitcode ("mov", "sp,a");
3289 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3290 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3292 if (options.useXstack) {
3293 emitcode ("mov", "r0,%s", spname);
3294 emitcode ("movx", "a,@r0");
3295 emitcode ("mov", "_bp,a");
3296 emitcode ("dec", "%s", spname);
3298 if (options.stack10bit) {
3299 emitcode ("pop", "_bpx+1");
3300 emitcode ("pop", "_bpx");
3302 emitcode ("pop", "_bp");
3307 /* restore the register bank */
3308 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3310 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3311 || !options.useXstack)
3313 /* Special case of ISR using non-zero bank with useXstack
3316 emitcode ("pop", "psw");
3320 if (IFFUNC_ISISR (sym->type))
3323 /* now we need to restore the registers */
3324 /* if this isr has no bank i.e. is going to
3325 run with bank 0 , then we need to save more
3327 if (!FUNC_REGBANK (sym->type))
3330 /* if this function does not call any other
3331 function then we can be economical and
3332 save only those registers that are used */
3333 if (!IFFUNC_HASFCALL(sym->type))
3336 /* if any registers used */
3339 /* save the registers used */
3340 for (i = sym->regsUsed->size; i >= 0; i--)
3342 if (bitVectBitValue (sym->regsUsed, i))
3343 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3349 /* this function has a function call cannot
3350 determines register usage so we will have to pop the
3352 if (options.parms_in_bank1) {
3353 for (i = 7 ; i >= 0 ; i-- ) {
3354 emitcode ("pop","%s",rb1regs[i]);
3357 unsaveRBank (0, ic, FALSE);
3362 /* This ISR uses a non-zero bank.
3364 * Restore any register banks saved by genFunction
3367 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3370 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3372 if (savedBanks & (1 << ix))
3374 unsaveRBank(ix, NULL, FALSE);
3378 if (options.useXstack)
3380 /* Restore bank AFTER calling unsaveRBank,
3381 * since it can trash r0.
3383 emitcode ("pop", "psw");
3387 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3389 if (options.stack10bit)
3391 emitcode ("pop", DP2_RESULT_REG);
3392 emitcode ("pop", "dpx1");
3393 emitcode ("pop", "dph1");
3394 emitcode ("pop", "dpl1");
3396 emitcode ("pop", "dps");
3397 emitcode ("pop", "dpx");
3399 if (!inExcludeList ("dph"))
3400 emitcode ("pop", "dph");
3401 if (!inExcludeList ("dpl"))
3402 emitcode ("pop", "dpl");
3403 if (!inExcludeList ("b"))
3404 emitcode ("pop", "b");
3405 if (!inExcludeList ("acc"))
3406 emitcode ("pop", "acc");
3408 /* if debug then send end of function */
3409 if (options.debug && currFunc) {
3411 emitcode ("", "C$%s$%d$%d$%d ==.",
3412 FileBaseName (ic->filename), currFunc->lastLine,
3413 ic->level, ic->block);
3414 if (IS_STATIC (currFunc->etype))
3415 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3417 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3421 emitcode ("reti", "");
3425 if (IFFUNC_CALLEESAVES(sym->type))
3429 /* if any registers used */
3432 /* save the registers used */
3433 for (i = sym->regsUsed->size; i >= 0; i--)
3435 if (bitVectBitValue (sym->regsUsed, i))
3436 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3441 /* if debug then send end of function */
3442 if (options.debug && currFunc)
3445 emitcode ("", "C$%s$%d$%d$%d ==.",
3446 FileBaseName (ic->filename), currFunc->lastLine,
3447 ic->level, ic->block);
3448 if (IS_STATIC (currFunc->etype))
3449 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3451 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3455 emitcode ("ret", "");
3458 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3461 /* If this was an interrupt handler using bank 0 that called another */
3462 /* function, then all registers must be saved; nothing to optimized. */
3463 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3464 && !FUNC_REGBANK(sym->type))
3467 /* There are no push/pops to optimize if not callee-saves or ISR */
3468 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3471 /* If there were stack parameters, we cannot optimize without also */
3472 /* fixing all of the stack offsets; this is too dificult to consider. */
3473 if (FUNC_HASSTACKPARM(sym->type))
3476 /* Compute the registers actually used */
3477 regsUsed = newBitVect (ds390_nRegs);
3478 regsUsedPrologue = newBitVect (ds390_nRegs);
3481 if (lnp->ic && lnp->ic->op == FUNCTION)
3482 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3484 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3486 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3487 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3494 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3495 && !bitVectBitValue (regsUsed, DPS_IDX))
3497 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3500 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3501 && !bitVectBitValue (regsUsed, CND_IDX))
3503 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3504 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3506 bitVectUnSetBit (regsUsed, CND_IDX);
3509 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3511 /* If this was an interrupt handler that called another function */
3512 /* function, then assume working registers may be modified by it. */
3513 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3515 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3516 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3517 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3518 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3519 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3520 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3521 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3522 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3523 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3524 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3525 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3528 /* Remove the unneeded push/pops */
3529 regsUnneeded = newBitVect (ds390_nRegs);
3532 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3534 if (!strncmp(lnp->line, "push", 4))
3536 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3537 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3539 connectLine (lnp->prev, lnp->next);
3540 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3543 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3545 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3546 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3548 connectLine (lnp->prev, lnp->next);
3549 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3556 for (idx = 0; idx < regsUnneeded->size; idx++)
3557 if (bitVectBitValue (regsUnneeded, idx))
3558 emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3560 freeBitVect (regsUnneeded);
3561 freeBitVect (regsUsed);
3562 freeBitVect (regsUsedPrologue);
3565 /*-----------------------------------------------------------------*/
3566 /* genJavaNativeRet - generate code for return JavaNative */
3567 /*-----------------------------------------------------------------*/
3568 static void genJavaNativeRet(iCode *ic)
3572 aopOp (IC_LEFT (ic), ic, FALSE,
3573 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3574 size = AOP_SIZE (IC_LEFT (ic));
3578 /* it is assigned to GPR0-R3 then push them */
3579 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3580 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3581 for (i = 0 ; i < size ; i++ ) {
3582 emitcode ("push","%s",
3583 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3585 for (i = (size-1) ; i >= 0 ; i--) {
3586 emitcode ("pop","a%s",javaRet[i]);
3589 for (i = 0 ; i < size ; i++)
3590 emitcode ("mov","%s,%s",javaRet[i],
3591 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3593 for (i = size ; i < 4 ; i++ )
3594 emitcode ("mov","%s,#0",javaRet[i]);
3598 /*-----------------------------------------------------------------*/
3599 /* genRet - generate code for return statement */
3600 /*-----------------------------------------------------------------*/
3604 int size, offset = 0, pushed = 0;
3606 D (emitcode (";", "genRet "););
3608 /* if we have no return value then
3609 just generate the "ret" */
3613 /* if this is a JavaNative function then return
3614 value in different register */
3615 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3616 genJavaNativeRet(ic);
3619 /* we have something to return then
3620 move the return value into place */
3621 aopOp (IC_LEFT (ic), ic, FALSE,
3622 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3623 size = AOP_SIZE (IC_LEFT (ic));
3625 _startLazyDPSEvaluation ();
3629 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3631 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3633 emitcode ("push", "%s", l);
3638 /* Since A is the last element of fReturn,
3639 * is is OK to clobber it in the aopGet.
3641 l = aopGet (AOP (IC_LEFT (ic)), offset,
3642 FALSE, FALSE, NULL);
3643 if (strcmp (fReturn[offset], l))
3644 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3647 _endLazyDPSEvaluation ();
3654 if (strcmp (fReturn[pushed], "a"))
3655 emitcode ("pop", fReturn[pushed]);
3657 emitcode ("pop", "acc");
3660 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3663 /* generate a jump to the return label
3664 if the next is not the return statement */
3665 if (!(ic->next && ic->next->op == LABEL &&
3666 IC_LABEL (ic->next) == returnLabel))
3668 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3672 /*-----------------------------------------------------------------*/
3673 /* genLabel - generates a label */
3674 /*-----------------------------------------------------------------*/
3676 genLabel (iCode * ic)
3678 /* special case never generate */
3679 if (IC_LABEL (ic) == entryLabel)
3682 D (emitcode (";", "genLabel ");
3685 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3688 /*-----------------------------------------------------------------*/
3689 /* genGoto - generates a ljmp */
3690 /*-----------------------------------------------------------------*/
3692 genGoto (iCode * ic)
3694 D (emitcode (";", "genGoto ");
3696 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3699 /*-----------------------------------------------------------------*/
3700 /* findLabelBackwards: walks back through the iCode chain looking */
3701 /* for the given label. Returns number of iCode instructions */
3702 /* between that label and given ic. */
3703 /* Returns zero if label not found. */
3704 /*-----------------------------------------------------------------*/
3706 findLabelBackwards (iCode * ic, int key)
3715 /* If we have any pushes or pops, we cannot predict the distance.
3716 I don't like this at all, this should be dealt with in the
3718 if (ic->op == IPUSH || ic->op == IPOP) {
3722 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3724 /* printf("findLabelBackwards = %d\n", count); */
3732 /*-----------------------------------------------------------------*/
3733 /* genPlusIncr :- does addition with increment if possible */
3734 /*-----------------------------------------------------------------*/
3736 genPlusIncr (iCode * ic)
3738 unsigned int icount;
3739 unsigned int size = getDataSize (IC_RESULT (ic));
3741 /* will try to generate an increment */
3742 /* if the right side is not a literal
3744 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3747 /* if the literal value of the right hand side
3748 is greater than 4 then it is not worth it */
3749 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3752 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3753 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3755 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3759 /* if increment 16 bits in register */
3761 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3762 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3763 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3772 /* If the next instruction is a goto and the goto target
3773 * is <= 5 instructions previous to this, we can generate
3774 * jumps straight to that target.
3776 if (ic->next && ic->next->op == GOTO
3777 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3780 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3781 tlbl = IC_LABEL (ic->next);
3786 tlbl = newiTempLabel (NULL);
3790 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3791 emitcode ("inc", "%s", l);
3793 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3794 IS_AOP_PREG (IC_RESULT (ic)))
3796 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3800 emitcode ("clr", "a");
3801 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3804 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3805 emitcode ("inc", "%s", l);
3808 if (!strcmp(l, "acc"))
3810 emitcode("jnz", "!tlabel", tlbl->key + 100);
3812 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3813 IS_AOP_PREG (IC_RESULT (ic)))
3815 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3819 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3822 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3823 emitcode ("inc", "%s", l);
3827 if (!strcmp(l, "acc"))
3829 emitcode("jnz", "!tlabel", tlbl->key + 100);
3831 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3832 IS_AOP_PREG (IC_RESULT (ic)))
3834 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3838 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3841 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3842 emitcode ("inc", "%s", l); }
3846 emitcode ("", "!tlabeldef", tlbl->key + 100);
3851 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3852 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3853 options.model == MODEL_FLAT24 ) {
3857 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3859 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3861 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3864 while (icount--) emitcode ("inc","dptr");
3868 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3869 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3871 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3872 while (icount--) emitcode ("inc","dptr");
3873 emitcode ("mov","dps,#0");
3877 /* if the sizes are greater than 1 then we cannot */
3878 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3879 AOP_SIZE (IC_LEFT (ic)) > 1)
3882 /* we can if the aops of the left & result match or
3883 if they are in registers and the registers are the
3886 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3887 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3888 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3893 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3894 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3895 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3900 _startLazyDPSEvaluation ();
3903 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3905 _endLazyDPSEvaluation ();
3914 /*-----------------------------------------------------------------*/
3915 /* outBitAcc - output a bit in acc */
3916 /*-----------------------------------------------------------------*/
3918 outBitAcc (operand * result)
3920 symbol *tlbl = newiTempLabel (NULL);
3921 /* if the result is a bit */
3922 if (AOP_TYPE (result) == AOP_CRY)
3924 aopPut (AOP (result), "a", 0);
3928 emitcode ("jz", "!tlabel", tlbl->key + 100);
3929 emitcode ("mov", "a,%s", one);
3930 emitcode ("", "!tlabeldef", tlbl->key + 100);
3935 /*-----------------------------------------------------------------*/
3936 /* genPlusBits - generates code for addition of two bits */
3937 /*-----------------------------------------------------------------*/
3939 genPlusBits (iCode * ic)
3941 D (emitcode (";", "genPlusBits "););
3943 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3945 symbol *lbl = newiTempLabel (NULL);
3946 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3947 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3948 emitcode ("cpl", "c");
3949 emitcode ("", "!tlabeldef", (lbl->key + 100));
3950 outBitC (IC_RESULT (ic));
3954 emitcode ("clr", "a");
3955 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3956 emitcode ("rlc", "a");
3957 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3958 emitcode ("addc", "a,#0");
3959 outAcc (IC_RESULT (ic));
3964 adjustArithmeticResult (iCode * ic)
3966 if (opIsGptr (IC_RESULT (ic)) &&
3967 opIsGptr (IC_LEFT (ic)) &&
3968 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3970 aopPut (AOP (IC_RESULT (ic)),
3971 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3975 if (opIsGptr (IC_RESULT (ic)) &&
3976 opIsGptr (IC_RIGHT (ic)) &&
3977 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3979 aopPut (AOP (IC_RESULT (ic)),
3980 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3984 if (opIsGptr (IC_RESULT (ic)) &&
3985 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3986 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3987 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3988 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3991 SNPRINTF (buff, sizeof(buff),
3992 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3993 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3997 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3998 // generates the result if possible. If result is generated, returns TRUE; otherwise
3999 // returns false and caller must deal with fact that result isn't aopOp'd.
4000 bool aopOp3(iCode * ic)
4002 bool dp1InUse, dp2InUse;
4005 // First, generate the right opcode. DPTR may be used if neither left nor result are
4008 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4009 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4010 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4011 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4013 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4014 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4015 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4016 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4019 // Right uses DPTR unless left or result is an AOP_STR; however,
4020 // if right is an AOP_STR, it must use DPTR regardless.
4021 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4022 && !AOP_IS_STR(IC_RIGHT(ic)))
4031 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4033 // if the right used DPTR, left MUST use DPTR2.
4034 // if the right used DPTR2, left MUST use DPTR.
4035 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4036 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4037 // enabling us to assign DPTR to result.
4039 if (AOP_USESDPTR(IC_RIGHT(ic)))
4043 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4049 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4059 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4062 // We've op'd the left & right. So, if left or right are the same operand as result,
4063 // we know aopOp will succeed, and we can just do it & bail.
4064 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4066 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4069 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4071 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4072 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4076 // Operands may be equivalent (but not equal) if they share a spill location. If
4077 // so, use the same DPTR or DPTR2.
4078 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4080 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4083 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4085 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4089 // Note which dptrs are currently in use.
4090 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4091 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4093 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4095 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4100 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4101 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4106 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4107 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4112 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4114 // Some sanity checking...
4115 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4118 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4119 __FILE__, __LINE__, ic->filename, ic->lineno);
4120 emitcode(";", ">>> unexpected DPTR here.");
4123 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4126 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4127 __FILE__, __LINE__, ic->filename, ic->lineno);
4128 emitcode(";", ">>> unexpected DPTR2 here.");
4134 // Macro to aopOp all three operands of an ic. If this cannot be done,
4135 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4136 // will be set TRUE. The caller must then handle the case specially, noting
4137 // that the IC_RESULT operand is not aopOp'd.
4139 #define AOP_OP_3_NOFATAL(ic, rc) \
4140 do { rc = !aopOp3(ic); } while (0)
4142 // aopOp the left & right operands of an ic.
4143 #define AOP_OP_2(ic) \
4144 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4145 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4147 // convienience macro.
4148 #define AOP_SET_LOCALS(ic) \
4149 left = IC_LEFT(ic); \
4150 right = IC_RIGHT(ic); \
4151 result = IC_RESULT(ic);
4154 // Given an integer value of pushedSize bytes on the stack,
4155 // adjust it to be resultSize bytes, either by discarding
4156 // the most significant bytes or by zero-padding.
4158 // On exit from this macro, pushedSize will have been adjusted to
4159 // equal resultSize, and ACC may be trashed.
4160 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4161 /* If the pushed data is bigger than the result, \
4162 * simply discard unused bytes. Icky, but works. \
4164 while (pushedSize > resultSize) \
4166 D (emitcode (";", "discarding unused result byte."););\
4167 emitcode ("pop", "acc"); \
4170 if (pushedSize < resultSize) \
4172 emitcode ("clr", "a"); \
4173 /* Conversly, we haven't pushed enough here. \
4174 * just zero-pad, and all is well. \
4176 while (pushedSize < resultSize) \
4178 emitcode("push", "acc"); \
4182 assert(pushedSize == resultSize);
4184 /*-----------------------------------------------------------------*/
4185 /* genPlus - generates code for addition */
4186 /*-----------------------------------------------------------------*/
4188 genPlus (iCode * ic)
4190 int size, offset = 0;
4194 D (emitcode (";", "genPlus "););
4196 /* special cases :- */
4197 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4198 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4199 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4200 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4202 while (size--) emitcode ("inc","dptr");
4204 emitcode ("mov","a,dpl");
4205 emitcode ("add","a,#!constbyte",size & 0xff);
4206 emitcode ("mov","dpl,a");
4207 emitcode ("mov","a,dph");
4208 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4209 emitcode ("mov","dph,a");
4210 emitcode ("mov","a,dpx");
4211 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4212 emitcode ("mov","dpx,a");
4214 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4217 if ( IS_SYMOP(IC_LEFT(ic)) &&
4218 OP_SYMBOL(IC_LEFT(ic))->remat &&
4219 isOperandInFarSpace(IC_RIGHT(ic))) {
4220 operand *op = IC_RIGHT(ic);
4221 IC_RIGHT(ic) = IC_LEFT(ic);
4225 AOP_OP_3_NOFATAL (ic, pushResult);
4229 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4234 /* if literal, literal on the right or
4235 if left requires ACC or right is already
4237 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4238 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4239 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4241 operand *t = IC_RIGHT (ic);
4242 IC_RIGHT (ic) = IC_LEFT (ic);
4244 emitcode (";", "Swapped plus args.");
4247 /* if both left & right are in bit
4249 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4250 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4256 /* if left in bit space & right literal */
4257 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4258 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4260 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4261 /* if result in bit space */
4262 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4264 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4265 emitcode ("cpl", "c");
4266 outBitC (IC_RESULT (ic));
4270 size = getDataSize (IC_RESULT (ic));
4271 _startLazyDPSEvaluation ();
4274 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4275 emitcode ("addc", "a,#0");
4276 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4278 _endLazyDPSEvaluation ();
4283 /* if I can do an increment instead
4284 of add then GOOD for ME */
4285 if (genPlusIncr (ic) == TRUE)
4287 emitcode (";", "did genPlusIncr");
4292 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4294 _startLazyDPSEvaluation ();
4297 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4299 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4301 emitcode ("add", "a,%s",
4302 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4304 emitcode ("addc", "a,%s",
4305 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4309 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4311 /* right is going to use ACC or we would have taken the
4314 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4316 D(emitcode(";", "+ AOP_ACC special case."););
4317 emitcode("xch", "a, %s", DP2_RESULT_REG);
4319 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4325 emitcode("add", "a, %s", DP2_RESULT_REG);
4329 emitcode ("add", "a,%s",
4330 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4336 emitcode ("addc", "a,%s",
4337 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4343 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4347 emitcode ("push", "acc");
4351 _endLazyDPSEvaluation ();
4355 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4357 size = getDataSize (IC_LEFT (ic));
4358 rSize = getDataSize (IC_RESULT (ic));
4360 ADJUST_PUSHED_RESULT(size, rSize);
4362 _startLazyDPSEvaluation ();
4365 emitcode ("pop", "acc");
4366 aopPut (AOP (IC_RESULT (ic)), "a", size);
4368 _endLazyDPSEvaluation ();
4371 adjustArithmeticResult (ic);
4374 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4376 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4379 /*-----------------------------------------------------------------*/
4380 /* genMinusDec :- does subtraction with deccrement if possible */
4381 /*-----------------------------------------------------------------*/
4383 genMinusDec (iCode * ic)
4385 unsigned int icount;
4386 unsigned int size = getDataSize (IC_RESULT (ic));
4388 /* will try to generate an increment */
4389 /* if the right side is not a literal
4391 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4394 /* if the literal value of the right hand side
4395 is greater than 4 then it is not worth it */
4396 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4399 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4400 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4402 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4406 /* if decrement 16 bits in register */
4407 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4408 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4409 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4418 /* If the next instruction is a goto and the goto target
4419 * is <= 5 instructions previous to this, we can generate
4420 * jumps straight to that target.
4422 if (ic->next && ic->next->op == GOTO
4423 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4426 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4427 tlbl = IC_LABEL (ic->next);
4432 tlbl = newiTempLabel (NULL);
4436 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4437 emitcode ("dec", "%s", l);
4439 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4440 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4441 IS_AOP_PREG (IC_RESULT (ic)))
4443 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4447 emitcode ("mov", "a,#!constbyte",0xff);
4448 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4450 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4451 emitcode ("dec", "%s", l);
4454 if (!strcmp(l, "acc"))
4456 emitcode("jnz", "!tlabel", tlbl->key + 100);
4458 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4459 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4460 IS_AOP_PREG (IC_RESULT (ic)))
4462 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4466 emitcode ("mov", "a,#!constbyte",0xff);
4467 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4469 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4470 emitcode ("dec", "%s", l);
4474 if (!strcmp(l, "acc"))
4476 emitcode("jnz", "!tlabel", tlbl->key + 100);
4478 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4479 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4480 IS_AOP_PREG (IC_RESULT (ic)))
4482 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4486 emitcode ("mov", "a,#!constbyte",0xff);
4487 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4489 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4490 emitcode ("dec", "%s", l);
4494 emitcode ("", "!tlabeldef", tlbl->key + 100);
4499 /* if the sizes are greater than 1 then we cannot */
4500 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4501 AOP_SIZE (IC_LEFT (ic)) > 1)
4504 /* we can if the aops of the left & result match or
4505 if they are in registers and the registers are the
4508 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4509 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4510 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4513 _startLazyDPSEvaluation ();
4516 emitcode ("dec", "%s",
4517 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4519 _endLazyDPSEvaluation ();
4527 /*-----------------------------------------------------------------*/
4528 /* addSign - complete with sign */
4529 /*-----------------------------------------------------------------*/
4531 addSign (operand * result, int offset, int sign)
4533 int size = (getDataSize (result) - offset);
4536 _startLazyDPSEvaluation();
4539 emitcode ("rlc", "a");
4540 emitcode ("subb", "a,acc");
4543 aopPut (AOP (result), "a", offset++);
4550 aopPut (AOP (result), zero, offset++);
4553 _endLazyDPSEvaluation();
4557 /*-----------------------------------------------------------------*/
4558 /* genMinusBits - generates code for subtraction of two bits */
4559 /*-----------------------------------------------------------------*/
4561 genMinusBits (iCode * ic)
4563 symbol *lbl = newiTempLabel (NULL);
4565 D (emitcode (";", "genMinusBits "););
4567 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4569 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4570 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4571 emitcode ("cpl", "c");
4572 emitcode ("", "!tlabeldef", (lbl->key + 100));
4573 outBitC (IC_RESULT (ic));
4577 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4578 emitcode ("subb", "a,acc");
4579 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4580 emitcode ("inc", "a");
4581 emitcode ("", "!tlabeldef", (lbl->key + 100));
4582 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4583 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4587 /*-----------------------------------------------------------------*/
4588 /* genMinus - generates code for subtraction */
4589 /*-----------------------------------------------------------------*/
4591 genMinus (iCode * ic)
4593 int size, offset = 0;
4598 D (emitcode (";", "genMinus "););
4600 AOP_OP_3_NOFATAL(ic, pushResult);
4604 /* special cases :- */
4605 /* if both left & right are in bit space */
4606 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4607 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4613 /* if I can do an decrement instead
4614 of subtract then GOOD for ME */
4615 if (genMinusDec (ic) == TRUE)
4620 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4622 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4628 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4633 /* if literal, add a,#-lit, else normal subb */
4634 _startLazyDPSEvaluation ();
4636 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4637 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4638 emitcode ("mov","b,%s",
4639 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4640 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4641 emitcode ("subb","a,b");
4643 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4644 emitcode ("subb", "a,%s",
4645 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4649 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4650 /* first add without previous c */
4652 if (!size && lit==-1) {
4653 emitcode ("dec", "a");
4655 emitcode ("add", "a,#!constbyte",
4656 (unsigned int) (lit & 0x0FFL));
4659 emitcode ("addc", "a,#!constbyte",
4660 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4665 emitcode ("push", "acc");
4667 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4671 _endLazyDPSEvaluation ();
4675 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4677 size = getDataSize (IC_LEFT (ic));
4678 rSize = getDataSize (IC_RESULT (ic));
4680 ADJUST_PUSHED_RESULT(size, rSize);
4682 _startLazyDPSEvaluation ();
4685 emitcode ("pop", "acc");
4686 aopPut (AOP (IC_RESULT (ic)), "a", size);
4688 _endLazyDPSEvaluation ();
4691 adjustArithmeticResult (ic);
4694 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4700 /*-----------------------------------------------------------------*/
4701 /* genMultbits :- multiplication of bits */
4702 /*-----------------------------------------------------------------*/
4704 genMultbits (operand * left,
4709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4710 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4711 aopOp(result, ic, TRUE, FALSE);
4716 /*-----------------------------------------------------------------*/
4717 /* genMultOneByte : 8*8=8/16 bit multiplication */
4718 /*-----------------------------------------------------------------*/
4720 genMultOneByte (operand * left,
4727 bool runtimeSign, compiletimeSign;
4728 bool lUnsigned, rUnsigned;
4731 /* (if two literals: the value is computed before) */
4732 /* if one literal, literal on the right */
4733 if (AOP_TYPE (left) == AOP_LIT)
4738 emitcode (";", "swapped left and right");
4741 /* (if two literals: the value is computed before) */
4742 /* if one literal, literal on the right */
4743 if (AOP_TYPE (left) == AOP_LIT)
4748 /* emitcode (";", "swapped left and right"); */
4750 /* if no literal, unsigned on the right: shorter code */
4751 if ( AOP_TYPE (right) != AOP_LIT
4752 && SPEC_USIGN (getSpec (operandType (left))))
4759 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4760 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4762 if ((lUnsigned && rUnsigned)
4763 /* sorry, I don't know how to get size
4764 without calling aopOp (result,...);
4765 see Feature Request */
4766 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4767 no need to take care about the signedness! */
4769 /* just an unsigned 8 * 8 = 8 multiply
4771 /* emitcode (";","unsigned"); */
4772 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4773 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4774 emitcode ("mul", "ab");
4776 _G.accInUse++; _G.bInUse++;
4777 aopOp (result, ic, TRUE, FALSE);
4778 size = AOP_SIZE (result);
4780 if (size < 1 || size > 2)
4782 /* this should never happen */
4783 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4784 size, __FILE__, lineno);
4788 aopPut (AOP (result), "a", 0);
4789 _G.accInUse--; _G.bInUse--;
4791 aopPut (AOP (result), "b", 1);
4795 /* we have to do a signed multiply */
4796 /* emitcode (";", "signed"); */
4798 /* now sign adjust for both left & right */
4800 /* let's see what's needed: */
4801 /* apply negative sign during runtime */
4802 runtimeSign = FALSE;
4803 /* negative sign from literals */
4804 compiletimeSign = FALSE;
4808 if (AOP_TYPE(left) == AOP_LIT)
4810 /* signed literal */
4811 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4813 compiletimeSign = TRUE;
4816 /* signed but not literal */
4822 if (AOP_TYPE(right) == AOP_LIT)
4824 /* signed literal */
4825 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4827 compiletimeSign ^= TRUE;
4830 /* signed but not literal */
4834 /* initialize F0, which stores the runtime sign */
4837 if (compiletimeSign)
4838 emitcode ("setb", "F0"); /* set sign flag */
4840 emitcode ("clr", "F0"); /* reset sign flag */
4843 /* save the signs of the operands */
4844 if (AOP_TYPE(right) == AOP_LIT)
4846 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4848 if (!rUnsigned && val < 0)
4849 emitcode ("mov", "b,#!constbyte", -val);
4851 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4853 else /* ! literal */
4855 if (rUnsigned) /* emitcode (";", "signed"); */
4856 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4859 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4860 lbl = newiTempLabel (NULL);
4861 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4862 emitcode ("cpl", "F0"); /* complement sign flag */
4863 emitcode ("cpl", "a"); /* 2's complement */
4864 emitcode ("inc", "a");
4865 emitcode ("", "!tlabeldef", lbl->key + 100);
4866 emitcode ("mov", "b,a");
4870 if (AOP_TYPE(left) == AOP_LIT)
4872 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4874 if (!lUnsigned && val < 0)
4875 emitcode ("mov", "a,#!constbyte", -val);
4877 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4879 else /* ! literal */
4881 if (lUnsigned) /* emitcode (";", "signed"); */
4883 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4886 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4887 lbl = newiTempLabel (NULL);
4888 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4889 emitcode ("cpl", "F0"); /* complement sign flag */
4890 emitcode ("cpl", "a"); /* 2's complement */
4891 emitcode ("inc", "a");
4892 emitcode ("", "!tlabeldef", lbl->key + 100);
4896 /* now the multiplication */
4897 emitcode ("mul", "ab");
4898 _G.accInUse++;_G.bInUse++;
4899 aopOp(result, ic, TRUE, FALSE);
4900 size = AOP_SIZE (result);
4902 if (size < 1 || size > 2)
4904 /* this should never happen */
4905 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4906 size, __FILE__, lineno);
4910 if (runtimeSign || compiletimeSign)
4912 lbl = newiTempLabel (NULL);
4914 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4915 emitcode ("cpl", "a"); /* lsb 2's complement */
4917 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4920 emitcode ("add", "a,#1"); /* this sets carry flag */
4921 emitcode ("xch", "a,b");
4922 emitcode ("cpl", "a"); /* msb 2's complement */
4923 emitcode ("addc", "a,#0");
4924 emitcode ("xch", "a,b");
4926 emitcode ("", "!tlabeldef", lbl->key + 100);
4928 aopPut (AOP (result), "a", 0);
4929 _G.accInUse--;_G.bInUse--;
4931 aopPut (AOP (result), "b", 1);
4934 /*-----------------------------------------------------------------*/
4935 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4936 /*-----------------------------------------------------------------*/
4937 static void genMultTwoByte (operand *left, operand *right,
4938 operand *result, iCode *ic)
4940 sym_link *retype = getSpec(operandType(right));
4941 sym_link *letype = getSpec(operandType(left));
4942 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4945 if (AOP_TYPE (left) == AOP_LIT) {
4950 /* save EA bit in F1 */
4951 lbl = newiTempLabel(NULL);
4952 emitcode ("setb","F1");
4953 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4954 emitcode ("clr","F1");
4955 emitcode("","!tlabeldef",lbl->key+100);
4957 /* load up MB with right */
4959 emitcode("clr","F0");
4960 if (AOP_TYPE(right) == AOP_LIT) {
4961 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4963 emitcode("setb","F0");
4966 emitcode ("mov","mb,#!constbyte",val & 0xff);
4967 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4969 lbl = newiTempLabel(NULL);
4970 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4971 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4972 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4973 emitcode ("xch", "a,b");
4974 emitcode ("cpl","a");
4975 emitcode ("add", "a,#1");
4976 emitcode ("xch", "a,b");
4977 emitcode ("cpl", "a"); // msb
4978 emitcode ("addc", "a,#0");
4979 emitcode ("setb","F0");
4980 emitcode ("","!tlabeldef",lbl->key+100);
4981 emitcode ("mov","mb,b");
4982 emitcode ("mov","mb,a");
4985 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4986 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4988 /* load up MA with left */
4990 lbl = newiTempLabel(NULL);
4991 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4992 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4993 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4994 emitcode ("xch", "a,b");
4995 emitcode ("cpl","a");
4996 emitcode ("add", "a,#1");
4997 emitcode ("xch", "a,b");
4998 emitcode ("cpl", "a"); // msb
4999 emitcode ("addc","a,#0");
5000 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5001 emitcode ("setb","F0");
5002 emitcode ("","!tlabeldef",lbl->key+100);
5003 emitcode ("mov","ma,b");
5004 emitcode ("mov","ma,a");
5006 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5009 /* wait for multiplication to finish */
5010 lbl = newiTempLabel(NULL);
5011 emitcode("","!tlabeldef", lbl->key+100);
5012 emitcode("mov","a,mcnt1");
5013 emitcode("anl","a,#!constbyte",0x80);
5014 emitcode("jnz","!tlabel",lbl->key+100);
5016 freeAsmop (left, NULL, ic, TRUE);
5017 freeAsmop (right, NULL, ic,TRUE);
5018 aopOp(result, ic, TRUE, FALSE);
5020 /* if unsigned then simple */
5022 emitcode ("mov","a,ma");
5023 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5024 emitcode ("mov","a,ma");
5025 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5026 aopPut(AOP(result),"ma",1);
5027 aopPut(AOP(result),"ma",0);
5029 emitcode("push","ma");
5030 emitcode("push","ma");
5031 emitcode("push","ma");
5033 /* negate result if needed */
5034 lbl = newiTempLabel(NULL);
5035 emitcode("jnb","F0,!tlabel",lbl->key+100);
5036 emitcode("cpl","a");
5037 emitcode("add","a,#1");
5038 emitcode("","!tlabeldef", lbl->key+100);
5039 if (AOP_TYPE(result) == AOP_ACC)
5041 D(emitcode(";", "ACC special case."););
5042 /* We know result is the only live aop, and
5043 * it's obviously not a DPTR2, so AP is available.
5045 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5049 aopPut(AOP(result),"a",0);
5052 emitcode("pop","acc");
5053 lbl = newiTempLabel(NULL);
5054 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055 emitcode("cpl","a");
5056 emitcode("addc","a,#0");
5057 emitcode("","!tlabeldef", lbl->key+100);
5058 aopPut(AOP(result),"a",1);
5059 emitcode("pop","acc");
5060 if (AOP_SIZE(result) >= 3) {
5061 lbl = newiTempLabel(NULL);
5062 emitcode("jnb","F0,!tlabel",lbl->key+100);
5063 emitcode("cpl","a");
5064 emitcode("addc","a,#0");
5065 emitcode("","!tlabeldef", lbl->key+100);
5066 aopPut(AOP(result),"a",2);
5068 emitcode("pop","acc");
5069 if (AOP_SIZE(result) >= 4) {
5070 lbl = newiTempLabel(NULL);
5071 emitcode("jnb","F0,!tlabel",lbl->key+100);
5072 emitcode("cpl","a");
5073 emitcode("addc","a,#0");
5074 emitcode("","!tlabeldef", lbl->key+100);
5075 aopPut(AOP(result),"a",3);
5077 if (AOP_TYPE(result) == AOP_ACC)
5079 /* We stashed the result away above. */
5080 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5084 freeAsmop (result, NULL, ic, TRUE);
5086 /* restore EA bit in F1 */
5087 lbl = newiTempLabel(NULL);
5088 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5089 emitcode ("setb","EA");
5090 emitcode("","!tlabeldef",lbl->key+100);
5094 /*-----------------------------------------------------------------*/
5095 /* genMult - generates code for multiplication */
5096 /*-----------------------------------------------------------------*/
5098 genMult (iCode * ic)
5100 operand *left = IC_LEFT (ic);
5101 operand *right = IC_RIGHT (ic);
5102 operand *result = IC_RESULT (ic);
5104 D (emitcode (";", "genMult "););
5106 /* assign the amsops */
5109 /* special cases first */
5111 if (AOP_TYPE (left) == AOP_CRY &&
5112 AOP_TYPE (right) == AOP_CRY)
5114 genMultbits (left, right, result, ic);
5118 /* if both are of size == 1 */
5119 if (AOP_SIZE (left) == 1 &&
5120 AOP_SIZE (right) == 1)
5122 genMultOneByte (left, right, result, ic);
5126 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5127 /* use the ds390 ARITHMETIC accel UNIT */
5128 genMultTwoByte (left, right, result, ic);
5131 /* should have been converted to function call */
5135 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137 freeAsmop (result, NULL, ic, TRUE);
5140 /*-----------------------------------------------------------------*/
5141 /* genDivbits :- division of bits */
5142 /*-----------------------------------------------------------------*/
5144 genDivbits (operand * left,
5152 /* the result must be bit */
5153 LOAD_AB_FOR_DIV (left, right, l);
5154 emitcode ("div", "ab");
5155 emitcode ("rrc", "a");
5156 aopOp(result, ic, TRUE, FALSE);
5158 aopPut (AOP (result), "c", 0);
5161 /*-----------------------------------------------------------------*/
5162 /* genDivOneByte : 8 bit division */
5163 /*-----------------------------------------------------------------*/
5165 genDivOneByte (operand * left,
5170 bool lUnsigned, rUnsigned;
5171 bool runtimeSign, compiletimeSign;
5177 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5178 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5180 /* signed or unsigned */
5181 if (lUnsigned && rUnsigned)
5183 /* unsigned is easy */
5184 LOAD_AB_FOR_DIV (left, right, l);
5185 emitcode ("div", "ab");
5188 aopOp (result, ic, TRUE, FALSE);
5189 aopPut (AOP (result), "a", 0);
5192 size = AOP_SIZE (result) - 1;
5195 aopPut (AOP (result), zero, offset++);
5199 /* signed is a little bit more difficult */
5201 /* now sign adjust for both left & right */
5203 /* let's see what's needed: */
5204 /* apply negative sign during runtime */
5205 runtimeSign = FALSE;
5206 /* negative sign from literals */
5207 compiletimeSign = FALSE;
5211 if (AOP_TYPE(left) == AOP_LIT)
5213 /* signed literal */
5214 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5216 compiletimeSign = TRUE;
5219 /* signed but not literal */
5225 if (AOP_TYPE(right) == AOP_LIT)
5227 /* signed literal */
5228 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5230 compiletimeSign ^= TRUE;
5233 /* signed but not literal */
5237 /* initialize F0, which stores the runtime sign */
5240 if (compiletimeSign)
5241 emitcode ("setb", "F0"); /* set sign flag */
5243 emitcode ("clr", "F0"); /* reset sign flag */
5246 /* save the signs of the operands */
5247 if (AOP_TYPE(right) == AOP_LIT)
5249 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5251 if (!rUnsigned && val < 0)
5252 emitcode ("mov", "b,#0x%02x", -val);
5254 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5256 else /* ! literal */
5259 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5262 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5263 lbl = newiTempLabel (NULL);
5264 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5265 emitcode ("cpl", "F0"); /* complement sign flag */
5266 emitcode ("cpl", "a"); /* 2's complement */
5267 emitcode ("inc", "a");
5268 emitcode ("", "!tlabeldef", lbl->key + 100);
5269 emitcode ("mov", "b,a");
5273 if (AOP_TYPE(left) == AOP_LIT)
5275 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5277 if (!lUnsigned && val < 0)
5278 emitcode ("mov", "a,#0x%02x", -val);
5280 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5282 else /* ! literal */
5285 emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5289 lbl = newiTempLabel (NULL);
5290 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5291 emitcode ("cpl", "F0"); /* complement sign flag */
5292 emitcode ("cpl", "a"); /* 2's complement */
5293 emitcode ("inc", "a");
5294 emitcode ("", "!tlabeldef", lbl->key + 100);
5298 /* now the division */
5299 emitcode ("nop", "; workaround for DS80C390 div bug.");
5300 emitcode ("div", "ab");
5302 if (runtimeSign || compiletimeSign)
5304 lbl = newiTempLabel (NULL);
5306 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5307 emitcode ("cpl", "a"); /* lsb 2's complement */
5308 emitcode ("inc", "a");
5309 emitcode ("", "!tlabeldef", lbl->key + 100);
5311 _G.accInUse++; _G.bInUse++;
5312 aopOp (result, ic, TRUE, FALSE);
5313 size = AOP_SIZE (result) - 1;
5317 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5318 then the result will be in b, a */
5319 emitcode ("mov", "b,a"); /* 1 */
5320 /* msb is 0x00 or 0xff depending on the sign */
5323 emitcode ("mov", "c,F0");
5324 emitcode ("subb", "a,acc");
5325 emitcode ("xch", "a,b"); /* 2 */
5327 aopPut (AOP (result), "b", offset++); /* write msb's */
5329 else /* compiletimeSign */
5331 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5333 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5337 _G.accInUse++; _G.bInUse++;
5338 aopOp(result, ic, TRUE, FALSE);
5339 size = AOP_SIZE (result) - 1;
5341 aopPut (AOP (result), "a", 0);
5343 aopPut (AOP (result), zero, offset++);
5345 _G.accInUse--; _G.bInUse--;
5349 /*-----------------------------------------------------------------*/
5350 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5351 /*-----------------------------------------------------------------*/
5352 static void genDivTwoByte (operand *left, operand *right,
5353 operand *result, iCode *ic)
5355 sym_link *retype = getSpec(operandType(right));
5356 sym_link *letype = getSpec(operandType(left));
5357 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5360 /* save EA bit in F1 */
5361 lbl = newiTempLabel(NULL);
5362 emitcode ("setb","F1");
5363 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5364 emitcode ("clr","F1");
5365 emitcode("","!tlabeldef",lbl->key+100);
5367 /* load up MA with left */
5369 emitcode("clr","F0");
5370 lbl = newiTempLabel(NULL);
5371 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5372 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5373 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5374 emitcode ("xch", "a,b");
5375 emitcode ("cpl","a");
5376 emitcode ("add", "a,#1");
5377 emitcode ("xch", "a,b");
5378 emitcode ("cpl", "a"); // msb
5379 emitcode ("addc","a,#0");
5380 emitcode ("setb","F0");
5381 emitcode ("","!tlabeldef",lbl->key+100);
5382 emitcode ("mov","ma,b");
5383 emitcode ("mov","ma,a");
5385 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5386 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5389 /* load up MB with right */
5391 if (AOP_TYPE(right) == AOP_LIT) {
5392 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5394 lbl = newiTempLabel(NULL);
5395 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5396 emitcode("setb","F0");
5397 emitcode ("","!tlabeldef",lbl->key+100);
5400 emitcode ("mov","mb,#!constbyte",val & 0xff);
5401 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5403 lbl = newiTempLabel(NULL);
5404 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5405 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5406 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5407 emitcode ("xch", "a,b");
5408 emitcode ("cpl","a");
5409 emitcode ("add", "a,#1");
5410 emitcode ("xch", "a,b");
5411 emitcode ("cpl", "a"); // msb
5412 emitcode ("addc", "a,#0");
5413 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414 emitcode ("setb","F0");
5415 emitcode ("","!tlabeldef",lbl->key+100);
5416 emitcode ("mov","mb,b");
5417 emitcode ("mov","mb,a");
5420 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5421 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424 /* wait for multiplication to finish */
5425 lbl = newiTempLabel(NULL);
5426 emitcode("","!tlabeldef", lbl->key+100);
5427 emitcode("mov","a,mcnt1");
5428 emitcode("anl","a,#!constbyte",0x80);
5429 emitcode("jnz","!tlabel",lbl->key+100);
5431 freeAsmop (left, NULL, ic, TRUE);
5432 freeAsmop (right, NULL, ic,TRUE);
5433 aopOp(result, ic, TRUE, FALSE);
5435 /* if unsigned then simple */
5437 aopPut(AOP(result),"ma",1);
5438 aopPut(AOP(result),"ma",0);
5440 emitcode("push","ma");
5442 /* negate result if needed */
5443 lbl = newiTempLabel(NULL);
5444 emitcode("jnb","F0,!tlabel",lbl->key+100);
5445 emitcode("cpl","a");
5446 emitcode("add","a,#1");
5447 emitcode("","!tlabeldef", lbl->key+100);
5448 aopPut(AOP(result),"a",0);
5449 emitcode("pop","acc");
5450 lbl = newiTempLabel(NULL);
5451 emitcode("jnb","F0,!tlabel",lbl->key+100);
5452 emitcode("cpl","a");
5453 emitcode("addc","a,#0");
5454 emitcode("","!tlabeldef", lbl->key+100);
5455 aopPut(AOP(result),"a",1);
5457 freeAsmop (result, NULL, ic, TRUE);
5458 /* restore EA bit in F1 */
5459 lbl = newiTempLabel(NULL);
5460 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5461 emitcode ("setb","EA");
5462 emitcode("","!tlabeldef",lbl->key+100);
5466 /*-----------------------------------------------------------------*/
5467 /* genDiv - generates code for division */
5468 /*-----------------------------------------------------------------*/
5472 operand *left = IC_LEFT (ic);
5473 operand *right = IC_RIGHT (ic);
5474 operand *result = IC_RESULT (ic);
5476 D (emitcode (";", "genDiv "););
5478 /* assign the amsops */
5481 /* special cases first */
5483 if (AOP_TYPE (left) == AOP_CRY &&
5484 AOP_TYPE (right) == AOP_CRY)
5486 genDivbits (left, right, result, ic);
5490 /* if both are of size == 1 */
5491 if (AOP_SIZE (left) == 1 &&
5492 AOP_SIZE (right) == 1)
5494 genDivOneByte (left, right, result, ic);
5498 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5499 /* use the ds390 ARITHMETIC accel UNIT */
5500 genDivTwoByte (left, right, result, ic);
5503 /* should have been converted to function call */
5506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 freeAsmop (result, NULL, ic, TRUE);
5511 /*-----------------------------------------------------------------*/
5512 /* genModbits :- modulus of bits */
5513 /*-----------------------------------------------------------------*/
5515 genModbits (operand * left,
5523 /* the result must be bit */
5524 LOAD_AB_FOR_DIV (left, right, l);
5525 emitcode ("div", "ab");
5526 emitcode ("mov", "a,b");
5527 emitcode ("rrc", "a");
5528 aopOp(result, ic, TRUE, FALSE);
5529 aopPut (AOP (result), "c", 0);
5532 /*-----------------------------------------------------------------*/
5533 /* genModOneByte : 8 bit modulus */
5534 /*-----------------------------------------------------------------*/
5536 genModOneByte (operand * left,
5541 bool lUnsigned, rUnsigned;
5542 bool runtimeSign, compiletimeSign;
5548 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5549 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5551 /* signed or unsigned */
5552 if (lUnsigned && rUnsigned)
5554 /* unsigned is easy */
5555 LOAD_AB_FOR_DIV (left, right, l);
5556 emitcode ("div", "ab");
5557 aopOp (result, ic, TRUE, FALSE);
5558 aopPut (AOP (result), "b", 0);
5560 for (size = AOP_SIZE (result) - 1; size--;)
5561 aopPut (AOP (result), zero, offset++);
5565 /* signed is a little bit more difficult */
5567 /* now sign adjust for both left & right */
5569 /* modulus: sign of the right operand has no influence on the result! */
5570 if (AOP_TYPE(right) == AOP_LIT)
5572 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5574 if (!rUnsigned && val < 0)
5575 emitcode ("mov", "b,#0x%02x", -val);
5577 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5579 else /* ! literal */
5582 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5585 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5586 lbl = newiTempLabel (NULL);
5587 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5588 emitcode ("cpl", "a"); /* 2's complement */
5589 emitcode ("inc", "a");
5590 emitcode ("", "!tlabeldef", lbl->key + 100);
5591 emitcode ("mov", "b,a");
5595 /* let's see what's needed: */
5596 /* apply negative sign during runtime */
5597 runtimeSign = FALSE;
5598 /* negative sign from literals */
5599 compiletimeSign = FALSE;
5601 /* sign adjust left side */
5602 if (AOP_TYPE(left) == AOP_LIT)
5604 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5606 if (!lUnsigned && val < 0)
5608 compiletimeSign = TRUE; /* set sign flag */
5609 emitcode ("mov", "a,#0x%02x", -val);
5612 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5614 else /* ! literal */
5616 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5621 emitcode ("clr", "F0"); /* clear sign flag */
5623 lbl = newiTempLabel (NULL);
5624 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5625 emitcode ("setb", "F0"); /* set sign flag */
5626 emitcode ("cpl", "a"); /* 2's complement */
5627 emitcode ("inc", "a");
5628 emitcode ("", "!tlabeldef", lbl->key + 100);
5632 /* now the modulus */
5633 emitcode ("nop", "; workaround for DS80C390 div bug.");
5634 emitcode ("div", "ab");
5636 if (runtimeSign || compiletimeSign)
5638 emitcode ("mov", "a,b");
5639 lbl = newiTempLabel (NULL);
5641 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5642 emitcode ("cpl", "a"); /* lsb 2's complement */
5643 emitcode ("inc", "a");
5644 emitcode ("", "!tlabeldef", lbl->key + 100);
5646 _G.accInUse++; _G.bInUse++;
5647 aopOp (result, ic, TRUE, FALSE);
5648 size = AOP_SIZE (result) - 1;
5652 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5653 then the result will be in b, a */
5654 emitcode ("mov", "b,a"); /* 1 */
5655 /* msb is 0x00 or 0xff depending on the sign */
5658 emitcode ("mov", "c,F0");
5659 emitcode ("subb", "a,acc");
5660 emitcode ("xch", "a,b"); /* 2 */
5662 aopPut (AOP (result), "b", offset++); /* write msb's */
5664 else /* compiletimeSign */
5666 aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5668 aopPut (AOP (result), "a", 0); /* 3: write lsb */
5672 _G.accInUse++; _G.bInUse++;
5673 aopOp(result, ic, TRUE, FALSE);
5674 size = AOP_SIZE (result) - 1;
5676 aopPut (AOP (result), "b", 0);
5678 aopPut (AOP (result), zero, offset++);
5680 _G.accInUse--; _G.bInUse--;
5684 /*-----------------------------------------------------------------*/
5685 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5686 /*-----------------------------------------------------------------*/
5687 static void genModTwoByte (operand *left, operand *right,
5688 operand *result, iCode *ic)
5690 sym_link *retype = getSpec(operandType(right));
5691 sym_link *letype = getSpec(operandType(left));
5692 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5695 /* load up MA with left */
5696 /* save EA bit in F1 */
5697 lbl = newiTempLabel(NULL);
5698 emitcode ("setb","F1");
5699 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5700 emitcode ("clr","F1");
5701 emitcode("","!tlabeldef",lbl->key+100);
5704 lbl = newiTempLabel(NULL);
5705 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5706 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5707 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5708 emitcode ("xch", "a,b");
5709 emitcode ("cpl","a");
5710 emitcode ("add", "a,#1");
5711 emitcode ("xch", "a,b");
5712 emitcode ("cpl", "a"); // msb
5713 emitcode ("addc","a,#0");
5714 emitcode ("","!tlabeldef",lbl->key+100);
5715 emitcode ("mov","ma,b");
5716 emitcode ("mov","ma,a");
5718 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5719 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5722 /* load up MB with right */
5724 if (AOP_TYPE(right) == AOP_LIT) {
5725 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5729 emitcode ("mov","mb,#!constbyte",val & 0xff);
5730 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5732 lbl = newiTempLabel(NULL);
5733 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5734 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5735 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5736 emitcode ("xch", "a,b");
5737 emitcode ("cpl","a");
5738 emitcode ("add", "a,#1");
5739 emitcode ("xch", "a,b");
5740 emitcode ("cpl", "a"); // msb
5741 emitcode ("addc", "a,#0");
5742 emitcode ("","!tlabeldef",lbl->key+100);
5743 emitcode ("mov","mb,b");
5744 emitcode ("mov","mb,a");
5747 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5748 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5751 /* wait for multiplication to finish */
5752 lbl = newiTempLabel(NULL);
5753 emitcode("","!tlabeldef", lbl->key+100);
5754 emitcode("mov","a,mcnt1");
5755 emitcode("anl","a,#!constbyte",0x80);
5756 emitcode("jnz","!tlabel",lbl->key+100);
5758 freeAsmop (left, NULL, ic, TRUE);
5759 freeAsmop (right, NULL, ic,TRUE);
5760 aopOp(result, ic, TRUE, FALSE);
5762 aopPut(AOP(result),"mb",1);
5763 aopPut(AOP(result),"mb",0);
5764 freeAsmop (result, NULL, ic, TRUE);
5766 /* restore EA bit in F1 */
5767 lbl = newiTempLabel(NULL);
5768 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5769 emitcode ("setb","EA");
5770 emitcode("","!tlabeldef",lbl->key+100);
5774 /*-----------------------------------------------------------------*/
5775 /* genMod - generates code for division */
5776 /*-----------------------------------------------------------------*/
5780 operand *left = IC_LEFT (ic);
5781 operand *right = IC_RIGHT (ic);
5782 operand *result = IC_RESULT (ic);
5784 D (emitcode (";", "genMod "); );
5786 /* assign the amsops */
5789 /* special cases first */
5791 if (AOP_TYPE (left) == AOP_CRY &&
5792 AOP_TYPE (right) == AOP_CRY)
5794 genModbits (left, right, result, ic);
5798 /* if both are of size == 1 */
5799 if (AOP_SIZE (left) == 1 &&
5800 AOP_SIZE (right) == 1)
5802 genModOneByte (left, right, result, ic);
5806 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5807 /* use the ds390 ARITHMETIC accel UNIT */
5808 genModTwoByte (left, right, result, ic);
5812 /* should have been converted to function call */
5816 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818 freeAsmop (result, NULL, ic, TRUE);
5821 /*-----------------------------------------------------------------*/
5822 /* genIfxJump :- will create a jump depending on the ifx */
5823 /*-----------------------------------------------------------------*/
5825 genIfxJump (iCode * ic, char *jval)
5828 symbol *tlbl = newiTempLabel (NULL);
5831 D (emitcode (";", "genIfxJump"););
5833 /* if true label then we jump if condition
5837 jlbl = IC_TRUE (ic);
5838 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5839 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5843 /* false label is present */
5844 jlbl = IC_FALSE (ic);
5845 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5846 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5848 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5849 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5851 emitcode (inst, "!tlabel", tlbl->key + 100);
5852 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5853 emitcode ("", "!tlabeldef", tlbl->key + 100);
5855 /* mark the icode as generated */
5859 /*-----------------------------------------------------------------*/
5860 /* genCmp :- greater or less than comparison */
5861 /*-----------------------------------------------------------------*/
5863 genCmp (operand * left, operand * right,
5864 iCode * ic, iCode * ifx, int sign)
5866 int size, offset = 0;
5867 unsigned long lit = 0L;
5870 D (emitcode (";", "genCmp"););
5872 result = IC_RESULT (ic);
5874 /* if left & right are bit variables */
5875 if (AOP_TYPE (left) == AOP_CRY &&
5876 AOP_TYPE (right) == AOP_CRY)
5878 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5879 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5883 /* subtract right from left if at the
5884 end the carry flag is set then we know that
5885 left is greater than right */
5886 size = max (AOP_SIZE (left), AOP_SIZE (right));
5888 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5889 if ((size == 1) && !sign
5890 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5892 symbol *lbl = newiTempLabel (NULL);
5893 emitcode ("cjne", "%s,%s,!tlabel",
5894 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5895 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5897 emitcode ("", "!tlabeldef", lbl->key + 100);
5901 if (AOP_TYPE (right) == AOP_LIT)
5903 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5904 /* optimize if(x < 0) or if(x >= 0) */
5913 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5915 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5916 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918 aopOp (result, ic, FALSE, FALSE);
5920 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5922 freeAsmop (result, NULL, ic, TRUE);
5923 genIfxJump (ifx, "acc.7");
5928 emitcode ("rlc", "a");
5930 goto release_freedLR;
5938 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5939 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5940 // emitcode (";", "genCmp #2");
5941 if (sign && (size == 0))
5943 // emitcode (";", "genCmp #3");
5944 emitcode ("xrl", "a,#!constbyte",0x80);
5945 if (AOP_TYPE (right) == AOP_LIT)
5947 unsigned long lit = (unsigned long)
5948 floatFromVal (AOP (right)->aopu.aop_lit);
5949 // emitcode (";", "genCmp #3.1");
5950 emitcode ("subb", "a,#!constbyte",
5951 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5955 // emitcode (";", "genCmp #3.2");
5957 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5958 saveAccWarn = DEFAULT_ACC_WARNING;
5959 emitcode ("xrl", "b,#!constbyte",0x80);
5960 emitcode ("subb", "a,b");
5967 // emitcode (";", "genCmp #4");
5969 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5970 saveAccWarn = DEFAULT_ACC_WARNING;
5972 emitcode ("subb", "a,%s", s);
5979 /* Don't need the left & right operands any more; do need the result. */
5980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 aopOp (result, ic, FALSE, FALSE);
5987 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5993 /* if the result is used in the next
5994 ifx conditional branch then generate
5995 code a little differently */
5998 genIfxJump (ifx, "c");
6004 /* leave the result in acc */
6006 freeAsmop (result, NULL, ic, TRUE);
6009 /*-----------------------------------------------------------------*/
6010 /* genCmpGt :- greater than comparison */
6011 /*-----------------------------------------------------------------*/
6013 genCmpGt (iCode * ic, iCode * ifx)
6015 operand *left, *right;
6016 sym_link *letype, *retype;
6019 D (emitcode (";", "genCmpGt ");
6022 left = IC_LEFT (ic);
6023 right = IC_RIGHT (ic);
6025 letype = getSpec (operandType (left));
6026 retype = getSpec (operandType (right));
6027 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6029 /* assign the left & right amsops */
6032 genCmp (right, left, ic, ifx, sign);
6035 /*-----------------------------------------------------------------*/
6036 /* genCmpLt - less than comparisons */
6037 /*-----------------------------------------------------------------*/
6039 genCmpLt (iCode * ic, iCode * ifx)
6041 operand *left, *right;
6042 sym_link *letype, *retype;
6045 D (emitcode (";", "genCmpLt "););
6047 left = IC_LEFT (ic);
6048 right = IC_RIGHT (ic);
6050 letype = getSpec (operandType (left));
6051 retype = getSpec (operandType (right));
6052 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6054 /* assign the left & right amsops */
6057 genCmp (left, right, ic, ifx, sign);
6060 /*-----------------------------------------------------------------*/
6061 /* gencjneshort - compare and jump if not equal */
6062 /*-----------------------------------------------------------------*/
6064 gencjneshort (operand * left, operand * right, symbol * lbl)
6066 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6068 unsigned long lit = 0L;
6070 D (emitcode (";", "gencjneshort");
6073 /* if the left side is a literal or
6074 if the right is in a pointer register and left
6076 if ((AOP_TYPE (left) == AOP_LIT) ||
6077 (AOP_TYPE (left) == AOP_IMMD) ||
6078 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6085 if (AOP_TYPE (right) == AOP_LIT)
6086 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6088 if (opIsGptr (left) || opIsGptr (right))
6090 /* We are comparing a generic pointer to something.
6091 * Exclude the generic type byte from the comparison.
6094 D (emitcode (";", "cjneshort: generic ptr special case."););
6098 /* if the right side is a literal then anything goes */
6099 if (AOP_TYPE (right) == AOP_LIT &&
6100 AOP_TYPE (left) != AOP_DIR)
6104 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6105 emitcode ("cjne", "a,%s,!tlabel",
6106 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6112 /* if the right side is in a register or in direct space or
6113 if the left is a pointer register & right is not */
6114 else if (AOP_TYPE (right) == AOP_REG ||
6115 AOP_TYPE (right) == AOP_DIR ||
6116 AOP_TYPE (right) == AOP_LIT ||
6117 AOP_TYPE (right) == AOP_IMMD ||
6118 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6119 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6123 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6124 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6125 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6126 emitcode ("jnz", "!tlabel", lbl->key + 100);
6128 emitcode ("cjne", "a,%s,!tlabel",
6129 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6136 /* right is a pointer reg need both a & b */
6139 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6140 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6141 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6147 /*-----------------------------------------------------------------*/
6148 /* gencjne - compare and jump if not equal */
6149 /*-----------------------------------------------------------------*/
6151 gencjne (operand * left, operand * right, symbol * lbl)
6153 symbol *tlbl = newiTempLabel (NULL);
6155 D (emitcode (";", "gencjne");
6158 gencjneshort (left, right, lbl);
6160 emitcode ("mov", "a,%s", one);
6161 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6162 emitcode ("", "!tlabeldef", lbl->key + 100);
6163 emitcode ("clr", "a");
6164 emitcode ("", "!tlabeldef", tlbl->key + 100);
6167 /*-----------------------------------------------------------------*/
6168 /* genCmpEq - generates code for equal to */
6169 /*-----------------------------------------------------------------*/
6171 genCmpEq (iCode * ic, iCode * ifx)
6173 operand *left, *right, *result;
6175 D (emitcode (";", "genCmpEq ");
6179 AOP_SET_LOCALS (ic);
6181 /* if literal, literal on the right or
6182 if the right is in a pointer register and left
6184 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6185 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6187 operand *t = IC_RIGHT (ic);
6188 IC_RIGHT (ic) = IC_LEFT (ic);
6192 if (ifx && /* !AOP_SIZE(result) */
6193 OP_SYMBOL (result) &&
6194 OP_SYMBOL (result)->regType == REG_CND)
6197 /* if they are both bit variables */
6198 if (AOP_TYPE (left) == AOP_CRY &&
6199 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6201 if (AOP_TYPE (right) == AOP_LIT)
6203 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6206 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207 emitcode ("cpl", "c");
6211 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6215 emitcode ("clr", "c");
6217 /* AOP_TYPE(right) == AOP_CRY */
6221 symbol *lbl = newiTempLabel (NULL);
6222 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6223 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6224 emitcode ("cpl", "c");
6225 emitcode ("", "!tlabeldef", (lbl->key + 100));
6227 /* if true label then we jump if condition
6229 tlbl = newiTempLabel (NULL);
6232 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6233 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6237 emitcode ("jc", "!tlabel", tlbl->key + 100);
6238 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6240 emitcode ("", "!tlabeldef", tlbl->key + 100);
6244 tlbl = newiTempLabel (NULL);
6245 gencjneshort (left, right, tlbl);
6248 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6249 emitcode ("", "!tlabeldef", tlbl->key + 100);
6253 symbol *lbl = newiTempLabel (NULL);
6254 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6255 emitcode ("", "!tlabeldef", tlbl->key + 100);
6256 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6257 emitcode ("", "!tlabeldef", lbl->key + 100);
6260 /* mark the icode as generated */
6263 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6264 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268 /* if they are both bit variables */
6269 if (AOP_TYPE (left) == AOP_CRY &&
6270 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6272 if (AOP_TYPE (right) == AOP_LIT)
6274 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278 emitcode ("cpl", "c");
6282 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6286 emitcode ("clr", "c");
6288 /* AOP_TYPE(right) == AOP_CRY */
6292 symbol *lbl = newiTempLabel (NULL);
6293 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6294 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6295 emitcode ("cpl", "c");
6296 emitcode ("", "!tlabeldef", (lbl->key + 100));
6299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6302 aopOp (result, ic, TRUE, FALSE);
6305 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6312 genIfxJump (ifx, "c");
6315 /* if the result is used in an arithmetic operation
6316 then put the result in place */
6321 gencjne (left, right, newiTempLabel (NULL));
6323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 aopOp (result, ic, TRUE, FALSE);
6328 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6330 aopPut (AOP (result), "a", 0);
6335 genIfxJump (ifx, "a");
6338 /* if the result is used in an arithmetic operation
6339 then put the result in place */
6340 if (AOP_TYPE (result) != AOP_CRY)
6342 /* leave the result in acc */
6346 freeAsmop (result, NULL, ic, TRUE);
6349 /*-----------------------------------------------------------------*/
6350 /* ifxForOp - returns the icode containing the ifx for operand */
6351 /*-----------------------------------------------------------------*/
6353 ifxForOp (operand * op, iCode * ic)
6355 /* if true symbol then needs to be assigned */
6356 if (IS_TRUE_SYMOP (op))
6359 /* if this has register type condition and
6360 the next instruction is ifx with the same operand
6361 and live to of the operand is upto the ifx only then */
6363 ic->next->op == IFX &&
6364 IC_COND (ic->next)->key == op->key &&
6365 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6370 /*-----------------------------------------------------------------*/
6371 /* hasInc - operand is incremented before any other use */
6372 /*-----------------------------------------------------------------*/
6374 hasInc (operand *op, iCode *ic, int osize)
6376 sym_link *type = operandType(op);
6377 sym_link *retype = getSpec (type);
6378 iCode *lic = ic->next;
6381 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6382 if (!IS_SYMOP(op)) return NULL;
6384 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6385 if (IS_AGGREGATE(type->next)) return NULL;
6386 if (osize != (isize = getSize(type->next))) return NULL;
6389 /* if operand of the form op = op + <sizeof *op> */
6390 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6391 isOperandEqual(IC_RESULT(lic),op) &&
6392 isOperandLiteral(IC_RIGHT(lic)) &&
6393 operandLitValue(IC_RIGHT(lic)) == isize) {
6396 /* if the operand used or deffed */
6397 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6400 /* if GOTO or IFX */
6401 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6407 /*-----------------------------------------------------------------*/
6408 /* genAndOp - for && operation */
6409 /*-----------------------------------------------------------------*/
6411 genAndOp (iCode * ic)
6413 operand *left, *right, *result;
6416 D (emitcode (";", "genAndOp "););
6418 /* note here that && operations that are in an
6419 if statement are taken away by backPatchLabels
6420 only those used in arthmetic operations remain */
6422 AOP_SET_LOCALS (ic);
6424 /* if both are bit variables */
6425 if (AOP_TYPE (left) == AOP_CRY &&
6426 AOP_TYPE (right) == AOP_CRY)
6428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6429 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6430 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6433 aopOp (result,ic,FALSE, FALSE);
6438 tlbl = newiTempLabel (NULL);
6440 emitcode ("jz", "!tlabel", tlbl->key + 100);
6442 emitcode ("", "!tlabeldef", tlbl->key + 100);
6443 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6446 aopOp (result,ic,FALSE, FALSE);
6449 freeAsmop (result, NULL, ic, TRUE);
6453 /*-----------------------------------------------------------------*/
6454 /* genOrOp - for || operation */
6455 /*-----------------------------------------------------------------*/
6457 genOrOp (iCode * ic)
6459 operand *left, *right, *result;
6462 D (emitcode (";", "genOrOp "););
6464 /* note here that || operations that are in an
6465 if statement are taken away by backPatchLabels
6466 only those used in arthmetic operations remain */
6468 AOP_SET_LOCALS (ic);
6470 /* if both are bit variables */
6471 if (AOP_TYPE (left) == AOP_CRY &&
6472 AOP_TYPE (right) == AOP_CRY)
6474 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6475 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6479 aopOp (result,ic,FALSE, FALSE);
6485 tlbl = newiTempLabel (NULL);
6487 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6489 emitcode ("", "!tlabeldef", tlbl->key + 100);
6490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 aopOp (result,ic,FALSE, FALSE);
6498 freeAsmop (result, NULL, ic, TRUE);
6501 /*-----------------------------------------------------------------*/
6502 /* isLiteralBit - test if lit == 2^n */
6503 /*-----------------------------------------------------------------*/
6505 isLiteralBit (unsigned long lit)
6507 unsigned long pw[32] =
6508 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6509 0x100L, 0x200L, 0x400L, 0x800L,
6510 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6511 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6512 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6513 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6514 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6517 for (idx = 0; idx < 32; idx++)
6523 /*-----------------------------------------------------------------*/
6524 /* continueIfTrue - */
6525 /*-----------------------------------------------------------------*/
6527 continueIfTrue (iCode * ic)
6530 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6534 /*-----------------------------------------------------------------*/
6536 /*-----------------------------------------------------------------*/
6538 jumpIfTrue (iCode * ic)
6541 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6545 /*-----------------------------------------------------------------*/
6546 /* jmpTrueOrFalse - */
6547 /*-----------------------------------------------------------------*/
6549 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6551 // ugly but optimized by peephole
6554 symbol *nlbl = newiTempLabel (NULL);
6555 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6556 emitcode ("", "!tlabeldef", tlbl->key + 100);
6557 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6558 emitcode ("", "!tlabeldef", nlbl->key + 100);
6562 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6563 emitcode ("", "!tlabeldef", tlbl->key + 100);
6568 // Generate code to perform a bit-wise logic operation
6569 // on two operands in far space (assumed to already have been
6570 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6571 // in far space. This requires pushing the result on the stack
6572 // then popping it into the result.
6574 genFarFarLogicOp(iCode *ic, char *logicOp)
6576 int size, resultSize, compSize;
6580 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6581 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6582 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6584 _startLazyDPSEvaluation();
6585 for (size = compSize; (size--); offset++)
6587 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6588 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6589 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6591 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6592 emitcode ("push", "acc");
6594 _endLazyDPSEvaluation();
6596 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6598 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6600 resultSize = AOP_SIZE(IC_RESULT(ic));
6602 ADJUST_PUSHED_RESULT(compSize, resultSize);
6604 _startLazyDPSEvaluation();
6607 emitcode ("pop", "acc");
6608 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6610 _endLazyDPSEvaluation();
6611 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6615 /*-----------------------------------------------------------------*/
6616 /* genAnd - code for and */
6617 /*-----------------------------------------------------------------*/
6619 genAnd (iCode * ic, iCode * ifx)
6621 operand *left, *right, *result;
6622 int size, offset = 0;
6623 unsigned long lit = 0L;
6628 D (emitcode (";", "genAnd "););
6630 AOP_OP_3_NOFATAL (ic, pushResult);
6631 AOP_SET_LOCALS (ic);
6635 genFarFarLogicOp(ic, "anl");
6640 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6642 AOP_TYPE (left), AOP_TYPE (right));
6643 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6645 AOP_SIZE (left), AOP_SIZE (right));
6648 /* if left is a literal & right is not then exchange them */
6649 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6650 #ifdef LOGIC_OPS_BROKEN
6651 || AOP_NEEDSACC (left)
6655 operand *tmp = right;
6660 /* if result = right then exchange them */
6661 if (sameRegs (AOP (result), AOP (right)))
6663 operand *tmp = right;
6668 /* if right is bit then exchange them */
6669 if (AOP_TYPE (right) == AOP_CRY &&
6670 AOP_TYPE (left) != AOP_CRY)
6672 operand *tmp = right;
6676 if (AOP_TYPE (right) == AOP_LIT)
6677 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6679 size = AOP_SIZE (result);
6682 // result = bit & yy;
6683 if (AOP_TYPE (left) == AOP_CRY)
6685 // c = bit & literal;
6686 if (AOP_TYPE (right) == AOP_LIT)
6690 if (size && sameRegs (AOP (result), AOP (left)))
6693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6698 if (size && (AOP_TYPE (result) == AOP_CRY))
6700 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6703 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6708 emitcode ("clr", "c");
6713 if (AOP_TYPE (right) == AOP_CRY)
6716 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6717 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6722 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6724 emitcode ("rrc", "a");
6725 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6733 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6734 genIfxJump (ifx, "c");
6738 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6739 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6740 if ((AOP_TYPE (right) == AOP_LIT) &&
6741 (AOP_TYPE (result) == AOP_CRY) &&
6742 (AOP_TYPE (left) != AOP_CRY))
6744 int posbit = isLiteralBit (lit);
6749 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6752 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6758 SNPRINTF (buff, sizeof(buff),
6759 "acc.%d", posbit & 0x07);
6760 genIfxJump (ifx, buff);
6764 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6771 symbol *tlbl = newiTempLabel (NULL);
6772 int sizel = AOP_SIZE (left);
6774 emitcode ("setb", "c");
6777 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6779 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6781 if ((posbit = isLiteralBit (bytelit)) != 0)
6782 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6785 if (bytelit != 0x0FFL)
6786 emitcode ("anl", "a,%s",
6787 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6788 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6793 // bit = left & literal
6796 emitcode ("clr", "c");
6797 emitcode ("", "!tlabeldef", tlbl->key + 100);
6799 // if(left & literal)
6803 jmpTrueOrFalse (ifx, tlbl);
6805 emitcode ("", "!tlabeldef", tlbl->key + 100);
6813 /* if left is same as result */
6814 if (sameRegs (AOP (result), AOP (left)))
6816 for (; size--; offset++)
6818 if (AOP_TYPE (right) == AOP_LIT)
6820 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6822 else if (bytelit == 0)
6823 aopPut (AOP (result), zero, offset);
6824 else if (IS_AOP_PREG (result))
6826 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6827 emitcode ("anl", "a,%s",
6828 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6829 aopPut (AOP (result), "a", offset);
6832 emitcode ("anl", "%s,%s",
6833 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6834 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6838 if (AOP_TYPE (left) == AOP_ACC)
6839 emitcode ("anl", "a,%s",
6840 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6843 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6844 if (IS_AOP_PREG (result))
6846 emitcode ("anl", "a,%s",
6847 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6848 aopPut (AOP (result), "a", offset);
6851 emitcode ("anl", "%s,a",
6852 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6859 // left & result in different registers
6860 if (AOP_TYPE (result) == AOP_CRY)
6863 // if(size), result in bit
6864 // if(!size && ifx), conditional oper: if(left & right)
6865 symbol *tlbl = newiTempLabel (NULL);
6866 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6868 emitcode ("setb", "c");
6871 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6872 emitcode ("anl", "a,%s",
6873 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6875 if (AOP_TYPE(left)==AOP_ACC) {
6876 emitcode("mov", "b,a");
6877 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6878 emitcode("anl", "a,b");
6880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6881 emitcode ("anl", "a,%s",
6882 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6885 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6891 emitcode ("", "!tlabeldef", tlbl->key + 100);
6895 jmpTrueOrFalse (ifx, tlbl);
6897 emitcode ("", "!tlabeldef", tlbl->key + 100);
6901 for (; (size--); offset++)
6904 // result = left & right
6905 if (AOP_TYPE (right) == AOP_LIT)
6907 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6909 aopPut (AOP (result),
6910 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6914 else if (bytelit == 0)
6916 aopPut (AOP (result), zero, offset);
6919 D (emitcode (";", "better literal AND."););
6920 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6921 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6922 FALSE, FALSE, DP2_RESULT_REG));
6927 // faster than result <- left, anl result,right
6928 // and better if result is SFR
6929 if (AOP_TYPE (left) == AOP_ACC)
6931 emitcode ("anl", "a,%s",
6932 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6936 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6937 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6939 emitcode("mov", "b,a");
6943 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6944 emitcode ("anl", "a,%s", rOp);
6947 aopPut (AOP (result), "a", offset);
6953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6955 freeAsmop (result, NULL, ic, TRUE);
6959 /*-----------------------------------------------------------------*/
6960 /* genOr - code for or */
6961 /*-----------------------------------------------------------------*/
6963 genOr (iCode * ic, iCode * ifx)
6965 operand *left, *right, *result;
6966 int size, offset = 0;
6967 unsigned long lit = 0L;
6970 D (emitcode (";", "genOr "););
6972 AOP_OP_3_NOFATAL (ic, pushResult);
6973 AOP_SET_LOCALS (ic);
6977 genFarFarLogicOp(ic, "orl");
6983 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6985 AOP_TYPE (left), AOP_TYPE (right));
6986 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6988 AOP_SIZE (left), AOP_SIZE (right));
6991 /* if left is a literal & right is not then exchange them */
6992 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6993 #ifdef LOGIC_OPS_BROKEN
6994 || AOP_NEEDSACC (left) // I think this is a net loss now.
6998 operand *tmp = right;
7003 /* if result = right then exchange them */
7004 if (sameRegs (AOP (result), AOP (right)))
7006 operand *tmp = right;
7011 /* if right is bit then exchange them */
7012 if (AOP_TYPE (right) == AOP_CRY &&
7013 AOP_TYPE (left) != AOP_CRY)
7015 operand *tmp = right;
7019 if (AOP_TYPE (right) == AOP_LIT)
7020 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7022 size = AOP_SIZE (result);
7026 if (AOP_TYPE (left) == AOP_CRY)
7028 if (AOP_TYPE (right) == AOP_LIT)
7030 // c = bit & literal;
7033 // lit != 0 => result = 1
7034 if (AOP_TYPE (result) == AOP_CRY)
7037 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7039 continueIfTrue (ifx);
7042 emitcode ("setb", "c");
7046 // lit == 0 => result = left
7047 if (size && sameRegs (AOP (result), AOP (left)))
7049 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7054 if (AOP_TYPE (right) == AOP_CRY)
7057 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7058 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7063 symbol *tlbl = newiTempLabel (NULL);
7064 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7065 emitcode ("setb", "c");
7066 emitcode ("jb", "%s,!tlabel",
7067 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7069 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7070 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7072 jmpTrueOrFalse (ifx, tlbl);
7078 emitcode ("", "!tlabeldef", tlbl->key + 100);
7087 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7088 genIfxJump (ifx, "c");
7092 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7093 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7094 if ((AOP_TYPE (right) == AOP_LIT) &&
7095 (AOP_TYPE (result) == AOP_CRY) &&
7096 (AOP_TYPE (left) != AOP_CRY))
7102 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7104 continueIfTrue (ifx);
7109 // lit = 0, result = boolean(left)
7111 emitcode ("setb", "c");
7115 symbol *tlbl = newiTempLabel (NULL);
7116 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7118 emitcode ("", "!tlabeldef", tlbl->key + 100);
7122 genIfxJump (ifx, "a");
7130 /* if left is same as result */
7131 if (sameRegs (AOP (result), AOP (left)))
7133 for (; size--; offset++)
7135 if (AOP_TYPE (right) == AOP_LIT)
7137 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7143 if (IS_AOP_PREG (left))
7145 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7146 emitcode ("orl", "a,%s",
7147 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7148 aopPut (AOP (result), "a", offset);
7152 emitcode ("orl", "%s,%s",
7153 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7154 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7160 if (AOP_TYPE (left) == AOP_ACC)
7162 emitcode ("orl", "a,%s",
7163 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7167 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7168 if (IS_AOP_PREG (left))
7170 emitcode ("orl", "a,%s",
7171 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7172 aopPut (AOP (result), "a", offset);
7176 emitcode ("orl", "%s,a",
7177 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7185 // left & result in different registers
7186 if (AOP_TYPE (result) == AOP_CRY)
7189 // if(size), result in bit
7190 // if(!size && ifx), conditional oper: if(left | right)
7191 symbol *tlbl = newiTempLabel (NULL);
7192 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7194 emitcode ("setb", "c");
7197 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7198 emitcode ("orl", "a,%s",
7199 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7202 emitcode ("orl", "a,%s",
7203 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7205 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7211 emitcode ("", "!tlabeldef", tlbl->key + 100);
7215 jmpTrueOrFalse (ifx, tlbl);
7217 emitcode ("", "!tlabeldef", tlbl->key + 100);
7221 _startLazyDPSEvaluation();
7222 for (; (size--); offset++)
7225 // result = left & right
7226 if (AOP_TYPE (right) == AOP_LIT)
7228 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7230 aopPut (AOP (result),
7231 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7235 D (emitcode (";", "better literal OR."););
7236 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7237 emitcode ("orl", "a, %s",
7238 aopGet (AOP (right), offset,
7239 FALSE, FALSE, DP2_RESULT_REG));
7244 // faster than result <- left, anl result,right
7245 // and better if result is SFR
7246 if (AOP_TYPE (left) == AOP_ACC)
7248 emitcode ("orl", "a,%s",
7249 aopGet (AOP (right), offset,
7250 FALSE, FALSE, DP2_RESULT_REG));
7254 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7256 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7258 emitcode("mov", "b,a");
7262 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7263 emitcode ("orl", "a,%s", rOp);
7266 aopPut (AOP (result), "a", offset);
7268 _endLazyDPSEvaluation();
7273 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7274 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7275 freeAsmop (result, NULL, ic, TRUE);
7278 /*-----------------------------------------------------------------*/
7279 /* genXor - code for xclusive or */
7280 /*-----------------------------------------------------------------*/
7282 genXor (iCode * ic, iCode * ifx)
7284 operand *left, *right, *result;
7285 int size, offset = 0;
7286 unsigned long lit = 0L;
7289 D (emitcode (";", "genXor "););
7291 AOP_OP_3_NOFATAL (ic, pushResult);
7292 AOP_SET_LOCALS (ic);
7296 genFarFarLogicOp(ic, "xrl");
7301 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7303 AOP_TYPE (left), AOP_TYPE (right));
7304 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7306 AOP_SIZE (left), AOP_SIZE (right));
7309 /* if left is a literal & right is not ||
7310 if left needs acc & right does not */
7311 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7312 #ifdef LOGIC_OPS_BROKEN
7313 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7317 operand *tmp = right;
7322 /* if result = right then exchange them */
7323 if (sameRegs (AOP (result), AOP (right)))
7325 operand *tmp = right;
7330 /* if right is bit then exchange them */
7331 if (AOP_TYPE (right) == AOP_CRY &&
7332 AOP_TYPE (left) != AOP_CRY)
7334 operand *tmp = right;
7338 if (AOP_TYPE (right) == AOP_LIT)
7339 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7341 size = AOP_SIZE (result);
7345 if (AOP_TYPE (left) == AOP_CRY)
7347 if (AOP_TYPE (right) == AOP_LIT)
7349 // c = bit & literal;
7352 // lit>>1 != 0 => result = 1
7353 if (AOP_TYPE (result) == AOP_CRY)
7356 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7358 continueIfTrue (ifx);
7361 emitcode ("setb", "c");
7368 // lit == 0, result = left
7369 if (size && sameRegs (AOP (result), AOP (left)))
7371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7375 // lit == 1, result = not(left)
7376 if (size && sameRegs (AOP (result), AOP (left)))
7378 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7384 emitcode ("cpl", "c");
7393 symbol *tlbl = newiTempLabel (NULL);
7394 if (AOP_TYPE (right) == AOP_CRY)
7397 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7401 int sizer = AOP_SIZE (right);
7403 // if val>>1 != 0, result = 1
7404 emitcode ("setb", "c");
7407 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7409 // test the msb of the lsb
7410 emitcode ("anl", "a,#!constbyte",0xfe);
7411 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7415 emitcode ("rrc", "a");
7417 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7418 emitcode ("cpl", "c");
7419 emitcode ("", "!tlabeldef", (tlbl->key + 100));
7426 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7427 genIfxJump (ifx, "c");
7431 if (sameRegs (AOP (result), AOP (left)))
7433 /* if left is same as result */
7434 for (; size--; offset++)
7436 if (AOP_TYPE (right) == AOP_LIT)
7438 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7440 else if (IS_AOP_PREG (left))
7442 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7443 emitcode ("xrl", "a,%s",
7444 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7445 aopPut (AOP (result), "a", offset);
7448 emitcode ("xrl", "%s,%s",
7449 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7450 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7454 if (AOP_TYPE (left) == AOP_ACC)
7455 emitcode ("xrl", "a,%s",
7456 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7459 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7460 if (IS_AOP_PREG (left))
7462 emitcode ("xrl", "a,%s",
7463 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7464 aopPut (AOP (result), "a", offset);
7467 emitcode ("xrl", "%s,a",
7468 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7475 // left & result in different registers
7476 if (AOP_TYPE (result) == AOP_CRY)
7479 // if(size), result in bit
7480 // if(!size && ifx), conditional oper: if(left ^ right)
7481 symbol *tlbl = newiTempLabel (NULL);
7482 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7485 emitcode ("setb", "c");
7488 if ((AOP_TYPE (right) == AOP_LIT) &&
7489 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7491 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7495 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7496 emitcode ("xrl", "a,%s",
7497 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7499 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7500 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7502 emitcode("mov", "b,a");
7506 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7507 emitcode ("xrl", "a,%s", rOp);
7510 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7516 emitcode ("", "!tlabeldef", tlbl->key + 100);
7520 jmpTrueOrFalse (ifx, tlbl);
7524 for (; (size--); offset++)
7527 // result = left & right
7528 if (AOP_TYPE (right) == AOP_LIT)
7530 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7532 aopPut (AOP (result),
7533 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7537 D (emitcode (";", "better literal XOR."););
7538 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7539 emitcode ("xrl", "a, %s",
7540 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7544 // faster than result <- left, anl result,right
7545 // and better if result is SFR
7546 if (AOP_TYPE (left) == AOP_ACC)
7548 emitcode ("xrl", "a,%s",
7549 aopGet (AOP (right), offset,
7550 FALSE, FALSE, DP2_RESULT_REG));
7554 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7555 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7557 emitcode("mov", "b,a");
7561 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7562 emitcode ("xrl", "a,%s", rOp);
7565 aopPut (AOP (result), "a", offset);
7572 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7573 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7574 freeAsmop (result, NULL, ic, TRUE);
7577 /*-----------------------------------------------------------------*/
7578 /* genInline - write the inline code out */
7579 /*-----------------------------------------------------------------*/
7581 genInline (iCode * ic)
7583 char *buffer, *bp, *bp1;
7585 D (emitcode (";", "genInline "); );
7587 _G.inLine += (!options.asmpeep);
7589 buffer = Safe_strdup(IC_INLINE(ic));
7593 /* emit each line as a code */
7618 /* emitcode("",buffer); */
7619 _G.inLine -= (!options.asmpeep);
7622 /*-----------------------------------------------------------------*/
7623 /* genRRC - rotate right with carry */
7624 /*-----------------------------------------------------------------*/
7628 operand *left, *result;
7631 D (emitcode (";", "genRRC "););
7633 /* rotate right with carry */
7634 left = IC_LEFT (ic);
7635 result = IC_RESULT (ic);
7636 aopOp (left, ic, FALSE, FALSE);
7637 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7639 /* move it to the result */
7640 size = AOP_SIZE (result);
7644 _startLazyDPSEvaluation ();
7647 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7648 emitcode ("rrc", "a");
7649 if (AOP_SIZE (result) > 1)
7650 aopPut (AOP (result), "a", offset--);
7652 _endLazyDPSEvaluation ();
7654 /* now we need to put the carry into the
7655 highest order byte of the result */
7656 if (AOP_SIZE (result) > 1)
7658 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7660 emitcode ("mov", "acc.7,c");
7661 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7662 freeAsmop (left, NULL, ic, TRUE);
7663 freeAsmop (result, NULL, ic, TRUE);
7666 /*-----------------------------------------------------------------*/
7667 /* genRLC - generate code for rotate left with carry */
7668 /*-----------------------------------------------------------------*/
7672 operand *left, *result;
7676 D (emitcode (";", "genRLC "););
7678 /* rotate right with carry */
7679 left = IC_LEFT (ic);
7680 result = IC_RESULT (ic);
7681 aopOp (left, ic, FALSE, FALSE);
7682 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7684 /* move it to the result */
7685 size = AOP_SIZE (result);
7689 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7691 emitcode ("add", "a,acc");
7692 if (AOP_SIZE (result) > 1)
7694 aopPut (AOP (result), "a", offset++);
7697 _startLazyDPSEvaluation ();
7700 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7702 emitcode ("rlc", "a");
7703 if (AOP_SIZE (result) > 1)
7704 aopPut (AOP (result), "a", offset++);
7706 _endLazyDPSEvaluation ();
7708 /* now we need to put the carry into the
7709 highest order byte of the result */
7710 if (AOP_SIZE (result) > 1)
7712 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7715 emitcode ("mov", "acc.0,c");
7716 aopPut (AOP (result), "a", 0);
7717 freeAsmop (left, NULL, ic, TRUE);
7718 freeAsmop (result, NULL, ic, TRUE);
7721 /*-----------------------------------------------------------------*/
7722 /* genGetHbit - generates code get highest order bit */
7723 /*-----------------------------------------------------------------*/
7725 genGetHbit (iCode * ic)
7727 operand *left, *result;
7728 left = IC_LEFT (ic);
7729 result = IC_RESULT (ic);
7730 aopOp (left, ic, FALSE, FALSE);
7731 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7733 D (emitcode (";", "genGetHbit "););
7735 /* get the highest order byte into a */
7736 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7737 if (AOP_TYPE (result) == AOP_CRY)
7739 emitcode ("rlc", "a");
7744 emitcode ("rl", "a");
7745 emitcode ("anl", "a,#1");
7750 freeAsmop (left, NULL, ic, TRUE);
7751 freeAsmop (result, NULL, ic, TRUE);
7754 /*-----------------------------------------------------------------*/
7755 /* genSwap - generates code to swap nibbles or bytes */
7756 /*-----------------------------------------------------------------*/
7758 genSwap (iCode * ic)
7760 operand *left, *result;
7762 D(emitcode ("; genSwap",""));
7764 left = IC_LEFT (ic);
7765 result = IC_RESULT (ic);
7766 aopOp (left, ic, FALSE, FALSE);
7767 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7769 _startLazyDPSEvaluation ();
7770 switch (AOP_SIZE (left))
7772 case 1: /* swap nibbles in byte */
7773 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7774 emitcode ("swap", "a");
7775 aopPut (AOP (result), "a", 0);
7777 case 2: /* swap bytes in word */
7778 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7780 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7781 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7782 aopPut (AOP (result), "a", 1);
7784 else if (operandsEqu (left, result))
7787 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7788 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7790 emitcode ("mov", "b,a");
7794 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7795 aopPut (AOP (result), reg, 1);
7800 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7801 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7805 wassertl(FALSE, "unsupported SWAP operand size");
7807 _endLazyDPSEvaluation ();
7809 freeAsmop (left, NULL, ic, TRUE);
7810 freeAsmop (result, NULL, ic, TRUE);
7813 /*-----------------------------------------------------------------*/
7814 /* AccRol - rotate left accumulator by known count */
7815 /*-----------------------------------------------------------------*/
7817 AccRol (int shCount)
7819 shCount &= 0x0007; // shCount : 0..7
7826 emitcode ("rl", "a");
7829 emitcode ("rl", "a");
7830 emitcode ("rl", "a");
7833 emitcode ("swap", "a");
7834 emitcode ("rr", "a");
7837 emitcode ("swap", "a");
7840 emitcode ("swap", "a");
7841 emitcode ("rl", "a");
7844 emitcode ("rr", "a");
7845 emitcode ("rr", "a");
7848 emitcode ("rr", "a");
7853 /*-----------------------------------------------------------------*/
7854 /* AccLsh - left shift accumulator by known count */
7855 /*-----------------------------------------------------------------*/
7857 AccLsh (int shCount)
7862 emitcode ("add", "a,acc");
7863 else if (shCount == 2)
7865 emitcode ("add", "a,acc");
7866 emitcode ("add", "a,acc");
7870 /* rotate left accumulator */
7872 /* and kill the lower order bits */
7873 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7878 /*-----------------------------------------------------------------*/
7879 /* AccRsh - right shift accumulator by known count */
7880 /*-----------------------------------------------------------------*/
7882 AccRsh (int shCount)
7889 emitcode ("rrc", "a");
7893 /* rotate right accumulator */
7894 AccRol (8 - shCount);
7895 /* and kill the higher order bits */
7896 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7901 #ifdef BETTER_LITERAL_SHIFT
7902 /*-----------------------------------------------------------------*/
7903 /* AccSRsh - signed right shift accumulator by known count */
7904 /*-----------------------------------------------------------------*/
7906 AccSRsh (int shCount)
7913 emitcode ("mov", "c,acc.7");
7914 emitcode ("rrc", "a");
7916 else if (shCount == 2)
7918 emitcode ("mov", "c,acc.7");
7919 emitcode ("rrc", "a");
7920 emitcode ("mov", "c,acc.7");
7921 emitcode ("rrc", "a");
7925 tlbl = newiTempLabel (NULL);
7926 /* rotate right accumulator */
7927 AccRol (8 - shCount);
7928 /* and kill the higher order bits */
7929 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7930 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7931 emitcode ("orl", "a,#!constbyte",
7932 (unsigned char) ~SRMask[shCount]);
7933 emitcode ("", "!tlabeldef", tlbl->key + 100);
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* shiftR1Left2Result - shift right one byte from left to result */
7942 /*-----------------------------------------------------------------*/
7944 shiftR1Left2Result (operand * left, int offl,
7945 operand * result, int offr,
7946 int shCount, int sign)
7948 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7949 /* shift right accumulator */
7954 aopPut (AOP (result), "a", offr);
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* shiftL1Left2Result - shift left one byte from left to result */
7961 /*-----------------------------------------------------------------*/
7963 shiftL1Left2Result (operand * left, int offl,
7964 operand * result, int offr, int shCount)
7966 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7967 /* shift left accumulator */
7969 aopPut (AOP (result), "a", offr);
7973 #ifdef BETTER_LITERAL_SHIFT
7974 /*-----------------------------------------------------------------*/
7975 /* movLeft2Result - move byte from left to result */
7976 /*-----------------------------------------------------------------*/
7978 movLeft2Result (operand * left, int offl,
7979 operand * result, int offr, int sign)
7982 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7984 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7986 if (*l == '@' && (IS_AOP_PREG (result)))
7988 emitcode ("mov", "a,%s", l);
7989 aopPut (AOP (result), "a", offr);
7995 aopPut (AOP (result), l, offr);
7999 /* MSB sign in acc.7 ! */
8000 if (getDataSize (left) == offl + 1)
8002 emitcode ("mov", "a,%s", l);
8003 aopPut (AOP (result), "a", offr);
8011 #ifdef BETTER_LITERAL_SHIFT
8012 /*-----------------------------------------------------------------*/
8013 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8014 /*-----------------------------------------------------------------*/
8018 emitcode ("rrc", "a");
8019 emitcode ("xch", "a,%s", x);
8020 emitcode ("rrc", "a");
8021 emitcode ("xch", "a,%s", x);
8025 #ifdef BETTER_LITERAL_SHIFT
8027 /*-----------------------------------------------------------------*/
8028 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8029 /*-----------------------------------------------------------------*/
8033 emitcode ("xch", "a,%s", x);
8034 emitcode ("rlc", "a");
8035 emitcode ("xch", "a,%s", x);
8036 emitcode ("rlc", "a");
8040 #ifdef BETTER_LITERAL_SHIFT
8041 /*-----------------------------------------------------------------*/
8042 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8043 /*-----------------------------------------------------------------*/
8047 emitcode ("xch", "a,%s", x);
8048 emitcode ("add", "a,acc");
8049 emitcode ("xch", "a,%s", x);
8050 emitcode ("rlc", "a");
8054 #ifdef BETTER_LITERAL_SHIFT
8055 /*-----------------------------------------------------------------*/
8056 /* AccAXLsh - left shift a:x by known count (0..7) */
8057 /*-----------------------------------------------------------------*/
8059 AccAXLsh (char *x, int shCount)
8074 case 5: // AAAAABBB:CCCCCDDD
8076 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8078 emitcode ("anl", "a,#!constbyte",
8079 SLMask[shCount]); // BBB00000:CCCCCDDD
8081 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8083 AccRol (shCount); // DDDCCCCC:BBB00000
8085 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8087 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8089 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8091 emitcode ("anl", "a,#!constbyte",
8092 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8094 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8096 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8099 case 6: // AAAAAABB:CCCCCCDD
8100 emitcode ("anl", "a,#!constbyte",
8101 SRMask[shCount]); // 000000BB:CCCCCCDD
8102 emitcode ("mov", "c,acc.0"); // c = B
8103 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8105 AccAXRrl1 (x); // BCCCCCCD:D000000B
8106 AccAXRrl1 (x); // BBCCCCCC:DD000000
8108 emitcode("rrc","a");
8109 emitcode("xch","a,%s", x);
8110 emitcode("rrc","a");
8111 emitcode("mov","c,acc.0"); //<< get correct bit
8112 emitcode("xch","a,%s", x);
8114 emitcode("rrc","a");
8115 emitcode("xch","a,%s", x);
8116 emitcode("rrc","a");
8117 emitcode("xch","a,%s", x);
8120 case 7: // a:x <<= 7
8122 emitcode ("anl", "a,#!constbyte",
8123 SRMask[shCount]); // 0000000B:CCCCCCCD
8125 emitcode ("mov", "c,acc.0"); // c = B
8127 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8129 AccAXRrl1 (x); // BCCCCCCC:D0000000
8138 #ifdef BETTER_LITERAL_SHIFT
8140 /*-----------------------------------------------------------------*/
8141 /* AccAXRsh - right shift a:x known count (0..7) */
8142 /*-----------------------------------------------------------------*/
8144 AccAXRsh (char *x, int shCount)
8152 AccAXRrl1 (x); // 0->a:x
8157 AccAXRrl1 (x); // 0->a:x
8160 AccAXRrl1 (x); // 0->a:x
8165 case 5: // AAAAABBB:CCCCCDDD = a:x
8167 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8169 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8171 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8173 emitcode ("anl", "a,#!constbyte",
8174 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8176 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8178 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8180 emitcode ("anl", "a,#!constbyte",
8181 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8183 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8185 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8187 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8190 case 6: // AABBBBBB:CCDDDDDD
8192 emitcode ("mov", "c,acc.7");
8193 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8195 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8197 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8199 emitcode ("anl", "a,#!constbyte",
8200 SRMask[shCount]); // 000000AA:BBBBBBCC
8203 case 7: // ABBBBBBB:CDDDDDDD
8205 emitcode ("mov", "c,acc.7"); // c = A
8207 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8209 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8211 emitcode ("anl", "a,#!constbyte",
8212 SRMask[shCount]); // 0000000A:BBBBBBBC
8221 #ifdef BETTER_LITERAL_SHIFT
8222 /*-----------------------------------------------------------------*/
8223 /* AccAXRshS - right shift signed a:x known count (0..7) */
8224 /*-----------------------------------------------------------------*/
8226 AccAXRshS (char *x, int shCount)
8234 emitcode ("mov", "c,acc.7");
8235 AccAXRrl1 (x); // s->a:x
8239 emitcode ("mov", "c,acc.7");
8240 AccAXRrl1 (x); // s->a:x
8242 emitcode ("mov", "c,acc.7");
8243 AccAXRrl1 (x); // s->a:x
8248 case 5: // AAAAABBB:CCCCCDDD = a:x
8250 tlbl = newiTempLabel (NULL);
8251 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8253 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8255 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8257 emitcode ("anl", "a,#!constbyte",
8258 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8260 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8262 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8264 emitcode ("anl", "a,#!constbyte",
8265 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8267 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8269 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8271 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8273 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8274 emitcode ("orl", "a,#!constbyte",
8275 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8277 emitcode ("", "!tlabeldef", tlbl->key + 100);
8278 break; // SSSSAAAA:BBBCCCCC
8280 case 6: // AABBBBBB:CCDDDDDD
8282 tlbl = newiTempLabel (NULL);
8283 emitcode ("mov", "c,acc.7");
8284 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8286 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8288 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8290 emitcode ("anl", "a,#!constbyte",
8291 SRMask[shCount]); // 000000AA:BBBBBBCC
8293 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8294 emitcode ("orl", "a,#!constbyte",
8295 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8297 emitcode ("", "!tlabeldef", tlbl->key + 100);
8299 case 7: // ABBBBBBB:CDDDDDDD
8301 tlbl = newiTempLabel (NULL);
8302 emitcode ("mov", "c,acc.7"); // c = A
8304 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8306 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8308 emitcode ("anl", "a,#!constbyte",
8309 SRMask[shCount]); // 0000000A:BBBBBBBC
8311 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8312 emitcode ("orl", "a,#!constbyte",
8313 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8315 emitcode ("", "!tlabeldef", tlbl->key + 100);
8323 #ifdef BETTER_LITERAL_SHIFT
8325 _loadLeftIntoAx(char **lsb,
8331 // Get the initial value from left into a pair of registers.
8332 // MSB must be in A, LSB can be any register.
8334 // If the result is held in registers, it is an optimization
8335 // if the LSB can be held in the register which will hold the,
8336 // result LSB since this saves us from having to copy it into
8337 // the result following AccAXLsh.
8339 // If the result is addressed indirectly, this is not a gain.
8340 if (AOP_NEEDSACC(result))
8344 _startLazyDPSEvaluation();
8345 if (AOP_TYPE(left) == AOP_DPTR2)
8348 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8349 // get LSB in DP2_RESULT_REG.
8350 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8351 assert(!strcmp(leftByte, DP2_RESULT_REG));
8355 // get LSB into DP2_RESULT_REG
8356 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8357 if (strcmp(leftByte, DP2_RESULT_REG))
8360 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8363 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8364 assert(strcmp(leftByte, DP2_RESULT_REG));
8367 _endLazyDPSEvaluation();
8368 *lsb = DP2_RESULT_REG;
8372 if (sameRegs (AOP (result), AOP (left)) &&
8373 ((offl + MSB16) == offr))
8375 /* don't crash result[offr] */
8376 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8377 emitcode ("xch", "a,%s",
8378 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8382 movLeft2Result (left, offl, result, offr, 0);
8383 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8385 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8386 assert(strcmp(*lsb,"a"));
8391 _storeAxResults(char *lsb,
8395 _startLazyDPSEvaluation();
8396 if (AOP_NEEDSACC(result))
8398 /* We have to explicitly update the result LSB.
8400 emitcode("xch","a,%s", lsb);
8401 aopPut(AOP(result), "a", offr);
8402 emitcode("mov","a,%s", lsb);
8404 if (getDataSize (result) > 1)
8406 aopPut (AOP (result), "a", offr + MSB16);
8408 _endLazyDPSEvaluation();
8411 /*-----------------------------------------------------------------*/
8412 /* shiftL2Left2Result - shift left two bytes from left to result */
8413 /*-----------------------------------------------------------------*/
8415 shiftL2Left2Result (operand * left, int offl,
8416 operand * result, int offr, int shCount)
8420 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8422 AccAXLsh (lsb, shCount);
8424 _storeAxResults(lsb, result, offr);
8428 #ifdef BETTER_LITERAL_SHIFT
8429 /*-----------------------------------------------------------------*/
8430 /* shiftR2Left2Result - shift right two bytes from left to result */
8431 /*-----------------------------------------------------------------*/
8433 shiftR2Left2Result (operand * left, int offl,
8434 operand * result, int offr,
8435 int shCount, int sign)
8439 _loadLeftIntoAx(&lsb, left, result, offl, offr);
8441 /* a:x >> shCount (x = lsb(result)) */
8444 AccAXRshS(lsb, shCount);
8448 AccAXRsh(lsb, shCount);
8451 _storeAxResults(lsb, result, offr);
8455 /*-----------------------------------------------------------------*/
8456 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8457 /*-----------------------------------------------------------------*/
8459 shiftLLeftOrResult (operand * left, int offl,
8460 operand * result, int offr, int shCount)
8462 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8463 /* shift left accumulator */
8465 /* or with result */
8466 emitcode ("orl", "a,%s",
8467 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8468 /* back to result */
8469 aopPut (AOP (result), "a", offr);
8474 /*-----------------------------------------------------------------*/
8475 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8476 /*-----------------------------------------------------------------*/
8478 shiftRLeftOrResult (operand * left, int offl,
8479 operand * result, int offr, int shCount)
8481 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8482 /* shift right accumulator */
8484 /* or with result */
8485 emitcode ("orl", "a,%s",
8486 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8487 /* back to result */
8488 aopPut (AOP (result), "a", offr);
8492 #ifdef BETTER_LITERAL_SHIFT
8493 /*-----------------------------------------------------------------*/
8494 /* genlshOne - left shift a one byte quantity by known count */
8495 /*-----------------------------------------------------------------*/
8497 genlshOne (operand * result, operand * left, int shCount)
8499 D (emitcode (";", "genlshOne "););
8500 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8504 #ifdef BETTER_LITERAL_SHIFT
8505 /*-----------------------------------------------------------------*/
8506 /* genlshTwo - left shift two bytes by known amount != 0 */
8507 /*-----------------------------------------------------------------*/
8509 genlshTwo (operand * result, operand * left, int shCount)
8513 D (emitcode (";", "genlshTwo "););
8515 size = getDataSize (result);
8517 /* if shCount >= 8 */
8522 _startLazyDPSEvaluation();
8528 _endLazyDPSEvaluation();
8529 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8530 aopPut (AOP (result), zero, LSB);
8534 movLeft2Result (left, LSB, result, MSB16, 0);
8535 aopPut (AOP (result), zero, LSB);
8536 _endLazyDPSEvaluation();
8541 aopPut (AOP (result), zero, LSB);
8542 _endLazyDPSEvaluation();
8546 /* 1 <= shCount <= 7 */
8551 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8555 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8563 /*-----------------------------------------------------------------*/
8564 /* shiftLLong - shift left one long from left to result */
8565 /* offl = LSB or MSB16 */
8566 /*-----------------------------------------------------------------*/
8568 shiftLLong (operand * left, operand * result, int offr)
8571 int size = AOP_SIZE (result);
8573 if (size >= LSB + offr)
8575 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8577 emitcode ("add", "a,acc");
8578 if (sameRegs (AOP (left), AOP (result)) &&
8579 size >= MSB16 + offr && offr != LSB)
8580 emitcode ("xch", "a,%s",
8581 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8583 aopPut (AOP (result), "a", LSB + offr);
8586 if (size >= MSB16 + offr)
8588 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8590 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8592 emitcode ("rlc", "a");
8593 if (sameRegs (AOP (left), AOP (result)) &&
8594 size >= MSB24 + offr && offr != LSB)
8595 emitcode ("xch", "a,%s",
8596 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8598 aopPut (AOP (result), "a", MSB16 + offr);
8601 if (size >= MSB24 + offr)
8603 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8605 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8607 emitcode ("rlc", "a");
8608 if (sameRegs (AOP (left), AOP (result)) &&
8609 size >= MSB32 + offr && offr != LSB)
8610 emitcode ("xch", "a,%s",
8611 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8613 aopPut (AOP (result), "a", MSB24 + offr);
8616 if (size > MSB32 + offr)
8618 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8620 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8622 emitcode ("rlc", "a");
8623 aopPut (AOP (result), "a", MSB32 + offr);
8626 aopPut (AOP (result), zero, LSB);
8632 /*-----------------------------------------------------------------*/
8633 /* genlshFour - shift four byte by a known amount != 0 */
8634 /*-----------------------------------------------------------------*/
8636 genlshFour (operand * result, operand * left, int shCount)
8640 D (emitcode (";", "genlshFour ");
8643 size = AOP_SIZE (result);
8645 /* if shifting more that 3 bytes */
8650 /* lowest order of left goes to the highest
8651 order of the destination */
8652 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8654 movLeft2Result (left, LSB, result, MSB32, 0);
8655 aopPut (AOP (result), zero, LSB);
8656 aopPut (AOP (result), zero, MSB16);
8657 aopPut (AOP (result), zero, MSB24);
8661 /* more than two bytes */
8662 else if (shCount >= 16)
8664 /* lower order two bytes goes to higher order two bytes */
8666 /* if some more remaining */
8668 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8671 movLeft2Result (left, MSB16, result, MSB32, 0);
8672 movLeft2Result (left, LSB, result, MSB24, 0);
8674 aopPut (AOP (result), zero, MSB16);
8675 aopPut (AOP (result), zero, LSB);
8679 /* if more than 1 byte */
8680 else if (shCount >= 8)
8682 /* lower order three bytes goes to higher order three bytes */
8687 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8689 movLeft2Result (left, LSB, result, MSB16, 0);
8695 movLeft2Result (left, MSB24, result, MSB32, 0);
8696 movLeft2Result (left, MSB16, result, MSB24, 0);
8697 movLeft2Result (left, LSB, result, MSB16, 0);
8698 aopPut (AOP (result), zero, LSB);
8700 else if (shCount == 1)
8701 shiftLLong (left, result, MSB16);
8704 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8705 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8706 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8707 aopPut (AOP (result), zero, LSB);
8712 /* 1 <= shCount <= 7 */
8713 else if (shCount <= 2)
8715 shiftLLong (left, result, LSB);
8717 shiftLLong (result, result, LSB);
8719 /* 3 <= shCount <= 7, optimize */
8722 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8723 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8724 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8729 #ifdef BETTER_LITERAL_SHIFT
8730 /*-----------------------------------------------------------------*/
8731 /* genLeftShiftLiteral - left shifting by known count */
8732 /*-----------------------------------------------------------------*/
8734 genLeftShiftLiteral (operand * left,
8739 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8742 size = getSize (operandType (result));
8744 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8746 /* We only handle certain easy cases so far. */
8748 && (shCount < (size * 8))
8752 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8756 freeAsmop (right, NULL, ic, TRUE);
8758 aopOp(left, ic, FALSE, FALSE);
8759 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8762 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8764 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8765 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8767 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8770 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8772 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8773 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8775 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8781 emitcode ("; shift left ", "result %d, left %d", size,
8785 /* I suppose that the left size >= result size */
8788 _startLazyDPSEvaluation();
8791 movLeft2Result (left, size, result, size, 0);
8793 _endLazyDPSEvaluation();
8795 else if (shCount >= (size * 8))
8797 _startLazyDPSEvaluation();
8800 aopPut (AOP (result), zero, size);
8802 _endLazyDPSEvaluation();
8809 genlshOne (result, left, shCount);
8813 genlshTwo (result, left, shCount);
8817 genlshFour (result, left, shCount);
8821 fprintf(stderr, "*** ack! mystery literal shift!\n");
8825 freeAsmop (left, NULL, ic, TRUE);
8826 freeAsmop (result, NULL, ic, TRUE);
8831 /*-----------------------------------------------------------------*/
8832 /* genLeftShift - generates code for left shifting */
8833 /*-----------------------------------------------------------------*/
8835 genLeftShift (iCode * ic)
8837 operand *left, *right, *result;
8840 symbol *tlbl, *tlbl1;
8842 D (emitcode (";", "genLeftShift "););
8844 right = IC_RIGHT (ic);
8845 left = IC_LEFT (ic);
8846 result = IC_RESULT (ic);
8848 aopOp (right, ic, FALSE, FALSE);
8851 #ifdef BETTER_LITERAL_SHIFT
8852 /* if the shift count is known then do it
8853 as efficiently as possible */
8854 if (AOP_TYPE (right) == AOP_LIT)
8856 if (genLeftShiftLiteral (left, right, result, ic))
8863 /* shift count is unknown then we have to form
8864 a loop get the loop count in B : Note: we take
8865 only the lower order byte since shifting
8866 more that 32 bits make no sense anyway, ( the
8867 largest size of an object can be only 32 bits ) */
8869 if (AOP_TYPE (right) == AOP_LIT)
8871 /* Really should be handled by genLeftShiftLiteral,
8872 * but since I'm too lazy to fix that today, at least we can make
8873 * some small improvement.
8875 emitcode("mov", "b,#!constbyte",
8876 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8880 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8881 emitcode ("inc", "b");
8883 freeAsmop (right, NULL, ic, TRUE);
8884 aopOp (left, ic, FALSE, FALSE);
8885 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8887 /* now move the left to the result if they are not the
8889 if (!sameRegs (AOP (left), AOP (result)) &&
8890 AOP_SIZE (result) > 1)
8893 size = AOP_SIZE (result);
8895 _startLazyDPSEvaluation ();
8898 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8899 if (*l == '@' && (IS_AOP_PREG (result)))
8902 emitcode ("mov", "a,%s", l);
8903 aopPut (AOP (result), "a", offset);
8906 aopPut (AOP (result), l, offset);
8909 _endLazyDPSEvaluation ();
8912 tlbl = newiTempLabel (NULL);
8913 size = AOP_SIZE (result);
8915 tlbl1 = newiTempLabel (NULL);
8917 /* if it is only one byte then */
8920 symbol *tlbl1 = newiTempLabel (NULL);
8922 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8923 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8924 emitcode ("", "!tlabeldef", tlbl->key + 100);
8925 emitcode ("add", "a,acc");
8926 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8927 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8928 aopPut (AOP (result), "a", 0);
8932 reAdjustPreg (AOP (result));
8934 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8935 emitcode ("", "!tlabeldef", tlbl->key + 100);
8936 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8937 emitcode ("add", "a,acc");
8938 aopPut (AOP (result), "a", offset++);
8939 _startLazyDPSEvaluation ();
8942 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8943 emitcode ("rlc", "a");
8944 aopPut (AOP (result), "a", offset++);
8946 _endLazyDPSEvaluation ();
8947 reAdjustPreg (AOP (result));
8949 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8950 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8952 freeAsmop (left, NULL, ic, TRUE);
8953 freeAsmop (result, NULL, ic, TRUE);
8956 #ifdef BETTER_LITERAL_SHIFT
8957 /*-----------------------------------------------------------------*/
8958 /* genrshOne - right shift a one byte quantity by known count */
8959 /*-----------------------------------------------------------------*/
8961 genrshOne (operand * result, operand * left,
8962 int shCount, int sign)
8964 D (emitcode (";", "genrshOne"););
8965 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8969 #ifdef BETTER_LITERAL_SHIFT
8970 /*-----------------------------------------------------------------*/
8971 /* genrshTwo - right shift two bytes by known amount != 0 */
8972 /*-----------------------------------------------------------------*/
8974 genrshTwo (operand * result, operand * left,
8975 int shCount, int sign)
8977 D (emitcode (";", "genrshTwo"););
8979 /* if shCount >= 8 */
8983 _startLazyDPSEvaluation();
8986 shiftR1Left2Result (left, MSB16, result, LSB,
8991 movLeft2Result (left, MSB16, result, LSB, sign);
8993 addSign (result, MSB16, sign);
8994 _endLazyDPSEvaluation();
8997 /* 1 <= shCount <= 7 */
9000 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9005 /*-----------------------------------------------------------------*/
9006 /* shiftRLong - shift right one long from left to result */
9007 /* offl = LSB or MSB16 */
9008 /*-----------------------------------------------------------------*/
9010 shiftRLong (operand * left, int offl,
9011 operand * result, int sign)
9013 int isSameRegs=sameRegs(AOP(left),AOP(result));
9015 if (isSameRegs && offl>1) {
9016 // we are in big trouble, but this shouldn't happen
9017 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9020 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9025 emitcode ("rlc", "a");
9026 emitcode ("subb", "a,acc");
9027 emitcode ("xch", "a,%s",
9028 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9030 aopPut (AOP(result), zero, MSB32);
9035 emitcode ("clr", "c");
9037 emitcode ("mov", "c,acc.7");
9040 emitcode ("rrc", "a");
9042 if (isSameRegs && offl==MSB16) {
9044 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9046 aopPut (AOP (result), "a", MSB32);
9047 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9050 emitcode ("rrc", "a");
9051 if (isSameRegs && offl==1) {
9052 emitcode ("xch", "a,%s",
9053 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9055 aopPut (AOP (result), "a", MSB24);
9056 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9058 emitcode ("rrc", "a");
9059 aopPut (AOP (result), "a", MSB16 - offl);
9063 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9064 emitcode ("rrc", "a");
9065 aopPut (AOP (result), "a", LSB);
9069 /*-----------------------------------------------------------------*/
9070 /* genrshFour - shift four byte by a known amount != 0 */
9071 /*-----------------------------------------------------------------*/
9073 genrshFour (operand * result, operand * left,
9074 int shCount, int sign)
9076 D (emitcode (";", "genrshFour"););
9078 /* if shifting more that 3 bytes */
9082 _startLazyDPSEvaluation();
9084 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9086 movLeft2Result (left, MSB32, result, LSB, sign);
9087 addSign (result, MSB16, sign);
9088 _endLazyDPSEvaluation();
9090 else if (shCount >= 16)
9093 _startLazyDPSEvaluation();
9095 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9098 movLeft2Result (left, MSB24, result, LSB, 0);
9099 movLeft2Result (left, MSB32, result, MSB16, sign);
9101 addSign (result, MSB24, sign);
9102 _endLazyDPSEvaluation();
9104 else if (shCount >= 8)
9107 _startLazyDPSEvaluation();
9110 shiftRLong (left, MSB16, result, sign);
9112 else if (shCount == 0)
9114 movLeft2Result (left, MSB16, result, LSB, 0);
9115 movLeft2Result (left, MSB24, result, MSB16, 0);
9116 movLeft2Result (left, MSB32, result, MSB24, sign);
9117 addSign (result, MSB32, sign);
9121 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9122 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9123 /* the last shift is signed */
9124 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9125 addSign (result, MSB32, sign);
9127 _endLazyDPSEvaluation();
9131 /* 1 <= shCount <= 7 */
9134 shiftRLong (left, LSB, result, sign);
9136 shiftRLong (result, LSB, result, sign);
9140 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9141 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9142 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9147 #ifdef BETTER_LITERAL_SHIFT
9148 /*-----------------------------------------------------------------*/
9149 /* genRightShiftLiteral - right shifting by known count */
9150 /*-----------------------------------------------------------------*/
9152 genRightShiftLiteral (operand * left,
9158 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9161 size = getSize (operandType (result));
9163 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9165 /* We only handle certain easy cases so far. */
9167 && (shCount < (size * 8))
9172 D(emitcode (";", "genRightShiftLiteral wimping out"););
9176 freeAsmop (right, NULL, ic, TRUE);
9178 aopOp (left, ic, FALSE, FALSE);
9179 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9182 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9186 /* test the LEFT size !!! */
9188 /* I suppose that the left size >= result size */
9191 size = getDataSize (result);
9192 _startLazyDPSEvaluation();
9195 movLeft2Result (left, size, result, size, 0);
9197 _endLazyDPSEvaluation();
9199 else if (shCount >= (size * 8))
9203 /* get sign in acc.7 */
9204 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9206 addSign (result, LSB, sign);
9213 genrshOne (result, left, shCount, sign);
9217 genrshTwo (result, left, shCount, sign);
9221 genrshFour (result, left, shCount, sign);
9228 freeAsmop (left, NULL, ic, TRUE);
9229 freeAsmop (result, NULL, ic, TRUE);
9235 /*-----------------------------------------------------------------*/
9236 /* genSignedRightShift - right shift of signed number */
9237 /*-----------------------------------------------------------------*/
9239 genSignedRightShift (iCode * ic)
9241 operand *right, *left, *result;
9244 symbol *tlbl, *tlbl1;
9246 D (emitcode (";", "genSignedRightShift "););
9248 /* we do it the hard way put the shift count in b
9249 and loop thru preserving the sign */
9251 right = IC_RIGHT (ic);
9252 left = IC_LEFT (ic);
9253 result = IC_RESULT (ic);
9255 aopOp (right, ic, FALSE, FALSE);
9257 #ifdef BETTER_LITERAL_SHIFT
9258 if (AOP_TYPE (right) == AOP_LIT)
9260 if (genRightShiftLiteral (left, right, result, ic, 1))
9266 /* shift count is unknown then we have to form
9267 a loop get the loop count in B : Note: we take
9268 only the lower order byte since shifting
9269 more that 32 bits make no sense anyway, ( the
9270 largest size of an object can be only 32 bits ) */
9272 if (AOP_TYPE (right) == AOP_LIT)
9274 /* Really should be handled by genRightShiftLiteral,
9275 * but since I'm too lazy to fix that today, at least we can make
9276 * some small improvement.
9278 emitcode("mov", "b,#!constbyte",
9279 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9283 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9284 emitcode ("inc", "b");
9286 freeAsmop (right, NULL, ic, TRUE);
9287 aopOp (left, ic, FALSE, FALSE);
9288 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9290 /* now move the left to the result if they are not the
9292 if (!sameRegs (AOP (left), AOP (result)) &&
9293 AOP_SIZE (result) > 1)
9296 size = AOP_SIZE (result);
9298 _startLazyDPSEvaluation ();
9301 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9302 if (*l == '@' && IS_AOP_PREG (result))
9305 emitcode ("mov", "a,%s", l);
9306 aopPut (AOP (result), "a", offset);
9309 aopPut (AOP (result), l, offset);
9312 _endLazyDPSEvaluation ();
9315 /* mov the highest order bit to OVR */
9316 tlbl = newiTempLabel (NULL);
9317 tlbl1 = newiTempLabel (NULL);
9319 size = AOP_SIZE (result);
9321 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9322 emitcode ("rlc", "a");
9323 emitcode ("mov", "ov,c");
9324 /* if it is only one byte then */
9327 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9328 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9329 emitcode ("", "!tlabeldef", tlbl->key + 100);
9330 emitcode ("mov", "c,ov");
9331 emitcode ("rrc", "a");
9332 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9333 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9334 aopPut (AOP (result), "a", 0);
9338 reAdjustPreg (AOP (result));
9339 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9340 emitcode ("", "!tlabeldef", tlbl->key + 100);
9341 emitcode ("mov", "c,ov");
9342 _startLazyDPSEvaluation ();
9345 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9346 emitcode ("rrc", "a");
9347 aopPut (AOP (result), "a", offset--);
9349 _endLazyDPSEvaluation ();
9350 reAdjustPreg (AOP (result));
9351 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9352 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9355 freeAsmop (left, NULL, ic, TRUE);
9356 freeAsmop (result, NULL, ic, TRUE);
9359 /*-----------------------------------------------------------------*/
9360 /* genRightShift - generate code for right shifting */
9361 /*-----------------------------------------------------------------*/
9363 genRightShift (iCode * ic)
9365 operand *right, *left, *result;
9369 symbol *tlbl, *tlbl1;
9371 D (emitcode (";", "genRightShift "););
9373 /* if signed then we do it the hard way preserve the
9374 sign bit moving it inwards */
9375 letype = getSpec (operandType (IC_LEFT (ic)));
9377 if (!SPEC_USIGN (letype))
9379 genSignedRightShift (ic);
9383 /* signed & unsigned types are treated the same : i.e. the
9384 signed is NOT propagated inwards : quoting from the
9385 ANSI - standard : "for E1 >> E2, is equivalent to division
9386 by 2**E2 if unsigned or if it has a non-negative value,
9387 otherwise the result is implementation defined ", MY definition
9388 is that the sign does not get propagated */
9390 right = IC_RIGHT (ic);
9391 left = IC_LEFT (ic);
9392 result = IC_RESULT (ic);
9394 aopOp (right, ic, FALSE, FALSE);
9396 #ifdef BETTER_LITERAL_SHIFT
9397 /* if the shift count is known then do it
9398 as efficiently as possible */
9399 if (AOP_TYPE (right) == AOP_LIT)
9401 if (genRightShiftLiteral (left, right, result, ic, 0))
9408 /* shift count is unknown then we have to form
9409 a loop get the loop count in B : Note: we take
9410 only the lower order byte since shifting
9411 more that 32 bits make no sense anyway, ( the
9412 largest size of an object can be only 32 bits ) */
9414 if (AOP_TYPE (right) == AOP_LIT)
9416 /* Really should be handled by genRightShiftLiteral,
9417 * but since I'm too lazy to fix that today, at least we can make
9418 * some small improvement.
9420 emitcode("mov", "b,#!constbyte",
9421 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9425 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9426 emitcode ("inc", "b");
9428 freeAsmop (right, NULL, ic, TRUE);
9429 aopOp (left, ic, FALSE, FALSE);
9430 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9432 /* now move the left to the result if they are not the
9434 if (!sameRegs (AOP (left), AOP (result)) &&
9435 AOP_SIZE (result) > 1)
9438 size = AOP_SIZE (result);
9440 _startLazyDPSEvaluation ();
9443 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9444 if (*l == '@' && IS_AOP_PREG (result))
9447 emitcode ("mov", "a,%s", l);
9448 aopPut (AOP (result), "a", offset);
9451 aopPut (AOP (result), l, offset);
9454 _endLazyDPSEvaluation ();
9457 tlbl = newiTempLabel (NULL);
9458 tlbl1 = newiTempLabel (NULL);
9459 size = AOP_SIZE (result);
9462 /* if it is only one byte then */
9465 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9466 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9467 emitcode ("", "!tlabeldef", tlbl->key + 100);
9469 emitcode ("rrc", "a");
9470 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9471 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9472 aopPut (AOP (result), "a", 0);
9476 reAdjustPreg (AOP (result));
9477 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9478 emitcode ("", "!tlabeldef", tlbl->key + 100);
9480 _startLazyDPSEvaluation ();
9483 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9484 emitcode ("rrc", "a");
9485 aopPut (AOP (result), "a", offset--);
9487 _endLazyDPSEvaluation ();
9488 reAdjustPreg (AOP (result));
9490 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9491 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9494 freeAsmop (left, NULL, ic, TRUE);
9495 freeAsmop (result, NULL, ic, TRUE);
9499 /*-----------------------------------------------------------------*/
9500 /* emitPtrByteGet - emits code to get a byte into A through a */
9501 /* pointer register (R0, R1, or DPTR). The */
9502 /* original value of A can be preserved in B. */
9503 /*-----------------------------------------------------------------*/
9505 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9512 emitcode ("mov", "b,a");
9513 emitcode ("mov", "a,@%s", rname);
9518 emitcode ("mov", "b,a");
9519 emitcode ("movx", "a,@%s", rname);
9524 emitcode ("mov", "b,a");
9525 emitcode ("movx", "a,@dptr");
9530 emitcode ("mov", "b,a");
9531 emitcode ("clr", "a");
9532 emitcode ("movc", "a,@a+dptr");
9538 emitcode ("push", "b");
9539 emitcode ("push", "acc");
9541 emitcode ("lcall", "__gptrget");
9543 emitcode ("pop", "b");
9548 /*-----------------------------------------------------------------*/
9549 /* emitPtrByteSet - emits code to set a byte from src through a */
9550 /* pointer register (R0, R1, or DPTR). */
9551 /*-----------------------------------------------------------------*/
9553 emitPtrByteSet (char *rname, int p_type, char *src)
9562 emitcode ("mov", "@%s,a", rname);
9565 emitcode ("mov", "@%s,%s", rname, src);
9570 emitcode ("movx", "@%s,a", rname);
9575 emitcode ("movx", "@dptr,a");
9580 emitcode ("lcall", "__gptrput");
9585 /*-----------------------------------------------------------------*/
9586 /* genUnpackBits - generates code for unpacking bits */
9587 /*-----------------------------------------------------------------*/
9589 genUnpackBits (operand * result, char *rname, int ptype)
9591 int offset = 0; /* result byte offset */
9592 int rsize; /* result size */
9593 int rlen = 0; /* remaining bitfield length */
9594 sym_link *etype; /* bitfield type information */
9595 int blen; /* bitfield length */
9596 int bstr; /* bitfield starting bit within byte */
9598 D(emitcode ("; genUnpackBits",""));
9600 etype = getSpec (operandType (result));
9601 rsize = getSize (operandType (result));
9602 blen = SPEC_BLEN (etype);
9603 bstr = SPEC_BSTR (etype);
9605 /* If the bitfield length is less than a byte */
9608 emitPtrByteGet (rname, ptype, FALSE);
9610 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9611 aopPut (AOP (result), "a", offset++);
9615 /* Bit field did not fit in a byte. Copy all
9616 but the partial byte at the end. */
9617 for (rlen=blen;rlen>=8;rlen-=8)
9619 emitPtrByteGet (rname, ptype, FALSE);
9620 aopPut (AOP (result), "a", offset++);
9622 emitcode ("inc", "%s", rname);
9625 /* Handle the partial byte at the end */
9628 emitPtrByteGet (rname, ptype, FALSE);
9629 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9630 aopPut (AOP (result), "a", offset++);
9638 aopPut (AOP (result), zero, offset++);
9643 /*-----------------------------------------------------------------*/
9644 /* genDataPointerGet - generates code when ptr offset is known */
9645 /*-----------------------------------------------------------------*/
9647 genDataPointerGet (operand * left,
9653 int size, offset = 0;
9654 aopOp (result, ic, TRUE, FALSE);
9656 /* get the string representation of the name */
9657 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9658 size = AOP_SIZE (result);
9659 _startLazyDPSEvaluation ();
9664 SNPRINTF (buff, sizeof(buff),
9665 "(%s + %d)", l + 1, offset);
9669 SNPRINTF (buff, sizeof(buff),
9672 aopPut (AOP (result), buff, offset++);
9674 _endLazyDPSEvaluation ();
9676 freeAsmop (left, NULL, ic, TRUE);
9677 freeAsmop (result, NULL, ic, TRUE);
9680 /*-----------------------------------------------------------------*/
9681 /* genNearPointerGet - emitcode for near pointer fetch */
9682 /*-----------------------------------------------------------------*/
9684 genNearPointerGet (operand * left,
9692 sym_link *rtype, *retype, *letype;
9693 sym_link *ltype = operandType (left);
9696 rtype = operandType (result);
9697 retype = getSpec (rtype);
9698 letype = getSpec (ltype);
9700 aopOp (left, ic, FALSE, FALSE);
9702 /* if left is rematerialisable and
9703 result is not bitfield variable type and
9704 the left is pointer to data space i.e
9705 lower 128 bytes of space */
9706 if (AOP_TYPE (left) == AOP_IMMD &&
9707 !IS_BITFIELD (retype) &&
9708 !IS_BITFIELD (letype) &&
9709 DCL_TYPE (ltype) == POINTER)
9711 genDataPointerGet (left, result, ic);
9715 /* if the value is already in a pointer register
9716 then don't need anything more */
9717 if (!AOP_INPREG (AOP (left)))
9719 /* otherwise get a free pointer register */
9721 preg = getFreePtr (ic, &aop, FALSE);
9722 emitcode ("mov", "%s,%s",
9724 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9728 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9730 freeAsmop (left, NULL, ic, TRUE);
9731 aopOp (result, ic, FALSE, FALSE);
9733 /* if bitfield then unpack the bits */
9734 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9735 genUnpackBits (result, rname, POINTER);
9738 /* we have can just get the values */
9739 int size = AOP_SIZE (result);
9744 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9747 emitcode ("mov", "a,@%s", rname);
9748 aopPut (AOP (result), "a", offset);
9752 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9753 aopPut (AOP (result), buff, offset);
9758 emitcode ("inc", "%s", rname);
9763 /* now some housekeeping stuff */
9766 /* we had to allocate for this iCode */
9767 if (pi) { /* post increment present */
9768 aopPut(AOP ( left ),rname,0);
9770 freeAsmop (NULL, aop, ic, TRUE);
9774 /* we did not allocate which means left
9775 already in a pointer register, then
9776 if size > 0 && this could be used again
9777 we have to point it back to where it
9779 if (AOP_SIZE (result) > 1 &&
9780 !OP_SYMBOL (left)->remat &&
9781 (OP_SYMBOL (left)->liveTo > ic->seq ||
9785 int size = AOP_SIZE (result) - 1;
9787 emitcode ("dec", "%s", rname);
9792 freeAsmop (result, NULL, ic, TRUE);
9793 if (pi) pi->generated = 1;
9796 /*-----------------------------------------------------------------*/
9797 /* genPagedPointerGet - emitcode for paged pointer fetch */
9798 /*-----------------------------------------------------------------*/
9800 genPagedPointerGet (operand * left,
9808 sym_link *rtype, *retype, *letype;
9810 rtype = operandType (result);
9811 retype = getSpec (rtype);
9812 letype = getSpec (operandType (left));
9813 aopOp (left, ic, FALSE, FALSE);
9815 /* if the value is already in a pointer register
9816 then don't need anything more */
9817 if (!AOP_INPREG (AOP (left)))
9819 /* otherwise get a free pointer register */
9821 preg = getFreePtr (ic, &aop, FALSE);
9822 emitcode ("mov", "%s,%s",
9824 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9828 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9830 freeAsmop (left, NULL, ic, TRUE);
9831 aopOp (result, ic, FALSE, FALSE);
9833 /* if bitfield then unpack the bits */
9834 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9835 genUnpackBits (result, rname, PPOINTER);
9838 /* we have can just get the values */
9839 int size = AOP_SIZE (result);
9845 emitcode ("movx", "a,@%s", rname);
9846 aopPut (AOP (result), "a", offset);
9851 emitcode ("inc", "%s", rname);
9855 /* now some housekeeping stuff */
9858 /* we had to allocate for this iCode */
9859 if (pi) aopPut ( AOP (left), rname, 0);
9860 freeAsmop (NULL, aop, ic, TRUE);
9864 /* we did not allocate which means left
9865 already in a pointer register, then
9866 if size > 0 && this could be used again
9867 we have to point it back to where it
9869 if (AOP_SIZE (result) > 1 &&
9870 !OP_SYMBOL (left)->remat &&
9871 (OP_SYMBOL (left)->liveTo > ic->seq ||
9875 int size = AOP_SIZE (result) - 1;
9877 emitcode ("dec", "%s", rname);
9882 freeAsmop (result, NULL, ic, TRUE);
9883 if (pi) pi->generated = 1;
9886 /*-----------------------------------------------------------------*/
9887 /* genFarPointerGet - gget value from far space */
9888 /*-----------------------------------------------------------------*/
9890 genFarPointerGet (operand * left,
9891 operand * result, iCode * ic, iCode *pi)
9893 int size, offset, dopi=1;
9894 sym_link *retype = getSpec (operandType (result));
9895 sym_link *letype = getSpec (operandType (left));
9896 D (emitcode (";", "genFarPointerGet"););
9898 aopOp (left, ic, FALSE, FALSE);
9900 /* if the operand is already in dptr
9901 then we do nothing else we move the value to dptr */
9902 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9904 /* if this is remateriazable */
9905 if (AOP_TYPE (left) == AOP_IMMD)
9907 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9911 /* we need to get it byte by byte */
9912 _startLazyDPSEvaluation ();
9913 if (AOP_TYPE (left) != AOP_DPTR)
9915 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9916 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9917 if (options.model == MODEL_FLAT24)
9918 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9922 /* We need to generate a load to DPTR indirect through DPTR. */
9923 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9924 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9925 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9926 if (options.model == MODEL_FLAT24)
9927 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9928 emitcode ("pop", "dph");
9929 emitcode ("pop", "dpl");
9932 _endLazyDPSEvaluation ();
9935 /* so dptr know contains the address */
9936 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9938 /* if bit then unpack */
9939 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9940 if (AOP_INDPTRn(left)) {
9941 genSetDPTR(AOP(left)->aopu.dptr);
9943 genUnpackBits (result, "dptr", FPOINTER);
9944 if (AOP_INDPTRn(left)) {
9949 size = AOP_SIZE (result);
9952 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9954 genSetDPTR(AOP(left)->aopu.dptr);
9955 emitcode ("movx", "a,@dptr");
9956 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9957 emitcode ("inc", "dptr");
9959 aopPut (AOP (result), "a", offset++);
9962 _startLazyDPSEvaluation ();
9964 if (AOP_INDPTRn(left)) {
9965 genSetDPTR(AOP(left)->aopu.dptr);
9971 emitcode ("movx", "a,@dptr");
9972 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9973 emitcode ("inc", "dptr");
9975 aopPut (AOP (result), "a", offset++);
9977 _endLazyDPSEvaluation ();
9980 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9981 if (!AOP_INDPTRn(left)) {
9982 _startLazyDPSEvaluation ();
9983 aopPut ( AOP (left), "dpl", 0);
9984 aopPut ( AOP (left), "dph", 1);
9985 if (options.model == MODEL_FLAT24)
9986 aopPut ( AOP (left), "dpx", 2);
9987 _endLazyDPSEvaluation ();
9990 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9991 AOP_SIZE(result) > 1 &&
9993 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9995 size = AOP_SIZE (result) - 1;
9996 if (AOP_INDPTRn(left)) {
9997 genSetDPTR(AOP(left)->aopu.dptr);
9999 while (size--) emitcode ("lcall","__decdptr");
10000 if (AOP_INDPTRn(left)) {
10005 freeAsmop (left, NULL, ic, TRUE);
10006 freeAsmop (result, NULL, ic, TRUE);
10009 /*-----------------------------------------------------------------*/
10010 /* genCodePointerGet - get value from code space */
10011 /*-----------------------------------------------------------------*/
10013 genCodePointerGet (operand * left,
10014 operand * result, iCode * ic, iCode *pi)
10016 int size, offset, dopi=1;
10017 sym_link *retype = getSpec (operandType (result));
10019 aopOp (left, ic, FALSE, FALSE);
10021 /* if the operand is already in dptr
10022 then we do nothing else we move the value to dptr */
10023 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10025 /* if this is remateriazable */
10026 if (AOP_TYPE (left) == AOP_IMMD)
10028 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10031 { /* we need to get it byte by byte */
10032 _startLazyDPSEvaluation ();
10033 if (AOP_TYPE (left) != AOP_DPTR)
10035 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10036 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10037 if (options.model == MODEL_FLAT24)
10038 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10042 /* We need to generate a load to DPTR indirect through DPTR. */
10043 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10044 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10045 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10046 if (options.model == MODEL_FLAT24)
10047 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10048 emitcode ("pop", "dph");
10049 emitcode ("pop", "dpl");
10052 _endLazyDPSEvaluation ();
10055 /* so dptr know contains the address */
10056 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10058 /* if bit then unpack */
10059 if (IS_BITFIELD (retype)) {
10060 if (AOP_INDPTRn(left)) {
10061 genSetDPTR(AOP(left)->aopu.dptr);
10063 genUnpackBits (result, "dptr", CPOINTER);
10064 if (AOP_INDPTRn(left)) {
10069 size = AOP_SIZE (result);
10071 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10073 genSetDPTR(AOP(left)->aopu.dptr);
10074 emitcode ("clr", "a");
10075 emitcode ("movc", "a,@a+dptr");
10076 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10077 emitcode ("inc", "dptr");
10079 aopPut (AOP (result), "a", offset++);
10082 _startLazyDPSEvaluation ();
10085 if (AOP_INDPTRn(left)) {
10086 genSetDPTR(AOP(left)->aopu.dptr);
10092 emitcode ("clr", "a");
10093 emitcode ("movc", "a,@a+dptr");
10094 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10095 emitcode ("inc", "dptr");
10096 aopPut (AOP (result), "a", offset++);
10098 _endLazyDPSEvaluation ();
10101 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10102 if (!AOP_INDPTRn(left)) {
10103 _startLazyDPSEvaluation ();
10105 aopPut ( AOP (left), "dpl", 0);
10106 aopPut ( AOP (left), "dph", 1);
10107 if (options.model == MODEL_FLAT24)
10108 aopPut ( AOP (left), "dpx", 2);
10110 _endLazyDPSEvaluation ();
10113 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10114 AOP_SIZE(result) > 1 &&
10115 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10117 size = AOP_SIZE (result) - 1;
10118 if (AOP_INDPTRn(left)) {
10119 genSetDPTR(AOP(left)->aopu.dptr);
10121 while (size--) emitcode ("lcall","__decdptr");
10122 if (AOP_INDPTRn(left)) {
10127 freeAsmop (left, NULL, ic, TRUE);
10128 freeAsmop (result, NULL, ic, TRUE);
10131 /*-----------------------------------------------------------------*/
10132 /* genGenPointerGet - gget value from generic pointer space */
10133 /*-----------------------------------------------------------------*/
10135 genGenPointerGet (operand * left,
10136 operand * result, iCode * ic, iCode * pi)
10139 sym_link *retype = getSpec (operandType (result));
10140 sym_link *letype = getSpec (operandType (left));
10142 D (emitcode (";", "genGenPointerGet "); );
10144 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10146 /* if the operand is already in dptr
10147 then we do nothing else we move the value to dptr */
10148 if (AOP_TYPE (left) != AOP_STR)
10150 /* if this is remateriazable */
10151 if (AOP_TYPE (left) == AOP_IMMD)
10153 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10154 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10156 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10160 emitcode ("mov", "b,#%d", pointerCode (retype));
10164 { /* we need to get it byte by byte */
10165 _startLazyDPSEvaluation ();
10166 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10167 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10168 if (options.model == MODEL_FLAT24) {
10169 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10170 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10172 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10174 _endLazyDPSEvaluation ();
10178 /* so dptr-b now contains the address */
10180 aopOp (result, ic, FALSE, TRUE);
10183 /* if bit then unpack */
10184 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10186 genUnpackBits (result, "dptr", GPOINTER);
10190 size = AOP_SIZE (result);
10197 // Get two bytes at a time, results in _AP & A.
10198 // dptr will be incremented ONCE by __gptrgetWord.
10200 // Note: any change here must be coordinated
10201 // with the implementation of __gptrgetWord
10202 // in device/lib/_gptrget.c
10203 emitcode ("lcall", "__gptrgetWord");
10204 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10205 aopPut (AOP (result), "a", offset++);
10210 // Only one byte to get.
10211 emitcode ("lcall", "__gptrget");
10212 aopPut (AOP (result), "a", offset++);
10215 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10217 emitcode ("inc", "dptr");
10222 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10223 _startLazyDPSEvaluation ();
10225 aopPut ( AOP (left), "dpl", 0);
10226 aopPut ( AOP (left), "dph", 1);
10227 if (options.model == MODEL_FLAT24) {
10228 aopPut ( AOP (left), "dpx", 2);
10229 aopPut ( AOP (left), "b", 3);
10230 } else aopPut ( AOP (left), "b", 2);
10232 _endLazyDPSEvaluation ();
10235 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10236 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10238 size = AOP_SIZE (result) - 1;
10239 while (size--) emitcode ("lcall","__decdptr");
10242 freeAsmop (left, NULL, ic, TRUE);
10243 freeAsmop (result, NULL, ic, TRUE);
10246 /*-----------------------------------------------------------------*/
10247 /* genPointerGet - generate code for pointer get */
10248 /*-----------------------------------------------------------------*/
10250 genPointerGet (iCode * ic, iCode *pi)
10252 operand *left, *result;
10253 sym_link *type, *etype;
10256 D (emitcode (";", "genPointerGet ");
10259 left = IC_LEFT (ic);
10260 result = IC_RESULT (ic);
10262 /* depending on the type of pointer we need to
10263 move it to the correct pointer register */
10264 type = operandType (left);
10265 etype = getSpec (type);
10266 /* if left is of type of pointer then it is simple */
10267 if (IS_PTR (type) && !IS_FUNC (type->next))
10268 p_type = DCL_TYPE (type);
10271 /* we have to go by the storage class */
10272 p_type = PTR_TYPE (SPEC_OCLS (etype));
10274 /* special case when cast remat */
10275 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10276 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10277 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10278 type = operandType (left);
10279 p_type = DCL_TYPE (type);
10281 /* now that we have the pointer type we assign
10282 the pointer values */
10288 genNearPointerGet (left, result, ic, pi);
10292 genPagedPointerGet (left, result, ic, pi);
10296 genFarPointerGet (left, result, ic, pi);
10300 genCodePointerGet (left, result, ic, pi);
10304 genGenPointerGet (left, result, ic, pi);
10310 /*-----------------------------------------------------------------*/
10311 /* genPackBits - generates code for packed bit storage */
10312 /*-----------------------------------------------------------------*/
10314 genPackBits (sym_link * etype,
10316 char *rname, int p_type)
10318 int offset = 0; /* source byte offset */
10319 int rlen = 0; /* remaining bitfield length */
10320 int blen; /* bitfield length */
10321 int bstr; /* bitfield starting bit within byte */
10322 int litval; /* source literal value (if AOP_LIT) */
10323 unsigned char mask; /* bitmask within current byte */
10325 D(emitcode ("; genPackBits",""));
10327 blen = SPEC_BLEN (etype);
10328 bstr = SPEC_BSTR (etype);
10330 /* If the bitfield length is less than a byte */
10333 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10334 (unsigned char) (0xFF >> (8 - bstr)));
10336 if (AOP_TYPE (right) == AOP_LIT)
10338 /* Case with a bitfield length <8 and literal source
10340 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10342 litval &= (~mask) & 0xff;
10343 emitPtrByteGet (rname, p_type, FALSE);
10344 if ((mask|litval)!=0xff)
10345 emitcode ("anl","a,#!constbyte", mask);
10347 emitcode ("orl","a,#!constbyte", litval);
10351 if ((blen==1) && (p_type!=GPOINTER))
10353 /* Case with a bitfield length == 1 and no generic pointer
10355 if (AOP_TYPE (right) == AOP_CRY)
10356 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10359 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10360 emitcode ("rrc","a");
10362 emitPtrByteGet (rname, p_type, FALSE);
10363 emitcode ("mov","acc.%d,c",bstr);
10367 /* Case with a bitfield length < 8 and arbitrary source
10369 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10370 /* shift and mask source value */
10372 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10374 /* transfer A to B and get next byte */
10375 emitPtrByteGet (rname, p_type, TRUE);
10377 emitcode ("anl", "a,#!constbyte", mask);
10378 emitcode ("orl", "a,b");
10379 if (p_type == GPOINTER)
10380 emitcode ("pop", "b");
10384 emitPtrByteSet (rname, p_type, "a");
10388 /* Bit length is greater than 7 bits. In this case, copy */
10389 /* all except the partial byte at the end */
10390 for (rlen=blen;rlen>=8;rlen-=8)
10392 emitPtrByteSet (rname, p_type,
10393 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10395 emitcode ("inc", "%s", rname);
10398 /* If there was a partial byte at the end */
10401 mask = (((unsigned char) -1 << rlen) & 0xff);
10403 if (AOP_TYPE (right) == AOP_LIT)
10405 /* Case with partial byte and literal source
10407 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10408 litval >>= (blen-rlen);
10409 litval &= (~mask) & 0xff;
10410 emitPtrByteGet (rname, p_type, FALSE);
10411 if ((mask|litval)!=0xff)
10412 emitcode ("anl","a,#!constbyte", mask);
10414 emitcode ("orl","a,#!constbyte", litval);
10418 /* Case with partial byte and arbitrary source
10420 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10421 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10423 /* transfer A to B and get next byte */
10424 emitPtrByteGet (rname, p_type, TRUE);
10426 emitcode ("anl", "a,#!constbyte", mask);
10427 emitcode ("orl", "a,b");
10428 if (p_type == GPOINTER)
10429 emitcode ("pop", "b");
10431 emitPtrByteSet (rname, p_type, "a");
10437 /*-----------------------------------------------------------------*/
10438 /* genDataPointerSet - remat pointer to data space */
10439 /*-----------------------------------------------------------------*/
10441 genDataPointerSet (operand * right,
10445 int size, offset = 0;
10446 char *l, buff[256];
10448 aopOp (right, ic, FALSE, FALSE);
10450 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10451 size = AOP_SIZE (right);
10456 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10460 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10463 emitcode ("mov", "%s,%s", buff,
10464 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10467 freeAsmop (right, NULL, ic, TRUE);
10468 freeAsmop (result, NULL, ic, TRUE);
10471 /*-----------------------------------------------------------------*/
10472 /* genNearPointerSet - emitcode for near pointer put */
10473 /*-----------------------------------------------------------------*/
10475 genNearPointerSet (operand * right,
10482 sym_link *retype, *letype;
10483 sym_link *ptype = operandType (result);
10485 retype = getSpec (operandType (right));
10486 letype = getSpec (ptype);
10488 aopOp (result, ic, FALSE, FALSE);
10490 /* if the result is rematerializable &
10491 in data space & not a bit variable */
10492 if (AOP_TYPE (result) == AOP_IMMD &&
10493 DCL_TYPE (ptype) == POINTER &&
10494 !IS_BITVAR (retype) &&
10495 !IS_BITVAR (letype))
10497 genDataPointerSet (right, result, ic);
10501 /* if the value is already in a pointer register
10502 then don't need anything more */
10503 if (!AOP_INPREG (AOP (result)))
10505 /* otherwise get a free pointer register */
10508 aop = newAsmop (0);
10509 preg = getFreePtr (ic, &aop, FALSE);
10510 emitcode ("mov", "%s,%s",
10512 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10513 rname = preg->name;
10516 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10518 aopOp (right, ic, FALSE, FALSE);
10520 /* if bitfield then unpack the bits */
10521 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10522 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10525 /* we have can just get the values */
10526 int size = AOP_SIZE (right);
10531 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10535 emitcode ("mov", "@%s,a", rname);
10538 emitcode ("mov", "@%s,%s", rname, l);
10540 emitcode ("inc", "%s", rname);
10545 /* now some housekeeping stuff */
10548 /* we had to allocate for this iCode */
10549 if (pi) aopPut (AOP (result),rname,0);
10550 freeAsmop (NULL, aop, ic, TRUE);
10554 /* we did not allocate which means left
10555 already in a pointer register, then
10556 if size > 0 && this could be used again
10557 we have to point it back to where it
10559 if (AOP_SIZE (right) > 1 &&
10560 !OP_SYMBOL (result)->remat &&
10561 (OP_SYMBOL (result)->liveTo > ic->seq ||
10565 int size = AOP_SIZE (right) - 1;
10567 emitcode ("dec", "%s", rname);
10572 if (pi) pi->generated = 1;
10573 freeAsmop (result, NULL, ic, TRUE);
10574 freeAsmop (right, NULL, ic, TRUE);
10579 /*-----------------------------------------------------------------*/
10580 /* genPagedPointerSet - emitcode for Paged pointer put */
10581 /*-----------------------------------------------------------------*/
10583 genPagedPointerSet (operand * right,
10590 sym_link *retype, *letype;
10592 retype = getSpec (operandType (right));
10593 letype = getSpec (operandType (result));
10595 aopOp (result, ic, FALSE, FALSE);
10597 /* if the value is already in a pointer register
10598 then don't need anything more */
10599 if (!AOP_INPREG (AOP (result)))
10601 /* otherwise get a free pointer register */
10604 aop = newAsmop (0);
10605 preg = getFreePtr (ic, &aop, FALSE);
10606 emitcode ("mov", "%s,%s",
10608 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10609 rname = preg->name;
10612 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10614 aopOp (right, ic, FALSE, FALSE);
10616 /* if bitfield then unpack the bits */
10617 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10618 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10621 /* we have can just get the values */
10622 int size = AOP_SIZE (right);
10627 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10629 emitcode ("movx", "@%s,a", rname);
10632 emitcode ("inc", "%s", rname);
10638 /* now some housekeeping stuff */
10641 if (pi) aopPut (AOP (result),rname,0);
10642 /* we had to allocate for this iCode */
10643 freeAsmop (NULL, aop, ic, TRUE);
10647 /* we did not allocate which means left
10648 already in a pointer register, then
10649 if size > 0 && this could be used again
10650 we have to point it back to where it
10652 if (AOP_SIZE (right) > 1 &&
10653 !OP_SYMBOL (result)->remat &&
10654 (OP_SYMBOL (result)->liveTo > ic->seq ||
10658 int size = AOP_SIZE (right) - 1;
10660 emitcode ("dec", "%s", rname);
10665 if (pi) pi->generated = 1;
10666 freeAsmop (result, NULL, ic, TRUE);
10667 freeAsmop (right, NULL, ic, TRUE);
10672 /*-----------------------------------------------------------------*/
10673 /* genFarPointerSet - set value from far space */
10674 /*-----------------------------------------------------------------*/
10676 genFarPointerSet (operand * right,
10677 operand * result, iCode * ic, iCode *pi)
10679 int size, offset, dopi=1;
10680 sym_link *retype = getSpec (operandType (right));
10681 sym_link *letype = getSpec (operandType (result));
10683 aopOp (result, ic, FALSE, FALSE);
10685 /* if the operand is already in dptr
10686 then we do nothing else we move the value to dptr */
10687 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10689 /* if this is remateriazable */
10690 if (AOP_TYPE (result) == AOP_IMMD)
10691 emitcode ("mov", "dptr,%s",
10692 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10695 /* we need to get it byte by byte */
10696 _startLazyDPSEvaluation ();
10697 if (AOP_TYPE (result) != AOP_DPTR)
10699 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10700 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10701 if (options.model == MODEL_FLAT24)
10702 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10706 /* We need to generate a load to DPTR indirect through DPTR. */
10707 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10709 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10710 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10711 if (options.model == MODEL_FLAT24)
10712 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10713 emitcode ("pop", "dph");
10714 emitcode ("pop", "dpl");
10717 _endLazyDPSEvaluation ();
10720 /* so dptr know contains the address */
10721 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10723 /* if bit then unpack */
10724 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10725 if (AOP_INDPTRn(result)) {
10726 genSetDPTR(AOP(result)->aopu.dptr);
10728 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10729 if (AOP_INDPTRn(result)) {
10733 size = AOP_SIZE (right);
10735 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10737 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10739 genSetDPTR(AOP(result)->aopu.dptr);
10740 emitcode ("movx", "@dptr,a");
10741 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10742 emitcode ("inc", "dptr");
10746 _startLazyDPSEvaluation ();
10748 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10750 if (AOP_INDPTRn(result)) {
10751 genSetDPTR(AOP(result)->aopu.dptr);
10757 emitcode ("movx", "@dptr,a");
10758 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10759 emitcode ("inc", "dptr");
10761 _endLazyDPSEvaluation ();
10765 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10766 if (!AOP_INDPTRn(result)) {
10767 _startLazyDPSEvaluation ();
10769 aopPut (AOP(result),"dpl",0);
10770 aopPut (AOP(result),"dph",1);
10771 if (options.model == MODEL_FLAT24)
10772 aopPut (AOP(result),"dpx",2);
10774 _endLazyDPSEvaluation ();
10777 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10778 AOP_SIZE(right) > 1 &&
10779 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10781 size = AOP_SIZE (right) - 1;
10782 if (AOP_INDPTRn(result)) {
10783 genSetDPTR(AOP(result)->aopu.dptr);
10785 while (size--) emitcode ("lcall","__decdptr");
10786 if (AOP_INDPTRn(result)) {
10790 freeAsmop (result, NULL, ic, TRUE);
10791 freeAsmop (right, NULL, ic, TRUE);
10794 /*-----------------------------------------------------------------*/
10795 /* genGenPointerSet - set value from generic pointer space */
10796 /*-----------------------------------------------------------------*/
10798 genGenPointerSet (operand * right,
10799 operand * result, iCode * ic, iCode *pi)
10802 sym_link *retype = getSpec (operandType (right));
10803 sym_link *letype = getSpec (operandType (result));
10805 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10807 /* if the operand is already in dptr
10808 then we do nothing else we move the value to dptr */
10809 if (AOP_TYPE (result) != AOP_STR)
10811 _startLazyDPSEvaluation ();
10812 /* if this is remateriazable */
10813 if (AOP_TYPE (result) == AOP_IMMD)
10815 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10816 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10818 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10823 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10827 { /* we need to get it byte by byte */
10828 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10829 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10830 if (options.model == MODEL_FLAT24) {
10831 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10832 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10834 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10837 _endLazyDPSEvaluation ();
10839 /* so dptr + b now contains the address */
10841 aopOp (right, ic, FALSE, TRUE);
10845 /* if bit then unpack */
10846 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10848 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10852 size = AOP_SIZE (right);
10855 _startLazyDPSEvaluation ();
10860 // Set two bytes at a time, passed in _AP & A.
10861 // dptr will be incremented ONCE by __gptrputWord.
10863 // Note: any change here must be coordinated
10864 // with the implementation of __gptrputWord
10865 // in device/lib/_gptrput.c
10866 emitcode("mov", "_ap, %s",
10867 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10868 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10872 emitcode ("lcall", "__gptrputWord");
10877 // Only one byte to put.
10878 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10882 emitcode ("lcall", "__gptrput");
10885 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10887 emitcode ("inc", "dptr");
10890 _endLazyDPSEvaluation ();
10893 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10894 _startLazyDPSEvaluation ();
10896 aopPut (AOP(result),"dpl",0);
10897 aopPut (AOP(result),"dph",1);
10898 if (options.model == MODEL_FLAT24) {
10899 aopPut (AOP(result),"dpx",2);
10900 aopPut (AOP(result),"b",3);
10902 aopPut (AOP(result),"b",2);
10904 _endLazyDPSEvaluation ();
10907 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10908 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10910 size = AOP_SIZE (right) - 1;
10911 while (size--) emitcode ("lcall","__decdptr");
10913 freeAsmop (result, NULL, ic, TRUE);
10914 freeAsmop (right, NULL, ic, TRUE);
10917 /*-----------------------------------------------------------------*/
10918 /* genPointerSet - stores the value into a pointer location */
10919 /*-----------------------------------------------------------------*/
10921 genPointerSet (iCode * ic, iCode *pi)
10923 operand *right, *result;
10924 sym_link *type, *etype;
10927 D (emitcode (";", "genPointerSet "););
10929 right = IC_RIGHT (ic);
10930 result = IC_RESULT (ic);
10932 /* depending on the type of pointer we need to
10933 move it to the correct pointer register */
10934 type = operandType (result);
10935 etype = getSpec (type);
10936 /* if left is of type of pointer then it is simple */
10937 if (IS_PTR (type) && !IS_FUNC (type->next))
10939 p_type = DCL_TYPE (type);
10943 /* we have to go by the storage class */
10944 p_type = PTR_TYPE (SPEC_OCLS (etype));
10946 /* special case when cast remat */
10947 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10948 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10949 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10950 type = operandType (result);
10951 p_type = DCL_TYPE (type);
10954 /* now that we have the pointer type we assign
10955 the pointer values */
10961 genNearPointerSet (right, result, ic, pi);
10965 genPagedPointerSet (right, result, ic, pi);
10969 genFarPointerSet (right, result, ic, pi);
10973 genGenPointerSet (right, result, ic, pi);
10977 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10978 "genPointerSet: illegal pointer type");
10983 /*-----------------------------------------------------------------*/
10984 /* genIfx - generate code for Ifx statement */
10985 /*-----------------------------------------------------------------*/
10987 genIfx (iCode * ic, iCode * popIc)
10989 operand *cond = IC_COND (ic);
10992 D (emitcode (";", "genIfx "););
10994 aopOp (cond, ic, FALSE, FALSE);
10996 /* get the value into acc */
10997 if (AOP_TYPE (cond) != AOP_CRY)
11006 /* the result is now in the accumulator */
11007 freeAsmop (cond, NULL, ic, TRUE);
11009 /* if there was something to be popped then do it */
11013 /* if the condition is a bit variable */
11014 if (isbit && IS_ITEMP (cond) &&
11017 genIfxJump (ic, SPIL_LOC (cond)->rname);
11019 else if (isbit && !IS_ITEMP (cond))
11021 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11025 genIfxJump (ic, "a");
11031 /*-----------------------------------------------------------------*/
11032 /* genAddrOf - generates code for address of */
11033 /*-----------------------------------------------------------------*/
11035 genAddrOf (iCode * ic)
11037 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11040 D (emitcode (";", "genAddrOf ");
11043 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11045 /* if the operand is on the stack then we
11046 need to get the stack offset of this
11048 if (sym->onStack) {
11050 /* if 10 bit stack */
11051 if (options.stack10bit) {
11055 tsprintf(buff, sizeof(buff),
11056 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11057 /* if it has an offset then we need to compute it */
11058 /* emitcode ("subb", "a,#!constbyte", */
11059 /* -((sym->stack < 0) ? */
11060 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11061 /* ((short) sym->stack)) & 0xff); */
11062 /* emitcode ("mov","b,a"); */
11063 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11064 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11065 /* ((short) sym->stack)) >> 8) & 0xff); */
11067 emitcode ("mov", "a,_bpx");
11068 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11069 ((char) (sym->stack - _G.nRegsSaved)) :
11070 ((char) sym->stack )) & 0xff);
11071 emitcode ("mov", "b,a");
11072 emitcode ("mov", "a,_bpx+1");
11074 offset = (((sym->stack < 0) ?
11075 ((short) (sym->stack - _G.nRegsSaved)) :
11076 ((short) sym->stack )) >> 8) & 0xff;
11078 emitcode ("addc","a,#!constbyte", offset);
11080 aopPut (AOP (IC_RESULT (ic)), "b", 0);
11081 aopPut (AOP (IC_RESULT (ic)), "a", 1);
11082 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11084 /* we can just move _bp */
11085 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11086 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11087 aopPut (AOP (IC_RESULT (ic)), buff, 2);
11090 /* if it has an offset then we need to compute it */
11092 emitcode ("mov", "a,_bp");
11093 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11094 aopPut (AOP (IC_RESULT (ic)), "a", 0);
11096 /* we can just move _bp */
11097 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11099 /* fill the result with zero */
11100 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11103 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11105 "*** warning: pointer to stack var truncated.\n");
11110 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11116 /* object not on stack then we need the name */
11117 size = AOP_SIZE (IC_RESULT (ic));
11122 char s[SDCC_NAME_MAX];
11126 tsprintf(s, sizeof(s), "#!his",sym->rname);
11129 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11132 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11134 default: /* should not need this (just in case) */
11135 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11142 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11145 aopPut (AOP (IC_RESULT (ic)), s, offset++);
11149 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11153 #if 0 // obsolete, and buggy for != xdata
11154 /*-----------------------------------------------------------------*/
11155 /* genArrayInit - generates code for address of */
11156 /*-----------------------------------------------------------------*/
11158 genArrayInit (iCode * ic)
11160 literalList *iLoop;
11162 int elementSize = 0, eIndex;
11163 unsigned val, lastVal;
11165 operand *left=IC_LEFT(ic);
11167 D (emitcode (";", "genArrayInit "););
11169 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11171 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11173 // Load immediate value into DPTR.
11174 emitcode("mov", "dptr, %s",
11175 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11177 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11180 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11181 "Unexpected operand to genArrayInit.\n");
11184 // a regression because of SDCCcse.c:1.52
11185 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11186 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11187 if (options.model == MODEL_FLAT24)
11188 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11192 type = operandType(IC_LEFT(ic));
11194 if (type && type->next)
11196 elementSize = getSize(type->next);
11200 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11201 "can't determine element size in genArrayInit.\n");
11205 iLoop = IC_ARRAYILIST(ic);
11210 bool firstpass = TRUE;
11212 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11213 iLoop->count, (int)iLoop->literalValue, elementSize);
11219 symbol *tlbl = NULL;
11221 count = ix > 256 ? 256 : ix;
11225 tlbl = newiTempLabel (NULL);
11226 if (firstpass || (count & 0xff))
11228 emitcode("mov", "b, #!constbyte", count & 0xff);
11231 emitcode ("", "!tlabeldef", tlbl->key + 100);
11236 for (eIndex = 0; eIndex < elementSize; eIndex++)
11238 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11239 if (val != lastVal)
11241 emitcode("mov", "a, #!constbyte", val);
11245 emitcode("movx", "@dptr, a");
11246 emitcode("inc", "dptr");
11251 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11257 iLoop = iLoop->next;
11260 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11264 /*-----------------------------------------------------------------*/
11265 /* genFarFarAssign - assignment when both are in far space */
11266 /*-----------------------------------------------------------------*/
11268 genFarFarAssign (operand * result, operand * right, iCode * ic)
11270 int size = AOP_SIZE (right);
11272 symbol *rSym = NULL;
11276 /* quick & easy case. */
11277 D(emitcode(";","genFarFarAssign (1 byte case)"););
11278 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11279 freeAsmop (right, NULL, ic, FALSE);
11280 /* now assign DPTR to result */
11282 aopOp(result, ic, FALSE, FALSE);
11284 aopPut(AOP(result), "a", 0);
11285 freeAsmop(result, NULL, ic, FALSE);
11289 /* See if we've got an underlying symbol to abuse. */
11290 if (IS_SYMOP(result) && OP_SYMBOL(result))
11292 if (IS_TRUE_SYMOP(result))
11294 rSym = OP_SYMBOL(result);
11296 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11298 rSym = OP_SYMBOL(result)->usl.spillLoc;
11302 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11304 /* We can use the '390 auto-toggle feature to good effect here. */
11306 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11307 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11308 emitcode ("mov", "dptr,#%s", rSym->rname);
11309 /* DP2 = result, DP1 = right, DP1 is current. */
11312 emitcode("movx", "a,@dptr");
11313 emitcode("movx", "@dptr,a");
11316 emitcode("inc", "dptr");
11317 emitcode("inc", "dptr");
11320 emitcode("mov", "dps,#0");
11321 freeAsmop (right, NULL, ic, FALSE);
11323 some alternative code for processors without auto-toggle
11324 no time to test now, so later well put in...kpb
11325 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11326 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11327 emitcode ("mov", "dptr,#%s", rSym->rname);
11328 /* DP2 = result, DP1 = right, DP1 is current. */
11332 emitcode("movx", "a,@dptr");
11334 emitcode("inc", "dptr");
11335 emitcode("inc", "dps");
11336 emitcode("movx", "@dptr,a");
11338 emitcode("inc", "dptr");
11339 emitcode("inc", "dps");
11341 emitcode("mov", "dps,#0");
11342 freeAsmop (right, NULL, ic, FALSE);
11347 D (emitcode (";", "genFarFarAssign"););
11348 aopOp (result, ic, TRUE, TRUE);
11350 _startLazyDPSEvaluation ();
11354 aopPut (AOP (result),
11355 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11358 _endLazyDPSEvaluation ();
11359 freeAsmop (result, NULL, ic, FALSE);
11360 freeAsmop (right, NULL, ic, FALSE);
11364 /*-----------------------------------------------------------------*/
11365 /* genAssign - generate code for assignment */
11366 /*-----------------------------------------------------------------*/
11368 genAssign (iCode * ic)
11370 operand *result, *right;
11372 unsigned long lit = 0L;
11374 D (emitcode (";", "genAssign ");
11377 result = IC_RESULT (ic);
11378 right = IC_RIGHT (ic);
11380 /* if they are the same */
11381 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11384 aopOp (right, ic, FALSE, FALSE);
11386 emitcode (";", "genAssign: resultIsFar = %s",
11387 isOperandInFarSpace (result) ?
11390 /* special case both in far space */
11391 if ((AOP_TYPE (right) == AOP_DPTR ||
11392 AOP_TYPE (right) == AOP_DPTR2) &&
11393 /* IS_TRUE_SYMOP(result) && */
11394 isOperandInFarSpace (result))
11396 genFarFarAssign (result, right, ic);
11400 aopOp (result, ic, TRUE, FALSE);
11402 /* if they are the same registers */
11403 if (sameRegs (AOP (right), AOP (result)))
11406 /* if the result is a bit */
11407 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11409 /* if the right size is a literal then
11410 we know what the value is */
11411 if (AOP_TYPE (right) == AOP_LIT)
11413 if (((int) operandLitValue (right)))
11414 aopPut (AOP (result), one, 0);
11416 aopPut (AOP (result), zero, 0);
11420 /* the right is also a bit variable */
11421 if (AOP_TYPE (right) == AOP_CRY)
11423 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11424 aopPut (AOP (result), "c", 0);
11428 /* we need to or */
11430 aopPut (AOP (result), "a", 0);
11434 /* bit variables done */
11436 size = AOP_SIZE (result);
11438 if (AOP_TYPE (right) == AOP_LIT)
11439 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11442 (AOP_TYPE (result) != AOP_REG) &&
11443 (AOP_TYPE (right) == AOP_LIT) &&
11444 !IS_FLOAT (operandType (right)))
11446 _startLazyDPSEvaluation ();
11447 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11449 aopPut (AOP (result),
11450 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11455 /* And now fill the rest with zeros. */
11458 emitcode ("clr", "a");
11462 aopPut (AOP (result), "a", offset++);
11464 _endLazyDPSEvaluation ();
11468 _startLazyDPSEvaluation ();
11471 aopPut (AOP (result),
11472 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11476 _endLazyDPSEvaluation ();
11480 freeAsmop (right, NULL, ic, FALSE);
11481 freeAsmop (result, NULL, ic, TRUE);
11484 /*-----------------------------------------------------------------*/
11485 /* genJumpTab - generates code for jump table */
11486 /*-----------------------------------------------------------------*/
11488 genJumpTab (iCode * ic)
11493 D (emitcode (";", "genJumpTab ");
11496 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11497 /* get the condition into accumulator */
11498 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11500 /* multiply by four! */
11501 emitcode ("add", "a,acc");
11502 emitcode ("add", "a,acc");
11503 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11505 jtab = newiTempLabel (NULL);
11506 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11507 emitcode ("jmp", "@a+dptr");
11508 emitcode ("", "!tlabeldef", jtab->key + 100);
11509 /* now generate the jump labels */
11510 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11511 jtab = setNextItem (IC_JTLABELS (ic)))
11512 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11516 /*-----------------------------------------------------------------*/
11517 /* genCast - gen code for casting */
11518 /*-----------------------------------------------------------------*/
11520 genCast (iCode * ic)
11522 operand *result = IC_RESULT (ic);
11523 sym_link *ctype = operandType (IC_LEFT (ic));
11524 sym_link *rtype = operandType (IC_RIGHT (ic));
11525 operand *right = IC_RIGHT (ic);
11528 D (emitcode (";", "genCast "););
11530 /* if they are equivalent then do nothing */
11531 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11534 aopOp (right, ic, FALSE, AOP_IS_STR (result));
11535 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11537 /* if the result is a bit */
11538 if (IS_BITVAR (OP_SYMBOL (result)->type)
11539 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11541 /* if the right size is a literal then
11542 we know what the value is */
11543 if (AOP_TYPE (right) == AOP_LIT)
11545 if (((int) operandLitValue (right)))
11546 aopPut (AOP (result), one, 0);
11548 aopPut (AOP (result), zero, 0);
11553 /* the right is also a bit variable */
11554 if (AOP_TYPE (right) == AOP_CRY)
11556 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11557 aopPut (AOP (result), "c", 0);
11561 /* we need to or */
11563 aopPut (AOP (result), "a", 0);
11567 /* if they are the same size : or less */
11568 if (AOP_SIZE (result) <= AOP_SIZE (right))
11571 /* if they are in the same place */
11572 if (sameRegs (AOP (right), AOP (result)))
11575 /* if they in different places then copy */
11576 size = AOP_SIZE (result);
11578 _startLazyDPSEvaluation ();
11581 aopPut (AOP (result),
11582 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11586 _endLazyDPSEvaluation ();
11591 /* if the result is of type pointer */
11592 if (IS_PTR (ctype))
11596 sym_link *type = operandType (right);
11598 /* pointer to generic pointer */
11599 if (IS_GENPTR (ctype))
11603 p_type = DCL_TYPE (type);
11607 #if OLD_CAST_BEHAVIOR
11608 /* KV: we are converting a non-pointer type to
11609 * a generic pointer. This (ifdef'd out) code
11610 * says that the resulting generic pointer
11611 * should have the same class as the storage
11612 * location of the non-pointer variable.
11614 * For example, converting an int (which happens
11615 * to be stored in DATA space) to a pointer results
11616 * in a DATA generic pointer; if the original int
11617 * in XDATA space, so will be the resulting pointer.
11619 * I don't like that behavior, and thus this change:
11620 * all such conversions will be forced to XDATA and
11621 * throw a warning. If you want some non-XDATA
11622 * type, or you want to suppress the warning, you
11623 * must go through an intermediate cast, like so:
11625 * char _generic *gp = (char _xdata *)(intVar);
11627 sym_link *etype = getSpec (type);
11629 /* we have to go by the storage class */
11630 if (SPEC_OCLS (etype) != generic)
11632 p_type = PTR_TYPE (SPEC_OCLS (etype));
11637 /* Converting unknown class (i.e. register variable)
11638 * to generic pointer. This is not good, but
11639 * we'll make a guess (and throw a warning).
11642 werror (W_INT_TO_GEN_PTR_CAST);
11646 /* the first two bytes are known */
11647 size = GPTRSIZE - 1;
11649 _startLazyDPSEvaluation ();
11652 aopPut (AOP (result),
11653 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11657 _endLazyDPSEvaluation ();
11659 /* the last byte depending on type */
11661 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11666 // pointerTypeToGPByte will have bitched.
11670 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11671 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11676 /* just copy the pointers */
11677 size = AOP_SIZE (result);
11679 _startLazyDPSEvaluation ();
11682 aopPut (AOP (result),
11683 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11687 _endLazyDPSEvaluation ();
11691 /* so we now know that the size of destination is greater
11692 than the size of the source */
11693 /* we move to result for the size of source */
11694 size = AOP_SIZE (right);
11696 _startLazyDPSEvaluation ();
11699 aopPut (AOP (result),
11700 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11704 _endLazyDPSEvaluation ();
11706 /* now depending on the sign of the source && destination */
11707 size = AOP_SIZE (result) - AOP_SIZE (right);
11708 /* if unsigned or not an integral type */
11709 /* also, if the source is a bit, we don't need to sign extend, because
11710 * it can't possibly have set the sign bit.
11712 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11716 aopPut (AOP (result), zero, offset++);
11721 /* we need to extend the sign :{ */
11722 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11723 FALSE, FALSE, NULL));
11724 emitcode ("rlc", "a");
11725 emitcode ("subb", "a,acc");
11727 aopPut (AOP (result), "a", offset++);
11730 /* we are done hurray !!!! */
11733 freeAsmop (right, NULL, ic, TRUE);
11734 freeAsmop (result, NULL, ic, TRUE);
11738 /*-----------------------------------------------------------------*/
11739 /* genDjnz - generate decrement & jump if not zero instrucion */
11740 /*-----------------------------------------------------------------*/
11742 genDjnz (iCode * ic, iCode * ifx)
11744 symbol *lbl, *lbl1;
11748 /* if the if condition has a false label
11749 then we cannot save */
11750 if (IC_FALSE (ifx))
11753 /* if the minus is not of the form
11755 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11756 !IS_OP_LITERAL (IC_RIGHT (ic)))
11759 if (operandLitValue (IC_RIGHT (ic)) != 1)
11762 /* if the size of this greater than one then no
11764 if (getSize (operandType (IC_RESULT (ic))) > 1)
11767 /* otherwise we can save BIG */
11768 D(emitcode(";", "genDjnz"););
11770 lbl = newiTempLabel (NULL);
11771 lbl1 = newiTempLabel (NULL);
11773 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11775 if (AOP_NEEDSACC(IC_RESULT(ic)))
11777 /* If the result is accessed indirectly via
11778 * the accumulator, we must explicitly write
11779 * it back after the decrement.
11781 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11783 if (strcmp(rByte, "a"))
11785 /* Something is hopelessly wrong */
11786 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11787 __FILE__, __LINE__);
11788 /* We can just give up; the generated code will be inefficient,
11789 * but what the hey.
11791 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11794 emitcode ("dec", "%s", rByte);
11795 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11796 emitcode ("jnz", "!tlabel", lbl->key + 100);
11798 else if (IS_AOP_PREG (IC_RESULT (ic)))
11800 emitcode ("dec", "%s",
11801 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11802 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11803 emitcode ("jnz", "!tlabel", lbl->key + 100);
11807 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11810 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11811 emitcode ("", "!tlabeldef", lbl->key + 100);
11812 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11813 emitcode ("", "!tlabeldef", lbl1->key + 100);
11815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11816 ifx->generated = 1;
11820 /*-----------------------------------------------------------------*/
11821 /* genReceive - generate code for a receive iCode */
11822 /*-----------------------------------------------------------------*/
11824 genReceive (iCode * ic)
11826 int size = getSize (operandType (IC_RESULT (ic)));
11830 D (emitcode (";", "genReceive "););
11832 if (ic->argreg == 1)
11834 /* first parameter */
11835 if (AOP_IS_STR(IC_RESULT(ic)))
11837 /* Nothing to do: it's already in the proper place. */
11844 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11845 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11846 IS_TRUE_SYMOP (IC_RESULT (ic)));
11849 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11852 /* Sanity checking... */
11853 if (AOP_USESDPTR(IC_RESULT(ic)))
11855 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11856 "genReceive got unexpected DPTR.");
11858 assignResultValue (IC_RESULT (ic));
11863 /* second receive onwards */
11864 /* this gets a little tricky since unused recevies will be
11865 eliminated, we have saved the reg in the type field . and
11866 we use that to figure out which register to use */
11867 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11868 rb1off = ic->argreg;
11871 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11877 /*-----------------------------------------------------------------*/
11878 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11879 /*-----------------------------------------------------------------*/
11880 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11882 operand *from , *to , *count;
11887 /* we know it has to be 3 parameters */
11888 assert (nparms == 3);
11890 rsave = newBitVect(16);
11891 /* save DPTR if it needs to be saved */
11892 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11893 if (bitVectBitValue(ic->rMask,i))
11894 rsave = bitVectSetBit(rsave,i);
11896 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11897 ds390_rUmaskForOp (IC_RESULT(ic))));
11904 aopOp (from, ic->next, FALSE, FALSE);
11906 /* get from into DPTR1 */
11907 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11908 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11909 if (options.model == MODEL_FLAT24) {
11910 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11913 freeAsmop (from, NULL, ic, FALSE);
11914 aopOp (to, ic, FALSE, FALSE);
11915 /* get "to" into DPTR */
11916 /* if the operand is already in dptr
11917 then we do nothing else we move the value to dptr */
11918 if (AOP_TYPE (to) != AOP_STR) {
11919 /* if already in DPTR then we need to push */
11920 if (AOP_TYPE(to) == AOP_DPTR) {
11921 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11922 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11923 if (options.model == MODEL_FLAT24)
11924 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11925 emitcode ("pop", "dph");
11926 emitcode ("pop", "dpl");
11928 _startLazyDPSEvaluation ();
11929 /* if this is remateriazable */
11930 if (AOP_TYPE (to) == AOP_IMMD) {
11931 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11932 } else { /* we need to get it byte by byte */
11933 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11934 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11935 if (options.model == MODEL_FLAT24) {
11936 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11939 _endLazyDPSEvaluation ();
11942 freeAsmop (to, NULL, ic, FALSE);
11943 _G.dptrInUse = _G.dptr1InUse = 1;
11944 aopOp (count, ic->next->next, FALSE,FALSE);
11945 lbl =newiTempLabel(NULL);
11947 /* now for the actual copy */
11948 if (AOP_TYPE(count) == AOP_LIT &&
11949 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11950 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11952 emitcode ("lcall","__bi_memcpyc2x_s");
11954 emitcode ("lcall","__bi_memcpyx2x_s");
11956 freeAsmop (count, NULL, ic, FALSE);
11958 symbol *lbl1 = newiTempLabel(NULL);
11960 emitcode (";"," Auto increment but no djnz");
11961 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11962 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11963 freeAsmop (count, NULL, ic, FALSE);
11964 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11965 emitcode ("","!tlabeldef",lbl->key+100);
11967 emitcode ("clr","a");
11968 emitcode ("movc", "a,@a+dptr");
11970 emitcode ("movx", "a,@dptr");
11971 emitcode ("movx", "@dptr,a");
11972 emitcode ("inc", "dptr");
11973 emitcode ("inc", "dptr");
11974 emitcode ("mov","a,b");
11975 emitcode ("orl","a,_ap");
11976 emitcode ("jz","!tlabel",lbl1->key+100);
11977 emitcode ("mov","a,_ap");
11978 emitcode ("add","a,#!constbyte",0xFF);
11979 emitcode ("mov","_ap,a");
11980 emitcode ("mov","a,b");
11981 emitcode ("addc","a,#!constbyte",0xFF);
11982 emitcode ("mov","b,a");
11983 emitcode ("sjmp","!tlabel",lbl->key+100);
11984 emitcode ("","!tlabeldef",lbl1->key+100);
11986 emitcode ("mov", "dps,#0");
11987 _G.dptrInUse = _G.dptr1InUse = 0;
11988 unsavermask(rsave);
11992 /*-----------------------------------------------------------------*/
11993 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11994 /*-----------------------------------------------------------------*/
11995 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11997 operand *from , *to , *count;
12002 /* we know it has to be 3 parameters */
12003 assert (nparms == 3);
12005 rsave = newBitVect(16);
12006 /* save DPTR if it needs to be saved */
12007 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12008 if (bitVectBitValue(ic->rMask,i))
12009 rsave = bitVectSetBit(rsave,i);
12011 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12012 ds390_rUmaskForOp (IC_RESULT(ic))));
12019 aopOp (from, ic->next, FALSE, FALSE);
12021 /* get from into DPTR1 */
12022 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12023 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12024 if (options.model == MODEL_FLAT24) {
12025 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12028 freeAsmop (from, NULL, ic, FALSE);
12029 aopOp (to, ic, FALSE, FALSE);
12030 /* get "to" into DPTR */
12031 /* if the operand is already in dptr
12032 then we do nothing else we move the value to dptr */
12033 if (AOP_TYPE (to) != AOP_STR) {
12034 /* if already in DPTR then we need to push */
12035 if (AOP_TYPE(to) == AOP_DPTR) {
12036 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12037 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12038 if (options.model == MODEL_FLAT24)
12039 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12040 emitcode ("pop", "dph");
12041 emitcode ("pop", "dpl");
12043 _startLazyDPSEvaluation ();
12044 /* if this is remateriazable */
12045 if (AOP_TYPE (to) == AOP_IMMD) {
12046 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12047 } else { /* we need to get it byte by byte */
12048 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12049 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12050 if (options.model == MODEL_FLAT24) {
12051 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12054 _endLazyDPSEvaluation ();
12057 freeAsmop (to, NULL, ic, FALSE);
12058 _G.dptrInUse = _G.dptr1InUse = 1;
12059 aopOp (count, ic->next->next, FALSE,FALSE);
12060 lbl =newiTempLabel(NULL);
12061 lbl2 =newiTempLabel(NULL);
12063 /* now for the actual compare */
12064 if (AOP_TYPE(count) == AOP_LIT &&
12065 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12066 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12068 emitcode("lcall","__bi_memcmpc2x_s");
12070 emitcode("lcall","__bi_memcmpx2x_s");
12071 freeAsmop (count, NULL, ic, FALSE);
12072 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12073 aopPut(AOP(IC_RESULT(ic)),"a",0);
12074 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12076 symbol *lbl1 = newiTempLabel(NULL);
12078 emitcode("push","ar0");
12079 emitcode (";"," Auto increment but no djnz");
12080 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12081 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12082 freeAsmop (count, NULL, ic, FALSE);
12083 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12084 emitcode ("","!tlabeldef",lbl->key+100);
12086 emitcode ("clr","a");
12087 emitcode ("movc", "a,@a+dptr");
12089 emitcode ("movx", "a,@dptr");
12090 emitcode ("mov","r0,a");
12091 emitcode ("movx", "a,@dptr");
12092 emitcode ("clr","c");
12093 emitcode ("subb","a,r0");
12094 emitcode ("jnz","!tlabel",lbl2->key+100);
12095 emitcode ("inc", "dptr");
12096 emitcode ("inc", "dptr");
12097 emitcode ("mov","a,b");
12098 emitcode ("orl","a,_ap");
12099 emitcode ("jz","!tlabel",lbl1->key+100);
12100 emitcode ("mov","a,_ap");
12101 emitcode ("add","a,#!constbyte",0xFF);
12102 emitcode ("mov","_ap,a");
12103 emitcode ("mov","a,b");
12104 emitcode ("addc","a,#!constbyte",0xFF);
12105 emitcode ("mov","b,a");
12106 emitcode ("sjmp","!tlabel",lbl->key+100);
12107 emitcode ("","!tlabeldef",lbl1->key+100);
12108 emitcode ("clr","a");
12109 emitcode ("","!tlabeldef",lbl2->key+100);
12110 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12111 aopPut(AOP(IC_RESULT(ic)),"a",0);
12112 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12113 emitcode("pop","ar0");
12114 emitcode ("mov", "dps,#0");
12116 _G.dptrInUse = _G.dptr1InUse = 0;
12117 unsavermask(rsave);
12121 /*-----------------------------------------------------------------*/
12122 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12123 /* port, first parameter output area second parameter pointer to */
12124 /* port third parameter count */
12125 /*-----------------------------------------------------------------*/
12126 static void genInp( iCode *ic, int nparms, operand **parms)
12128 operand *from , *to , *count;
12133 /* we know it has to be 3 parameters */
12134 assert (nparms == 3);
12136 rsave = newBitVect(16);
12137 /* save DPTR if it needs to be saved */
12138 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12139 if (bitVectBitValue(ic->rMask,i))
12140 rsave = bitVectSetBit(rsave,i);
12142 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12143 ds390_rUmaskForOp (IC_RESULT(ic))));
12150 aopOp (from, ic->next, FALSE, FALSE);
12152 /* get from into DPTR1 */
12153 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12154 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12155 if (options.model == MODEL_FLAT24) {
12156 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12159 freeAsmop (from, NULL, ic, FALSE);
12160 aopOp (to, ic, FALSE, FALSE);
12161 /* get "to" into DPTR */
12162 /* if the operand is already in dptr
12163 then we do nothing else we move the value to dptr */
12164 if (AOP_TYPE (to) != AOP_STR) {
12165 /* if already in DPTR then we need to push */
12166 if (AOP_TYPE(to) == AOP_DPTR) {
12167 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12168 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12169 if (options.model == MODEL_FLAT24)
12170 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12171 emitcode ("pop", "dph");
12172 emitcode ("pop", "dpl");
12174 _startLazyDPSEvaluation ();
12175 /* if this is remateriazable */
12176 if (AOP_TYPE (to) == AOP_IMMD) {
12177 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12178 } else { /* we need to get it byte by byte */
12179 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12180 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12181 if (options.model == MODEL_FLAT24) {
12182 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12185 _endLazyDPSEvaluation ();
12188 freeAsmop (to, NULL, ic, FALSE);
12190 _G.dptrInUse = _G.dptr1InUse = 1;
12191 aopOp (count, ic->next->next, FALSE,FALSE);
12192 lbl =newiTempLabel(NULL);
12194 /* now for the actual copy */
12195 if (AOP_TYPE(count) == AOP_LIT &&
12196 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12197 emitcode (";","OH JOY auto increment with djnz (very fast)");
12198 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12199 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12200 freeAsmop (count, NULL, ic, FALSE);
12201 emitcode ("","!tlabeldef",lbl->key+100);
12202 emitcode ("movx", "a,@dptr"); /* read data from port */
12203 emitcode ("dec","dps"); /* switch to DPTR */
12204 emitcode ("movx", "@dptr,a"); /* save into location */
12205 emitcode ("inc", "dptr"); /* point to next area */
12206 emitcode ("inc","dps"); /* switch to DPTR2 */
12207 emitcode ("djnz","b,!tlabel",lbl->key+100);
12209 symbol *lbl1 = newiTempLabel(NULL);
12211 emitcode (";"," Auto increment but no djnz");
12212 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12213 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12214 freeAsmop (count, NULL, ic, FALSE);
12215 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12216 emitcode ("","!tlabeldef",lbl->key+100);
12217 emitcode ("movx", "a,@dptr");
12218 emitcode ("dec","dps"); /* switch to DPTR */
12219 emitcode ("movx", "@dptr,a");
12220 emitcode ("inc", "dptr");
12221 emitcode ("inc","dps"); /* switch to DPTR2 */
12222 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12223 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12224 emitcode ("mov","a,b");
12225 emitcode ("orl","a,_ap");
12226 emitcode ("jz","!tlabel",lbl1->key+100);
12227 emitcode ("mov","a,_ap");
12228 emitcode ("add","a,#!constbyte",0xFF);
12229 emitcode ("mov","_ap,a");
12230 emitcode ("mov","a,b");
12231 emitcode ("addc","a,#!constbyte",0xFF);
12232 emitcode ("mov","b,a");
12233 emitcode ("sjmp","!tlabel",lbl->key+100);
12234 emitcode ("","!tlabeldef",lbl1->key+100);
12236 emitcode ("mov", "dps,#0");
12237 _G.dptrInUse = _G.dptr1InUse = 0;
12238 unsavermask(rsave);
12242 /*-----------------------------------------------------------------*/
12243 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12244 /* port, first parameter output area second parameter pointer to */
12245 /* port third parameter count */
12246 /*-----------------------------------------------------------------*/
12247 static void genOutp( iCode *ic, int nparms, operand **parms)
12249 operand *from , *to , *count;
12254 /* we know it has to be 3 parameters */
12255 assert (nparms == 3);
12257 rsave = newBitVect(16);
12258 /* save DPTR if it needs to be saved */
12259 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12260 if (bitVectBitValue(ic->rMask,i))
12261 rsave = bitVectSetBit(rsave,i);
12263 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12264 ds390_rUmaskForOp (IC_RESULT(ic))));
12271 aopOp (from, ic->next, FALSE, FALSE);
12273 /* get from into DPTR1 */
12274 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12275 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12276 if (options.model == MODEL_FLAT24) {
12277 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12280 freeAsmop (from, NULL, ic, FALSE);
12281 aopOp (to, ic, FALSE, FALSE);
12282 /* get "to" into DPTR */
12283 /* if the operand is already in dptr
12284 then we do nothing else we move the value to dptr */
12285 if (AOP_TYPE (to) != AOP_STR) {
12286 /* if already in DPTR then we need to push */
12287 if (AOP_TYPE(to) == AOP_DPTR) {
12288 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12289 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12290 if (options.model == MODEL_FLAT24)
12291 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12292 emitcode ("pop", "dph");
12293 emitcode ("pop", "dpl");
12295 _startLazyDPSEvaluation ();
12296 /* if this is remateriazable */
12297 if (AOP_TYPE (to) == AOP_IMMD) {
12298 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12299 } else { /* we need to get it byte by byte */
12300 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12301 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12302 if (options.model == MODEL_FLAT24) {
12303 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12306 _endLazyDPSEvaluation ();
12309 freeAsmop (to, NULL, ic, FALSE);
12311 _G.dptrInUse = _G.dptr1InUse = 1;
12312 aopOp (count, ic->next->next, FALSE,FALSE);
12313 lbl =newiTempLabel(NULL);
12315 /* now for the actual copy */
12316 if (AOP_TYPE(count) == AOP_LIT &&
12317 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12318 emitcode (";","OH JOY auto increment with djnz (very fast)");
12319 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12320 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12321 emitcode ("","!tlabeldef",lbl->key+100);
12322 emitcode ("movx", "a,@dptr"); /* read data from port */
12323 emitcode ("inc","dps"); /* switch to DPTR2 */
12324 emitcode ("movx", "@dptr,a"); /* save into location */
12325 emitcode ("inc", "dptr"); /* point to next area */
12326 emitcode ("dec","dps"); /* switch to DPTR */
12327 emitcode ("djnz","b,!tlabel",lbl->key+100);
12328 freeAsmop (count, NULL, ic, FALSE);
12330 symbol *lbl1 = newiTempLabel(NULL);
12332 emitcode (";"," Auto increment but no djnz");
12333 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12334 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12335 freeAsmop (count, NULL, ic, FALSE);
12336 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12337 emitcode ("","!tlabeldef",lbl->key+100);
12338 emitcode ("movx", "a,@dptr");
12339 emitcode ("inc", "dptr");
12340 emitcode ("inc","dps"); /* switch to DPTR2 */
12341 emitcode ("movx", "@dptr,a");
12342 emitcode ("dec","dps"); /* switch to DPTR */
12343 emitcode ("mov","a,b");
12344 emitcode ("orl","a,_ap");
12345 emitcode ("jz","!tlabel",lbl1->key+100);
12346 emitcode ("mov","a,_ap");
12347 emitcode ("add","a,#!constbyte",0xFF);
12348 emitcode ("mov","_ap,a");
12349 emitcode ("mov","a,b");
12350 emitcode ("addc","a,#!constbyte",0xFF);
12351 emitcode ("mov","b,a");
12352 emitcode ("sjmp","!tlabel",lbl->key+100);
12353 emitcode ("","!tlabeldef",lbl1->key+100);
12355 emitcode ("mov", "dps,#0");
12356 _G.dptrInUse = _G.dptr1InUse = 0;
12357 unsavermask(rsave);
12361 /*-----------------------------------------------------------------*/
12362 /* genSwapW - swap lower & high order bytes */
12363 /*-----------------------------------------------------------------*/
12364 static void genSwapW(iCode *ic, int nparms, operand **parms)
12368 assert (nparms==1);
12371 dest=IC_RESULT(ic);
12373 assert(getSize(operandType(src))==2);
12375 aopOp (src, ic, FALSE, FALSE);
12376 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12378 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12380 freeAsmop (src, NULL, ic, FALSE);
12382 aopOp (dest,ic, FALSE, FALSE);
12383 aopPut(AOP(dest),"b",0);
12384 aopPut(AOP(dest),"a",1);
12385 freeAsmop (dest, NULL, ic, FALSE);
12388 /*-----------------------------------------------------------------*/
12389 /* genMemsetX - gencode for memSetX data */
12390 /*-----------------------------------------------------------------*/
12391 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12393 operand *to , *val , *count;
12399 /* we know it has to be 3 parameters */
12400 assert (nparms == 3);
12406 /* save DPTR if it needs to be saved */
12407 rsave = newBitVect(16);
12408 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12409 if (bitVectBitValue(ic->rMask,i))
12410 rsave = bitVectSetBit(rsave,i);
12412 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12413 ds390_rUmaskForOp (IC_RESULT(ic))));
12416 aopOp (to, ic, FALSE, FALSE);
12417 /* get "to" into DPTR */
12418 /* if the operand is already in dptr
12419 then we do nothing else we move the value to dptr */
12420 if (AOP_TYPE (to) != AOP_STR) {
12421 /* if already in DPTR then we need to push */
12422 if (AOP_TYPE(to) == AOP_DPTR) {
12423 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12424 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12425 if (options.model == MODEL_FLAT24)
12426 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12427 emitcode ("pop", "dph");
12428 emitcode ("pop", "dpl");
12430 _startLazyDPSEvaluation ();
12431 /* if this is remateriazable */
12432 if (AOP_TYPE (to) == AOP_IMMD) {
12433 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12434 } else { /* we need to get it byte by byte */
12435 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12436 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12437 if (options.model == MODEL_FLAT24) {
12438 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12441 _endLazyDPSEvaluation ();
12444 freeAsmop (to, NULL, ic, FALSE);
12446 aopOp (val, ic->next->next, FALSE,FALSE);
12447 aopOp (count, ic->next->next, FALSE,FALSE);
12448 lbl =newiTempLabel(NULL);
12449 /* now for the actual copy */
12450 if (AOP_TYPE(count) == AOP_LIT &&
12451 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12452 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12453 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12455 emitcode ("","!tlabeldef",lbl->key+100);
12456 emitcode ("movx", "@dptr,a");
12457 emitcode ("inc", "dptr");
12458 emitcode ("djnz","b,!tlabel",lbl->key+100);
12460 symbol *lbl1 = newiTempLabel(NULL);
12462 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12463 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12464 emitcode ("","!tlabeldef",lbl->key+100);
12465 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12466 emitcode ("movx", "@dptr,a");
12467 emitcode ("inc", "dptr");
12468 emitcode ("mov","a,b");
12469 emitcode ("orl","a,_ap");
12470 emitcode ("jz","!tlabel",lbl1->key+100);
12471 emitcode ("mov","a,_ap");
12472 emitcode ("add","a,#!constbyte",0xFF);
12473 emitcode ("mov","_ap,a");
12474 emitcode ("mov","a,b");
12475 emitcode ("addc","a,#!constbyte",0xFF);
12476 emitcode ("mov","b,a");
12477 emitcode ("sjmp","!tlabel",lbl->key+100);
12478 emitcode ("","!tlabeldef",lbl1->key+100);
12480 freeAsmop (count, NULL, ic, FALSE);
12481 unsavermask(rsave);
12484 /*-----------------------------------------------------------------*/
12485 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12486 /*-----------------------------------------------------------------*/
12487 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12490 operand *pnum, *result;
12493 assert (nparms==1);
12494 /* save registers that need to be saved */
12495 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12496 ds390_rUmaskForOp (IC_RESULT(ic))));
12499 aopOp (pnum, ic, FALSE, FALSE);
12500 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12501 freeAsmop (pnum, NULL, ic, FALSE);
12502 emitcode ("lcall","NatLib_LoadPrimitive");
12503 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12504 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12505 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12506 for (i = (size-1) ; i >= 0 ; i-- ) {
12507 emitcode ("push","a%s",javaRet[i]);
12509 for (i=0; i < size ; i++ ) {
12510 emitcode ("pop","a%s",
12511 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12514 for (i = 0 ; i < size ; i++ ) {
12515 aopPut(AOP(result),javaRet[i],i);
12518 freeAsmop (result, NULL, ic, FALSE);
12519 unsavermask(rsave);
12522 /*-----------------------------------------------------------------*/
12523 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12524 /*-----------------------------------------------------------------*/
12525 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12528 operand *pnum, *result;
12532 assert (nparms==1);
12533 /* save registers that need to be saved */
12534 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12535 ds390_rUmaskForOp (IC_RESULT(ic))));
12538 aopOp (pnum, ic, FALSE, FALSE);
12539 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12540 freeAsmop (pnum, NULL, ic, FALSE);
12541 emitcode ("lcall","NatLib_LoadPointer");
12542 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12543 if (AOP_TYPE(result)!=AOP_STR) {
12544 for (i = 0 ; i < size ; i++ ) {
12545 aopPut(AOP(result),fReturn[i],i);
12548 freeAsmop (result, NULL, ic, FALSE);
12549 unsavermask(rsave);
12552 /*-----------------------------------------------------------------*/
12553 /* genNatLibInstallStateBlock - */
12554 /*-----------------------------------------------------------------*/
12555 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12556 operand **parms, const char *name)
12559 operand *psb, *handle;
12560 assert (nparms==2);
12562 /* save registers that need to be saved */
12563 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12564 ds390_rUmaskForOp (IC_RESULT(ic))));
12568 /* put pointer to state block into DPTR1 */
12569 aopOp (psb, ic, FALSE, FALSE);
12570 if (AOP_TYPE (psb) == AOP_IMMD) {
12571 emitcode ("mov","dps,#1");
12572 emitcode ("mov", "dptr,%s",
12573 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12574 emitcode ("mov","dps,#0");
12576 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12577 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12578 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12580 freeAsmop (psb, NULL, ic, FALSE);
12582 /* put libraryID into DPTR */
12583 emitcode ("mov","dptr,#LibraryID");
12585 /* put handle into r3:r2 */
12586 aopOp (handle, ic, FALSE, FALSE);
12587 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12588 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12589 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12590 emitcode ("pop","ar3");
12591 emitcode ("pop","ar2");
12593 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12594 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12596 freeAsmop (psb, NULL, ic, FALSE);
12598 /* make the call */
12599 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12601 /* put return value into place*/
12603 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12605 aopPut(AOP(IC_RESULT(ic)),"a",0);
12606 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12607 unsavermask(rsave);
12610 /*-----------------------------------------------------------------*/
12611 /* genNatLibRemoveStateBlock - */
12612 /*-----------------------------------------------------------------*/
12613 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12619 /* save registers that need to be saved */
12620 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12621 ds390_rUmaskForOp (IC_RESULT(ic))));
12623 /* put libraryID into DPTR */
12624 emitcode ("mov","dptr,#LibraryID");
12625 /* make the call */
12626 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12627 unsavermask(rsave);
12630 /*-----------------------------------------------------------------*/
12631 /* genNatLibGetStateBlock - */
12632 /*-----------------------------------------------------------------*/
12633 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12634 operand **parms,const char *name)
12637 symbol *lbl = newiTempLabel(NULL);
12640 /* save registers that need to be saved */
12641 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12642 ds390_rUmaskForOp (IC_RESULT(ic))));
12644 /* put libraryID into DPTR */
12645 emitcode ("mov","dptr,#LibraryID");
12646 /* make the call */
12647 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12648 emitcode ("jnz","!tlabel",lbl->key+100);
12650 /* put return value into place */
12651 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12652 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12653 emitcode ("push","ar3");
12654 emitcode ("push","ar2");
12655 emitcode ("pop","%s",
12656 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12657 emitcode ("pop","%s",
12658 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12660 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12661 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12663 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12664 emitcode ("","!tlabeldef",lbl->key+100);
12665 unsavermask(rsave);
12668 /*-----------------------------------------------------------------*/
12669 /* genMMMalloc - */
12670 /*-----------------------------------------------------------------*/
12671 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12672 int size, const char *name)
12677 symbol *lbl = newiTempLabel(NULL);
12679 assert (nparms == 1);
12680 /* save registers that need to be saved */
12681 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12682 ds390_rUmaskForOp (IC_RESULT(ic))));
12685 aopOp (bsize,ic,FALSE,FALSE);
12687 /* put the size in R4-R2 */
12688 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12689 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12690 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12692 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12693 emitcode("pop","ar4");
12695 emitcode("pop","ar3");
12696 emitcode("pop","ar2");
12698 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12699 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12701 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12704 freeAsmop (bsize, NULL, ic, FALSE);
12706 /* make the call */
12707 emitcode ("lcall","MM_%s",name);
12708 emitcode ("jz","!tlabel",lbl->key+100);
12709 emitcode ("mov","r2,#!constbyte",0xff);
12710 emitcode ("mov","r3,#!constbyte",0xff);
12711 emitcode ("","!tlabeldef",lbl->key+100);
12712 /* we don't care about the pointer : we just save the handle */
12713 rsym = OP_SYMBOL(IC_RESULT(ic));
12714 if (rsym->liveFrom != rsym->liveTo) {
12715 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12716 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12717 emitcode ("push","ar3");
12718 emitcode ("push","ar2");
12719 emitcode ("pop","%s",
12720 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12721 emitcode ("pop","%s",
12722 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12724 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12725 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12727 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12729 unsavermask(rsave);
12732 /*-----------------------------------------------------------------*/
12734 /*-----------------------------------------------------------------*/
12735 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12740 assert (nparms == 1);
12741 /* save registers that need to be saved */
12742 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12743 ds390_rUmaskForOp (IC_RESULT(ic))));
12746 aopOp (handle,ic,FALSE,FALSE);
12748 /* put the size in R4-R2 */
12749 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12750 emitcode("push","%s",
12751 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12752 emitcode("push","%s",
12753 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12754 emitcode("pop","ar3");
12755 emitcode("pop","ar2");
12757 emitcode ("mov","r2,%s",
12758 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12759 emitcode ("mov","r3,%s",
12760 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12762 freeAsmop (handle, NULL, ic, FALSE);
12764 /* make the call */
12765 emitcode ("lcall","MM_Deref");
12768 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12769 if (rsym->liveFrom != rsym->liveTo) {
12770 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12771 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12772 _startLazyDPSEvaluation ();
12774 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12775 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12776 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12778 _endLazyDPSEvaluation ();
12783 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12784 unsavermask(rsave);
12787 /*-----------------------------------------------------------------*/
12788 /* genMMUnrestrictedPersist - */
12789 /*-----------------------------------------------------------------*/
12790 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12795 assert (nparms == 1);
12796 /* save registers that need to be saved */
12797 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12798 ds390_rUmaskForOp (IC_RESULT(ic))));
12801 aopOp (handle,ic,FALSE,FALSE);
12803 /* put the size in R3-R2 */
12804 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12805 emitcode("push","%s",
12806 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12807 emitcode("push","%s",
12808 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12809 emitcode("pop","ar3");
12810 emitcode("pop","ar2");
12812 emitcode ("mov","r2,%s",
12813 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12814 emitcode ("mov","r3,%s",
12815 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12817 freeAsmop (handle, NULL, ic, FALSE);
12819 /* make the call */
12820 emitcode ("lcall","MM_UnrestrictedPersist");
12823 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12824 if (rsym->liveFrom != rsym->liveTo) {
12825 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12826 aopPut(AOP(IC_RESULT(ic)),"a",0);
12827 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12830 unsavermask(rsave);
12833 /*-----------------------------------------------------------------*/
12834 /* genSystemExecJavaProcess - */
12835 /*-----------------------------------------------------------------*/
12836 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12839 operand *handle, *pp;
12841 assert (nparms==2);
12842 /* save registers that need to be saved */
12843 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12844 ds390_rUmaskForOp (IC_RESULT(ic))));
12849 /* put the handle in R3-R2 */
12850 aopOp (handle,ic,FALSE,FALSE);
12851 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12852 emitcode("push","%s",
12853 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12854 emitcode("push","%s",
12855 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12856 emitcode("pop","ar3");
12857 emitcode("pop","ar2");
12859 emitcode ("mov","r2,%s",
12860 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12861 emitcode ("mov","r3,%s",
12862 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12864 freeAsmop (handle, NULL, ic, FALSE);
12866 /* put pointer in DPTR */
12867 aopOp (pp,ic,FALSE,FALSE);
12868 if (AOP_TYPE(pp) == AOP_IMMD) {
12869 emitcode ("mov", "dptr,%s",
12870 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12871 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12872 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12873 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12874 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12876 freeAsmop (handle, NULL, ic, FALSE);
12878 /* make the call */
12879 emitcode ("lcall","System_ExecJavaProcess");
12881 /* put result in place */
12883 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12884 if (rsym->liveFrom != rsym->liveTo) {
12885 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12886 aopPut(AOP(IC_RESULT(ic)),"a",0);
12887 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12891 unsavermask(rsave);
12894 /*-----------------------------------------------------------------*/
12895 /* genSystemRTCRegisters - */
12896 /*-----------------------------------------------------------------*/
12897 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12903 assert (nparms==1);
12904 /* save registers that need to be saved */
12905 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12906 ds390_rUmaskForOp (IC_RESULT(ic))));
12909 /* put pointer in DPTR */
12910 aopOp (pp,ic,FALSE,FALSE);
12911 if (AOP_TYPE (pp) == AOP_IMMD) {
12912 emitcode ("mov","dps,#1");
12913 emitcode ("mov", "dptr,%s",
12914 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12915 emitcode ("mov","dps,#0");
12917 emitcode ("mov","dpl1,%s",
12918 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12919 emitcode ("mov","dph1,%s",
12920 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12921 emitcode ("mov","dpx1,%s",
12922 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12924 freeAsmop (pp, NULL, ic, FALSE);
12926 /* make the call */
12927 emitcode ("lcall","System_%sRTCRegisters",name);
12929 unsavermask(rsave);
12932 /*-----------------------------------------------------------------*/
12933 /* genSystemThreadSleep - */
12934 /*-----------------------------------------------------------------*/
12935 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12940 assert (nparms==1);
12941 /* save registers that need to be saved */
12942 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12943 ds390_rUmaskForOp (IC_RESULT(ic))));
12946 aopOp(to,ic,FALSE,FALSE);
12947 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12948 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12949 emitcode ("push","%s",
12950 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12951 emitcode ("push","%s",
12952 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12953 emitcode ("push","%s",
12954 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12955 emitcode ("push","%s",
12956 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12957 emitcode ("pop","ar3");
12958 emitcode ("pop","ar2");
12959 emitcode ("pop","ar1");
12960 emitcode ("pop","ar0");
12962 emitcode ("mov","r0,%s",
12963 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12964 emitcode ("mov","r1,%s",
12965 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12966 emitcode ("mov","r2,%s",
12967 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12968 emitcode ("mov","r3,%s",
12969 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12971 freeAsmop (to, NULL, ic, FALSE);
12973 /* suspend in acc */
12975 aopOp(s,ic,FALSE,FALSE);
12976 emitcode ("mov","a,%s",
12977 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12978 freeAsmop (s, NULL, ic, FALSE);
12980 /* make the call */
12981 emitcode ("lcall","System_%s",name);
12983 unsavermask(rsave);
12986 /*-----------------------------------------------------------------*/
12987 /* genSystemThreadResume - */
12988 /*-----------------------------------------------------------------*/
12989 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12994 assert (nparms==2);
12995 /* save registers that need to be saved */
12996 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12997 ds390_rUmaskForOp (IC_RESULT(ic))));
13003 aopOp(pid,ic,FALSE,FALSE);
13004 emitcode ("mov","r0,%s",
13005 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13006 freeAsmop (pid, NULL, ic, FALSE);
13009 aopOp(tid,ic,FALSE,FALSE);
13010 emitcode ("mov","a,%s",
13011 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13012 freeAsmop (tid, NULL, ic, FALSE);
13014 emitcode ("lcall","System_ThreadResume");
13016 /* put result into place */
13018 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13019 if (rsym->liveFrom != rsym->liveTo) {
13020 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13021 aopPut(AOP(IC_RESULT(ic)),"a",0);
13022 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13025 unsavermask(rsave);
13028 /*-----------------------------------------------------------------*/
13029 /* genSystemProcessResume - */
13030 /*-----------------------------------------------------------------*/
13031 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13036 assert (nparms==1);
13037 /* save registers that need to be saved */
13038 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13039 ds390_rUmaskForOp (IC_RESULT(ic))));
13044 aopOp(pid,ic,FALSE,FALSE);
13045 emitcode ("mov","a,%s",
13046 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13047 freeAsmop (pid, NULL, ic, FALSE);
13049 emitcode ("lcall","System_ProcessResume");
13051 unsavermask(rsave);
13054 /*-----------------------------------------------------------------*/
13056 /*-----------------------------------------------------------------*/
13057 static void genSystem (iCode *ic,int nparms,char *name)
13059 assert(nparms == 0);
13061 emitcode ("lcall","System_%s",name);
13064 /*-----------------------------------------------------------------*/
13065 /* genSystemPoll - */
13066 /*-----------------------------------------------------------------*/
13067 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13072 assert (nparms==1);
13073 /* save registers that need to be saved */
13074 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13075 ds390_rUmaskForOp (IC_RESULT(ic))));
13078 aopOp (fp,ic,FALSE,FALSE);
13079 if (AOP_TYPE (fp) == AOP_IMMD) {
13080 emitcode ("mov", "dptr,%s",
13081 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13082 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13083 emitcode ("mov","dpl,%s",
13084 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13085 emitcode ("mov","dph,%s",
13086 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13087 emitcode ("mov","dpx,%s",
13088 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13090 freeAsmop (fp, NULL, ic, FALSE);
13092 emitcode ("lcall","System_%sPoll",name);
13094 /* put result into place */
13096 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13097 if (rsym->liveFrom != rsym->liveTo) {
13098 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13099 aopPut(AOP(IC_RESULT(ic)),"a",0);
13100 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13103 unsavermask(rsave);
13106 /*-----------------------------------------------------------------*/
13107 /* genSystemGetCurrentID - */
13108 /*-----------------------------------------------------------------*/
13109 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13111 assert (nparms==0);
13113 emitcode ("lcall","System_GetCurrent%sId",name);
13114 /* put result into place */
13116 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13117 if (rsym->liveFrom != rsym->liveTo) {
13118 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13119 aopPut(AOP(IC_RESULT(ic)),"a",0);
13120 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13125 /*-----------------------------------------------------------------*/
13126 /* genDummyRead - generate code for dummy read of volatiles */
13127 /*-----------------------------------------------------------------*/
13129 genDummyRead (iCode * ic)
13134 D(emitcode("; genDummyRead",""));
13136 op = IC_RIGHT (ic);
13137 if (op && IS_SYMOP (op))
13139 aopOp (op, ic, FALSE, FALSE);
13141 /* if the result is a bit */
13142 if (AOP_TYPE (op) == AOP_CRY)
13143 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13146 /* bit variables done */
13148 size = AOP_SIZE (op);
13152 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13157 freeAsmop (op, NULL, ic, TRUE);
13161 if (op && IS_SYMOP (op))
13163 aopOp (op, ic, FALSE, FALSE);
13165 /* if the result is a bit */
13166 if (AOP_TYPE (op) == AOP_CRY)
13167 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13170 /* bit variables done */
13172 size = AOP_SIZE (op);
13176 MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13181 freeAsmop (op, NULL, ic, TRUE);
13186 /*-----------------------------------------------------------------*/
13187 /* genCritical - generate code for start of a critical sequence */
13188 /*-----------------------------------------------------------------*/
13190 genCritical (iCode *ic)
13192 symbol *tlbl = newiTempLabel (NULL);
13194 D(emitcode("; genCritical",""));
13196 if (IC_RESULT (ic))
13197 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13199 emitcode ("setb", "c");
13200 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13201 emitcode ("clr", "c");
13202 emitcode ("", "%05d$:", (tlbl->key + 100));
13204 if (IC_RESULT (ic))
13205 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13207 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13209 if (IC_RESULT (ic))
13210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13213 /*-----------------------------------------------------------------*/
13214 /* genEndCritical - generate code for end of a critical sequence */
13215 /*-----------------------------------------------------------------*/
13217 genEndCritical (iCode *ic)
13219 D(emitcode("; genEndCritical",""));
13223 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13224 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13226 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13227 emitcode ("mov", "ea,c");
13231 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13232 emitcode ("rrc", "a");
13233 emitcode ("mov", "ea,c");
13235 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13239 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13240 emitcode ("mov", "ea,c");
13246 /*-----------------------------------------------------------------*/
13247 /* genBuiltIn - calls the appropriate function to generating code */
13248 /* for a built in function */
13249 /*-----------------------------------------------------------------*/
13250 static void genBuiltIn (iCode *ic)
13252 operand *bi_parms[MAX_BUILTIN_ARGS];
13257 /* get all the arguments for a built in function */
13258 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13260 /* which function is it */
13261 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13262 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13263 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13264 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13265 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13266 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13267 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13268 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13269 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13270 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13271 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13272 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13273 genInp(bi_iCode,nbi_parms,bi_parms);
13274 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13275 genOutp(bi_iCode,nbi_parms,bi_parms);
13276 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13277 genSwapW(bi_iCode,nbi_parms,bi_parms);
13278 /* JavaNative builtIns */
13279 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13280 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13281 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13282 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13283 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13284 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13285 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13286 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13287 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13288 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13289 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13290 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13291 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13292 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13293 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13294 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13295 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13296 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13297 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13298 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13299 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13300 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13301 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13302 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13303 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13304 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13305 } else if (strcmp(bif->name,"MM_Free")==0) {
13306 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13307 } else if (strcmp(bif->name,"MM_Deref")==0) {
13308 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13309 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13310 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13311 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13312 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13313 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13314 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13315 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13316 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13317 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13318 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13319 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13320 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13321 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13322 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13323 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13324 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13325 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13326 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13327 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13328 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13329 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13330 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13331 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13332 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13333 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13334 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13335 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13336 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13337 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13338 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13339 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13340 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13341 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13342 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13343 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13344 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13345 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13346 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13347 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13348 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13350 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13356 /*-----------------------------------------------------------------*/
13357 /* gen390Code - generate code for Dallas 390 based controllers */
13358 /*-----------------------------------------------------------------*/
13360 gen390Code (iCode * lic)
13365 lineHead = lineCurr = NULL;
13366 dptrn[1][0] = "dpl1";
13367 dptrn[1][1] = "dph1";
13368 dptrn[1][2] = "dpx1";
13370 if (options.model == MODEL_FLAT24) {
13371 fReturnSizeDS390 = 5;
13372 fReturn = fReturn24;
13374 fReturnSizeDS390 = 4;
13375 fReturn = fReturn16;
13376 options.stack10bit=0;
13379 /* print the allocation information */
13380 if (allocInfo && currFunc)
13381 printAllocInfo (currFunc, codeOutFile);
13383 /* if debug information required */
13384 if (options.debug && currFunc)
13386 debugFile->writeFunction(currFunc);
13388 if (IS_STATIC (currFunc->etype))
13389 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13391 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13394 /* stack pointer name */
13395 if (options.useXstack)
13401 for (ic = lic; ic; ic = ic->next)
13404 _G.current_iCode = ic;
13406 if (ic->lineno && cln != ic->lineno)
13411 emitcode ("", "C$%s$%d$%d$%d ==.",
13412 FileBaseName (ic->filename), ic->lineno,
13413 ic->level, ic->block);
13416 if (!options.noCcodeInAsm) {
13417 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13418 printCLine(ic->filename, ic->lineno));
13422 if (options.iCodeInAsm) {
13423 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13425 /* if the result is marked as
13426 spilt and rematerializable or code for
13427 this has already been generated then
13429 if (resultRemat (ic) || ic->generated)
13432 /* depending on the operation */
13452 /* IPOP happens only when trying to restore a
13453 spilt live range, if there is an ifx statement
13454 following this pop then the if statement might
13455 be using some of the registers being popped which
13456 would destory the contents of the register so
13457 we need to check for this condition and handle it */
13459 ic->next->op == IFX &&
13460 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13461 genIfx (ic->next, ic);
13479 genEndFunction (ic);
13499 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13516 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13520 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13527 /* note these two are xlated by algebraic equivalence
13528 during parsing SDCC.y */
13529 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13530 "got '>=' or '<=' shouldn't have come here");
13534 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13546 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13550 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13554 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13578 genRightShift (ic);
13581 case GET_VALUE_AT_ADDRESS:
13582 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13586 if (POINTER_SET (ic))
13587 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13613 if (ic->builtinSEND) genBuiltIn(ic);
13614 else addSet (&_G.sendSet, ic);
13617 case DUMMY_READ_VOLATILE:
13626 genEndCritical (ic);
13633 #if 0 // obsolete, and buggy for != xdata
13645 /* now we are ready to call the
13646 peep hole optimizer */
13647 if (!options.nopeep)
13648 peepHole (&lineHead);
13650 /* now do the actual printing */
13651 printLine (lineHead, codeOutFile);