1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
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)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
75 short r0InB : 2;//2 so we can see it overflow
76 short r1InB : 2;//2 so we can see it overflow
77 short OpInB : 2;//2 so we can see it overflow
91 static char *rb1regs[] = {
92 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
95 extern int mcs51_ptrRegReq;
96 extern int mcs51_nRegs;
97 extern FILE *codeOutFile;
98 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, const char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
140 SNPRINTF (lb, sizeof(lb), "%s", inst);
141 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
144 tvsprintf (lb, sizeof(lb), fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
155 lineCurr->ic = _G.current_iCode;
156 lineCurr->isComment = (*lbp==';');
160 /*-----------------------------------------------------------------*/
161 /* mcs51_emitDebuggerSymbol - associate the current code location */
162 /* with a debugger symbol */
163 /*-----------------------------------------------------------------*/
165 mcs51_emitDebuggerSymbol (char * debugSym)
168 emitcode ("", "%s ==.", debugSym);
172 /*-----------------------------------------------------------------*/
173 /* mova - moves specified value into accumulator */
174 /*-----------------------------------------------------------------*/
178 /* do some early peephole optimization */
179 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
182 emitcode("mov","a,%s", x);
185 /*-----------------------------------------------------------------*/
186 /* pushB - saves register B if necessary */
187 /*-----------------------------------------------------------------*/
191 bool pushedB = FALSE;
195 emitcode ("push", "b");
196 // printf("B was in use !\n");
206 /*-----------------------------------------------------------------*/
207 /* popB - restores value of register B if necessary */
208 /*-----------------------------------------------------------------*/
214 emitcode ("pop", "b");
222 /*-----------------------------------------------------------------*/
223 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
224 /*-----------------------------------------------------------------*/
226 getFreePtr (iCode * ic, asmop ** aopp, bool result)
231 /* the logic: if r0 & r1 used in the instruction
232 then we are in trouble otherwise */
234 /* first check if r0 & r1 are used by this
235 instruction, in which case we are in trouble */
236 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
237 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
242 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
243 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
245 /* if no usage of r0 then return it */
248 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
249 (*aopp)->type = AOP_R0;
251 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
254 /* if no usage of r1 then return it */
257 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
258 (*aopp)->type = AOP_R1;
260 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
263 /* now we know they both have usage */
264 /* if r0 not used in this instruction */
267 /* push it if not already pushed */
270 emitcode ("mov", "b,%s",
271 mcs51_regWithIdx (R0_IDX)->dname);
274 else if (!_G.r0Pushed)
276 emitcode ("push", "%s",
277 mcs51_regWithIdx (R0_IDX)->dname);
281 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
282 (*aopp)->type = AOP_R0;
284 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
287 /* if r1 not used then */
291 /* push it if not already pushed */
294 emitcode ("mov", "b,%s",
295 mcs51_regWithIdx (R1_IDX)->dname);
298 else if (!_G.r1Pushed)
300 emitcode ("push", "%s",
301 mcs51_regWithIdx (R1_IDX)->dname);
305 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
306 (*aopp)->type = AOP_R1;
307 return mcs51_regWithIdx (R1_IDX);
310 /* I said end of world, but not quite end of world yet */
312 /* we can push it on the stack */
313 (*aopp)->type = AOP_STK;
316 /* in the case that result AND left AND right needs a pointer reg
317 we can safely use the result's */
318 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
319 (*aopp)->type = AOP_R0;
320 return mcs51_regWithIdx (R0_IDX);
322 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
323 (*aopp)->type = AOP_R1;
324 return mcs51_regWithIdx (R1_IDX);
328 /* now this is REALLY the end of the world */
329 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
330 "getFreePtr should never reach here");
335 /*-----------------------------------------------------------------*/
336 /* getTempRegs - initialize an array of pointers to GPR registers */
337 /* that are not in use. Returns 1 if the requested */
338 /* number of registers were available, 0 otherwise. */
339 /*-----------------------------------------------------------------*/
341 getTempRegs(regs **tempRegs, int size, iCode *ic)
348 ic = _G.current_iCode;
354 freeRegs = newBitVect(8);
355 bitVectSetBit (freeRegs, R2_IDX);
356 bitVectSetBit (freeRegs, R3_IDX);
357 bitVectSetBit (freeRegs, R4_IDX);
358 bitVectSetBit (freeRegs, R5_IDX);
359 bitVectSetBit (freeRegs, R6_IDX);
360 bitVectSetBit (freeRegs, R7_IDX);
362 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
364 bitVect * newfreeRegs;
365 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
366 freeBitVect(freeRegs);
367 freeRegs = newfreeRegs;
369 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
372 for (i=0; i<freeRegs->size; i++)
374 if (bitVectBitValue(freeRegs,i))
375 tempRegs[offset++] = mcs51_regWithIdx(i);
378 freeBitVect(freeRegs);
383 freeBitVect(freeRegs);
388 /*-----------------------------------------------------------------*/
389 /* newAsmop - creates a new asmOp */
390 /*-----------------------------------------------------------------*/
392 newAsmop (short type)
396 aop = Safe_calloc (1, sizeof (asmop));
401 /*-----------------------------------------------------------------*/
402 /* pointerCode - returns the code for a pointer type */
403 /*-----------------------------------------------------------------*/
405 pointerCode (sym_link * etype)
408 return PTR_TYPE (SPEC_OCLS (etype));
412 /*-----------------------------------------------------------------*/
413 /* leftRightUseAcc - returns size of accumulator use by operands */
414 /*-----------------------------------------------------------------*/
416 leftRightUseAcc(iCode *ic)
425 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
426 "null iCode pointer");
433 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
436 size = getSize (OP_SYMBOL (op)->type);
441 else if (ic->op == JUMPTABLE)
444 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
447 size = getSize (OP_SYMBOL (op)->type);
455 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
458 size = getSize (OP_SYMBOL (op)->type);
463 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
466 size = getSize (OP_SYMBOL (op)->type);
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol */
480 /*-----------------------------------------------------------------*/
482 aopForSym (iCode * ic, symbol * sym, bool result)
487 wassertl (ic != NULL, "Got a null iCode");
488 wassertl (sym != NULL, "Got a null symbol");
490 space = SPEC_OCLS (sym->etype);
492 /* if already has one */
496 /* assign depending on the storage class */
497 /* if it is on the stack or indirectly addressable */
498 /* space we need to assign either r0 or r1 to it */
499 if (sym->onStack || sym->iaccess)
501 sym->aop = aop = newAsmop (0);
502 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
503 aop->size = getSize (sym->type);
505 /* now assign the address of the variable to
506 the pointer register */
507 if (aop->type != AOP_STK)
512 if (_G.accInUse || leftRightUseAcc (ic))
513 emitcode ("push", "acc");
515 emitcode ("mov", "a,_bp");
516 emitcode ("add", "a,#0x%02x",
518 ((char) (sym->stack - _G.nRegsSaved)) :
519 ((char) sym->stack)) & 0xff);
520 emitcode ("mov", "%s,a",
521 aop->aopu.aop_ptr->name);
523 if (_G.accInUse || leftRightUseAcc (ic))
524 emitcode ("pop", "acc");
527 emitcode ("mov", "%s,#%s",
528 aop->aopu.aop_ptr->name,
530 aop->paged = space->paged;
533 aop->aopu.aop_stk = sym->stack;
537 /* if in bit space */
538 if (IN_BITSPACE (space))
540 sym->aop = aop = newAsmop (AOP_CRY);
541 aop->aopu.aop_dir = sym->rname;
542 aop->size = getSize (sym->type);
545 /* if it is in direct space */
546 if (IN_DIRSPACE (space))
548 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
549 //printTypeChainRaw(sym->type, NULL);
550 //printf("space = %s\n", space ? space->sname : "NULL");
551 sym->aop = aop = newAsmop (AOP_DIR);
552 aop->aopu.aop_dir = sym->rname;
553 aop->size = getSize (sym->type);
557 /* special case for a function */
558 if (IS_FUNC (sym->type))
560 sym->aop = aop = newAsmop (AOP_IMMD);
561 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
562 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
563 aop->size = FPTRSIZE;
567 /* only remaining is far space */
568 /* in which case DPTR gets the address */
569 sym->aop = aop = newAsmop (AOP_DPTR);
570 emitcode ("mov", "dptr,#%s", sym->rname);
571 aop->size = getSize (sym->type);
573 /* if it is in code space */
574 if (IN_CODESPACE (space))
580 /*-----------------------------------------------------------------*/
581 /* aopForRemat - rematerialzes an object */
582 /*-----------------------------------------------------------------*/
584 aopForRemat (symbol * sym)
586 iCode *ic = sym->rematiCode;
587 asmop *aop = newAsmop (AOP_IMMD);
594 val += (int) operandLitValue (IC_RIGHT (ic));
595 else if (ic->op == '-')
596 val -= (int) operandLitValue (IC_RIGHT (ic));
597 else if (IS_CAST_ICODE(ic)) {
598 sym_link *from_type = operandType(IC_RIGHT(ic));
599 aop->aopu.aop_immd.from_cast_remat = 1;
600 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
601 ptr_type = DCL_TYPE(from_type);
602 if (ptr_type == IPOINTER) {
609 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
613 sprintf (buffer, "(%s %c 0x%04x)",
614 OP_SYMBOL (IC_LEFT (ic))->rname,
615 val >= 0 ? '+' : '-',
618 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
620 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
621 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
622 /* set immd2 field if required */
623 if (aop->aopu.aop_immd.from_cast_remat) {
624 sprintf(buffer,"#0x%02x",ptr_type);
625 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
626 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
632 /*-----------------------------------------------------------------*/
633 /* regsInCommon - two operands have some registers in common */
634 /*-----------------------------------------------------------------*/
636 regsInCommon (operand * op1, operand * op2)
641 /* if they have registers in common */
642 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645 sym1 = OP_SYMBOL (op1);
646 sym2 = OP_SYMBOL (op2);
648 if (sym1->nRegs == 0 || sym2->nRegs == 0)
651 for (i = 0; i < sym1->nRegs; i++)
657 for (j = 0; j < sym2->nRegs; j++)
662 if (sym2->regs[j] == sym1->regs[i])
670 /*-----------------------------------------------------------------*/
671 /* operandsEqu - equivalent */
672 /*-----------------------------------------------------------------*/
674 operandsEqu (operand * op1, operand * op2)
678 /* if they're not symbols */
679 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
682 sym1 = OP_SYMBOL (op1);
683 sym2 = OP_SYMBOL (op2);
685 /* if both are itemps & one is spilt
686 and the other is not then false */
687 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
688 sym1->isspilt != sym2->isspilt)
691 /* if they are the same */
695 /* if they have the same rname */
696 if (sym1->rname[0] && sym2->rname[0]
697 && strcmp (sym1->rname, sym2->rname) == 0)
700 /* if left is a tmp & right is not */
701 if (IS_ITEMP (op1) &&
704 (sym1->usl.spillLoc == sym2))
707 if (IS_ITEMP (op2) &&
711 (sym2->usl.spillLoc == sym1))
717 /*-----------------------------------------------------------------*/
718 /* sameRegs - two asmops have the same registers */
719 /*-----------------------------------------------------------------*/
721 sameRegs (asmop * aop1, asmop * aop2)
728 if (aop1->type != AOP_REG ||
729 aop2->type != AOP_REG)
732 if (aop1->size != aop2->size)
735 for (i = 0; i < aop1->size; i++)
736 if (aop1->aopu.aop_reg[i] !=
737 aop2->aopu.aop_reg[i])
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand : */
745 /*-----------------------------------------------------------------*/
747 aopOp (operand * op, iCode * ic, bool result)
756 /* if this a literal */
757 if (IS_OP_LITERAL (op))
759 op->aop = aop = newAsmop (AOP_LIT);
760 aop->aopu.aop_lit = op->operand.valOperand;
761 aop->size = getSize (operandType (op));
765 /* if already has a asmop then continue */
769 /* if the underlying symbol has a aop */
770 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
772 op->aop = OP_SYMBOL (op)->aop;
776 /* if this is a true symbol */
777 if (IS_TRUE_SYMOP (op))
779 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
783 /* this is a temporary : this has
789 e) can be a return use only */
791 sym = OP_SYMBOL (op);
793 /* if the type is a conditional */
794 if (sym->regType == REG_CND)
796 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
801 /* if it is spilt then two situations
803 b) has a spill location */
804 if (sym->isspilt || sym->nRegs == 0)
807 /* rematerialize it NOW */
810 sym->aop = op->aop = aop =
812 aop->size = getSize (sym->type);
819 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
820 aop->size = getSize (sym->type);
821 for (i = 0; i < 2; i++)
822 aop->aopu.aop_str[i] = accUse[i];
830 aop = op->aop = sym->aop = newAsmop (AOP_STR);
831 aop->size = getSize (sym->type);
832 for (i = 0; i < fReturnSizeMCS51; i++)
833 aop->aopu.aop_str[i] = fReturn[i];
837 if (sym->usl.spillLoc)
839 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
841 /* force a new aop if sizes differ */
842 sym->usl.spillLoc->aop = NULL;
844 sym->aop = op->aop = aop =
845 aopForSym (ic, sym->usl.spillLoc, result);
846 aop->size = getSize (sym->type);
850 /* else must be a dummy iTemp */
851 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
852 aop->size = getSize (sym->type);
856 /* must be in a register */
857 sym->aop = op->aop = aop = newAsmop (AOP_REG);
858 aop->size = sym->nRegs;
859 for (i = 0; i < sym->nRegs; i++)
860 aop->aopu.aop_reg[i] = sym->regs[i];
863 /*-----------------------------------------------------------------*/
864 /* freeAsmop - free up the asmop given to an operand */
865 /*----------------------------------------------------------------*/
867 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
884 /* depending on the asmop type only three cases need work AOP_RO
885 , AOP_R1 && AOP_STK */
891 emitcode ("mov", "r0,b");
894 else if (_G.r0Pushed)
898 emitcode ("pop", "ar0");
902 bitVectUnSetBit (ic->rUsed, R0_IDX);
908 emitcode ("mov", "r1,b");
915 emitcode ("pop", "ar1");
919 bitVectUnSetBit (ic->rUsed, R1_IDX);
925 int stk = aop->aopu.aop_stk + aop->size - 1;
926 bitVectUnSetBit (ic->rUsed, R0_IDX);
927 bitVectUnSetBit (ic->rUsed, R1_IDX);
929 getFreePtr (ic, &aop, FALSE);
933 emitcode ("mov", "a,_bp");
934 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
935 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
939 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
944 emitcode ("pop", "acc");
945 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
948 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 freeAsmop (op, NULL, ic, TRUE);
954 emitcode ("pop", "ar1");
960 emitcode ("pop", "ar0");
967 /* all other cases just dealloc */
973 OP_SYMBOL (op)->aop = NULL;
974 /* if the symbol has a spill */
976 SPIL_LOC (op)->aop = NULL;
981 /*------------------------------------------------------------------*/
982 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
983 /* pop r0 or r1 off stack if pushed */
984 /*------------------------------------------------------------------*/
986 freeForBranchAsmop (operand * op)
1006 emitcode ("mov", "r0,b");
1008 else if (_G.r0Pushed)
1010 emitcode ("pop", "ar0");
1017 emitcode ("mov", "r1,b");
1019 else if (_G.r1Pushed)
1021 emitcode ("pop", "ar1");
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1030 emitcode ("mov", "b,r0");
1033 emitcode ("mov", "a,_bp");
1034 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1035 emitcode ("mov", "r0,a");
1039 emitcode ("mov", "r0,_bp");
1044 emitcode ("pop", "acc");
1045 emitcode ("mov", "@r0,a");
1048 emitcode ("dec", "r0");
1050 emitcode ("mov", "r0,b");
1056 /*-----------------------------------------------------------------*/
1057 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1058 /* clobber the accumulator */
1059 /*-----------------------------------------------------------------*/
1061 aopGetUsesAcc (asmop *aop, int offset)
1063 if (offset > (aop->size - 1))
1081 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1090 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1096 /* Error case --- will have been caught already */
1102 /*-----------------------------------------------------------------*/
1103 /* aopGet - for fetching value of the aop */
1104 /*-----------------------------------------------------------------*/
1106 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1111 /* offset is greater than
1113 if (offset > (aop->size - 1) &&
1114 aop->type != AOP_LIT)
1117 /* depending on type */
1125 /* if we need to increment it */
1126 while (offset > aop->coff)
1128 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1132 while (offset < aop->coff)
1134 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1141 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1142 return (dname ? "acc" : "a");
1144 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1145 rs = Safe_calloc (1, strlen (s) + 1);
1150 if (aop->code && aop->coff==0 && offset>=1) {
1151 emitcode ("mov", "a,#0x%02x", offset);
1152 emitcode ("movc", "a,@a+dptr");
1153 return (dname ? "acc" : "a");
1156 while (offset > aop->coff)
1158 emitcode ("inc", "dptr");
1162 while (offset < aop->coff)
1164 emitcode ("lcall", "__decdptr");
1171 emitcode ("clr", "a");
1172 emitcode ("movc", "a,@a+dptr");
1176 emitcode ("movx", "a,@dptr");
1178 return (dname ? "acc" : "a");
1182 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1183 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1185 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1187 sprintf (s, "#(%s >> %d)",
1188 aop->aopu.aop_immd.aop_immd1,
1192 aop->aopu.aop_immd.aop_immd1);
1193 rs = Safe_calloc (1, strlen (s) + 1);
1199 sprintf (s, "(%s + %d)",
1203 sprintf (s, "%s", aop->aopu.aop_dir);
1204 rs = Safe_calloc (1, strlen (s) + 1);
1210 return aop->aopu.aop_reg[offset]->dname;
1212 return aop->aopu.aop_reg[offset]->name;
1215 emitcode ("clr", "a");
1216 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1217 emitcode ("rlc", "a");
1218 return (dname ? "acc" : "a");
1221 if (!offset && dname)
1223 return aop->aopu.aop_str[offset];
1226 return aopLiteral (aop->aopu.aop_lit, offset);
1230 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1234 return aop->aopu.aop_str[offset];
1238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1239 "aopget got unsupported aop->type");
1242 /*-----------------------------------------------------------------*/
1243 /* aopPut - puts a string for a aop */
1244 /*-----------------------------------------------------------------*/
1246 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1250 if (aop->size && offset > (aop->size - 1))
1252 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1253 "aopPut got offset > aop->size");
1257 /* will assign value to value */
1258 /* depending on where it is ofcourse */
1262 MOVA (s); /* read s in case it was volatile */
1267 sprintf (d, "(%s + %d)",
1268 aop->aopu.aop_dir, offset);
1270 sprintf (d, "%s", aop->aopu.aop_dir);
1272 if (strcmp (d, s) ||
1274 emitcode ("mov", "%s,%s", d, s);
1279 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1280 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1283 strcmp (s, "r0") == 0 ||
1284 strcmp (s, "r1") == 0 ||
1285 strcmp (s, "r2") == 0 ||
1286 strcmp (s, "r3") == 0 ||
1287 strcmp (s, "r4") == 0 ||
1288 strcmp (s, "r5") == 0 ||
1289 strcmp (s, "r6") == 0 ||
1290 strcmp (s, "r7") == 0)
1291 emitcode ("mov", "%s,%s",
1292 aop->aopu.aop_reg[offset]->dname, s);
1294 emitcode ("mov", "%s,%s",
1295 aop->aopu.aop_reg[offset]->name, s);
1302 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1303 "aopPut writing to code space");
1307 while (offset > aop->coff)
1310 emitcode ("inc", "dptr");
1313 while (offset < aop->coff)
1316 emitcode ("lcall", "__decdptr");
1321 /* if not in accumulater */
1324 emitcode ("movx", "@dptr,a");
1329 while (offset > aop->coff)
1332 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1334 while (offset < aop->coff)
1337 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1344 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1350 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1352 else if (strcmp (s, "r0") == 0 ||
1353 strcmp (s, "r1") == 0 ||
1354 strcmp (s, "r2") == 0 ||
1355 strcmp (s, "r3") == 0 ||
1356 strcmp (s, "r4") == 0 ||
1357 strcmp (s, "r5") == 0 ||
1358 strcmp (s, "r6") == 0 ||
1359 strcmp (s, "r7") == 0)
1362 sprintf (buffer, "a%s", s);
1363 emitcode ("mov", "@%s,%s",
1364 aop->aopu.aop_ptr->name, buffer);
1367 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1372 if (strcmp (s, "a") == 0)
1373 emitcode ("push", "acc");
1377 emitcode ("push", "acc");
1379 emitcode ("push", s);
1385 /* if bit variable */
1386 if (!aop->aopu.aop_dir)
1388 emitcode ("clr", "a");
1389 emitcode ("rlc", "a");
1394 emitcode ("clr", "%s", aop->aopu.aop_dir);
1396 emitcode ("setb", "%s", aop->aopu.aop_dir);
1397 else if (!strcmp (s, "c"))
1398 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1401 if (strcmp (s, "a"))
1406 /* set C, if a >= 1 */
1407 emitcode ("add", "a,#0xff");
1408 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1416 if (strcmp (aop->aopu.aop_str[offset], s) ||
1418 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1423 if (!offset && (strcmp (s, "acc") == 0) &&
1427 if (strcmp (aop->aopu.aop_str[offset], s) &&
1429 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1433 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1434 "aopPut got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* pointToEnd :- points to the last byte of the operand */
1444 /*-----------------------------------------------------------------*/
1446 pointToEnd (asmop * aop)
1452 aop->coff = count = (aop->size - 1);
1458 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1462 emitcode ("inc", "dptr");
1469 /*-----------------------------------------------------------------*/
1470 /* reAdjustPreg - points a register back to where it should */
1471 /*-----------------------------------------------------------------*/
1473 reAdjustPreg (asmop * aop)
1475 if ((aop->coff==0) || aop->size <= 1)
1483 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1488 emitcode ("lcall", "__decdptr");
1495 #define AOP(op) op->aop
1496 #define AOP_TYPE(op) AOP(op)->type
1497 #define AOP_SIZE(op) AOP(op)->size
1498 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1499 AOP_TYPE(x) == AOP_R0))
1501 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1502 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1504 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1505 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1506 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is */
1511 /* a generic pointer type. */
1512 /*-----------------------------------------------------------------*/
1514 opIsGptr (operand * op)
1516 sym_link *type = operandType (op);
1518 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size */
1527 /*-----------------------------------------------------------------*/
1529 getDataSize (operand * op)
1532 size = AOP_SIZE (op);
1533 if (size == GPTRSIZE)
1535 sym_link *type = operandType (op);
1536 if (IS_GENPTR (type))
1538 /* generic pointer; arithmetic operations
1539 * should ignore the high byte (pointer type).
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc */
1549 /*-----------------------------------------------------------------*/
1551 outAcc (operand * result)
1554 size = getDataSize (result);
1557 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1560 /* unsigned or positive */
1563 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C */
1570 /*-----------------------------------------------------------------*/
1572 outBitC (operand * result)
1574 /* if the result is bit */
1575 if (AOP_TYPE (result) == AOP_CRY)
1576 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1579 emitcode ("clr", "a");
1580 emitcode ("rlc", "a");
1585 /*-----------------------------------------------------------------*/
1586 /* toBoolean - emit code for orl a,operator(sizeop) */
1587 /*-----------------------------------------------------------------*/
1589 toBoolean (operand * oper)
1591 int size = AOP_SIZE (oper) - 1;
1593 bool AccUsed = FALSE;
1596 while (!AccUsed && size--)
1598 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1601 size = AOP_SIZE (oper) - 1;
1603 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1604 if (AccUsed && (AOP (oper)->type != AOP_ACC))
1607 emitcode("mov", "b,a");
1610 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1611 emitcode ("orl", "b,a");
1619 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1625 /*-----------------------------------------------------------------*/
1626 /* genNot - generate code for ! operation */
1627 /*-----------------------------------------------------------------*/
1633 D(emitcode ("; genNot",""));
1635 /* assign asmOps to operand & result */
1636 aopOp (IC_LEFT (ic), ic, FALSE);
1637 aopOp (IC_RESULT (ic), ic, TRUE);
1639 /* if in bit space then a special case */
1640 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1643 emitcode ("cpl", "c");
1644 outBitC (IC_RESULT (ic));
1648 toBoolean (IC_LEFT (ic));
1650 tlbl = newiTempLabel (NULL);
1651 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1652 emitcode ("", "%05d$:", tlbl->key + 100);
1653 outBitC (IC_RESULT (ic));
1656 /* release the aops */
1657 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genCpl - generate code for complement */
1664 /*-----------------------------------------------------------------*/
1672 D(emitcode ("; genCpl",""));
1674 /* assign asmOps to operand & result */
1675 aopOp (IC_LEFT (ic), ic, FALSE);
1676 aopOp (IC_RESULT (ic), ic, TRUE);
1678 /* special case if in bit space */
1679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1681 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1683 /* promotion rules are responsible for this strange result: */
1684 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1688 tlbl=newiTempLabel(NULL);
1689 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1690 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1691 IS_AOP_PREG (IC_LEFT (ic)))
1693 emitcode ("cjne", "%s,#0x01,%05d$",
1694 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1699 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1701 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1703 emitcode ("", "%05d$:", tlbl->key + 100);
1704 outBitC (IC_RESULT(ic));
1708 size = AOP_SIZE (IC_RESULT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1713 emitcode ("cpl", "a");
1714 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1719 /* release the aops */
1720 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 /*-----------------------------------------------------------------*/
1725 /* genUminusFloat - unary minus for floating points */
1726 /*-----------------------------------------------------------------*/
1728 genUminusFloat (operand * op, operand * result)
1730 int size, offset = 0;
1733 D(emitcode ("; genUminusFloat",""));
1735 /* for this we just copy and then flip the bit */
1737 size = AOP_SIZE (op) - 1;
1741 aopPut (AOP (result),
1742 aopGet (AOP (op), offset, FALSE, FALSE),
1744 isOperandVolatile (result, FALSE));
1748 l = aopGet (AOP (op), offset, FALSE, FALSE);
1752 emitcode ("cpl", "acc.7");
1753 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1756 /*-----------------------------------------------------------------*/
1757 /* genUminus - unary minus code generation */
1758 /*-----------------------------------------------------------------*/
1760 genUminus (iCode * ic)
1763 sym_link *optype, *rtype;
1766 D(emitcode ("; genUminus",""));
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1770 aopOp (IC_RESULT (ic), ic, TRUE);
1772 /* if both in bit space then special
1774 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1775 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1778 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1779 emitcode ("cpl", "c");
1780 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1784 optype = operandType (IC_LEFT (ic));
1785 rtype = operandType (IC_RESULT (ic));
1787 /* if float then do float stuff */
1788 if (IS_FLOAT (optype))
1790 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1794 /* otherwise subtract from zero */
1795 size = AOP_SIZE (IC_LEFT (ic));
1800 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1801 if (!strcmp (l, "a"))
1805 emitcode ("cpl", "a");
1806 emitcode ("addc", "a,#0");
1812 emitcode ("clr", "a");
1813 emitcode ("subb", "a,%s", l);
1815 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1818 /* if any remaining bytes in the result */
1819 /* we just need to propagate the sign */
1820 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1822 emitcode ("rlc", "a");
1823 emitcode ("subb", "a,acc");
1825 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1829 /* release the aops */
1830 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1834 /*-----------------------------------------------------------------*/
1835 /* saveRegisters - will look for a call and save the registers */
1836 /*-----------------------------------------------------------------*/
1838 saveRegisters (iCode * lic)
1845 for (ic = lic; ic; ic = ic->next)
1846 if (ic->op == CALL || ic->op == PCALL)
1851 fprintf (stderr, "found parameter push with no function call\n");
1855 /* if the registers have been saved already or don't need to be then
1859 if (IS_SYMOP(IC_LEFT(ic)) &&
1860 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1861 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1864 /* save the registers in use at this time but skip the
1865 ones for the result */
1866 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1867 mcs51_rUmaskForOp (IC_RESULT(ic)));
1870 if (options.useXstack)
1872 int count = bitVectnBitsOn (rsave);
1876 i = bitVectFirstBit (rsave);
1877 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1878 emitcode ("mov", "r0,%s", spname);
1879 emitcode ("inc", "%s", spname);// allocate before use
1880 emitcode ("movx", "@r0,a");
1881 if (bitVectBitValue (rsave, R0_IDX))
1882 emitcode ("mov", "r0,a");
1884 else if (count != 0)
1886 if (bitVectBitValue (rsave, R0_IDX))
1888 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1890 emitcode ("mov", "r0,%s", spname);
1892 emitcode ("add", "a,#%d", count);
1893 emitcode ("mov", "%s,a", spname);
1894 for (i = 0; i < mcs51_nRegs; i++)
1896 if (bitVectBitValue (rsave, i))
1900 emitcode ("pop", "acc");
1901 emitcode ("push", "acc");
1905 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1907 emitcode ("movx", "@r0,a");
1910 emitcode ("inc", "r0");
1914 if (bitVectBitValue (rsave, R0_IDX))
1916 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1921 for (i = 0; i < mcs51_nRegs; i++)
1923 if (bitVectBitValue (rsave, i))
1924 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1928 /*-----------------------------------------------------------------*/
1929 /* unsaveRegisters - pop the pushed registers */
1930 /*-----------------------------------------------------------------*/
1932 unsaveRegisters (iCode * ic)
1937 /* restore the registers in use at this time but skip the
1938 ones for the result */
1939 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1940 mcs51_rUmaskForOp (IC_RESULT(ic)));
1942 if (options.useXstack)
1944 int count = bitVectnBitsOn (rsave);
1948 emitcode ("mov", "r0,%s", spname);
1949 emitcode ("dec", "r0");
1950 emitcode ("movx", "a,@r0");
1951 i = bitVectFirstBit (rsave);
1952 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1953 emitcode ("dec", "%s", spname);
1957 emitcode ("mov", "r0,%s", spname);
1958 for (i = mcs51_nRegs; i >= 0; i--)
1960 if (bitVectBitValue (rsave, i))
1962 emitcode ("dec", "r0");
1963 emitcode ("movx", "a,@r0");
1965 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1968 emitcode ("mov", "%s,r0", spname);
1969 if (bitVectBitValue (rsave, R0_IDX))
1971 emitcode ("mov", "r0,a");
1976 for (i = mcs51_nRegs; i >= 0; i--)
1978 if (bitVectBitValue (rsave, i))
1979 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1984 /*-----------------------------------------------------------------*/
1986 /*-----------------------------------------------------------------*/
1988 pushSide (operand * oper, int size)
1993 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1994 if (AOP_TYPE (oper) != AOP_REG &&
1995 AOP_TYPE (oper) != AOP_DIR &&
1999 emitcode ("push", "acc");
2002 emitcode ("push", "%s", l);
2006 /*-----------------------------------------------------------------*/
2007 /* assignResultValue - */
2008 /*-----------------------------------------------------------------*/
2010 assignResultValue (operand * oper)
2013 int size = AOP_SIZE (oper);
2016 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2022 /*-----------------------------------------------------------------*/
2023 /* genXpush - pushes onto the external stack */
2024 /*-----------------------------------------------------------------*/
2026 genXpush (iCode * ic)
2028 asmop *aop = newAsmop (0);
2030 int size, offset = 0;
2032 D(emitcode ("; genXpush",""));
2034 aopOp (IC_LEFT (ic), ic, FALSE);
2035 r = getFreePtr (ic, &aop, FALSE);
2037 size = AOP_SIZE (IC_LEFT (ic));
2041 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2042 emitcode ("mov", "%s,%s", r->name, spname);
2043 emitcode ("inc", "%s", spname); // allocate space first
2044 emitcode ("movx", "@%s,a", r->name);
2048 // allocate space first
2049 emitcode ("mov", "%s,%s", r->name, spname);
2051 emitcode ("add", "a,#%d", size);
2052 emitcode ("mov", "%s,a", spname);
2056 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2057 emitcode ("movx", "@%s,a", r->name);
2058 emitcode ("inc", "%s", r->name);
2062 freeAsmop (NULL, aop, ic, TRUE);
2063 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2066 /*-----------------------------------------------------------------*/
2067 /* genIpush - genrate code for pushing this gets a little complex */
2068 /*-----------------------------------------------------------------*/
2070 genIpush (iCode * ic)
2072 int size, offset = 0;
2075 D(emitcode ("; genIpush",""));
2077 /* if this is not a parm push : ie. it is spill push
2078 and spill push is always done on the local stack */
2082 /* and the item is spilt then do nothing */
2083 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2086 aopOp (IC_LEFT (ic), ic, FALSE);
2087 size = AOP_SIZE (IC_LEFT (ic));
2088 /* push it on the stack */
2091 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2097 emitcode ("push", "%s", l);
2102 /* this is a paramter push: in this case we call
2103 the routine to find the call and save those
2104 registers that need to be saved */
2107 /* if use external stack then call the external
2108 stack pushing routine */
2109 if (options.useXstack)
2115 /* then do the push */
2116 aopOp (IC_LEFT (ic), ic, FALSE);
2118 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2119 size = AOP_SIZE (IC_LEFT (ic));
2123 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2124 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2125 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2129 emitcode ("push", "acc");
2132 emitcode ("push", "%s", l);
2135 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* genIpop - recover the registers: can happen only for spilling */
2140 /*-----------------------------------------------------------------*/
2142 genIpop (iCode * ic)
2146 D(emitcode ("; genIpop",""));
2148 /* if the temp was not pushed then */
2149 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2152 aopOp (IC_LEFT (ic), ic, FALSE);
2153 size = AOP_SIZE (IC_LEFT (ic));
2154 offset = (size - 1);
2156 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2159 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2162 /*-----------------------------------------------------------------*/
2163 /* saveRBank - saves an entire register bank on the stack */
2164 /*-----------------------------------------------------------------*/
2166 saveRBank (int bank, iCode * ic, bool pushPsw)
2169 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2173 if (options.useXstack)
2177 /* Assume r0 is available for use. */
2178 r = mcs51_regWithIdx (R0_IDX);;
2183 r = getFreePtr (ic, &aop, FALSE);
2185 // allocate space first
2186 emitcode ("mov", "%s,%s", r->name, spname);
2188 emitcode ("add", "a,#%d", count);
2189 emitcode ("mov", "%s,a", spname);
2192 for (i = 0; i < mcs51_nRegs; i++)
2194 if (options.useXstack)
2196 emitcode ("mov", "a,(%s+%d)",
2197 regs8051[i].base, 8 * bank + regs8051[i].offset);
2198 emitcode ("movx", "@%s,a", r->name);
2200 emitcode ("inc", "%s", r->name);
2203 emitcode ("push", "(%s+%d)",
2204 regs8051[i].base, 8 * bank + regs8051[i].offset);
2209 if (options.useXstack)
2211 emitcode ("mov", "a,psw");
2212 emitcode ("movx", "@%s,a", r->name);
2217 emitcode ("push", "psw");
2220 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2225 freeAsmop (NULL, aop, ic, TRUE);
2234 /*-----------------------------------------------------------------*/
2235 /* unsaveRBank - restores the register bank from stack */
2236 /*-----------------------------------------------------------------*/
2238 unsaveRBank (int bank, iCode * ic, bool popPsw)
2244 if (options.useXstack)
2248 /* Assume r0 is available for use. */
2249 r = mcs51_regWithIdx (R0_IDX);;
2254 r = getFreePtr (ic, &aop, FALSE);
2256 emitcode ("mov", "%s,%s", r->name, spname);
2261 if (options.useXstack)
2263 emitcode ("dec", "%s", r->name);
2264 emitcode ("movx", "a,@%s", r->name);
2265 emitcode ("mov", "psw,a");
2269 emitcode ("pop", "psw");
2273 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2275 if (options.useXstack)
2277 emitcode ("dec", "%s", r->name);
2278 emitcode ("movx", "a,@%s", r->name);
2279 emitcode ("mov", "(%s+%d),a",
2280 regs8051[i].base, 8 * bank + regs8051[i].offset);
2284 emitcode ("pop", "(%s+%d)",
2285 regs8051[i].base, 8 * bank + regs8051[i].offset);
2289 if (options.useXstack)
2291 emitcode ("mov", "%s,%s", spname, r->name);
2296 freeAsmop (NULL, aop, ic, TRUE);
2300 /*-----------------------------------------------------------------*/
2301 /* genSend - gen code for SEND */
2302 /*-----------------------------------------------------------------*/
2303 static void genSend(set *sendSet)
2308 for (sic = setFirstItem (sendSet); sic;
2309 sic = setNextItem (sendSet)) {
2310 int size, offset = 0;
2311 aopOp (IC_LEFT (sic), sic, FALSE);
2312 size = AOP_SIZE (IC_LEFT (sic));
2314 if (sic->argreg == 1) {
2316 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2318 if (strcmp (l, fReturn[offset]))
2319 emitcode ("mov", "%s,%s", fReturn[offset], l);
2325 emitcode ("mov","b1_%d,%s",rb1_count++,
2326 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2329 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2333 /*-----------------------------------------------------------------*/
2334 /* genCall - generates a call statement */
2335 /*-----------------------------------------------------------------*/
2337 genCall (iCode * ic)
2340 // bool restoreBank = FALSE;
2341 bool swapBanks = FALSE;
2343 D(emitcode("; genCall",""));
2345 dtype = operandType (IC_LEFT (ic));
2346 /* if send set is not empty then assign */
2349 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2350 genSend(reverseSet(_G.sendSet));
2352 genSend(_G.sendSet);
2358 /* if we are calling a not _naked function that is not using
2359 the same register bank then we need to save the
2360 destination registers on the stack */
2361 dtype = operandType (IC_LEFT (ic));
2362 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2363 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2364 !IFFUNC_ISISR (dtype))
2369 /* if caller saves & we have not saved then */
2375 emitcode ("mov", "psw,#0x%02x",
2376 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2380 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2381 OP_SYMBOL (IC_LEFT (ic))->rname :
2382 OP_SYMBOL (IC_LEFT (ic))->name));
2386 emitcode ("mov", "psw,#0x%02x",
2387 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2390 /* if we need assign a result value */
2391 if ((IS_ITEMP (IC_RESULT (ic)) &&
2392 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2393 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2394 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2395 IS_TRUE_SYMOP (IC_RESULT (ic)))
2399 aopOp (IC_RESULT (ic), ic, FALSE);
2402 assignResultValue (IC_RESULT (ic));
2404 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2407 /* adjust the stack for parameters if
2412 if (ic->parmBytes > 3)
2414 emitcode ("mov", "a,%s", spname);
2415 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2416 emitcode ("mov", "%s,a", spname);
2419 for (i = 0; i < ic->parmBytes; i++)
2420 emitcode ("dec", "%s", spname);
2423 /* if we hade saved some registers then unsave them */
2424 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2425 unsaveRegisters (ic);
2427 // /* if register bank was saved then pop them */
2429 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2432 /*-----------------------------------------------------------------*/
2433 /* -10l - generates a call by pointer statement */
2434 /*-----------------------------------------------------------------*/
2436 genPcall (iCode * ic)
2439 symbol *rlbl = newiTempLabel (NULL);
2440 // bool restoreBank=FALSE;
2441 bool swapBanks = FALSE;
2443 D(emitcode("; genPCall",""));
2445 /* if caller saves & we have not saved then */
2449 /* if we are calling a not _naked function that is not using
2450 the same register bank then we need to save the
2451 destination registers on the stack */
2452 dtype = operandType (IC_LEFT (ic))->next;
2453 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2454 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2455 !IFFUNC_ISISR (dtype))
2457 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2458 // restoreBank=TRUE;
2460 // need caution message to user here
2463 /* push the return address on to the stack */
2464 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2465 emitcode ("push", "acc");
2466 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2467 emitcode ("push", "acc");
2469 /* now push the calling address */
2470 aopOp (IC_LEFT (ic), ic, FALSE);
2472 pushSide (IC_LEFT (ic), FPTRSIZE);
2474 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2476 /* if send set is not empty the assign */
2479 genSend(reverseSet(_G.sendSet));
2485 emitcode ("mov", "psw,#0x%02x",
2486 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2490 emitcode ("ret", "");
2491 emitcode ("", "%05d$:", (rlbl->key + 100));
2496 emitcode ("mov", "psw,#0x%02x",
2497 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2500 /* if we need assign a result value */
2501 if ((IS_ITEMP (IC_RESULT (ic)) &&
2502 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2503 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2504 IS_TRUE_SYMOP (IC_RESULT (ic)))
2508 aopOp (IC_RESULT (ic), ic, FALSE);
2511 assignResultValue (IC_RESULT (ic));
2513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2516 /* adjust the stack for parameters if
2521 if (ic->parmBytes > 3)
2523 emitcode ("mov", "a,%s", spname);
2524 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2525 emitcode ("mov", "%s,a", spname);
2528 for (i = 0; i < ic->parmBytes; i++)
2529 emitcode ("dec", "%s", spname);
2533 // /* if register bank was saved then unsave them */
2535 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2537 /* if we hade saved some registers then
2539 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2540 unsaveRegisters (ic);
2543 /*-----------------------------------------------------------------*/
2544 /* resultRemat - result is rematerializable */
2545 /*-----------------------------------------------------------------*/
2547 resultRemat (iCode * ic)
2549 if (SKIP_IC (ic) || ic->op == IFX)
2552 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2554 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2555 if (sym->remat && !POINTER_SET (ic))
2562 #if defined(__BORLANDC__) || defined(_MSC_VER)
2563 #define STRCASECMP stricmp
2565 #define STRCASECMP strcasecmp
2568 /*-----------------------------------------------------------------*/
2569 /* inExcludeList - return 1 if the string is in exclude Reg list */
2570 /*-----------------------------------------------------------------*/
2572 regsCmp(void *p1, void *p2)
2574 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2578 inExcludeList (char *s)
2580 const char *p = setFirstItem(options.excludeRegsSet);
2582 if (p == NULL || STRCASECMP(p, "none") == 0)
2586 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2589 /*-----------------------------------------------------------------*/
2590 /* genFunction - generated code for function entry */
2591 /*-----------------------------------------------------------------*/
2593 genFunction (iCode * ic)
2595 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2597 bool switchedPSW = FALSE;
2598 int calleesaves_saved_register = -1;
2599 int stackAdjust = sym->stack;
2600 int accIsFree = sym->recvSize < 4;
2601 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2602 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2605 /* create the function header */
2606 emitcode (";", "-----------------------------------------");
2607 emitcode (";", " function %s", sym->name);
2608 emitcode (";", "-----------------------------------------");
2610 emitcode ("", "%s:", sym->rname);
2611 ftype = operandType (IC_LEFT (ic));
2612 _G.currentFunc = sym;
2614 if (IFFUNC_ISNAKED(ftype))
2616 emitcode(";", "naked function: no prologue.");
2620 /* here we need to generate the equates for the
2621 register bank if required */
2622 if (FUNC_REGBANK (ftype) != rbank)
2626 rbank = FUNC_REGBANK (ftype);
2627 for (i = 0; i < mcs51_nRegs; i++)
2629 if (strcmp (regs8051[i].base, "0") == 0)
2630 emitcode ("", "%s = 0x%02x",
2632 8 * rbank + regs8051[i].offset);
2634 emitcode ("", "%s = %s + 0x%02x",
2637 8 * rbank + regs8051[i].offset);
2641 /* if this is an interrupt service routine then
2642 save acc, b, dpl, dph */
2643 if (IFFUNC_ISISR (sym->type))
2646 if (!inExcludeList ("acc"))
2647 emitcode ("push", "acc");
2648 if (!inExcludeList ("b"))
2649 emitcode ("push", "b");
2650 if (!inExcludeList ("dpl"))
2651 emitcode ("push", "dpl");
2652 if (!inExcludeList ("dph"))
2653 emitcode ("push", "dph");
2654 /* if this isr has no bank i.e. is going to
2655 run with bank 0 , then we need to save more
2657 if (!FUNC_REGBANK (sym->type))
2660 /* if this function does not call any other
2661 function then we can be economical and
2662 save only those registers that are used */
2663 if (!IFFUNC_HASFCALL(sym->type))
2667 /* if any registers used */
2670 /* save the registers used */
2671 for (i = 0; i < sym->regsUsed->size; i++)
2673 if (bitVectBitValue (sym->regsUsed, i))
2674 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2681 /* this function has a function call. We cannot
2682 determines register usage so we will have to push the
2684 saveRBank (0, ic, FALSE);
2685 if (options.parms_in_bank1) {
2687 for (i=0; i < 8 ; i++ ) {
2688 emitcode ("push","%s",rb1regs[i]);
2695 /* This ISR uses a non-zero bank.
2697 * We assume that the bank is available for our
2700 * However, if this ISR calls a function which uses some
2701 * other bank, we must save that bank entirely.
2703 unsigned long banksToSave = 0;
2705 if (IFFUNC_HASFCALL(sym->type))
2708 #define MAX_REGISTER_BANKS 4
2713 for (i = ic; i; i = i->next)
2715 if (i->op == ENDFUNCTION)
2717 /* we got to the end OK. */
2725 dtype = operandType (IC_LEFT(i));
2727 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2729 /* Mark this bank for saving. */
2730 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2732 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2736 banksToSave |= (1 << FUNC_REGBANK(dtype));
2739 /* And note that we don't need to do it in
2747 /* This is a mess; we have no idea what
2748 * register bank the called function might
2751 * The only thing I can think of to do is
2752 * throw a warning and hope.
2754 werror(W_FUNCPTR_IN_USING_ISR);
2758 if (banksToSave && options.useXstack)
2760 /* Since we aren't passing it an ic,
2761 * saveRBank will assume r0 is available to abuse.
2763 * So switch to our (trashable) bank now, so
2764 * the caller's R0 isn't trashed.
2766 emitcode ("push", "psw");
2767 emitcode ("mov", "psw,#0x%02x",
2768 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2772 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2774 if (banksToSave & (1 << ix))
2776 saveRBank(ix, NULL, FALSE);
2780 // TODO: this needs a closer look
2781 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2784 /* Set the register bank to the desired value if nothing else */
2785 /* has done so yet. */
2788 emitcode ("push", "psw");
2789 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2794 /* This is a non-ISR function. The caller has already switched register */
2795 /* banks, if necessary, so just handle the callee-saves option. */
2797 /* if callee-save to be used for this function
2798 then save the registers being used in this function */
2799 if (IFFUNC_CALLEESAVES(sym->type))
2803 /* if any registers used */
2806 /* save the registers used */
2807 for (i = 0; i < sym->regsUsed->size; i++)
2809 if (bitVectBitValue (sym->regsUsed, i))
2811 /* remember one saved register for later usage */
2812 if (calleesaves_saved_register < 0)
2813 calleesaves_saved_register = i;
2814 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2825 if (options.useXstack)
2827 emitcode ("mov", "r0,%s", spname);
2828 emitcode ("inc", "%s", spname);
2829 emitcode ("xch", "a,_bp");
2830 emitcode ("movx", "@r0,a");
2831 emitcode ("inc", "r0");
2832 emitcode ("mov", "a,r0");
2833 emitcode ("xch", "a,_bp");
2837 /* set up the stack */
2838 emitcode ("push", "_bp"); /* save the callers stack */
2839 emitcode ("mov", "_bp,%s", spname);
2843 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2844 /* before setting up the stack frame completely. */
2845 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2847 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2851 if (rsym && rsym->regType == REG_CND)
2853 if (rsym && (rsym->accuse || rsym->ruonly))
2855 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2856 rsym = rsym->usl.spillLoc;
2859 /* If the RECEIVE operand immediately spills to the first entry on the */
2860 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2861 /* rather than the usual @r0/r1 machinations. */
2862 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2866 _G.current_iCode = ric;
2867 D(emitcode ("; genReceive",""));
2868 for (ofs=0; ofs < sym->recvSize; ofs++)
2870 if (!strcmp (fReturn[ofs], "a"))
2871 emitcode ("push", "acc");
2873 emitcode ("push", fReturn[ofs]);
2875 stackAdjust -= sym->recvSize;
2878 assert (stackAdjust>=0);
2881 _G.current_iCode = ic;
2885 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2886 /* to free up the accumulator. */
2887 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2891 _G.current_iCode = ric;
2892 D(emitcode ("; genReceive",""));
2893 for (ofs=0; ofs < sym->recvSize; ofs++)
2895 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2897 _G.current_iCode = ic;
2903 /* adjust the stack for the function */
2906 int i = stackAdjust;
2908 werror (W_STACK_OVERFLOW, sym->name);
2910 if (i > 3 && accIsFree)
2912 emitcode ("mov", "a,sp");
2913 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2914 emitcode ("mov", "sp,a");
2918 /* The accumulator is not free, so we will need another register */
2919 /* to clobber. No need to worry about a possible conflict with */
2920 /* the above early RECEIVE optimizations since they would have */
2921 /* freed the accumulator if they were generated. */
2923 if (IFFUNC_CALLEESAVES(sym->type))
2925 /* if it's a callee-saves function we need a saved register */
2926 if (calleesaves_saved_register >= 0)
2928 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2929 emitcode ("mov", "a,sp");
2930 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2931 emitcode ("mov", "sp,a");
2932 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2935 /* do it the hard way */
2937 emitcode ("inc", "sp");
2941 /* not callee-saves, we can clobber r0 */
2942 emitcode ("mov", "r0,a");
2943 emitcode ("mov", "a,sp");
2944 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2945 emitcode ("mov", "sp,a");
2946 emitcode ("mov", "a,r0");
2951 emitcode ("inc", "sp");
2956 char i = ((char) sym->xstack & 0xff);
2958 if (i > 3 && accIsFree)
2960 emitcode ("mov", "a,_spx");
2961 emitcode ("add", "a,#0x%02x", i);
2962 emitcode ("mov", "_spx,a");
2966 emitcode ("push", "acc");
2967 emitcode ("mov", "a,_spx");
2968 emitcode ("add", "a,#0x%02x", i);
2969 emitcode ("mov", "_spx,a");
2970 emitcode ("pop", "acc");
2975 emitcode ("inc", "_spx");
2979 /* if critical function then turn interrupts off */
2980 if (IFFUNC_ISCRITICAL (ftype))
2982 symbol *tlbl = newiTempLabel (NULL);
2983 emitcode ("setb", "c");
2984 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2985 emitcode ("clr", "c");
2986 emitcode ("", "%05d$:", (tlbl->key + 100));
2987 emitcode ("push", "psw"); /* save old ea via c in psw */
2991 /*-----------------------------------------------------------------*/
2992 /* genEndFunction - generates epilogue for functions */
2993 /*-----------------------------------------------------------------*/
2995 genEndFunction (iCode * ic)
2997 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2998 lineNode *lnp = lineCurr;
3000 bitVect *regsUsedPrologue;
3001 bitVect *regsUnneeded;
3002 int accIsFree = sym->recvSize < 4;
3005 _G.currentFunc = NULL;
3006 if (IFFUNC_ISNAKED(sym->type))
3008 emitcode(";", "naked function: no epilogue.");
3009 if (options.debug && currFunc)
3010 debugFile->writeEndFunction (currFunc, ic, 0);
3014 if (IFFUNC_ISCRITICAL (sym->type))
3016 emitcode ("pop", "psw"); /* restore ea via c in psw */
3017 emitcode ("mov", "ea,c");
3020 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3022 emitcode ("mov", "%s,_bp", spname);
3025 /* if use external stack but some variables were
3026 added to the local stack then decrement the
3028 if (options.useXstack && sym->stack)
3030 char count = sym->stack;
3032 if ((count>3) && accIsFree)
3034 emitcode ("mov", "a,sp");
3035 emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3036 emitcode ("mov", "sp,a");
3041 emitcode ("dec", "sp");
3045 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3047 if (options.useXstack)
3049 emitcode ("xch", "a,_bp");
3050 emitcode ("mov", "r0,a");
3051 emitcode ("dec", "r0");
3052 emitcode ("movx", "a,@r0");
3053 emitcode ("xch", "a,_bp");
3054 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3058 emitcode ("pop", "_bp");
3062 /* restore the register bank */
3063 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3065 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3066 || !options.useXstack)
3068 /* Special case of ISR using non-zero bank with useXstack
3071 emitcode ("pop", "psw");
3075 if (IFFUNC_ISISR (sym->type))
3078 /* now we need to restore the registers */
3079 /* if this isr has no bank i.e. is going to
3080 run with bank 0 , then we need to save more
3082 if (!FUNC_REGBANK (sym->type))
3084 /* if this function does not call any other
3085 function then we can be economical and
3086 save only those registers that are used */
3087 if (!IFFUNC_HASFCALL(sym->type))
3091 /* if any registers used */
3094 /* save the registers used */
3095 for (i = sym->regsUsed->size; i >= 0; i--)
3097 if (bitVectBitValue (sym->regsUsed, i))
3098 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3104 if (options.parms_in_bank1) {
3106 for (i = 7 ; i >= 0 ; i-- ) {
3107 emitcode ("pop","%s",rb1regs[i]);
3110 /* this function has a function call cannot
3111 determines register usage so we will have to pop the
3113 unsaveRBank (0, ic, FALSE);
3118 /* This ISR uses a non-zero bank.
3120 * Restore any register banks saved by genFunction
3123 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3126 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3128 if (savedBanks & (1 << ix))
3130 unsaveRBank(ix, NULL, FALSE);
3134 if (options.useXstack)
3136 /* Restore bank AFTER calling unsaveRBank,
3137 * since it can trash r0.
3139 emitcode ("pop", "psw");
3143 if (!inExcludeList ("dph"))
3144 emitcode ("pop", "dph");
3145 if (!inExcludeList ("dpl"))
3146 emitcode ("pop", "dpl");
3147 if (!inExcludeList ("b"))
3148 emitcode ("pop", "b");
3149 if (!inExcludeList ("acc"))
3150 emitcode ("pop", "acc");
3152 /* if debug then send end of function */
3153 if (options.debug && currFunc)
3155 debugFile->writeEndFunction (currFunc, ic, 1);
3158 emitcode ("reti", "");
3162 if (IFFUNC_CALLEESAVES(sym->type))
3166 /* if any registers used */
3169 /* save the registers used */
3170 for (i = sym->regsUsed->size; i >= 0; i--)
3172 if (bitVectBitValue (sym->regsUsed, i) ||
3173 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3174 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3177 else if (mcs51_ptrRegReq)
3179 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3180 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3185 /* if debug then send end of function */
3186 if (options.debug && currFunc)
3188 debugFile->writeEndFunction (currFunc, ic, 1);
3191 emitcode ("ret", "");
3194 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3197 /* If this was an interrupt handler using bank 0 that called another */
3198 /* function, then all registers must be saved; nothing to optimized. */
3199 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3200 && !FUNC_REGBANK(sym->type))
3203 /* There are no push/pops to optimize if not callee-saves or ISR */
3204 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3207 /* If there were stack parameters, we cannot optimize without also */
3208 /* fixing all of the stack offsets; this is too dificult to consider. */
3209 if (FUNC_HASSTACKPARM(sym->type))
3212 /* Compute the registers actually used */
3213 regsUsed = newBitVect (mcs51_nRegs);
3214 regsUsedPrologue = newBitVect (mcs51_nRegs);
3217 if (lnp->ic && lnp->ic->op == FUNCTION)
3218 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3220 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3222 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3223 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3230 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3231 && !bitVectBitValue (regsUsed, CND_IDX))
3233 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3234 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3235 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3236 bitVectUnSetBit (regsUsed, CND_IDX);
3239 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3241 /* If this was an interrupt handler that called another function */
3242 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3243 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3245 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3246 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3247 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3248 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3249 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3252 /* Remove the unneeded push/pops */
3253 regsUnneeded = newBitVect (mcs51_nRegs);
3256 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3258 if (!strncmp(lnp->line, "push", 4))
3260 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3261 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3263 connectLine (lnp->prev, lnp->next);
3264 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3267 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3269 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3270 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3272 connectLine (lnp->prev, lnp->next);
3273 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3280 for (idx = 0; idx < regsUnneeded->size; idx++)
3281 if (bitVectBitValue (regsUnneeded, idx))
3282 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3284 freeBitVect (regsUnneeded);
3285 freeBitVect (regsUsed);
3286 freeBitVect (regsUsedPrologue);
3289 /*-----------------------------------------------------------------*/
3290 /* genRet - generate code for return statement */
3291 /*-----------------------------------------------------------------*/
3295 int size, offset = 0, pushed = 0;
3297 D(emitcode ("; genRet",""));
3299 /* if we have no return value then
3300 just generate the "ret" */
3304 /* we have something to return then
3305 move the return value into place */
3306 aopOp (IC_LEFT (ic), ic, FALSE);
3307 size = AOP_SIZE (IC_LEFT (ic));
3312 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3315 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3317 emitcode ("push", "%s", l);
3322 l = aopGet (AOP (IC_LEFT (ic)), offset,
3324 if (strcmp (fReturn[offset], l))
3325 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3334 if (strcmp (fReturn[pushed], "a"))
3335 emitcode ("pop", fReturn[pushed]);
3337 emitcode ("pop", "acc");
3340 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3343 /* generate a jump to the return label
3344 if the next is not the return statement */
3345 if (!(ic->next && ic->next->op == LABEL &&
3346 IC_LABEL (ic->next) == returnLabel))
3348 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3352 /*-----------------------------------------------------------------*/
3353 /* genLabel - generates a label */
3354 /*-----------------------------------------------------------------*/
3356 genLabel (iCode * ic)
3358 /* special case never generate */
3359 if (IC_LABEL (ic) == entryLabel)
3362 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3365 /*-----------------------------------------------------------------*/
3366 /* genGoto - generates a ljmp */
3367 /*-----------------------------------------------------------------*/
3369 genGoto (iCode * ic)
3371 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3374 /*-----------------------------------------------------------------*/
3375 /* findLabelBackwards: walks back through the iCode chain looking */
3376 /* for the given label. Returns number of iCode instructions */
3377 /* between that label and given ic. */
3378 /* Returns zero if label not found. */
3379 /*-----------------------------------------------------------------*/
3381 findLabelBackwards (iCode * ic, int key)
3390 /* If we have any pushes or pops, we cannot predict the distance.
3391 I don't like this at all, this should be dealt with in the
3393 if (ic->op == IPUSH || ic->op == IPOP) {
3397 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3406 /*-----------------------------------------------------------------*/
3407 /* genPlusIncr :- does addition with increment if possible */
3408 /*-----------------------------------------------------------------*/
3410 genPlusIncr (iCode * ic)
3412 unsigned int icount;
3413 unsigned int size = getDataSize (IC_RESULT (ic));
3415 /* will try to generate an increment */
3416 /* if the right side is not a literal
3418 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3421 /* if the literal value of the right hand side
3422 is greater than 4 then it is not worth it */
3423 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3426 D(emitcode ("; genPlusIncr",""));
3428 /* if increment >=16 bits in register or direct space */
3429 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3430 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3438 /* If the next instruction is a goto and the goto target
3439 * is < 10 instructions previous to this, we can generate
3440 * jumps straight to that target.
3442 if (ic->next && ic->next->op == GOTO
3443 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3444 && labelRange <= 10)
3446 emitcode (";", "tail increment optimized");
3447 tlbl = IC_LABEL (ic->next);
3452 tlbl = newiTempLabel (NULL);
3455 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3456 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3457 IS_AOP_PREG (IC_RESULT (ic)))
3458 emitcode ("cjne", "%s,#0x00,%05d$",
3459 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3463 emitcode ("clr", "a");
3464 emitcode ("cjne", "a,%s,%05d$",
3465 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3469 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3472 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3473 IS_AOP_PREG (IC_RESULT (ic)))
3474 emitcode ("cjne", "%s,#0x00,%05d$",
3475 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3478 emitcode ("cjne", "a,%s,%05d$",
3479 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3482 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3486 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3487 IS_AOP_PREG (IC_RESULT (ic)))
3488 emitcode ("cjne", "%s,#0x00,%05d$",
3489 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3493 emitcode ("cjne", "a,%s,%05d$",
3494 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3497 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3502 emitcode ("", "%05d$:", tlbl->key + 100);
3507 /* if the sizes are greater than 1 then we cannot */
3508 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3509 AOP_SIZE (IC_LEFT (ic)) > 1)
3512 /* we can if the aops of the left & result match or
3513 if they are in registers and the registers are the
3515 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3520 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3521 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3522 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3528 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3537 /*-----------------------------------------------------------------*/
3538 /* outBitAcc - output a bit in acc */
3539 /*-----------------------------------------------------------------*/
3541 outBitAcc (operand * result)
3543 symbol *tlbl = newiTempLabel (NULL);
3544 /* if the result is a bit */
3545 if (AOP_TYPE (result) == AOP_CRY)
3547 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3551 emitcode ("jz", "%05d$", tlbl->key + 100);
3552 emitcode ("mov", "a,%s", one);
3553 emitcode ("", "%05d$:", tlbl->key + 100);
3558 /*-----------------------------------------------------------------*/
3559 /* genPlusBits - generates code for addition of two bits */
3560 /*-----------------------------------------------------------------*/
3562 genPlusBits (iCode * ic)
3564 D(emitcode ("; genPlusBits",""));
3566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3568 symbol *lbl = newiTempLabel (NULL);
3569 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3570 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3571 emitcode ("cpl", "c");
3572 emitcode ("", "%05d$:", (lbl->key + 100));
3573 outBitC (IC_RESULT (ic));
3577 emitcode ("clr", "a");
3578 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3579 emitcode ("rlc", "a");
3580 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3581 emitcode ("addc", "a,#0x00");
3582 outAcc (IC_RESULT (ic));
3587 /* This is the original version of this code.
3589 * This is being kept around for reference,
3590 * because I am not entirely sure I got it right...
3593 adjustArithmeticResult (iCode * ic)
3595 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3596 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3597 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3598 aopPut (AOP (IC_RESULT (ic)),
3599 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3601 isOperandVolatile (IC_RESULT (ic), FALSE));
3603 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3604 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3605 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3606 aopPut (AOP (IC_RESULT (ic)),
3607 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3609 isOperandVolatile (IC_RESULT (ic), FALSE));
3611 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3612 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3613 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3614 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3615 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3618 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3619 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3623 /* This is the pure and virtuous version of this code.
3624 * I'm pretty certain it's right, but not enough to toss the old
3628 adjustArithmeticResult (iCode * ic)
3630 if (opIsGptr (IC_RESULT (ic)) &&
3631 opIsGptr (IC_LEFT (ic)) &&
3632 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3634 aopPut (AOP (IC_RESULT (ic)),
3635 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3637 isOperandVolatile (IC_RESULT (ic), FALSE));
3640 if (opIsGptr (IC_RESULT (ic)) &&
3641 opIsGptr (IC_RIGHT (ic)) &&
3642 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3644 aopPut (AOP (IC_RESULT (ic)),
3645 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3647 isOperandVolatile (IC_RESULT (ic), FALSE));
3650 if (opIsGptr (IC_RESULT (ic)) &&
3651 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3652 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3653 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3654 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3657 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3658 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3663 /*-----------------------------------------------------------------*/
3664 /* genPlus - generates code for addition */
3665 /*-----------------------------------------------------------------*/
3667 genPlus (iCode * ic)
3669 int size, offset = 0;
3672 asmop *leftOp, *rightOp;
3675 /* special cases :- */
3677 D(emitcode ("; genPlus",""));
3679 aopOp (IC_LEFT (ic), ic, FALSE);
3680 aopOp (IC_RIGHT (ic), ic, FALSE);
3681 aopOp (IC_RESULT (ic), ic, TRUE);
3683 /* if literal, literal on the right or
3684 if left requires ACC or right is already
3686 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3687 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3688 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3690 operand *t = IC_RIGHT (ic);
3691 IC_RIGHT (ic) = IC_LEFT (ic);
3695 /* if both left & right are in bit
3697 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3698 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3704 /* if left in bit space & right literal */
3705 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3706 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3708 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3709 /* if result in bit space */
3710 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3712 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3713 emitcode ("cpl", "c");
3714 outBitC (IC_RESULT (ic));
3718 size = getDataSize (IC_RESULT (ic));
3721 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3722 emitcode ("addc", "a,#00");
3723 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3729 /* if I can do an increment instead
3730 of add then GOOD for ME */
3731 if (genPlusIncr (ic) == TRUE)
3734 size = getDataSize (IC_RESULT (ic));
3735 leftOp = AOP(IC_LEFT(ic));
3736 rightOp = AOP(IC_RIGHT(ic));
3739 /* if this is an add for an array access
3740 at a 256 byte boundary */
3742 && AOP_TYPE (op) == AOP_IMMD
3744 && IS_SPEC (OP_SYM_ETYPE (op))
3745 && SPEC_ABSA (OP_SYM_ETYPE (op))
3746 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3749 D(emitcode ("; genPlus aligned array",""));
3750 aopPut (AOP (IC_RESULT (ic)),
3751 aopGet (rightOp, 0, FALSE, FALSE),
3753 isOperandVolatile (IC_RESULT (ic), FALSE));
3755 if( 1 == getDataSize (IC_RIGHT (ic)) )
3757 aopPut (AOP (IC_RESULT (ic)),
3758 aopGet (leftOp, 1, FALSE, FALSE),
3760 isOperandVolatile (IC_RESULT (ic), FALSE));
3764 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3765 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3766 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3771 /* if the lower bytes of a literal are zero skip the addition */
3772 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3774 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3775 (skip_bytes+1 < size))
3780 D(emitcode ("; genPlus shortcut",""));
3785 if( offset >= skip_bytes )
3787 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3790 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3792 emitcode("xch", "a,b");
3793 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3794 emitcode (add, "a,b");
3797 else if (aopGetUsesAcc (leftOp, offset))
3799 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3800 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3804 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3805 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3807 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3808 add = "addc"; /* further adds must propagate carry */
3812 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3813 isOperandVolatile (IC_RESULT (ic), FALSE))
3816 aopPut (AOP (IC_RESULT (ic)),
3817 aopGet (leftOp, offset, FALSE, FALSE),
3819 isOperandVolatile (IC_RESULT (ic), FALSE));
3825 adjustArithmeticResult (ic);
3828 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3833 /*-----------------------------------------------------------------*/
3834 /* genMinusDec :- does subtraction with deccrement if possible */
3835 /*-----------------------------------------------------------------*/
3837 genMinusDec (iCode * ic)
3839 unsigned int icount;
3840 unsigned int size = getDataSize (IC_RESULT (ic));
3842 /* will try to generate an increment */
3843 /* if the right side is not a literal
3845 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 /* if the literal value of the right hand side
3849 is greater than 4 then it is not worth it */
3850 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3853 D(emitcode ("; genMinusDec",""));
3855 /* if decrement >=16 bits in register or direct space */
3856 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3857 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3865 /* If the next instruction is a goto and the goto target
3866 * is <= 10 instructions previous to this, we can generate
3867 * jumps straight to that target.
3869 if (ic->next && ic->next->op == GOTO
3870 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3871 && labelRange <= 10)
3873 emitcode (";", "tail decrement optimized");
3874 tlbl = IC_LABEL (ic->next);
3879 tlbl = newiTempLabel (NULL);
3883 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3884 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3885 IS_AOP_PREG (IC_RESULT (ic)))
3886 emitcode ("cjne", "%s,#0xff,%05d$"
3887 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3891 emitcode ("mov", "a,#0xff");
3892 emitcode ("cjne", "a,%s,%05d$"
3893 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3896 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3899 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3900 IS_AOP_PREG (IC_RESULT (ic)))
3901 emitcode ("cjne", "%s,#0xff,%05d$"
3902 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3906 emitcode ("cjne", "a,%s,%05d$"
3907 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3910 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3914 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3915 IS_AOP_PREG (IC_RESULT (ic)))
3916 emitcode ("cjne", "%s,#0xff,%05d$"
3917 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3921 emitcode ("cjne", "a,%s,%05d$"
3922 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3925 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3929 emitcode ("", "%05d$:", tlbl->key + 100);
3934 /* if the sizes are greater than 1 then we cannot */
3935 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3936 AOP_SIZE (IC_LEFT (ic)) > 1)
3939 /* we can if the aops of the left & result match or
3940 if they are in registers and the registers are the
3942 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3946 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3954 /*-----------------------------------------------------------------*/
3955 /* addSign - complete with sign */
3956 /*-----------------------------------------------------------------*/
3958 addSign (operand * result, int offset, int sign)
3960 int size = (getDataSize (result) - offset);
3965 emitcode ("rlc", "a");
3966 emitcode ("subb", "a,acc");
3968 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3972 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3976 /*-----------------------------------------------------------------*/
3977 /* genMinusBits - generates code for subtraction of two bits */
3978 /*-----------------------------------------------------------------*/
3980 genMinusBits (iCode * ic)
3982 symbol *lbl = newiTempLabel (NULL);
3984 D(emitcode ("; genMinusBits",""));
3986 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3988 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3989 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3990 emitcode ("cpl", "c");
3991 emitcode ("", "%05d$:", (lbl->key + 100));
3992 outBitC (IC_RESULT (ic));
3996 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3997 emitcode ("subb", "a,acc");
3998 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3999 emitcode ("inc", "a");
4000 emitcode ("", "%05d$:", (lbl->key + 100));
4001 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4002 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4006 /*-----------------------------------------------------------------*/
4007 /* genMinus - generates code for subtraction */
4008 /*-----------------------------------------------------------------*/
4010 genMinus (iCode * ic)
4012 int size, offset = 0;
4014 D(emitcode ("; genMinus",""));
4016 aopOp (IC_LEFT (ic), ic, FALSE);
4017 aopOp (IC_RIGHT (ic), ic, FALSE);
4018 aopOp (IC_RESULT (ic), ic, TRUE);
4020 /* special cases :- */
4021 /* if both left & right are in bit space */
4022 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4023 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4029 /* if I can do an decrement instead
4030 of subtract then GOOD for ME */
4031 if (genMinusDec (ic) == TRUE)
4034 size = getDataSize (IC_RESULT (ic));
4036 /* if literal, add a,#-lit, else normal subb */
4037 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4039 unsigned long lit = 0L;
4041 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4046 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4047 /* first add without previous c */
4049 if (!size && lit== (unsigned long) -1) {
4050 emitcode ("dec", "a");
4052 emitcode ("add", "a,#0x%02x",
4053 (unsigned int) (lit & 0x0FFL));
4056 emitcode ("addc", "a,#0x%02x",
4057 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4059 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4064 asmop *leftOp, *rightOp;
4066 leftOp = AOP(IC_LEFT(ic));
4067 rightOp = AOP(IC_RIGHT(ic));
4071 if (aopGetUsesAcc(rightOp, offset)) {
4072 if (aopGetUsesAcc(leftOp, offset)) {
4075 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4077 emitcode ("mov", "b,a");
4080 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4081 emitcode ("subb", "a,b");
4084 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4085 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4087 emitcode( "setb", "c");
4089 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4090 emitcode("cpl", "a");
4093 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4096 emitcode ("subb", "a,%s",
4097 aopGet(rightOp, offset, FALSE, TRUE));
4100 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4105 adjustArithmeticResult (ic);
4108 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4109 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4114 /*-----------------------------------------------------------------*/
4115 /* genMultbits :- multiplication of bits */
4116 /*-----------------------------------------------------------------*/
4118 genMultbits (operand * left,
4122 D(emitcode ("; genMultbits",""));
4124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4125 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4129 /*-----------------------------------------------------------------*/
4130 /* genMultOneByte : 8*8=8/16 bit multiplication */
4131 /*-----------------------------------------------------------------*/
4133 genMultOneByte (operand * left,
4138 int size = AOP_SIZE (result);
4139 bool runtimeSign, compiletimeSign;
4140 bool lUnsigned, rUnsigned, pushedB;
4142 D(emitcode ("; genMultOneByte",""));
4144 if (size < 1 || size > 2)
4146 /* this should never happen */
4147 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4148 AOP_SIZE(result), __FILE__, lineno);
4152 /* (if two literals: the value is computed before) */
4153 /* if one literal, literal on the right */
4154 if (AOP_TYPE (left) == AOP_LIT)
4159 /* emitcode (";", "swapped left and right"); */
4161 /* if no literal, unsigned on the right: shorter code */
4162 if ( AOP_TYPE (right) != AOP_LIT
4163 && SPEC_USIGN (getSpec (operandType (left))))
4170 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4171 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4175 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4176 no need to take care about the signedness! */
4177 || (lUnsigned && rUnsigned))
4179 /* just an unsigned 8 * 8 = 8 multiply
4181 /* emitcode (";","unsigned"); */
4182 /* TODO: check for accumulator clash between left & right aops? */
4184 if (AOP_TYPE (right) == AOP_LIT)
4186 /* moving to accumulator first helps peepholes */
4187 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4192 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4193 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4196 emitcode ("mul", "ab");
4197 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4199 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4205 /* we have to do a signed multiply */
4206 /* emitcode (";", "signed"); */
4208 /* now sign adjust for both left & right */
4210 /* let's see what's needed: */
4211 /* apply negative sign during runtime */
4212 runtimeSign = FALSE;
4213 /* negative sign from literals */
4214 compiletimeSign = FALSE;
4218 if (AOP_TYPE(left) == AOP_LIT)
4220 /* signed literal */
4221 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4223 compiletimeSign = TRUE;
4226 /* signed but not literal */
4232 if (AOP_TYPE(right) == AOP_LIT)
4234 /* signed literal */
4235 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4237 compiletimeSign ^= TRUE;
4240 /* signed but not literal */
4244 /* initialize F0, which stores the runtime sign */
4247 if (compiletimeSign)
4248 emitcode ("setb", "F0"); /* set sign flag */
4250 emitcode ("clr", "F0"); /* reset sign flag */
4253 /* save the signs of the operands */
4254 if (AOP_TYPE(right) == AOP_LIT)
4256 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4258 if (!rUnsigned && val < 0)
4259 emitcode ("mov", "b,#0x%02x", -val);
4261 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4263 else /* ! literal */
4265 if (rUnsigned) /* emitcode (";", "signed"); */
4267 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4270 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4271 lbl = newiTempLabel (NULL);
4272 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4273 emitcode ("cpl", "F0"); /* complement sign flag */
4274 emitcode ("cpl", "a"); /* 2's complement */
4275 emitcode ("inc", "a");
4276 emitcode ("", "%05d$:", (lbl->key + 100));
4277 emitcode ("mov", "b,a");
4281 if (AOP_TYPE(left) == AOP_LIT)
4283 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4285 if (!lUnsigned && val < 0)
4286 emitcode ("mov", "a,#0x%02x", -val);
4288 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4290 else /* ! literal */
4292 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4296 lbl = newiTempLabel (NULL);
4297 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4298 emitcode ("cpl", "F0"); /* complement sign flag */
4299 emitcode ("cpl", "a"); /* 2's complement */
4300 emitcode ("inc", "a");
4301 emitcode ("", "%05d$:", (lbl->key + 100));
4305 /* now the multiplication */
4306 emitcode ("mul", "ab");
4307 if (runtimeSign || compiletimeSign)
4309 lbl = newiTempLabel (NULL);
4311 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4312 emitcode ("cpl", "a"); /* lsb 2's complement */
4314 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4317 emitcode ("add", "a,#1"); /* this sets carry flag */
4318 emitcode ("xch", "a,b");
4319 emitcode ("cpl", "a"); /* msb 2's complement */
4320 emitcode ("addc", "a,#0");
4321 emitcode ("xch", "a,b");
4323 emitcode ("", "%05d$:", (lbl->key + 100));
4325 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4327 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4332 /*-----------------------------------------------------------------*/
4333 /* genMult - generates code for multiplication */
4334 /*-----------------------------------------------------------------*/
4336 genMult (iCode * ic)
4338 operand *left = IC_LEFT (ic);
4339 operand *right = IC_RIGHT (ic);
4340 operand *result = IC_RESULT (ic);
4342 D(emitcode ("; genMult",""));
4344 /* assign the amsops */
4345 aopOp (left, ic, FALSE);
4346 aopOp (right, ic, FALSE);
4347 aopOp (result, ic, TRUE);
4349 /* special cases first */
4351 if (AOP_TYPE (left) == AOP_CRY &&
4352 AOP_TYPE (right) == AOP_CRY)
4354 genMultbits (left, right, result);
4358 /* if both are of size == 1 */
4359 #if 0 // one of them can be a sloc shared with the result
4360 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4362 if (getSize(operandType(left)) == 1 &&
4363 getSize(operandType(right)) == 1)
4366 genMultOneByte (left, right, result);
4370 /* should have been converted to function call */
4371 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4372 getSize(OP_SYMBOL(right)->type));
4376 freeAsmop (result, NULL, ic, TRUE);
4377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4378 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4381 /*-----------------------------------------------------------------*/
4382 /* genDivbits :- division of bits */
4383 /*-----------------------------------------------------------------*/
4385 genDivbits (operand * left,
4392 D(emitcode ("; genDivbits",""));
4396 /* the result must be bit */
4397 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4398 l = aopGet (AOP (left), 0, FALSE, FALSE);
4402 emitcode ("div", "ab");
4403 emitcode ("rrc", "a");
4407 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division */
4412 /*-----------------------------------------------------------------*/
4414 genDivOneByte (operand * left,
4418 bool lUnsigned, rUnsigned, pushedB;
4419 bool runtimeSign, compiletimeSign;
4423 D(emitcode ("; genDivOneByte",""));
4425 /* Why is it necessary that genDivOneByte() can return an int result?
4428 volatile unsigned char uc;
4429 volatile signed char sc1, sc2;
4442 In all cases a one byte result would overflow, the following cast to int
4443 would return the wrong result.
4445 Two possible solution:
4446 a) cast operands to int, if ((unsigned) / (signed)) or
4447 ((signed) / (signed))
4448 b) return an 16 bit signed int; this is what we're doing here!
4451 size = AOP_SIZE (result) - 1;
4453 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4454 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4458 /* signed or unsigned */
4459 if (lUnsigned && rUnsigned)
4461 /* unsigned is easy */
4462 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4463 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4464 emitcode ("div", "ab");
4465 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4467 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4473 /* signed is a little bit more difficult */
4475 /* now sign adjust for both left & right */
4477 /* let's see what's needed: */
4478 /* apply negative sign during runtime */
4479 runtimeSign = FALSE;
4480 /* negative sign from literals */
4481 compiletimeSign = FALSE;
4485 if (AOP_TYPE(left) == AOP_LIT)
4487 /* signed literal */
4488 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4490 compiletimeSign = TRUE;
4493 /* signed but not literal */
4499 if (AOP_TYPE(right) == AOP_LIT)
4501 /* signed literal */
4502 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4504 compiletimeSign ^= TRUE;
4507 /* signed but not literal */
4511 /* initialize F0, which stores the runtime sign */
4514 if (compiletimeSign)
4515 emitcode ("setb", "F0"); /* set sign flag */
4517 emitcode ("clr", "F0"); /* reset sign flag */
4520 /* save the signs of the operands */
4521 if (AOP_TYPE(right) == AOP_LIT)
4523 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4525 if (!rUnsigned && val < 0)
4526 emitcode ("mov", "b,#0x%02x", -val);
4528 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4530 else /* ! literal */
4533 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4536 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4537 lbl = newiTempLabel (NULL);
4538 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4539 emitcode ("cpl", "F0"); /* complement sign flag */
4540 emitcode ("cpl", "a"); /* 2's complement */
4541 emitcode ("inc", "a");
4542 emitcode ("", "%05d$:", (lbl->key + 100));
4543 emitcode ("mov", "b,a");
4547 if (AOP_TYPE(left) == AOP_LIT)
4549 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4551 if (!lUnsigned && val < 0)
4552 emitcode ("mov", "a,#0x%02x", -val);
4554 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4556 else /* ! literal */
4558 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4562 lbl = newiTempLabel (NULL);
4563 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4564 emitcode ("cpl", "F0"); /* complement sign flag */
4565 emitcode ("cpl", "a"); /* 2's complement */
4566 emitcode ("inc", "a");
4567 emitcode ("", "%05d$:", (lbl->key + 100));
4571 /* now the division */
4572 emitcode ("div", "ab");
4574 if (runtimeSign || compiletimeSign)
4576 lbl = newiTempLabel (NULL);
4578 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4579 emitcode ("cpl", "a"); /* lsb 2's complement */
4580 emitcode ("inc", "a");
4581 emitcode ("", "%05d$:", (lbl->key + 100));
4583 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4586 /* msb is 0x00 or 0xff depending on the sign */
4589 emitcode ("mov", "c,F0");
4590 emitcode ("subb", "a,acc");
4592 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4594 else /* compiletimeSign */
4596 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4601 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4603 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4609 /*-----------------------------------------------------------------*/
4610 /* genDiv - generates code for division */
4611 /*-----------------------------------------------------------------*/
4615 operand *left = IC_LEFT (ic);
4616 operand *right = IC_RIGHT (ic);
4617 operand *result = IC_RESULT (ic);
4619 D(emitcode ("; genDiv",""));
4621 /* assign the amsops */
4622 aopOp (left, ic, FALSE);
4623 aopOp (right, ic, FALSE);
4624 aopOp (result, ic, TRUE);
4626 /* special cases first */
4628 if (AOP_TYPE (left) == AOP_CRY &&
4629 AOP_TYPE (right) == AOP_CRY)
4631 genDivbits (left, right, result);
4635 /* if both are of size == 1 */
4636 if (AOP_SIZE (left) == 1 &&
4637 AOP_SIZE (right) == 1)
4639 genDivOneByte (left, right, result);
4643 /* should have been converted to function call */
4646 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4648 freeAsmop (result, NULL, ic, TRUE);
4651 /*-----------------------------------------------------------------*/
4652 /* genModbits :- modulus of bits */
4653 /*-----------------------------------------------------------------*/
4655 genModbits (operand * left,
4662 D(emitcode ("; genModbits",""));
4666 /* the result must be bit */
4667 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4668 l = aopGet (AOP (left), 0, FALSE, FALSE);
4672 emitcode ("div", "ab");
4673 emitcode ("mov", "a,b");
4674 emitcode ("rrc", "a");
4678 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4681 /*-----------------------------------------------------------------*/
4682 /* genModOneByte : 8 bit modulus */
4683 /*-----------------------------------------------------------------*/
4685 genModOneByte (operand * left,
4689 bool lUnsigned, rUnsigned, pushedB;
4690 bool runtimeSign, compiletimeSign;
4694 D(emitcode ("; genModOneByte",""));
4696 size = AOP_SIZE (result) - 1;
4698 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4699 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4703 /* signed or unsigned */
4704 if (lUnsigned && rUnsigned)
4706 /* unsigned is easy */
4707 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4708 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4709 emitcode ("div", "ab");
4710 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4712 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4718 /* signed is a little bit more difficult */
4720 /* now sign adjust for both left & right */
4722 /* modulus: sign of the right operand has no influence on the result! */
4723 if (AOP_TYPE(right) == AOP_LIT)
4725 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4727 if (!rUnsigned && val < 0)
4728 emitcode ("mov", "b,#0x%02x", -val);
4730 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4732 else /* not literal */
4735 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4738 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4739 lbl = newiTempLabel (NULL);
4740 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4741 emitcode ("cpl", "a"); /* 2's complement */
4742 emitcode ("inc", "a");
4743 emitcode ("", "%05d$:", (lbl->key + 100));
4744 emitcode ("mov", "b,a");
4748 /* let's see what's needed: */
4749 /* apply negative sign during runtime */
4750 runtimeSign = FALSE;
4751 /* negative sign from literals */
4752 compiletimeSign = FALSE;
4754 /* sign adjust left side */
4755 if (AOP_TYPE(left) == AOP_LIT)
4757 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4759 if (!lUnsigned && val < 0)
4761 compiletimeSign = TRUE; /* set sign flag */
4762 emitcode ("mov", "a,#0x%02x", -val);
4765 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4767 else /* ! literal */
4769 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4774 emitcode ("clr", "F0"); /* clear sign flag */
4776 lbl = newiTempLabel (NULL);
4777 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4778 emitcode ("setb", "F0"); /* set sign flag */
4779 emitcode ("cpl", "a"); /* 2's complement */
4780 emitcode ("inc", "a");
4781 emitcode ("", "%05d$:", (lbl->key + 100));
4785 /* now the modulus */
4786 emitcode ("div", "ab");
4788 if (runtimeSign || compiletimeSign)
4790 emitcode ("mov", "a,b");
4791 lbl = newiTempLabel (NULL);
4793 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4794 emitcode ("cpl", "a"); /* 2's complement */
4795 emitcode ("inc", "a");
4796 emitcode ("", "%05d$:", (lbl->key + 100));
4798 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4801 /* msb is 0x00 or 0xff depending on the sign */
4804 emitcode ("mov", "c,F0");
4805 emitcode ("subb", "a,acc");
4807 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4809 else /* compiletimeSign */
4811 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4816 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4818 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4824 /*-----------------------------------------------------------------*/
4825 /* genMod - generates code for division */
4826 /*-----------------------------------------------------------------*/
4830 operand *left = IC_LEFT (ic);
4831 operand *right = IC_RIGHT (ic);
4832 operand *result = IC_RESULT (ic);
4834 D(emitcode ("; genMod",""));
4836 /* assign the amsops */
4837 aopOp (left, ic, FALSE);
4838 aopOp (right, ic, FALSE);
4839 aopOp (result, ic, TRUE);
4841 /* special cases first */
4843 if (AOP_TYPE (left) == AOP_CRY &&
4844 AOP_TYPE (right) == AOP_CRY)
4846 genModbits (left, right, result);
4850 /* if both are of size == 1 */
4851 if (AOP_SIZE (left) == 1 &&
4852 AOP_SIZE (right) == 1)
4854 genModOneByte (left, right, result);
4858 /* should have been converted to function call */
4862 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864 freeAsmop (result, NULL, ic, TRUE);
4867 /*-----------------------------------------------------------------*/
4868 /* genIfxJump :- will create a jump depending on the ifx */
4869 /*-----------------------------------------------------------------*/
4871 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4874 symbol *tlbl = newiTempLabel (NULL);
4877 D(emitcode ("; genIfxJump",""));
4879 /* if true label then we jump if condition
4883 jlbl = IC_TRUE (ic);
4884 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4885 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4889 /* false label is present */
4890 jlbl = IC_FALSE (ic);
4891 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4892 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4894 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4895 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4897 emitcode (inst, "%05d$", tlbl->key + 100);
4898 freeForBranchAsmop (result);
4899 freeForBranchAsmop (right);
4900 freeForBranchAsmop (left);
4901 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4902 emitcode ("", "%05d$:", tlbl->key + 100);
4904 /* mark the icode as generated */
4908 /*-----------------------------------------------------------------*/
4909 /* genCmp :- greater or less than comparison */
4910 /*-----------------------------------------------------------------*/
4912 genCmp (operand * left, operand * right,
4913 operand * result, iCode * ifx, int sign, iCode *ic)
4915 int size, offset = 0;
4916 unsigned long lit = 0L;
4919 D(emitcode ("; genCmp",""));
4921 /* if left & right are bit variables */
4922 if (AOP_TYPE (left) == AOP_CRY &&
4923 AOP_TYPE (right) == AOP_CRY)
4925 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4926 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4930 /* subtract right from left if at the
4931 end the carry flag is set then we know that
4932 left is greater than right */
4933 size = max (AOP_SIZE (left), AOP_SIZE (right));
4935 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4936 if ((size == 1) && !sign &&
4937 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4939 symbol *lbl = newiTempLabel (NULL);
4940 emitcode ("cjne", "%s,%s,%05d$",
4941 aopGet (AOP (left), offset, FALSE, FALSE),
4942 aopGet (AOP (right), offset, FALSE, FALSE),
4944 emitcode ("", "%05d$:", lbl->key + 100);
4948 if (AOP_TYPE (right) == AOP_LIT)
4950 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4951 /* optimize if(x < 0) or if(x >= 0) */
4960 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4961 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4963 genIfxJump (ifx, "acc.7", left, right, result);
4964 freeAsmop (right, NULL, ic, TRUE);
4965 freeAsmop (left, NULL, ic, TRUE);
4970 emitcode ("rlc", "a");
4978 bool pushedB = FALSE;
4979 rightInB = aopGetUsesAcc(AOP (right), offset);
4983 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4985 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4986 if (sign && size == 0)
4988 emitcode ("xrl", "a,#0x80");
4989 if (AOP_TYPE (right) == AOP_LIT)
4991 unsigned long lit = (unsigned long)
4992 floatFromVal (AOP (right)->aopu.aop_lit);
4993 emitcode ("subb", "a,#0x%02x",
4994 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5002 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5004 emitcode ("xrl", "b,#0x80");
5005 emitcode ("subb", "a,b");
5011 emitcode ("subb", "a,b");
5013 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5023 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5024 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5025 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5031 /* if the result is used in the next
5032 ifx conditional branch then generate
5033 code a little differently */
5035 genIfxJump (ifx, "c", NULL, NULL, result);
5038 /* leave the result in acc */
5042 /*-----------------------------------------------------------------*/
5043 /* genCmpGt :- greater than comparison */
5044 /*-----------------------------------------------------------------*/
5046 genCmpGt (iCode * ic, iCode * ifx)
5048 operand *left, *right, *result;
5049 sym_link *letype, *retype;
5052 D(emitcode ("; genCmpGt",""));
5054 left = IC_LEFT (ic);
5055 right = IC_RIGHT (ic);
5056 result = IC_RESULT (ic);
5058 letype = getSpec (operandType (left));
5059 retype = getSpec (operandType (right));
5060 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5061 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5062 /* assign the amsops */
5063 aopOp (left, ic, FALSE);
5064 aopOp (right, ic, FALSE);
5065 aopOp (result, ic, TRUE);
5067 genCmp (right, left, result, ifx, sign, ic);
5069 freeAsmop (result, NULL, ic, TRUE);
5072 /*-----------------------------------------------------------------*/
5073 /* genCmpLt - less than comparisons */
5074 /*-----------------------------------------------------------------*/
5076 genCmpLt (iCode * ic, iCode * ifx)
5078 operand *left, *right, *result;
5079 sym_link *letype, *retype;
5082 D(emitcode ("; genCmpLt",""));
5084 left = IC_LEFT (ic);
5085 right = IC_RIGHT (ic);
5086 result = IC_RESULT (ic);
5088 letype = getSpec (operandType (left));
5089 retype = getSpec (operandType (right));
5090 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5091 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5092 /* assign the amsops */
5093 aopOp (left, ic, FALSE);
5094 aopOp (right, ic, FALSE);
5095 aopOp (result, ic, TRUE);
5097 genCmp (left, right, result, ifx, sign,ic);
5099 freeAsmop (result, NULL, ic, TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* gencjneshort - compare and jump if not equal */
5104 /*-----------------------------------------------------------------*/
5106 gencjneshort (operand * left, operand * right, symbol * lbl)
5108 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5110 unsigned long lit = 0L;
5112 /* if the left side is a literal or
5113 if the right is in a pointer register and left
5115 if ((AOP_TYPE (left) == AOP_LIT) ||
5116 (AOP_TYPE (left) == AOP_IMMD) ||
5117 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5124 if (AOP_TYPE (right) == AOP_LIT)
5125 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5127 /* if the right side is a literal then anything goes */
5128 if (AOP_TYPE (right) == AOP_LIT &&
5129 AOP_TYPE (left) != AOP_DIR &&
5130 AOP_TYPE (left) != AOP_IMMD)
5134 emitcode ("cjne", "%s,%s,%05d$",
5135 aopGet (AOP (left), offset, FALSE, FALSE),
5136 aopGet (AOP (right), offset, FALSE, FALSE),
5142 /* if the right side is in a register or in direct space or
5143 if the left is a pointer register & right is not */
5144 else if (AOP_TYPE (right) == AOP_REG ||
5145 AOP_TYPE (right) == AOP_DIR ||
5146 AOP_TYPE (right) == AOP_LIT ||
5147 AOP_TYPE (right) == AOP_IMMD ||
5148 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5149 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5153 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5154 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5155 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5156 emitcode ("jnz", "%05d$", lbl->key + 100);
5158 emitcode ("cjne", "a,%s,%05d$",
5159 aopGet (AOP (right), offset, FALSE, TRUE),
5166 /* right is a pointer reg need both a & b */
5170 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5171 wassertl(!_G.BInUse, "B was in use");
5172 l = aopGet (AOP (left), offset, FALSE, FALSE);
5173 if (strcmp (l, "b"))
5174 emitcode ("mov", "b,%s", l);
5175 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5176 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5182 /*-----------------------------------------------------------------*/
5183 /* gencjne - compare and jump if not equal */
5184 /*-----------------------------------------------------------------*/
5186 gencjne (operand * left, operand * right, symbol * lbl)
5188 symbol *tlbl = newiTempLabel (NULL);
5190 gencjneshort (left, right, lbl);
5192 emitcode ("mov", "a,%s", one);
5193 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5194 emitcode ("", "%05d$:", lbl->key + 100);
5195 emitcode ("clr", "a");
5196 emitcode ("", "%05d$:", tlbl->key + 100);
5199 /*-----------------------------------------------------------------*/
5200 /* genCmpEq - generates code for equal to */
5201 /*-----------------------------------------------------------------*/
5203 genCmpEq (iCode * ic, iCode * ifx)
5205 operand *left, *right, *result;
5207 D(emitcode ("; genCmpEq",""));
5209 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5210 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5211 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5213 /* if literal, literal on the right or
5214 if the right is in a pointer register and left
5216 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5217 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5219 operand *t = IC_RIGHT (ic);
5220 IC_RIGHT (ic) = IC_LEFT (ic);
5224 if (ifx && !AOP_SIZE (result))
5227 /* if they are both bit variables */
5228 if (AOP_TYPE (left) == AOP_CRY &&
5229 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5231 if (AOP_TYPE (right) == AOP_LIT)
5233 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5236 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5237 emitcode ("cpl", "c");
5241 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5245 emitcode ("clr", "c");
5247 /* AOP_TYPE(right) == AOP_CRY */
5251 symbol *lbl = newiTempLabel (NULL);
5252 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5253 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5254 emitcode ("cpl", "c");
5255 emitcode ("", "%05d$:", (lbl->key + 100));
5257 /* if true label then we jump if condition
5259 tlbl = newiTempLabel (NULL);
5262 emitcode ("jnc", "%05d$", tlbl->key + 100);
5263 freeForBranchAsmop (result);
5264 freeForBranchAsmop (right);
5265 freeForBranchAsmop (left);
5266 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5270 emitcode ("jc", "%05d$", tlbl->key + 100);
5271 freeForBranchAsmop (result);
5272 freeForBranchAsmop (right);
5273 freeForBranchAsmop (left);
5274 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5276 emitcode ("", "%05d$:", tlbl->key + 100);
5280 tlbl = newiTempLabel (NULL);
5281 gencjneshort (left, right, tlbl);
5284 freeForBranchAsmop (result);
5285 freeForBranchAsmop (right);
5286 freeForBranchAsmop (left);
5287 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5288 emitcode ("", "%05d$:", tlbl->key + 100);
5292 symbol *lbl = newiTempLabel (NULL);
5293 emitcode ("sjmp", "%05d$", lbl->key + 100);
5294 emitcode ("", "%05d$:", tlbl->key + 100);
5295 freeForBranchAsmop (result);
5296 freeForBranchAsmop (right);
5297 freeForBranchAsmop (left);
5298 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5299 emitcode ("", "%05d$:", lbl->key + 100);
5302 /* mark the icode as generated */
5307 /* if they are both bit variables */
5308 if (AOP_TYPE (left) == AOP_CRY &&
5309 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5311 if (AOP_TYPE (right) == AOP_LIT)
5313 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5316 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5317 emitcode ("cpl", "c");
5321 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5325 emitcode ("clr", "c");
5327 /* AOP_TYPE(right) == AOP_CRY */
5331 symbol *lbl = newiTempLabel (NULL);
5332 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5333 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5334 emitcode ("cpl", "c");
5335 emitcode ("", "%05d$:", (lbl->key + 100));
5338 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5345 genIfxJump (ifx, "c", left, right, result);
5348 /* if the result is used in an arithmetic operation
5349 then put the result in place */
5354 gencjne (left, right, newiTempLabel (NULL));
5355 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5357 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5362 genIfxJump (ifx, "a", left, right, result);
5365 /* if the result is used in an arithmetic operation
5366 then put the result in place */
5367 if (AOP_TYPE (result) != AOP_CRY)
5369 /* leave the result in acc */
5373 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5374 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (result, NULL, ic, TRUE);
5378 /*-----------------------------------------------------------------*/
5379 /* ifxForOp - returns the icode containing the ifx for operand */
5380 /*-----------------------------------------------------------------*/
5382 ifxForOp (operand * op, iCode * ic)
5384 /* if true symbol then needs to be assigned */
5385 if (IS_TRUE_SYMOP (op))
5388 /* if this has register type condition and
5389 the next instruction is ifx with the same operand
5390 and live to of the operand is upto the ifx only then */
5392 ic->next->op == IFX &&
5393 IC_COND (ic->next)->key == op->key &&
5394 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5400 /*-----------------------------------------------------------------*/
5401 /* hasInc - operand is incremented before any other use */
5402 /*-----------------------------------------------------------------*/
5404 hasInc (operand *op, iCode *ic,int osize)
5406 sym_link *type = operandType(op);
5407 sym_link *retype = getSpec (type);
5408 iCode *lic = ic->next;
5411 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5412 if (!IS_SYMOP(op)) return NULL;
5414 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5415 if (IS_AGGREGATE(type->next)) return NULL;
5416 if (osize != (isize = getSize(type->next))) return NULL;
5419 /* if operand of the form op = op + <sizeof *op> */
5420 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5421 isOperandEqual(IC_RESULT(lic),op) &&
5422 isOperandLiteral(IC_RIGHT(lic)) &&
5423 operandLitValue(IC_RIGHT(lic)) == isize) {
5426 /* if the operand used or deffed */
5427 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5430 /* if GOTO or IFX */
5431 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5437 /*-----------------------------------------------------------------*/
5438 /* genAndOp - for && operation */
5439 /*-----------------------------------------------------------------*/
5441 genAndOp (iCode * ic)
5443 operand *left, *right, *result;
5446 D(emitcode ("; genAndOp",""));
5448 /* note here that && operations that are in an
5449 if statement are taken away by backPatchLabels
5450 only those used in arthmetic operations remain */
5451 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5452 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5453 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5455 /* if both are bit variables */
5456 if (AOP_TYPE (left) == AOP_CRY &&
5457 AOP_TYPE (right) == AOP_CRY)
5459 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5460 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5465 tlbl = newiTempLabel (NULL);
5467 emitcode ("jz", "%05d$", tlbl->key + 100);
5469 emitcode ("", "%05d$:", tlbl->key + 100);
5473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5474 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5475 freeAsmop (result, NULL, ic, TRUE);
5479 /*-----------------------------------------------------------------*/
5480 /* genOrOp - for || operation */
5481 /*-----------------------------------------------------------------*/
5483 genOrOp (iCode * ic)
5485 operand *left, *right, *result;
5488 D(emitcode ("; genOrOp",""));
5490 /* note here that || operations that are in an
5491 if statement are taken away by backPatchLabels
5492 only those used in arthmetic operations remain */
5493 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5494 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5495 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5497 /* if both are bit variables */
5498 if (AOP_TYPE (left) == AOP_CRY &&
5499 AOP_TYPE (right) == AOP_CRY)
5501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5502 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5507 tlbl = newiTempLabel (NULL);
5509 emitcode ("jnz", "%05d$", tlbl->key + 100);
5511 emitcode ("", "%05d$:", tlbl->key + 100);
5515 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5516 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5517 freeAsmop (result, NULL, ic, TRUE);
5520 /*-----------------------------------------------------------------*/
5521 /* isLiteralBit - test if lit == 2^n */
5522 /*-----------------------------------------------------------------*/
5524 isLiteralBit (unsigned long lit)
5526 unsigned long pw[32] =
5527 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5528 0x100L, 0x200L, 0x400L, 0x800L,
5529 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5530 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5531 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5532 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5533 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5536 for (idx = 0; idx < 32; idx++)
5542 /*-----------------------------------------------------------------*/
5543 /* continueIfTrue - */
5544 /*-----------------------------------------------------------------*/
5546 continueIfTrue (iCode * ic)
5549 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5553 /*-----------------------------------------------------------------*/
5555 /*-----------------------------------------------------------------*/
5557 jumpIfTrue (iCode * ic)
5560 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5564 /*-----------------------------------------------------------------*/
5565 /* jmpTrueOrFalse - */
5566 /*-----------------------------------------------------------------*/
5568 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5570 // ugly but optimized by peephole
5573 symbol *nlbl = newiTempLabel (NULL);
5574 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5575 emitcode ("", "%05d$:", tlbl->key + 100);
5576 freeForBranchAsmop (result);
5577 freeForBranchAsmop (right);
5578 freeForBranchAsmop (left);
5579 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5580 emitcode ("", "%05d$:", nlbl->key + 100);
5584 freeForBranchAsmop (result);
5585 freeForBranchAsmop (right);
5586 freeForBranchAsmop (left);
5587 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5588 emitcode ("", "%05d$:", tlbl->key + 100);
5593 /*-----------------------------------------------------------------*/
5594 /* genAnd - code for and */
5595 /*-----------------------------------------------------------------*/
5597 genAnd (iCode * ic, iCode * ifx)
5599 operand *left, *right, *result;
5600 int size, offset = 0;
5601 unsigned long lit = 0L;
5605 D(emitcode ("; genAnd",""));
5607 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5608 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5609 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5612 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5614 AOP_TYPE (left), AOP_TYPE (right));
5615 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5617 AOP_SIZE (left), AOP_SIZE (right));
5620 /* if left is a literal & right is not then exchange them */
5621 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5622 AOP_NEEDSACC (left))
5624 operand *tmp = right;
5629 /* if result = right then exchange left and right */
5630 if (sameRegs (AOP (result), AOP (right)))
5632 operand *tmp = right;
5637 /* if right is bit then exchange them */
5638 if (AOP_TYPE (right) == AOP_CRY &&
5639 AOP_TYPE (left) != AOP_CRY)
5641 operand *tmp = right;
5645 if (AOP_TYPE (right) == AOP_LIT)
5646 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5648 size = AOP_SIZE (result);
5651 // result = bit & yy;
5652 if (AOP_TYPE (left) == AOP_CRY)
5654 // c = bit & literal;
5655 if (AOP_TYPE (right) == AOP_LIT)
5659 if (size && sameRegs (AOP (result), AOP (left)))
5662 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5667 if (size && (AOP_TYPE (result) == AOP_CRY))
5669 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5672 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5677 emitcode ("clr", "c");
5682 if (AOP_TYPE (right) == AOP_CRY)
5685 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5686 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5691 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5693 emitcode ("rrc", "a");
5694 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5702 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5703 genIfxJump (ifx, "c", left, right, result);
5707 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5708 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5709 if ((AOP_TYPE (right) == AOP_LIT) &&
5710 (AOP_TYPE (result) == AOP_CRY) &&
5711 (AOP_TYPE (left) != AOP_CRY))
5713 int posbit = isLiteralBit (lit);
5718 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5721 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5727 SNPRINTF (buffer, sizeof(buffer),
5728 "acc.%d", posbit & 0x07);
5729 genIfxJump (ifx, buffer, left, right, result);
5732 {// what is this case? just found it in ds390/gen.c
5733 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5740 symbol *tlbl = newiTempLabel (NULL);
5741 int sizel = AOP_SIZE (left);
5743 emitcode ("setb", "c");
5746 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5748 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5750 if ((posbit = isLiteralBit (bytelit)) != 0)
5751 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5754 if (bytelit != 0x0FFL)
5755 emitcode ("anl", "a,%s",
5756 aopGet (AOP (right), offset, FALSE, TRUE));
5757 emitcode ("jnz", "%05d$", tlbl->key + 100);
5762 // bit = left & literal
5765 emitcode ("clr", "c");
5766 emitcode ("", "%05d$:", tlbl->key + 100);
5768 // if(left & literal)
5772 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5774 emitcode ("", "%05d$:", tlbl->key + 100);
5782 /* if left is same as result */
5783 if (sameRegs (AOP (result), AOP (left)))
5785 for (; size--; offset++)
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5790 if (bytelit == 0x0FF)
5792 /* dummy read of volatile operand */
5793 if (isOperandVolatile (left, FALSE))
5794 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5798 else if (bytelit == 0)
5800 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5802 else if (IS_AOP_PREG (result))
5804 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5805 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5806 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5809 emitcode ("anl", "%s,%s",
5810 aopGet (AOP (left), offset, FALSE, TRUE),
5811 aopGet (AOP (right), offset, FALSE, FALSE));
5815 if (AOP_TYPE (left) == AOP_ACC)
5816 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5819 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5820 if (IS_AOP_PREG (result))
5822 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5823 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5826 emitcode ("anl", "%s,a",
5827 aopGet (AOP (left), offset, FALSE, TRUE));
5834 // left & result in different registers
5835 if (AOP_TYPE (result) == AOP_CRY)
5838 // if(size), result in bit
5839 // if(!size && ifx), conditional oper: if(left & right)
5840 symbol *tlbl = newiTempLabel (NULL);
5841 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5843 emitcode ("setb", "c");
5846 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5847 emitcode ("anl", "a,%s",
5848 aopGet (AOP (right), offset, FALSE, FALSE));
5850 if (AOP_TYPE(left)==AOP_ACC) {
5851 bool pushedB = pushB ();
5852 emitcode("mov", "b,a");
5853 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5854 emitcode("anl", "a,b");
5857 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5858 emitcode ("anl", "a,%s",
5859 aopGet (AOP (left), offset, FALSE, FALSE));
5862 emitcode ("jnz", "%05d$", tlbl->key + 100);
5868 emitcode ("", "%05d$:", tlbl->key + 100);
5872 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5874 emitcode ("", "%05d$:", tlbl->key + 100);
5878 for (; (size--); offset++)
5881 // result = left & right
5882 if (AOP_TYPE (right) == AOP_LIT)
5884 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5885 if (bytelit == 0x0FF)
5887 aopPut (AOP (result),
5888 aopGet (AOP (left), offset, FALSE, FALSE),
5890 isOperandVolatile (result, FALSE));
5893 else if (bytelit == 0)
5895 /* dummy read of volatile operand */
5896 if (isOperandVolatile (left, FALSE))
5897 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5898 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5902 // faster than result <- left, anl result,right
5903 // and better if result is SFR
5904 if (AOP_TYPE (left) == AOP_ACC)
5905 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5908 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5909 emitcode ("anl", "a,%s",
5910 aopGet (AOP (left), offset, FALSE, FALSE));
5912 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5918 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5919 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5920 freeAsmop (result, NULL, ic, TRUE);
5923 /*-----------------------------------------------------------------*/
5924 /* genOr - code for or */
5925 /*-----------------------------------------------------------------*/
5927 genOr (iCode * ic, iCode * ifx)
5929 operand *left, *right, *result;
5930 int size, offset = 0;
5931 unsigned long lit = 0L;
5934 D(emitcode ("; genOr",""));
5936 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5937 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5938 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5941 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5943 AOP_TYPE (left), AOP_TYPE (right));
5944 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5946 AOP_SIZE (left), AOP_SIZE (right));
5949 /* if left is a literal & right is not then exchange them */
5950 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5951 AOP_NEEDSACC (left))
5953 operand *tmp = right;
5958 /* if result = right then exchange them */
5959 if (sameRegs (AOP (result), AOP (right)))
5961 operand *tmp = right;
5966 /* if right is bit then exchange them */
5967 if (AOP_TYPE (right) == AOP_CRY &&
5968 AOP_TYPE (left) != AOP_CRY)
5970 operand *tmp = right;
5974 if (AOP_TYPE (right) == AOP_LIT)
5975 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5977 size = AOP_SIZE (result);
5981 if (AOP_TYPE (left) == AOP_CRY)
5983 if (AOP_TYPE (right) == AOP_LIT)
5985 // c = bit | literal;
5988 // lit != 0 => result = 1
5989 if (AOP_TYPE (result) == AOP_CRY)
5992 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5994 continueIfTrue (ifx);
5997 emitcode ("setb", "c");
6001 // lit == 0 => result = left
6002 if (size && sameRegs (AOP (result), AOP (left)))
6004 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6009 if (AOP_TYPE (right) == AOP_CRY)
6012 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6013 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6018 symbol *tlbl = newiTempLabel (NULL);
6019 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6020 emitcode ("setb", "c");
6021 emitcode ("jb", "%s,%05d$",
6022 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6024 emitcode ("jnz", "%05d$", tlbl->key + 100);
6025 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6027 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6033 emitcode ("", "%05d$:", tlbl->key + 100);
6042 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6043 genIfxJump (ifx, "c", left, right, result);
6047 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6048 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6049 if ((AOP_TYPE (right) == AOP_LIT) &&
6050 (AOP_TYPE (result) == AOP_CRY) &&
6051 (AOP_TYPE (left) != AOP_CRY))
6057 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6059 continueIfTrue (ifx);
6064 // lit = 0, result = boolean(left)
6066 emitcode ("setb", "c");
6070 symbol *tlbl = newiTempLabel (NULL);
6071 emitcode ("jnz", "%05d$", tlbl->key + 100);
6073 emitcode ("", "%05d$:", tlbl->key + 100);
6077 genIfxJump (ifx, "a", left, right, result);
6085 /* if left is same as result */
6086 if (sameRegs (AOP (result), AOP (left)))
6088 for (; size--; offset++)
6090 if (AOP_TYPE (right) == AOP_LIT)
6092 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6095 /* dummy read of volatile operand */
6096 if (isOperandVolatile (left, FALSE))
6097 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6101 else if (bytelit == 0x0FF)
6103 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6105 else if (IS_AOP_PREG (left))
6107 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6108 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6109 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6113 emitcode ("orl", "%s,%s",
6114 aopGet (AOP (left), offset, FALSE, TRUE),
6115 aopGet (AOP (right), offset, FALSE, FALSE));
6120 if (AOP_TYPE (left) == AOP_ACC)
6121 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6124 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6125 if (IS_AOP_PREG (left))
6127 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6128 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6132 emitcode ("orl", "%s,a",
6133 aopGet (AOP (left), offset, FALSE, TRUE));
6141 // left & result in different registers
6142 if (AOP_TYPE (result) == AOP_CRY)
6145 // if(size), result in bit
6146 // if(!size && ifx), conditional oper: if(left | right)
6147 symbol *tlbl = newiTempLabel (NULL);
6148 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6150 emitcode ("setb", "c");
6153 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6154 emitcode ("orl", "a,%s",
6155 aopGet (AOP (right), offset, FALSE, FALSE));
6157 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6158 emitcode ("orl", "a,%s",
6159 aopGet (AOP (left), offset, FALSE, FALSE));
6161 emitcode ("jnz", "%05d$", tlbl->key + 100);
6167 emitcode ("", "%05d$:", tlbl->key + 100);
6171 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6173 emitcode ("", "%05d$:", tlbl->key + 100);
6177 for (; (size--); offset++)
6180 // result = left | right
6181 if (AOP_TYPE (right) == AOP_LIT)
6183 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6186 aopPut (AOP (result),
6187 aopGet (AOP (left), offset, FALSE, FALSE),
6189 isOperandVolatile (result, FALSE));
6192 else if (bytelit == 0x0FF)
6194 /* dummy read of volatile operand */
6195 if (isOperandVolatile (left, FALSE))
6196 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6197 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6201 // faster than result <- left, anl result,right
6202 // and better if result is SFR
6203 if (AOP_TYPE (left) == AOP_ACC)
6204 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6207 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6208 emitcode ("orl", "a,%s",
6209 aopGet (AOP (left), offset, FALSE, FALSE));
6211 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6217 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6219 freeAsmop (result, NULL, ic, TRUE);
6222 /*-----------------------------------------------------------------*/
6223 /* genXor - code for xclusive or */
6224 /*-----------------------------------------------------------------*/
6226 genXor (iCode * ic, iCode * ifx)
6228 operand *left, *right, *result;
6229 int size, offset = 0;
6230 unsigned long lit = 0L;
6233 D(emitcode ("; genXor",""));
6235 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6236 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6237 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6240 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6242 AOP_TYPE (left), AOP_TYPE (right));
6243 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6245 AOP_SIZE (left), AOP_SIZE (right));
6248 /* if left is a literal & right is not ||
6249 if left needs acc & right does not */
6250 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6251 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6253 operand *tmp = right;
6258 /* if result = right then exchange them */
6259 if (sameRegs (AOP (result), AOP (right)))
6261 operand *tmp = right;
6266 /* if right is bit then exchange them */
6267 if (AOP_TYPE (right) == AOP_CRY &&
6268 AOP_TYPE (left) != AOP_CRY)
6270 operand *tmp = right;
6274 if (AOP_TYPE (right) == AOP_LIT)
6275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6277 size = AOP_SIZE (result);
6281 if (AOP_TYPE (left) == AOP_CRY)
6283 if (AOP_TYPE (right) == AOP_LIT)
6285 // c = bit & literal;
6288 // lit>>1 != 0 => result = 1
6289 if (AOP_TYPE (result) == AOP_CRY)
6292 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6294 continueIfTrue (ifx);
6297 emitcode ("setb", "c");
6304 // lit == 0, result = left
6305 if (size && sameRegs (AOP (result), AOP (left)))
6307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6311 // lit == 1, result = not(left)
6312 if (size && sameRegs (AOP (result), AOP (left)))
6314 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6320 emitcode ("cpl", "c");
6329 symbol *tlbl = newiTempLabel (NULL);
6330 if (AOP_TYPE (right) == AOP_CRY)
6333 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6337 int sizer = AOP_SIZE (right);
6339 // if val>>1 != 0, result = 1
6340 emitcode ("setb", "c");
6343 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6345 // test the msb of the lsb
6346 emitcode ("anl", "a,#0xfe");
6347 emitcode ("jnz", "%05d$", tlbl->key + 100);
6351 emitcode ("rrc", "a");
6353 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6354 emitcode ("cpl", "c");
6355 emitcode ("", "%05d$:", (tlbl->key + 100));
6362 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6363 genIfxJump (ifx, "c", left, right, result);
6367 /* if left is same as result */
6368 if (sameRegs (AOP (result), AOP (left)))
6370 for (; size--; offset++)
6372 if (AOP_TYPE (right) == AOP_LIT)
6374 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6377 /* dummy read of volatile operand */
6378 if (isOperandVolatile (left, FALSE))
6379 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6383 else if (IS_AOP_PREG (left))
6385 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6386 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6387 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6391 emitcode ("xrl", "%s,%s",
6392 aopGet (AOP (left), offset, FALSE, TRUE),
6393 aopGet (AOP (right), offset, FALSE, FALSE));
6398 if (AOP_TYPE (left) == AOP_ACC)
6399 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6402 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6403 if (IS_AOP_PREG (left))
6405 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6406 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6409 emitcode ("xrl", "%s,a",
6410 aopGet (AOP (left), offset, FALSE, TRUE));
6417 // left & result in different registers
6418 if (AOP_TYPE (result) == AOP_CRY)
6421 // if(size), result in bit
6422 // if(!size && ifx), conditional oper: if(left ^ right)
6423 symbol *tlbl = newiTempLabel (NULL);
6424 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6426 emitcode ("setb", "c");
6429 if ((AOP_TYPE (right) == AOP_LIT) &&
6430 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6432 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6436 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6437 emitcode ("xrl", "a,%s",
6438 aopGet (AOP (right), offset, FALSE, FALSE));
6440 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6441 emitcode ("xrl", "a,%s",
6442 aopGet (AOP (left), offset, FALSE, FALSE));
6445 emitcode ("jnz", "%05d$", tlbl->key + 100);
6451 emitcode ("", "%05d$:", tlbl->key + 100);
6455 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6459 for (; (size--); offset++)
6462 // result = left & right
6463 if (AOP_TYPE (right) == AOP_LIT)
6465 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6468 aopPut (AOP (result),
6469 aopGet (AOP (left), offset, FALSE, FALSE),
6471 isOperandVolatile (result, FALSE));
6475 // faster than result <- left, anl result,right
6476 // and better if result is SFR
6477 if (AOP_TYPE (left) == AOP_ACC)
6478 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6481 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6482 emitcode ("xrl", "a,%s",
6483 aopGet (AOP (left), offset, FALSE, TRUE));
6485 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6491 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493 freeAsmop (result, NULL, ic, TRUE);
6496 /*-----------------------------------------------------------------*/
6497 /* genInline - write the inline code out */
6498 /*-----------------------------------------------------------------*/
6500 genInline (iCode * ic)
6502 char *buffer, *bp, *bp1;
6504 D(emitcode ("; genInline",""));
6506 _G.inLine += (!options.asmpeep);
6508 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6509 strcpy (buffer, IC_INLINE (ic));
6511 /* emit each line as a code */
6522 /* Add \n for labels, not dirs such as c:\mydir */
6523 if ( (*bp == ':') && (isspace(bp[1])) )
6537 /* emitcode("",buffer); */
6538 _G.inLine -= (!options.asmpeep);
6541 /*-----------------------------------------------------------------*/
6542 /* genRRC - rotate right with carry */
6543 /*-----------------------------------------------------------------*/
6547 operand *left, *result;
6548 int size, offset = 0;
6551 D(emitcode ("; genRRC",""));
6553 /* rotate right with carry */
6554 left = IC_LEFT (ic);
6555 result = IC_RESULT (ic);
6556 aopOp (left, ic, FALSE);
6557 aopOp (result, ic, FALSE);
6559 /* move it to the result */
6560 size = AOP_SIZE (result);
6562 if (size == 1) { /* special case for 1 byte */
6563 l = aopGet (AOP (left), offset, FALSE, FALSE);
6565 emitcode ("rr", "a");
6571 l = aopGet (AOP (left), offset, FALSE, FALSE);
6573 emitcode ("rrc", "a");
6574 if (AOP_SIZE (result) > 1)
6575 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6577 /* now we need to put the carry into the
6578 highest order byte of the result */
6579 if (AOP_SIZE (result) > 1)
6581 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6584 emitcode ("mov", "acc.7,c");
6586 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6587 freeAsmop (left, NULL, ic, TRUE);
6588 freeAsmop (result, NULL, ic, TRUE);
6591 /*-----------------------------------------------------------------*/
6592 /* genRLC - generate code for rotate left with carry */
6593 /*-----------------------------------------------------------------*/
6597 operand *left, *result;
6598 int size, offset = 0;
6601 D(emitcode ("; genRLC",""));
6603 /* rotate right with carry */
6604 left = IC_LEFT (ic);
6605 result = IC_RESULT (ic);
6606 aopOp (left, ic, FALSE);
6607 aopOp (result, ic, FALSE);
6609 /* move it to the result */
6610 size = AOP_SIZE (result);
6614 l = aopGet (AOP (left), offset, FALSE, FALSE);
6616 if (size == 0) { /* special case for 1 byte */
6620 emitcode ("add", "a,acc");
6621 if (AOP_SIZE (result) > 1)
6622 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6625 l = aopGet (AOP (left), offset, FALSE, FALSE);
6627 emitcode ("rlc", "a");
6628 if (AOP_SIZE (result) > 1)
6629 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6632 /* now we need to put the carry into the
6633 highest order byte of the result */
6634 if (AOP_SIZE (result) > 1)
6636 l = aopGet (AOP (result), 0, FALSE, FALSE);
6639 emitcode ("mov", "acc.0,c");
6641 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6642 freeAsmop (left, NULL, ic, TRUE);
6643 freeAsmop (result, NULL, ic, TRUE);
6646 /*-----------------------------------------------------------------*/
6647 /* genGetHbit - generates code get highest order bit */
6648 /*-----------------------------------------------------------------*/
6650 genGetHbit (iCode * ic)
6652 operand *left, *result;
6654 D(emitcode ("; genGetHbit",""));
6656 left = IC_LEFT (ic);
6657 result = IC_RESULT (ic);
6658 aopOp (left, ic, FALSE);
6659 aopOp (result, ic, FALSE);
6661 /* get the highest order byte into a */
6662 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6663 if (AOP_TYPE (result) == AOP_CRY)
6665 emitcode ("rlc", "a");
6670 emitcode ("rl", "a");
6671 emitcode ("anl", "a,#0x01");
6676 freeAsmop (left, NULL, ic, TRUE);
6677 freeAsmop (result, NULL, ic, TRUE);
6680 /*-----------------------------------------------------------------*/
6681 /* genSwap - generates code to swap nibbles or bytes */
6682 /*-----------------------------------------------------------------*/
6684 genSwap (iCode * ic)
6686 operand *left, *result;
6688 D(emitcode ("; genSwap",""));
6690 left = IC_LEFT (ic);
6691 result = IC_RESULT (ic);
6692 aopOp (left, ic, FALSE);
6693 aopOp (result, ic, FALSE);
6695 switch (AOP_SIZE (left))
6697 case 1: /* swap nibbles in byte */
6698 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6699 emitcode ("swap", "a");
6700 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6702 case 2: /* swap bytes in word */
6703 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6705 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6706 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6707 0, isOperandVolatile (result, FALSE));
6708 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6710 else if (operandsEqu (left, result))
6713 bool pushedB = FALSE, leftInB = FALSE;
6715 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6716 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6719 emitcode ("mov", "b,a");
6723 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6724 0, isOperandVolatile (result, FALSE));
6725 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6732 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6733 0, isOperandVolatile (result, FALSE));
6734 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6735 1, isOperandVolatile (result, FALSE));
6739 wassertl(FALSE, "unsupported SWAP operand size");
6742 freeAsmop (left, NULL, ic, TRUE);
6743 freeAsmop (result, NULL, ic, TRUE);
6747 /*-----------------------------------------------------------------*/
6748 /* AccRol - rotate left accumulator by known count */
6749 /*-----------------------------------------------------------------*/
6751 AccRol (int shCount)
6753 shCount &= 0x0007; // shCount : 0..7
6760 emitcode ("rl", "a");
6763 emitcode ("rl", "a");
6764 emitcode ("rl", "a");
6767 emitcode ("swap", "a");
6768 emitcode ("rr", "a");
6771 emitcode ("swap", "a");
6774 emitcode ("swap", "a");
6775 emitcode ("rl", "a");
6778 emitcode ("rr", "a");
6779 emitcode ("rr", "a");
6782 emitcode ("rr", "a");
6787 /*-----------------------------------------------------------------*/
6788 /* AccLsh - left shift accumulator by known count */
6789 /*-----------------------------------------------------------------*/
6791 AccLsh (int shCount)
6796 emitcode ("add", "a,acc");
6797 else if (shCount == 2)
6799 emitcode ("add", "a,acc");
6800 emitcode ("add", "a,acc");
6804 /* rotate left accumulator */
6806 /* and kill the lower order bits */
6807 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6812 /*-----------------------------------------------------------------*/
6813 /* AccRsh - right shift accumulator by known count */
6814 /*-----------------------------------------------------------------*/
6816 AccRsh (int shCount)
6823 emitcode ("rrc", "a");
6827 /* rotate right accumulator */
6828 AccRol (8 - shCount);
6829 /* and kill the higher order bits */
6830 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6835 /*-----------------------------------------------------------------*/
6836 /* AccSRsh - signed right shift accumulator by known count */
6837 /*-----------------------------------------------------------------*/
6839 AccSRsh (int shCount)
6846 emitcode ("mov", "c,acc.7");
6847 emitcode ("rrc", "a");
6849 else if (shCount == 2)
6851 emitcode ("mov", "c,acc.7");
6852 emitcode ("rrc", "a");
6853 emitcode ("mov", "c,acc.7");
6854 emitcode ("rrc", "a");
6858 tlbl = newiTempLabel (NULL);
6859 /* rotate right accumulator */
6860 AccRol (8 - shCount);
6861 /* and kill the higher order bits */
6862 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6863 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6864 emitcode ("orl", "a,#0x%02x",
6865 (unsigned char) ~SRMask[shCount]);
6866 emitcode ("", "%05d$:", tlbl->key + 100);
6871 /*-----------------------------------------------------------------*/
6872 /* shiftR1Left2Result - shift right one byte from left to result */
6873 /*-----------------------------------------------------------------*/
6875 shiftR1Left2Result (operand * left, int offl,
6876 operand * result, int offr,
6877 int shCount, int sign)
6879 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6880 /* shift right accumulator */
6885 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6888 /*-----------------------------------------------------------------*/
6889 /* shiftL1Left2Result - shift left one byte from left to result */
6890 /*-----------------------------------------------------------------*/
6892 shiftL1Left2Result (operand * left, int offl,
6893 operand * result, int offr, int shCount)
6896 l = aopGet (AOP (left), offl, FALSE, FALSE);
6898 /* shift left accumulator */
6900 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6903 /*-----------------------------------------------------------------*/
6904 /* movLeft2Result - move byte from left to result */
6905 /*-----------------------------------------------------------------*/
6907 movLeft2Result (operand * left, int offl,
6908 operand * result, int offr, int sign)
6911 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6913 l = aopGet (AOP (left), offl, FALSE, FALSE);
6915 if (*l == '@' && (IS_AOP_PREG (result)))
6917 emitcode ("mov", "a,%s", l);
6918 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6923 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6926 /* MSB sign in acc.7 ! */
6927 if (getDataSize (left) == offl + 1)
6929 emitcode ("mov", "a,%s", l);
6930 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6937 /*-----------------------------------------------------------------*/
6938 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6939 /*-----------------------------------------------------------------*/
6943 emitcode ("rrc", "a");
6944 emitcode ("xch", "a,%s", x);
6945 emitcode ("rrc", "a");
6946 emitcode ("xch", "a,%s", x);
6949 /*-----------------------------------------------------------------*/
6950 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6951 /*-----------------------------------------------------------------*/
6955 emitcode ("xch", "a,%s", x);
6956 emitcode ("rlc", "a");
6957 emitcode ("xch", "a,%s", x);
6958 emitcode ("rlc", "a");
6961 /*-----------------------------------------------------------------*/
6962 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6963 /*-----------------------------------------------------------------*/
6967 emitcode ("xch", "a,%s", x);
6968 emitcode ("add", "a,acc");
6969 emitcode ("xch", "a,%s", x);
6970 emitcode ("rlc", "a");
6973 /*-----------------------------------------------------------------*/
6974 /* AccAXLsh - left shift a:x by known count (0..7) */
6975 /*-----------------------------------------------------------------*/
6977 AccAXLsh (char *x, int shCount)
6992 case 5: // AAAAABBB:CCCCCDDD
6994 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6996 emitcode ("anl", "a,#0x%02x",
6997 SLMask[shCount]); // BBB00000:CCCCCDDD
6999 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7001 AccRol (shCount); // DDDCCCCC:BBB00000
7003 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7005 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7007 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7009 emitcode ("anl", "a,#0x%02x",
7010 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7012 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7014 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7017 case 6: // AAAAAABB:CCCCCCDD
7018 emitcode ("anl", "a,#0x%02x",
7019 SRMask[shCount]); // 000000BB:CCCCCCDD
7020 emitcode ("mov", "c,acc.0"); // c = B
7021 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7023 AccAXRrl1 (x); // BCCCCCCD:D000000B
7024 AccAXRrl1 (x); // BBCCCCCC:DD000000
7026 emitcode("rrc","a");
7027 emitcode("xch","a,%s", x);
7028 emitcode("rrc","a");
7029 emitcode("mov","c,acc.0"); //<< get correct bit
7030 emitcode("xch","a,%s", x);
7032 emitcode("rrc","a");
7033 emitcode("xch","a,%s", x);
7034 emitcode("rrc","a");
7035 emitcode("xch","a,%s", x);
7038 case 7: // a:x <<= 7
7040 emitcode ("anl", "a,#0x%02x",
7041 SRMask[shCount]); // 0000000B:CCCCCCCD
7043 emitcode ("mov", "c,acc.0"); // c = B
7045 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7047 AccAXRrl1 (x); // BCCCCCCC:D0000000
7055 /*-----------------------------------------------------------------*/
7056 /* AccAXRsh - right shift a:x known count (0..7) */
7057 /*-----------------------------------------------------------------*/
7059 AccAXRsh (char *x, int shCount)
7067 AccAXRrl1 (x); // 0->a:x
7072 AccAXRrl1 (x); // 0->a:x
7075 AccAXRrl1 (x); // 0->a:x
7080 case 5: // AAAAABBB:CCCCCDDD = a:x
7082 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7084 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7086 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7088 emitcode ("anl", "a,#0x%02x",
7089 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7091 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7093 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7095 emitcode ("anl", "a,#0x%02x",
7096 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7098 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7100 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7102 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7105 case 6: // AABBBBBB:CCDDDDDD
7107 emitcode ("mov", "c,acc.7");
7108 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7110 emitcode ("mov", "c,acc.7");
7111 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7113 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7115 emitcode ("anl", "a,#0x%02x",
7116 SRMask[shCount]); // 000000AA:BBBBBBCC
7119 case 7: // ABBBBBBB:CDDDDDDD
7121 emitcode ("mov", "c,acc.7"); // c = A
7123 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7125 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7127 emitcode ("anl", "a,#0x%02x",
7128 SRMask[shCount]); // 0000000A:BBBBBBBC
7136 /*-----------------------------------------------------------------*/
7137 /* AccAXRshS - right shift signed a:x known count (0..7) */
7138 /*-----------------------------------------------------------------*/
7140 AccAXRshS (char *x, int shCount)
7148 emitcode ("mov", "c,acc.7");
7149 AccAXRrl1 (x); // s->a:x
7153 emitcode ("mov", "c,acc.7");
7154 AccAXRrl1 (x); // s->a:x
7156 emitcode ("mov", "c,acc.7");
7157 AccAXRrl1 (x); // s->a:x
7162 case 5: // AAAAABBB:CCCCCDDD = a:x
7164 tlbl = newiTempLabel (NULL);
7165 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7167 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7169 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7171 emitcode ("anl", "a,#0x%02x",
7172 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7174 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7176 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7178 emitcode ("anl", "a,#0x%02x",
7179 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7181 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7183 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7185 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7187 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7188 emitcode ("orl", "a,#0x%02x",
7189 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7191 emitcode ("", "%05d$:", tlbl->key + 100);
7192 break; // SSSSAAAA:BBBCCCCC
7194 case 6: // AABBBBBB:CCDDDDDD
7196 tlbl = newiTempLabel (NULL);
7197 emitcode ("mov", "c,acc.7");
7198 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7200 emitcode ("mov", "c,acc.7");
7201 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7203 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7205 emitcode ("anl", "a,#0x%02x",
7206 SRMask[shCount]); // 000000AA:BBBBBBCC
7208 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7209 emitcode ("orl", "a,#0x%02x",
7210 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7212 emitcode ("", "%05d$:", tlbl->key + 100);
7214 case 7: // ABBBBBBB:CDDDDDDD
7216 tlbl = newiTempLabel (NULL);
7217 emitcode ("mov", "c,acc.7"); // c = A
7219 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7221 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7223 emitcode ("anl", "a,#0x%02x",
7224 SRMask[shCount]); // 0000000A:BBBBBBBC
7226 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7227 emitcode ("orl", "a,#0x%02x",
7228 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7230 emitcode ("", "%05d$:", tlbl->key + 100);
7237 /*-----------------------------------------------------------------*/
7238 /* shiftL2Left2Result - shift left two bytes from left to result */
7239 /*-----------------------------------------------------------------*/
7241 shiftL2Left2Result (operand * left, int offl,
7242 operand * result, int offr, int shCount)
7244 if (sameRegs (AOP (result), AOP (left)) &&
7245 ((offl + MSB16) == offr))
7247 /* don't crash result[offr] */
7248 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7249 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7253 movLeft2Result (left, offl, result, offr, 0);
7254 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7256 /* ax << shCount (x = lsb(result)) */
7257 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7258 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7262 /*-----------------------------------------------------------------*/
7263 /* shiftR2Left2Result - shift right two bytes from left to result */
7264 /*-----------------------------------------------------------------*/
7266 shiftR2Left2Result (operand * left, int offl,
7267 operand * result, int offr,
7268 int shCount, int sign)
7270 if (sameRegs (AOP (result), AOP (left)) &&
7271 ((offl + MSB16) == offr))
7273 /* don't crash result[offr] */
7274 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7275 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7279 movLeft2Result (left, offl, result, offr, 0);
7280 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7282 /* a:x >> shCount (x = lsb(result)) */
7284 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7286 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7287 if (getDataSize (result) > 1)
7288 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7291 /*-----------------------------------------------------------------*/
7292 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7293 /*-----------------------------------------------------------------*/
7295 shiftLLeftOrResult (operand * left, int offl,
7296 operand * result, int offr, int shCount)
7298 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7299 /* shift left accumulator */
7301 /* or with result */
7302 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7303 /* back to result */
7304 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7307 /*-----------------------------------------------------------------*/
7308 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7309 /*-----------------------------------------------------------------*/
7311 shiftRLeftOrResult (operand * left, int offl,
7312 operand * result, int offr, int shCount)
7314 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7315 /* shift right accumulator */
7317 /* or with result */
7318 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7319 /* back to result */
7320 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7323 /*-----------------------------------------------------------------*/
7324 /* genlshOne - left shift a one byte quantity by known count */
7325 /*-----------------------------------------------------------------*/
7327 genlshOne (operand * result, operand * left, int shCount)
7329 D(emitcode ("; genlshOne",""));
7331 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7334 /*-----------------------------------------------------------------*/
7335 /* genlshTwo - left shift two bytes by known amount != 0 */
7336 /*-----------------------------------------------------------------*/
7338 genlshTwo (operand * result, operand * left, int shCount)
7342 D(emitcode ("; genlshTwo",""));
7344 size = getDataSize (result);
7346 /* if shCount >= 8 */
7354 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7356 movLeft2Result (left, LSB, result, MSB16, 0);
7358 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7361 /* 1 <= shCount <= 7 */
7365 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7367 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7371 /*-----------------------------------------------------------------*/
7372 /* shiftLLong - shift left one long from left to result */
7373 /* offl = LSB or MSB16 */
7374 /*-----------------------------------------------------------------*/
7376 shiftLLong (operand * left, operand * result, int offr)
7379 int size = AOP_SIZE (result);
7381 if (size >= LSB + offr)
7383 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7385 emitcode ("add", "a,acc");
7386 if (sameRegs (AOP (left), AOP (result)) &&
7387 size >= MSB16 + offr && offr != LSB)
7388 emitcode ("xch", "a,%s",
7389 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7391 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7394 if (size >= MSB16 + offr)
7396 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7398 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7401 emitcode ("rlc", "a");
7402 if (sameRegs (AOP (left), AOP (result)) &&
7403 size >= MSB24 + offr && offr != LSB)
7404 emitcode ("xch", "a,%s",
7405 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7407 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7410 if (size >= MSB24 + offr)
7412 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7414 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7417 emitcode ("rlc", "a");
7418 if (sameRegs (AOP (left), AOP (result)) &&
7419 size >= MSB32 + offr && offr != LSB)
7420 emitcode ("xch", "a,%s",
7421 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7423 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7426 if (size > MSB32 + offr)
7428 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7430 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7433 emitcode ("rlc", "a");
7434 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7437 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7440 /*-----------------------------------------------------------------*/
7441 /* genlshFour - shift four byte by a known amount != 0 */
7442 /*-----------------------------------------------------------------*/
7444 genlshFour (operand * result, operand * left, int shCount)
7448 D(emitcode ("; genlshFour",""));
7450 size = AOP_SIZE (result);
7452 /* if shifting more that 3 bytes */
7457 /* lowest order of left goes to the highest
7458 order of the destination */
7459 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7461 movLeft2Result (left, LSB, result, MSB32, 0);
7462 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7463 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7464 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7468 /* more than two bytes */
7469 else if (shCount >= 16)
7471 /* lower order two bytes goes to higher order two bytes */
7473 /* if some more remaining */
7475 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7478 movLeft2Result (left, MSB16, result, MSB32, 0);
7479 movLeft2Result (left, LSB, result, MSB24, 0);
7481 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7482 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7486 /* if more than 1 byte */
7487 else if (shCount >= 8)
7489 /* lower order three bytes goes to higher order three bytes */
7494 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7496 movLeft2Result (left, LSB, result, MSB16, 0);
7502 movLeft2Result (left, MSB24, result, MSB32, 0);
7503 movLeft2Result (left, MSB16, result, MSB24, 0);
7504 movLeft2Result (left, LSB, result, MSB16, 0);
7505 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7507 else if (shCount == 1)
7508 shiftLLong (left, result, MSB16);
7511 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7512 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7513 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7514 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7519 /* 1 <= shCount <= 7 */
7520 else if (shCount <= 2)
7522 shiftLLong (left, result, LSB);
7524 shiftLLong (result, result, LSB);
7526 /* 3 <= shCount <= 7, optimize */
7529 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7530 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7531 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7535 /*-----------------------------------------------------------------*/
7536 /* genLeftShiftLiteral - left shifting by known count */
7537 /*-----------------------------------------------------------------*/
7539 genLeftShiftLiteral (operand * left,
7544 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7547 D(emitcode ("; genLeftShiftLiteral",""));
7549 freeAsmop (right, NULL, ic, TRUE);
7551 aopOp (left, ic, FALSE);
7552 aopOp (result, ic, FALSE);
7554 size = getSize (operandType (result));
7557 emitcode ("; shift left ", "result %d, left %d", size,
7561 /* I suppose that the left size >= result size */
7566 movLeft2Result (left, size, result, size, 0);
7570 else if (shCount >= (size * 8))
7572 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7578 genlshOne (result, left, shCount);
7582 genlshTwo (result, left, shCount);
7586 genlshFour (result, left, shCount);
7589 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7590 "*** ack! mystery literal shift!\n");
7594 freeAsmop (left, NULL, ic, TRUE);
7595 freeAsmop (result, NULL, ic, TRUE);
7598 /*-----------------------------------------------------------------*/
7599 /* genLeftShift - generates code for left shifting */
7600 /*-----------------------------------------------------------------*/
7602 genLeftShift (iCode * ic)
7604 operand *left, *right, *result;
7607 symbol *tlbl, *tlbl1;
7610 D(emitcode ("; genLeftShift",""));
7612 right = IC_RIGHT (ic);
7613 left = IC_LEFT (ic);
7614 result = IC_RESULT (ic);
7616 aopOp (right, ic, FALSE);
7618 /* if the shift count is known then do it
7619 as efficiently as possible */
7620 if (AOP_TYPE (right) == AOP_LIT)
7622 genLeftShiftLiteral (left, right, result, ic);
7626 /* shift count is unknown then we have to form
7627 a loop get the loop count in B : Note: we take
7628 only the lower order byte since shifting
7629 more that 32 bits make no sense anyway, ( the
7630 largest size of an object can be only 32 bits ) */
7633 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7634 emitcode ("inc", "b");
7635 freeAsmop (right, NULL, ic, TRUE);
7636 aopOp (left, ic, FALSE);
7637 aopOp (result, ic, FALSE);
7639 /* now move the left to the result if they are not the same */
7640 if (!sameRegs (AOP (left), AOP (result)) &&
7641 AOP_SIZE (result) > 1)
7644 size = AOP_SIZE (result);
7648 l = aopGet (AOP (left), offset, FALSE, TRUE);
7649 if (*l == '@' && (IS_AOP_PREG (result)))
7652 emitcode ("mov", "a,%s", l);
7653 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7656 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7661 tlbl = newiTempLabel (NULL);
7662 size = AOP_SIZE (result);
7664 tlbl1 = newiTempLabel (NULL);
7666 /* if it is only one byte then */
7669 symbol *tlbl1 = newiTempLabel (NULL);
7671 l = aopGet (AOP (left), 0, FALSE, FALSE);
7673 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7674 emitcode ("", "%05d$:", tlbl->key + 100);
7675 emitcode ("add", "a,acc");
7676 emitcode ("", "%05d$:", tlbl1->key + 100);
7677 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7679 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7683 reAdjustPreg (AOP (result));
7685 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7686 emitcode ("", "%05d$:", tlbl->key + 100);
7687 l = aopGet (AOP (result), offset, FALSE, FALSE);
7689 emitcode ("add", "a,acc");
7690 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7693 l = aopGet (AOP (result), offset, FALSE, FALSE);
7695 emitcode ("rlc", "a");
7696 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7698 reAdjustPreg (AOP (result));
7700 emitcode ("", "%05d$:", tlbl1->key + 100);
7701 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7704 freeAsmop (left, NULL, ic, TRUE);
7705 freeAsmop (result, NULL, ic, TRUE);
7708 /*-----------------------------------------------------------------*/
7709 /* genrshOne - right shift a one byte quantity by known count */
7710 /*-----------------------------------------------------------------*/
7712 genrshOne (operand * result, operand * left,
7713 int shCount, int sign)
7715 D(emitcode ("; genrshOne",""));
7717 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7720 /*-----------------------------------------------------------------*/
7721 /* genrshTwo - right shift two bytes by known amount != 0 */
7722 /*-----------------------------------------------------------------*/
7724 genrshTwo (operand * result, operand * left,
7725 int shCount, int sign)
7727 D(emitcode ("; genrshTwo",""));
7729 /* if shCount >= 8 */
7734 shiftR1Left2Result (left, MSB16, result, LSB,
7737 movLeft2Result (left, MSB16, result, LSB, sign);
7738 addSign (result, MSB16, sign);
7741 /* 1 <= shCount <= 7 */
7743 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7746 /*-----------------------------------------------------------------*/
7747 /* shiftRLong - shift right one long from left to result */
7748 /* offl = LSB or MSB16 */
7749 /*-----------------------------------------------------------------*/
7751 shiftRLong (operand * left, int offl,
7752 operand * result, int sign)
7754 int isSameRegs=sameRegs(AOP(left),AOP(result));
7756 if (isSameRegs && offl>1) {
7757 // we are in big trouble, but this shouldn't happen
7758 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7761 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7766 emitcode ("rlc", "a");
7767 emitcode ("subb", "a,acc");
7769 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7771 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7772 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7775 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7780 emitcode ("clr", "c");
7782 emitcode ("mov", "c,acc.7");
7785 emitcode ("rrc", "a");
7787 if (isSameRegs && offl==MSB16) {
7788 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7790 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7791 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7794 emitcode ("rrc", "a");
7795 if (isSameRegs && offl==1) {
7796 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7798 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7799 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7801 emitcode ("rrc", "a");
7802 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7806 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7807 emitcode ("rrc", "a");
7808 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7812 /*-----------------------------------------------------------------*/
7813 /* genrshFour - shift four byte by a known amount != 0 */
7814 /*-----------------------------------------------------------------*/
7816 genrshFour (operand * result, operand * left,
7817 int shCount, int sign)
7819 D(emitcode ("; genrshFour",""));
7821 /* if shifting more that 3 bytes */
7826 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7828 movLeft2Result (left, MSB32, result, LSB, sign);
7829 addSign (result, MSB16, sign);
7831 else if (shCount >= 16)
7835 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7838 movLeft2Result (left, MSB24, result, LSB, 0);
7839 movLeft2Result (left, MSB32, result, MSB16, sign);
7841 addSign (result, MSB24, sign);
7843 else if (shCount >= 8)
7847 shiftRLong (left, MSB16, result, sign);
7848 else if (shCount == 0)
7850 movLeft2Result (left, MSB16, result, LSB, 0);
7851 movLeft2Result (left, MSB24, result, MSB16, 0);
7852 movLeft2Result (left, MSB32, result, MSB24, sign);
7853 addSign (result, MSB32, sign);
7857 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7858 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7859 /* the last shift is signed */
7860 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7861 addSign (result, MSB32, sign);
7865 { /* 1 <= shCount <= 7 */
7868 shiftRLong (left, LSB, result, sign);
7870 shiftRLong (result, LSB, result, sign);
7874 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7875 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7876 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7881 /*-----------------------------------------------------------------*/
7882 /* genRightShiftLiteral - right shifting by known count */
7883 /*-----------------------------------------------------------------*/
7885 genRightShiftLiteral (operand * left,
7891 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7894 D(emitcode ("; genRightShiftLiteral",""));
7896 freeAsmop (right, NULL, ic, TRUE);
7898 aopOp (left, ic, FALSE);
7899 aopOp (result, ic, FALSE);
7902 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7906 size = getDataSize (left);
7907 /* test the LEFT size !!! */
7909 /* I suppose that the left size >= result size */
7912 size = getDataSize (result);
7914 movLeft2Result (left, size, result, size, 0);
7917 else if (shCount >= (size * 8))
7920 /* get sign in acc.7 */
7921 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7923 addSign (result, LSB, sign);
7930 genrshOne (result, left, shCount, sign);
7934 genrshTwo (result, left, shCount, sign);
7938 genrshFour (result, left, shCount, sign);
7944 freeAsmop (left, NULL, ic, TRUE);
7945 freeAsmop (result, NULL, ic, TRUE);
7948 /*-----------------------------------------------------------------*/
7949 /* genSignedRightShift - right shift of signed number */
7950 /*-----------------------------------------------------------------*/
7952 genSignedRightShift (iCode * ic)
7954 operand *right, *left, *result;
7957 symbol *tlbl, *tlbl1;
7960 D(emitcode ("; genSignedRightShift",""));
7962 /* we do it the hard way put the shift count in b
7963 and loop thru preserving the sign */
7965 right = IC_RIGHT (ic);
7966 left = IC_LEFT (ic);
7967 result = IC_RESULT (ic);
7969 aopOp (right, ic, FALSE);
7972 if (AOP_TYPE (right) == AOP_LIT)
7974 genRightShiftLiteral (left, right, result, ic, 1);
7977 /* shift count is unknown then we have to form
7978 a loop get the loop count in B : Note: we take
7979 only the lower order byte since shifting
7980 more that 32 bits make no sense anyway, ( the
7981 largest size of an object can be only 32 bits ) */
7984 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7985 emitcode ("inc", "b");
7986 freeAsmop (right, NULL, ic, TRUE);
7987 aopOp (left, ic, FALSE);
7988 aopOp (result, ic, FALSE);
7990 /* now move the left to the result if they are not the
7992 if (!sameRegs (AOP (left), AOP (result)) &&
7993 AOP_SIZE (result) > 1)
7996 size = AOP_SIZE (result);
8000 l = aopGet (AOP (left), offset, FALSE, TRUE);
8001 if (*l == '@' && IS_AOP_PREG (result))
8004 emitcode ("mov", "a,%s", l);
8005 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8008 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8013 /* mov the highest order bit to OVR */
8014 tlbl = newiTempLabel (NULL);
8015 tlbl1 = newiTempLabel (NULL);
8017 size = AOP_SIZE (result);
8019 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8020 emitcode ("rlc", "a");
8021 emitcode ("mov", "ov,c");
8022 /* if it is only one byte then */
8025 l = aopGet (AOP (left), 0, FALSE, FALSE);
8027 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8028 emitcode ("", "%05d$:", tlbl->key + 100);
8029 emitcode ("mov", "c,ov");
8030 emitcode ("rrc", "a");
8031 emitcode ("", "%05d$:", tlbl1->key + 100);
8032 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8034 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8038 reAdjustPreg (AOP (result));
8039 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8040 emitcode ("", "%05d$:", tlbl->key + 100);
8041 emitcode ("mov", "c,ov");
8044 l = aopGet (AOP (result), offset, FALSE, FALSE);
8046 emitcode ("rrc", "a");
8047 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8049 reAdjustPreg (AOP (result));
8050 emitcode ("", "%05d$:", tlbl1->key + 100);
8051 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8055 freeAsmop (left, NULL, ic, TRUE);
8056 freeAsmop (result, NULL, ic, TRUE);
8059 /*-----------------------------------------------------------------*/
8060 /* genRightShift - generate code for right shifting */
8061 /*-----------------------------------------------------------------*/
8063 genRightShift (iCode * ic)
8065 operand *right, *left, *result;
8069 symbol *tlbl, *tlbl1;
8072 D(emitcode ("; genRightShift",""));
8074 /* if signed then we do it the hard way preserve the
8075 sign bit moving it inwards */
8076 letype = getSpec (operandType (IC_LEFT (ic)));
8078 if (!SPEC_USIGN (letype))
8080 genSignedRightShift (ic);
8084 /* signed & unsigned types are treated the same : i.e. the
8085 signed is NOT propagated inwards : quoting from the
8086 ANSI - standard : "for E1 >> E2, is equivalent to division
8087 by 2**E2 if unsigned or if it has a non-negative value,
8088 otherwise the result is implementation defined ", MY definition
8089 is that the sign does not get propagated */
8091 right = IC_RIGHT (ic);
8092 left = IC_LEFT (ic);
8093 result = IC_RESULT (ic);
8095 aopOp (right, ic, FALSE);
8097 /* if the shift count is known then do it
8098 as efficiently as possible */
8099 if (AOP_TYPE (right) == AOP_LIT)
8101 genRightShiftLiteral (left, right, result, ic, 0);
8105 /* shift count is unknown then we have to form
8106 a loop get the loop count in B : Note: we take
8107 only the lower order byte since shifting
8108 more that 32 bits make no sense anyway, ( the
8109 largest size of an object can be only 32 bits ) */
8112 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8113 emitcode ("inc", "b");
8114 freeAsmop (right, NULL, ic, TRUE);
8115 aopOp (left, ic, FALSE);
8116 aopOp (result, ic, FALSE);
8118 /* now move the left to the result if they are not the
8120 if (!sameRegs (AOP (left), AOP (result)) &&
8121 AOP_SIZE (result) > 1)
8124 size = AOP_SIZE (result);
8128 l = aopGet (AOP (left), offset, FALSE, TRUE);
8129 if (*l == '@' && IS_AOP_PREG (result))
8132 emitcode ("mov", "a,%s", l);
8133 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8136 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8141 tlbl = newiTempLabel (NULL);
8142 tlbl1 = newiTempLabel (NULL);
8143 size = AOP_SIZE (result);
8146 /* if it is only one byte then */
8149 l = aopGet (AOP (left), 0, FALSE, FALSE);
8151 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8152 emitcode ("", "%05d$:", tlbl->key + 100);
8154 emitcode ("rrc", "a");
8155 emitcode ("", "%05d$:", tlbl1->key + 100);
8156 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8158 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8162 reAdjustPreg (AOP (result));
8163 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8164 emitcode ("", "%05d$:", tlbl->key + 100);
8168 l = aopGet (AOP (result), offset, FALSE, FALSE);
8170 emitcode ("rrc", "a");
8171 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8173 reAdjustPreg (AOP (result));
8175 emitcode ("", "%05d$:", tlbl1->key + 100);
8176 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8180 freeAsmop (left, NULL, ic, TRUE);
8181 freeAsmop (result, NULL, ic, TRUE);
8184 /*-----------------------------------------------------------------*/
8185 /* emitPtrByteGet - emits code to get a byte into A through a */
8186 /* pointer register (R0, R1, or DPTR). The */
8187 /* original value of A can be preserved in B. */
8188 /*-----------------------------------------------------------------*/
8190 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8197 emitcode ("mov", "b,a");
8198 emitcode ("mov", "a,@%s", rname);
8203 emitcode ("mov", "b,a");
8204 emitcode ("movx", "a,@%s", rname);
8209 emitcode ("mov", "b,a");
8210 emitcode ("movx", "a,@dptr");
8215 emitcode ("mov", "b,a");
8216 emitcode ("clr", "a");
8217 emitcode ("movc", "a,@a+dptr");
8223 emitcode ("push", "b");
8224 emitcode ("push", "acc");
8226 emitcode ("lcall", "__gptrget");
8228 emitcode ("pop", "b");
8233 /*-----------------------------------------------------------------*/
8234 /* emitPtrByteSet - emits code to set a byte from src through a */
8235 /* pointer register (R0, R1, or DPTR). */
8236 /*-----------------------------------------------------------------*/
8238 emitPtrByteSet (char *rname, int p_type, char *src)
8247 emitcode ("mov", "@%s,a", rname);
8250 emitcode ("mov", "@%s,%s", rname, src);
8255 emitcode ("movx", "@%s,a", rname);
8260 emitcode ("movx", "@dptr,a");
8265 emitcode ("lcall", "__gptrput");
8270 /*-----------------------------------------------------------------*/
8271 /* genUnpackBits - generates code for unpacking bits */
8272 /*-----------------------------------------------------------------*/
8274 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8276 int offset = 0; /* result byte offset */
8277 int rsize; /* result size */
8278 int rlen = 0; /* remaining bitfield length */
8279 sym_link *etype; /* bitfield type information */
8280 int blen; /* bitfield length */
8281 int bstr; /* bitfield starting bit within byte */
8284 D(emitcode ("; genUnpackBits",""));
8286 etype = getSpec (operandType (result));
8287 rsize = getSize (operandType (result));
8288 blen = SPEC_BLEN (etype);
8289 bstr = SPEC_BSTR (etype);
8291 if (ifx && blen <= 8)
8293 emitPtrByteGet (rname, ptype, FALSE);
8296 SNPRINTF (buffer, sizeof(buffer),
8298 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8303 emitcode ("anl", "a,#0x%02x",
8304 (((unsigned char) -1) >> (8 - blen)) << bstr);
8305 genIfxJump (ifx, "a", NULL, NULL, NULL);
8311 /* If the bitfield length is less than a byte */
8314 emitPtrByteGet (rname, ptype, FALSE);
8316 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8317 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8321 /* Bit field did not fit in a byte. Copy all
8322 but the partial byte at the end. */
8323 for (rlen=blen;rlen>=8;rlen-=8)
8325 emitPtrByteGet (rname, ptype, FALSE);
8326 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8328 emitcode ("inc", "%s", rname);
8331 /* Handle the partial byte at the end */
8334 emitPtrByteGet (rname, ptype, FALSE);
8335 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8336 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8344 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8349 /*-----------------------------------------------------------------*/
8350 /* genDataPointerGet - generates code when ptr offset is known */
8351 /*-----------------------------------------------------------------*/
8353 genDataPointerGet (operand * left,
8359 int size, offset = 0;
8361 D(emitcode ("; genDataPointerGet",""));
8363 aopOp (result, ic, TRUE);
8365 /* get the string representation of the name */
8366 l = aopGet (AOP (left), 0, FALSE, TRUE);
8367 size = AOP_SIZE (result);
8371 sprintf (buffer, "(%s + %d)", l + 1, offset);
8373 sprintf (buffer, "%s", l + 1);
8374 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8377 freeAsmop (left, NULL, ic, TRUE);
8378 freeAsmop (result, NULL, ic, TRUE);
8381 /*-----------------------------------------------------------------*/
8382 /* genNearPointerGet - emitcode for near pointer fetch */
8383 /*-----------------------------------------------------------------*/
8385 genNearPointerGet (operand * left,
8394 sym_link *rtype, *retype;
8395 sym_link *ltype = operandType (left);
8398 D(emitcode ("; genNearPointerGet",""));
8400 rtype = operandType (result);
8401 retype = getSpec (rtype);
8403 aopOp (left, ic, FALSE);
8405 /* if left is rematerialisable and
8406 result is not bitfield variable type and
8407 the left is pointer to data space i.e
8408 lower 128 bytes of space */
8409 if (AOP_TYPE (left) == AOP_IMMD &&
8410 !IS_BITFIELD (retype) &&
8411 DCL_TYPE (ltype) == POINTER)
8413 genDataPointerGet (left, result, ic);
8417 /* if the value is already in a pointer register
8418 then don't need anything more */
8419 if (!AOP_INPREG (AOP (left)))
8421 if (IS_AOP_PREG (left))
8423 // Aha, it is a pointer, just in disguise.
8424 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8427 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8428 __FILE__, __LINE__);
8433 emitcode ("mov", "a%s,%s", rname + 1, rname);
8434 rname++; // skip the '@'.
8439 /* otherwise get a free pointer register */
8441 preg = getFreePtr (ic, &aop, FALSE);
8442 emitcode ("mov", "%s,%s",
8444 aopGet (AOP (left), 0, FALSE, TRUE));
8449 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8451 //aopOp (result, ic, FALSE);
8452 aopOp (result, ic, result?TRUE:FALSE);
8454 /* if bitfield then unpack the bits */
8455 if (IS_BITFIELD (retype))
8456 genUnpackBits (result, rname, POINTER, ifx);
8459 /* we have can just get the values */
8460 int size = AOP_SIZE (result);
8465 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8468 emitcode ("mov", "a,@%s", rname);
8470 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8474 sprintf (buffer, "@%s", rname);
8475 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8479 emitcode ("inc", "%s", rname);
8483 /* now some housekeeping stuff */
8484 if (aop) /* we had to allocate for this iCode */
8486 if (pi) { /* post increment present */
8487 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8489 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8493 /* we did not allocate which means left
8494 already in a pointer register, then
8495 if size > 0 && this could be used again
8496 we have to point it back to where it
8498 if ((AOP_SIZE (result) > 1 &&
8499 !OP_SYMBOL (left)->remat &&
8500 (OP_SYMBOL (left)->liveTo > ic->seq ||
8504 int size = AOP_SIZE (result) - 1;
8506 emitcode ("dec", "%s", rname);
8510 if (ifx && !ifx->generated)
8512 genIfxJump (ifx, "a", left, NULL, result);
8516 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8517 freeAsmop (left, NULL, ic, TRUE);
8518 if (pi) pi->generated = 1;
8521 /*-----------------------------------------------------------------*/
8522 /* genPagedPointerGet - emitcode for paged pointer fetch */
8523 /*-----------------------------------------------------------------*/
8525 genPagedPointerGet (operand * left,
8534 sym_link *rtype, *retype;
8536 D(emitcode ("; genPagedPointerGet",""));
8538 rtype = operandType (result);
8539 retype = getSpec (rtype);
8541 aopOp (left, ic, FALSE);
8543 /* if the value is already in a pointer register
8544 then don't need anything more */
8545 if (!AOP_INPREG (AOP (left)))
8547 /* otherwise get a free pointer register */
8549 preg = getFreePtr (ic, &aop, FALSE);
8550 emitcode ("mov", "%s,%s",
8552 aopGet (AOP (left), 0, FALSE, TRUE));
8556 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8558 aopOp (result, ic, FALSE);
8560 /* if bitfield then unpack the bits */
8561 if (IS_BITFIELD (retype))
8562 genUnpackBits (result, rname, PPOINTER, ifx);
8565 /* we have can just get the values */
8566 int size = AOP_SIZE (result);
8572 emitcode ("movx", "a,@%s", rname);
8574 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8579 emitcode ("inc", "%s", rname);
8583 /* now some housekeeping stuff */
8584 if (aop) /* we had to allocate for this iCode */
8586 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8587 freeAsmop (NULL, aop, ic, TRUE);
8591 /* we did not allocate which means left
8592 already in a pointer register, then
8593 if size > 0 && this could be used again
8594 we have to point it back to where it
8596 if ((AOP_SIZE (result) > 1 &&
8597 !OP_SYMBOL (left)->remat &&
8598 (OP_SYMBOL (left)->liveTo > ic->seq ||
8602 int size = AOP_SIZE (result) - 1;
8604 emitcode ("dec", "%s", rname);
8608 if (ifx && !ifx->generated)
8610 genIfxJump (ifx, "a", left, NULL, result);
8614 freeAsmop (left, NULL, ic, TRUE);
8615 freeAsmop (result, NULL, ic, TRUE);
8616 if (pi) pi->generated = 1;
8620 /*--------------------------------------------------------------------*/
8621 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8622 /*--------------------------------------------------------------------*/
8624 loadDptrFromOperand (operand *op, bool loadBToo)
8626 if (AOP_TYPE (op) != AOP_STR)
8628 /* if this is rematerializable */
8629 if (AOP_TYPE (op) == AOP_IMMD)
8631 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8634 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8635 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8638 wassertl(FALSE, "need pointerCode");
8639 emitcode ("", "; mov b,???");
8640 /* genPointerGet and genPointerSet originally did different
8641 ** things for this case. Both seem wrong.
8642 ** from genPointerGet:
8643 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8644 ** from genPointerSet:
8645 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8650 else if (AOP_TYPE (op) == AOP_DPTR)
8654 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8655 emitcode ("push", "acc");
8656 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8657 emitcode ("push", "acc");
8658 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8659 emitcode ("pop", "dph");
8660 emitcode ("pop", "dpl");
8664 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8665 emitcode ("push", "acc");
8666 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8667 emitcode ("pop", "dpl");
8671 { /* we need to get it byte by byte */
8672 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8673 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8675 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8680 /*-----------------------------------------------------------------*/
8681 /* genFarPointerGet - gget value from far space */
8682 /*-----------------------------------------------------------------*/
8684 genFarPointerGet (operand * left,
8685 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8688 sym_link *retype = getSpec (operandType (result));
8690 D(emitcode ("; genFarPointerGet",""));
8692 aopOp (left, ic, FALSE);
8693 loadDptrFromOperand (left, FALSE);
8695 /* so dptr now contains the address */
8696 aopOp (result, ic, FALSE);
8698 /* if bit then unpack */
8699 if (IS_BITFIELD (retype))
8700 genUnpackBits (result, "dptr", FPOINTER, ifx);
8703 size = AOP_SIZE (result);
8708 emitcode ("movx", "a,@dptr");
8710 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8712 emitcode ("inc", "dptr");
8716 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8718 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8719 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8723 if (ifx && !ifx->generated)
8725 genIfxJump (ifx, "a", left, NULL, result);
8728 freeAsmop (left, NULL, ic, TRUE);
8729 freeAsmop (result, NULL, ic, TRUE);
8732 /*-----------------------------------------------------------------*/
8733 /* genCodePointerGet - gget value from code space */
8734 /*-----------------------------------------------------------------*/
8736 genCodePointerGet (operand * left,
8737 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8740 sym_link *retype = getSpec (operandType (result));
8742 D(emitcode ("; genCodePointerGet",""));
8744 aopOp (left, ic, FALSE);
8745 loadDptrFromOperand (left, FALSE);
8747 /* so dptr now contains the address */
8748 aopOp (result, ic, FALSE);
8750 /* if bit then unpack */
8751 if (IS_BITFIELD (retype))
8752 genUnpackBits (result, "dptr", CPOINTER, ifx);
8755 size = AOP_SIZE (result);
8762 emitcode ("clr", "a");
8763 emitcode ("movc", "a,@a+dptr");
8765 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8766 emitcode ("inc", "dptr");
8770 emitcode ("mov", "a,#0x%02x", offset);
8771 emitcode ("movc", "a,@a+dptr");
8773 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8778 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8780 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8781 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8785 if (ifx && !ifx->generated)
8787 genIfxJump (ifx, "a", left, NULL, result);
8790 freeAsmop (left, NULL, ic, TRUE);
8791 freeAsmop (result, NULL, ic, TRUE);
8794 /*-----------------------------------------------------------------*/
8795 /* genGenPointerGet - gget value from generic pointer space */
8796 /*-----------------------------------------------------------------*/
8798 genGenPointerGet (operand * left,
8799 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8802 sym_link *retype = getSpec (operandType (result));
8804 D(emitcode ("; genGenPointerGet",""));
8806 aopOp (left, ic, FALSE);
8807 loadDptrFromOperand (left, TRUE);
8809 /* so dptr know contains the address */
8810 aopOp (result, ic, FALSE);
8812 /* if bit then unpack */
8813 if (IS_BITFIELD (retype))
8814 genUnpackBits (result, "dptr", GPOINTER, ifx);
8817 size = AOP_SIZE (result);
8822 emitcode ("lcall", "__gptrget");
8824 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8826 emitcode ("inc", "dptr");
8830 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8832 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8833 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8837 if (ifx && !ifx->generated)
8839 genIfxJump (ifx, "a", left, NULL, result);
8843 freeAsmop (left, NULL, ic, TRUE);
8844 freeAsmop (result, NULL, ic, TRUE);
8847 /*-----------------------------------------------------------------*/
8848 /* genPointerGet - generate code for pointer get */
8849 /*-----------------------------------------------------------------*/
8851 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8853 operand *left, *result;
8854 sym_link *type, *etype;
8857 D(emitcode ("; genPointerGet",""));
8859 left = IC_LEFT (ic);
8860 result = IC_RESULT (ic);
8862 if (getSize (operandType (result))>1)
8865 /* depending on the type of pointer we need to
8866 move it to the correct pointer register */
8867 type = operandType (left);
8868 etype = getSpec (type);
8869 /* if left is of type of pointer then it is simple */
8870 if (IS_PTR (type) && !IS_FUNC (type->next))
8871 p_type = DCL_TYPE (type);
8874 /* we have to go by the storage class */
8875 p_type = PTR_TYPE (SPEC_OCLS (etype));
8878 /* special case when cast remat */
8879 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8880 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8881 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8882 type = operandType (left);
8883 p_type = DCL_TYPE (type);
8885 /* now that we have the pointer type we assign
8886 the pointer values */
8892 genNearPointerGet (left, result, ic, pi, ifx);
8896 genPagedPointerGet (left, result, ic, pi, ifx);
8900 genFarPointerGet (left, result, ic, pi, ifx);
8904 genCodePointerGet (left, result, ic, pi, ifx);
8908 genGenPointerGet (left, result, ic, pi, ifx);
8916 /*-----------------------------------------------------------------*/
8917 /* genPackBits - generates code for packed bit storage */
8918 /*-----------------------------------------------------------------*/
8920 genPackBits (sym_link * etype,
8922 char *rname, int p_type)
8924 int offset = 0; /* source byte offset */
8925 int rlen = 0; /* remaining bitfield length */
8926 int blen; /* bitfield length */
8927 int bstr; /* bitfield starting bit within byte */
8928 int litval; /* source literal value (if AOP_LIT) */
8929 unsigned char mask; /* bitmask within current byte */
8931 D(emitcode ("; genPackBits",""));
8933 blen = SPEC_BLEN (etype);
8934 bstr = SPEC_BSTR (etype);
8936 /* If the bitfield length is less than a byte */
8939 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8940 (unsigned char) (0xFF >> (8 - bstr)));
8942 if (AOP_TYPE (right) == AOP_LIT)
8944 /* Case with a bitfield length <8 and literal source
8946 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8948 litval &= (~mask) & 0xff;
8949 emitPtrByteGet (rname, p_type, FALSE);
8950 if ((mask|litval)!=0xff)
8951 emitcode ("anl","a,#0x%02x", mask);
8953 emitcode ("orl","a,#0x%02x", litval);
8957 if ((blen==1) && (p_type!=GPOINTER))
8959 /* Case with a bitfield length == 1 and no generic pointer
8961 if (AOP_TYPE (right) == AOP_CRY)
8962 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8965 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8966 emitcode ("rrc","a");
8968 emitPtrByteGet (rname, p_type, FALSE);
8969 emitcode ("mov","acc.%d,c",bstr);
8974 /* Case with a bitfield length < 8 and arbitrary source
8976 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8977 /* shift and mask source value */
8979 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8982 /* transfer A to B and get next byte */
8983 emitPtrByteGet (rname, p_type, TRUE);
8985 emitcode ("anl", "a,#0x%02x", mask);
8986 emitcode ("orl", "a,b");
8987 if (p_type == GPOINTER)
8988 emitcode ("pop", "b");
8994 emitPtrByteSet (rname, p_type, "a");
8998 /* Bit length is greater than 7 bits. In this case, copy */
8999 /* all except the partial byte at the end */
9000 for (rlen=blen;rlen>=8;rlen-=8)
9002 emitPtrByteSet (rname, p_type,
9003 aopGet (AOP (right), offset++, FALSE, TRUE) );
9005 emitcode ("inc", "%s", rname);
9008 /* If there was a partial byte at the end */
9011 mask = (((unsigned char) -1 << rlen) & 0xff);
9013 if (AOP_TYPE (right) == AOP_LIT)
9015 /* Case with partial byte and literal source
9017 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9018 litval >>= (blen-rlen);
9019 litval &= (~mask) & 0xff;
9020 emitPtrByteGet (rname, p_type, FALSE);
9021 if ((mask|litval)!=0xff)
9022 emitcode ("anl","a,#0x%02x", mask);
9024 emitcode ("orl","a,#0x%02x", litval);
9029 /* Case with partial byte and arbitrary source
9031 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9032 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9035 /* transfer A to B and get next byte */
9036 emitPtrByteGet (rname, p_type, TRUE);
9038 emitcode ("anl", "a,#0x%02x", mask);
9039 emitcode ("orl", "a,b");
9040 if (p_type == GPOINTER)
9041 emitcode ("pop", "b");
9045 emitPtrByteSet (rname, p_type, "a");
9051 /*-----------------------------------------------------------------*/
9052 /* genDataPointerSet - remat pointer to data space */
9053 /*-----------------------------------------------------------------*/
9055 genDataPointerSet (operand * right,
9059 int size, offset = 0;
9060 char *l, buffer[256];
9062 D(emitcode ("; genDataPointerSet",""));
9064 aopOp (right, ic, FALSE);
9066 l = aopGet (AOP (result), 0, FALSE, TRUE);
9067 size = AOP_SIZE (right);
9071 sprintf (buffer, "(%s + %d)", l + 1, offset);
9073 sprintf (buffer, "%s", l + 1);
9074 emitcode ("mov", "%s,%s", buffer,
9075 aopGet (AOP (right), offset++, FALSE, FALSE));
9078 freeAsmop (right, NULL, ic, TRUE);
9079 freeAsmop (result, NULL, ic, TRUE);
9082 /*-----------------------------------------------------------------*/
9083 /* genNearPointerSet - emitcode for near pointer put */
9084 /*-----------------------------------------------------------------*/
9086 genNearPointerSet (operand * right,
9094 sym_link *retype, *letype;
9095 sym_link *ptype = operandType (result);
9097 D(emitcode ("; genNearPointerSet",""));
9099 retype = getSpec (operandType (right));
9100 letype = getSpec (ptype);
9101 aopOp (result, ic, FALSE);
9103 /* if the result is rematerializable &
9104 in data space & not a bit variable */
9105 if (AOP_TYPE (result) == AOP_IMMD &&
9106 DCL_TYPE (ptype) == POINTER &&
9107 !IS_BITVAR (retype) &&
9108 !IS_BITVAR (letype))
9110 genDataPointerSet (right, result, ic);
9114 /* if the value is already in a pointer register
9115 then don't need anything more */
9116 if (!AOP_INPREG (AOP (result)))
9119 //AOP_TYPE (result) == AOP_STK
9123 // Aha, it is a pointer, just in disguise.
9124 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9127 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9128 __FILE__, __LINE__);
9133 emitcode ("mov", "a%s,%s", rname + 1, rname);
9134 rname++; // skip the '@'.
9139 /* otherwise get a free pointer register */
9141 preg = getFreePtr (ic, &aop, FALSE);
9142 emitcode ("mov", "%s,%s",
9144 aopGet (AOP (result), 0, FALSE, TRUE));
9150 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9153 aopOp (right, ic, FALSE);
9155 /* if bitfield then unpack the bits */
9156 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9157 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9160 /* we have can just get the values */
9161 int size = AOP_SIZE (right);
9166 l = aopGet (AOP (right), offset, FALSE, TRUE);
9170 emitcode ("mov", "@%s,a", rname);
9173 emitcode ("mov", "@%s,%s", rname, l);
9175 emitcode ("inc", "%s", rname);
9180 /* now some housekeeping stuff */
9181 if (aop) /* we had to allocate for this iCode */
9184 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9185 freeAsmop (NULL, aop, ic, TRUE);
9189 /* we did not allocate which means left
9190 already in a pointer register, then
9191 if size > 0 && this could be used again
9192 we have to point it back to where it
9194 if ((AOP_SIZE (right) > 1 &&
9195 !OP_SYMBOL (result)->remat &&
9196 (OP_SYMBOL (result)->liveTo > ic->seq ||
9200 int size = AOP_SIZE (right) - 1;
9202 emitcode ("dec", "%s", rname);
9207 if (pi) pi->generated = 1;
9208 freeAsmop (result, NULL, ic, TRUE);
9209 freeAsmop (right, NULL, ic, TRUE);
9212 /*-----------------------------------------------------------------*/
9213 /* genPagedPointerSet - emitcode for Paged pointer put */
9214 /*-----------------------------------------------------------------*/
9216 genPagedPointerSet (operand * right,
9224 sym_link *retype, *letype;
9226 D(emitcode ("; genPagedPointerSet",""));
9228 retype = getSpec (operandType (right));
9229 letype = getSpec (operandType (result));
9231 aopOp (result, ic, FALSE);
9233 /* if the value is already in a pointer register
9234 then don't need anything more */
9235 if (!AOP_INPREG (AOP (result)))
9237 /* otherwise get a free pointer register */
9239 preg = getFreePtr (ic, &aop, FALSE);
9240 emitcode ("mov", "%s,%s",
9242 aopGet (AOP (result), 0, FALSE, TRUE));
9246 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9248 aopOp (right, ic, FALSE);
9250 /* if bitfield then unpack the bits */
9251 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9252 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9255 /* we have can just get the values */
9256 int size = AOP_SIZE (right);
9261 l = aopGet (AOP (right), offset, FALSE, TRUE);
9264 emitcode ("movx", "@%s,a", rname);
9267 emitcode ("inc", "%s", rname);
9273 /* now some housekeeping stuff */
9274 if (aop) /* we had to allocate for this iCode */
9277 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9278 freeAsmop (NULL, aop, ic, TRUE);
9282 /* we did not allocate which means left
9283 already in a pointer register, then
9284 if size > 0 && this could be used again
9285 we have to point it back to where it
9287 if (AOP_SIZE (right) > 1 &&
9288 !OP_SYMBOL (result)->remat &&
9289 (OP_SYMBOL (result)->liveTo > ic->seq ||
9292 int size = AOP_SIZE (right) - 1;
9294 emitcode ("dec", "%s", rname);
9299 if (pi) pi->generated = 1;
9300 freeAsmop (result, NULL, ic, TRUE);
9301 freeAsmop (right, NULL, ic, TRUE);
9306 /*-----------------------------------------------------------------*/
9307 /* genFarPointerSet - set value from far space */
9308 /*-----------------------------------------------------------------*/
9310 genFarPointerSet (operand * right,
9311 operand * result, iCode * ic, iCode * pi)
9314 sym_link *retype = getSpec (operandType (right));
9315 sym_link *letype = getSpec (operandType (result));
9317 D(emitcode ("; genFarPointerSet",""));
9319 aopOp (result, ic, FALSE);
9320 loadDptrFromOperand (result, FALSE);
9322 /* so dptr know contains the address */
9323 aopOp (right, ic, FALSE);
9325 /* if bit then unpack */
9326 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9327 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9330 size = AOP_SIZE (right);
9335 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9337 emitcode ("movx", "@dptr,a");
9339 emitcode ("inc", "dptr");
9342 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9343 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9344 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9347 freeAsmop (result, NULL, ic, TRUE);
9348 freeAsmop (right, NULL, ic, TRUE);
9351 /*-----------------------------------------------------------------*/
9352 /* genGenPointerSet - set value from generic pointer space */
9353 /*-----------------------------------------------------------------*/
9355 genGenPointerSet (operand * right,
9356 operand * result, iCode * ic, iCode * pi)
9359 sym_link *retype = getSpec (operandType (right));
9360 sym_link *letype = getSpec (operandType (result));
9362 D(emitcode ("; genGenPointerSet",""));
9364 aopOp (result, ic, FALSE);
9365 loadDptrFromOperand (result, TRUE);
9367 /* so dptr know contains the address */
9368 aopOp (right, ic, FALSE);
9370 /* if bit then unpack */
9371 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9372 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9375 size = AOP_SIZE (right);
9380 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9382 emitcode ("lcall", "__gptrput");
9384 emitcode ("inc", "dptr");
9388 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9389 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9390 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9393 freeAsmop (result, NULL, ic, TRUE);
9394 freeAsmop (right, NULL, ic, TRUE);
9397 /*-----------------------------------------------------------------*/
9398 /* genPointerSet - stores the value into a pointer location */
9399 /*-----------------------------------------------------------------*/
9401 genPointerSet (iCode * ic, iCode *pi)
9403 operand *right, *result;
9404 sym_link *type, *etype;
9407 D(emitcode ("; genPointerSet",""));
9409 right = IC_RIGHT (ic);
9410 result = IC_RESULT (ic);
9412 /* depending on the type of pointer we need to
9413 move it to the correct pointer register */
9414 type = operandType (result);
9415 etype = getSpec (type);
9416 /* if left is of type of pointer then it is simple */
9417 if (IS_PTR (type) && !IS_FUNC (type->next))
9419 p_type = DCL_TYPE (type);
9423 /* we have to go by the storage class */
9424 p_type = PTR_TYPE (SPEC_OCLS (etype));
9427 /* special case when cast remat */
9428 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9429 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9430 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9431 type = operandType (result);
9432 p_type = DCL_TYPE (type);
9434 /* now that we have the pointer type we assign
9435 the pointer values */
9441 genNearPointerSet (right, result, ic, pi);
9445 genPagedPointerSet (right, result, ic, pi);
9449 genFarPointerSet (right, result, ic, pi);
9453 genGenPointerSet (right, result, ic, pi);
9457 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9458 "genPointerSet: illegal pointer type");
9463 /*-----------------------------------------------------------------*/
9464 /* genIfx - generate code for Ifx statement */
9465 /*-----------------------------------------------------------------*/
9467 genIfx (iCode * ic, iCode * popIc)
9469 operand *cond = IC_COND (ic);
9472 D(emitcode ("; genIfx",""));
9474 aopOp (cond, ic, FALSE);
9476 /* get the value into acc */
9477 if (AOP_TYPE (cond) != AOP_CRY)
9481 /* the result is now in the accumulator */
9482 freeAsmop (cond, NULL, ic, TRUE);
9484 /* if there was something to be popped then do it */
9488 /* if the condition is a bit variable */
9489 if (isbit && IS_ITEMP (cond) &&
9491 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9492 else if (isbit && !IS_ITEMP (cond))
9493 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9495 genIfxJump (ic, "a", NULL, NULL, NULL);
9500 /*-----------------------------------------------------------------*/
9501 /* genAddrOf - generates code for address of */
9502 /*-----------------------------------------------------------------*/
9504 genAddrOf (iCode * ic)
9506 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9509 D(emitcode ("; genAddrOf",""));
9511 aopOp (IC_RESULT (ic), ic, FALSE);
9513 /* if the operand is on the stack then we
9514 need to get the stack offset of this
9518 /* if it has an offset then we need to compute
9522 emitcode ("mov", "a,_bp");
9523 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9524 ((char) (sym->stack - _G.nRegsSaved)) :
9525 ((char) sym->stack)) & 0xff);
9526 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9530 /* we can just move _bp */
9531 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9533 /* fill the result with zero */
9534 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9539 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9545 /* object not on stack then we need the name */
9546 size = AOP_SIZE (IC_RESULT (ic));
9551 char s[SDCC_NAME_MAX];
9553 sprintf (s, "#(%s >> %d)",
9557 sprintf (s, "#%s", sym->rname);
9558 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9562 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9566 /*-----------------------------------------------------------------*/
9567 /* genFarFarAssign - assignment when both are in far space */
9568 /*-----------------------------------------------------------------*/
9570 genFarFarAssign (operand * result, operand * right, iCode * ic)
9572 int size = AOP_SIZE (right);
9576 D(emitcode ("; genFarFarAssign",""));
9578 /* first push the right side on to the stack */
9581 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9583 emitcode ("push", "acc");
9586 freeAsmop (right, NULL, ic, FALSE);
9587 /* now assign DPTR to result */
9588 aopOp (result, ic, FALSE);
9589 size = AOP_SIZE (result);
9592 emitcode ("pop", "acc");
9593 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9595 freeAsmop (result, NULL, ic, FALSE);
9599 /*-----------------------------------------------------------------*/
9600 /* genAssign - generate code for assignment */
9601 /*-----------------------------------------------------------------*/
9603 genAssign (iCode * ic)
9605 operand *result, *right;
9607 unsigned long lit = 0L;
9609 D(emitcode("; genAssign",""));
9611 result = IC_RESULT (ic);
9612 right = IC_RIGHT (ic);
9614 /* if they are the same */
9615 if (operandsEqu (result, right) &&
9616 !isOperandVolatile (result, FALSE) &&
9617 !isOperandVolatile (right, FALSE))
9620 aopOp (right, ic, FALSE);
9622 /* special case both in far space */
9623 if (AOP_TYPE (right) == AOP_DPTR &&
9624 IS_TRUE_SYMOP (result) &&
9625 isOperandInFarSpace (result))
9628 genFarFarAssign (result, right, ic);
9632 aopOp (result, ic, TRUE);
9634 /* if they are the same registers */
9635 if (sameRegs (AOP (right), AOP (result)) &&
9636 !isOperandVolatile (result, FALSE) &&
9637 !isOperandVolatile (right, FALSE))
9640 /* if the result is a bit */
9641 if (AOP_TYPE (result) == AOP_CRY)
9644 /* if the right size is a literal then
9645 we know what the value is */
9646 if (AOP_TYPE (right) == AOP_LIT)
9648 if (((int) operandLitValue (right)))
9649 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9651 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9655 /* the right is also a bit variable */
9656 if (AOP_TYPE (right) == AOP_CRY)
9658 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9659 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9665 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9669 /* bit variables done */
9671 size = AOP_SIZE (result);
9673 if (AOP_TYPE (right) == AOP_LIT)
9674 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9676 (AOP_TYPE (result) != AOP_REG) &&
9677 (AOP_TYPE (right) == AOP_LIT) &&
9678 !IS_FLOAT (operandType (right)) &&
9681 while ((size) && (lit))
9683 aopPut (AOP (result),
9684 aopGet (AOP (right), offset, FALSE, FALSE),
9686 isOperandVolatile (result, FALSE));
9691 emitcode ("clr", "a");
9694 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9702 aopPut (AOP (result),
9703 aopGet (AOP (right), offset, FALSE, FALSE),
9705 isOperandVolatile (result, FALSE));
9711 freeAsmop (right, NULL, ic, TRUE);
9712 freeAsmop (result, NULL, ic, TRUE);
9715 /*-----------------------------------------------------------------*/
9716 /* genJumpTab - genrates code for jump table */
9717 /*-----------------------------------------------------------------*/
9719 genJumpTab (iCode * ic)
9721 symbol *jtab,*jtablo,*jtabhi;
9725 D(emitcode ("; genJumpTab",""));
9727 count = elementsInSet( IC_JTLABELS (ic) );
9731 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9732 if the switch argument is in a register.
9733 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9734 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9735 How will multiply by three be updated ???*/
9736 aopOp (IC_JTCOND (ic), ic, FALSE);
9737 /* get the condition into accumulator */
9738 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9740 /* multiply by three */
9741 emitcode ("add", "a,acc");
9742 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9743 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9745 jtab = newiTempLabel (NULL);
9746 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9747 emitcode ("jmp", "@a+dptr");
9748 emitcode ("", "%05d$:", jtab->key + 100);
9749 /* now generate the jump labels */
9750 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9751 jtab = setNextItem (IC_JTLABELS (ic)))
9752 emitcode ("ljmp", "%05d$", jtab->key + 100);
9756 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9757 if the switch argument is in a register.
9758 For n>6 this algorithm may be more compact */
9759 jtablo = newiTempLabel (NULL);
9760 jtabhi = newiTempLabel (NULL);
9762 /* get the condition into accumulator.
9763 Using b as temporary storage, if register push/pop is needed */
9764 aopOp (IC_JTCOND (ic), ic, FALSE);
9765 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9766 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9767 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9769 // (MB) what if B is in use???
9770 wassertl(!_G.BInUse, "B was in use");
9771 emitcode ("mov", "b,%s", l);
9774 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9778 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9779 emitcode ("movc", "a,@a+pc");
9780 emitcode ("push", "acc");
9783 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9784 emitcode ("movc", "a,@a+pc");
9785 emitcode ("push", "acc");
9789 /* this scales up to n<=255, but needs two more bytes
9791 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9792 emitcode ("movc", "a,@a+dptr");
9793 emitcode ("push", "acc");
9796 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9797 emitcode ("movc", "a,@a+dptr");
9798 emitcode ("push", "acc");
9801 emitcode ("ret", "");
9803 /* now generate jump table, LSB */
9804 emitcode ("", "%05d$:", jtablo->key + 100);
9805 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9806 jtab = setNextItem (IC_JTLABELS (ic)))
9807 emitcode (".db", "%05d$", jtab->key + 100);
9809 /* now generate jump table, MSB */
9810 emitcode ("", "%05d$:", jtabhi->key + 100);
9811 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9812 jtab = setNextItem (IC_JTLABELS (ic)))
9813 emitcode (".db", "%05d$>>8", jtab->key + 100);
9817 /*-----------------------------------------------------------------*/
9818 /* genCast - gen code for casting */
9819 /*-----------------------------------------------------------------*/
9821 genCast (iCode * ic)
9823 operand *result = IC_RESULT (ic);
9824 sym_link *ctype = operandType (IC_LEFT (ic));
9825 sym_link *rtype = operandType (IC_RIGHT (ic));
9826 operand *right = IC_RIGHT (ic);
9829 D(emitcode("; genCast",""));
9831 /* if they are equivalent then do nothing */
9832 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9835 aopOp (right, ic, FALSE);
9836 aopOp (result, ic, FALSE);
9838 /* if the result is a bit (and not a bitfield) */
9839 // if (AOP_TYPE (result) == AOP_CRY)
9840 if (IS_BITVAR (OP_SYMBOL (result)->type)
9841 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9843 /* if the right size is a literal then
9844 we know what the value is */
9845 if (AOP_TYPE (right) == AOP_LIT)
9847 if (((int) operandLitValue (right)))
9848 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9850 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9855 /* the right is also a bit variable */
9856 if (AOP_TYPE (right) == AOP_CRY)
9858 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9859 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9865 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9870 /* if they are the same size : or less */
9871 if (AOP_SIZE (result) <= AOP_SIZE (right))
9874 /* if they are in the same place */
9875 if (sameRegs (AOP (right), AOP (result)))
9878 /* if they in different places then copy */
9879 size = AOP_SIZE (result);
9883 aopPut (AOP (result),
9884 aopGet (AOP (right), offset, FALSE, FALSE),
9886 isOperandVolatile (result, FALSE));
9893 /* if the result is of type pointer */
9898 sym_link *type = operandType (right);
9899 sym_link *etype = getSpec (type);
9901 /* pointer to generic pointer */
9902 if (IS_GENPTR (ctype))
9905 p_type = DCL_TYPE (type);
9908 if (SPEC_SCLS(etype)==S_REGISTER) {
9909 // let's assume it is a generic pointer
9912 /* we have to go by the storage class */
9913 p_type = PTR_TYPE (SPEC_OCLS (etype));
9917 /* the first two bytes are known */
9918 size = GPTRSIZE - 1;
9922 aopPut (AOP (result),
9923 aopGet (AOP (right), offset, FALSE, FALSE),
9925 isOperandVolatile (result, FALSE));
9928 /* the last byte depending on type */
9930 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9935 // pointerTypeToGPByte will have bitched.
9939 sprintf(gpValStr, "#0x%d", gpVal);
9940 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9945 /* just copy the pointers */
9946 size = AOP_SIZE (result);
9950 aopPut (AOP (result),
9951 aopGet (AOP (right), offset, FALSE, FALSE),
9953 isOperandVolatile (result, FALSE));
9959 /* so we now know that the size of destination is greater
9960 than the size of the source */
9961 /* we move to result for the size of source */
9962 size = AOP_SIZE (right);
9966 aopPut (AOP (result),
9967 aopGet (AOP (right), offset, FALSE, FALSE),
9969 isOperandVolatile (result, FALSE));
9973 /* now depending on the sign of the source && destination */
9974 size = AOP_SIZE (result) - AOP_SIZE (right);
9975 /* if unsigned or not an integral type */
9976 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9979 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9983 /* we need to extend the sign :{ */
9984 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9987 emitcode ("rlc", "a");
9988 emitcode ("subb", "a,acc");
9990 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9993 /* we are done hurray !!!! */
9996 freeAsmop (right, NULL, ic, TRUE);
9997 freeAsmop (result, NULL, ic, TRUE);
10001 /*-----------------------------------------------------------------*/
10002 /* genDjnz - generate decrement & jump if not zero instrucion */
10003 /*-----------------------------------------------------------------*/
10005 genDjnz (iCode * ic, iCode * ifx)
10007 symbol *lbl, *lbl1;
10011 D(emitcode ("; genDjnz",""));
10013 /* if the if condition has a false label
10014 then we cannot save */
10015 if (IC_FALSE (ifx))
10018 /* if the minus is not of the form
10020 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10021 !IS_OP_LITERAL (IC_RIGHT (ic)))
10024 if (operandLitValue (IC_RIGHT (ic)) != 1)
10027 /* if the size of this greater than one then no
10029 if (getSize (operandType (IC_RESULT (ic))) > 1)
10032 /* otherwise we can save BIG */
10033 lbl = newiTempLabel (NULL);
10034 lbl1 = newiTempLabel (NULL);
10036 aopOp (IC_RESULT (ic), ic, FALSE);
10038 if (AOP_NEEDSACC(IC_RESULT(ic)))
10040 /* If the result is accessed indirectly via
10041 * the accumulator, we must explicitly write
10042 * it back after the decrement.
10044 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10046 if (strcmp(rByte, "a"))
10048 /* Something is hopelessly wrong */
10049 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10050 __FILE__, __LINE__);
10051 /* We can just give up; the generated code will be inefficient,
10052 * but what the hey.
10054 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10057 emitcode ("dec", "%s", rByte);
10058 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10059 emitcode ("jnz", "%05d$", lbl->key + 100);
10061 else if (IS_AOP_PREG (IC_RESULT (ic)))
10063 emitcode ("dec", "%s",
10064 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10065 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10066 emitcode ("jnz", "%05d$", lbl->key + 100);
10070 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10073 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10074 emitcode ("", "%05d$:", lbl->key + 100);
10075 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10076 emitcode ("", "%05d$:", lbl1->key + 100);
10078 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10079 ifx->generated = 1;
10083 /*-----------------------------------------------------------------*/
10084 /* genReceive - generate code for a receive iCode */
10085 /*-----------------------------------------------------------------*/
10087 genReceive (iCode * ic)
10089 int size = getSize (operandType (IC_RESULT (ic)));
10091 D(emitcode ("; genReceive",""));
10093 if (ic->argreg == 1) { /* first parameter */
10094 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10095 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10096 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10099 int receivingA = 0;
10102 for (offset = 0; offset<size; offset++)
10103 if (!strcmp (fReturn[offset], "a"))
10108 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10110 for (offset = size-1; offset>0; offset--)
10111 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10112 emitcode("mov","a,%s", fReturn[0]);
10114 aopOp (IC_RESULT (ic), ic, FALSE);
10116 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10117 isOperandVolatile (IC_RESULT (ic), FALSE));
10118 for (offset = 1; offset<size; offset++)
10119 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10120 isOperandVolatile (IC_RESULT (ic), FALSE));
10126 if (getTempRegs(tempRegs, size, ic))
10128 for (offset = 0; offset<size; offset++)
10129 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10130 aopOp (IC_RESULT (ic), ic, FALSE);
10131 for (offset = 0; offset<size; offset++)
10132 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10133 isOperandVolatile (IC_RESULT (ic), FALSE));
10138 offset = fReturnSizeMCS51 - size;
10140 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10141 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10144 aopOp (IC_RESULT (ic), ic, FALSE);
10145 size = AOP_SIZE (IC_RESULT (ic));
10148 emitcode ("pop", "acc");
10149 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10154 aopOp (IC_RESULT (ic), ic, FALSE);
10156 assignResultValue (IC_RESULT (ic));
10158 } else { /* second receive onwards */
10160 aopOp (IC_RESULT (ic), ic, FALSE);
10161 rb1off = ic->argreg;
10163 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10171 /*-----------------------------------------------------------------*/
10172 /* genDummyRead - generate code for dummy read of volatiles */
10173 /*-----------------------------------------------------------------*/
10175 genDummyRead (iCode * ic)
10180 D(emitcode("; genDummyRead",""));
10182 op = IC_RIGHT (ic);
10183 if (op && IS_SYMOP (op))
10185 aopOp (op, ic, FALSE);
10187 /* if the result is a bit */
10188 if (AOP_TYPE (op) == AOP_CRY)
10189 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10192 /* bit variables done */
10194 size = AOP_SIZE (op);
10198 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10203 freeAsmop (op, NULL, ic, TRUE);
10207 if (op && IS_SYMOP (op))
10209 aopOp (op, ic, FALSE);
10211 /* if the result is a bit */
10212 if (AOP_TYPE (op) == AOP_CRY)
10213 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10216 /* bit variables done */
10218 size = AOP_SIZE (op);
10222 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10227 freeAsmop (op, NULL, ic, TRUE);
10231 /*-----------------------------------------------------------------*/
10232 /* genCritical - generate code for start of a critical sequence */
10233 /*-----------------------------------------------------------------*/
10235 genCritical (iCode *ic)
10237 symbol *tlbl = newiTempLabel (NULL);
10239 D(emitcode("; genCritical",""));
10241 if (IC_RESULT (ic))
10243 aopOp (IC_RESULT (ic), ic, TRUE);
10244 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10245 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10246 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10247 emitcode ("", "%05d$:", (tlbl->key + 100));
10248 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10252 emitcode ("setb", "c");
10253 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10254 emitcode ("clr", "c");
10255 emitcode ("", "%05d$:", (tlbl->key + 100));
10256 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10260 /*-----------------------------------------------------------------*/
10261 /* genEndCritical - generate code for end of a critical sequence */
10262 /*-----------------------------------------------------------------*/
10264 genEndCritical (iCode *ic)
10266 D(emitcode("; genEndCritical",""));
10270 aopOp (IC_RIGHT (ic), ic, FALSE);
10271 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10273 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10274 emitcode ("mov", "ea,c");
10278 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10279 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10280 emitcode ("rrc", "a");
10281 emitcode ("mov", "ea,c");
10283 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10287 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10288 emitcode ("mov", "ea,c");
10292 /*-----------------------------------------------------------------*/
10293 /* gen51Code - generate code for 8051 based controllers */
10294 /*-----------------------------------------------------------------*/
10296 gen51Code (iCode * lic)
10300 /* int cseq = 0; */
10302 _G.currentFunc = NULL;
10303 lineHead = lineCurr = NULL;
10305 /* print the allocation information */
10306 if (allocInfo && currFunc)
10307 printAllocInfo (currFunc, codeOutFile);
10308 /* if debug information required */
10309 if (options.debug && currFunc)
10311 debugFile->writeFunction (currFunc, lic);
10313 /* stack pointer name */
10314 if (options.useXstack)
10320 for (ic = lic; ic; ic = ic->next)
10322 _G.current_iCode = ic;
10324 if (ic->lineno && cln != ic->lineno)
10328 debugFile->writeCLine (ic);
10330 if (!options.noCcodeInAsm) {
10331 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10332 printCLine(ic->filename, ic->lineno));
10337 if (ic->seqPoint && ic->seqPoint != cseq)
10339 emitcode ("", "; sequence point %d", ic->seqPoint);
10340 cseq = ic->seqPoint;
10343 if (options.iCodeInAsm) {
10344 char regsInUse[80];
10347 for (i=0; i<8; i++) {
10348 sprintf (®sInUse[i],
10349 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10352 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10354 /* if the result is marked as
10355 spilt and rematerializable or code for
10356 this has already been generated then
10358 if (resultRemat (ic) || ic->generated)
10361 /* depending on the operation */
10381 /* IPOP happens only when trying to restore a
10382 spilt live range, if there is an ifx statement
10383 following this pop then the if statement might
10384 be using some of the registers being popped which
10385 would destory the contents of the register so
10386 we need to check for this condition and handle it */
10388 ic->next->op == IFX &&
10389 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10390 genIfx (ic->next, ic);
10408 genEndFunction (ic);
10428 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10445 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10449 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10456 /* note these two are xlated by algebraic equivalence
10457 during parsing SDCC.y */
10458 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10459 "got '>=' or '<=' shouldn't have come here");
10463 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10475 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10479 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10483 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10507 genRightShift (ic);
10510 case GET_VALUE_AT_ADDRESS:
10512 hasInc (IC_LEFT (ic), ic,
10513 getSize (operandType (IC_RESULT (ic)))),
10514 ifxForOp (IC_RESULT (ic), ic) );
10518 if (POINTER_SET (ic))
10519 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10545 addSet (&_G.sendSet, ic);
10548 case DUMMY_READ_VOLATILE:
10557 genEndCritical (ic);
10569 _G.current_iCode = NULL;
10571 /* now we are ready to call the
10572 peep hole optimizer */
10573 if (!options.nopeep)
10574 peepHole (&lineHead);
10576 /* now do the actual printing */
10577 printLine (lineHead, codeOutFile);