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 (size && 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 /*-----------------------------------------------------------------*/
1671 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1673 D(emitcode (";", "genCpl"));
1675 /* assign asmOps to operand & result */
1676 aopOp (IC_LEFT (ic), ic, FALSE);
1677 aopOp (IC_RESULT (ic), ic, TRUE);
1679 /* special case if in bit space */
1680 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1684 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1685 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1687 /* promotion rules are responsible for this strange result:
1688 bit -> int -> ~int -> bit
1689 uchar -> int -> ~int -> bit
1691 werror(W_COMPLEMENT);
1692 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1696 tlbl=newiTempLabel(NULL);
1697 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1698 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1699 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1700 IS_AOP_PREG (IC_LEFT (ic)))
1702 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1707 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1709 emitcode ("", "%05d$:", tlbl->key + 100);
1710 outBitC (IC_RESULT(ic));
1714 size = AOP_SIZE (IC_RESULT (ic));
1717 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1719 emitcode ("cpl", "a");
1720 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1725 /* release the aops */
1726 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1730 /*-----------------------------------------------------------------*/
1731 /* genUminusFloat - unary minus for floating points */
1732 /*-----------------------------------------------------------------*/
1734 genUminusFloat (operand * op, operand * result)
1736 int size, offset = 0;
1739 D(emitcode ("; genUminusFloat",""));
1741 /* for this we just copy and then flip the bit */
1743 size = AOP_SIZE (op) - 1;
1747 aopPut (AOP (result),
1748 aopGet (AOP (op), offset, FALSE, FALSE),
1750 isOperandVolatile (result, FALSE));
1754 l = aopGet (AOP (op), offset, FALSE, FALSE);
1758 emitcode ("cpl", "acc.7");
1759 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1762 /*-----------------------------------------------------------------*/
1763 /* genUminus - unary minus code generation */
1764 /*-----------------------------------------------------------------*/
1766 genUminus (iCode * ic)
1769 sym_link *optype, *rtype;
1772 D(emitcode ("; genUminus",""));
1775 aopOp (IC_LEFT (ic), ic, FALSE);
1776 aopOp (IC_RESULT (ic), ic, TRUE);
1778 /* if both in bit space then special
1780 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1781 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1784 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1785 emitcode ("cpl", "c");
1786 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1790 optype = operandType (IC_LEFT (ic));
1791 rtype = operandType (IC_RESULT (ic));
1793 /* if float then do float stuff */
1794 if (IS_FLOAT (optype))
1796 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1800 /* otherwise subtract from zero */
1801 size = AOP_SIZE (IC_LEFT (ic));
1806 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1807 if (!strcmp (l, "a"))
1811 emitcode ("cpl", "a");
1812 emitcode ("addc", "a,#0");
1818 emitcode ("clr", "a");
1819 emitcode ("subb", "a,%s", l);
1821 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1824 /* if any remaining bytes in the result */
1825 /* we just need to propagate the sign */
1826 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1828 emitcode ("rlc", "a");
1829 emitcode ("subb", "a,acc");
1831 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1835 /* release the aops */
1836 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1840 /*-----------------------------------------------------------------*/
1841 /* saveRegisters - will look for a call and save the registers */
1842 /*-----------------------------------------------------------------*/
1844 saveRegisters (iCode * lic)
1851 for (ic = lic; ic; ic = ic->next)
1852 if (ic->op == CALL || ic->op == PCALL)
1857 fprintf (stderr, "found parameter push with no function call\n");
1861 /* if the registers have been saved already or don't need to be then
1865 if (IS_SYMOP(IC_LEFT(ic)) &&
1866 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1867 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1870 /* save the registers in use at this time but skip the
1871 ones for the result */
1872 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1873 mcs51_rUmaskForOp (IC_RESULT(ic)));
1876 if (options.useXstack)
1878 int count = bitVectnBitsOn (rsave);
1882 i = bitVectFirstBit (rsave);
1883 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1884 emitcode ("mov", "r0,%s", spname);
1885 emitcode ("inc", "%s", spname);// allocate before use
1886 emitcode ("movx", "@r0,a");
1887 if (bitVectBitValue (rsave, R0_IDX))
1888 emitcode ("mov", "r0,a");
1890 else if (count != 0)
1892 if (bitVectBitValue (rsave, R0_IDX))
1894 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1896 emitcode ("mov", "r0,%s", spname);
1898 emitcode ("add", "a,#%d", count);
1899 emitcode ("mov", "%s,a", spname);
1900 for (i = 0; i < mcs51_nRegs; i++)
1902 if (bitVectBitValue (rsave, i))
1906 emitcode ("pop", "acc");
1907 emitcode ("push", "acc");
1911 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1913 emitcode ("movx", "@r0,a");
1916 emitcode ("inc", "r0");
1920 if (bitVectBitValue (rsave, R0_IDX))
1922 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1927 for (i = 0; i < mcs51_nRegs; i++)
1929 if (bitVectBitValue (rsave, i))
1930 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1934 /*-----------------------------------------------------------------*/
1935 /* unsaveRegisters - pop the pushed registers */
1936 /*-----------------------------------------------------------------*/
1938 unsaveRegisters (iCode * ic)
1943 /* restore the registers in use at this time but skip the
1944 ones for the result */
1945 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1946 mcs51_rUmaskForOp (IC_RESULT(ic)));
1948 if (options.useXstack)
1950 int count = bitVectnBitsOn (rsave);
1954 emitcode ("mov", "r0,%s", spname);
1955 emitcode ("dec", "r0");
1956 emitcode ("movx", "a,@r0");
1957 i = bitVectFirstBit (rsave);
1958 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1959 emitcode ("dec", "%s", spname);
1963 emitcode ("mov", "r0,%s", spname);
1964 for (i = mcs51_nRegs; i >= 0; i--)
1966 if (bitVectBitValue (rsave, i))
1968 emitcode ("dec", "r0");
1969 emitcode ("movx", "a,@r0");
1971 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1974 emitcode ("mov", "%s,r0", spname);
1975 if (bitVectBitValue (rsave, R0_IDX))
1977 emitcode ("mov", "r0,a");
1982 for (i = mcs51_nRegs; i >= 0; i--)
1984 if (bitVectBitValue (rsave, i))
1985 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1990 /*-----------------------------------------------------------------*/
1992 /*-----------------------------------------------------------------*/
1994 pushSide (operand * oper, int size)
1999 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2000 if (AOP_TYPE (oper) != AOP_REG &&
2001 AOP_TYPE (oper) != AOP_DIR &&
2005 emitcode ("push", "acc");
2008 emitcode ("push", "%s", l);
2012 /*-----------------------------------------------------------------*/
2013 /* assignResultValue - */
2014 /*-----------------------------------------------------------------*/
2016 assignResultValue (operand * oper)
2019 int size = AOP_SIZE (oper);
2022 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2028 /*-----------------------------------------------------------------*/
2029 /* genXpush - pushes onto the external stack */
2030 /*-----------------------------------------------------------------*/
2032 genXpush (iCode * ic)
2034 asmop *aop = newAsmop (0);
2036 int size, offset = 0;
2038 D(emitcode ("; genXpush",""));
2040 aopOp (IC_LEFT (ic), ic, FALSE);
2041 r = getFreePtr (ic, &aop, FALSE);
2043 size = AOP_SIZE (IC_LEFT (ic));
2047 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2048 emitcode ("mov", "%s,%s", r->name, spname);
2049 emitcode ("inc", "%s", spname); // allocate space first
2050 emitcode ("movx", "@%s,a", r->name);
2054 // allocate space first
2055 emitcode ("mov", "%s,%s", r->name, spname);
2057 emitcode ("add", "a,#%d", size);
2058 emitcode ("mov", "%s,a", spname);
2062 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2063 emitcode ("movx", "@%s,a", r->name);
2064 emitcode ("inc", "%s", r->name);
2068 freeAsmop (NULL, aop, ic, TRUE);
2069 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2072 /*-----------------------------------------------------------------*/
2073 /* genIpush - genrate code for pushing this gets a little complex */
2074 /*-----------------------------------------------------------------*/
2076 genIpush (iCode * ic)
2078 int size, offset = 0;
2081 D(emitcode ("; genIpush",""));
2083 /* if this is not a parm push : ie. it is spill push
2084 and spill push is always done on the local stack */
2088 /* and the item is spilt then do nothing */
2089 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2092 aopOp (IC_LEFT (ic), ic, FALSE);
2093 size = AOP_SIZE (IC_LEFT (ic));
2094 /* push it on the stack */
2097 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2103 emitcode ("push", "%s", l);
2108 /* this is a paramter push: in this case we call
2109 the routine to find the call and save those
2110 registers that need to be saved */
2113 /* if use external stack then call the external
2114 stack pushing routine */
2115 if (options.useXstack)
2121 /* then do the push */
2122 aopOp (IC_LEFT (ic), ic, FALSE);
2124 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2125 size = AOP_SIZE (IC_LEFT (ic));
2129 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2130 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2131 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2135 emitcode ("push", "acc");
2138 emitcode ("push", "%s", l);
2141 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2144 /*-----------------------------------------------------------------*/
2145 /* genIpop - recover the registers: can happen only for spilling */
2146 /*-----------------------------------------------------------------*/
2148 genIpop (iCode * ic)
2152 D(emitcode ("; genIpop",""));
2154 /* if the temp was not pushed then */
2155 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2158 aopOp (IC_LEFT (ic), ic, FALSE);
2159 size = AOP_SIZE (IC_LEFT (ic));
2160 offset = (size - 1);
2162 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2165 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2168 /*-----------------------------------------------------------------*/
2169 /* saveRBank - saves an entire register bank on the stack */
2170 /*-----------------------------------------------------------------*/
2172 saveRBank (int bank, iCode * ic, bool pushPsw)
2175 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2179 if (options.useXstack)
2183 /* Assume r0 is available for use. */
2184 r = mcs51_regWithIdx (R0_IDX);;
2189 r = getFreePtr (ic, &aop, FALSE);
2191 // allocate space first
2192 emitcode ("mov", "%s,%s", r->name, spname);
2194 emitcode ("add", "a,#%d", count);
2195 emitcode ("mov", "%s,a", spname);
2198 for (i = 0; i < mcs51_nRegs; i++)
2200 if (options.useXstack)
2202 emitcode ("mov", "a,(%s+%d)",
2203 regs8051[i].base, 8 * bank + regs8051[i].offset);
2204 emitcode ("movx", "@%s,a", r->name);
2206 emitcode ("inc", "%s", r->name);
2209 emitcode ("push", "(%s+%d)",
2210 regs8051[i].base, 8 * bank + regs8051[i].offset);
2215 if (options.useXstack)
2217 emitcode ("mov", "a,psw");
2218 emitcode ("movx", "@%s,a", r->name);
2223 emitcode ("push", "psw");
2226 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2231 freeAsmop (NULL, aop, ic, TRUE);
2240 /*-----------------------------------------------------------------*/
2241 /* unsaveRBank - restores the register bank from stack */
2242 /*-----------------------------------------------------------------*/
2244 unsaveRBank (int bank, iCode * ic, bool popPsw)
2250 if (options.useXstack)
2254 /* Assume r0 is available for use. */
2255 r = mcs51_regWithIdx (R0_IDX);;
2260 r = getFreePtr (ic, &aop, FALSE);
2262 emitcode ("mov", "%s,%s", r->name, spname);
2267 if (options.useXstack)
2269 emitcode ("dec", "%s", r->name);
2270 emitcode ("movx", "a,@%s", r->name);
2271 emitcode ("mov", "psw,a");
2275 emitcode ("pop", "psw");
2279 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2281 if (options.useXstack)
2283 emitcode ("dec", "%s", r->name);
2284 emitcode ("movx", "a,@%s", r->name);
2285 emitcode ("mov", "(%s+%d),a",
2286 regs8051[i].base, 8 * bank + regs8051[i].offset);
2290 emitcode ("pop", "(%s+%d)",
2291 regs8051[i].base, 8 * bank + regs8051[i].offset);
2295 if (options.useXstack)
2297 emitcode ("mov", "%s,%s", spname, r->name);
2302 freeAsmop (NULL, aop, ic, TRUE);
2306 /*-----------------------------------------------------------------*/
2307 /* genSend - gen code for SEND */
2308 /*-----------------------------------------------------------------*/
2309 static void genSend(set *sendSet)
2314 for (sic = setFirstItem (sendSet); sic;
2315 sic = setNextItem (sendSet)) {
2316 int size, offset = 0;
2317 aopOp (IC_LEFT (sic), sic, FALSE);
2318 size = AOP_SIZE (IC_LEFT (sic));
2320 if (sic->argreg == 1) {
2322 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2324 if (strcmp (l, fReturn[offset]))
2325 emitcode ("mov", "%s,%s", fReturn[offset], l);
2331 emitcode ("mov","b1_%d,%s",rb1_count++,
2332 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2335 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2339 /*-----------------------------------------------------------------*/
2340 /* genCall - generates a call statement */
2341 /*-----------------------------------------------------------------*/
2343 genCall (iCode * ic)
2346 // bool restoreBank = FALSE;
2347 bool swapBanks = FALSE;
2349 D(emitcode("; genCall",""));
2351 dtype = operandType (IC_LEFT (ic));
2352 /* if send set is not empty then assign */
2355 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2356 genSend(reverseSet(_G.sendSet));
2358 genSend(_G.sendSet);
2364 /* if we are calling a not _naked function that is not using
2365 the same register bank then we need to save the
2366 destination registers on the stack */
2367 dtype = operandType (IC_LEFT (ic));
2368 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2369 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2370 !IFFUNC_ISISR (dtype))
2375 /* if caller saves & we have not saved then */
2381 emitcode ("mov", "psw,#0x%02x",
2382 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2386 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2387 OP_SYMBOL (IC_LEFT (ic))->rname :
2388 OP_SYMBOL (IC_LEFT (ic))->name));
2392 emitcode ("mov", "psw,#0x%02x",
2393 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2396 /* if we need assign a result value */
2397 if ((IS_ITEMP (IC_RESULT (ic)) &&
2398 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2399 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2400 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2401 IS_TRUE_SYMOP (IC_RESULT (ic)))
2405 aopOp (IC_RESULT (ic), ic, FALSE);
2408 assignResultValue (IC_RESULT (ic));
2410 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2413 /* adjust the stack for parameters if
2418 if (ic->parmBytes > 3)
2420 emitcode ("mov", "a,%s", spname);
2421 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2422 emitcode ("mov", "%s,a", spname);
2425 for (i = 0; i < ic->parmBytes; i++)
2426 emitcode ("dec", "%s", spname);
2429 /* if we hade saved some registers then unsave them */
2430 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2431 unsaveRegisters (ic);
2433 // /* if register bank was saved then pop them */
2435 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2438 /*-----------------------------------------------------------------*/
2439 /* -10l - generates a call by pointer statement */
2440 /*-----------------------------------------------------------------*/
2442 genPcall (iCode * ic)
2445 symbol *rlbl = newiTempLabel (NULL);
2446 // bool restoreBank=FALSE;
2447 bool swapBanks = FALSE;
2449 D(emitcode("; genPCall",""));
2451 /* if caller saves & we have not saved then */
2455 /* if we are calling a not _naked function that is not using
2456 the same register bank then we need to save the
2457 destination registers on the stack */
2458 dtype = operandType (IC_LEFT (ic))->next;
2459 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2460 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2461 !IFFUNC_ISISR (dtype))
2463 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2464 // restoreBank=TRUE;
2466 // need caution message to user here
2469 /* push the return address on to the stack */
2470 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2471 emitcode ("push", "acc");
2472 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2473 emitcode ("push", "acc");
2475 /* now push the calling address */
2476 aopOp (IC_LEFT (ic), ic, FALSE);
2478 pushSide (IC_LEFT (ic), FPTRSIZE);
2480 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2482 /* if send set is not empty the assign */
2485 genSend(reverseSet(_G.sendSet));
2491 emitcode ("mov", "psw,#0x%02x",
2492 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2496 emitcode ("ret", "");
2497 emitcode ("", "%05d$:", (rlbl->key + 100));
2502 emitcode ("mov", "psw,#0x%02x",
2503 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2506 /* if we need assign a result value */
2507 if ((IS_ITEMP (IC_RESULT (ic)) &&
2508 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2509 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2510 IS_TRUE_SYMOP (IC_RESULT (ic)))
2514 aopOp (IC_RESULT (ic), ic, FALSE);
2517 assignResultValue (IC_RESULT (ic));
2519 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2522 /* adjust the stack for parameters if
2527 if (ic->parmBytes > 3)
2529 emitcode ("mov", "a,%s", spname);
2530 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2531 emitcode ("mov", "%s,a", spname);
2534 for (i = 0; i < ic->parmBytes; i++)
2535 emitcode ("dec", "%s", spname);
2539 // /* if register bank was saved then unsave them */
2541 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2543 /* if we hade saved some registers then
2545 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2546 unsaveRegisters (ic);
2549 /*-----------------------------------------------------------------*/
2550 /* resultRemat - result is rematerializable */
2551 /*-----------------------------------------------------------------*/
2553 resultRemat (iCode * ic)
2555 if (SKIP_IC (ic) || ic->op == IFX)
2558 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2560 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2561 if (sym->remat && !POINTER_SET (ic))
2568 #if defined(__BORLANDC__) || defined(_MSC_VER)
2569 #define STRCASECMP stricmp
2571 #define STRCASECMP strcasecmp
2574 /*-----------------------------------------------------------------*/
2575 /* inExcludeList - return 1 if the string is in exclude Reg list */
2576 /*-----------------------------------------------------------------*/
2578 regsCmp(void *p1, void *p2)
2580 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2584 inExcludeList (char *s)
2586 const char *p = setFirstItem(options.excludeRegsSet);
2588 if (p == NULL || STRCASECMP(p, "none") == 0)
2592 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2595 /*-----------------------------------------------------------------*/
2596 /* genFunction - generated code for function entry */
2597 /*-----------------------------------------------------------------*/
2599 genFunction (iCode * ic)
2601 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2603 bool switchedPSW = FALSE;
2604 int calleesaves_saved_register = -1;
2605 int stackAdjust = sym->stack;
2606 int accIsFree = sym->recvSize < 4;
2607 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2608 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2611 /* create the function header */
2612 emitcode (";", "-----------------------------------------");
2613 emitcode (";", " function %s", sym->name);
2614 emitcode (";", "-----------------------------------------");
2616 emitcode ("", "%s:", sym->rname);
2617 ftype = operandType (IC_LEFT (ic));
2618 _G.currentFunc = sym;
2620 if (IFFUNC_ISNAKED(ftype))
2622 emitcode(";", "naked function: no prologue.");
2626 /* here we need to generate the equates for the
2627 register bank if required */
2628 if (FUNC_REGBANK (ftype) != rbank)
2632 rbank = FUNC_REGBANK (ftype);
2633 for (i = 0; i < mcs51_nRegs; i++)
2635 if (strcmp (regs8051[i].base, "0") == 0)
2636 emitcode ("", "%s = 0x%02x",
2638 8 * rbank + regs8051[i].offset);
2640 emitcode ("", "%s = %s + 0x%02x",
2643 8 * rbank + regs8051[i].offset);
2647 /* if this is an interrupt service routine then
2648 save acc, b, dpl, dph */
2649 if (IFFUNC_ISISR (sym->type))
2652 if (!inExcludeList ("acc"))
2653 emitcode ("push", "acc");
2654 if (!inExcludeList ("b"))
2655 emitcode ("push", "b");
2656 if (!inExcludeList ("dpl"))
2657 emitcode ("push", "dpl");
2658 if (!inExcludeList ("dph"))
2659 emitcode ("push", "dph");
2660 /* if this isr has no bank i.e. is going to
2661 run with bank 0 , then we need to save more
2663 if (!FUNC_REGBANK (sym->type))
2666 /* if this function does not call any other
2667 function then we can be economical and
2668 save only those registers that are used */
2669 if (!IFFUNC_HASFCALL(sym->type))
2673 /* if any registers used */
2676 /* save the registers used */
2677 for (i = 0; i < sym->regsUsed->size; i++)
2679 if (bitVectBitValue (sym->regsUsed, i))
2680 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2687 /* this function has a function call. We cannot
2688 determines register usage so we will have to push the
2690 saveRBank (0, ic, FALSE);
2691 if (options.parms_in_bank1) {
2693 for (i=0; i < 8 ; i++ ) {
2694 emitcode ("push","%s",rb1regs[i]);
2701 /* This ISR uses a non-zero bank.
2703 * We assume that the bank is available for our
2706 * However, if this ISR calls a function which uses some
2707 * other bank, we must save that bank entirely.
2709 unsigned long banksToSave = 0;
2711 if (IFFUNC_HASFCALL(sym->type))
2714 #define MAX_REGISTER_BANKS 4
2719 for (i = ic; i; i = i->next)
2721 if (i->op == ENDFUNCTION)
2723 /* we got to the end OK. */
2731 dtype = operandType (IC_LEFT(i));
2733 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2735 /* Mark this bank for saving. */
2736 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2738 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2742 banksToSave |= (1 << FUNC_REGBANK(dtype));
2745 /* And note that we don't need to do it in
2753 /* This is a mess; we have no idea what
2754 * register bank the called function might
2757 * The only thing I can think of to do is
2758 * throw a warning and hope.
2760 werror(W_FUNCPTR_IN_USING_ISR);
2764 if (banksToSave && options.useXstack)
2766 /* Since we aren't passing it an ic,
2767 * saveRBank will assume r0 is available to abuse.
2769 * So switch to our (trashable) bank now, so
2770 * the caller's R0 isn't trashed.
2772 emitcode ("push", "psw");
2773 emitcode ("mov", "psw,#0x%02x",
2774 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2778 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2780 if (banksToSave & (1 << ix))
2782 saveRBank(ix, NULL, FALSE);
2786 // TODO: this needs a closer look
2787 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2790 /* Set the register bank to the desired value if nothing else */
2791 /* has done so yet. */
2794 emitcode ("push", "psw");
2795 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2800 /* This is a non-ISR function. The caller has already switched register */
2801 /* banks, if necessary, so just handle the callee-saves option. */
2803 /* if callee-save to be used for this function
2804 then save the registers being used in this function */
2805 if (IFFUNC_CALLEESAVES(sym->type))
2809 /* if any registers used */
2812 /* save the registers used */
2813 for (i = 0; i < sym->regsUsed->size; i++)
2815 if (bitVectBitValue (sym->regsUsed, i))
2817 /* remember one saved register for later usage */
2818 if (calleesaves_saved_register < 0)
2819 calleesaves_saved_register = i;
2820 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2831 if (options.useXstack)
2833 emitcode ("mov", "r0,%s", spname);
2834 emitcode ("inc", "%s", spname);
2835 emitcode ("xch", "a,_bp");
2836 emitcode ("movx", "@r0,a");
2837 emitcode ("inc", "r0");
2838 emitcode ("mov", "a,r0");
2839 emitcode ("xch", "a,_bp");
2843 /* set up the stack */
2844 emitcode ("push", "_bp"); /* save the callers stack */
2845 emitcode ("mov", "_bp,%s", spname);
2849 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2850 /* before setting up the stack frame completely. */
2851 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2853 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2857 if (rsym && rsym->regType == REG_CND)
2859 if (rsym && (rsym->accuse || rsym->ruonly))
2861 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2862 rsym = rsym->usl.spillLoc;
2865 /* If the RECEIVE operand immediately spills to the first entry on the */
2866 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2867 /* rather than the usual @r0/r1 machinations. */
2868 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2872 _G.current_iCode = ric;
2873 D(emitcode ("; genReceive",""));
2874 for (ofs=0; ofs < sym->recvSize; ofs++)
2876 if (!strcmp (fReturn[ofs], "a"))
2877 emitcode ("push", "acc");
2879 emitcode ("push", fReturn[ofs]);
2881 stackAdjust -= sym->recvSize;
2884 assert (stackAdjust>=0);
2887 _G.current_iCode = ic;
2891 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2892 /* to free up the accumulator. */
2893 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2897 _G.current_iCode = ric;
2898 D(emitcode ("; genReceive",""));
2899 for (ofs=0; ofs < sym->recvSize; ofs++)
2901 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2903 _G.current_iCode = ic;
2909 /* adjust the stack for the function */
2912 int i = stackAdjust;
2914 werror (W_STACK_OVERFLOW, sym->name);
2916 if (i > 3 && accIsFree)
2918 emitcode ("mov", "a,sp");
2919 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2920 emitcode ("mov", "sp,a");
2924 /* The accumulator is not free, so we will need another register */
2925 /* to clobber. No need to worry about a possible conflict with */
2926 /* the above early RECEIVE optimizations since they would have */
2927 /* freed the accumulator if they were generated. */
2929 if (IFFUNC_CALLEESAVES(sym->type))
2931 /* if it's a callee-saves function we need a saved register */
2932 if (calleesaves_saved_register >= 0)
2934 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2935 emitcode ("mov", "a,sp");
2936 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2937 emitcode ("mov", "sp,a");
2938 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2941 /* do it the hard way */
2943 emitcode ("inc", "sp");
2947 /* not callee-saves, we can clobber r0 */
2948 emitcode ("mov", "r0,a");
2949 emitcode ("mov", "a,sp");
2950 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2951 emitcode ("mov", "sp,a");
2952 emitcode ("mov", "a,r0");
2957 emitcode ("inc", "sp");
2962 char i = ((char) sym->xstack & 0xff);
2964 if (i > 3 && accIsFree)
2966 emitcode ("mov", "a,_spx");
2967 emitcode ("add", "a,#0x%02x", i);
2968 emitcode ("mov", "_spx,a");
2972 emitcode ("push", "acc");
2973 emitcode ("mov", "a,_spx");
2974 emitcode ("add", "a,#0x%02x", i);
2975 emitcode ("mov", "_spx,a");
2976 emitcode ("pop", "acc");
2981 emitcode ("inc", "_spx");
2985 /* if critical function then turn interrupts off */
2986 if (IFFUNC_ISCRITICAL (ftype))
2988 symbol *tlbl = newiTempLabel (NULL);
2989 emitcode ("setb", "c");
2990 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2991 emitcode ("clr", "c");
2992 emitcode ("", "%05d$:", (tlbl->key + 100));
2993 emitcode ("push", "psw"); /* save old ea via c in psw */
2997 /*-----------------------------------------------------------------*/
2998 /* genEndFunction - generates epilogue for functions */
2999 /*-----------------------------------------------------------------*/
3001 genEndFunction (iCode * ic)
3003 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3004 lineNode *lnp = lineCurr;
3006 bitVect *regsUsedPrologue;
3007 bitVect *regsUnneeded;
3008 int accIsFree = sym->recvSize < 4;
3011 _G.currentFunc = NULL;
3012 if (IFFUNC_ISNAKED(sym->type))
3014 emitcode(";", "naked function: no epilogue.");
3015 if (options.debug && currFunc)
3016 debugFile->writeEndFunction (currFunc, ic, 0);
3020 if (IFFUNC_ISCRITICAL (sym->type))
3022 emitcode ("pop", "psw"); /* restore ea via c in psw */
3023 emitcode ("mov", "ea,c");
3026 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3028 emitcode ("mov", "%s,_bp", spname);
3031 /* if use external stack but some variables were
3032 added to the local stack then decrement the
3034 if (options.useXstack && sym->stack)
3036 char count = sym->stack;
3038 if ((count>3) && accIsFree)
3040 emitcode ("mov", "a,sp");
3041 emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3042 emitcode ("mov", "sp,a");
3047 emitcode ("dec", "sp");
3051 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3053 if (options.useXstack)
3055 emitcode ("xch", "a,_bp");
3056 emitcode ("mov", "r0,a");
3057 emitcode ("dec", "r0");
3058 emitcode ("movx", "a,@r0");
3059 emitcode ("xch", "a,_bp");
3060 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3064 emitcode ("pop", "_bp");
3068 /* restore the register bank */
3069 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3071 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3072 || !options.useXstack)
3074 /* Special case of ISR using non-zero bank with useXstack
3077 emitcode ("pop", "psw");
3081 if (IFFUNC_ISISR (sym->type))
3084 /* now we need to restore the registers */
3085 /* if this isr has no bank i.e. is going to
3086 run with bank 0 , then we need to save more
3088 if (!FUNC_REGBANK (sym->type))
3090 /* if this function does not call any other
3091 function then we can be economical and
3092 save only those registers that are used */
3093 if (!IFFUNC_HASFCALL(sym->type))
3097 /* if any registers used */
3100 /* save the registers used */
3101 for (i = sym->regsUsed->size; i >= 0; i--)
3103 if (bitVectBitValue (sym->regsUsed, i))
3104 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3110 if (options.parms_in_bank1) {
3112 for (i = 7 ; i >= 0 ; i-- ) {
3113 emitcode ("pop","%s",rb1regs[i]);
3116 /* this function has a function call cannot
3117 determines register usage so we will have to pop the
3119 unsaveRBank (0, ic, FALSE);
3124 /* This ISR uses a non-zero bank.
3126 * Restore any register banks saved by genFunction
3129 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3132 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3134 if (savedBanks & (1 << ix))
3136 unsaveRBank(ix, NULL, FALSE);
3140 if (options.useXstack)
3142 /* Restore bank AFTER calling unsaveRBank,
3143 * since it can trash r0.
3145 emitcode ("pop", "psw");
3149 if (!inExcludeList ("dph"))
3150 emitcode ("pop", "dph");
3151 if (!inExcludeList ("dpl"))
3152 emitcode ("pop", "dpl");
3153 if (!inExcludeList ("b"))
3154 emitcode ("pop", "b");
3155 if (!inExcludeList ("acc"))
3156 emitcode ("pop", "acc");
3158 /* if debug then send end of function */
3159 if (options.debug && currFunc)
3161 debugFile->writeEndFunction (currFunc, ic, 1);
3164 emitcode ("reti", "");
3168 if (IFFUNC_CALLEESAVES(sym->type))
3172 /* if any registers used */
3175 /* save the registers used */
3176 for (i = sym->regsUsed->size; i >= 0; i--)
3178 if (bitVectBitValue (sym->regsUsed, i) ||
3179 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3180 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3183 else if (mcs51_ptrRegReq)
3185 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3186 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3191 /* if debug then send end of function */
3192 if (options.debug && currFunc)
3194 debugFile->writeEndFunction (currFunc, ic, 1);
3197 emitcode ("ret", "");
3200 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3203 /* If this was an interrupt handler using bank 0 that called another */
3204 /* function, then all registers must be saved; nothing to optimized. */
3205 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3206 && !FUNC_REGBANK(sym->type))
3209 /* There are no push/pops to optimize if not callee-saves or ISR */
3210 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3213 /* If there were stack parameters, we cannot optimize without also */
3214 /* fixing all of the stack offsets; this is too dificult to consider. */
3215 if (FUNC_HASSTACKPARM(sym->type))
3218 /* Compute the registers actually used */
3219 regsUsed = newBitVect (mcs51_nRegs);
3220 regsUsedPrologue = newBitVect (mcs51_nRegs);
3223 if (lnp->ic && lnp->ic->op == FUNCTION)
3224 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3226 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3228 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3229 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3236 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3237 && !bitVectBitValue (regsUsed, CND_IDX))
3239 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3240 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3241 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3242 bitVectUnSetBit (regsUsed, CND_IDX);
3245 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3247 /* If this was an interrupt handler that called another function */
3248 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3249 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3251 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3252 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3253 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3254 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3255 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3258 /* Remove the unneeded push/pops */
3259 regsUnneeded = newBitVect (mcs51_nRegs);
3262 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3264 if (!strncmp(lnp->line, "push", 4))
3266 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3267 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3269 connectLine (lnp->prev, lnp->next);
3270 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3273 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3275 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3276 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3278 connectLine (lnp->prev, lnp->next);
3279 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3286 for (idx = 0; idx < regsUnneeded->size; idx++)
3287 if (bitVectBitValue (regsUnneeded, idx))
3288 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3290 freeBitVect (regsUnneeded);
3291 freeBitVect (regsUsed);
3292 freeBitVect (regsUsedPrologue);
3295 /*-----------------------------------------------------------------*/
3296 /* genRet - generate code for return statement */
3297 /*-----------------------------------------------------------------*/
3301 int size, offset = 0, pushed = 0;
3303 D(emitcode ("; genRet",""));
3305 /* if we have no return value then
3306 just generate the "ret" */
3310 /* we have something to return then
3311 move the return value into place */
3312 aopOp (IC_LEFT (ic), ic, FALSE);
3313 size = AOP_SIZE (IC_LEFT (ic));
3318 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3321 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3323 emitcode ("push", "%s", l);
3328 l = aopGet (AOP (IC_LEFT (ic)), offset,
3330 if (strcmp (fReturn[offset], l))
3331 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3340 if (strcmp (fReturn[pushed], "a"))
3341 emitcode ("pop", fReturn[pushed]);
3343 emitcode ("pop", "acc");
3346 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3349 /* generate a jump to the return label
3350 if the next is not the return statement */
3351 if (!(ic->next && ic->next->op == LABEL &&
3352 IC_LABEL (ic->next) == returnLabel))
3354 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3358 /*-----------------------------------------------------------------*/
3359 /* genLabel - generates a label */
3360 /*-----------------------------------------------------------------*/
3362 genLabel (iCode * ic)
3364 /* special case never generate */
3365 if (IC_LABEL (ic) == entryLabel)
3368 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3371 /*-----------------------------------------------------------------*/
3372 /* genGoto - generates a ljmp */
3373 /*-----------------------------------------------------------------*/
3375 genGoto (iCode * ic)
3377 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3380 /*-----------------------------------------------------------------*/
3381 /* findLabelBackwards: walks back through the iCode chain looking */
3382 /* for the given label. Returns number of iCode instructions */
3383 /* between that label and given ic. */
3384 /* Returns zero if label not found. */
3385 /*-----------------------------------------------------------------*/
3387 findLabelBackwards (iCode * ic, int key)
3396 /* If we have any pushes or pops, we cannot predict the distance.
3397 I don't like this at all, this should be dealt with in the
3399 if (ic->op == IPUSH || ic->op == IPOP) {
3403 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3412 /*-----------------------------------------------------------------*/
3413 /* genPlusIncr :- does addition with increment if possible */
3414 /*-----------------------------------------------------------------*/
3416 genPlusIncr (iCode * ic)
3418 unsigned int icount;
3419 unsigned int size = getDataSize (IC_RESULT (ic));
3421 /* will try to generate an increment */
3422 /* if the right side is not a literal
3424 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3427 /* if the literal value of the right hand side
3428 is greater than 4 then it is not worth it */
3429 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3432 D(emitcode ("; genPlusIncr",""));
3434 /* if increment >=16 bits in register or direct space */
3435 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3436 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3444 /* If the next instruction is a goto and the goto target
3445 * is < 10 instructions previous to this, we can generate
3446 * jumps straight to that target.
3448 if (ic->next && ic->next->op == GOTO
3449 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3450 && labelRange <= 10)
3452 emitcode (";", "tail increment optimized");
3453 tlbl = IC_LABEL (ic->next);
3458 tlbl = newiTempLabel (NULL);
3461 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3462 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3463 IS_AOP_PREG (IC_RESULT (ic)))
3464 emitcode ("cjne", "%s,#0x00,%05d$",
3465 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3469 emitcode ("clr", "a");
3470 emitcode ("cjne", "a,%s,%05d$",
3471 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3475 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3478 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3479 IS_AOP_PREG (IC_RESULT (ic)))
3480 emitcode ("cjne", "%s,#0x00,%05d$",
3481 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3484 emitcode ("cjne", "a,%s,%05d$",
3485 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3488 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3492 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3493 IS_AOP_PREG (IC_RESULT (ic)))
3494 emitcode ("cjne", "%s,#0x00,%05d$",
3495 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3499 emitcode ("cjne", "a,%s,%05d$",
3500 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3503 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3508 emitcode ("", "%05d$:", tlbl->key + 100);
3513 /* if the sizes are greater than 1 then we cannot */
3514 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3515 AOP_SIZE (IC_LEFT (ic)) > 1)
3518 /* we can if the aops of the left & result match or
3519 if they are in registers and the registers are the
3521 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3526 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3527 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3528 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3534 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3543 /*-----------------------------------------------------------------*/
3544 /* outBitAcc - output a bit in acc */
3545 /*-----------------------------------------------------------------*/
3547 outBitAcc (operand * result)
3549 symbol *tlbl = newiTempLabel (NULL);
3550 /* if the result is a bit */
3551 if (AOP_TYPE (result) == AOP_CRY)
3553 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3557 emitcode ("jz", "%05d$", tlbl->key + 100);
3558 emitcode ("mov", "a,%s", one);
3559 emitcode ("", "%05d$:", tlbl->key + 100);
3564 /*-----------------------------------------------------------------*/
3565 /* genPlusBits - generates code for addition of two bits */
3566 /*-----------------------------------------------------------------*/
3568 genPlusBits (iCode * ic)
3570 D(emitcode ("; genPlusBits",""));
3572 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3574 symbol *lbl = newiTempLabel (NULL);
3575 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3576 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3577 emitcode ("cpl", "c");
3578 emitcode ("", "%05d$:", (lbl->key + 100));
3579 outBitC (IC_RESULT (ic));
3583 emitcode ("clr", "a");
3584 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3585 emitcode ("rlc", "a");
3586 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3587 emitcode ("addc", "a,#0x00");
3588 outAcc (IC_RESULT (ic));
3593 /* This is the original version of this code.
3595 * This is being kept around for reference,
3596 * because I am not entirely sure I got it right...
3599 adjustArithmeticResult (iCode * ic)
3601 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3602 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3603 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3604 aopPut (AOP (IC_RESULT (ic)),
3605 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3607 isOperandVolatile (IC_RESULT (ic), FALSE));
3609 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3610 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3611 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3612 aopPut (AOP (IC_RESULT (ic)),
3613 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3615 isOperandVolatile (IC_RESULT (ic), FALSE));
3617 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3618 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3619 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3620 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3621 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3624 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3625 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3629 /* This is the pure and virtuous version of this code.
3630 * I'm pretty certain it's right, but not enough to toss the old
3634 adjustArithmeticResult (iCode * ic)
3636 if (opIsGptr (IC_RESULT (ic)) &&
3637 opIsGptr (IC_LEFT (ic)) &&
3638 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3640 aopPut (AOP (IC_RESULT (ic)),
3641 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3643 isOperandVolatile (IC_RESULT (ic), FALSE));
3646 if (opIsGptr (IC_RESULT (ic)) &&
3647 opIsGptr (IC_RIGHT (ic)) &&
3648 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3650 aopPut (AOP (IC_RESULT (ic)),
3651 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3653 isOperandVolatile (IC_RESULT (ic), FALSE));
3656 if (opIsGptr (IC_RESULT (ic)) &&
3657 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3658 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3659 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3660 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3663 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3664 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3669 /*-----------------------------------------------------------------*/
3670 /* genPlus - generates code for addition */
3671 /*-----------------------------------------------------------------*/
3673 genPlus (iCode * ic)
3675 int size, offset = 0;
3678 asmop *leftOp, *rightOp;
3681 /* special cases :- */
3683 D(emitcode ("; genPlus",""));
3685 aopOp (IC_LEFT (ic), ic, FALSE);
3686 aopOp (IC_RIGHT (ic), ic, FALSE);
3687 aopOp (IC_RESULT (ic), ic, TRUE);
3689 /* if literal, literal on the right or
3690 if left requires ACC or right is already
3692 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3693 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3694 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3696 operand *t = IC_RIGHT (ic);
3697 IC_RIGHT (ic) = IC_LEFT (ic);
3701 /* if both left & right are in bit
3703 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3704 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3710 /* if left in bit space & right literal */
3711 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3712 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3714 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3715 /* if result in bit space */
3716 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3718 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3719 emitcode ("cpl", "c");
3720 outBitC (IC_RESULT (ic));
3724 size = getDataSize (IC_RESULT (ic));
3727 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3728 emitcode ("addc", "a,#00");
3729 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3735 /* if I can do an increment instead
3736 of add then GOOD for ME */
3737 if (genPlusIncr (ic) == TRUE)
3740 size = getDataSize (IC_RESULT (ic));
3741 leftOp = AOP(IC_LEFT(ic));
3742 rightOp = AOP(IC_RIGHT(ic));
3745 /* if this is an add for an array access
3746 at a 256 byte boundary */
3748 && AOP_TYPE (op) == AOP_IMMD
3750 && IS_SPEC (OP_SYM_ETYPE (op))
3751 && SPEC_ABSA (OP_SYM_ETYPE (op))
3752 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3755 D(emitcode ("; genPlus aligned array",""));
3756 aopPut (AOP (IC_RESULT (ic)),
3757 aopGet (rightOp, 0, FALSE, FALSE),
3759 isOperandVolatile (IC_RESULT (ic), FALSE));
3761 if( 1 == getDataSize (IC_RIGHT (ic)) )
3763 aopPut (AOP (IC_RESULT (ic)),
3764 aopGet (leftOp, 1, FALSE, FALSE),
3766 isOperandVolatile (IC_RESULT (ic), FALSE));
3770 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3771 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3772 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3777 /* if the lower bytes of a literal are zero skip the addition */
3778 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3780 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3781 (skip_bytes+1 < size))
3786 D(emitcode ("; genPlus shortcut",""));
3791 if( offset >= skip_bytes )
3793 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3796 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3798 emitcode("xch", "a,b");
3799 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3800 emitcode (add, "a,b");
3803 else if (aopGetUsesAcc (leftOp, offset))
3805 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3806 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3810 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3811 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3813 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3814 add = "addc"; /* further adds must propagate carry */
3818 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3819 isOperandVolatile (IC_RESULT (ic), FALSE))
3822 aopPut (AOP (IC_RESULT (ic)),
3823 aopGet (leftOp, offset, FALSE, FALSE),
3825 isOperandVolatile (IC_RESULT (ic), FALSE));
3831 adjustArithmeticResult (ic);
3834 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3835 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3836 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3839 /*-----------------------------------------------------------------*/
3840 /* genMinusDec :- does subtraction with deccrement if possible */
3841 /*-----------------------------------------------------------------*/
3843 genMinusDec (iCode * ic)
3845 unsigned int icount;
3846 unsigned int size = getDataSize (IC_RESULT (ic));
3848 /* will try to generate an increment */
3849 /* if the right side is not a literal
3851 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3854 /* if the literal value of the right hand side
3855 is greater than 4 then it is not worth it */
3856 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3859 D(emitcode ("; genMinusDec",""));
3861 /* if decrement >=16 bits in register or direct space */
3862 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3863 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3871 /* If the next instruction is a goto and the goto target
3872 * is <= 10 instructions previous to this, we can generate
3873 * jumps straight to that target.
3875 if (ic->next && ic->next->op == GOTO
3876 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3877 && labelRange <= 10)
3879 emitcode (";", "tail decrement optimized");
3880 tlbl = IC_LABEL (ic->next);
3885 tlbl = newiTempLabel (NULL);
3889 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3890 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3891 IS_AOP_PREG (IC_RESULT (ic)))
3892 emitcode ("cjne", "%s,#0xff,%05d$"
3893 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3897 emitcode ("mov", "a,#0xff");
3898 emitcode ("cjne", "a,%s,%05d$"
3899 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3902 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3905 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3906 IS_AOP_PREG (IC_RESULT (ic)))
3907 emitcode ("cjne", "%s,#0xff,%05d$"
3908 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3912 emitcode ("cjne", "a,%s,%05d$"
3913 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3916 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3921 IS_AOP_PREG (IC_RESULT (ic)))
3922 emitcode ("cjne", "%s,#0xff,%05d$"
3923 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3927 emitcode ("cjne", "a,%s,%05d$"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3931 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3935 emitcode ("", "%05d$:", tlbl->key + 100);
3940 /* if the sizes are greater than 1 then we cannot */
3941 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942 AOP_SIZE (IC_LEFT (ic)) > 1)
3945 /* we can if the aops of the left & result match or
3946 if they are in registers and the registers are the
3948 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3952 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3960 /*-----------------------------------------------------------------*/
3961 /* addSign - complete with sign */
3962 /*-----------------------------------------------------------------*/
3964 addSign (operand * result, int offset, int sign)
3966 int size = (getDataSize (result) - offset);
3971 emitcode ("rlc", "a");
3972 emitcode ("subb", "a,acc");
3974 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3978 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3982 /*-----------------------------------------------------------------*/
3983 /* genMinusBits - generates code for subtraction of two bits */
3984 /*-----------------------------------------------------------------*/
3986 genMinusBits (iCode * ic)
3988 symbol *lbl = newiTempLabel (NULL);
3990 D(emitcode ("; genMinusBits",""));
3992 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3994 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3995 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3996 emitcode ("cpl", "c");
3997 emitcode ("", "%05d$:", (lbl->key + 100));
3998 outBitC (IC_RESULT (ic));
4002 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4003 emitcode ("subb", "a,acc");
4004 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4005 emitcode ("inc", "a");
4006 emitcode ("", "%05d$:", (lbl->key + 100));
4007 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4008 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4012 /*-----------------------------------------------------------------*/
4013 /* genMinus - generates code for subtraction */
4014 /*-----------------------------------------------------------------*/
4016 genMinus (iCode * ic)
4018 int size, offset = 0;
4020 D(emitcode ("; genMinus",""));
4022 aopOp (IC_LEFT (ic), ic, FALSE);
4023 aopOp (IC_RIGHT (ic), ic, FALSE);
4024 aopOp (IC_RESULT (ic), ic, TRUE);
4026 /* special cases :- */
4027 /* if both left & right are in bit space */
4028 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4029 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4035 /* if I can do an decrement instead
4036 of subtract then GOOD for ME */
4037 if (genMinusDec (ic) == TRUE)
4040 size = getDataSize (IC_RESULT (ic));
4042 /* if literal, add a,#-lit, else normal subb */
4043 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4045 unsigned long lit = 0L;
4047 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4052 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4053 /* first add without previous c */
4055 if (!size && lit== (unsigned long) -1) {
4056 emitcode ("dec", "a");
4058 emitcode ("add", "a,#0x%02x",
4059 (unsigned int) (lit & 0x0FFL));
4062 emitcode ("addc", "a,#0x%02x",
4063 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4065 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4070 asmop *leftOp, *rightOp;
4072 leftOp = AOP(IC_LEFT(ic));
4073 rightOp = AOP(IC_RIGHT(ic));
4077 if (aopGetUsesAcc(rightOp, offset)) {
4078 if (aopGetUsesAcc(leftOp, offset)) {
4081 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4083 emitcode ("mov", "b,a");
4086 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4087 emitcode ("subb", "a,b");
4090 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4091 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4093 emitcode( "setb", "c");
4095 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4096 emitcode("cpl", "a");
4099 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4102 emitcode ("subb", "a,%s",
4103 aopGet(rightOp, offset, FALSE, TRUE));
4106 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4111 adjustArithmeticResult (ic);
4114 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4115 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4120 /*-----------------------------------------------------------------*/
4121 /* genMultbits :- multiplication of bits */
4122 /*-----------------------------------------------------------------*/
4124 genMultbits (operand * left,
4128 D(emitcode ("; genMultbits",""));
4130 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4131 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4135 /*-----------------------------------------------------------------*/
4136 /* genMultOneByte : 8*8=8/16 bit multiplication */
4137 /*-----------------------------------------------------------------*/
4139 genMultOneByte (operand * left,
4144 int size = AOP_SIZE (result);
4145 bool runtimeSign, compiletimeSign;
4146 bool lUnsigned, rUnsigned, pushedB;
4148 D(emitcode ("; genMultOneByte",""));
4150 if (size < 1 || size > 2)
4152 /* this should never happen */
4153 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4154 AOP_SIZE(result), __FILE__, lineno);
4158 /* (if two literals: the value is computed before) */
4159 /* if one literal, literal on the right */
4160 if (AOP_TYPE (left) == AOP_LIT)
4165 /* emitcode (";", "swapped left and right"); */
4167 /* if no literal, unsigned on the right: shorter code */
4168 if ( AOP_TYPE (right) != AOP_LIT
4169 && SPEC_USIGN (getSpec (operandType (left))))
4176 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4177 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4181 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4182 no need to take care about the signedness! */
4183 || (lUnsigned && rUnsigned))
4185 /* just an unsigned 8 * 8 = 8 multiply
4187 /* emitcode (";","unsigned"); */
4188 /* TODO: check for accumulator clash between left & right aops? */
4190 if (AOP_TYPE (right) == AOP_LIT)
4192 /* moving to accumulator first helps peepholes */
4193 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4194 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4198 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4199 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4202 emitcode ("mul", "ab");
4203 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4205 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4211 /* we have to do a signed multiply */
4212 /* emitcode (";", "signed"); */
4214 /* now sign adjust for both left & right */
4216 /* let's see what's needed: */
4217 /* apply negative sign during runtime */
4218 runtimeSign = FALSE;
4219 /* negative sign from literals */
4220 compiletimeSign = FALSE;
4224 if (AOP_TYPE(left) == AOP_LIT)
4226 /* signed literal */
4227 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4229 compiletimeSign = TRUE;
4232 /* signed but not literal */
4238 if (AOP_TYPE(right) == AOP_LIT)
4240 /* signed literal */
4241 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4243 compiletimeSign ^= TRUE;
4246 /* signed but not literal */
4250 /* initialize F0, which stores the runtime sign */
4253 if (compiletimeSign)
4254 emitcode ("setb", "F0"); /* set sign flag */
4256 emitcode ("clr", "F0"); /* reset sign flag */
4259 /* save the signs of the operands */
4260 if (AOP_TYPE(right) == AOP_LIT)
4262 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4264 if (!rUnsigned && val < 0)
4265 emitcode ("mov", "b,#0x%02x", -val);
4267 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4269 else /* ! literal */
4271 if (rUnsigned) /* emitcode (";", "signed"); */
4273 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4276 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4277 lbl = newiTempLabel (NULL);
4278 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4279 emitcode ("cpl", "F0"); /* complement sign flag */
4280 emitcode ("cpl", "a"); /* 2's complement */
4281 emitcode ("inc", "a");
4282 emitcode ("", "%05d$:", (lbl->key + 100));
4283 emitcode ("mov", "b,a");
4287 if (AOP_TYPE(left) == AOP_LIT)
4289 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4291 if (!lUnsigned && val < 0)
4292 emitcode ("mov", "a,#0x%02x", -val);
4294 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4296 else /* ! literal */
4298 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4302 lbl = newiTempLabel (NULL);
4303 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4304 emitcode ("cpl", "F0"); /* complement sign flag */
4305 emitcode ("cpl", "a"); /* 2's complement */
4306 emitcode ("inc", "a");
4307 emitcode ("", "%05d$:", (lbl->key + 100));
4311 /* now the multiplication */
4312 emitcode ("mul", "ab");
4313 if (runtimeSign || compiletimeSign)
4315 lbl = newiTempLabel (NULL);
4317 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4318 emitcode ("cpl", "a"); /* lsb 2's complement */
4320 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4323 emitcode ("add", "a,#1"); /* this sets carry flag */
4324 emitcode ("xch", "a,b");
4325 emitcode ("cpl", "a"); /* msb 2's complement */
4326 emitcode ("addc", "a,#0");
4327 emitcode ("xch", "a,b");
4329 emitcode ("", "%05d$:", (lbl->key + 100));
4331 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4333 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4338 /*-----------------------------------------------------------------*/
4339 /* genMult - generates code for multiplication */
4340 /*-----------------------------------------------------------------*/
4342 genMult (iCode * ic)
4344 operand *left = IC_LEFT (ic);
4345 operand *right = IC_RIGHT (ic);
4346 operand *result = IC_RESULT (ic);
4348 D(emitcode ("; genMult",""));
4350 /* assign the amsops */
4351 aopOp (left, ic, FALSE);
4352 aopOp (right, ic, FALSE);
4353 aopOp (result, ic, TRUE);
4355 /* special cases first */
4357 if (AOP_TYPE (left) == AOP_CRY &&
4358 AOP_TYPE (right) == AOP_CRY)
4360 genMultbits (left, right, result);
4364 /* if both are of size == 1 */
4365 #if 0 // one of them can be a sloc shared with the result
4366 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4368 if (getSize(operandType(left)) == 1 &&
4369 getSize(operandType(right)) == 1)
4372 genMultOneByte (left, right, result);
4376 /* should have been converted to function call */
4377 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4378 getSize(OP_SYMBOL(right)->type));
4382 freeAsmop (result, NULL, ic, TRUE);
4383 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4384 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4387 /*-----------------------------------------------------------------*/
4388 /* genDivbits :- division of bits */
4389 /*-----------------------------------------------------------------*/
4391 genDivbits (operand * left,
4398 D(emitcode ("; genDivbits",""));
4402 /* the result must be bit */
4403 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4404 l = aopGet (AOP (left), 0, FALSE, FALSE);
4408 emitcode ("div", "ab");
4409 emitcode ("rrc", "a");
4413 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4416 /*-----------------------------------------------------------------*/
4417 /* genDivOneByte : 8 bit division */
4418 /*-----------------------------------------------------------------*/
4420 genDivOneByte (operand * left,
4424 bool lUnsigned, rUnsigned, pushedB;
4425 bool runtimeSign, compiletimeSign;
4429 D(emitcode ("; genDivOneByte",""));
4431 /* Why is it necessary that genDivOneByte() can return an int result?
4434 volatile unsigned char uc;
4435 volatile signed char sc1, sc2;
4448 In all cases a one byte result would overflow, the following cast to int
4449 would return the wrong result.
4451 Two possible solution:
4452 a) cast operands to int, if ((unsigned) / (signed)) or
4453 ((signed) / (signed))
4454 b) return an 16 bit signed int; this is what we're doing here!
4457 size = AOP_SIZE (result) - 1;
4459 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4460 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4464 /* signed or unsigned */
4465 if (lUnsigned && rUnsigned)
4467 /* unsigned is easy */
4468 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4469 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4470 emitcode ("div", "ab");
4471 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4473 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4479 /* signed is a little bit more difficult */
4481 /* now sign adjust for both left & right */
4483 /* let's see what's needed: */
4484 /* apply negative sign during runtime */
4485 runtimeSign = FALSE;
4486 /* negative sign from literals */
4487 compiletimeSign = FALSE;
4491 if (AOP_TYPE(left) == AOP_LIT)
4493 /* signed literal */
4494 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4496 compiletimeSign = TRUE;
4499 /* signed but not literal */
4505 if (AOP_TYPE(right) == AOP_LIT)
4507 /* signed literal */
4508 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4510 compiletimeSign ^= TRUE;
4513 /* signed but not literal */
4517 /* initialize F0, which stores the runtime sign */
4520 if (compiletimeSign)
4521 emitcode ("setb", "F0"); /* set sign flag */
4523 emitcode ("clr", "F0"); /* reset sign flag */
4526 /* save the signs of the operands */
4527 if (AOP_TYPE(right) == AOP_LIT)
4529 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4531 if (!rUnsigned && val < 0)
4532 emitcode ("mov", "b,#0x%02x", -val);
4534 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4536 else /* ! literal */
4539 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4542 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4543 lbl = newiTempLabel (NULL);
4544 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4545 emitcode ("cpl", "F0"); /* complement sign flag */
4546 emitcode ("cpl", "a"); /* 2's complement */
4547 emitcode ("inc", "a");
4548 emitcode ("", "%05d$:", (lbl->key + 100));
4549 emitcode ("mov", "b,a");
4553 if (AOP_TYPE(left) == AOP_LIT)
4555 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4557 if (!lUnsigned && val < 0)
4558 emitcode ("mov", "a,#0x%02x", -val);
4560 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4562 else /* ! literal */
4564 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4568 lbl = newiTempLabel (NULL);
4569 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4570 emitcode ("cpl", "F0"); /* complement sign flag */
4571 emitcode ("cpl", "a"); /* 2's complement */
4572 emitcode ("inc", "a");
4573 emitcode ("", "%05d$:", (lbl->key + 100));
4577 /* now the division */
4578 emitcode ("div", "ab");
4580 if (runtimeSign || compiletimeSign)
4582 lbl = newiTempLabel (NULL);
4584 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4585 emitcode ("cpl", "a"); /* lsb 2's complement */
4586 emitcode ("inc", "a");
4587 emitcode ("", "%05d$:", (lbl->key + 100));
4589 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4592 /* msb is 0x00 or 0xff depending on the sign */
4595 emitcode ("mov", "c,F0");
4596 emitcode ("subb", "a,acc");
4598 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4600 else /* compiletimeSign */
4602 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4607 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4609 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4615 /*-----------------------------------------------------------------*/
4616 /* genDiv - generates code for division */
4617 /*-----------------------------------------------------------------*/
4621 operand *left = IC_LEFT (ic);
4622 operand *right = IC_RIGHT (ic);
4623 operand *result = IC_RESULT (ic);
4625 D(emitcode ("; genDiv",""));
4627 /* assign the amsops */
4628 aopOp (left, ic, FALSE);
4629 aopOp (right, ic, FALSE);
4630 aopOp (result, ic, TRUE);
4632 /* special cases first */
4634 if (AOP_TYPE (left) == AOP_CRY &&
4635 AOP_TYPE (right) == AOP_CRY)
4637 genDivbits (left, right, result);
4641 /* if both are of size == 1 */
4642 if (AOP_SIZE (left) == 1 &&
4643 AOP_SIZE (right) == 1)
4645 genDivOneByte (left, right, result);
4649 /* should have been converted to function call */
4652 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4654 freeAsmop (result, NULL, ic, TRUE);
4657 /*-----------------------------------------------------------------*/
4658 /* genModbits :- modulus of bits */
4659 /*-----------------------------------------------------------------*/
4661 genModbits (operand * left,
4668 D(emitcode ("; genModbits",""));
4672 /* the result must be bit */
4673 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4674 l = aopGet (AOP (left), 0, FALSE, FALSE);
4678 emitcode ("div", "ab");
4679 emitcode ("mov", "a,b");
4680 emitcode ("rrc", "a");
4684 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4687 /*-----------------------------------------------------------------*/
4688 /* genModOneByte : 8 bit modulus */
4689 /*-----------------------------------------------------------------*/
4691 genModOneByte (operand * left,
4695 bool lUnsigned, rUnsigned, pushedB;
4696 bool runtimeSign, compiletimeSign;
4700 D(emitcode ("; genModOneByte",""));
4702 size = AOP_SIZE (result) - 1;
4704 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4705 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4707 /* if right is a literal, check it for 2^n */
4708 if (AOP_TYPE(right) == AOP_LIT)
4710 unsigned char val = abs(operandLitValue(right));
4711 symbol *lbl2 = NULL;
4715 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4724 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4725 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4726 /* because iCode should have been changed to genAnd */
4727 /* see file "SDCCopt.c", function "convertToFcall()" */
4729 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4730 emitcode ("mov", "c,acc.7");
4731 emitcode ("anl", "a,#0x%02x", val - 1);
4732 lbl = newiTempLabel (NULL);
4733 emitcode ("jz", "%05d$", (lbl->key + 100));
4734 emitcode ("jnc", "%05d$", (lbl->key + 100));
4735 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4741 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4743 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4744 lbl2 = newiTempLabel (NULL);
4745 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4747 emitcode ("", "%05d$:", (lbl->key + 100));
4748 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4750 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4753 emitcode ("", "%05d$:", (lbl2->key + 100));
4764 /* signed or unsigned */
4765 if (lUnsigned && rUnsigned)
4767 /* unsigned is easy */
4768 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4769 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4770 emitcode ("div", "ab");
4771 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4773 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4779 /* signed is a little bit more difficult */
4781 /* now sign adjust for both left & right */
4783 /* modulus: sign of the right operand has no influence on the result! */
4784 if (AOP_TYPE(right) == AOP_LIT)
4786 signed char val = (char) operandLitValue(right);
4788 if (!rUnsigned && val < 0)
4789 emitcode ("mov", "b,#0x%02x", -val);
4791 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4793 else /* not literal */
4796 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4799 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4800 lbl = newiTempLabel (NULL);
4801 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4802 emitcode ("cpl", "a"); /* 2's complement */
4803 emitcode ("inc", "a");
4804 emitcode ("", "%05d$:", (lbl->key + 100));
4805 emitcode ("mov", "b,a");
4809 /* let's see what's needed: */
4810 /* apply negative sign during runtime */
4811 runtimeSign = FALSE;
4812 /* negative sign from literals */
4813 compiletimeSign = FALSE;
4815 /* sign adjust left side */
4816 if (AOP_TYPE(left) == AOP_LIT)
4818 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4820 if (!lUnsigned && val < 0)
4822 compiletimeSign = TRUE; /* set sign flag */
4823 emitcode ("mov", "a,#0x%02x", -val);
4826 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4828 else /* ! literal */
4830 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4835 emitcode ("clr", "F0"); /* clear sign flag */
4837 lbl = newiTempLabel (NULL);
4838 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4839 emitcode ("setb", "F0"); /* set sign flag */
4840 emitcode ("cpl", "a"); /* 2's complement */
4841 emitcode ("inc", "a");
4842 emitcode ("", "%05d$:", (lbl->key + 100));
4846 /* now the modulus */
4847 emitcode ("div", "ab");
4849 if (runtimeSign || compiletimeSign)
4851 emitcode ("mov", "a,b");
4852 lbl = newiTempLabel (NULL);
4854 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4855 emitcode ("cpl", "a"); /* 2's complement */
4856 emitcode ("inc", "a");
4857 emitcode ("", "%05d$:", (lbl->key + 100));
4859 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4862 /* msb is 0x00 or 0xff depending on the sign */
4865 emitcode ("mov", "c,F0");
4866 emitcode ("subb", "a,acc");
4868 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4870 else /* compiletimeSign */
4872 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4877 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4879 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4885 /*-----------------------------------------------------------------*/
4886 /* genMod - generates code for division */
4887 /*-----------------------------------------------------------------*/
4891 operand *left = IC_LEFT (ic);
4892 operand *right = IC_RIGHT (ic);
4893 operand *result = IC_RESULT (ic);
4895 D(emitcode ("; genMod",""));
4897 /* assign the asmops */
4898 aopOp (left, ic, FALSE);
4899 aopOp (right, ic, FALSE);
4900 aopOp (result, ic, TRUE);
4902 /* special cases first */
4904 if (AOP_TYPE (left) == AOP_CRY &&
4905 AOP_TYPE (right) == AOP_CRY)
4907 genModbits (left, right, result);
4911 /* if both are of size == 1 */
4912 if (AOP_SIZE (left) == 1 &&
4913 AOP_SIZE (right) == 1)
4915 genModOneByte (left, right, result);
4919 /* should have been converted to function call */
4923 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (result, NULL, ic, TRUE);
4928 /*-----------------------------------------------------------------*/
4929 /* genIfxJump :- will create a jump depending on the ifx */
4930 /*-----------------------------------------------------------------*/
4932 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4935 symbol *tlbl = newiTempLabel (NULL);
4938 D(emitcode ("; genIfxJump",""));
4940 /* if true label then we jump if condition
4944 jlbl = IC_TRUE (ic);
4945 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4946 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4950 /* false label is present */
4951 jlbl = IC_FALSE (ic);
4952 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4953 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4955 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4956 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4958 emitcode (inst, "%05d$", tlbl->key + 100);
4959 freeForBranchAsmop (result);
4960 freeForBranchAsmop (right);
4961 freeForBranchAsmop (left);
4962 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4963 emitcode ("", "%05d$:", tlbl->key + 100);
4965 /* mark the icode as generated */
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison */
4971 /*-----------------------------------------------------------------*/
4973 genCmp (operand * left, operand * right,
4974 operand * result, iCode * ifx, int sign, iCode *ic)
4976 int size, offset = 0;
4977 unsigned long lit = 0L;
4980 D(emitcode ("; genCmp",""));
4982 /* if left & right are bit variables */
4983 if (AOP_TYPE (left) == AOP_CRY &&
4984 AOP_TYPE (right) == AOP_CRY)
4986 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4987 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4991 /* subtract right from left if at the
4992 end the carry flag is set then we know that
4993 left is greater than right */
4994 size = max (AOP_SIZE (left), AOP_SIZE (right));
4996 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4997 if ((size == 1) && !sign &&
4998 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5000 symbol *lbl = newiTempLabel (NULL);
5001 emitcode ("cjne", "%s,%s,%05d$",
5002 aopGet (AOP (left), offset, FALSE, FALSE),
5003 aopGet (AOP (right), offset, FALSE, FALSE),
5005 emitcode ("", "%05d$:", lbl->key + 100);
5009 if (AOP_TYPE (right) == AOP_LIT)
5011 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5012 /* optimize if(x < 0) or if(x >= 0) */
5021 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5022 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5024 genIfxJump (ifx, "acc.7", left, right, result);
5025 freeAsmop (right, NULL, ic, TRUE);
5026 freeAsmop (left, NULL, ic, TRUE);
5031 emitcode ("rlc", "a");
5039 bool pushedB = FALSE;
5040 rightInB = aopGetUsesAcc(AOP (right), offset);
5044 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5046 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5047 if (sign && size == 0)
5049 emitcode ("xrl", "a,#0x80");
5050 if (AOP_TYPE (right) == AOP_LIT)
5052 unsigned long lit = (unsigned long)
5053 floatFromVal (AOP (right)->aopu.aop_lit);
5054 emitcode ("subb", "a,#0x%02x",
5055 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5063 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5065 emitcode ("xrl", "b,#0x80");
5066 emitcode ("subb", "a,b");
5072 emitcode ("subb", "a,b");
5074 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5084 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5092 /* if the result is used in the next
5093 ifx conditional branch then generate
5094 code a little differently */
5096 genIfxJump (ifx, "c", NULL, NULL, result);
5099 /* leave the result in acc */
5103 /*-----------------------------------------------------------------*/
5104 /* genCmpGt :- greater than comparison */
5105 /*-----------------------------------------------------------------*/
5107 genCmpGt (iCode * ic, iCode * ifx)
5109 operand *left, *right, *result;
5110 sym_link *letype, *retype;
5113 D(emitcode ("; genCmpGt",""));
5115 left = IC_LEFT (ic);
5116 right = IC_RIGHT (ic);
5117 result = IC_RESULT (ic);
5119 letype = getSpec (operandType (left));
5120 retype = getSpec (operandType (right));
5121 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5122 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5123 /* assign the amsops */
5124 aopOp (left, ic, FALSE);
5125 aopOp (right, ic, FALSE);
5126 aopOp (result, ic, TRUE);
5128 genCmp (right, left, result, ifx, sign, ic);
5130 freeAsmop (result, NULL, ic, TRUE);
5133 /*-----------------------------------------------------------------*/
5134 /* genCmpLt - less than comparisons */
5135 /*-----------------------------------------------------------------*/
5137 genCmpLt (iCode * ic, iCode * ifx)
5139 operand *left, *right, *result;
5140 sym_link *letype, *retype;
5143 D(emitcode ("; genCmpLt",""));
5145 left = IC_LEFT (ic);
5146 right = IC_RIGHT (ic);
5147 result = IC_RESULT (ic);
5149 letype = getSpec (operandType (left));
5150 retype = getSpec (operandType (right));
5151 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5152 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5153 /* assign the amsops */
5154 aopOp (left, ic, FALSE);
5155 aopOp (right, ic, FALSE);
5156 aopOp (result, ic, TRUE);
5158 genCmp (left, right, result, ifx, sign,ic);
5160 freeAsmop (result, NULL, ic, TRUE);
5163 /*-----------------------------------------------------------------*/
5164 /* gencjneshort - compare and jump if not equal */
5165 /*-----------------------------------------------------------------*/
5167 gencjneshort (operand * left, operand * right, symbol * lbl)
5169 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5171 unsigned long lit = 0L;
5173 /* if the left side is a literal or
5174 if the right is in a pointer register and left
5176 if ((AOP_TYPE (left) == AOP_LIT) ||
5177 (AOP_TYPE (left) == AOP_IMMD) ||
5178 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5185 if (AOP_TYPE (right) == AOP_LIT)
5186 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5188 /* if the right side is a literal then anything goes */
5189 if (AOP_TYPE (right) == AOP_LIT &&
5190 AOP_TYPE (left) != AOP_DIR &&
5191 AOP_TYPE (left) != AOP_IMMD)
5195 emitcode ("cjne", "%s,%s,%05d$",
5196 aopGet (AOP (left), offset, FALSE, FALSE),
5197 aopGet (AOP (right), offset, FALSE, FALSE),
5203 /* if the right side is in a register or in direct space or
5204 if the left is a pointer register & right is not */
5205 else if (AOP_TYPE (right) == AOP_REG ||
5206 AOP_TYPE (right) == AOP_DIR ||
5207 AOP_TYPE (right) == AOP_LIT ||
5208 AOP_TYPE (right) == AOP_IMMD ||
5209 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5210 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5215 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5216 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5217 emitcode ("jnz", "%05d$", lbl->key + 100);
5219 emitcode ("cjne", "a,%s,%05d$",
5220 aopGet (AOP (right), offset, FALSE, TRUE),
5227 /* right is a pointer reg need both a & b */
5231 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5232 wassertl(!_G.BInUse, "B was in use");
5233 l = aopGet (AOP (left), offset, FALSE, FALSE);
5234 if (strcmp (l, "b"))
5235 emitcode ("mov", "b,%s", l);
5236 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5237 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5243 /*-----------------------------------------------------------------*/
5244 /* gencjne - compare and jump if not equal */
5245 /*-----------------------------------------------------------------*/
5247 gencjne (operand * left, operand * right, symbol * lbl)
5249 symbol *tlbl = newiTempLabel (NULL);
5251 gencjneshort (left, right, lbl);
5253 emitcode ("mov", "a,%s", one);
5254 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5255 emitcode ("", "%05d$:", lbl->key + 100);
5256 emitcode ("clr", "a");
5257 emitcode ("", "%05d$:", tlbl->key + 100);
5260 /*-----------------------------------------------------------------*/
5261 /* genCmpEq - generates code for equal to */
5262 /*-----------------------------------------------------------------*/
5264 genCmpEq (iCode * ic, iCode * ifx)
5266 operand *left, *right, *result;
5268 D(emitcode ("; genCmpEq",""));
5270 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5271 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5272 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5274 /* if literal, literal on the right or
5275 if the right is in a pointer register and left
5277 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5278 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5280 operand *t = IC_RIGHT (ic);
5281 IC_RIGHT (ic) = IC_LEFT (ic);
5285 if (ifx && !AOP_SIZE (result))
5288 /* if they are both bit variables */
5289 if (AOP_TYPE (left) == AOP_CRY &&
5290 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5292 if (AOP_TYPE (right) == AOP_LIT)
5294 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5297 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 emitcode ("cpl", "c");
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5306 emitcode ("clr", "c");
5308 /* AOP_TYPE(right) == AOP_CRY */
5312 symbol *lbl = newiTempLabel (NULL);
5313 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5314 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5315 emitcode ("cpl", "c");
5316 emitcode ("", "%05d$:", (lbl->key + 100));
5318 /* if true label then we jump if condition
5320 tlbl = newiTempLabel (NULL);
5323 emitcode ("jnc", "%05d$", tlbl->key + 100);
5324 freeForBranchAsmop (result);
5325 freeForBranchAsmop (right);
5326 freeForBranchAsmop (left);
5327 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5331 emitcode ("jc", "%05d$", tlbl->key + 100);
5332 freeForBranchAsmop (result);
5333 freeForBranchAsmop (right);
5334 freeForBranchAsmop (left);
5335 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5337 emitcode ("", "%05d$:", tlbl->key + 100);
5341 tlbl = newiTempLabel (NULL);
5342 gencjneshort (left, right, tlbl);
5345 freeForBranchAsmop (result);
5346 freeForBranchAsmop (right);
5347 freeForBranchAsmop (left);
5348 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5349 emitcode ("", "%05d$:", tlbl->key + 100);
5353 symbol *lbl = newiTempLabel (NULL);
5354 emitcode ("sjmp", "%05d$", lbl->key + 100);
5355 emitcode ("", "%05d$:", tlbl->key + 100);
5356 freeForBranchAsmop (result);
5357 freeForBranchAsmop (right);
5358 freeForBranchAsmop (left);
5359 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5360 emitcode ("", "%05d$:", lbl->key + 100);
5363 /* mark the icode as generated */
5368 /* if they are both bit variables */
5369 if (AOP_TYPE (left) == AOP_CRY &&
5370 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5377 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5378 emitcode ("cpl", "c");
5382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5386 emitcode ("clr", "c");
5388 /* AOP_TYPE(right) == AOP_CRY */
5392 symbol *lbl = newiTempLabel (NULL);
5393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5394 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5395 emitcode ("cpl", "c");
5396 emitcode ("", "%05d$:", (lbl->key + 100));
5399 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5406 genIfxJump (ifx, "c", left, right, result);
5409 /* if the result is used in an arithmetic operation
5410 then put the result in place */
5415 gencjne (left, right, newiTempLabel (NULL));
5416 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5418 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5423 genIfxJump (ifx, "a", left, right, result);
5426 /* if the result is used in an arithmetic operation
5427 then put the result in place */
5428 if (AOP_TYPE (result) != AOP_CRY)
5430 /* leave the result in acc */
5434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5436 freeAsmop (result, NULL, ic, TRUE);
5439 /*-----------------------------------------------------------------*/
5440 /* ifxForOp - returns the icode containing the ifx for operand */
5441 /*-----------------------------------------------------------------*/
5443 ifxForOp (operand * op, iCode * ic)
5445 /* if true symbol then needs to be assigned */
5446 if (IS_TRUE_SYMOP (op))
5449 /* if this has register type condition and
5450 the next instruction is ifx with the same operand
5451 and live to of the operand is upto the ifx only then */
5453 ic->next->op == IFX &&
5454 IC_COND (ic->next)->key == op->key &&
5455 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5461 /*-----------------------------------------------------------------*/
5462 /* hasInc - operand is incremented before any other use */
5463 /*-----------------------------------------------------------------*/
5465 hasInc (operand *op, iCode *ic,int osize)
5467 sym_link *type = operandType(op);
5468 sym_link *retype = getSpec (type);
5469 iCode *lic = ic->next;
5472 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5473 if (!IS_SYMOP(op)) return NULL;
5475 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5476 if (IS_AGGREGATE(type->next)) return NULL;
5477 if (osize != (isize = getSize(type->next))) return NULL;
5480 /* if operand of the form op = op + <sizeof *op> */
5481 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5482 isOperandEqual(IC_RESULT(lic),op) &&
5483 isOperandLiteral(IC_RIGHT(lic)) &&
5484 operandLitValue(IC_RIGHT(lic)) == isize) {
5487 /* if the operand used or deffed */
5488 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5491 /* if GOTO or IFX */
5492 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5498 /*-----------------------------------------------------------------*/
5499 /* genAndOp - for && operation */
5500 /*-----------------------------------------------------------------*/
5502 genAndOp (iCode * ic)
5504 operand *left, *right, *result;
5507 D(emitcode ("; genAndOp",""));
5509 /* note here that && operations that are in an
5510 if statement are taken away by backPatchLabels
5511 only those used in arthmetic operations remain */
5512 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5513 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5514 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5516 /* if both are bit variables */
5517 if (AOP_TYPE (left) == AOP_CRY &&
5518 AOP_TYPE (right) == AOP_CRY)
5520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5521 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5526 tlbl = newiTempLabel (NULL);
5528 emitcode ("jz", "%05d$", tlbl->key + 100);
5530 emitcode ("", "%05d$:", tlbl->key + 100);
5534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536 freeAsmop (result, NULL, ic, TRUE);
5540 /*-----------------------------------------------------------------*/
5541 /* genOrOp - for || operation */
5542 /*-----------------------------------------------------------------*/
5544 genOrOp (iCode * ic)
5546 operand *left, *right, *result;
5549 D(emitcode ("; genOrOp",""));
5551 /* note here that || operations that are in an
5552 if statement are taken away by backPatchLabels
5553 only those used in arthmetic operations remain */
5554 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5556 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5558 /* if both are bit variables */
5559 if (AOP_TYPE (left) == AOP_CRY &&
5560 AOP_TYPE (right) == AOP_CRY)
5562 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5563 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5568 tlbl = newiTempLabel (NULL);
5570 emitcode ("jnz", "%05d$", tlbl->key + 100);
5572 emitcode ("", "%05d$:", tlbl->key + 100);
5576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5578 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* isLiteralBit - test if lit == 2^n */
5583 /*-----------------------------------------------------------------*/
5585 isLiteralBit (unsigned long lit)
5587 unsigned long pw[32] =
5588 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5589 0x100L, 0x200L, 0x400L, 0x800L,
5590 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5591 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5592 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5593 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5594 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5597 for (idx = 0; idx < 32; idx++)
5603 /*-----------------------------------------------------------------*/
5604 /* continueIfTrue - */
5605 /*-----------------------------------------------------------------*/
5607 continueIfTrue (iCode * ic)
5610 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5614 /*-----------------------------------------------------------------*/
5616 /*-----------------------------------------------------------------*/
5618 jumpIfTrue (iCode * ic)
5621 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5625 /*-----------------------------------------------------------------*/
5626 /* jmpTrueOrFalse - */
5627 /*-----------------------------------------------------------------*/
5629 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5631 // ugly but optimized by peephole
5634 symbol *nlbl = newiTempLabel (NULL);
5635 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5636 emitcode ("", "%05d$:", tlbl->key + 100);
5637 freeForBranchAsmop (result);
5638 freeForBranchAsmop (right);
5639 freeForBranchAsmop (left);
5640 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5641 emitcode ("", "%05d$:", nlbl->key + 100);
5645 freeForBranchAsmop (result);
5646 freeForBranchAsmop (right);
5647 freeForBranchAsmop (left);
5648 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5649 emitcode ("", "%05d$:", tlbl->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* genAnd - code for and */
5656 /*-----------------------------------------------------------------*/
5658 genAnd (iCode * ic, iCode * ifx)
5660 operand *left, *right, *result;
5661 int size, offset = 0;
5662 unsigned long lit = 0L;
5666 D(emitcode ("; genAnd",""));
5668 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5669 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5670 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5673 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5675 AOP_TYPE (left), AOP_TYPE (right));
5676 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5678 AOP_SIZE (left), AOP_SIZE (right));
5681 /* if left is a literal & right is not then exchange them */
5682 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5683 AOP_NEEDSACC (left))
5685 operand *tmp = right;
5690 /* if result = right then exchange left and right */
5691 if (sameRegs (AOP (result), AOP (right)))
5693 operand *tmp = right;
5698 /* if right is bit then exchange them */
5699 if (AOP_TYPE (right) == AOP_CRY &&
5700 AOP_TYPE (left) != AOP_CRY)
5702 operand *tmp = right;
5706 if (AOP_TYPE (right) == AOP_LIT)
5707 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5709 size = AOP_SIZE (result);
5712 // result = bit & yy;
5713 if (AOP_TYPE (left) == AOP_CRY)
5715 // c = bit & literal;
5716 if (AOP_TYPE (right) == AOP_LIT)
5720 if (size && sameRegs (AOP (result), AOP (left)))
5723 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5728 if (size && (AOP_TYPE (result) == AOP_CRY))
5730 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5733 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5738 emitcode ("clr", "c");
5743 if (AOP_TYPE (right) == AOP_CRY)
5746 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5747 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5752 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5754 emitcode ("rrc", "a");
5755 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5763 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5764 genIfxJump (ifx, "c", left, right, result);
5768 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5769 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5770 if ((AOP_TYPE (right) == AOP_LIT) &&
5771 (AOP_TYPE (result) == AOP_CRY) &&
5772 (AOP_TYPE (left) != AOP_CRY))
5774 int posbit = isLiteralBit (lit);
5779 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5782 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5788 SNPRINTF (buffer, sizeof(buffer),
5789 "acc.%d", posbit & 0x07);
5790 genIfxJump (ifx, buffer, left, right, result);
5793 {// what is this case? just found it in ds390/gen.c
5794 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5801 symbol *tlbl = newiTempLabel (NULL);
5802 int sizel = AOP_SIZE (left);
5804 emitcode ("setb", "c");
5807 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5809 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5811 if ((posbit = isLiteralBit (bytelit)) != 0)
5812 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5815 if (bytelit != 0x0FFL)
5816 emitcode ("anl", "a,%s",
5817 aopGet (AOP (right), offset, FALSE, TRUE));
5818 emitcode ("jnz", "%05d$", tlbl->key + 100);
5823 // bit = left & literal
5826 emitcode ("clr", "c");
5827 emitcode ("", "%05d$:", tlbl->key + 100);
5829 // if(left & literal)
5833 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5835 emitcode ("", "%05d$:", tlbl->key + 100);
5843 /* if left is same as result */
5844 if (sameRegs (AOP (result), AOP (left)))
5846 for (; size--; offset++)
5848 if (AOP_TYPE (right) == AOP_LIT)
5850 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5851 if (bytelit == 0x0FF)
5853 /* dummy read of volatile operand */
5854 if (isOperandVolatile (left, FALSE))
5855 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5859 else if (bytelit == 0)
5861 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5863 else if (IS_AOP_PREG (result))
5865 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5866 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5867 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5870 emitcode ("anl", "%s,%s",
5871 aopGet (AOP (left), offset, FALSE, TRUE),
5872 aopGet (AOP (right), offset, FALSE, FALSE));
5876 if (AOP_TYPE (left) == AOP_ACC)
5877 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5881 if (IS_AOP_PREG (result))
5883 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5884 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5887 emitcode ("anl", "%s,a",
5888 aopGet (AOP (left), offset, FALSE, TRUE));
5895 // left & result in different registers
5896 if (AOP_TYPE (result) == AOP_CRY)
5899 // if(size), result in bit
5900 // if(!size && ifx), conditional oper: if(left & right)
5901 symbol *tlbl = newiTempLabel (NULL);
5902 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5904 emitcode ("setb", "c");
5907 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5908 emitcode ("anl", "a,%s",
5909 aopGet (AOP (right), offset, FALSE, FALSE));
5911 if (AOP_TYPE(left)==AOP_ACC) {
5912 bool pushedB = pushB ();
5913 emitcode("mov", "b,a");
5914 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5915 emitcode("anl", "a,b");
5918 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5919 emitcode ("anl", "a,%s",
5920 aopGet (AOP (left), offset, FALSE, FALSE));
5923 emitcode ("jnz", "%05d$", tlbl->key + 100);
5929 emitcode ("", "%05d$:", tlbl->key + 100);
5933 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5935 emitcode ("", "%05d$:", tlbl->key + 100);
5939 for (; (size--); offset++)
5942 // result = left & right
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5946 if (bytelit == 0x0FF)
5948 aopPut (AOP (result),
5949 aopGet (AOP (left), offset, FALSE, FALSE),
5951 isOperandVolatile (result, FALSE));
5954 else if (bytelit == 0)
5956 /* dummy read of volatile operand */
5957 if (isOperandVolatile (left, FALSE))
5958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5959 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5963 // faster than result <- left, anl result,right
5964 // and better if result is SFR
5965 if (AOP_TYPE (left) == AOP_ACC)
5966 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5969 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5970 emitcode ("anl", "a,%s",
5971 aopGet (AOP (left), offset, FALSE, FALSE));
5973 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981 freeAsmop (result, NULL, ic, TRUE);
5984 /*-----------------------------------------------------------------*/
5985 /* genOr - code for or */
5986 /*-----------------------------------------------------------------*/
5988 genOr (iCode * ic, iCode * ifx)
5990 operand *left, *right, *result;
5991 int size, offset = 0;
5992 unsigned long lit = 0L;
5995 D(emitcode ("; genOr",""));
5997 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5998 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5999 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6002 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6004 AOP_TYPE (left), AOP_TYPE (right));
6005 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6007 AOP_SIZE (left), AOP_SIZE (right));
6010 /* if left is a literal & right is not then exchange them */
6011 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6012 AOP_NEEDSACC (left))
6014 operand *tmp = right;
6019 /* if result = right then exchange them */
6020 if (sameRegs (AOP (result), AOP (right)))
6022 operand *tmp = right;
6027 /* if right is bit then exchange them */
6028 if (AOP_TYPE (right) == AOP_CRY &&
6029 AOP_TYPE (left) != AOP_CRY)
6031 operand *tmp = right;
6035 if (AOP_TYPE (right) == AOP_LIT)
6036 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6038 size = AOP_SIZE (result);
6042 if (AOP_TYPE (left) == AOP_CRY)
6044 if (AOP_TYPE (right) == AOP_LIT)
6046 // c = bit | literal;
6049 // lit != 0 => result = 1
6050 if (AOP_TYPE (result) == AOP_CRY)
6053 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6055 continueIfTrue (ifx);
6058 emitcode ("setb", "c");
6062 // lit == 0 => result = left
6063 if (size && sameRegs (AOP (result), AOP (left)))
6065 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6070 if (AOP_TYPE (right) == AOP_CRY)
6073 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6074 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6079 symbol *tlbl = newiTempLabel (NULL);
6080 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6081 emitcode ("setb", "c");
6082 emitcode ("jb", "%s,%05d$",
6083 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6085 emitcode ("jnz", "%05d$", tlbl->key + 100);
6086 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6088 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6094 emitcode ("", "%05d$:", tlbl->key + 100);
6103 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6104 genIfxJump (ifx, "c", left, right, result);
6108 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6109 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6110 if ((AOP_TYPE (right) == AOP_LIT) &&
6111 (AOP_TYPE (result) == AOP_CRY) &&
6112 (AOP_TYPE (left) != AOP_CRY))
6118 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6120 continueIfTrue (ifx);
6125 // lit = 0, result = boolean(left)
6127 emitcode ("setb", "c");
6131 symbol *tlbl = newiTempLabel (NULL);
6132 emitcode ("jnz", "%05d$", tlbl->key + 100);
6134 emitcode ("", "%05d$:", tlbl->key + 100);
6138 genIfxJump (ifx, "a", left, right, result);
6146 /* if left is same as result */
6147 if (sameRegs (AOP (result), AOP (left)))
6149 for (; size--; offset++)
6151 if (AOP_TYPE (right) == AOP_LIT)
6153 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6156 /* dummy read of volatile operand */
6157 if (isOperandVolatile (left, FALSE))
6158 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6162 else if (bytelit == 0x0FF)
6164 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6166 else if (IS_AOP_PREG (left))
6168 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6169 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6170 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6174 emitcode ("orl", "%s,%s",
6175 aopGet (AOP (left), offset, FALSE, TRUE),
6176 aopGet (AOP (right), offset, FALSE, FALSE));
6181 if (AOP_TYPE (left) == AOP_ACC)
6182 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6186 if (IS_AOP_PREG (left))
6188 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6189 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6193 emitcode ("orl", "%s,a",
6194 aopGet (AOP (left), offset, FALSE, TRUE));
6202 // left & result in different registers
6203 if (AOP_TYPE (result) == AOP_CRY)
6206 // if(size), result in bit
6207 // if(!size && ifx), conditional oper: if(left | right)
6208 symbol *tlbl = newiTempLabel (NULL);
6209 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6211 emitcode ("setb", "c");
6214 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6215 emitcode ("orl", "a,%s",
6216 aopGet (AOP (right), offset, FALSE, FALSE));
6218 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6219 emitcode ("orl", "a,%s",
6220 aopGet (AOP (left), offset, FALSE, FALSE));
6222 emitcode ("jnz", "%05d$", tlbl->key + 100);
6228 emitcode ("", "%05d$:", tlbl->key + 100);
6232 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6234 emitcode ("", "%05d$:", tlbl->key + 100);
6238 for (; (size--); offset++)
6241 // result = left | right
6242 if (AOP_TYPE (right) == AOP_LIT)
6244 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6247 aopPut (AOP (result),
6248 aopGet (AOP (left), offset, FALSE, FALSE),
6250 isOperandVolatile (result, FALSE));
6253 else if (bytelit == 0x0FF)
6255 /* dummy read of volatile operand */
6256 if (isOperandVolatile (left, FALSE))
6257 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6258 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6262 // faster than result <- left, anl result,right
6263 // and better if result is SFR
6264 if (AOP_TYPE (left) == AOP_ACC)
6265 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6268 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6269 emitcode ("orl", "a,%s",
6270 aopGet (AOP (left), offset, FALSE, FALSE));
6272 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6278 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6279 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6280 freeAsmop (result, NULL, ic, TRUE);
6283 /*-----------------------------------------------------------------*/
6284 /* genXor - code for xclusive or */
6285 /*-----------------------------------------------------------------*/
6287 genXor (iCode * ic, iCode * ifx)
6289 operand *left, *right, *result;
6290 int size, offset = 0;
6291 unsigned long lit = 0L;
6294 D(emitcode ("; genXor",""));
6296 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6297 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6298 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6301 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6303 AOP_TYPE (left), AOP_TYPE (right));
6304 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6306 AOP_SIZE (left), AOP_SIZE (right));
6309 /* if left is a literal & right is not ||
6310 if left needs acc & right does not */
6311 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6312 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6314 operand *tmp = right;
6319 /* if result = right then exchange them */
6320 if (sameRegs (AOP (result), AOP (right)))
6322 operand *tmp = right;
6327 /* if right is bit then exchange them */
6328 if (AOP_TYPE (right) == AOP_CRY &&
6329 AOP_TYPE (left) != AOP_CRY)
6331 operand *tmp = right;
6335 if (AOP_TYPE (right) == AOP_LIT)
6336 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6338 size = AOP_SIZE (result);
6342 if (AOP_TYPE (left) == AOP_CRY)
6344 if (AOP_TYPE (right) == AOP_LIT)
6346 // c = bit & literal;
6349 // lit>>1 != 0 => result = 1
6350 if (AOP_TYPE (result) == AOP_CRY)
6353 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6355 continueIfTrue (ifx);
6358 emitcode ("setb", "c");
6365 // lit == 0, result = left
6366 if (size && sameRegs (AOP (result), AOP (left)))
6368 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6372 // lit == 1, result = not(left)
6373 if (size && sameRegs (AOP (result), AOP (left)))
6375 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6381 emitcode ("cpl", "c");
6390 symbol *tlbl = newiTempLabel (NULL);
6391 if (AOP_TYPE (right) == AOP_CRY)
6394 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6398 int sizer = AOP_SIZE (right);
6400 // if val>>1 != 0, result = 1
6401 emitcode ("setb", "c");
6404 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6406 // test the msb of the lsb
6407 emitcode ("anl", "a,#0xfe");
6408 emitcode ("jnz", "%05d$", tlbl->key + 100);
6412 emitcode ("rrc", "a");
6414 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6415 emitcode ("cpl", "c");
6416 emitcode ("", "%05d$:", (tlbl->key + 100));
6423 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6424 genIfxJump (ifx, "c", left, right, result);
6428 /* if left is same as result */
6429 if (sameRegs (AOP (result), AOP (left)))
6431 for (; size--; offset++)
6433 if (AOP_TYPE (right) == AOP_LIT)
6435 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6438 /* dummy read of volatile operand */
6439 if (isOperandVolatile (left, FALSE))
6440 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6444 else if (IS_AOP_PREG (left))
6446 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6447 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6448 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6452 emitcode ("xrl", "%s,%s",
6453 aopGet (AOP (left), offset, FALSE, TRUE),
6454 aopGet (AOP (right), offset, FALSE, FALSE));
6459 if (AOP_TYPE (left) == AOP_ACC)
6460 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6463 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6464 if (IS_AOP_PREG (left))
6466 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6467 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6470 emitcode ("xrl", "%s,a",
6471 aopGet (AOP (left), offset, FALSE, TRUE));
6478 // left & result in different registers
6479 if (AOP_TYPE (result) == AOP_CRY)
6482 // if(size), result in bit
6483 // if(!size && ifx), conditional oper: if(left ^ right)
6484 symbol *tlbl = newiTempLabel (NULL);
6485 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6487 emitcode ("setb", "c");
6490 if ((AOP_TYPE (right) == AOP_LIT) &&
6491 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6493 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6497 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6498 emitcode ("xrl", "a,%s",
6499 aopGet (AOP (right), offset, FALSE, FALSE));
6501 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6502 emitcode ("xrl", "a,%s",
6503 aopGet (AOP (left), offset, FALSE, FALSE));
6506 emitcode ("jnz", "%05d$", tlbl->key + 100);
6512 emitcode ("", "%05d$:", tlbl->key + 100);
6516 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6520 for (; (size--); offset++)
6523 // result = left & right
6524 if (AOP_TYPE (right) == AOP_LIT)
6526 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6529 aopPut (AOP (result),
6530 aopGet (AOP (left), offset, FALSE, FALSE),
6532 isOperandVolatile (result, FALSE));
6536 // faster than result <- left, anl result,right
6537 // and better if result is SFR
6538 if (AOP_TYPE (left) == AOP_ACC)
6539 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6542 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6543 emitcode ("xrl", "a,%s",
6544 aopGet (AOP (left), offset, FALSE, TRUE));
6546 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6552 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6553 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6554 freeAsmop (result, NULL, ic, TRUE);
6557 /*-----------------------------------------------------------------*/
6558 /* genInline - write the inline code out */
6559 /*-----------------------------------------------------------------*/
6561 genInline (iCode * ic)
6563 char *buffer, *bp, *bp1;
6565 D(emitcode ("; genInline",""));
6567 _G.inLine += (!options.asmpeep);
6569 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6570 strcpy (buffer, IC_INLINE (ic));
6572 /* emit each line as a code */
6583 /* Add \n for labels, not dirs such as c:\mydir */
6584 if ( (*bp == ':') && (isspace(bp[1])) )
6598 /* emitcode("",buffer); */
6599 _G.inLine -= (!options.asmpeep);
6602 /*-----------------------------------------------------------------*/
6603 /* genRRC - rotate right with carry */
6604 /*-----------------------------------------------------------------*/
6608 operand *left, *result;
6609 int size, offset = 0;
6612 D(emitcode ("; genRRC",""));
6614 /* rotate right with carry */
6615 left = IC_LEFT (ic);
6616 result = IC_RESULT (ic);
6617 aopOp (left, ic, FALSE);
6618 aopOp (result, ic, FALSE);
6620 /* move it to the result */
6621 size = AOP_SIZE (result);
6623 if (size == 1) { /* special case for 1 byte */
6624 l = aopGet (AOP (left), offset, FALSE, FALSE);
6626 emitcode ("rr", "a");
6629 /* no need to clear carry, bit7 will be written later */
6632 l = aopGet (AOP (left), offset, FALSE, FALSE);
6634 emitcode ("rrc", "a");
6635 if (AOP_SIZE (result) > 1)
6636 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6638 /* now we need to put the carry into the
6639 highest order byte of the result */
6640 if (AOP_SIZE (result) > 1)
6642 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6645 emitcode ("mov", "acc.7,c");
6647 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6648 freeAsmop (left, NULL, ic, TRUE);
6649 freeAsmop (result, NULL, ic, TRUE);
6652 /*-----------------------------------------------------------------*/
6653 /* genRLC - generate code for rotate left with carry */
6654 /*-----------------------------------------------------------------*/
6658 operand *left, *result;
6659 int size, offset = 0;
6662 D(emitcode ("; genRLC",""));
6664 /* rotate right with carry */
6665 left = IC_LEFT (ic);
6666 result = IC_RESULT (ic);
6667 aopOp (left, ic, FALSE);
6668 aopOp (result, ic, FALSE);
6670 /* move it to the result */
6671 size = AOP_SIZE (result);
6675 l = aopGet (AOP (left), offset, FALSE, FALSE);
6677 if (size == 0) { /* special case for 1 byte */
6681 emitcode("rlc","a"); /* bit0 will be written later */
6682 if (AOP_SIZE (result) > 1)
6683 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6686 l = aopGet (AOP (left), offset, FALSE, FALSE);
6688 emitcode ("rlc", "a");
6689 if (AOP_SIZE (result) > 1)
6690 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6693 /* now we need to put the carry into the
6694 highest order byte of the result */
6695 if (AOP_SIZE (result) > 1)
6697 l = aopGet (AOP (result), 0, FALSE, FALSE);
6700 emitcode ("mov", "acc.0,c");
6702 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6703 freeAsmop (left, NULL, ic, TRUE);
6704 freeAsmop (result, NULL, ic, TRUE);
6707 /*-----------------------------------------------------------------*/
6708 /* genGetHbit - generates code get highest order bit */
6709 /*-----------------------------------------------------------------*/
6711 genGetHbit (iCode * ic)
6713 operand *left, *result;
6715 D(emitcode ("; genGetHbit",""));
6717 left = IC_LEFT (ic);
6718 result = IC_RESULT (ic);
6719 aopOp (left, ic, FALSE);
6720 aopOp (result, ic, FALSE);
6722 /* get the highest order byte into a */
6723 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6724 if (AOP_TYPE (result) == AOP_CRY)
6726 emitcode ("rlc", "a");
6731 emitcode ("rl", "a");
6732 emitcode ("anl", "a,#0x01");
6737 freeAsmop (left, NULL, ic, TRUE);
6738 freeAsmop (result, NULL, ic, TRUE);
6741 /*-----------------------------------------------------------------*/
6742 /* genSwap - generates code to swap nibbles or bytes */
6743 /*-----------------------------------------------------------------*/
6745 genSwap (iCode * ic)
6747 operand *left, *result;
6749 D(emitcode ("; genSwap",""));
6751 left = IC_LEFT (ic);
6752 result = IC_RESULT (ic);
6753 aopOp (left, ic, FALSE);
6754 aopOp (result, ic, FALSE);
6756 switch (AOP_SIZE (left))
6758 case 1: /* swap nibbles in byte */
6759 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6760 emitcode ("swap", "a");
6761 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6763 case 2: /* swap bytes in word */
6764 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6766 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6767 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6768 0, isOperandVolatile (result, FALSE));
6769 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6771 else if (operandsEqu (left, result))
6774 bool pushedB = FALSE, leftInB = FALSE;
6776 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6777 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6780 emitcode ("mov", "b,a");
6784 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6785 0, isOperandVolatile (result, FALSE));
6786 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6793 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6794 0, isOperandVolatile (result, FALSE));
6795 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6796 1, isOperandVolatile (result, FALSE));
6800 wassertl(FALSE, "unsupported SWAP operand size");
6803 freeAsmop (left, NULL, ic, TRUE);
6804 freeAsmop (result, NULL, ic, TRUE);
6808 /*-----------------------------------------------------------------*/
6809 /* AccRol - rotate left accumulator by known count */
6810 /*-----------------------------------------------------------------*/
6812 AccRol (int shCount)
6814 shCount &= 0x0007; // shCount : 0..7
6821 emitcode ("rl", "a");
6824 emitcode ("rl", "a");
6825 emitcode ("rl", "a");
6828 emitcode ("swap", "a");
6829 emitcode ("rr", "a");
6832 emitcode ("swap", "a");
6835 emitcode ("swap", "a");
6836 emitcode ("rl", "a");
6839 emitcode ("rr", "a");
6840 emitcode ("rr", "a");
6843 emitcode ("rr", "a");
6848 /*-----------------------------------------------------------------*/
6849 /* AccLsh - left shift accumulator by known count */
6850 /*-----------------------------------------------------------------*/
6852 AccLsh (int shCount)
6857 emitcode ("add", "a,acc");
6858 else if (shCount == 2)
6860 emitcode ("add", "a,acc");
6861 emitcode ("add", "a,acc");
6865 /* rotate left accumulator */
6867 /* and kill the lower order bits */
6868 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6873 /*-----------------------------------------------------------------*/
6874 /* AccRsh - right shift accumulator by known count */
6875 /*-----------------------------------------------------------------*/
6877 AccRsh (int shCount)
6884 emitcode ("rrc", "a");
6888 /* rotate right accumulator */
6889 AccRol (8 - shCount);
6890 /* and kill the higher order bits */
6891 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6896 /*-----------------------------------------------------------------*/
6897 /* AccSRsh - signed right shift accumulator by known count */
6898 /*-----------------------------------------------------------------*/
6900 AccSRsh (int shCount)
6907 emitcode ("mov", "c,acc.7");
6908 emitcode ("rrc", "a");
6910 else if (shCount == 2)
6912 emitcode ("mov", "c,acc.7");
6913 emitcode ("rrc", "a");
6914 emitcode ("mov", "c,acc.7");
6915 emitcode ("rrc", "a");
6919 tlbl = newiTempLabel (NULL);
6920 /* rotate right accumulator */
6921 AccRol (8 - shCount);
6922 /* and kill the higher order bits */
6923 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6924 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6925 emitcode ("orl", "a,#0x%02x",
6926 (unsigned char) ~SRMask[shCount]);
6927 emitcode ("", "%05d$:", tlbl->key + 100);
6932 /*-----------------------------------------------------------------*/
6933 /* shiftR1Left2Result - shift right one byte from left to result */
6934 /*-----------------------------------------------------------------*/
6936 shiftR1Left2Result (operand * left, int offl,
6937 operand * result, int offr,
6938 int shCount, int sign)
6940 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6941 /* shift right accumulator */
6946 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6949 /*-----------------------------------------------------------------*/
6950 /* shiftL1Left2Result - shift left one byte from left to result */
6951 /*-----------------------------------------------------------------*/
6953 shiftL1Left2Result (operand * left, int offl,
6954 operand * result, int offr, int shCount)
6957 l = aopGet (AOP (left), offl, FALSE, FALSE);
6959 /* shift left accumulator */
6961 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6964 /*-----------------------------------------------------------------*/
6965 /* movLeft2Result - move byte from left to result */
6966 /*-----------------------------------------------------------------*/
6968 movLeft2Result (operand * left, int offl,
6969 operand * result, int offr, int sign)
6972 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6974 l = aopGet (AOP (left), offl, FALSE, FALSE);
6976 if (*l == '@' && (IS_AOP_PREG (result)))
6978 emitcode ("mov", "a,%s", l);
6979 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6984 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6987 /* MSB sign in acc.7 ! */
6988 if (getDataSize (left) == offl + 1)
6990 emitcode ("mov", "a,%s", l);
6991 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6998 /*-----------------------------------------------------------------*/
6999 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7000 /*-----------------------------------------------------------------*/
7004 emitcode ("rrc", "a");
7005 emitcode ("xch", "a,%s", x);
7006 emitcode ("rrc", "a");
7007 emitcode ("xch", "a,%s", x);
7010 /*-----------------------------------------------------------------*/
7011 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7012 /*-----------------------------------------------------------------*/
7016 emitcode ("xch", "a,%s", x);
7017 emitcode ("rlc", "a");
7018 emitcode ("xch", "a,%s", x);
7019 emitcode ("rlc", "a");
7022 /*-----------------------------------------------------------------*/
7023 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7024 /*-----------------------------------------------------------------*/
7028 emitcode ("xch", "a,%s", x);
7029 emitcode ("add", "a,acc");
7030 emitcode ("xch", "a,%s", x);
7031 emitcode ("rlc", "a");
7034 /*-----------------------------------------------------------------*/
7035 /* AccAXLsh - left shift a:x by known count (0..7) */
7036 /*-----------------------------------------------------------------*/
7038 AccAXLsh (char *x, int shCount)
7053 case 5: // AAAAABBB:CCCCCDDD
7055 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7057 emitcode ("anl", "a,#0x%02x",
7058 SLMask[shCount]); // BBB00000:CCCCCDDD
7060 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7062 AccRol (shCount); // DDDCCCCC:BBB00000
7064 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7066 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7068 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7070 emitcode ("anl", "a,#0x%02x",
7071 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7073 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7075 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7078 case 6: // AAAAAABB:CCCCCCDD
7079 emitcode ("anl", "a,#0x%02x",
7080 SRMask[shCount]); // 000000BB:CCCCCCDD
7081 emitcode ("mov", "c,acc.0"); // c = B
7082 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7084 AccAXRrl1 (x); // BCCCCCCD:D000000B
7085 AccAXRrl1 (x); // BBCCCCCC:DD000000
7087 emitcode("rrc","a");
7088 emitcode("xch","a,%s", x);
7089 emitcode("rrc","a");
7090 emitcode("mov","c,acc.0"); //<< get correct bit
7091 emitcode("xch","a,%s", x);
7093 emitcode("rrc","a");
7094 emitcode("xch","a,%s", x);
7095 emitcode("rrc","a");
7096 emitcode("xch","a,%s", x);
7099 case 7: // a:x <<= 7
7101 emitcode ("anl", "a,#0x%02x",
7102 SRMask[shCount]); // 0000000B:CCCCCCCD
7104 emitcode ("mov", "c,acc.0"); // c = B
7106 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7108 AccAXRrl1 (x); // BCCCCCCC:D0000000
7116 /*-----------------------------------------------------------------*/
7117 /* AccAXRsh - right shift a:x known count (0..7) */
7118 /*-----------------------------------------------------------------*/
7120 AccAXRsh (char *x, int shCount)
7128 AccAXRrl1 (x); // 0->a:x
7133 AccAXRrl1 (x); // 0->a:x
7136 AccAXRrl1 (x); // 0->a:x
7141 case 5: // AAAAABBB:CCCCCDDD = a:x
7143 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7145 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7147 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7149 emitcode ("anl", "a,#0x%02x",
7150 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7152 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7154 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7156 emitcode ("anl", "a,#0x%02x",
7157 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7159 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7161 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7163 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7166 case 6: // AABBBBBB:CCDDDDDD
7168 emitcode ("mov", "c,acc.7");
7169 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7171 emitcode ("mov", "c,acc.7");
7172 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7174 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7176 emitcode ("anl", "a,#0x%02x",
7177 SRMask[shCount]); // 000000AA:BBBBBBCC
7180 case 7: // ABBBBBBB:CDDDDDDD
7182 emitcode ("mov", "c,acc.7"); // c = A
7184 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7186 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7188 emitcode ("anl", "a,#0x%02x",
7189 SRMask[shCount]); // 0000000A:BBBBBBBC
7197 /*-----------------------------------------------------------------*/
7198 /* AccAXRshS - right shift signed a:x known count (0..7) */
7199 /*-----------------------------------------------------------------*/
7201 AccAXRshS (char *x, int shCount)
7209 emitcode ("mov", "c,acc.7");
7210 AccAXRrl1 (x); // s->a:x
7214 emitcode ("mov", "c,acc.7");
7215 AccAXRrl1 (x); // s->a:x
7217 emitcode ("mov", "c,acc.7");
7218 AccAXRrl1 (x); // s->a:x
7223 case 5: // AAAAABBB:CCCCCDDD = a:x
7225 tlbl = newiTempLabel (NULL);
7226 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7228 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7230 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7232 emitcode ("anl", "a,#0x%02x",
7233 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7235 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7237 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7239 emitcode ("anl", "a,#0x%02x",
7240 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7242 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7244 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7246 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7248 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7249 emitcode ("orl", "a,#0x%02x",
7250 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7252 emitcode ("", "%05d$:", tlbl->key + 100);
7253 break; // SSSSAAAA:BBBCCCCC
7255 case 6: // AABBBBBB:CCDDDDDD
7257 tlbl = newiTempLabel (NULL);
7258 emitcode ("mov", "c,acc.7");
7259 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7261 emitcode ("mov", "c,acc.7");
7262 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7264 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7266 emitcode ("anl", "a,#0x%02x",
7267 SRMask[shCount]); // 000000AA:BBBBBBCC
7269 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7270 emitcode ("orl", "a,#0x%02x",
7271 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7273 emitcode ("", "%05d$:", tlbl->key + 100);
7275 case 7: // ABBBBBBB:CDDDDDDD
7277 tlbl = newiTempLabel (NULL);
7278 emitcode ("mov", "c,acc.7"); // c = A
7280 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7282 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7284 emitcode ("anl", "a,#0x%02x",
7285 SRMask[shCount]); // 0000000A:BBBBBBBC
7287 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7288 emitcode ("orl", "a,#0x%02x",
7289 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7291 emitcode ("", "%05d$:", tlbl->key + 100);
7298 /*-----------------------------------------------------------------*/
7299 /* shiftL2Left2Result - shift left two bytes from left to result */
7300 /*-----------------------------------------------------------------*/
7302 shiftL2Left2Result (operand * left, int offl,
7303 operand * result, int offr, int shCount)
7305 if (sameRegs (AOP (result), AOP (left)) &&
7306 ((offl + MSB16) == offr))
7308 /* don't crash result[offr] */
7309 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7310 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7314 movLeft2Result (left, offl, result, offr, 0);
7315 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7317 /* ax << shCount (x = lsb(result)) */
7318 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7319 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7323 /*-----------------------------------------------------------------*/
7324 /* shiftR2Left2Result - shift right two bytes from left to result */
7325 /*-----------------------------------------------------------------*/
7327 shiftR2Left2Result (operand * left, int offl,
7328 operand * result, int offr,
7329 int shCount, int sign)
7331 if (sameRegs (AOP (result), AOP (left)) &&
7332 ((offl + MSB16) == offr))
7334 /* don't crash result[offr] */
7335 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7336 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7340 movLeft2Result (left, offl, result, offr, 0);
7341 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7343 /* a:x >> shCount (x = lsb(result)) */
7345 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7347 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7348 if (getDataSize (result) > 1)
7349 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7352 /*-----------------------------------------------------------------*/
7353 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7354 /*-----------------------------------------------------------------*/
7356 shiftLLeftOrResult (operand * left, int offl,
7357 operand * result, int offr, int shCount)
7359 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7360 /* shift left accumulator */
7362 /* or with result */
7363 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7364 /* back to result */
7365 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7368 /*-----------------------------------------------------------------*/
7369 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7370 /*-----------------------------------------------------------------*/
7372 shiftRLeftOrResult (operand * left, int offl,
7373 operand * result, int offr, int shCount)
7375 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7376 /* shift right accumulator */
7378 /* or with result */
7379 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7380 /* back to result */
7381 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7384 /*-----------------------------------------------------------------*/
7385 /* genlshOne - left shift a one byte quantity by known count */
7386 /*-----------------------------------------------------------------*/
7388 genlshOne (operand * result, operand * left, int shCount)
7390 D(emitcode ("; genlshOne",""));
7392 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7395 /*-----------------------------------------------------------------*/
7396 /* genlshTwo - left shift two bytes by known amount != 0 */
7397 /*-----------------------------------------------------------------*/
7399 genlshTwo (operand * result, operand * left, int shCount)
7403 D(emitcode ("; genlshTwo",""));
7405 size = getDataSize (result);
7407 /* if shCount >= 8 */
7415 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7417 movLeft2Result (left, LSB, result, MSB16, 0);
7419 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7422 /* 1 <= shCount <= 7 */
7426 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7428 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7432 /*-----------------------------------------------------------------*/
7433 /* shiftLLong - shift left one long from left to result */
7434 /* offl = LSB or MSB16 */
7435 /*-----------------------------------------------------------------*/
7437 shiftLLong (operand * left, operand * result, int offr)
7440 int size = AOP_SIZE (result);
7442 if (size >= LSB + offr)
7444 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7446 emitcode ("add", "a,acc");
7447 if (sameRegs (AOP (left), AOP (result)) &&
7448 size >= MSB16 + offr && offr != LSB)
7449 emitcode ("xch", "a,%s",
7450 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7452 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7455 if (size >= MSB16 + offr)
7457 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7459 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7462 emitcode ("rlc", "a");
7463 if (sameRegs (AOP (left), AOP (result)) &&
7464 size >= MSB24 + offr && offr != LSB)
7465 emitcode ("xch", "a,%s",
7466 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7468 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7471 if (size >= MSB24 + offr)
7473 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7475 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7478 emitcode ("rlc", "a");
7479 if (sameRegs (AOP (left), AOP (result)) &&
7480 size >= MSB32 + offr && offr != LSB)
7481 emitcode ("xch", "a,%s",
7482 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7484 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7487 if (size > MSB32 + offr)
7489 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7491 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7494 emitcode ("rlc", "a");
7495 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7498 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7501 /*-----------------------------------------------------------------*/
7502 /* genlshFour - shift four byte by a known amount != 0 */
7503 /*-----------------------------------------------------------------*/
7505 genlshFour (operand * result, operand * left, int shCount)
7509 D(emitcode ("; genlshFour",""));
7511 size = AOP_SIZE (result);
7513 /* if shifting more that 3 bytes */
7518 /* lowest order of left goes to the highest
7519 order of the destination */
7520 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7522 movLeft2Result (left, LSB, result, MSB32, 0);
7523 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7524 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7525 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7529 /* more than two bytes */
7530 else if (shCount >= 16)
7532 /* lower order two bytes goes to higher order two bytes */
7534 /* if some more remaining */
7536 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7539 movLeft2Result (left, MSB16, result, MSB32, 0);
7540 movLeft2Result (left, LSB, result, MSB24, 0);
7542 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7543 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7547 /* if more than 1 byte */
7548 else if (shCount >= 8)
7550 /* lower order three bytes goes to higher order three bytes */
7555 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7557 movLeft2Result (left, LSB, result, MSB16, 0);
7563 movLeft2Result (left, MSB24, result, MSB32, 0);
7564 movLeft2Result (left, MSB16, result, MSB24, 0);
7565 movLeft2Result (left, LSB, result, MSB16, 0);
7566 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7568 else if (shCount == 1)
7569 shiftLLong (left, result, MSB16);
7572 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7573 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7574 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7575 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7580 /* 1 <= shCount <= 7 */
7581 else if (shCount <= 2)
7583 shiftLLong (left, result, LSB);
7585 shiftLLong (result, result, LSB);
7587 /* 3 <= shCount <= 7, optimize */
7590 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7591 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7592 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7596 /*-----------------------------------------------------------------*/
7597 /* genLeftShiftLiteral - left shifting by known count */
7598 /*-----------------------------------------------------------------*/
7600 genLeftShiftLiteral (operand * left,
7605 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7608 D(emitcode ("; genLeftShiftLiteral",""));
7610 freeAsmop (right, NULL, ic, TRUE);
7612 aopOp (left, ic, FALSE);
7613 aopOp (result, ic, FALSE);
7615 size = getSize (operandType (result));
7618 emitcode ("; shift left ", "result %d, left %d", size,
7622 /* I suppose that the left size >= result size */
7627 movLeft2Result (left, size, result, size, 0);
7631 else if (shCount >= (size * 8))
7633 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7639 genlshOne (result, left, shCount);
7643 genlshTwo (result, left, shCount);
7647 genlshFour (result, left, shCount);
7650 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7651 "*** ack! mystery literal shift!\n");
7655 freeAsmop (left, NULL, ic, TRUE);
7656 freeAsmop (result, NULL, ic, TRUE);
7659 /*-----------------------------------------------------------------*/
7660 /* genLeftShift - generates code for left shifting */
7661 /*-----------------------------------------------------------------*/
7663 genLeftShift (iCode * ic)
7665 operand *left, *right, *result;
7668 symbol *tlbl, *tlbl1;
7671 D(emitcode ("; genLeftShift",""));
7673 right = IC_RIGHT (ic);
7674 left = IC_LEFT (ic);
7675 result = IC_RESULT (ic);
7677 aopOp (right, ic, FALSE);
7679 /* if the shift count is known then do it
7680 as efficiently as possible */
7681 if (AOP_TYPE (right) == AOP_LIT)
7683 genLeftShiftLiteral (left, right, result, ic);
7687 /* shift count is unknown then we have to form
7688 a loop get the loop count in B : Note: we take
7689 only the lower order byte since shifting
7690 more that 32 bits make no sense anyway, ( the
7691 largest size of an object can be only 32 bits ) */
7694 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7695 emitcode ("inc", "b");
7696 freeAsmop (right, NULL, ic, TRUE);
7697 aopOp (left, ic, FALSE);
7698 aopOp (result, ic, FALSE);
7700 /* now move the left to the result if they are not the same */
7701 if (!sameRegs (AOP (left), AOP (result)) &&
7702 AOP_SIZE (result) > 1)
7705 size = AOP_SIZE (result);
7709 l = aopGet (AOP (left), offset, FALSE, TRUE);
7710 if (*l == '@' && (IS_AOP_PREG (result)))
7713 emitcode ("mov", "a,%s", l);
7714 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7717 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7722 tlbl = newiTempLabel (NULL);
7723 size = AOP_SIZE (result);
7725 tlbl1 = newiTempLabel (NULL);
7727 /* if it is only one byte then */
7730 symbol *tlbl1 = newiTempLabel (NULL);
7732 l = aopGet (AOP (left), 0, FALSE, FALSE);
7734 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7735 emitcode ("", "%05d$:", tlbl->key + 100);
7736 emitcode ("add", "a,acc");
7737 emitcode ("", "%05d$:", tlbl1->key + 100);
7738 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7740 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7744 reAdjustPreg (AOP (result));
7746 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7747 emitcode ("", "%05d$:", tlbl->key + 100);
7748 l = aopGet (AOP (result), offset, FALSE, FALSE);
7750 emitcode ("add", "a,acc");
7751 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7754 l = aopGet (AOP (result), offset, FALSE, FALSE);
7756 emitcode ("rlc", "a");
7757 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7759 reAdjustPreg (AOP (result));
7761 emitcode ("", "%05d$:", tlbl1->key + 100);
7762 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7765 freeAsmop (left, NULL, ic, TRUE);
7766 freeAsmop (result, NULL, ic, TRUE);
7769 /*-----------------------------------------------------------------*/
7770 /* genrshOne - right shift a one byte quantity by known count */
7771 /*-----------------------------------------------------------------*/
7773 genrshOne (operand * result, operand * left,
7774 int shCount, int sign)
7776 D(emitcode ("; genrshOne",""));
7778 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7781 /*-----------------------------------------------------------------*/
7782 /* genrshTwo - right shift two bytes by known amount != 0 */
7783 /*-----------------------------------------------------------------*/
7785 genrshTwo (operand * result, operand * left,
7786 int shCount, int sign)
7788 D(emitcode ("; genrshTwo",""));
7790 /* if shCount >= 8 */
7795 shiftR1Left2Result (left, MSB16, result, LSB,
7798 movLeft2Result (left, MSB16, result, LSB, sign);
7799 addSign (result, MSB16, sign);
7802 /* 1 <= shCount <= 7 */
7804 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7807 /*-----------------------------------------------------------------*/
7808 /* shiftRLong - shift right one long from left to result */
7809 /* offl = LSB or MSB16 */
7810 /*-----------------------------------------------------------------*/
7812 shiftRLong (operand * left, int offl,
7813 operand * result, int sign)
7815 int isSameRegs=sameRegs(AOP(left),AOP(result));
7817 if (isSameRegs && offl>1) {
7818 // we are in big trouble, but this shouldn't happen
7819 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7822 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7827 emitcode ("rlc", "a");
7828 emitcode ("subb", "a,acc");
7830 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7832 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7833 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7836 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7841 emitcode ("clr", "c");
7843 emitcode ("mov", "c,acc.7");
7846 emitcode ("rrc", "a");
7848 if (isSameRegs && offl==MSB16) {
7849 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7851 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7852 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7855 emitcode ("rrc", "a");
7856 if (isSameRegs && offl==1) {
7857 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7859 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7860 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7862 emitcode ("rrc", "a");
7863 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7867 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7868 emitcode ("rrc", "a");
7869 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7873 /*-----------------------------------------------------------------*/
7874 /* genrshFour - shift four byte by a known amount != 0 */
7875 /*-----------------------------------------------------------------*/
7877 genrshFour (operand * result, operand * left,
7878 int shCount, int sign)
7880 D(emitcode ("; genrshFour",""));
7882 /* if shifting more that 3 bytes */
7887 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7889 movLeft2Result (left, MSB32, result, LSB, sign);
7890 addSign (result, MSB16, sign);
7892 else if (shCount >= 16)
7896 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7899 movLeft2Result (left, MSB24, result, LSB, 0);
7900 movLeft2Result (left, MSB32, result, MSB16, sign);
7902 addSign (result, MSB24, sign);
7904 else if (shCount >= 8)
7908 shiftRLong (left, MSB16, result, sign);
7909 else if (shCount == 0)
7911 movLeft2Result (left, MSB16, result, LSB, 0);
7912 movLeft2Result (left, MSB24, result, MSB16, 0);
7913 movLeft2Result (left, MSB32, result, MSB24, sign);
7914 addSign (result, MSB32, sign);
7918 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7919 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7920 /* the last shift is signed */
7921 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7922 addSign (result, MSB32, sign);
7926 { /* 1 <= shCount <= 7 */
7929 shiftRLong (left, LSB, result, sign);
7931 shiftRLong (result, LSB, result, sign);
7935 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7936 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7937 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7942 /*-----------------------------------------------------------------*/
7943 /* genRightShiftLiteral - right shifting by known count */
7944 /*-----------------------------------------------------------------*/
7946 genRightShiftLiteral (operand * left,
7952 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7955 D(emitcode ("; genRightShiftLiteral",""));
7957 freeAsmop (right, NULL, ic, TRUE);
7959 aopOp (left, ic, FALSE);
7960 aopOp (result, ic, FALSE);
7963 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7967 size = getDataSize (left);
7968 /* test the LEFT size !!! */
7970 /* I suppose that the left size >= result size */
7973 size = getDataSize (result);
7975 movLeft2Result (left, size, result, size, 0);
7978 else if (shCount >= (size * 8))
7981 /* get sign in acc.7 */
7982 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7984 addSign (result, LSB, sign);
7991 genrshOne (result, left, shCount, sign);
7995 genrshTwo (result, left, shCount, sign);
7999 genrshFour (result, left, shCount, sign);
8005 freeAsmop (left, NULL, ic, TRUE);
8006 freeAsmop (result, NULL, ic, TRUE);
8009 /*-----------------------------------------------------------------*/
8010 /* genSignedRightShift - right shift of signed number */
8011 /*-----------------------------------------------------------------*/
8013 genSignedRightShift (iCode * ic)
8015 operand *right, *left, *result;
8018 symbol *tlbl, *tlbl1;
8021 D(emitcode ("; genSignedRightShift",""));
8023 /* we do it the hard way put the shift count in b
8024 and loop thru preserving the sign */
8026 right = IC_RIGHT (ic);
8027 left = IC_LEFT (ic);
8028 result = IC_RESULT (ic);
8030 aopOp (right, ic, FALSE);
8033 if (AOP_TYPE (right) == AOP_LIT)
8035 genRightShiftLiteral (left, right, result, ic, 1);
8038 /* shift count is unknown then we have to form
8039 a loop get the loop count in B : Note: we take
8040 only the lower order byte since shifting
8041 more that 32 bits make no sense anyway, ( the
8042 largest size of an object can be only 32 bits ) */
8045 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8046 emitcode ("inc", "b");
8047 freeAsmop (right, NULL, ic, TRUE);
8048 aopOp (left, ic, FALSE);
8049 aopOp (result, ic, FALSE);
8051 /* now move the left to the result if they are not the
8053 if (!sameRegs (AOP (left), AOP (result)) &&
8054 AOP_SIZE (result) > 1)
8057 size = AOP_SIZE (result);
8061 l = aopGet (AOP (left), offset, FALSE, TRUE);
8062 if (*l == '@' && IS_AOP_PREG (result))
8065 emitcode ("mov", "a,%s", l);
8066 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8069 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8074 /* mov the highest order bit to OVR */
8075 tlbl = newiTempLabel (NULL);
8076 tlbl1 = newiTempLabel (NULL);
8078 size = AOP_SIZE (result);
8080 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8081 emitcode ("rlc", "a");
8082 emitcode ("mov", "ov,c");
8083 /* if it is only one byte then */
8086 l = aopGet (AOP (left), 0, FALSE, FALSE);
8088 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8089 emitcode ("", "%05d$:", tlbl->key + 100);
8090 emitcode ("mov", "c,ov");
8091 emitcode ("rrc", "a");
8092 emitcode ("", "%05d$:", tlbl1->key + 100);
8093 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8095 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8099 reAdjustPreg (AOP (result));
8100 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8101 emitcode ("", "%05d$:", tlbl->key + 100);
8102 emitcode ("mov", "c,ov");
8105 l = aopGet (AOP (result), offset, FALSE, FALSE);
8107 emitcode ("rrc", "a");
8108 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8110 reAdjustPreg (AOP (result));
8111 emitcode ("", "%05d$:", tlbl1->key + 100);
8112 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8116 freeAsmop (left, NULL, ic, TRUE);
8117 freeAsmop (result, NULL, ic, TRUE);
8120 /*-----------------------------------------------------------------*/
8121 /* genRightShift - generate code for right shifting */
8122 /*-----------------------------------------------------------------*/
8124 genRightShift (iCode * ic)
8126 operand *right, *left, *result;
8130 symbol *tlbl, *tlbl1;
8133 D(emitcode ("; genRightShift",""));
8135 /* if signed then we do it the hard way preserve the
8136 sign bit moving it inwards */
8137 letype = getSpec (operandType (IC_LEFT (ic)));
8139 if (!SPEC_USIGN (letype))
8141 genSignedRightShift (ic);
8145 /* signed & unsigned types are treated the same : i.e. the
8146 signed is NOT propagated inwards : quoting from the
8147 ANSI - standard : "for E1 >> E2, is equivalent to division
8148 by 2**E2 if unsigned or if it has a non-negative value,
8149 otherwise the result is implementation defined ", MY definition
8150 is that the sign does not get propagated */
8152 right = IC_RIGHT (ic);
8153 left = IC_LEFT (ic);
8154 result = IC_RESULT (ic);
8156 aopOp (right, ic, FALSE);
8158 /* if the shift count is known then do it
8159 as efficiently as possible */
8160 if (AOP_TYPE (right) == AOP_LIT)
8162 genRightShiftLiteral (left, right, result, ic, 0);
8166 /* shift count is unknown then we have to form
8167 a loop get the loop count in B : Note: we take
8168 only the lower order byte since shifting
8169 more that 32 bits make no sense anyway, ( the
8170 largest size of an object can be only 32 bits ) */
8173 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8174 emitcode ("inc", "b");
8175 freeAsmop (right, NULL, ic, TRUE);
8176 aopOp (left, ic, FALSE);
8177 aopOp (result, ic, FALSE);
8179 /* now move the left to the result if they are not the
8181 if (!sameRegs (AOP (left), AOP (result)) &&
8182 AOP_SIZE (result) > 1)
8185 size = AOP_SIZE (result);
8189 l = aopGet (AOP (left), offset, FALSE, TRUE);
8190 if (*l == '@' && IS_AOP_PREG (result))
8193 emitcode ("mov", "a,%s", l);
8194 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8197 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8202 tlbl = newiTempLabel (NULL);
8203 tlbl1 = newiTempLabel (NULL);
8204 size = AOP_SIZE (result);
8207 /* if it is only one byte then */
8210 l = aopGet (AOP (left), 0, FALSE, FALSE);
8212 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8213 emitcode ("", "%05d$:", tlbl->key + 100);
8215 emitcode ("rrc", "a");
8216 emitcode ("", "%05d$:", tlbl1->key + 100);
8217 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8219 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8223 reAdjustPreg (AOP (result));
8224 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8225 emitcode ("", "%05d$:", tlbl->key + 100);
8229 l = aopGet (AOP (result), offset, FALSE, FALSE);
8231 emitcode ("rrc", "a");
8232 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8234 reAdjustPreg (AOP (result));
8236 emitcode ("", "%05d$:", tlbl1->key + 100);
8237 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8241 freeAsmop (left, NULL, ic, TRUE);
8242 freeAsmop (result, NULL, ic, TRUE);
8245 /*-----------------------------------------------------------------*/
8246 /* emitPtrByteGet - emits code to get a byte into A through a */
8247 /* pointer register (R0, R1, or DPTR). The */
8248 /* original value of A can be preserved in B. */
8249 /*-----------------------------------------------------------------*/
8251 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8258 emitcode ("mov", "b,a");
8259 emitcode ("mov", "a,@%s", rname);
8264 emitcode ("mov", "b,a");
8265 emitcode ("movx", "a,@%s", rname);
8270 emitcode ("mov", "b,a");
8271 emitcode ("movx", "a,@dptr");
8276 emitcode ("mov", "b,a");
8277 emitcode ("clr", "a");
8278 emitcode ("movc", "a,@a+dptr");
8284 emitcode ("push", "b");
8285 emitcode ("push", "acc");
8287 emitcode ("lcall", "__gptrget");
8289 emitcode ("pop", "b");
8294 /*-----------------------------------------------------------------*/
8295 /* emitPtrByteSet - emits code to set a byte from src through a */
8296 /* pointer register (R0, R1, or DPTR). */
8297 /*-----------------------------------------------------------------*/
8299 emitPtrByteSet (char *rname, int p_type, char *src)
8308 emitcode ("mov", "@%s,a", rname);
8311 emitcode ("mov", "@%s,%s", rname, src);
8316 emitcode ("movx", "@%s,a", rname);
8321 emitcode ("movx", "@dptr,a");
8326 emitcode ("lcall", "__gptrput");
8331 /*-----------------------------------------------------------------*/
8332 /* genUnpackBits - generates code for unpacking bits */
8333 /*-----------------------------------------------------------------*/
8335 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8337 int offset = 0; /* result byte offset */
8338 int rsize; /* result size */
8339 int rlen = 0; /* remaining bitfield length */
8340 sym_link *etype; /* bitfield type information */
8341 int blen; /* bitfield length */
8342 int bstr; /* bitfield starting bit within byte */
8345 D(emitcode ("; genUnpackBits",""));
8347 etype = getSpec (operandType (result));
8348 rsize = getSize (operandType (result));
8349 blen = SPEC_BLEN (etype);
8350 bstr = SPEC_BSTR (etype);
8352 if (ifx && blen <= 8)
8354 emitPtrByteGet (rname, ptype, FALSE);
8357 SNPRINTF (buffer, sizeof(buffer),
8359 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8364 emitcode ("anl", "a,#0x%02x",
8365 (((unsigned char) -1) >> (8 - blen)) << bstr);
8366 genIfxJump (ifx, "a", NULL, NULL, NULL);
8372 /* If the bitfield length is less than a byte */
8375 emitPtrByteGet (rname, ptype, FALSE);
8377 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8378 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8382 /* Bit field did not fit in a byte. Copy all
8383 but the partial byte at the end. */
8384 for (rlen=blen;rlen>=8;rlen-=8)
8386 emitPtrByteGet (rname, ptype, FALSE);
8387 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8389 emitcode ("inc", "%s", rname);
8392 /* Handle the partial byte at the end */
8395 emitPtrByteGet (rname, ptype, FALSE);
8396 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8397 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8405 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8410 /*-----------------------------------------------------------------*/
8411 /* genDataPointerGet - generates code when ptr offset is known */
8412 /*-----------------------------------------------------------------*/
8414 genDataPointerGet (operand * left,
8420 int size, offset = 0;
8422 D(emitcode ("; genDataPointerGet",""));
8424 aopOp (result, ic, TRUE);
8426 /* get the string representation of the name */
8427 l = aopGet (AOP (left), 0, FALSE, TRUE);
8428 size = AOP_SIZE (result);
8432 sprintf (buffer, "(%s + %d)", l + 1, offset);
8434 sprintf (buffer, "%s", l + 1);
8435 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8438 freeAsmop (left, NULL, ic, TRUE);
8439 freeAsmop (result, NULL, ic, TRUE);
8442 /*-----------------------------------------------------------------*/
8443 /* genNearPointerGet - emitcode for near pointer fetch */
8444 /*-----------------------------------------------------------------*/
8446 genNearPointerGet (operand * left,
8455 sym_link *rtype, *retype;
8456 sym_link *ltype = operandType (left);
8459 D(emitcode ("; genNearPointerGet",""));
8461 rtype = operandType (result);
8462 retype = getSpec (rtype);
8464 aopOp (left, ic, FALSE);
8466 /* if left is rematerialisable and
8467 result is not bitfield variable type and
8468 the left is pointer to data space i.e
8469 lower 128 bytes of space */
8470 if (AOP_TYPE (left) == AOP_IMMD &&
8471 !IS_BITFIELD (retype) &&
8472 DCL_TYPE (ltype) == POINTER)
8474 genDataPointerGet (left, result, ic);
8478 /* if the value is already in a pointer register
8479 then don't need anything more */
8480 if (!AOP_INPREG (AOP (left)))
8482 if (IS_AOP_PREG (left))
8484 // Aha, it is a pointer, just in disguise.
8485 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8488 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8489 __FILE__, __LINE__);
8494 emitcode ("mov", "a%s,%s", rname + 1, rname);
8495 rname++; // skip the '@'.
8500 /* otherwise get a free pointer register */
8502 preg = getFreePtr (ic, &aop, FALSE);
8503 emitcode ("mov", "%s,%s",
8505 aopGet (AOP (left), 0, FALSE, TRUE));
8510 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8512 //aopOp (result, ic, FALSE);
8513 aopOp (result, ic, result?TRUE:FALSE);
8515 /* if bitfield then unpack the bits */
8516 if (IS_BITFIELD (retype))
8517 genUnpackBits (result, rname, POINTER, ifx);
8520 /* we have can just get the values */
8521 int size = AOP_SIZE (result);
8526 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8529 emitcode ("mov", "a,@%s", rname);
8531 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8535 sprintf (buffer, "@%s", rname);
8536 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8540 emitcode ("inc", "%s", rname);
8544 /* now some housekeeping stuff */
8545 if (aop) /* we had to allocate for this iCode */
8547 if (pi) { /* post increment present */
8548 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8550 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8554 /* we did not allocate which means left
8555 already in a pointer register, then
8556 if size > 0 && this could be used again
8557 we have to point it back to where it
8559 if ((AOP_SIZE (result) > 1 &&
8560 !OP_SYMBOL (left)->remat &&
8561 (OP_SYMBOL (left)->liveTo > ic->seq ||
8565 int size = AOP_SIZE (result) - 1;
8567 emitcode ("dec", "%s", rname);
8571 if (ifx && !ifx->generated)
8573 genIfxJump (ifx, "a", left, NULL, result);
8577 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8578 freeAsmop (left, NULL, ic, TRUE);
8579 if (pi) pi->generated = 1;
8582 /*-----------------------------------------------------------------*/
8583 /* genPagedPointerGet - emitcode for paged pointer fetch */
8584 /*-----------------------------------------------------------------*/
8586 genPagedPointerGet (operand * left,
8595 sym_link *rtype, *retype;
8597 D(emitcode ("; genPagedPointerGet",""));
8599 rtype = operandType (result);
8600 retype = getSpec (rtype);
8602 aopOp (left, ic, FALSE);
8604 /* if the value is already in a pointer register
8605 then don't need anything more */
8606 if (!AOP_INPREG (AOP (left)))
8608 /* otherwise get a free pointer register */
8610 preg = getFreePtr (ic, &aop, FALSE);
8611 emitcode ("mov", "%s,%s",
8613 aopGet (AOP (left), 0, FALSE, TRUE));
8617 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8619 aopOp (result, ic, FALSE);
8621 /* if bitfield then unpack the bits */
8622 if (IS_BITFIELD (retype))
8623 genUnpackBits (result, rname, PPOINTER, ifx);
8626 /* we have can just get the values */
8627 int size = AOP_SIZE (result);
8633 emitcode ("movx", "a,@%s", rname);
8635 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8640 emitcode ("inc", "%s", rname);
8644 /* now some housekeeping stuff */
8645 if (aop) /* we had to allocate for this iCode */
8647 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8648 freeAsmop (NULL, aop, ic, TRUE);
8652 /* we did not allocate which means left
8653 already in a pointer register, then
8654 if size > 0 && this could be used again
8655 we have to point it back to where it
8657 if ((AOP_SIZE (result) > 1 &&
8658 !OP_SYMBOL (left)->remat &&
8659 (OP_SYMBOL (left)->liveTo > ic->seq ||
8663 int size = AOP_SIZE (result) - 1;
8665 emitcode ("dec", "%s", rname);
8669 if (ifx && !ifx->generated)
8671 genIfxJump (ifx, "a", left, NULL, result);
8675 freeAsmop (left, NULL, ic, TRUE);
8676 freeAsmop (result, NULL, ic, TRUE);
8677 if (pi) pi->generated = 1;
8681 /*--------------------------------------------------------------------*/
8682 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8683 /*--------------------------------------------------------------------*/
8685 loadDptrFromOperand (operand *op, bool loadBToo)
8687 if (AOP_TYPE (op) != AOP_STR)
8689 /* if this is rematerializable */
8690 if (AOP_TYPE (op) == AOP_IMMD)
8692 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8695 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8696 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8699 wassertl(FALSE, "need pointerCode");
8700 emitcode ("", "; mov b,???");
8701 /* genPointerGet and genPointerSet originally did different
8702 ** things for this case. Both seem wrong.
8703 ** from genPointerGet:
8704 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8705 ** from genPointerSet:
8706 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8711 else if (AOP_TYPE (op) == AOP_DPTR)
8715 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8716 emitcode ("push", "acc");
8717 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8718 emitcode ("push", "acc");
8719 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8720 emitcode ("pop", "dph");
8721 emitcode ("pop", "dpl");
8725 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8726 emitcode ("push", "acc");
8727 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8728 emitcode ("pop", "dpl");
8732 { /* we need to get it byte by byte */
8733 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8734 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8736 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8741 /*-----------------------------------------------------------------*/
8742 /* genFarPointerGet - gget value from far space */
8743 /*-----------------------------------------------------------------*/
8745 genFarPointerGet (operand * left,
8746 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8749 sym_link *retype = getSpec (operandType (result));
8751 D(emitcode ("; genFarPointerGet",""));
8753 aopOp (left, ic, FALSE);
8754 loadDptrFromOperand (left, FALSE);
8756 /* so dptr now contains the address */
8757 aopOp (result, ic, FALSE);
8759 /* if bit then unpack */
8760 if (IS_BITFIELD (retype))
8761 genUnpackBits (result, "dptr", FPOINTER, ifx);
8764 size = AOP_SIZE (result);
8769 emitcode ("movx", "a,@dptr");
8771 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8773 emitcode ("inc", "dptr");
8777 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8779 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8780 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8784 if (ifx && !ifx->generated)
8786 genIfxJump (ifx, "a", left, NULL, result);
8789 freeAsmop (left, NULL, ic, TRUE);
8790 freeAsmop (result, NULL, ic, TRUE);
8793 /*-----------------------------------------------------------------*/
8794 /* genCodePointerGet - gget value from code space */
8795 /*-----------------------------------------------------------------*/
8797 genCodePointerGet (operand * left,
8798 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8801 sym_link *retype = getSpec (operandType (result));
8803 D(emitcode ("; genCodePointerGet",""));
8805 aopOp (left, ic, FALSE);
8806 loadDptrFromOperand (left, FALSE);
8808 /* so dptr now contains the address */
8809 aopOp (result, ic, FALSE);
8811 /* if bit then unpack */
8812 if (IS_BITFIELD (retype))
8813 genUnpackBits (result, "dptr", CPOINTER, ifx);
8816 size = AOP_SIZE (result);
8823 emitcode ("clr", "a");
8824 emitcode ("movc", "a,@a+dptr");
8826 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8827 emitcode ("inc", "dptr");
8831 emitcode ("mov", "a,#0x%02x", offset);
8832 emitcode ("movc", "a,@a+dptr");
8834 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8839 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8841 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8842 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8846 if (ifx && !ifx->generated)
8848 genIfxJump (ifx, "a", left, NULL, result);
8851 freeAsmop (left, NULL, ic, TRUE);
8852 freeAsmop (result, NULL, ic, TRUE);
8855 /*-----------------------------------------------------------------*/
8856 /* genGenPointerGet - gget value from generic pointer space */
8857 /*-----------------------------------------------------------------*/
8859 genGenPointerGet (operand * left,
8860 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8863 sym_link *retype = getSpec (operandType (result));
8865 D(emitcode ("; genGenPointerGet",""));
8867 aopOp (left, ic, FALSE);
8868 loadDptrFromOperand (left, TRUE);
8870 /* so dptr know contains the address */
8871 aopOp (result, ic, FALSE);
8873 /* if bit then unpack */
8874 if (IS_BITFIELD (retype))
8875 genUnpackBits (result, "dptr", GPOINTER, ifx);
8878 size = AOP_SIZE (result);
8883 emitcode ("lcall", "__gptrget");
8885 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8887 emitcode ("inc", "dptr");
8891 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8893 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8894 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8898 if (ifx && !ifx->generated)
8900 genIfxJump (ifx, "a", left, NULL, result);
8904 freeAsmop (left, NULL, ic, TRUE);
8905 freeAsmop (result, NULL, ic, TRUE);
8908 /*-----------------------------------------------------------------*/
8909 /* genPointerGet - generate code for pointer get */
8910 /*-----------------------------------------------------------------*/
8912 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8914 operand *left, *result;
8915 sym_link *type, *etype;
8918 D(emitcode ("; genPointerGet",""));
8920 left = IC_LEFT (ic);
8921 result = IC_RESULT (ic);
8923 if (getSize (operandType (result))>1)
8926 /* depending on the type of pointer we need to
8927 move it to the correct pointer register */
8928 type = operandType (left);
8929 etype = getSpec (type);
8930 /* if left is of type of pointer then it is simple */
8931 if (IS_PTR (type) && !IS_FUNC (type->next))
8932 p_type = DCL_TYPE (type);
8935 /* we have to go by the storage class */
8936 p_type = PTR_TYPE (SPEC_OCLS (etype));
8939 /* special case when cast remat */
8940 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8941 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8942 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8943 type = operandType (left);
8944 p_type = DCL_TYPE (type);
8946 /* now that we have the pointer type we assign
8947 the pointer values */
8953 genNearPointerGet (left, result, ic, pi, ifx);
8957 genPagedPointerGet (left, result, ic, pi, ifx);
8961 genFarPointerGet (left, result, ic, pi, ifx);
8965 genCodePointerGet (left, result, ic, pi, ifx);
8969 genGenPointerGet (left, result, ic, pi, ifx);
8977 /*-----------------------------------------------------------------*/
8978 /* genPackBits - generates code for packed bit storage */
8979 /*-----------------------------------------------------------------*/
8981 genPackBits (sym_link * etype,
8983 char *rname, int p_type)
8985 int offset = 0; /* source byte offset */
8986 int rlen = 0; /* remaining bitfield length */
8987 int blen; /* bitfield length */
8988 int bstr; /* bitfield starting bit within byte */
8989 int litval; /* source literal value (if AOP_LIT) */
8990 unsigned char mask; /* bitmask within current byte */
8992 D(emitcode ("; genPackBits",""));
8994 blen = SPEC_BLEN (etype);
8995 bstr = SPEC_BSTR (etype);
8997 /* If the bitfield length is less than a byte */
9000 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9001 (unsigned char) (0xFF >> (8 - bstr)));
9003 if (AOP_TYPE (right) == AOP_LIT)
9005 /* Case with a bitfield length <8 and literal source
9007 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9009 litval &= (~mask) & 0xff;
9010 emitPtrByteGet (rname, p_type, FALSE);
9011 if ((mask|litval)!=0xff)
9012 emitcode ("anl","a,#0x%02x", mask);
9014 emitcode ("orl","a,#0x%02x", litval);
9018 if ((blen==1) && (p_type!=GPOINTER))
9020 /* Case with a bitfield length == 1 and no generic pointer
9022 if (AOP_TYPE (right) == AOP_CRY)
9023 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9026 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9027 emitcode ("rrc","a");
9029 emitPtrByteGet (rname, p_type, FALSE);
9030 emitcode ("mov","acc.%d,c",bstr);
9035 /* Case with a bitfield length < 8 and arbitrary source
9037 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9038 /* shift and mask source value */
9040 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9043 /* transfer A to B and get next byte */
9044 emitPtrByteGet (rname, p_type, TRUE);
9046 emitcode ("anl", "a,#0x%02x", mask);
9047 emitcode ("orl", "a,b");
9048 if (p_type == GPOINTER)
9049 emitcode ("pop", "b");
9055 emitPtrByteSet (rname, p_type, "a");
9059 /* Bit length is greater than 7 bits. In this case, copy */
9060 /* all except the partial byte at the end */
9061 for (rlen=blen;rlen>=8;rlen-=8)
9063 emitPtrByteSet (rname, p_type,
9064 aopGet (AOP (right), offset++, FALSE, TRUE) );
9066 emitcode ("inc", "%s", rname);
9069 /* If there was a partial byte at the end */
9072 mask = (((unsigned char) -1 << rlen) & 0xff);
9074 if (AOP_TYPE (right) == AOP_LIT)
9076 /* Case with partial byte and literal source
9078 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9079 litval >>= (blen-rlen);
9080 litval &= (~mask) & 0xff;
9081 emitPtrByteGet (rname, p_type, FALSE);
9082 if ((mask|litval)!=0xff)
9083 emitcode ("anl","a,#0x%02x", mask);
9085 emitcode ("orl","a,#0x%02x", litval);
9090 /* Case with partial byte and arbitrary source
9092 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9093 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9096 /* transfer A to B and get next byte */
9097 emitPtrByteGet (rname, p_type, TRUE);
9099 emitcode ("anl", "a,#0x%02x", mask);
9100 emitcode ("orl", "a,b");
9101 if (p_type == GPOINTER)
9102 emitcode ("pop", "b");
9106 emitPtrByteSet (rname, p_type, "a");
9112 /*-----------------------------------------------------------------*/
9113 /* genDataPointerSet - remat pointer to data space */
9114 /*-----------------------------------------------------------------*/
9116 genDataPointerSet (operand * right,
9120 int size, offset = 0;
9121 char *l, buffer[256];
9123 D(emitcode ("; genDataPointerSet",""));
9125 aopOp (right, ic, FALSE);
9127 l = aopGet (AOP (result), 0, FALSE, TRUE);
9128 size = AOP_SIZE (right);
9132 sprintf (buffer, "(%s + %d)", l + 1, offset);
9134 sprintf (buffer, "%s", l + 1);
9135 emitcode ("mov", "%s,%s", buffer,
9136 aopGet (AOP (right), offset++, FALSE, FALSE));
9139 freeAsmop (right, NULL, ic, TRUE);
9140 freeAsmop (result, NULL, ic, TRUE);
9143 /*-----------------------------------------------------------------*/
9144 /* genNearPointerSet - emitcode for near pointer put */
9145 /*-----------------------------------------------------------------*/
9147 genNearPointerSet (operand * right,
9155 sym_link *retype, *letype;
9156 sym_link *ptype = operandType (result);
9158 D(emitcode ("; genNearPointerSet",""));
9160 retype = getSpec (operandType (right));
9161 letype = getSpec (ptype);
9162 aopOp (result, ic, FALSE);
9164 /* if the result is rematerializable &
9165 in data space & not a bit variable */
9166 if (AOP_TYPE (result) == AOP_IMMD &&
9167 DCL_TYPE (ptype) == POINTER &&
9168 !IS_BITVAR (retype) &&
9169 !IS_BITVAR (letype))
9171 genDataPointerSet (right, result, ic);
9175 /* if the value is already in a pointer register
9176 then don't need anything more */
9177 if (!AOP_INPREG (AOP (result)))
9180 //AOP_TYPE (result) == AOP_STK
9184 // Aha, it is a pointer, just in disguise.
9185 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9188 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9189 __FILE__, __LINE__);
9194 emitcode ("mov", "a%s,%s", rname + 1, rname);
9195 rname++; // skip the '@'.
9200 /* otherwise get a free pointer register */
9202 preg = getFreePtr (ic, &aop, FALSE);
9203 emitcode ("mov", "%s,%s",
9205 aopGet (AOP (result), 0, FALSE, TRUE));
9211 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9214 aopOp (right, ic, FALSE);
9216 /* if bitfield then unpack the bits */
9217 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9218 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9221 /* we have can just get the values */
9222 int size = AOP_SIZE (right);
9227 l = aopGet (AOP (right), offset, FALSE, TRUE);
9231 emitcode ("mov", "@%s,a", rname);
9234 emitcode ("mov", "@%s,%s", rname, l);
9236 emitcode ("inc", "%s", rname);
9241 /* now some housekeeping stuff */
9242 if (aop) /* we had to allocate for this iCode */
9245 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9246 freeAsmop (NULL, aop, ic, TRUE);
9250 /* we did not allocate which means left
9251 already in a pointer register, then
9252 if size > 0 && this could be used again
9253 we have to point it back to where it
9255 if ((AOP_SIZE (right) > 1 &&
9256 !OP_SYMBOL (result)->remat &&
9257 (OP_SYMBOL (result)->liveTo > ic->seq ||
9261 int size = AOP_SIZE (right) - 1;
9263 emitcode ("dec", "%s", rname);
9268 if (pi) pi->generated = 1;
9269 freeAsmop (result, NULL, ic, TRUE);
9270 freeAsmop (right, NULL, ic, TRUE);
9273 /*-----------------------------------------------------------------*/
9274 /* genPagedPointerSet - emitcode for Paged pointer put */
9275 /*-----------------------------------------------------------------*/
9277 genPagedPointerSet (operand * right,
9285 sym_link *retype, *letype;
9287 D(emitcode ("; genPagedPointerSet",""));
9289 retype = getSpec (operandType (right));
9290 letype = getSpec (operandType (result));
9292 aopOp (result, ic, FALSE);
9294 /* if the value is already in a pointer register
9295 then don't need anything more */
9296 if (!AOP_INPREG (AOP (result)))
9298 /* otherwise get a free pointer register */
9300 preg = getFreePtr (ic, &aop, FALSE);
9301 emitcode ("mov", "%s,%s",
9303 aopGet (AOP (result), 0, FALSE, TRUE));
9307 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9309 aopOp (right, ic, FALSE);
9311 /* if bitfield then unpack the bits */
9312 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9313 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9316 /* we have can just get the values */
9317 int size = AOP_SIZE (right);
9322 l = aopGet (AOP (right), offset, FALSE, TRUE);
9325 emitcode ("movx", "@%s,a", rname);
9328 emitcode ("inc", "%s", rname);
9334 /* now some housekeeping stuff */
9335 if (aop) /* we had to allocate for this iCode */
9338 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9339 freeAsmop (NULL, aop, ic, TRUE);
9343 /* we did not allocate which means left
9344 already in a pointer register, then
9345 if size > 0 && this could be used again
9346 we have to point it back to where it
9348 if (AOP_SIZE (right) > 1 &&
9349 !OP_SYMBOL (result)->remat &&
9350 (OP_SYMBOL (result)->liveTo > ic->seq ||
9353 int size = AOP_SIZE (right) - 1;
9355 emitcode ("dec", "%s", rname);
9360 if (pi) pi->generated = 1;
9361 freeAsmop (result, NULL, ic, TRUE);
9362 freeAsmop (right, NULL, ic, TRUE);
9367 /*-----------------------------------------------------------------*/
9368 /* genFarPointerSet - set value from far space */
9369 /*-----------------------------------------------------------------*/
9371 genFarPointerSet (operand * right,
9372 operand * result, iCode * ic, iCode * pi)
9375 sym_link *retype = getSpec (operandType (right));
9376 sym_link *letype = getSpec (operandType (result));
9378 D(emitcode ("; genFarPointerSet",""));
9380 aopOp (result, ic, FALSE);
9381 loadDptrFromOperand (result, FALSE);
9383 /* so dptr know contains the address */
9384 aopOp (right, ic, FALSE);
9386 /* if bit then unpack */
9387 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9388 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9391 size = AOP_SIZE (right);
9396 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9398 emitcode ("movx", "@dptr,a");
9400 emitcode ("inc", "dptr");
9403 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9404 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9405 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9408 freeAsmop (result, NULL, ic, TRUE);
9409 freeAsmop (right, NULL, ic, TRUE);
9412 /*-----------------------------------------------------------------*/
9413 /* genGenPointerSet - set value from generic pointer space */
9414 /*-----------------------------------------------------------------*/
9416 genGenPointerSet (operand * right,
9417 operand * result, iCode * ic, iCode * pi)
9420 sym_link *retype = getSpec (operandType (right));
9421 sym_link *letype = getSpec (operandType (result));
9423 D(emitcode ("; genGenPointerSet",""));
9425 aopOp (result, ic, FALSE);
9426 loadDptrFromOperand (result, TRUE);
9428 /* so dptr know contains the address */
9429 aopOp (right, ic, FALSE);
9431 /* if bit then unpack */
9432 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9433 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9436 size = AOP_SIZE (right);
9441 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9443 emitcode ("lcall", "__gptrput");
9445 emitcode ("inc", "dptr");
9449 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9450 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9451 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9454 freeAsmop (result, NULL, ic, TRUE);
9455 freeAsmop (right, NULL, ic, TRUE);
9458 /*-----------------------------------------------------------------*/
9459 /* genPointerSet - stores the value into a pointer location */
9460 /*-----------------------------------------------------------------*/
9462 genPointerSet (iCode * ic, iCode *pi)
9464 operand *right, *result;
9465 sym_link *type, *etype;
9468 D(emitcode ("; genPointerSet",""));
9470 right = IC_RIGHT (ic);
9471 result = IC_RESULT (ic);
9473 /* depending on the type of pointer we need to
9474 move it to the correct pointer register */
9475 type = operandType (result);
9476 etype = getSpec (type);
9477 /* if left is of type of pointer then it is simple */
9478 if (IS_PTR (type) && !IS_FUNC (type->next))
9480 p_type = DCL_TYPE (type);
9484 /* we have to go by the storage class */
9485 p_type = PTR_TYPE (SPEC_OCLS (etype));
9488 /* special case when cast remat */
9489 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9490 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9491 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9492 type = operandType (result);
9493 p_type = DCL_TYPE (type);
9495 /* now that we have the pointer type we assign
9496 the pointer values */
9502 genNearPointerSet (right, result, ic, pi);
9506 genPagedPointerSet (right, result, ic, pi);
9510 genFarPointerSet (right, result, ic, pi);
9514 genGenPointerSet (right, result, ic, pi);
9518 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9519 "genPointerSet: illegal pointer type");
9524 /*-----------------------------------------------------------------*/
9525 /* genIfx - generate code for Ifx statement */
9526 /*-----------------------------------------------------------------*/
9528 genIfx (iCode * ic, iCode * popIc)
9530 operand *cond = IC_COND (ic);
9533 D(emitcode ("; genIfx",""));
9535 aopOp (cond, ic, FALSE);
9537 /* get the value into acc */
9538 if (AOP_TYPE (cond) != AOP_CRY)
9542 /* the result is now in the accumulator */
9543 freeAsmop (cond, NULL, ic, TRUE);
9545 /* if there was something to be popped then do it */
9549 /* if the condition is a bit variable */
9550 if (isbit && IS_ITEMP (cond) &&
9552 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9553 else if (isbit && !IS_ITEMP (cond))
9554 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9556 genIfxJump (ic, "a", NULL, NULL, NULL);
9561 /*-----------------------------------------------------------------*/
9562 /* genAddrOf - generates code for address of */
9563 /*-----------------------------------------------------------------*/
9565 genAddrOf (iCode * ic)
9567 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9570 D(emitcode ("; genAddrOf",""));
9572 aopOp (IC_RESULT (ic), ic, FALSE);
9574 /* if the operand is on the stack then we
9575 need to get the stack offset of this
9579 /* if it has an offset then we need to compute
9583 emitcode ("mov", "a,_bp");
9584 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9585 ((char) (sym->stack - _G.nRegsSaved)) :
9586 ((char) sym->stack)) & 0xff);
9587 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9591 /* we can just move _bp */
9592 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9594 /* fill the result with zero */
9595 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9600 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9606 /* object not on stack then we need the name */
9607 size = AOP_SIZE (IC_RESULT (ic));
9612 char s[SDCC_NAME_MAX];
9614 sprintf (s, "#(%s >> %d)",
9618 sprintf (s, "#%s", sym->rname);
9619 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9623 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9627 /*-----------------------------------------------------------------*/
9628 /* genFarFarAssign - assignment when both are in far space */
9629 /*-----------------------------------------------------------------*/
9631 genFarFarAssign (operand * result, operand * right, iCode * ic)
9633 int size = AOP_SIZE (right);
9637 D(emitcode ("; genFarFarAssign",""));
9639 /* first push the right side on to the stack */
9642 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9644 emitcode ("push", "acc");
9647 freeAsmop (right, NULL, ic, FALSE);
9648 /* now assign DPTR to result */
9649 aopOp (result, ic, FALSE);
9650 size = AOP_SIZE (result);
9653 emitcode ("pop", "acc");
9654 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9656 freeAsmop (result, NULL, ic, FALSE);
9660 /*-----------------------------------------------------------------*/
9661 /* genAssign - generate code for assignment */
9662 /*-----------------------------------------------------------------*/
9664 genAssign (iCode * ic)
9666 operand *result, *right;
9668 unsigned long lit = 0L;
9670 D(emitcode("; genAssign",""));
9672 result = IC_RESULT (ic);
9673 right = IC_RIGHT (ic);
9675 /* if they are the same */
9676 if (operandsEqu (result, right) &&
9677 !isOperandVolatile (result, FALSE) &&
9678 !isOperandVolatile (right, FALSE))
9681 aopOp (right, ic, FALSE);
9683 /* special case both in far space */
9684 if (AOP_TYPE (right) == AOP_DPTR &&
9685 IS_TRUE_SYMOP (result) &&
9686 isOperandInFarSpace (result))
9689 genFarFarAssign (result, right, ic);
9693 aopOp (result, ic, TRUE);
9695 /* if they are the same registers */
9696 if (sameRegs (AOP (right), AOP (result)) &&
9697 !isOperandVolatile (result, FALSE) &&
9698 !isOperandVolatile (right, FALSE))
9701 /* if the result is a bit */
9702 if (AOP_TYPE (result) == AOP_CRY)
9705 /* if the right size is a literal then
9706 we know what the value is */
9707 if (AOP_TYPE (right) == AOP_LIT)
9709 if (((int) operandLitValue (right)))
9710 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9712 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9716 /* the right is also a bit variable */
9717 if (AOP_TYPE (right) == AOP_CRY)
9719 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9720 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9726 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9730 /* bit variables done */
9732 size = AOP_SIZE (result);
9734 if (AOP_TYPE (right) == AOP_LIT)
9735 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9737 (AOP_TYPE (result) != AOP_REG) &&
9738 (AOP_TYPE (right) == AOP_LIT) &&
9739 !IS_FLOAT (operandType (right)) &&
9742 while ((size) && (lit))
9744 aopPut (AOP (result),
9745 aopGet (AOP (right), offset, FALSE, FALSE),
9747 isOperandVolatile (result, FALSE));
9752 emitcode ("clr", "a");
9755 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9763 aopPut (AOP (result),
9764 aopGet (AOP (right), offset, FALSE, FALSE),
9766 isOperandVolatile (result, FALSE));
9772 freeAsmop (right, NULL, ic, TRUE);
9773 freeAsmop (result, NULL, ic, TRUE);
9776 /*-----------------------------------------------------------------*/
9777 /* genJumpTab - genrates code for jump table */
9778 /*-----------------------------------------------------------------*/
9780 genJumpTab (iCode * ic)
9782 symbol *jtab,*jtablo,*jtabhi;
9786 D(emitcode ("; genJumpTab",""));
9788 count = elementsInSet( IC_JTLABELS (ic) );
9792 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9793 if the switch argument is in a register.
9794 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9795 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9796 How will multiply by three be updated ???*/
9797 aopOp (IC_JTCOND (ic), ic, FALSE);
9798 /* get the condition into accumulator */
9799 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9801 /* multiply by three */
9802 emitcode ("add", "a,acc");
9803 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9804 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9806 jtab = newiTempLabel (NULL);
9807 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9808 emitcode ("jmp", "@a+dptr");
9809 emitcode ("", "%05d$:", jtab->key + 100);
9810 /* now generate the jump labels */
9811 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9812 jtab = setNextItem (IC_JTLABELS (ic)))
9813 emitcode ("ljmp", "%05d$", jtab->key + 100);
9817 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9818 if the switch argument is in a register.
9819 For n>6 this algorithm may be more compact */
9820 jtablo = newiTempLabel (NULL);
9821 jtabhi = newiTempLabel (NULL);
9823 /* get the condition into accumulator.
9824 Using b as temporary storage, if register push/pop is needed */
9825 aopOp (IC_JTCOND (ic), ic, FALSE);
9826 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9827 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9828 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9830 // (MB) what if B is in use???
9831 wassertl(!_G.BInUse, "B was in use");
9832 emitcode ("mov", "b,%s", l);
9835 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9839 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9840 emitcode ("movc", "a,@a+pc");
9841 emitcode ("push", "acc");
9844 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9845 emitcode ("movc", "a,@a+pc");
9846 emitcode ("push", "acc");
9850 /* this scales up to n<=255, but needs two more bytes
9852 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9853 emitcode ("movc", "a,@a+dptr");
9854 emitcode ("push", "acc");
9857 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9858 emitcode ("movc", "a,@a+dptr");
9859 emitcode ("push", "acc");
9862 emitcode ("ret", "");
9864 /* now generate jump table, LSB */
9865 emitcode ("", "%05d$:", jtablo->key + 100);
9866 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9867 jtab = setNextItem (IC_JTLABELS (ic)))
9868 emitcode (".db", "%05d$", jtab->key + 100);
9870 /* now generate jump table, MSB */
9871 emitcode ("", "%05d$:", jtabhi->key + 100);
9872 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9873 jtab = setNextItem (IC_JTLABELS (ic)))
9874 emitcode (".db", "%05d$>>8", jtab->key + 100);
9878 /*-----------------------------------------------------------------*/
9879 /* genCast - gen code for casting */
9880 /*-----------------------------------------------------------------*/
9882 genCast (iCode * ic)
9884 operand *result = IC_RESULT (ic);
9885 sym_link *ctype = operandType (IC_LEFT (ic));
9886 sym_link *rtype = operandType (IC_RIGHT (ic));
9887 operand *right = IC_RIGHT (ic);
9890 D(emitcode("; genCast",""));
9892 /* if they are equivalent then do nothing */
9893 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9896 aopOp (right, ic, FALSE);
9897 aopOp (result, ic, FALSE);
9899 /* if the result is a bit (and not a bitfield) */
9900 // if (AOP_TYPE (result) == AOP_CRY)
9901 if (IS_BITVAR (OP_SYMBOL (result)->type)
9902 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9904 /* if the right size is a literal then
9905 we know what the value is */
9906 if (AOP_TYPE (right) == AOP_LIT)
9908 if (((int) operandLitValue (right)))
9909 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9911 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9916 /* the right is also a bit variable */
9917 if (AOP_TYPE (right) == AOP_CRY)
9919 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9920 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9926 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9931 /* if they are the same size : or less */
9932 if (AOP_SIZE (result) <= AOP_SIZE (right))
9935 /* if they are in the same place */
9936 if (sameRegs (AOP (right), AOP (result)))
9939 /* if they in different places then copy */
9940 size = AOP_SIZE (result);
9944 aopPut (AOP (result),
9945 aopGet (AOP (right), offset, FALSE, FALSE),
9947 isOperandVolatile (result, FALSE));
9954 /* if the result is of type pointer */
9959 sym_link *type = operandType (right);
9960 sym_link *etype = getSpec (type);
9962 /* pointer to generic pointer */
9963 if (IS_GENPTR (ctype))
9966 p_type = DCL_TYPE (type);
9969 if (SPEC_SCLS(etype)==S_REGISTER) {
9970 // let's assume it is a generic pointer
9973 /* we have to go by the storage class */
9974 p_type = PTR_TYPE (SPEC_OCLS (etype));
9978 /* the first two bytes are known */
9979 size = GPTRSIZE - 1;
9983 aopPut (AOP (result),
9984 aopGet (AOP (right), offset, FALSE, FALSE),
9986 isOperandVolatile (result, FALSE));
9989 /* the last byte depending on type */
9991 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9996 // pointerTypeToGPByte will have bitched.
10000 sprintf(gpValStr, "#0x%d", gpVal);
10001 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10006 /* just copy the pointers */
10007 size = AOP_SIZE (result);
10011 aopPut (AOP (result),
10012 aopGet (AOP (right), offset, FALSE, FALSE),
10014 isOperandVolatile (result, FALSE));
10020 /* so we now know that the size of destination is greater
10021 than the size of the source */
10022 /* we move to result for the size of source */
10023 size = AOP_SIZE (right);
10027 aopPut (AOP (result),
10028 aopGet (AOP (right), offset, FALSE, FALSE),
10030 isOperandVolatile (result, FALSE));
10034 /* now depending on the sign of the source && destination */
10035 size = AOP_SIZE (result) - AOP_SIZE (right);
10036 /* if unsigned or not an integral type */
10037 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10040 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10044 /* we need to extend the sign :{ */
10045 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10048 emitcode ("rlc", "a");
10049 emitcode ("subb", "a,acc");
10051 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10054 /* we are done hurray !!!! */
10057 freeAsmop (right, NULL, ic, TRUE);
10058 freeAsmop (result, NULL, ic, TRUE);
10062 /*-----------------------------------------------------------------*/
10063 /* genDjnz - generate decrement & jump if not zero instrucion */
10064 /*-----------------------------------------------------------------*/
10066 genDjnz (iCode * ic, iCode * ifx)
10068 symbol *lbl, *lbl1;
10072 D(emitcode ("; genDjnz",""));
10074 /* if the if condition has a false label
10075 then we cannot save */
10076 if (IC_FALSE (ifx))
10079 /* if the minus is not of the form
10081 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10082 !IS_OP_LITERAL (IC_RIGHT (ic)))
10085 if (operandLitValue (IC_RIGHT (ic)) != 1)
10088 /* if the size of this greater than one then no
10090 if (getSize (operandType (IC_RESULT (ic))) > 1)
10093 /* otherwise we can save BIG */
10094 lbl = newiTempLabel (NULL);
10095 lbl1 = newiTempLabel (NULL);
10097 aopOp (IC_RESULT (ic), ic, FALSE);
10099 if (AOP_NEEDSACC(IC_RESULT(ic)))
10101 /* If the result is accessed indirectly via
10102 * the accumulator, we must explicitly write
10103 * it back after the decrement.
10105 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10107 if (strcmp(rByte, "a"))
10109 /* Something is hopelessly wrong */
10110 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10111 __FILE__, __LINE__);
10112 /* We can just give up; the generated code will be inefficient,
10113 * but what the hey.
10115 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10118 emitcode ("dec", "%s", rByte);
10119 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10120 emitcode ("jnz", "%05d$", lbl->key + 100);
10122 else if (IS_AOP_PREG (IC_RESULT (ic)))
10124 emitcode ("dec", "%s",
10125 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10126 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10127 emitcode ("jnz", "%05d$", lbl->key + 100);
10131 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10134 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10135 emitcode ("", "%05d$:", lbl->key + 100);
10136 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10137 emitcode ("", "%05d$:", lbl1->key + 100);
10139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10140 ifx->generated = 1;
10144 /*-----------------------------------------------------------------*/
10145 /* genReceive - generate code for a receive iCode */
10146 /*-----------------------------------------------------------------*/
10148 genReceive (iCode * ic)
10150 int size = getSize (operandType (IC_RESULT (ic)));
10152 D(emitcode ("; genReceive",""));
10154 if (ic->argreg == 1) { /* first parameter */
10155 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10156 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10157 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10160 int receivingA = 0;
10163 for (offset = 0; offset<size; offset++)
10164 if (!strcmp (fReturn[offset], "a"))
10169 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10171 for (offset = size-1; offset>0; offset--)
10172 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10173 emitcode("mov","a,%s", fReturn[0]);
10175 aopOp (IC_RESULT (ic), ic, FALSE);
10177 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10178 isOperandVolatile (IC_RESULT (ic), FALSE));
10179 for (offset = 1; offset<size; offset++)
10180 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10181 isOperandVolatile (IC_RESULT (ic), FALSE));
10187 if (getTempRegs(tempRegs, size, ic))
10189 for (offset = 0; offset<size; offset++)
10190 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10191 aopOp (IC_RESULT (ic), ic, FALSE);
10192 for (offset = 0; offset<size; offset++)
10193 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10194 isOperandVolatile (IC_RESULT (ic), FALSE));
10199 offset = fReturnSizeMCS51 - size;
10201 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10202 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10205 aopOp (IC_RESULT (ic), ic, FALSE);
10206 size = AOP_SIZE (IC_RESULT (ic));
10209 emitcode ("pop", "acc");
10210 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10215 aopOp (IC_RESULT (ic), ic, FALSE);
10217 assignResultValue (IC_RESULT (ic));
10219 } else { /* second receive onwards */
10221 aopOp (IC_RESULT (ic), ic, FALSE);
10222 rb1off = ic->argreg;
10224 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10232 /*-----------------------------------------------------------------*/
10233 /* genDummyRead - generate code for dummy read of volatiles */
10234 /*-----------------------------------------------------------------*/
10236 genDummyRead (iCode * ic)
10241 D(emitcode("; genDummyRead",""));
10243 op = IC_RIGHT (ic);
10244 if (op && IS_SYMOP (op))
10246 aopOp (op, ic, FALSE);
10248 /* if the result is a bit */
10249 if (AOP_TYPE (op) == AOP_CRY)
10250 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10253 /* bit variables done */
10255 size = AOP_SIZE (op);
10259 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10264 freeAsmop (op, NULL, ic, TRUE);
10268 if (op && IS_SYMOP (op))
10270 aopOp (op, ic, FALSE);
10272 /* if the result is a bit */
10273 if (AOP_TYPE (op) == AOP_CRY)
10274 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10277 /* bit variables done */
10279 size = AOP_SIZE (op);
10283 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10288 freeAsmop (op, NULL, ic, TRUE);
10292 /*-----------------------------------------------------------------*/
10293 /* genCritical - generate code for start of a critical sequence */
10294 /*-----------------------------------------------------------------*/
10296 genCritical (iCode *ic)
10298 symbol *tlbl = newiTempLabel (NULL);
10300 D(emitcode("; genCritical",""));
10302 if (IC_RESULT (ic))
10304 aopOp (IC_RESULT (ic), ic, TRUE);
10305 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10306 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10307 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10308 emitcode ("", "%05d$:", (tlbl->key + 100));
10309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10313 emitcode ("setb", "c");
10314 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10315 emitcode ("clr", "c");
10316 emitcode ("", "%05d$:", (tlbl->key + 100));
10317 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10321 /*-----------------------------------------------------------------*/
10322 /* genEndCritical - generate code for end of a critical sequence */
10323 /*-----------------------------------------------------------------*/
10325 genEndCritical (iCode *ic)
10327 D(emitcode("; genEndCritical",""));
10331 aopOp (IC_RIGHT (ic), ic, FALSE);
10332 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10334 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10335 emitcode ("mov", "ea,c");
10339 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10340 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10341 emitcode ("rrc", "a");
10342 emitcode ("mov", "ea,c");
10344 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10348 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10349 emitcode ("mov", "ea,c");
10353 /*-----------------------------------------------------------------*/
10354 /* gen51Code - generate code for 8051 based controllers */
10355 /*-----------------------------------------------------------------*/
10357 gen51Code (iCode * lic)
10361 /* int cseq = 0; */
10363 _G.currentFunc = NULL;
10364 lineHead = lineCurr = NULL;
10366 /* print the allocation information */
10367 if (allocInfo && currFunc)
10368 printAllocInfo (currFunc, codeOutFile);
10369 /* if debug information required */
10370 if (options.debug && currFunc)
10372 debugFile->writeFunction (currFunc, lic);
10374 /* stack pointer name */
10375 if (options.useXstack)
10381 for (ic = lic; ic; ic = ic->next)
10383 _G.current_iCode = ic;
10385 if (ic->lineno && cln != ic->lineno)
10389 debugFile->writeCLine (ic);
10391 if (!options.noCcodeInAsm) {
10392 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10393 printCLine(ic->filename, ic->lineno));
10398 if (ic->seqPoint && ic->seqPoint != cseq)
10400 emitcode ("", "; sequence point %d", ic->seqPoint);
10401 cseq = ic->seqPoint;
10404 if (options.iCodeInAsm) {
10405 char regsInUse[80];
10408 for (i=0; i<8; i++) {
10409 sprintf (®sInUse[i],
10410 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10413 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10415 /* if the result is marked as
10416 spilt and rematerializable or code for
10417 this has already been generated then
10419 if (resultRemat (ic) || ic->generated)
10422 /* depending on the operation */
10442 /* IPOP happens only when trying to restore a
10443 spilt live range, if there is an ifx statement
10444 following this pop then the if statement might
10445 be using some of the registers being popped which
10446 would destory the contents of the register so
10447 we need to check for this condition and handle it */
10449 ic->next->op == IFX &&
10450 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10451 genIfx (ic->next, ic);
10469 genEndFunction (ic);
10489 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10506 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10510 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10517 /* note these two are xlated by algebraic equivalence
10518 during parsing SDCC.y */
10519 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10520 "got '>=' or '<=' shouldn't have come here");
10524 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10536 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10540 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10544 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10568 genRightShift (ic);
10571 case GET_VALUE_AT_ADDRESS:
10573 hasInc (IC_LEFT (ic), ic,
10574 getSize (operandType (IC_RESULT (ic)))),
10575 ifxForOp (IC_RESULT (ic), ic) );
10579 if (POINTER_SET (ic))
10580 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10606 addSet (&_G.sendSet, ic);
10609 case DUMMY_READ_VOLATILE:
10618 genEndCritical (ic);
10630 _G.current_iCode = NULL;
10632 /* now we are ready to call the
10633 peep hole optimizer */
10634 if (!options.nopeep)
10635 peepHole (&lineHead);
10637 /* now do the actual printing */
10638 printLine (lineHead, codeOutFile);