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 char *l = aopGet (AOP (oper), 0, FALSE, FALSE);
1596 if (!strncmp (l, "a", 2) || !strncmp (l, "acc", 4))
1601 emitcode("mov", "b,a");
1604 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1605 emitcode ("orl", "b,a");
1607 MOVA (aopGet (AOP (oper), offset, FALSE, FALSE));
1608 emitcode ("orl", "a,b");
1617 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1623 /*-----------------------------------------------------------------*/
1624 /* genNot - generate code for ! operation */
1625 /*-----------------------------------------------------------------*/
1631 D(emitcode ("; genNot",""));
1633 /* assign asmOps to operand & result */
1634 aopOp (IC_LEFT (ic), ic, FALSE);
1635 aopOp (IC_RESULT (ic), ic, TRUE);
1637 /* if in bit space then a special case */
1638 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1640 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1641 emitcode ("cpl", "c");
1642 outBitC (IC_RESULT (ic));
1646 toBoolean (IC_LEFT (ic));
1648 tlbl = newiTempLabel (NULL);
1649 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1650 emitcode ("", "%05d$:", tlbl->key + 100);
1651 outBitC (IC_RESULT (ic));
1654 /* release the aops */
1655 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1656 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 /*-----------------------------------------------------------------*/
1661 /* genCpl - generate code for complement */
1662 /*-----------------------------------------------------------------*/
1670 D(emitcode ("; genCpl",""));
1672 /* assign asmOps to operand & result */
1673 aopOp (IC_LEFT (ic), ic, FALSE);
1674 aopOp (IC_RESULT (ic), ic, TRUE);
1676 /* special case if in bit space */
1677 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1679 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1681 /* promotion rules are responsible for this strange result: */
1682 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1686 tlbl=newiTempLabel(NULL);
1687 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1688 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1689 IS_AOP_PREG (IC_LEFT (ic)))
1691 emitcode ("cjne", "%s,#0x01,%05d$",
1692 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1697 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1699 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1701 emitcode ("", "%05d$:", tlbl->key + 100);
1702 outBitC (IC_RESULT(ic));
1706 size = AOP_SIZE (IC_RESULT (ic));
1709 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1711 emitcode ("cpl", "a");
1712 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1717 /* release the aops */
1718 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1719 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1722 /*-----------------------------------------------------------------*/
1723 /* genUminusFloat - unary minus for floating points */
1724 /*-----------------------------------------------------------------*/
1726 genUminusFloat (operand * op, operand * result)
1728 int size, offset = 0;
1731 D(emitcode ("; genUminusFloat",""));
1733 /* for this we just copy and then flip the bit */
1735 size = AOP_SIZE (op) - 1;
1739 aopPut (AOP (result),
1740 aopGet (AOP (op), offset, FALSE, FALSE),
1742 isOperandVolatile (result, FALSE));
1746 l = aopGet (AOP (op), offset, FALSE, FALSE);
1750 emitcode ("cpl", "acc.7");
1751 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1754 /*-----------------------------------------------------------------*/
1755 /* genUminus - unary minus code generation */
1756 /*-----------------------------------------------------------------*/
1758 genUminus (iCode * ic)
1761 sym_link *optype, *rtype;
1764 D(emitcode ("; genUminus",""));
1767 aopOp (IC_LEFT (ic), ic, FALSE);
1768 aopOp (IC_RESULT (ic), ic, TRUE);
1770 /* if both in bit space then special
1772 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1773 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1776 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1777 emitcode ("cpl", "c");
1778 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1782 optype = operandType (IC_LEFT (ic));
1783 rtype = operandType (IC_RESULT (ic));
1785 /* if float then do float stuff */
1786 if (IS_FLOAT (optype))
1788 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1792 /* otherwise subtract from zero */
1793 size = AOP_SIZE (IC_LEFT (ic));
1798 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1799 if (!strcmp (l, "a"))
1803 emitcode ("cpl", "a");
1804 emitcode ("addc", "a,#0");
1810 emitcode ("clr", "a");
1811 emitcode ("subb", "a,%s", l);
1813 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1816 /* if any remaining bytes in the result */
1817 /* we just need to propagate the sign */
1818 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1820 emitcode ("rlc", "a");
1821 emitcode ("subb", "a,acc");
1823 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1827 /* release the aops */
1828 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1829 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1832 /*-----------------------------------------------------------------*/
1833 /* saveRegisters - will look for a call and save the registers */
1834 /*-----------------------------------------------------------------*/
1836 saveRegisters (iCode * lic)
1843 for (ic = lic; ic; ic = ic->next)
1844 if (ic->op == CALL || ic->op == PCALL)
1849 fprintf (stderr, "found parameter push with no function call\n");
1853 /* if the registers have been saved already or don't need to be then
1857 if (IS_SYMOP(IC_LEFT(ic)) &&
1858 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1859 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1862 /* save the registers in use at this time but skip the
1863 ones for the result */
1864 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1865 mcs51_rUmaskForOp (IC_RESULT(ic)));
1868 if (options.useXstack)
1870 if (bitVectBitValue (rsave, R0_IDX))
1872 emitcode ("mov", "a,r0");
1873 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1875 emitcode ("mov", "r0,%s", spname);
1876 for (i = 0; i < mcs51_nRegs; i++)
1878 if (bitVectBitValue (rsave, i))
1881 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1882 emitcode ("movx", "@r0,a");
1883 emitcode ("inc", "r0");
1886 emitcode ("mov", "%s,r0", spname);
1887 if (bitVectBitValue (rsave, R0_IDX))
1889 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1893 for (i = 0; i < mcs51_nRegs; i++)
1895 if (bitVectBitValue (rsave, i))
1896 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1900 /*-----------------------------------------------------------------*/
1901 /* unsaveRegisters - pop the pushed registers */
1902 /*-----------------------------------------------------------------*/
1904 unsaveRegisters (iCode * ic)
1909 /* restore the registers in use at this time but skip the
1910 ones for the result */
1911 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1912 mcs51_rUmaskForOp (IC_RESULT(ic)));
1914 if (options.useXstack)
1916 emitcode ("mov", "r0,%s", spname);
1917 for (i = mcs51_nRegs; i >= 0; i--)
1919 if (bitVectBitValue (rsave, i))
1921 emitcode ("dec", "r0");
1922 emitcode ("movx", "a,@r0");
1924 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1928 emitcode ("mov", "%s,r0", spname);
1929 if (bitVectBitValue (rsave, R0_IDX))
1931 emitcode ("mov", "r0,a");
1935 for (i = mcs51_nRegs; i >= 0; i--)
1937 if (bitVectBitValue (rsave, i))
1938 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1944 /*-----------------------------------------------------------------*/
1946 /*-----------------------------------------------------------------*/
1948 pushSide (operand * oper, int size)
1953 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1954 if (AOP_TYPE (oper) != AOP_REG &&
1955 AOP_TYPE (oper) != AOP_DIR &&
1959 emitcode ("push", "acc");
1962 emitcode ("push", "%s", l);
1966 /*-----------------------------------------------------------------*/
1967 /* assignResultValue - */
1968 /*-----------------------------------------------------------------*/
1970 assignResultValue (operand * oper)
1973 int size = AOP_SIZE (oper);
1976 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1982 /*-----------------------------------------------------------------*/
1983 /* genXpush - pushes onto the external stack */
1984 /*-----------------------------------------------------------------*/
1986 genXpush (iCode * ic)
1988 asmop *aop = newAsmop (0);
1990 int size, offset = 0;
1992 D(emitcode ("; genXpush",""));
1994 aopOp (IC_LEFT (ic), ic, FALSE);
1995 r = getFreePtr (ic, &aop, FALSE);
1998 emitcode ("mov", "%s,_spx", r->name);
2000 size = AOP_SIZE (IC_LEFT (ic));
2004 char *l = aopGet (AOP (IC_LEFT (ic)),
2005 offset++, FALSE, FALSE);
2007 emitcode ("movx", "@%s,a", r->name);
2008 emitcode ("inc", "%s", r->name);
2013 emitcode ("mov", "_spx,%s", r->name);
2015 freeAsmop (NULL, aop, ic, TRUE);
2016 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2019 /*-----------------------------------------------------------------*/
2020 /* genIpush - genrate code for pushing this gets a little complex */
2021 /*-----------------------------------------------------------------*/
2023 genIpush (iCode * ic)
2025 int size, offset = 0;
2028 D(emitcode ("; genIpush",""));
2030 /* if this is not a parm push : ie. it is spill push
2031 and spill push is always done on the local stack */
2035 /* and the item is spilt then do nothing */
2036 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2039 aopOp (IC_LEFT (ic), ic, FALSE);
2040 size = AOP_SIZE (IC_LEFT (ic));
2041 /* push it on the stack */
2044 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2050 emitcode ("push", "%s", l);
2055 /* this is a paramter push: in this case we call
2056 the routine to find the call and save those
2057 registers that need to be saved */
2060 /* if use external stack then call the external
2061 stack pushing routine */
2062 if (options.useXstack)
2068 /* then do the push */
2069 aopOp (IC_LEFT (ic), ic, FALSE);
2072 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2073 size = AOP_SIZE (IC_LEFT (ic));
2077 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2078 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2079 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2083 emitcode ("push", "acc");
2086 emitcode ("push", "%s", l);
2089 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2092 /*-----------------------------------------------------------------*/
2093 /* genIpop - recover the registers: can happen only for spilling */
2094 /*-----------------------------------------------------------------*/
2096 genIpop (iCode * ic)
2100 D(emitcode ("; genIpop",""));
2102 /* if the temp was not pushed then */
2103 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2106 aopOp (IC_LEFT (ic), ic, FALSE);
2107 size = AOP_SIZE (IC_LEFT (ic));
2108 offset = (size - 1);
2110 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2113 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2116 /*-----------------------------------------------------------------*/
2117 /* unsaveRBank - restores the resgister bank from stack */
2118 /*-----------------------------------------------------------------*/
2120 unsaveRBank (int bank, iCode * ic, bool popPsw)
2126 if (options.useXstack)
2130 /* Assume r0 is available for use. */
2131 r = mcs51_regWithIdx (R0_IDX);;
2136 r = getFreePtr (ic, &aop, FALSE);
2138 emitcode ("mov", "%s,_spx", r->name);
2143 if (options.useXstack)
2145 emitcode ("movx", "a,@%s", r->name);
2146 emitcode ("mov", "psw,a");
2147 emitcode ("dec", "%s", r->name);
2151 emitcode ("pop", "psw");
2155 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2157 if (options.useXstack)
2159 emitcode ("movx", "a,@%s", r->name);
2160 emitcode ("mov", "(%s+%d),a",
2161 regs8051[i].base, 8 * bank + regs8051[i].offset);
2162 emitcode ("dec", "%s", r->name);
2166 emitcode ("pop", "(%s+%d)",
2167 regs8051[i].base, 8 * bank + regs8051[i].offset);
2170 if (options.useXstack)
2172 emitcode ("mov", "_spx,%s", r->name);
2177 freeAsmop (NULL, aop, ic, TRUE);
2181 /*-----------------------------------------------------------------*/
2182 /* saveRBank - saves an entire register bank on the stack */
2183 /*-----------------------------------------------------------------*/
2185 saveRBank (int bank, iCode * ic, bool pushPsw)
2191 if (options.useXstack)
2195 /* Assume r0 is available for use. */
2196 r = mcs51_regWithIdx (R0_IDX);;
2201 r = getFreePtr (ic, &aop, FALSE);
2203 emitcode ("mov", "%s,_spx", r->name);
2206 for (i = 0; i < mcs51_nRegs; i++)
2208 if (options.useXstack)
2210 emitcode ("inc", "%s", r->name);
2211 emitcode ("mov", "a,(%s+%d)",
2212 regs8051[i].base, 8 * bank + regs8051[i].offset);
2213 emitcode ("movx", "@%s,a", r->name);
2216 emitcode ("push", "(%s+%d)",
2217 regs8051[i].base, 8 * bank + regs8051[i].offset);
2222 if (options.useXstack)
2224 emitcode ("mov", "a,psw");
2225 emitcode ("movx", "@%s,a", r->name);
2226 emitcode ("inc", "%s", r->name);
2227 emitcode ("mov", "_spx,%s", r->name);
2232 emitcode ("push", "psw");
2235 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2240 freeAsmop (NULL, aop, ic, TRUE);
2249 /*-----------------------------------------------------------------*/
2250 /* genSend - gen code for SEND */
2251 /*-----------------------------------------------------------------*/
2252 static void genSend(set *sendSet)
2257 for (sic = setFirstItem (sendSet); sic;
2258 sic = setNextItem (sendSet)) {
2259 int size, offset = 0;
2260 aopOp (IC_LEFT (sic), sic, FALSE);
2261 size = AOP_SIZE (IC_LEFT (sic));
2263 if (sic->argreg == 1) {
2265 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2267 if (strcmp (l, fReturn[offset]))
2268 emitcode ("mov", "%s,%s", fReturn[offset], l);
2274 emitcode ("mov","b1_%d,%s",rb1_count++,
2275 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2278 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2282 /*-----------------------------------------------------------------*/
2283 /* genCall - generates a call statement */
2284 /*-----------------------------------------------------------------*/
2286 genCall (iCode * ic)
2289 // bool restoreBank = FALSE;
2290 bool swapBanks = FALSE;
2292 D(emitcode("; genCall",""));
2294 dtype = operandType (IC_LEFT (ic));
2295 /* if send set is not empty then assign */
2298 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2299 genSend(reverseSet(_G.sendSet));
2301 genSend(_G.sendSet);
2307 /* if we are calling a not _naked function that is not using
2308 the same register bank then we need to save the
2309 destination registers on the stack */
2310 dtype = operandType (IC_LEFT (ic));
2311 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2312 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2313 !IFFUNC_ISISR (dtype))
2318 /* if caller saves & we have not saved then */
2324 emitcode ("mov", "psw,#0x%02x",
2325 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2329 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2330 OP_SYMBOL (IC_LEFT (ic))->rname :
2331 OP_SYMBOL (IC_LEFT (ic))->name));
2335 emitcode ("mov", "psw,#0x%02x",
2336 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2339 /* if we need assign a result value */
2340 if ((IS_ITEMP (IC_RESULT (ic)) &&
2341 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2342 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2343 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2344 IS_TRUE_SYMOP (IC_RESULT (ic)))
2348 aopOp (IC_RESULT (ic), ic, FALSE);
2351 assignResultValue (IC_RESULT (ic));
2353 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2356 /* adjust the stack for parameters if
2361 if (ic->parmBytes > 3)
2363 emitcode ("mov", "a,%s", spname);
2364 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2365 emitcode ("mov", "%s,a", spname);
2368 for (i = 0; i < ic->parmBytes; i++)
2369 emitcode ("dec", "%s", spname);
2372 /* if we hade saved some registers then unsave them */
2373 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2374 unsaveRegisters (ic);
2376 // /* if register bank was saved then pop them */
2378 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2381 /*-----------------------------------------------------------------*/
2382 /* -10l - generates a call by pointer statement */
2383 /*-----------------------------------------------------------------*/
2385 genPcall (iCode * ic)
2388 symbol *rlbl = newiTempLabel (NULL);
2389 // bool restoreBank=FALSE;
2390 bool swapBanks = FALSE;
2392 D(emitcode("; genPCall",""));
2394 /* if caller saves & we have not saved then */
2398 /* if we are calling a not _naked function that is not using
2399 the same register bank then we need to save the
2400 destination registers on the stack */
2401 dtype = operandType (IC_LEFT (ic))->next;
2402 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2403 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2404 !IFFUNC_ISISR (dtype))
2406 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2407 // restoreBank=TRUE;
2409 // need caution message to user here
2412 /* push the return address on to the stack */
2413 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2414 emitcode ("push", "acc");
2415 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2416 emitcode ("push", "acc");
2418 /* now push the calling address */
2419 aopOp (IC_LEFT (ic), ic, FALSE);
2421 pushSide (IC_LEFT (ic), FPTRSIZE);
2423 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2425 /* if send set is not empty the assign */
2428 genSend(reverseSet(_G.sendSet));
2434 emitcode ("mov", "psw,#0x%02x",
2435 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2439 emitcode ("ret", "");
2440 emitcode ("", "%05d$:", (rlbl->key + 100));
2445 emitcode ("mov", "psw,#0x%02x",
2446 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2449 /* if we need assign a result value */
2450 if ((IS_ITEMP (IC_RESULT (ic)) &&
2451 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2452 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2453 IS_TRUE_SYMOP (IC_RESULT (ic)))
2457 aopOp (IC_RESULT (ic), ic, FALSE);
2460 assignResultValue (IC_RESULT (ic));
2462 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2465 /* adjust the stack for parameters if
2470 if (ic->parmBytes > 3)
2472 emitcode ("mov", "a,%s", spname);
2473 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2474 emitcode ("mov", "%s,a", spname);
2477 for (i = 0; i < ic->parmBytes; i++)
2478 emitcode ("dec", "%s", spname);
2482 // /* if register bank was saved then unsave them */
2484 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2486 /* if we hade saved some registers then
2488 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2489 unsaveRegisters (ic);
2492 /*-----------------------------------------------------------------*/
2493 /* resultRemat - result is rematerializable */
2494 /*-----------------------------------------------------------------*/
2496 resultRemat (iCode * ic)
2498 if (SKIP_IC (ic) || ic->op == IFX)
2501 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2503 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2504 if (sym->remat && !POINTER_SET (ic))
2511 #if defined(__BORLANDC__) || defined(_MSC_VER)
2512 #define STRCASECMP stricmp
2514 #define STRCASECMP strcasecmp
2517 /*-----------------------------------------------------------------*/
2518 /* inExcludeList - return 1 if the string is in exclude Reg list */
2519 /*-----------------------------------------------------------------*/
2521 regsCmp(void *p1, void *p2)
2523 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2527 inExcludeList (char *s)
2529 const char *p = setFirstItem(options.excludeRegsSet);
2531 if (p == NULL || STRCASECMP(p, "none") == 0)
2535 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2538 /*-----------------------------------------------------------------*/
2539 /* genFunction - generated code for function entry */
2540 /*-----------------------------------------------------------------*/
2542 genFunction (iCode * ic)
2544 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2546 bool switchedPSW = FALSE;
2547 int calleesaves_saved_register = -1;
2548 int stackAdjust = sym->stack;
2549 int accIsFree = sym->recvSize < 4;
2550 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2553 /* create the function header */
2554 emitcode (";", "-----------------------------------------");
2555 emitcode (";", " function %s", sym->name);
2556 emitcode (";", "-----------------------------------------");
2558 emitcode ("", "%s:", sym->rname);
2559 ftype = operandType (IC_LEFT (ic));
2560 _G.currentFunc = sym;
2562 if (IFFUNC_ISNAKED(ftype))
2564 emitcode(";", "naked function: no prologue.");
2568 /* here we need to generate the equates for the
2569 register bank if required */
2570 if (FUNC_REGBANK (ftype) != rbank)
2574 rbank = FUNC_REGBANK (ftype);
2575 for (i = 0; i < mcs51_nRegs; i++)
2577 if (strcmp (regs8051[i].base, "0") == 0)
2578 emitcode ("", "%s = 0x%02x",
2580 8 * rbank + regs8051[i].offset);
2582 emitcode ("", "%s = %s + 0x%02x",
2585 8 * rbank + regs8051[i].offset);
2589 /* if this is an interrupt service routine then
2590 save acc, b, dpl, dph */
2591 if (IFFUNC_ISISR (sym->type))
2594 if (!inExcludeList ("acc"))
2595 emitcode ("push", "acc");
2596 if (!inExcludeList ("b"))
2597 emitcode ("push", "b");
2598 if (!inExcludeList ("dpl"))
2599 emitcode ("push", "dpl");
2600 if (!inExcludeList ("dph"))
2601 emitcode ("push", "dph");
2602 /* if this isr has no bank i.e. is going to
2603 run with bank 0 , then we need to save more
2605 if (!FUNC_REGBANK (sym->type))
2608 /* if this function does not call any other
2609 function then we can be economical and
2610 save only those registers that are used */
2611 if (!IFFUNC_HASFCALL(sym->type))
2615 /* if any registers used */
2618 /* save the registers used */
2619 for (i = 0; i < sym->regsUsed->size; i++)
2621 if (bitVectBitValue (sym->regsUsed, i))
2622 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2629 /* this function has a function call. We cannot
2630 determines register usage so we will have to push the
2632 saveRBank (0, ic, FALSE);
2633 if (options.parms_in_bank1) {
2635 for (i=0; i < 8 ; i++ ) {
2636 emitcode ("push","%s",rb1regs[i]);
2643 /* This ISR uses a non-zero bank.
2645 * We assume that the bank is available for our
2648 * However, if this ISR calls a function which uses some
2649 * other bank, we must save that bank entirely.
2651 unsigned long banksToSave = 0;
2653 if (IFFUNC_HASFCALL(sym->type))
2656 #define MAX_REGISTER_BANKS 4
2661 for (i = ic; i; i = i->next)
2663 if (i->op == ENDFUNCTION)
2665 /* we got to the end OK. */
2673 dtype = operandType (IC_LEFT(i));
2675 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2677 /* Mark this bank for saving. */
2678 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2680 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2684 banksToSave |= (1 << FUNC_REGBANK(dtype));
2687 /* And note that we don't need to do it in
2695 /* This is a mess; we have no idea what
2696 * register bank the called function might
2699 * The only thing I can think of to do is
2700 * throw a warning and hope.
2702 werror(W_FUNCPTR_IN_USING_ISR);
2706 if (banksToSave && options.useXstack)
2708 /* Since we aren't passing it an ic,
2709 * saveRBank will assume r0 is available to abuse.
2711 * So switch to our (trashable) bank now, so
2712 * the caller's R0 isn't trashed.
2714 emitcode ("push", "psw");
2715 emitcode ("mov", "psw,#0x%02x",
2716 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2720 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2722 if (banksToSave & (1 << ix))
2724 saveRBank(ix, NULL, FALSE);
2728 // TODO: this needs a closer look
2729 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2732 /* Set the register bank to the desired value if nothing else */
2733 /* has done so yet. */
2736 emitcode ("push", "psw");
2737 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2742 /* This is a non-ISR function. The caller has already switched register */
2743 /* banks, if necessary, so just handle the callee-saves option. */
2745 /* if callee-save to be used for this function
2746 then save the registers being used in this function */
2747 if (IFFUNC_CALLEESAVES(sym->type))
2751 /* if any registers used */
2754 /* save the registers used */
2755 for (i = 0; i < sym->regsUsed->size; i++)
2757 if (bitVectBitValue (sym->regsUsed, i))
2759 /* remember one saved register for later usage */
2760 if (calleesaves_saved_register < 0)
2761 calleesaves_saved_register = i;
2762 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2771 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2774 if (options.useXstack)
2777 emitcode ("push", "acc");
2778 emitcode ("mov", "r0,%s", spname);
2779 emitcode ("mov", "a,_bp");
2780 emitcode ("movx", "@r0,a");
2781 emitcode ("inc", "%s", spname);
2783 emitcode ("pop", "acc");
2787 /* set up the stack */
2788 emitcode ("push", "_bp"); /* save the callers stack */
2790 emitcode ("mov", "_bp,%s", spname);
2793 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2794 /* before setting up the stack frame completely. */
2795 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2797 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2801 if (rsym && rsym->regType == REG_CND)
2803 if (rsym && (rsym->accuse || rsym->ruonly))
2805 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2806 rsym = rsym->usl.spillLoc;
2809 /* If the RECEIVE operand immediately spills to the first entry on the */
2810 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2811 /* rather than the usual @r0/r1 machinations. */
2812 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2816 _G.current_iCode = ric;
2817 D(emitcode ("; genReceive",""));
2818 for (ofs=0; ofs < sym->recvSize; ofs++)
2820 if (!strcmp (fReturn[ofs], "a"))
2821 emitcode ("push", "acc");
2823 emitcode ("push", fReturn[ofs]);
2825 stackAdjust -= sym->recvSize;
2828 assert (stackAdjust>=0);
2831 _G.current_iCode = ic;
2835 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2836 /* to free up the accumulator. */
2837 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2841 _G.current_iCode = ric;
2842 D(emitcode ("; genReceive",""));
2843 for (ofs=0; ofs < sym->recvSize; ofs++)
2845 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2847 _G.current_iCode = ic;
2853 /* adjust the stack for the function */
2857 int i = stackAdjust;
2859 werror (W_STACK_OVERFLOW, sym->name);
2861 if (i > 3 && accIsFree)
2864 emitcode ("mov", "a,sp");
2865 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2866 emitcode ("mov", "sp,a");
2871 /* The accumulator is not free, so we will need another register */
2872 /* to clobber. No need to worry about a possible conflict with */
2873 /* the above early RECEIVE optimizations since they would have */
2874 /* freed the accumulator if they were generated. */
2876 if (IFFUNC_CALLEESAVES(sym->type))
2878 /* if it's a callee-saves function we need a saved register */
2879 if (calleesaves_saved_register >= 0)
2881 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2882 emitcode ("mov", "a,sp");
2883 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2884 emitcode ("mov", "sp,a");
2885 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2888 /* do it the hard way */
2890 emitcode ("inc", "sp");
2894 /* not callee-saves, we can clobber r0 */
2895 emitcode ("mov", "r0,a");
2896 emitcode ("mov", "a,sp");
2897 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2898 emitcode ("mov", "sp,a");
2899 emitcode ("mov", "a,r0");
2904 emitcode ("inc", "sp");
2911 emitcode ("push", "acc");
2912 emitcode ("mov", "a,_spx");
2913 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2914 emitcode ("mov", "_spx,a");
2916 emitcode ("pop", "acc");
2919 /* if critical function then turn interrupts off */
2920 if (IFFUNC_ISCRITICAL (ftype))
2922 symbol *tlbl = newiTempLabel (NULL);
2923 emitcode ("setb", "c");
2924 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2925 emitcode ("clr", "c");
2926 emitcode ("", "%05d$:", (tlbl->key + 100));
2927 emitcode ("push", "psw"); /* save old ea via c in psw */
2931 /*-----------------------------------------------------------------*/
2932 /* genEndFunction - generates epilogue for functions */
2933 /*-----------------------------------------------------------------*/
2935 genEndFunction (iCode * ic)
2937 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2938 lineNode *lnp = lineCurr;
2940 bitVect *regsUsedPrologue;
2941 bitVect *regsUnneeded;
2944 _G.currentFunc = NULL;
2945 if (IFFUNC_ISNAKED(sym->type))
2947 emitcode(";", "naked function: no epilogue.");
2948 if (options.debug && currFunc)
2949 debugFile->writeEndFunction (currFunc, ic, 0);
2953 if (IFFUNC_ISCRITICAL (sym->type))
2955 emitcode ("pop", "psw"); /* restore ea via c in psw */
2956 emitcode ("mov", "ea,c");
2959 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2961 emitcode ("mov", "%s,_bp", spname);
2964 /* if use external stack but some variables were
2965 added to the local stack then decrement the
2967 if (options.useXstack && sym->stack)
2969 emitcode ("mov", "a,sp");
2970 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2971 emitcode ("mov", "sp,a");
2975 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2977 if (options.useXstack)
2979 emitcode ("mov", "r0,%s", spname);
2980 emitcode ("movx", "a,@r0");
2981 emitcode ("mov", "_bp,a");
2982 emitcode ("dec", "%s", spname);
2986 emitcode ("pop", "_bp");
2990 /* restore the register bank */
2991 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2993 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2994 || !options.useXstack)
2996 /* Special case of ISR using non-zero bank with useXstack
2999 emitcode ("pop", "psw");
3003 if (IFFUNC_ISISR (sym->type))
3006 /* now we need to restore the registers */
3007 /* if this isr has no bank i.e. is going to
3008 run with bank 0 , then we need to save more
3010 if (!FUNC_REGBANK (sym->type))
3012 /* if this function does not call any other
3013 function then we can be economical and
3014 save only those registers that are used */
3015 if (!IFFUNC_HASFCALL(sym->type))
3019 /* if any registers used */
3022 /* save the registers used */
3023 for (i = sym->regsUsed->size; i >= 0; i--)
3025 if (bitVectBitValue (sym->regsUsed, i))
3026 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3032 if (options.parms_in_bank1) {
3034 for (i = 7 ; i >= 0 ; i-- ) {
3035 emitcode ("pop","%s",rb1regs[i]);
3038 /* this function has a function call cannot
3039 determines register usage so we will have to pop the
3041 unsaveRBank (0, ic, FALSE);
3046 /* This ISR uses a non-zero bank.
3048 * Restore any register banks saved by genFunction
3051 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3054 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3056 if (savedBanks & (1 << ix))
3058 unsaveRBank(ix, NULL, FALSE);
3062 if (options.useXstack)
3064 /* Restore bank AFTER calling unsaveRBank,
3065 * since it can trash r0.
3067 emitcode ("pop", "psw");
3071 if (!inExcludeList ("dph"))
3072 emitcode ("pop", "dph");
3073 if (!inExcludeList ("dpl"))
3074 emitcode ("pop", "dpl");
3075 if (!inExcludeList ("b"))
3076 emitcode ("pop", "b");
3077 if (!inExcludeList ("acc"))
3078 emitcode ("pop", "acc");
3080 /* if debug then send end of function */
3081 if (options.debug && currFunc)
3083 debugFile->writeEndFunction (currFunc, ic, 1);
3086 emitcode ("reti", "");
3090 if (IFFUNC_CALLEESAVES(sym->type))
3094 /* if any registers used */
3097 /* save the registers used */
3098 for (i = sym->regsUsed->size; i >= 0; i--)
3100 if (bitVectBitValue (sym->regsUsed, i) ||
3101 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3102 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3105 else if (mcs51_ptrRegReq)
3107 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3108 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3113 /* if debug then send end of function */
3114 if (options.debug && currFunc)
3116 debugFile->writeEndFunction (currFunc, ic, 1);
3119 emitcode ("ret", "");
3122 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3125 /* If this was an interrupt handler using bank 0 that called another */
3126 /* function, then all registers must be saved; nothing to optimized. */
3127 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3128 && !FUNC_REGBANK(sym->type))
3131 /* There are no push/pops to optimize if not callee-saves or ISR */
3132 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3135 /* If there were stack parameters, we cannot optimize without also */
3136 /* fixing all of the stack offsets; this is too dificult to consider. */
3137 if (FUNC_HASSTACKPARM(sym->type))
3140 /* Compute the registers actually used */
3141 regsUsed = newBitVect (mcs51_nRegs);
3142 regsUsedPrologue = newBitVect (mcs51_nRegs);
3145 if (lnp->ic && lnp->ic->op == FUNCTION)
3146 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3148 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3150 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3151 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3158 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3159 && !bitVectBitValue (regsUsed, CND_IDX))
3161 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3162 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3163 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3164 bitVectUnSetBit (regsUsed, CND_IDX);
3167 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3169 /* If this was an interrupt handler that called another function */
3170 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3171 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3173 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3174 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3175 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3176 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3177 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3180 /* Remove the unneeded push/pops */
3181 regsUnneeded = newBitVect (mcs51_nRegs);
3184 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3186 if (!strncmp(lnp->line, "push", 4))
3188 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3189 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3191 connectLine (lnp->prev, lnp->next);
3192 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3195 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3197 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3198 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3200 connectLine (lnp->prev, lnp->next);
3201 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3208 for (idx = 0; idx < regsUnneeded->size; idx++)
3209 if (bitVectBitValue (regsUnneeded, idx))
3210 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3212 freeBitVect (regsUnneeded);
3213 freeBitVect (regsUsed);
3214 freeBitVect (regsUsedPrologue);
3217 /*-----------------------------------------------------------------*/
3218 /* genRet - generate code for return statement */
3219 /*-----------------------------------------------------------------*/
3223 int size, offset = 0, pushed = 0;
3225 D(emitcode ("; genRet",""));
3227 /* if we have no return value then
3228 just generate the "ret" */
3232 /* we have something to return then
3233 move the return value into place */
3234 aopOp (IC_LEFT (ic), ic, FALSE);
3235 size = AOP_SIZE (IC_LEFT (ic));
3240 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3243 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3245 emitcode ("push", "%s", l);
3250 l = aopGet (AOP (IC_LEFT (ic)), offset,
3252 if (strcmp (fReturn[offset], l))
3253 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3262 if (strcmp (fReturn[pushed], "a"))
3263 emitcode ("pop", fReturn[pushed]);
3265 emitcode ("pop", "acc");
3268 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3271 /* generate a jump to the return label
3272 if the next is not the return statement */
3273 if (!(ic->next && ic->next->op == LABEL &&
3274 IC_LABEL (ic->next) == returnLabel))
3276 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3280 /*-----------------------------------------------------------------*/
3281 /* genLabel - generates a label */
3282 /*-----------------------------------------------------------------*/
3284 genLabel (iCode * ic)
3286 /* special case never generate */
3287 if (IC_LABEL (ic) == entryLabel)
3290 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3293 /*-----------------------------------------------------------------*/
3294 /* genGoto - generates a ljmp */
3295 /*-----------------------------------------------------------------*/
3297 genGoto (iCode * ic)
3299 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3302 /*-----------------------------------------------------------------*/
3303 /* findLabelBackwards: walks back through the iCode chain looking */
3304 /* for the given label. Returns number of iCode instructions */
3305 /* between that label and given ic. */
3306 /* Returns zero if label not found. */
3307 /*-----------------------------------------------------------------*/
3309 findLabelBackwards (iCode * ic, int key)
3318 /* If we have any pushes or pops, we cannot predict the distance.
3319 I don't like this at all, this should be dealt with in the
3321 if (ic->op == IPUSH || ic->op == IPOP) {
3325 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3334 /*-----------------------------------------------------------------*/
3335 /* genPlusIncr :- does addition with increment if possible */
3336 /*-----------------------------------------------------------------*/
3338 genPlusIncr (iCode * ic)
3340 unsigned int icount;
3341 unsigned int size = getDataSize (IC_RESULT (ic));
3343 /* will try to generate an increment */
3344 /* if the right side is not a literal
3346 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3349 /* if the literal value of the right hand side
3350 is greater than 4 then it is not worth it */
3351 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3354 D(emitcode ("; genPlusIncr",""));
3356 /* if increment >=16 bits in register or direct space */
3357 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3358 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3366 /* If the next instruction is a goto and the goto target
3367 * is < 10 instructions previous to this, we can generate
3368 * jumps straight to that target.
3370 if (ic->next && ic->next->op == GOTO
3371 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3372 && labelRange <= 10)
3374 emitcode (";", "tail increment optimized");
3375 tlbl = IC_LABEL (ic->next);
3380 tlbl = newiTempLabel (NULL);
3383 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3384 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3385 IS_AOP_PREG (IC_RESULT (ic)))
3386 emitcode ("cjne", "%s,#0x00,%05d$",
3387 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3391 emitcode ("clr", "a");
3392 emitcode ("cjne", "a,%s,%05d$",
3393 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3397 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3400 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3401 IS_AOP_PREG (IC_RESULT (ic)))
3402 emitcode ("cjne", "%s,#0x00,%05d$",
3403 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3406 emitcode ("cjne", "a,%s,%05d$",
3407 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3410 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3414 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3415 IS_AOP_PREG (IC_RESULT (ic)))
3416 emitcode ("cjne", "%s,#0x00,%05d$",
3417 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3421 emitcode ("cjne", "a,%s,%05d$",
3422 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3425 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3430 emitcode ("", "%05d$:", tlbl->key + 100);
3435 /* if the sizes are greater than 1 then we cannot */
3436 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3437 AOP_SIZE (IC_LEFT (ic)) > 1)
3440 /* we can if the aops of the left & result match or
3441 if they are in registers and the registers are the
3443 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3448 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3449 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3450 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3456 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3465 /*-----------------------------------------------------------------*/
3466 /* outBitAcc - output a bit in acc */
3467 /*-----------------------------------------------------------------*/
3469 outBitAcc (operand * result)
3471 symbol *tlbl = newiTempLabel (NULL);
3472 /* if the result is a bit */
3473 if (AOP_TYPE (result) == AOP_CRY)
3475 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3479 emitcode ("jz", "%05d$", tlbl->key + 100);
3480 emitcode ("mov", "a,%s", one);
3481 emitcode ("", "%05d$:", tlbl->key + 100);
3486 /*-----------------------------------------------------------------*/
3487 /* genPlusBits - generates code for addition of two bits */
3488 /*-----------------------------------------------------------------*/
3490 genPlusBits (iCode * ic)
3492 D(emitcode ("; genPlusBits",""));
3494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3496 symbol *lbl = newiTempLabel (NULL);
3497 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3498 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3499 emitcode ("cpl", "c");
3500 emitcode ("", "%05d$:", (lbl->key + 100));
3501 outBitC (IC_RESULT (ic));
3505 emitcode ("clr", "a");
3506 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3507 emitcode ("rlc", "a");
3508 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3509 emitcode ("addc", "a,#0x00");
3510 outAcc (IC_RESULT (ic));
3515 /* This is the original version of this code.
3517 * This is being kept around for reference,
3518 * because I am not entirely sure I got it right...
3521 adjustArithmeticResult (iCode * ic)
3523 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3524 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3525 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3526 aopPut (AOP (IC_RESULT (ic)),
3527 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3529 isOperandVolatile (IC_RESULT (ic), FALSE));
3531 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3532 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3533 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3534 aopPut (AOP (IC_RESULT (ic)),
3535 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3537 isOperandVolatile (IC_RESULT (ic), FALSE));
3539 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3540 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3541 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3542 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3543 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3546 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3547 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3551 /* This is the pure and virtuous version of this code.
3552 * I'm pretty certain it's right, but not enough to toss the old
3556 adjustArithmeticResult (iCode * ic)
3558 if (opIsGptr (IC_RESULT (ic)) &&
3559 opIsGptr (IC_LEFT (ic)) &&
3560 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3562 aopPut (AOP (IC_RESULT (ic)),
3563 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3565 isOperandVolatile (IC_RESULT (ic), FALSE));
3568 if (opIsGptr (IC_RESULT (ic)) &&
3569 opIsGptr (IC_RIGHT (ic)) &&
3570 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3572 aopPut (AOP (IC_RESULT (ic)),
3573 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3575 isOperandVolatile (IC_RESULT (ic), FALSE));
3578 if (opIsGptr (IC_RESULT (ic)) &&
3579 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3580 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3581 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3582 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3585 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3586 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3591 /*-----------------------------------------------------------------*/
3592 /* genPlus - generates code for addition */
3593 /*-----------------------------------------------------------------*/
3595 genPlus (iCode * ic)
3597 int size, offset = 0;
3600 asmop *leftOp, *rightOp;
3603 /* special cases :- */
3605 D(emitcode ("; genPlus",""));
3607 aopOp (IC_LEFT (ic), ic, FALSE);
3608 aopOp (IC_RIGHT (ic), ic, FALSE);
3609 aopOp (IC_RESULT (ic), ic, TRUE);
3611 /* if literal, literal on the right or
3612 if left requires ACC or right is already
3614 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3615 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3616 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3618 operand *t = IC_RIGHT (ic);
3619 IC_RIGHT (ic) = IC_LEFT (ic);
3623 /* if both left & right are in bit
3625 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3626 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3632 /* if left in bit space & right literal */
3633 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3634 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3636 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3637 /* if result in bit space */
3638 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3640 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3641 emitcode ("cpl", "c");
3642 outBitC (IC_RESULT (ic));
3646 size = getDataSize (IC_RESULT (ic));
3649 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3650 emitcode ("addc", "a,#00");
3651 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3657 /* if I can do an increment instead
3658 of add then GOOD for ME */
3659 if (genPlusIncr (ic) == TRUE)
3662 size = getDataSize (IC_RESULT (ic));
3663 leftOp = AOP(IC_LEFT(ic));
3664 rightOp = AOP(IC_RIGHT(ic));
3667 /* if this is an add for an array access
3668 at a 256 byte boundary */
3670 && AOP_TYPE (op) == AOP_IMMD
3672 && IS_SPEC (OP_SYM_ETYPE (op))
3673 && SPEC_ABSA (OP_SYM_ETYPE (op))
3674 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3677 D(emitcode ("; genPlus aligned array",""));
3678 aopPut (AOP (IC_RESULT (ic)),
3679 aopGet (rightOp, 0, FALSE, FALSE),
3681 isOperandVolatile (IC_RESULT (ic), FALSE));
3683 if( 1 == getDataSize (IC_RIGHT (ic)) )
3685 aopPut (AOP (IC_RESULT (ic)),
3686 aopGet (leftOp, 1, FALSE, FALSE),
3688 isOperandVolatile (IC_RESULT (ic), FALSE));
3692 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3693 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3694 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3699 /* if the lower bytes of a literal are zero skip the addition */
3700 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3702 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3703 (skip_bytes+1 < size))
3708 D(emitcode ("; genPlus shortcut",""));
3713 if( offset >= skip_bytes )
3715 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3718 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3720 emitcode("xch", "a,b");
3721 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3722 emitcode (add, "a,b");
3725 else if (aopGetUsesAcc (leftOp, offset))
3727 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3728 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3732 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3733 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3735 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3736 add = "addc"; /* further adds must propagate carry */
3740 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3741 isOperandVolatile (IC_RESULT (ic), FALSE))
3744 aopPut (AOP (IC_RESULT (ic)),
3745 aopGet (leftOp, offset, FALSE, FALSE),
3747 isOperandVolatile (IC_RESULT (ic), FALSE));
3753 adjustArithmeticResult (ic);
3756 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3757 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3758 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3761 /*-----------------------------------------------------------------*/
3762 /* genMinusDec :- does subtraction with deccrement if possible */
3763 /*-----------------------------------------------------------------*/
3765 genMinusDec (iCode * ic)
3767 unsigned int icount;
3768 unsigned int size = getDataSize (IC_RESULT (ic));
3770 /* will try to generate an increment */
3771 /* if the right side is not a literal
3773 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3776 /* if the literal value of the right hand side
3777 is greater than 4 then it is not worth it */
3778 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3781 D(emitcode ("; genMinusDec",""));
3783 /* if decrement >=16 bits in register or direct space */
3784 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3785 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3793 /* If the next instruction is a goto and the goto target
3794 * is <= 10 instructions previous to this, we can generate
3795 * jumps straight to that target.
3797 if (ic->next && ic->next->op == GOTO
3798 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3799 && labelRange <= 10)
3801 emitcode (";", "tail decrement optimized");
3802 tlbl = IC_LABEL (ic->next);
3807 tlbl = newiTempLabel (NULL);
3811 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3812 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3813 IS_AOP_PREG (IC_RESULT (ic)))
3814 emitcode ("cjne", "%s,#0xff,%05d$"
3815 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3819 emitcode ("mov", "a,#0xff");
3820 emitcode ("cjne", "a,%s,%05d$"
3821 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3824 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3827 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3828 IS_AOP_PREG (IC_RESULT (ic)))
3829 emitcode ("cjne", "%s,#0xff,%05d$"
3830 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3834 emitcode ("cjne", "a,%s,%05d$"
3835 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3838 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3842 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3843 IS_AOP_PREG (IC_RESULT (ic)))
3844 emitcode ("cjne", "%s,#0xff,%05d$"
3845 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3849 emitcode ("cjne", "a,%s,%05d$"
3850 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3853 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3857 emitcode ("", "%05d$:", tlbl->key + 100);
3862 /* if the sizes are greater than 1 then we cannot */
3863 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3864 AOP_SIZE (IC_LEFT (ic)) > 1)
3867 /* we can if the aops of the left & result match or
3868 if they are in registers and the registers are the
3870 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3874 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3882 /*-----------------------------------------------------------------*/
3883 /* addSign - complete with sign */
3884 /*-----------------------------------------------------------------*/
3886 addSign (operand * result, int offset, int sign)
3888 int size = (getDataSize (result) - offset);
3893 emitcode ("rlc", "a");
3894 emitcode ("subb", "a,acc");
3896 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3900 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3904 /*-----------------------------------------------------------------*/
3905 /* genMinusBits - generates code for subtraction of two bits */
3906 /*-----------------------------------------------------------------*/
3908 genMinusBits (iCode * ic)
3910 symbol *lbl = newiTempLabel (NULL);
3912 D(emitcode ("; genMinusBits",""));
3914 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3916 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3917 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3918 emitcode ("cpl", "c");
3919 emitcode ("", "%05d$:", (lbl->key + 100));
3920 outBitC (IC_RESULT (ic));
3924 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3925 emitcode ("subb", "a,acc");
3926 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3927 emitcode ("inc", "a");
3928 emitcode ("", "%05d$:", (lbl->key + 100));
3929 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3930 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3934 /*-----------------------------------------------------------------*/
3935 /* genMinus - generates code for subtraction */
3936 /*-----------------------------------------------------------------*/
3938 genMinus (iCode * ic)
3940 int size, offset = 0;
3942 D(emitcode ("; genMinus",""));
3944 aopOp (IC_LEFT (ic), ic, FALSE);
3945 aopOp (IC_RIGHT (ic), ic, FALSE);
3946 aopOp (IC_RESULT (ic), ic, TRUE);
3948 /* special cases :- */
3949 /* if both left & right are in bit space */
3950 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3951 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3957 /* if I can do an decrement instead
3958 of subtract then GOOD for ME */
3959 if (genMinusDec (ic) == TRUE)
3962 size = getDataSize (IC_RESULT (ic));
3964 /* if literal, add a,#-lit, else normal subb */
3965 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3967 unsigned long lit = 0L;
3969 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3974 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3975 /* first add without previous c */
3977 if (!size && lit== (unsigned long) -1) {
3978 emitcode ("dec", "a");
3980 emitcode ("add", "a,#0x%02x",
3981 (unsigned int) (lit & 0x0FFL));
3984 emitcode ("addc", "a,#0x%02x",
3985 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3987 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3992 asmop *leftOp, *rightOp;
3994 leftOp = AOP(IC_LEFT(ic));
3995 rightOp = AOP(IC_RIGHT(ic));
3999 if (aopGetUsesAcc(rightOp, offset)) {
4000 if (aopGetUsesAcc(leftOp, offset)) {
4003 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4005 emitcode ("mov", "b,a");
4008 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4009 emitcode ("subb", "a,b");
4012 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4013 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4015 emitcode( "setb", "c");
4017 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4018 emitcode("cpl", "a");
4021 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4024 emitcode ("subb", "a,%s",
4025 aopGet(rightOp, offset, FALSE, TRUE));
4028 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4033 adjustArithmeticResult (ic);
4036 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4037 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4042 /*-----------------------------------------------------------------*/
4043 /* genMultbits :- multiplication of bits */
4044 /*-----------------------------------------------------------------*/
4046 genMultbits (operand * left,
4050 D(emitcode ("; genMultbits",""));
4052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4053 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4057 /*-----------------------------------------------------------------*/
4058 /* genMultOneByte : 8*8=8/16 bit multiplication */
4059 /*-----------------------------------------------------------------*/
4061 genMultOneByte (operand * left,
4066 int size = AOP_SIZE (result);
4067 bool runtimeSign, compiletimeSign;
4068 bool lUnsigned, rUnsigned, pushedB;
4070 D(emitcode ("; genMultOneByte",""));
4072 if (size < 1 || size > 2)
4074 /* this should never happen */
4075 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4076 AOP_SIZE(result), __FILE__, lineno);
4080 /* (if two literals: the value is computed before) */
4081 /* if one literal, literal on the right */
4082 if (AOP_TYPE (left) == AOP_LIT)
4087 /* emitcode (";", "swapped left and right"); */
4089 /* if no literal, unsigned on the right: shorter code */
4090 if ( AOP_TYPE (right) != AOP_LIT
4091 && SPEC_USIGN (getSpec (operandType (left))))
4098 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4099 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4103 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4104 no need to take care about the signedness! */
4105 || (lUnsigned && rUnsigned))
4107 /* just an unsigned 8 * 8 = 8 multiply
4109 /* emitcode (";","unsigned"); */
4110 /* TODO: check for accumulator clash between left & right aops? */
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 /* moving to accumulator first helps peepholes */
4115 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4116 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4120 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4121 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4124 emitcode ("mul", "ab");
4125 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4127 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4133 /* we have to do a signed multiply */
4134 /* emitcode (";", "signed"); */
4136 /* now sign adjust for both left & right */
4138 /* let's see what's needed: */
4139 /* apply negative sign during runtime */
4140 runtimeSign = FALSE;
4141 /* negative sign from literals */
4142 compiletimeSign = FALSE;
4146 if (AOP_TYPE(left) == AOP_LIT)
4148 /* signed literal */
4149 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4151 compiletimeSign = TRUE;
4154 /* signed but not literal */
4160 if (AOP_TYPE(right) == AOP_LIT)
4162 /* signed literal */
4163 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4165 compiletimeSign ^= TRUE;
4168 /* signed but not literal */
4172 /* initialize F0, which stores the runtime sign */
4175 if (compiletimeSign)
4176 emitcode ("setb", "F0"); /* set sign flag */
4178 emitcode ("clr", "F0"); /* reset sign flag */
4181 /* save the signs of the operands */
4182 if (AOP_TYPE(right) == AOP_LIT)
4184 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4186 if (!rUnsigned && val < 0)
4187 emitcode ("mov", "b,#0x%02x", -val);
4189 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4191 else /* ! literal */
4193 if (rUnsigned) /* emitcode (";", "signed"); */
4195 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4198 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4199 lbl = newiTempLabel (NULL);
4200 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4201 emitcode ("cpl", "F0"); /* complement sign flag */
4202 emitcode ("cpl", "a"); /* 2's complement */
4203 emitcode ("inc", "a");
4204 emitcode ("", "%05d$:", (lbl->key + 100));
4205 emitcode ("mov", "b,a");
4209 if (AOP_TYPE(left) == AOP_LIT)
4211 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4213 if (!lUnsigned && val < 0)
4214 emitcode ("mov", "a,#0x%02x", -val);
4216 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4218 else /* ! literal */
4220 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4224 lbl = newiTempLabel (NULL);
4225 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4226 emitcode ("cpl", "F0"); /* complement sign flag */
4227 emitcode ("cpl", "a"); /* 2's complement */
4228 emitcode ("inc", "a");
4229 emitcode ("", "%05d$:", (lbl->key + 100));
4233 /* now the multiplication */
4234 emitcode ("mul", "ab");
4235 if (runtimeSign || compiletimeSign)
4237 lbl = newiTempLabel (NULL);
4239 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4240 emitcode ("cpl", "a"); /* lsb 2's complement */
4242 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4245 emitcode ("add", "a,#1"); /* this sets carry flag */
4246 emitcode ("xch", "a,b");
4247 emitcode ("cpl", "a"); /* msb 2's complement */
4248 emitcode ("addc", "a,#0");
4249 emitcode ("xch", "a,b");
4251 emitcode ("", "%05d$:", (lbl->key + 100));
4253 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4255 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4260 /*-----------------------------------------------------------------*/
4261 /* genMult - generates code for multiplication */
4262 /*-----------------------------------------------------------------*/
4264 genMult (iCode * ic)
4266 operand *left = IC_LEFT (ic);
4267 operand *right = IC_RIGHT (ic);
4268 operand *result = IC_RESULT (ic);
4270 D(emitcode ("; genMult",""));
4272 /* assign the amsops */
4273 aopOp (left, ic, FALSE);
4274 aopOp (right, ic, FALSE);
4275 aopOp (result, ic, TRUE);
4277 /* special cases first */
4279 if (AOP_TYPE (left) == AOP_CRY &&
4280 AOP_TYPE (right) == AOP_CRY)
4282 genMultbits (left, right, result);
4286 /* if both are of size == 1 */
4287 #if 0 // one of them can be a sloc shared with the result
4288 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4290 if (getSize(operandType(left)) == 1 &&
4291 getSize(operandType(right)) == 1)
4294 genMultOneByte (left, right, result);
4298 /* should have been converted to function call */
4299 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4300 getSize(OP_SYMBOL(right)->type));
4304 freeAsmop (result, NULL, ic, TRUE);
4305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4306 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 /*-----------------------------------------------------------------*/
4310 /* genDivbits :- division of bits */
4311 /*-----------------------------------------------------------------*/
4313 genDivbits (operand * left,
4320 D(emitcode ("; genDivbits",""));
4324 /* the result must be bit */
4325 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4326 l = aopGet (AOP (left), 0, FALSE, FALSE);
4330 emitcode ("div", "ab");
4331 emitcode ("rrc", "a");
4335 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4338 /*-----------------------------------------------------------------*/
4339 /* genDivOneByte : 8 bit division */
4340 /*-----------------------------------------------------------------*/
4342 genDivOneByte (operand * left,
4346 bool lUnsigned, rUnsigned, pushedB;
4347 bool runtimeSign, compiletimeSign;
4351 D(emitcode ("; genDivOneByte",""));
4353 /* Why is it necessary that genDivOneByte() can return an int result?
4356 volatile unsigned char uc;
4357 volatile signed char sc1, sc2;
4370 In all cases a one byte result would overflow, the following cast to int
4371 would return the wrong result.
4373 Two possible solution:
4374 a) cast operands to int, if ((unsigned) / (signed)) or
4375 ((signed) / (signed))
4376 b) return an 16 bit signed int; this is what we're doing here!
4379 size = AOP_SIZE (result) - 1;
4381 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4382 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4386 /* signed or unsigned */
4387 if (lUnsigned && rUnsigned)
4389 /* unsigned is easy */
4390 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4391 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4392 emitcode ("div", "ab");
4393 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4395 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4401 /* signed is a little bit more difficult */
4403 /* now sign adjust for both left & right */
4405 /* let's see what's needed: */
4406 /* apply negative sign during runtime */
4407 runtimeSign = FALSE;
4408 /* negative sign from literals */
4409 compiletimeSign = FALSE;
4413 if (AOP_TYPE(left) == AOP_LIT)
4415 /* signed literal */
4416 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4418 compiletimeSign = TRUE;
4421 /* signed but not literal */
4427 if (AOP_TYPE(right) == AOP_LIT)
4429 /* signed literal */
4430 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4432 compiletimeSign ^= TRUE;
4435 /* signed but not literal */
4439 /* initialize F0, which stores the runtime sign */
4442 if (compiletimeSign)
4443 emitcode ("setb", "F0"); /* set sign flag */
4445 emitcode ("clr", "F0"); /* reset sign flag */
4448 /* save the signs of the operands */
4449 if (AOP_TYPE(right) == AOP_LIT)
4451 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4453 if (!rUnsigned && val < 0)
4454 emitcode ("mov", "b,#0x%02x", -val);
4456 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4458 else /* ! literal */
4461 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4464 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4465 lbl = newiTempLabel (NULL);
4466 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4467 emitcode ("cpl", "F0"); /* complement sign flag */
4468 emitcode ("cpl", "a"); /* 2's complement */
4469 emitcode ("inc", "a");
4470 emitcode ("", "%05d$:", (lbl->key + 100));
4471 emitcode ("mov", "b,a");
4475 if (AOP_TYPE(left) == AOP_LIT)
4477 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4479 if (!lUnsigned && val < 0)
4480 emitcode ("mov", "a,#0x%02x", -val);
4482 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4484 else /* ! literal */
4486 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4490 lbl = newiTempLabel (NULL);
4491 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4492 emitcode ("cpl", "F0"); /* complement sign flag */
4493 emitcode ("cpl", "a"); /* 2's complement */
4494 emitcode ("inc", "a");
4495 emitcode ("", "%05d$:", (lbl->key + 100));
4499 /* now the division */
4500 emitcode ("div", "ab");
4502 if (runtimeSign || compiletimeSign)
4504 lbl = newiTempLabel (NULL);
4506 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4507 emitcode ("cpl", "a"); /* lsb 2's complement */
4508 emitcode ("inc", "a");
4509 emitcode ("", "%05d$:", (lbl->key + 100));
4511 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4514 /* msb is 0x00 or 0xff depending on the sign */
4517 emitcode ("mov", "c,F0");
4518 emitcode ("subb", "a,acc");
4520 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4522 else /* compiletimeSign */
4524 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4529 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4531 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4537 /*-----------------------------------------------------------------*/
4538 /* genDiv - generates code for division */
4539 /*-----------------------------------------------------------------*/
4543 operand *left = IC_LEFT (ic);
4544 operand *right = IC_RIGHT (ic);
4545 operand *result = IC_RESULT (ic);
4547 D(emitcode ("; genDiv",""));
4549 /* assign the amsops */
4550 aopOp (left, ic, FALSE);
4551 aopOp (right, ic, FALSE);
4552 aopOp (result, ic, TRUE);
4554 /* special cases first */
4556 if (AOP_TYPE (left) == AOP_CRY &&
4557 AOP_TYPE (right) == AOP_CRY)
4559 genDivbits (left, right, result);
4563 /* if both are of size == 1 */
4564 if (AOP_SIZE (left) == 1 &&
4565 AOP_SIZE (right) == 1)
4567 genDivOneByte (left, right, result);
4571 /* should have been converted to function call */
4574 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4576 freeAsmop (result, NULL, ic, TRUE);
4579 /*-----------------------------------------------------------------*/
4580 /* genModbits :- modulus of bits */
4581 /*-----------------------------------------------------------------*/
4583 genModbits (operand * left,
4590 D(emitcode ("; genModbits",""));
4594 /* the result must be bit */
4595 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4596 l = aopGet (AOP (left), 0, FALSE, FALSE);
4600 emitcode ("div", "ab");
4601 emitcode ("mov", "a,b");
4602 emitcode ("rrc", "a");
4606 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4609 /*-----------------------------------------------------------------*/
4610 /* genModOneByte : 8 bit modulus */
4611 /*-----------------------------------------------------------------*/
4613 genModOneByte (operand * left,
4617 bool lUnsigned, rUnsigned, pushedB;
4618 bool runtimeSign, compiletimeSign;
4622 D(emitcode ("; genModOneByte",""));
4624 size = AOP_SIZE (result) - 1;
4626 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4627 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4631 /* signed or unsigned */
4632 if (lUnsigned && rUnsigned)
4634 /* unsigned is easy */
4635 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4636 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4637 emitcode ("div", "ab");
4638 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4640 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4646 /* signed is a little bit more difficult */
4648 /* now sign adjust for both left & right */
4650 /* modulus: sign of the right operand has no influence on the result! */
4651 if (AOP_TYPE(right) == AOP_LIT)
4653 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4655 if (!rUnsigned && val < 0)
4656 emitcode ("mov", "b,#0x%02x", -val);
4658 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4660 else /* not literal */
4663 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4666 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4667 lbl = newiTempLabel (NULL);
4668 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4669 emitcode ("cpl", "a"); /* 2's complement */
4670 emitcode ("inc", "a");
4671 emitcode ("", "%05d$:", (lbl->key + 100));
4672 emitcode ("mov", "b,a");
4676 /* let's see what's needed: */
4677 /* apply negative sign during runtime */
4678 runtimeSign = FALSE;
4679 /* negative sign from literals */
4680 compiletimeSign = FALSE;
4682 /* sign adjust left side */
4683 if (AOP_TYPE(left) == AOP_LIT)
4685 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4687 if (!lUnsigned && val < 0)
4689 compiletimeSign = TRUE; /* set sign flag */
4690 emitcode ("mov", "a,#0x%02x", -val);
4693 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4695 else /* ! literal */
4697 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4702 emitcode ("clr", "F0"); /* clear sign flag */
4704 lbl = newiTempLabel (NULL);
4705 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4706 emitcode ("setb", "F0"); /* set sign flag */
4707 emitcode ("cpl", "a"); /* 2's complement */
4708 emitcode ("inc", "a");
4709 emitcode ("", "%05d$:", (lbl->key + 100));
4713 /* now the modulus */
4714 emitcode ("div", "ab");
4716 if (runtimeSign || compiletimeSign)
4718 emitcode ("mov", "a,b");
4719 lbl = newiTempLabel (NULL);
4721 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4722 emitcode ("cpl", "a"); /* 2's complement */
4723 emitcode ("inc", "a");
4724 emitcode ("", "%05d$:", (lbl->key + 100));
4726 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4729 /* msb is 0x00 or 0xff depending on the sign */
4732 emitcode ("mov", "c,F0");
4733 emitcode ("subb", "a,acc");
4735 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4737 else /* compiletimeSign */
4739 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4744 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4746 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4752 /*-----------------------------------------------------------------*/
4753 /* genMod - generates code for division */
4754 /*-----------------------------------------------------------------*/
4758 operand *left = IC_LEFT (ic);
4759 operand *right = IC_RIGHT (ic);
4760 operand *result = IC_RESULT (ic);
4762 D(emitcode ("; genMod",""));
4764 /* assign the amsops */
4765 aopOp (left, ic, FALSE);
4766 aopOp (right, ic, FALSE);
4767 aopOp (result, ic, TRUE);
4769 /* special cases first */
4771 if (AOP_TYPE (left) == AOP_CRY &&
4772 AOP_TYPE (right) == AOP_CRY)
4774 genModbits (left, right, result);
4778 /* if both are of size == 1 */
4779 if (AOP_SIZE (left) == 1 &&
4780 AOP_SIZE (right) == 1)
4782 genModOneByte (left, right, result);
4786 /* should have been converted to function call */
4790 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4791 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4792 freeAsmop (result, NULL, ic, TRUE);
4795 /*-----------------------------------------------------------------*/
4796 /* genIfxJump :- will create a jump depending on the ifx */
4797 /*-----------------------------------------------------------------*/
4799 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4802 symbol *tlbl = newiTempLabel (NULL);
4805 D(emitcode ("; genIfxJump",""));
4807 /* if true label then we jump if condition
4811 jlbl = IC_TRUE (ic);
4812 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4813 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4817 /* false label is present */
4818 jlbl = IC_FALSE (ic);
4819 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4820 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4822 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4823 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4825 emitcode (inst, "%05d$", tlbl->key + 100);
4826 freeForBranchAsmop (result);
4827 freeForBranchAsmop (right);
4828 freeForBranchAsmop (left);
4829 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4830 emitcode ("", "%05d$:", tlbl->key + 100);
4832 /* mark the icode as generated */
4836 /*-----------------------------------------------------------------*/
4837 /* genCmp :- greater or less than comparison */
4838 /*-----------------------------------------------------------------*/
4840 genCmp (operand * left, operand * right,
4841 operand * result, iCode * ifx, int sign, iCode *ic)
4843 int size, offset = 0;
4844 unsigned long lit = 0L;
4847 D(emitcode ("; genCmp",""));
4849 /* if left & right are bit variables */
4850 if (AOP_TYPE (left) == AOP_CRY &&
4851 AOP_TYPE (right) == AOP_CRY)
4853 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4854 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4858 /* subtract right from left if at the
4859 end the carry flag is set then we know that
4860 left is greater than right */
4861 size = max (AOP_SIZE (left), AOP_SIZE (right));
4863 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4864 if ((size == 1) && !sign &&
4865 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4867 symbol *lbl = newiTempLabel (NULL);
4868 emitcode ("cjne", "%s,%s,%05d$",
4869 aopGet (AOP (left), offset, FALSE, FALSE),
4870 aopGet (AOP (right), offset, FALSE, FALSE),
4872 emitcode ("", "%05d$:", lbl->key + 100);
4876 if (AOP_TYPE (right) == AOP_LIT)
4878 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4879 /* optimize if(x < 0) or if(x >= 0) */
4888 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4889 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4891 genIfxJump (ifx, "acc.7", left, right, result);
4892 freeAsmop (right, NULL, ic, TRUE);
4893 freeAsmop (left, NULL, ic, TRUE);
4898 emitcode ("rlc", "a");
4906 bool pushedB = FALSE;
4907 rightInB = aopGetUsesAcc(AOP (right), offset);
4911 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4913 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4914 if (sign && size == 0)
4916 emitcode ("xrl", "a,#0x80");
4917 if (AOP_TYPE (right) == AOP_LIT)
4919 unsigned long lit = (unsigned long)
4920 floatFromVal (AOP (right)->aopu.aop_lit);
4921 emitcode ("subb", "a,#0x%02x",
4922 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4930 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4932 emitcode ("xrl", "b,#0x80");
4933 emitcode ("subb", "a,b");
4939 emitcode ("subb", "a,b");
4941 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4951 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4953 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4959 /* if the result is used in the next
4960 ifx conditional branch then generate
4961 code a little differently */
4963 genIfxJump (ifx, "c", NULL, NULL, result);
4966 /* leave the result in acc */
4970 /*-----------------------------------------------------------------*/
4971 /* genCmpGt :- greater than comparison */
4972 /*-----------------------------------------------------------------*/
4974 genCmpGt (iCode * ic, iCode * ifx)
4976 operand *left, *right, *result;
4977 sym_link *letype, *retype;
4980 D(emitcode ("; genCmpGt",""));
4982 left = IC_LEFT (ic);
4983 right = IC_RIGHT (ic);
4984 result = IC_RESULT (ic);
4986 letype = getSpec (operandType (left));
4987 retype = getSpec (operandType (right));
4988 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4989 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4990 /* assign the amsops */
4991 aopOp (left, ic, FALSE);
4992 aopOp (right, ic, FALSE);
4993 aopOp (result, ic, TRUE);
4995 genCmp (right, left, result, ifx, sign,ic);
4997 freeAsmop (result, NULL, ic, TRUE);
5000 /*-----------------------------------------------------------------*/
5001 /* genCmpLt - less than comparisons */
5002 /*-----------------------------------------------------------------*/
5004 genCmpLt (iCode * ic, iCode * ifx)
5006 operand *left, *right, *result;
5007 sym_link *letype, *retype;
5010 D(emitcode ("; genCmpLt",""));
5012 left = IC_LEFT (ic);
5013 right = IC_RIGHT (ic);
5014 result = IC_RESULT (ic);
5016 letype = getSpec (operandType (left));
5017 retype = getSpec (operandType (right));
5018 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5019 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5020 /* assign the amsops */
5021 aopOp (left, ic, FALSE);
5022 aopOp (right, ic, FALSE);
5023 aopOp (result, ic, TRUE);
5025 genCmp (left, right, result, ifx, sign,ic);
5027 freeAsmop (result, NULL, ic, TRUE);
5030 /*-----------------------------------------------------------------*/
5031 /* gencjneshort - compare and jump if not equal */
5032 /*-----------------------------------------------------------------*/
5034 gencjneshort (operand * left, operand * right, symbol * lbl)
5036 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5038 unsigned long lit = 0L;
5040 /* if the left side is a literal or
5041 if the right is in a pointer register and left
5043 if ((AOP_TYPE (left) == AOP_LIT) ||
5044 (AOP_TYPE (left) == AOP_IMMD) ||
5045 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5052 if (AOP_TYPE (right) == AOP_LIT)
5053 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5055 /* if the right side is a literal then anything goes */
5056 if (AOP_TYPE (right) == AOP_LIT &&
5057 AOP_TYPE (left) != AOP_DIR &&
5058 AOP_TYPE (left) != AOP_IMMD)
5062 emitcode ("cjne", "%s,%s,%05d$",
5063 aopGet (AOP (left), offset, FALSE, FALSE),
5064 aopGet (AOP (right), offset, FALSE, FALSE),
5070 /* if the right side is in a register or in direct space or
5071 if the left is a pointer register & right is not */
5072 else if (AOP_TYPE (right) == AOP_REG ||
5073 AOP_TYPE (right) == AOP_DIR ||
5074 AOP_TYPE (right) == AOP_LIT ||
5075 AOP_TYPE (right) == AOP_IMMD ||
5076 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5077 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5081 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5082 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5083 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5084 emitcode ("jnz", "%05d$", lbl->key + 100);
5086 emitcode ("cjne", "a,%s,%05d$",
5087 aopGet (AOP (right), offset, FALSE, TRUE),
5094 /* right is a pointer reg need both a & b */
5098 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5099 wassertl(!_G.BInUse, "B was in use");
5100 l = aopGet (AOP (left), offset, FALSE, FALSE);
5101 if (strcmp (l, "b"))
5102 emitcode ("mov", "b,%s", l);
5103 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5104 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5110 /*-----------------------------------------------------------------*/
5111 /* gencjne - compare and jump if not equal */
5112 /*-----------------------------------------------------------------*/
5114 gencjne (operand * left, operand * right, symbol * lbl)
5116 symbol *tlbl = newiTempLabel (NULL);
5118 gencjneshort (left, right, lbl);
5120 emitcode ("mov", "a,%s", one);
5121 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5122 emitcode ("", "%05d$:", lbl->key + 100);
5123 emitcode ("clr", "a");
5124 emitcode ("", "%05d$:", tlbl->key + 100);
5127 /*-----------------------------------------------------------------*/
5128 /* genCmpEq - generates code for equal to */
5129 /*-----------------------------------------------------------------*/
5131 genCmpEq (iCode * ic, iCode * ifx)
5133 operand *left, *right, *result;
5135 D(emitcode ("; genCmpEq",""));
5137 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5138 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5139 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5141 /* if literal, literal on the right or
5142 if the right is in a pointer register and left
5144 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5145 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5147 operand *t = IC_RIGHT (ic);
5148 IC_RIGHT (ic) = IC_LEFT (ic);
5152 if (ifx && !AOP_SIZE (result))
5155 /* if they are both bit variables */
5156 if (AOP_TYPE (left) == AOP_CRY &&
5157 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5159 if (AOP_TYPE (right) == AOP_LIT)
5161 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5164 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5165 emitcode ("cpl", "c");
5169 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5173 emitcode ("clr", "c");
5175 /* AOP_TYPE(right) == AOP_CRY */
5179 symbol *lbl = newiTempLabel (NULL);
5180 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5181 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5182 emitcode ("cpl", "c");
5183 emitcode ("", "%05d$:", (lbl->key + 100));
5185 /* if true label then we jump if condition
5187 tlbl = newiTempLabel (NULL);
5190 emitcode ("jnc", "%05d$", tlbl->key + 100);
5191 freeForBranchAsmop (result);
5192 freeForBranchAsmop (right);
5193 freeForBranchAsmop (left);
5194 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5198 emitcode ("jc", "%05d$", tlbl->key + 100);
5199 freeForBranchAsmop (result);
5200 freeForBranchAsmop (right);
5201 freeForBranchAsmop (left);
5202 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5204 emitcode ("", "%05d$:", tlbl->key + 100);
5208 tlbl = newiTempLabel (NULL);
5209 gencjneshort (left, right, tlbl);
5212 freeForBranchAsmop (result);
5213 freeForBranchAsmop (right);
5214 freeForBranchAsmop (left);
5215 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5216 emitcode ("", "%05d$:", tlbl->key + 100);
5220 symbol *lbl = newiTempLabel (NULL);
5221 emitcode ("sjmp", "%05d$", lbl->key + 100);
5222 emitcode ("", "%05d$:", tlbl->key + 100);
5223 freeForBranchAsmop (result);
5224 freeForBranchAsmop (right);
5225 freeForBranchAsmop (left);
5226 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5227 emitcode ("", "%05d$:", lbl->key + 100);
5230 /* mark the icode as generated */
5235 /* if they are both bit variables */
5236 if (AOP_TYPE (left) == AOP_CRY &&
5237 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5239 if (AOP_TYPE (right) == AOP_LIT)
5241 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5244 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5245 emitcode ("cpl", "c");
5249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5253 emitcode ("clr", "c");
5255 /* AOP_TYPE(right) == AOP_CRY */
5259 symbol *lbl = newiTempLabel (NULL);
5260 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5261 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5262 emitcode ("cpl", "c");
5263 emitcode ("", "%05d$:", (lbl->key + 100));
5266 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5273 genIfxJump (ifx, "c", left, right, result);
5276 /* if the result is used in an arithmetic operation
5277 then put the result in place */
5282 gencjne (left, right, newiTempLabel (NULL));
5283 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5285 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5290 genIfxJump (ifx, "a", left, right, result);
5293 /* if the result is used in an arithmetic operation
5294 then put the result in place */
5295 if (AOP_TYPE (result) != AOP_CRY)
5297 /* leave the result in acc */
5301 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5303 freeAsmop (result, NULL, ic, TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* ifxForOp - returns the icode containing the ifx for operand */
5308 /*-----------------------------------------------------------------*/
5310 ifxForOp (operand * op, iCode * ic)
5312 /* if true symbol then needs to be assigned */
5313 if (IS_TRUE_SYMOP (op))
5316 /* if this has register type condition and
5317 the next instruction is ifx with the same operand
5318 and live to of the operand is upto the ifx only then */
5320 ic->next->op == IFX &&
5321 IC_COND (ic->next)->key == op->key &&
5322 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5328 /*-----------------------------------------------------------------*/
5329 /* hasInc - operand is incremented before any other use */
5330 /*-----------------------------------------------------------------*/
5332 hasInc (operand *op, iCode *ic,int osize)
5334 sym_link *type = operandType(op);
5335 sym_link *retype = getSpec (type);
5336 iCode *lic = ic->next;
5339 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5340 if (!IS_SYMOP(op)) return NULL;
5342 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5343 if (IS_AGGREGATE(type->next)) return NULL;
5344 if (osize != (isize = getSize(type->next))) return NULL;
5347 /* if operand of the form op = op + <sizeof *op> */
5348 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5349 isOperandEqual(IC_RESULT(lic),op) &&
5350 isOperandLiteral(IC_RIGHT(lic)) &&
5351 operandLitValue(IC_RIGHT(lic)) == isize) {
5354 /* if the operand used or deffed */
5355 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5358 /* if GOTO or IFX */
5359 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5365 /*-----------------------------------------------------------------*/
5366 /* genAndOp - for && operation */
5367 /*-----------------------------------------------------------------*/
5369 genAndOp (iCode * ic)
5371 operand *left, *right, *result;
5374 D(emitcode ("; genAndOp",""));
5376 /* note here that && operations that are in an
5377 if statement are taken away by backPatchLabels
5378 only those used in arthmetic operations remain */
5379 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5380 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5381 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5383 /* if both are bit variables */
5384 if (AOP_TYPE (left) == AOP_CRY &&
5385 AOP_TYPE (right) == AOP_CRY)
5387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5388 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5393 tlbl = newiTempLabel (NULL);
5395 emitcode ("jz", "%05d$", tlbl->key + 100);
5397 emitcode ("", "%05d$:", tlbl->key + 100);
5401 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5402 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403 freeAsmop (result, NULL, ic, TRUE);
5407 /*-----------------------------------------------------------------*/
5408 /* genOrOp - for || operation */
5409 /*-----------------------------------------------------------------*/
5411 genOrOp (iCode * ic)
5413 operand *left, *right, *result;
5416 D(emitcode ("; genOrOp",""));
5418 /* note here that || operations that are in an
5419 if statement are taken away by backPatchLabels
5420 only those used in arthmetic operations remain */
5421 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5422 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5423 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5425 /* if both are bit variables */
5426 if (AOP_TYPE (left) == AOP_CRY &&
5427 AOP_TYPE (right) == AOP_CRY)
5429 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5430 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5435 tlbl = newiTempLabel (NULL);
5437 emitcode ("jnz", "%05d$", tlbl->key + 100);
5439 emitcode ("", "%05d$:", tlbl->key + 100);
5443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5444 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5445 freeAsmop (result, NULL, ic, TRUE);
5448 /*-----------------------------------------------------------------*/
5449 /* isLiteralBit - test if lit == 2^n */
5450 /*-----------------------------------------------------------------*/
5452 isLiteralBit (unsigned long lit)
5454 unsigned long pw[32] =
5455 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5456 0x100L, 0x200L, 0x400L, 0x800L,
5457 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5458 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5459 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5460 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5461 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5464 for (idx = 0; idx < 32; idx++)
5470 /*-----------------------------------------------------------------*/
5471 /* continueIfTrue - */
5472 /*-----------------------------------------------------------------*/
5474 continueIfTrue (iCode * ic)
5477 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5481 /*-----------------------------------------------------------------*/
5483 /*-----------------------------------------------------------------*/
5485 jumpIfTrue (iCode * ic)
5488 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5492 /*-----------------------------------------------------------------*/
5493 /* jmpTrueOrFalse - */
5494 /*-----------------------------------------------------------------*/
5496 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5498 // ugly but optimized by peephole
5501 symbol *nlbl = newiTempLabel (NULL);
5502 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5503 emitcode ("", "%05d$:", tlbl->key + 100);
5504 freeForBranchAsmop (result);
5505 freeForBranchAsmop (right);
5506 freeForBranchAsmop (left);
5507 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5508 emitcode ("", "%05d$:", nlbl->key + 100);
5512 freeForBranchAsmop (result);
5513 freeForBranchAsmop (right);
5514 freeForBranchAsmop (left);
5515 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5516 emitcode ("", "%05d$:", tlbl->key + 100);
5521 /*-----------------------------------------------------------------*/
5522 /* genAnd - code for and */
5523 /*-----------------------------------------------------------------*/
5525 genAnd (iCode * ic, iCode * ifx)
5527 operand *left, *right, *result;
5528 int size, offset = 0;
5529 unsigned long lit = 0L;
5533 D(emitcode ("; genAnd",""));
5535 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5536 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5537 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5540 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5542 AOP_TYPE (left), AOP_TYPE (right));
5543 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5545 AOP_SIZE (left), AOP_SIZE (right));
5548 /* if left is a literal & right is not then exchange them */
5549 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5550 AOP_NEEDSACC (left))
5552 operand *tmp = right;
5557 /* if result = right then exchange left and right */
5558 if (sameRegs (AOP (result), AOP (right)))
5560 operand *tmp = right;
5565 /* if right is bit then exchange them */
5566 if (AOP_TYPE (right) == AOP_CRY &&
5567 AOP_TYPE (left) != AOP_CRY)
5569 operand *tmp = right;
5573 if (AOP_TYPE (right) == AOP_LIT)
5574 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5576 size = AOP_SIZE (result);
5579 // result = bit & yy;
5580 if (AOP_TYPE (left) == AOP_CRY)
5582 // c = bit & literal;
5583 if (AOP_TYPE (right) == AOP_LIT)
5587 if (size && sameRegs (AOP (result), AOP (left)))
5590 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5595 if (size && (AOP_TYPE (result) == AOP_CRY))
5597 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5600 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5605 emitcode ("clr", "c");
5610 if (AOP_TYPE (right) == AOP_CRY)
5613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5614 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5619 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5621 emitcode ("rrc", "a");
5622 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5630 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5631 genIfxJump (ifx, "c", left, right, result);
5635 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5636 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5637 if ((AOP_TYPE (right) == AOP_LIT) &&
5638 (AOP_TYPE (result) == AOP_CRY) &&
5639 (AOP_TYPE (left) != AOP_CRY))
5641 int posbit = isLiteralBit (lit);
5646 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5649 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5655 SNPRINTF (buffer, sizeof(buffer),
5656 "acc.%d", posbit & 0x07);
5657 genIfxJump (ifx, buffer, left, right, result);
5660 {// what is this case? just found it in ds390/gen.c
5661 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5668 symbol *tlbl = newiTempLabel (NULL);
5669 int sizel = AOP_SIZE (left);
5671 emitcode ("setb", "c");
5674 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5676 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5678 if ((posbit = isLiteralBit (bytelit)) != 0)
5679 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5682 if (bytelit != 0x0FFL)
5683 emitcode ("anl", "a,%s",
5684 aopGet (AOP (right), offset, FALSE, TRUE));
5685 emitcode ("jnz", "%05d$", tlbl->key + 100);
5690 // bit = left & literal
5693 emitcode ("clr", "c");
5694 emitcode ("", "%05d$:", tlbl->key + 100);
5696 // if(left & literal)
5700 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5702 emitcode ("", "%05d$:", tlbl->key + 100);
5710 /* if left is same as result */
5711 if (sameRegs (AOP (result), AOP (left)))
5713 for (; size--; offset++)
5715 if (AOP_TYPE (right) == AOP_LIT)
5717 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5718 if (bytelit == 0x0FF)
5720 /* dummy read of volatile operand */
5721 if (isOperandVolatile (left, FALSE))
5722 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5726 else if (bytelit == 0)
5728 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5730 else if (IS_AOP_PREG (result))
5732 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5733 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5734 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5737 emitcode ("anl", "%s,%s",
5738 aopGet (AOP (left), offset, FALSE, TRUE),
5739 aopGet (AOP (right), offset, FALSE, FALSE));
5743 if (AOP_TYPE (left) == AOP_ACC)
5744 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5747 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5748 if (IS_AOP_PREG (result))
5750 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5751 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5754 emitcode ("anl", "%s,a",
5755 aopGet (AOP (left), offset, FALSE, TRUE));
5762 // left & result in different registers
5763 if (AOP_TYPE (result) == AOP_CRY)
5766 // if(size), result in bit
5767 // if(!size && ifx), conditional oper: if(left & right)
5768 symbol *tlbl = newiTempLabel (NULL);
5769 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5771 emitcode ("setb", "c");
5774 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5775 emitcode ("anl", "a,%s",
5776 aopGet (AOP (right), offset, FALSE, FALSE));
5778 if (AOP_TYPE(left)==AOP_ACC) {
5779 bool pushedB = pushB ();
5780 emitcode("mov", "b,a");
5781 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5782 emitcode("anl", "a,b");
5785 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5786 emitcode ("anl", "a,%s",
5787 aopGet (AOP (left), offset, FALSE, FALSE));
5790 emitcode ("jnz", "%05d$", tlbl->key + 100);
5796 emitcode ("", "%05d$:", tlbl->key + 100);
5800 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5802 emitcode ("", "%05d$:", tlbl->key + 100);
5806 for (; (size--); offset++)
5809 // result = left & right
5810 if (AOP_TYPE (right) == AOP_LIT)
5812 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5813 if (bytelit == 0x0FF)
5815 aopPut (AOP (result),
5816 aopGet (AOP (left), offset, FALSE, FALSE),
5818 isOperandVolatile (result, FALSE));
5821 else if (bytelit == 0)
5823 /* dummy read of volatile operand */
5824 if (isOperandVolatile (left, FALSE))
5825 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5826 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5830 // faster than result <- left, anl result,right
5831 // and better if result is SFR
5832 if (AOP_TYPE (left) == AOP_ACC)
5833 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5836 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5837 emitcode ("anl", "a,%s",
5838 aopGet (AOP (left), offset, FALSE, FALSE));
5840 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5846 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5847 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848 freeAsmop (result, NULL, ic, TRUE);
5851 /*-----------------------------------------------------------------*/
5852 /* genOr - code for or */
5853 /*-----------------------------------------------------------------*/
5855 genOr (iCode * ic, iCode * ifx)
5857 operand *left, *right, *result;
5858 int size, offset = 0;
5859 unsigned long lit = 0L;
5862 D(emitcode ("; genOr",""));
5864 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5865 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5866 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5869 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5871 AOP_TYPE (left), AOP_TYPE (right));
5872 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5874 AOP_SIZE (left), AOP_SIZE (right));
5877 /* if left is a literal & right is not then exchange them */
5878 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5879 AOP_NEEDSACC (left))
5881 operand *tmp = right;
5886 /* if result = right then exchange them */
5887 if (sameRegs (AOP (result), AOP (right)))
5889 operand *tmp = right;
5894 /* if right is bit then exchange them */
5895 if (AOP_TYPE (right) == AOP_CRY &&
5896 AOP_TYPE (left) != AOP_CRY)
5898 operand *tmp = right;
5902 if (AOP_TYPE (right) == AOP_LIT)
5903 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5905 size = AOP_SIZE (result);
5909 if (AOP_TYPE (left) == AOP_CRY)
5911 if (AOP_TYPE (right) == AOP_LIT)
5913 // c = bit | literal;
5916 // lit != 0 => result = 1
5917 if (AOP_TYPE (result) == AOP_CRY)
5920 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5922 continueIfTrue (ifx);
5925 emitcode ("setb", "c");
5929 // lit == 0 => result = left
5930 if (size && sameRegs (AOP (result), AOP (left)))
5932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5937 if (AOP_TYPE (right) == AOP_CRY)
5940 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5941 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5946 symbol *tlbl = newiTempLabel (NULL);
5947 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5948 emitcode ("setb", "c");
5949 emitcode ("jb", "%s,%05d$",
5950 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5952 emitcode ("jnz", "%05d$", tlbl->key + 100);
5953 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5955 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5961 emitcode ("", "%05d$:", tlbl->key + 100);
5970 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5971 genIfxJump (ifx, "c", left, right, result);
5975 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5976 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5977 if ((AOP_TYPE (right) == AOP_LIT) &&
5978 (AOP_TYPE (result) == AOP_CRY) &&
5979 (AOP_TYPE (left) != AOP_CRY))
5985 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5987 continueIfTrue (ifx);
5992 // lit = 0, result = boolean(left)
5994 emitcode ("setb", "c");
5998 symbol *tlbl = newiTempLabel (NULL);
5999 emitcode ("jnz", "%05d$", tlbl->key + 100);
6001 emitcode ("", "%05d$:", tlbl->key + 100);
6005 genIfxJump (ifx, "a", left, right, result);
6013 /* if left is same as result */
6014 if (sameRegs (AOP (result), AOP (left)))
6016 for (; size--; offset++)
6018 if (AOP_TYPE (right) == AOP_LIT)
6020 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6023 /* dummy read of volatile operand */
6024 if (isOperandVolatile (left, FALSE))
6025 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6029 else if (bytelit == 0x0FF)
6031 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6033 else if (IS_AOP_PREG (left))
6035 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6036 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6037 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6041 emitcode ("orl", "%s,%s",
6042 aopGet (AOP (left), offset, FALSE, TRUE),
6043 aopGet (AOP (right), offset, FALSE, FALSE));
6048 if (AOP_TYPE (left) == AOP_ACC)
6049 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6052 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6053 if (IS_AOP_PREG (left))
6055 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6056 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6060 emitcode ("orl", "%s,a",
6061 aopGet (AOP (left), offset, FALSE, TRUE));
6069 // left & result in different registers
6070 if (AOP_TYPE (result) == AOP_CRY)
6073 // if(size), result in bit
6074 // if(!size && ifx), conditional oper: if(left | right)
6075 symbol *tlbl = newiTempLabel (NULL);
6076 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6078 emitcode ("setb", "c");
6081 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6082 emitcode ("orl", "a,%s",
6083 aopGet (AOP (right), offset, FALSE, FALSE));
6085 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6086 emitcode ("orl", "a,%s",
6087 aopGet (AOP (left), offset, FALSE, FALSE));
6089 emitcode ("jnz", "%05d$", tlbl->key + 100);
6095 emitcode ("", "%05d$:", tlbl->key + 100);
6099 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6101 emitcode ("", "%05d$:", tlbl->key + 100);
6105 for (; (size--); offset++)
6108 // result = left | right
6109 if (AOP_TYPE (right) == AOP_LIT)
6111 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6114 aopPut (AOP (result),
6115 aopGet (AOP (left), offset, FALSE, FALSE),
6117 isOperandVolatile (result, FALSE));
6120 else if (bytelit == 0x0FF)
6122 /* dummy read of volatile operand */
6123 if (isOperandVolatile (left, FALSE))
6124 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6125 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6129 // faster than result <- left, anl result,right
6130 // and better if result is SFR
6131 if (AOP_TYPE (left) == AOP_ACC)
6132 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6135 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6136 emitcode ("orl", "a,%s",
6137 aopGet (AOP (left), offset, FALSE, FALSE));
6139 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6145 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6146 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6147 freeAsmop (result, NULL, ic, TRUE);
6150 /*-----------------------------------------------------------------*/
6151 /* genXor - code for xclusive or */
6152 /*-----------------------------------------------------------------*/
6154 genXor (iCode * ic, iCode * ifx)
6156 operand *left, *right, *result;
6157 int size, offset = 0;
6158 unsigned long lit = 0L;
6161 D(emitcode ("; genXor",""));
6163 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6164 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6165 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6168 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6170 AOP_TYPE (left), AOP_TYPE (right));
6171 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6173 AOP_SIZE (left), AOP_SIZE (right));
6176 /* if left is a literal & right is not ||
6177 if left needs acc & right does not */
6178 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6179 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6181 operand *tmp = right;
6186 /* if result = right then exchange them */
6187 if (sameRegs (AOP (result), AOP (right)))
6189 operand *tmp = right;
6194 /* if right is bit then exchange them */
6195 if (AOP_TYPE (right) == AOP_CRY &&
6196 AOP_TYPE (left) != AOP_CRY)
6198 operand *tmp = right;
6202 if (AOP_TYPE (right) == AOP_LIT)
6203 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6205 size = AOP_SIZE (result);
6209 if (AOP_TYPE (left) == AOP_CRY)
6211 if (AOP_TYPE (right) == AOP_LIT)
6213 // c = bit & literal;
6216 // lit>>1 != 0 => result = 1
6217 if (AOP_TYPE (result) == AOP_CRY)
6220 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6222 continueIfTrue (ifx);
6225 emitcode ("setb", "c");
6232 // lit == 0, result = left
6233 if (size && sameRegs (AOP (result), AOP (left)))
6235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6239 // lit == 1, result = not(left)
6240 if (size && sameRegs (AOP (result), AOP (left)))
6242 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6247 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6248 emitcode ("cpl", "c");
6257 symbol *tlbl = newiTempLabel (NULL);
6258 if (AOP_TYPE (right) == AOP_CRY)
6261 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6265 int sizer = AOP_SIZE (right);
6267 // if val>>1 != 0, result = 1
6268 emitcode ("setb", "c");
6271 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6273 // test the msb of the lsb
6274 emitcode ("anl", "a,#0xfe");
6275 emitcode ("jnz", "%05d$", tlbl->key + 100);
6279 emitcode ("rrc", "a");
6281 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6282 emitcode ("cpl", "c");
6283 emitcode ("", "%05d$:", (tlbl->key + 100));
6290 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6291 genIfxJump (ifx, "c", left, right, result);
6295 /* if left is same as result */
6296 if (sameRegs (AOP (result), AOP (left)))
6298 for (; size--; offset++)
6300 if (AOP_TYPE (right) == AOP_LIT)
6302 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6305 /* dummy read of volatile operand */
6306 if (isOperandVolatile (left, FALSE))
6307 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6311 else if (IS_AOP_PREG (left))
6313 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6314 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6315 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6319 emitcode ("xrl", "%s,%s",
6320 aopGet (AOP (left), offset, FALSE, TRUE),
6321 aopGet (AOP (right), offset, FALSE, FALSE));
6326 if (AOP_TYPE (left) == AOP_ACC)
6327 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6331 if (IS_AOP_PREG (left))
6333 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6334 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6337 emitcode ("xrl", "%s,a",
6338 aopGet (AOP (left), offset, FALSE, TRUE));
6345 // left & result in different registers
6346 if (AOP_TYPE (result) == AOP_CRY)
6349 // if(size), result in bit
6350 // if(!size && ifx), conditional oper: if(left ^ right)
6351 symbol *tlbl = newiTempLabel (NULL);
6352 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6354 emitcode ("setb", "c");
6357 if ((AOP_TYPE (right) == AOP_LIT) &&
6358 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6360 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6364 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6365 emitcode ("xrl", "a,%s",
6366 aopGet (AOP (right), offset, FALSE, FALSE));
6368 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6369 emitcode ("xrl", "a,%s",
6370 aopGet (AOP (left), offset, FALSE, FALSE));
6373 emitcode ("jnz", "%05d$", tlbl->key + 100);
6379 emitcode ("", "%05d$:", tlbl->key + 100);
6383 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6387 for (; (size--); offset++)
6390 // result = left & right
6391 if (AOP_TYPE (right) == AOP_LIT)
6393 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6396 aopPut (AOP (result),
6397 aopGet (AOP (left), offset, FALSE, FALSE),
6399 isOperandVolatile (result, FALSE));
6403 // faster than result <- left, anl result,right
6404 // and better if result is SFR
6405 if (AOP_TYPE (left) == AOP_ACC)
6406 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6409 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6410 emitcode ("xrl", "a,%s",
6411 aopGet (AOP (left), offset, FALSE, TRUE));
6413 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6421 freeAsmop (result, NULL, ic, TRUE);
6424 /*-----------------------------------------------------------------*/
6425 /* genInline - write the inline code out */
6426 /*-----------------------------------------------------------------*/
6428 genInline (iCode * ic)
6430 char *buffer, *bp, *bp1;
6432 D(emitcode ("; genInline",""));
6434 _G.inLine += (!options.asmpeep);
6436 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6437 strcpy (buffer, IC_INLINE (ic));
6439 /* emit each line as a code */
6450 /* Add \n for labels, not dirs such as c:\mydir */
6451 if ( (*bp == ':') && (isspace(bp[1])) )
6465 /* emitcode("",buffer); */
6466 _G.inLine -= (!options.asmpeep);
6469 /*-----------------------------------------------------------------*/
6470 /* genRRC - rotate right with carry */
6471 /*-----------------------------------------------------------------*/
6475 operand *left, *result;
6476 int size, offset = 0;
6479 D(emitcode ("; genRRC",""));
6481 /* rotate right with carry */
6482 left = IC_LEFT (ic);
6483 result = IC_RESULT (ic);
6484 aopOp (left, ic, FALSE);
6485 aopOp (result, ic, FALSE);
6487 /* move it to the result */
6488 size = AOP_SIZE (result);
6490 if (size == 1) { /* special case for 1 byte */
6491 l = aopGet (AOP (left), offset, FALSE, FALSE);
6493 emitcode ("rr", "a");
6499 l = aopGet (AOP (left), offset, FALSE, FALSE);
6501 emitcode ("rrc", "a");
6502 if (AOP_SIZE (result) > 1)
6503 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6505 /* now we need to put the carry into the
6506 highest order byte of the result */
6507 if (AOP_SIZE (result) > 1)
6509 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6512 emitcode ("mov", "acc.7,c");
6514 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6515 freeAsmop (left, NULL, ic, TRUE);
6516 freeAsmop (result, NULL, ic, TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* genRLC - generate code for rotate left with carry */
6521 /*-----------------------------------------------------------------*/
6525 operand *left, *result;
6526 int size, offset = 0;
6529 D(emitcode ("; genRLC",""));
6531 /* rotate right with carry */
6532 left = IC_LEFT (ic);
6533 result = IC_RESULT (ic);
6534 aopOp (left, ic, FALSE);
6535 aopOp (result, ic, FALSE);
6537 /* move it to the result */
6538 size = AOP_SIZE (result);
6542 l = aopGet (AOP (left), offset, FALSE, FALSE);
6544 if (size == 0) { /* special case for 1 byte */
6548 emitcode ("add", "a,acc");
6549 if (AOP_SIZE (result) > 1)
6550 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6553 l = aopGet (AOP (left), offset, FALSE, FALSE);
6555 emitcode ("rlc", "a");
6556 if (AOP_SIZE (result) > 1)
6557 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6560 /* now we need to put the carry into the
6561 highest order byte of the result */
6562 if (AOP_SIZE (result) > 1)
6564 l = aopGet (AOP (result), 0, FALSE, FALSE);
6567 emitcode ("mov", "acc.0,c");
6569 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6570 freeAsmop (left, NULL, ic, TRUE);
6571 freeAsmop (result, NULL, ic, TRUE);
6574 /*-----------------------------------------------------------------*/
6575 /* genGetHbit - generates code get highest order bit */
6576 /*-----------------------------------------------------------------*/
6578 genGetHbit (iCode * ic)
6580 operand *left, *result;
6582 D(emitcode ("; genGetHbit",""));
6584 left = IC_LEFT (ic);
6585 result = IC_RESULT (ic);
6586 aopOp (left, ic, FALSE);
6587 aopOp (result, ic, FALSE);
6589 /* get the highest order byte into a */
6590 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6591 if (AOP_TYPE (result) == AOP_CRY)
6593 emitcode ("rlc", "a");
6598 emitcode ("rl", "a");
6599 emitcode ("anl", "a,#0x01");
6604 freeAsmop (left, NULL, ic, TRUE);
6605 freeAsmop (result, NULL, ic, TRUE);
6608 /*-----------------------------------------------------------------*/
6609 /* genSwap - generates code to swap nibbles or bytes */
6610 /*-----------------------------------------------------------------*/
6612 genSwap (iCode * ic)
6614 operand *left, *result;
6616 D(emitcode ("; genSwap",""));
6618 left = IC_LEFT (ic);
6619 result = IC_RESULT (ic);
6620 aopOp (left, ic, FALSE);
6621 aopOp (result, ic, FALSE);
6623 switch (AOP_SIZE (left))
6625 case 1: /* swap nibbles in byte */
6626 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6627 emitcode ("swap", "a");
6628 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6630 case 2: /* swap bytes in word */
6631 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6633 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6634 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6635 0, isOperandVolatile (result, FALSE));
6636 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6638 else if (operandsEqu (left, result))
6641 bool pushedB = FALSE, leftInB = FALSE;
6643 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6644 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6647 emitcode ("mov", "b,a");
6651 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6652 0, isOperandVolatile (result, FALSE));
6653 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6660 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6661 0, isOperandVolatile (result, FALSE));
6662 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6663 1, isOperandVolatile (result, FALSE));
6667 wassertl(FALSE, "unsupported SWAP operand size");
6670 freeAsmop (left, NULL, ic, TRUE);
6671 freeAsmop (result, NULL, ic, TRUE);
6675 /*-----------------------------------------------------------------*/
6676 /* AccRol - rotate left accumulator by known count */
6677 /*-----------------------------------------------------------------*/
6679 AccRol (int shCount)
6681 shCount &= 0x0007; // shCount : 0..7
6688 emitcode ("rl", "a");
6691 emitcode ("rl", "a");
6692 emitcode ("rl", "a");
6695 emitcode ("swap", "a");
6696 emitcode ("rr", "a");
6699 emitcode ("swap", "a");
6702 emitcode ("swap", "a");
6703 emitcode ("rl", "a");
6706 emitcode ("rr", "a");
6707 emitcode ("rr", "a");
6710 emitcode ("rr", "a");
6715 /*-----------------------------------------------------------------*/
6716 /* AccLsh - left shift accumulator by known count */
6717 /*-----------------------------------------------------------------*/
6719 AccLsh (int shCount)
6724 emitcode ("add", "a,acc");
6725 else if (shCount == 2)
6727 emitcode ("add", "a,acc");
6728 emitcode ("add", "a,acc");
6732 /* rotate left accumulator */
6734 /* and kill the lower order bits */
6735 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6740 /*-----------------------------------------------------------------*/
6741 /* AccRsh - right shift accumulator by known count */
6742 /*-----------------------------------------------------------------*/
6744 AccRsh (int shCount)
6751 emitcode ("rrc", "a");
6755 /* rotate right accumulator */
6756 AccRol (8 - shCount);
6757 /* and kill the higher order bits */
6758 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6763 /*-----------------------------------------------------------------*/
6764 /* AccSRsh - signed right shift accumulator by known count */
6765 /*-----------------------------------------------------------------*/
6767 AccSRsh (int shCount)
6774 emitcode ("mov", "c,acc.7");
6775 emitcode ("rrc", "a");
6777 else if (shCount == 2)
6779 emitcode ("mov", "c,acc.7");
6780 emitcode ("rrc", "a");
6781 emitcode ("mov", "c,acc.7");
6782 emitcode ("rrc", "a");
6786 tlbl = newiTempLabel (NULL);
6787 /* rotate right accumulator */
6788 AccRol (8 - shCount);
6789 /* and kill the higher order bits */
6790 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6791 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6792 emitcode ("orl", "a,#0x%02x",
6793 (unsigned char) ~SRMask[shCount]);
6794 emitcode ("", "%05d$:", tlbl->key + 100);
6799 /*-----------------------------------------------------------------*/
6800 /* shiftR1Left2Result - shift right one byte from left to result */
6801 /*-----------------------------------------------------------------*/
6803 shiftR1Left2Result (operand * left, int offl,
6804 operand * result, int offr,
6805 int shCount, int sign)
6807 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6808 /* shift right accumulator */
6813 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6816 /*-----------------------------------------------------------------*/
6817 /* shiftL1Left2Result - shift left one byte from left to result */
6818 /*-----------------------------------------------------------------*/
6820 shiftL1Left2Result (operand * left, int offl,
6821 operand * result, int offr, int shCount)
6824 l = aopGet (AOP (left), offl, FALSE, FALSE);
6826 /* shift left accumulator */
6828 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6831 /*-----------------------------------------------------------------*/
6832 /* movLeft2Result - move byte from left to result */
6833 /*-----------------------------------------------------------------*/
6835 movLeft2Result (operand * left, int offl,
6836 operand * result, int offr, int sign)
6839 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6841 l = aopGet (AOP (left), offl, FALSE, FALSE);
6843 if (*l == '@' && (IS_AOP_PREG (result)))
6845 emitcode ("mov", "a,%s", l);
6846 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6851 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6854 /* MSB sign in acc.7 ! */
6855 if (getDataSize (left) == offl + 1)
6857 emitcode ("mov", "a,%s", l);
6858 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6865 /*-----------------------------------------------------------------*/
6866 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6867 /*-----------------------------------------------------------------*/
6871 emitcode ("rrc", "a");
6872 emitcode ("xch", "a,%s", x);
6873 emitcode ("rrc", "a");
6874 emitcode ("xch", "a,%s", x);
6877 /*-----------------------------------------------------------------*/
6878 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6879 /*-----------------------------------------------------------------*/
6883 emitcode ("xch", "a,%s", x);
6884 emitcode ("rlc", "a");
6885 emitcode ("xch", "a,%s", x);
6886 emitcode ("rlc", "a");
6889 /*-----------------------------------------------------------------*/
6890 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6891 /*-----------------------------------------------------------------*/
6895 emitcode ("xch", "a,%s", x);
6896 emitcode ("add", "a,acc");
6897 emitcode ("xch", "a,%s", x);
6898 emitcode ("rlc", "a");
6901 /*-----------------------------------------------------------------*/
6902 /* AccAXLsh - left shift a:x by known count (0..7) */
6903 /*-----------------------------------------------------------------*/
6905 AccAXLsh (char *x, int shCount)
6920 case 5: // AAAAABBB:CCCCCDDD
6922 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6924 emitcode ("anl", "a,#0x%02x",
6925 SLMask[shCount]); // BBB00000:CCCCCDDD
6927 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6929 AccRol (shCount); // DDDCCCCC:BBB00000
6931 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6933 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6935 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6937 emitcode ("anl", "a,#0x%02x",
6938 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6940 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6942 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6945 case 6: // AAAAAABB:CCCCCCDD
6946 emitcode ("anl", "a,#0x%02x",
6947 SRMask[shCount]); // 000000BB:CCCCCCDD
6948 emitcode ("mov", "c,acc.0"); // c = B
6949 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6951 AccAXRrl1 (x); // BCCCCCCD:D000000B
6952 AccAXRrl1 (x); // BBCCCCCC:DD000000
6954 emitcode("rrc","a");
6955 emitcode("xch","a,%s", x);
6956 emitcode("rrc","a");
6957 emitcode("mov","c,acc.0"); //<< get correct bit
6958 emitcode("xch","a,%s", x);
6960 emitcode("rrc","a");
6961 emitcode("xch","a,%s", x);
6962 emitcode("rrc","a");
6963 emitcode("xch","a,%s", x);
6966 case 7: // a:x <<= 7
6968 emitcode ("anl", "a,#0x%02x",
6969 SRMask[shCount]); // 0000000B:CCCCCCCD
6971 emitcode ("mov", "c,acc.0"); // c = B
6973 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6975 AccAXRrl1 (x); // BCCCCCCC:D0000000
6983 /*-----------------------------------------------------------------*/
6984 /* AccAXRsh - right shift a:x known count (0..7) */
6985 /*-----------------------------------------------------------------*/
6987 AccAXRsh (char *x, int shCount)
6995 AccAXRrl1 (x); // 0->a:x
7000 AccAXRrl1 (x); // 0->a:x
7003 AccAXRrl1 (x); // 0->a:x
7008 case 5: // AAAAABBB:CCCCCDDD = a:x
7010 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7012 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7014 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7016 emitcode ("anl", "a,#0x%02x",
7017 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7019 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7021 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7023 emitcode ("anl", "a,#0x%02x",
7024 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7026 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7028 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7030 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7033 case 6: // AABBBBBB:CCDDDDDD
7035 emitcode ("mov", "c,acc.7");
7036 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7038 emitcode ("mov", "c,acc.7");
7039 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7041 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7043 emitcode ("anl", "a,#0x%02x",
7044 SRMask[shCount]); // 000000AA:BBBBBBCC
7047 case 7: // ABBBBBBB:CDDDDDDD
7049 emitcode ("mov", "c,acc.7"); // c = A
7051 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7053 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7055 emitcode ("anl", "a,#0x%02x",
7056 SRMask[shCount]); // 0000000A:BBBBBBBC
7064 /*-----------------------------------------------------------------*/
7065 /* AccAXRshS - right shift signed a:x known count (0..7) */
7066 /*-----------------------------------------------------------------*/
7068 AccAXRshS (char *x, int shCount)
7076 emitcode ("mov", "c,acc.7");
7077 AccAXRrl1 (x); // s->a:x
7081 emitcode ("mov", "c,acc.7");
7082 AccAXRrl1 (x); // s->a:x
7084 emitcode ("mov", "c,acc.7");
7085 AccAXRrl1 (x); // s->a:x
7090 case 5: // AAAAABBB:CCCCCDDD = a:x
7092 tlbl = newiTempLabel (NULL);
7093 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7095 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7097 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7099 emitcode ("anl", "a,#0x%02x",
7100 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7102 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7104 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7106 emitcode ("anl", "a,#0x%02x",
7107 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7109 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7111 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7113 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7115 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7116 emitcode ("orl", "a,#0x%02x",
7117 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7119 emitcode ("", "%05d$:", tlbl->key + 100);
7120 break; // SSSSAAAA:BBBCCCCC
7122 case 6: // AABBBBBB:CCDDDDDD
7124 tlbl = newiTempLabel (NULL);
7125 emitcode ("mov", "c,acc.7");
7126 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7128 emitcode ("mov", "c,acc.7");
7129 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7131 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7133 emitcode ("anl", "a,#0x%02x",
7134 SRMask[shCount]); // 000000AA:BBBBBBCC
7136 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7137 emitcode ("orl", "a,#0x%02x",
7138 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7140 emitcode ("", "%05d$:", tlbl->key + 100);
7142 case 7: // ABBBBBBB:CDDDDDDD
7144 tlbl = newiTempLabel (NULL);
7145 emitcode ("mov", "c,acc.7"); // c = A
7147 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7149 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7151 emitcode ("anl", "a,#0x%02x",
7152 SRMask[shCount]); // 0000000A:BBBBBBBC
7154 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7155 emitcode ("orl", "a,#0x%02x",
7156 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7158 emitcode ("", "%05d$:", tlbl->key + 100);
7165 /*-----------------------------------------------------------------*/
7166 /* shiftL2Left2Result - shift left two bytes from left to result */
7167 /*-----------------------------------------------------------------*/
7169 shiftL2Left2Result (operand * left, int offl,
7170 operand * result, int offr, int shCount)
7172 if (sameRegs (AOP (result), AOP (left)) &&
7173 ((offl + MSB16) == offr))
7175 /* don't crash result[offr] */
7176 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7177 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7181 movLeft2Result (left, offl, result, offr, 0);
7182 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7184 /* ax << shCount (x = lsb(result)) */
7185 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7186 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7190 /*-----------------------------------------------------------------*/
7191 /* shiftR2Left2Result - shift right two bytes from left to result */
7192 /*-----------------------------------------------------------------*/
7194 shiftR2Left2Result (operand * left, int offl,
7195 operand * result, int offr,
7196 int shCount, int sign)
7198 if (sameRegs (AOP (result), AOP (left)) &&
7199 ((offl + MSB16) == offr))
7201 /* don't crash result[offr] */
7202 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7203 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7207 movLeft2Result (left, offl, result, offr, 0);
7208 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7210 /* a:x >> shCount (x = lsb(result)) */
7212 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7214 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7215 if (getDataSize (result) > 1)
7216 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7219 /*-----------------------------------------------------------------*/
7220 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7221 /*-----------------------------------------------------------------*/
7223 shiftLLeftOrResult (operand * left, int offl,
7224 operand * result, int offr, int shCount)
7226 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7227 /* shift left accumulator */
7229 /* or with result */
7230 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7231 /* back to result */
7232 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7235 /*-----------------------------------------------------------------*/
7236 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7237 /*-----------------------------------------------------------------*/
7239 shiftRLeftOrResult (operand * left, int offl,
7240 operand * result, int offr, int shCount)
7242 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7243 /* shift right accumulator */
7245 /* or with result */
7246 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7247 /* back to result */
7248 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7251 /*-----------------------------------------------------------------*/
7252 /* genlshOne - left shift a one byte quantity by known count */
7253 /*-----------------------------------------------------------------*/
7255 genlshOne (operand * result, operand * left, int shCount)
7257 D(emitcode ("; genlshOne",""));
7259 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7262 /*-----------------------------------------------------------------*/
7263 /* genlshTwo - left shift two bytes by known amount != 0 */
7264 /*-----------------------------------------------------------------*/
7266 genlshTwo (operand * result, operand * left, int shCount)
7270 D(emitcode ("; genlshTwo",""));
7272 size = getDataSize (result);
7274 /* if shCount >= 8 */
7282 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7284 movLeft2Result (left, LSB, result, MSB16, 0);
7286 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7289 /* 1 <= shCount <= 7 */
7293 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7295 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7299 /*-----------------------------------------------------------------*/
7300 /* shiftLLong - shift left one long from left to result */
7301 /* offl = LSB or MSB16 */
7302 /*-----------------------------------------------------------------*/
7304 shiftLLong (operand * left, operand * result, int offr)
7307 int size = AOP_SIZE (result);
7309 if (size >= LSB + offr)
7311 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7313 emitcode ("add", "a,acc");
7314 if (sameRegs (AOP (left), AOP (result)) &&
7315 size >= MSB16 + offr && offr != LSB)
7316 emitcode ("xch", "a,%s",
7317 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7319 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7322 if (size >= MSB16 + offr)
7324 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7326 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7329 emitcode ("rlc", "a");
7330 if (sameRegs (AOP (left), AOP (result)) &&
7331 size >= MSB24 + offr && offr != LSB)
7332 emitcode ("xch", "a,%s",
7333 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7335 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7338 if (size >= MSB24 + offr)
7340 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7342 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7345 emitcode ("rlc", "a");
7346 if (sameRegs (AOP (left), AOP (result)) &&
7347 size >= MSB32 + offr && offr != LSB)
7348 emitcode ("xch", "a,%s",
7349 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7351 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7354 if (size > MSB32 + offr)
7356 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7358 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7361 emitcode ("rlc", "a");
7362 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7365 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7368 /*-----------------------------------------------------------------*/
7369 /* genlshFour - shift four byte by a known amount != 0 */
7370 /*-----------------------------------------------------------------*/
7372 genlshFour (operand * result, operand * left, int shCount)
7376 D(emitcode ("; genlshFour",""));
7378 size = AOP_SIZE (result);
7380 /* if shifting more that 3 bytes */
7385 /* lowest order of left goes to the highest
7386 order of the destination */
7387 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7389 movLeft2Result (left, LSB, result, MSB32, 0);
7390 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7391 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7392 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7396 /* more than two bytes */
7397 else if (shCount >= 16)
7399 /* lower order two bytes goes to higher order two bytes */
7401 /* if some more remaining */
7403 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7406 movLeft2Result (left, MSB16, result, MSB32, 0);
7407 movLeft2Result (left, LSB, result, MSB24, 0);
7409 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7410 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7414 /* if more than 1 byte */
7415 else if (shCount >= 8)
7417 /* lower order three bytes goes to higher order three bytes */
7422 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7424 movLeft2Result (left, LSB, result, MSB16, 0);
7430 movLeft2Result (left, MSB24, result, MSB32, 0);
7431 movLeft2Result (left, MSB16, result, MSB24, 0);
7432 movLeft2Result (left, LSB, result, MSB16, 0);
7433 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7435 else if (shCount == 1)
7436 shiftLLong (left, result, MSB16);
7439 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7440 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7441 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7442 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7447 /* 1 <= shCount <= 7 */
7448 else if (shCount <= 2)
7450 shiftLLong (left, result, LSB);
7452 shiftLLong (result, result, LSB);
7454 /* 3 <= shCount <= 7, optimize */
7457 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7458 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7459 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7463 /*-----------------------------------------------------------------*/
7464 /* genLeftShiftLiteral - left shifting by known count */
7465 /*-----------------------------------------------------------------*/
7467 genLeftShiftLiteral (operand * left,
7472 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7475 D(emitcode ("; genLeftShiftLiteral",""));
7477 freeAsmop (right, NULL, ic, TRUE);
7479 aopOp (left, ic, FALSE);
7480 aopOp (result, ic, FALSE);
7482 size = getSize (operandType (result));
7485 emitcode ("; shift left ", "result %d, left %d", size,
7489 /* I suppose that the left size >= result size */
7494 movLeft2Result (left, size, result, size, 0);
7498 else if (shCount >= (size * 8))
7500 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7506 genlshOne (result, left, shCount);
7510 genlshTwo (result, left, shCount);
7514 genlshFour (result, left, shCount);
7517 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7518 "*** ack! mystery literal shift!\n");
7522 freeAsmop (left, NULL, ic, TRUE);
7523 freeAsmop (result, NULL, ic, TRUE);
7526 /*-----------------------------------------------------------------*/
7527 /* genLeftShift - generates code for left shifting */
7528 /*-----------------------------------------------------------------*/
7530 genLeftShift (iCode * ic)
7532 operand *left, *right, *result;
7535 symbol *tlbl, *tlbl1;
7538 D(emitcode ("; genLeftShift",""));
7540 right = IC_RIGHT (ic);
7541 left = IC_LEFT (ic);
7542 result = IC_RESULT (ic);
7544 aopOp (right, ic, FALSE);
7546 /* if the shift count is known then do it
7547 as efficiently as possible */
7548 if (AOP_TYPE (right) == AOP_LIT)
7550 genLeftShiftLiteral (left, right, result, ic);
7554 /* shift count is unknown then we have to form
7555 a loop get the loop count in B : Note: we take
7556 only the lower order byte since shifting
7557 more that 32 bits make no sense anyway, ( the
7558 largest size of an object can be only 32 bits ) */
7561 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7562 emitcode ("inc", "b");
7563 freeAsmop (right, NULL, ic, TRUE);
7564 aopOp (left, ic, FALSE);
7565 aopOp (result, ic, FALSE);
7567 /* now move the left to the result if they are not the same */
7568 if (!sameRegs (AOP (left), AOP (result)) &&
7569 AOP_SIZE (result) > 1)
7572 size = AOP_SIZE (result);
7576 l = aopGet (AOP (left), offset, FALSE, TRUE);
7577 if (*l == '@' && (IS_AOP_PREG (result)))
7580 emitcode ("mov", "a,%s", l);
7581 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7584 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7589 tlbl = newiTempLabel (NULL);
7590 size = AOP_SIZE (result);
7592 tlbl1 = newiTempLabel (NULL);
7594 /* if it is only one byte then */
7597 symbol *tlbl1 = newiTempLabel (NULL);
7599 l = aopGet (AOP (left), 0, FALSE, FALSE);
7601 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7602 emitcode ("", "%05d$:", tlbl->key + 100);
7603 emitcode ("add", "a,acc");
7604 emitcode ("", "%05d$:", tlbl1->key + 100);
7605 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7607 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7611 reAdjustPreg (AOP (result));
7613 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7614 emitcode ("", "%05d$:", tlbl->key + 100);
7615 l = aopGet (AOP (result), offset, FALSE, FALSE);
7617 emitcode ("add", "a,acc");
7618 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7621 l = aopGet (AOP (result), offset, FALSE, FALSE);
7623 emitcode ("rlc", "a");
7624 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7626 reAdjustPreg (AOP (result));
7628 emitcode ("", "%05d$:", tlbl1->key + 100);
7629 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7632 freeAsmop (left, NULL, ic, TRUE);
7633 freeAsmop (result, NULL, ic, TRUE);
7636 /*-----------------------------------------------------------------*/
7637 /* genrshOne - right shift a one byte quantity by known count */
7638 /*-----------------------------------------------------------------*/
7640 genrshOne (operand * result, operand * left,
7641 int shCount, int sign)
7643 D(emitcode ("; genrshOne",""));
7645 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7648 /*-----------------------------------------------------------------*/
7649 /* genrshTwo - right shift two bytes by known amount != 0 */
7650 /*-----------------------------------------------------------------*/
7652 genrshTwo (operand * result, operand * left,
7653 int shCount, int sign)
7655 D(emitcode ("; genrshTwo",""));
7657 /* if shCount >= 8 */
7662 shiftR1Left2Result (left, MSB16, result, LSB,
7665 movLeft2Result (left, MSB16, result, LSB, sign);
7666 addSign (result, MSB16, sign);
7669 /* 1 <= shCount <= 7 */
7671 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7674 /*-----------------------------------------------------------------*/
7675 /* shiftRLong - shift right one long from left to result */
7676 /* offl = LSB or MSB16 */
7677 /*-----------------------------------------------------------------*/
7679 shiftRLong (operand * left, int offl,
7680 operand * result, int sign)
7682 int isSameRegs=sameRegs(AOP(left),AOP(result));
7684 if (isSameRegs && offl>1) {
7685 // we are in big trouble, but this shouldn't happen
7686 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7689 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7694 emitcode ("rlc", "a");
7695 emitcode ("subb", "a,acc");
7697 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7699 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7700 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7703 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7708 emitcode ("clr", "c");
7710 emitcode ("mov", "c,acc.7");
7713 emitcode ("rrc", "a");
7715 if (isSameRegs && offl==MSB16) {
7716 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7718 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7719 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7722 emitcode ("rrc", "a");
7723 if (isSameRegs && offl==1) {
7724 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7726 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7727 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7729 emitcode ("rrc", "a");
7730 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7734 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7735 emitcode ("rrc", "a");
7736 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7740 /*-----------------------------------------------------------------*/
7741 /* genrshFour - shift four byte by a known amount != 0 */
7742 /*-----------------------------------------------------------------*/
7744 genrshFour (operand * result, operand * left,
7745 int shCount, int sign)
7747 D(emitcode ("; genrshFour",""));
7749 /* if shifting more that 3 bytes */
7754 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7756 movLeft2Result (left, MSB32, result, LSB, sign);
7757 addSign (result, MSB16, sign);
7759 else if (shCount >= 16)
7763 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7766 movLeft2Result (left, MSB24, result, LSB, 0);
7767 movLeft2Result (left, MSB32, result, MSB16, sign);
7769 addSign (result, MSB24, sign);
7771 else if (shCount >= 8)
7775 shiftRLong (left, MSB16, result, sign);
7776 else if (shCount == 0)
7778 movLeft2Result (left, MSB16, result, LSB, 0);
7779 movLeft2Result (left, MSB24, result, MSB16, 0);
7780 movLeft2Result (left, MSB32, result, MSB24, sign);
7781 addSign (result, MSB32, sign);
7785 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7786 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7787 /* the last shift is signed */
7788 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7789 addSign (result, MSB32, sign);
7793 { /* 1 <= shCount <= 7 */
7796 shiftRLong (left, LSB, result, sign);
7798 shiftRLong (result, LSB, result, sign);
7802 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7803 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7804 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7809 /*-----------------------------------------------------------------*/
7810 /* genRightShiftLiteral - right shifting by known count */
7811 /*-----------------------------------------------------------------*/
7813 genRightShiftLiteral (operand * left,
7819 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7822 D(emitcode ("; genRightShiftLiteral",""));
7824 freeAsmop (right, NULL, ic, TRUE);
7826 aopOp (left, ic, FALSE);
7827 aopOp (result, ic, FALSE);
7830 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7834 size = getDataSize (left);
7835 /* test the LEFT size !!! */
7837 /* I suppose that the left size >= result size */
7840 size = getDataSize (result);
7842 movLeft2Result (left, size, result, size, 0);
7845 else if (shCount >= (size * 8))
7848 /* get sign in acc.7 */
7849 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7851 addSign (result, LSB, sign);
7858 genrshOne (result, left, shCount, sign);
7862 genrshTwo (result, left, shCount, sign);
7866 genrshFour (result, left, shCount, sign);
7872 freeAsmop (left, NULL, ic, TRUE);
7873 freeAsmop (result, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genSignedRightShift - right shift of signed number */
7878 /*-----------------------------------------------------------------*/
7880 genSignedRightShift (iCode * ic)
7882 operand *right, *left, *result;
7885 symbol *tlbl, *tlbl1;
7888 D(emitcode ("; genSignedRightShift",""));
7890 /* we do it the hard way put the shift count in b
7891 and loop thru preserving the sign */
7893 right = IC_RIGHT (ic);
7894 left = IC_LEFT (ic);
7895 result = IC_RESULT (ic);
7897 aopOp (right, ic, FALSE);
7900 if (AOP_TYPE (right) == AOP_LIT)
7902 genRightShiftLiteral (left, right, result, ic, 1);
7905 /* shift count is unknown then we have to form
7906 a loop get the loop count in B : Note: we take
7907 only the lower order byte since shifting
7908 more that 32 bits make no sense anyway, ( the
7909 largest size of an object can be only 32 bits ) */
7912 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7913 emitcode ("inc", "b");
7914 freeAsmop (right, NULL, ic, TRUE);
7915 aopOp (left, ic, FALSE);
7916 aopOp (result, ic, FALSE);
7918 /* now move the left to the result if they are not the
7920 if (!sameRegs (AOP (left), AOP (result)) &&
7921 AOP_SIZE (result) > 1)
7924 size = AOP_SIZE (result);
7928 l = aopGet (AOP (left), offset, FALSE, TRUE);
7929 if (*l == '@' && IS_AOP_PREG (result))
7932 emitcode ("mov", "a,%s", l);
7933 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7936 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7941 /* mov the highest order bit to OVR */
7942 tlbl = newiTempLabel (NULL);
7943 tlbl1 = newiTempLabel (NULL);
7945 size = AOP_SIZE (result);
7947 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7948 emitcode ("rlc", "a");
7949 emitcode ("mov", "ov,c");
7950 /* if it is only one byte then */
7953 l = aopGet (AOP (left), 0, FALSE, FALSE);
7955 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7956 emitcode ("", "%05d$:", tlbl->key + 100);
7957 emitcode ("mov", "c,ov");
7958 emitcode ("rrc", "a");
7959 emitcode ("", "%05d$:", tlbl1->key + 100);
7960 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7962 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7966 reAdjustPreg (AOP (result));
7967 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7968 emitcode ("", "%05d$:", tlbl->key + 100);
7969 emitcode ("mov", "c,ov");
7972 l = aopGet (AOP (result), offset, FALSE, FALSE);
7974 emitcode ("rrc", "a");
7975 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7977 reAdjustPreg (AOP (result));
7978 emitcode ("", "%05d$:", tlbl1->key + 100);
7979 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7983 freeAsmop (left, NULL, ic, TRUE);
7984 freeAsmop (result, NULL, ic, TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genRightShift - generate code for right shifting */
7989 /*-----------------------------------------------------------------*/
7991 genRightShift (iCode * ic)
7993 operand *right, *left, *result;
7997 symbol *tlbl, *tlbl1;
8000 D(emitcode ("; genRightShift",""));
8002 /* if signed then we do it the hard way preserve the
8003 sign bit moving it inwards */
8004 letype = getSpec (operandType (IC_LEFT (ic)));
8006 if (!SPEC_USIGN (letype))
8008 genSignedRightShift (ic);
8012 /* signed & unsigned types are treated the same : i.e. the
8013 signed is NOT propagated inwards : quoting from the
8014 ANSI - standard : "for E1 >> E2, is equivalent to division
8015 by 2**E2 if unsigned or if it has a non-negative value,
8016 otherwise the result is implementation defined ", MY definition
8017 is that the sign does not get propagated */
8019 right = IC_RIGHT (ic);
8020 left = IC_LEFT (ic);
8021 result = IC_RESULT (ic);
8023 aopOp (right, ic, FALSE);
8025 /* if the shift count is known then do it
8026 as efficiently as possible */
8027 if (AOP_TYPE (right) == AOP_LIT)
8029 genRightShiftLiteral (left, right, result, ic, 0);
8033 /* shift count is unknown then we have to form
8034 a loop get the loop count in B : Note: we take
8035 only the lower order byte since shifting
8036 more that 32 bits make no sense anyway, ( the
8037 largest size of an object can be only 32 bits ) */
8040 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8041 emitcode ("inc", "b");
8042 freeAsmop (right, NULL, ic, TRUE);
8043 aopOp (left, ic, FALSE);
8044 aopOp (result, ic, FALSE);
8046 /* now move the left to the result if they are not the
8048 if (!sameRegs (AOP (left), AOP (result)) &&
8049 AOP_SIZE (result) > 1)
8052 size = AOP_SIZE (result);
8056 l = aopGet (AOP (left), offset, FALSE, TRUE);
8057 if (*l == '@' && IS_AOP_PREG (result))
8060 emitcode ("mov", "a,%s", l);
8061 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8064 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8069 tlbl = newiTempLabel (NULL);
8070 tlbl1 = newiTempLabel (NULL);
8071 size = AOP_SIZE (result);
8074 /* if it is only one byte then */
8077 l = aopGet (AOP (left), 0, FALSE, FALSE);
8079 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8080 emitcode ("", "%05d$:", tlbl->key + 100);
8082 emitcode ("rrc", "a");
8083 emitcode ("", "%05d$:", tlbl1->key + 100);
8084 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8086 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8090 reAdjustPreg (AOP (result));
8091 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8092 emitcode ("", "%05d$:", tlbl->key + 100);
8096 l = aopGet (AOP (result), offset, FALSE, FALSE);
8098 emitcode ("rrc", "a");
8099 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8101 reAdjustPreg (AOP (result));
8103 emitcode ("", "%05d$:", tlbl1->key + 100);
8104 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8108 freeAsmop (left, NULL, ic, TRUE);
8109 freeAsmop (result, NULL, ic, TRUE);
8112 /*-----------------------------------------------------------------*/
8113 /* emitPtrByteGet - emits code to get a byte into A through a */
8114 /* pointer register (R0, R1, or DPTR). The */
8115 /* original value of A can be preserved in B. */
8116 /*-----------------------------------------------------------------*/
8118 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8125 emitcode ("mov", "b,a");
8126 emitcode ("mov", "a,@%s", rname);
8131 emitcode ("mov", "b,a");
8132 emitcode ("movx", "a,@%s", rname);
8137 emitcode ("mov", "b,a");
8138 emitcode ("movx", "a,@dptr");
8143 emitcode ("mov", "b,a");
8144 emitcode ("clr", "a");
8145 emitcode ("movc", "a,@a+dptr");
8151 emitcode ("push", "b");
8152 emitcode ("push", "acc");
8154 emitcode ("lcall", "__gptrget");
8156 emitcode ("pop", "b");
8161 /*-----------------------------------------------------------------*/
8162 /* emitPtrByteSet - emits code to set a byte from src through a */
8163 /* pointer register (R0, R1, or DPTR). */
8164 /*-----------------------------------------------------------------*/
8166 emitPtrByteSet (char *rname, int p_type, char *src)
8175 emitcode ("mov", "@%s,a", rname);
8178 emitcode ("mov", "@%s,%s", rname, src);
8183 emitcode ("movx", "@%s,a", rname);
8188 emitcode ("movx", "@dptr,a");
8193 emitcode ("lcall", "__gptrput");
8198 /*-----------------------------------------------------------------*/
8199 /* genUnpackBits - generates code for unpacking bits */
8200 /*-----------------------------------------------------------------*/
8202 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8204 int offset = 0; /* result byte offset */
8205 int rsize; /* result size */
8206 int rlen = 0; /* remaining bitfield length */
8207 sym_link *etype; /* bitfield type information */
8208 int blen; /* bitfield length */
8209 int bstr; /* bitfield starting bit within byte */
8212 D(emitcode ("; genUnpackBits",""));
8214 etype = getSpec (operandType (result));
8215 rsize = getSize (operandType (result));
8216 blen = SPEC_BLEN (etype);
8217 bstr = SPEC_BSTR (etype);
8219 if (ifx && blen <= 8)
8221 emitPtrByteGet (rname, ptype, FALSE);
8224 SNPRINTF (buffer, sizeof(buffer),
8226 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8231 emitcode ("anl", "a,#0x%02x",
8232 (((unsigned char) -1) >> (8 - blen)) << bstr);
8233 genIfxJump (ifx, "a", NULL, NULL, NULL);
8239 /* If the bitfield length is less than a byte */
8242 emitPtrByteGet (rname, ptype, FALSE);
8244 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8245 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8249 /* Bit field did not fit in a byte. Copy all
8250 but the partial byte at the end. */
8251 for (rlen=blen;rlen>=8;rlen-=8)
8253 emitPtrByteGet (rname, ptype, FALSE);
8254 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8256 emitcode ("inc", "%s", rname);
8259 /* Handle the partial byte at the end */
8262 emitPtrByteGet (rname, ptype, FALSE);
8263 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8264 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8272 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8277 /*-----------------------------------------------------------------*/
8278 /* genDataPointerGet - generates code when ptr offset is known */
8279 /*-----------------------------------------------------------------*/
8281 genDataPointerGet (operand * left,
8287 int size, offset = 0;
8289 D(emitcode ("; genDataPointerGet",""));
8291 aopOp (result, ic, TRUE);
8293 /* get the string representation of the name */
8294 l = aopGet (AOP (left), 0, FALSE, TRUE);
8295 size = AOP_SIZE (result);
8299 sprintf (buffer, "(%s + %d)", l + 1, offset);
8301 sprintf (buffer, "%s", l + 1);
8302 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8305 freeAsmop (left, NULL, ic, TRUE);
8306 freeAsmop (result, NULL, ic, TRUE);
8309 /*-----------------------------------------------------------------*/
8310 /* genNearPointerGet - emitcode for near pointer fetch */
8311 /*-----------------------------------------------------------------*/
8313 genNearPointerGet (operand * left,
8322 sym_link *rtype, *retype;
8323 sym_link *ltype = operandType (left);
8326 D(emitcode ("; genNearPointerGet",""));
8328 rtype = operandType (result);
8329 retype = getSpec (rtype);
8331 aopOp (left, ic, FALSE);
8333 /* if left is rematerialisable and
8334 result is not bitfield variable type and
8335 the left is pointer to data space i.e
8336 lower 128 bytes of space */
8337 if (AOP_TYPE (left) == AOP_IMMD &&
8338 !IS_BITFIELD (retype) &&
8339 DCL_TYPE (ltype) == POINTER)
8341 genDataPointerGet (left, result, ic);
8345 /* if the value is already in a pointer register
8346 then don't need anything more */
8347 if (!AOP_INPREG (AOP (left)))
8349 if (IS_AOP_PREG (left))
8351 // Aha, it is a pointer, just in disguise.
8352 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8355 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8356 __FILE__, __LINE__);
8361 emitcode ("mov", "a%s,%s", rname + 1, rname);
8362 rname++; // skip the '@'.
8367 /* otherwise get a free pointer register */
8369 preg = getFreePtr (ic, &aop, FALSE);
8370 emitcode ("mov", "%s,%s",
8372 aopGet (AOP (left), 0, FALSE, TRUE));
8377 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8379 //aopOp (result, ic, FALSE);
8380 aopOp (result, ic, result?TRUE:FALSE);
8382 /* if bitfield then unpack the bits */
8383 if (IS_BITFIELD (retype))
8384 genUnpackBits (result, rname, POINTER, ifx);
8387 /* we have can just get the values */
8388 int size = AOP_SIZE (result);
8393 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8396 emitcode ("mov", "a,@%s", rname);
8398 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8402 sprintf (buffer, "@%s", rname);
8403 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8407 emitcode ("inc", "%s", rname);
8411 /* now some housekeeping stuff */
8412 if (aop) /* we had to allocate for this iCode */
8414 if (pi) { /* post increment present */
8415 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8417 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8421 /* we did not allocate which means left
8422 already in a pointer register, then
8423 if size > 0 && this could be used again
8424 we have to point it back to where it
8426 if ((AOP_SIZE (result) > 1 &&
8427 !OP_SYMBOL (left)->remat &&
8428 (OP_SYMBOL (left)->liveTo > ic->seq ||
8432 int size = AOP_SIZE (result) - 1;
8434 emitcode ("dec", "%s", rname);
8438 if (ifx && !ifx->generated)
8440 genIfxJump (ifx, "a", left, NULL, result);
8444 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8445 freeAsmop (left, NULL, ic, TRUE);
8446 if (pi) pi->generated = 1;
8449 /*-----------------------------------------------------------------*/
8450 /* genPagedPointerGet - emitcode for paged pointer fetch */
8451 /*-----------------------------------------------------------------*/
8453 genPagedPointerGet (operand * left,
8462 sym_link *rtype, *retype;
8464 D(emitcode ("; genPagedPointerGet",""));
8466 rtype = operandType (result);
8467 retype = getSpec (rtype);
8469 aopOp (left, ic, FALSE);
8471 /* if the value is already in a pointer register
8472 then don't need anything more */
8473 if (!AOP_INPREG (AOP (left)))
8475 /* otherwise get a free pointer register */
8477 preg = getFreePtr (ic, &aop, FALSE);
8478 emitcode ("mov", "%s,%s",
8480 aopGet (AOP (left), 0, FALSE, TRUE));
8484 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8486 aopOp (result, ic, FALSE);
8488 /* if bitfield then unpack the bits */
8489 if (IS_BITFIELD (retype))
8490 genUnpackBits (result, rname, PPOINTER, ifx);
8493 /* we have can just get the values */
8494 int size = AOP_SIZE (result);
8500 emitcode ("movx", "a,@%s", rname);
8502 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8507 emitcode ("inc", "%s", rname);
8511 /* now some housekeeping stuff */
8512 if (aop) /* we had to allocate for this iCode */
8514 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8515 freeAsmop (NULL, aop, ic, TRUE);
8519 /* we did not allocate which means left
8520 already in a pointer register, then
8521 if size > 0 && this could be used again
8522 we have to point it back to where it
8524 if ((AOP_SIZE (result) > 1 &&
8525 !OP_SYMBOL (left)->remat &&
8526 (OP_SYMBOL (left)->liveTo > ic->seq ||
8530 int size = AOP_SIZE (result) - 1;
8532 emitcode ("dec", "%s", rname);
8536 if (ifx && !ifx->generated)
8538 genIfxJump (ifx, "a", left, NULL, result);
8542 freeAsmop (left, NULL, ic, TRUE);
8543 freeAsmop (result, NULL, ic, TRUE);
8544 if (pi) pi->generated = 1;
8548 /*--------------------------------------------------------------------*/
8549 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8550 /*--------------------------------------------------------------------*/
8552 loadDptrFromOperand (operand *op, bool loadBToo)
8554 if (AOP_TYPE (op) != AOP_STR)
8556 /* if this is rematerializable */
8557 if (AOP_TYPE (op) == AOP_IMMD)
8559 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8562 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8563 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8566 wassertl(FALSE, "need pointerCode");
8567 emitcode ("", "; mov b,???");
8568 /* genPointerGet and genPointerSet originally did different
8569 ** things for this case. Both seem wrong.
8570 ** from genPointerGet:
8571 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8572 ** from genPointerSet:
8573 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8578 else if (AOP_TYPE (op) == AOP_DPTR)
8582 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8583 emitcode ("push", "acc");
8584 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8585 emitcode ("push", "acc");
8586 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8587 emitcode ("pop", "dph");
8588 emitcode ("pop", "dpl");
8592 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8593 emitcode ("push", "acc");
8594 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8595 emitcode ("pop", "dpl");
8599 { /* we need to get it byte by byte */
8600 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8601 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8603 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8608 /*-----------------------------------------------------------------*/
8609 /* genFarPointerGet - gget value from far space */
8610 /*-----------------------------------------------------------------*/
8612 genFarPointerGet (operand * left,
8613 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8616 sym_link *retype = getSpec (operandType (result));
8618 D(emitcode ("; genFarPointerGet",""));
8620 aopOp (left, ic, FALSE);
8621 loadDptrFromOperand (left, FALSE);
8623 /* so dptr now contains the address */
8624 aopOp (result, ic, FALSE);
8626 /* if bit then unpack */
8627 if (IS_BITFIELD (retype))
8628 genUnpackBits (result, "dptr", FPOINTER, ifx);
8631 size = AOP_SIZE (result);
8636 emitcode ("movx", "a,@dptr");
8638 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8640 emitcode ("inc", "dptr");
8644 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8646 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8647 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8651 if (ifx && !ifx->generated)
8653 genIfxJump (ifx, "a", left, NULL, result);
8656 freeAsmop (left, NULL, ic, TRUE);
8657 freeAsmop (result, NULL, ic, TRUE);
8660 /*-----------------------------------------------------------------*/
8661 /* genCodePointerGet - gget value from code space */
8662 /*-----------------------------------------------------------------*/
8664 genCodePointerGet (operand * left,
8665 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8668 sym_link *retype = getSpec (operandType (result));
8670 D(emitcode ("; genCodePointerGet",""));
8672 aopOp (left, ic, FALSE);
8673 loadDptrFromOperand (left, FALSE);
8675 /* so dptr now contains the address */
8676 aopOp (result, ic, FALSE);
8678 /* if bit then unpack */
8679 if (IS_BITFIELD (retype))
8680 genUnpackBits (result, "dptr", CPOINTER, ifx);
8683 size = AOP_SIZE (result);
8690 emitcode ("clr", "a");
8691 emitcode ("movc", "a,@a+dptr");
8693 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8694 emitcode ("inc", "dptr");
8698 emitcode ("mov", "a,#0x%02x", offset);
8699 emitcode ("movc", "a,@a+dptr");
8701 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8706 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8708 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8709 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8713 if (ifx && !ifx->generated)
8715 genIfxJump (ifx, "a", left, NULL, result);
8718 freeAsmop (left, NULL, ic, TRUE);
8719 freeAsmop (result, NULL, ic, TRUE);
8722 /*-----------------------------------------------------------------*/
8723 /* genGenPointerGet - gget value from generic pointer space */
8724 /*-----------------------------------------------------------------*/
8726 genGenPointerGet (operand * left,
8727 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8730 sym_link *retype = getSpec (operandType (result));
8732 D(emitcode ("; genGenPointerGet",""));
8734 aopOp (left, ic, FALSE);
8735 loadDptrFromOperand (left, TRUE);
8737 /* so dptr know contains the address */
8738 aopOp (result, ic, FALSE);
8740 /* if bit then unpack */
8741 if (IS_BITFIELD (retype))
8742 genUnpackBits (result, "dptr", GPOINTER, ifx);
8745 size = AOP_SIZE (result);
8750 emitcode ("lcall", "__gptrget");
8752 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8754 emitcode ("inc", "dptr");
8758 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8760 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8761 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8765 if (ifx && !ifx->generated)
8767 genIfxJump (ifx, "a", left, NULL, result);
8771 freeAsmop (left, NULL, ic, TRUE);
8772 freeAsmop (result, NULL, ic, TRUE);
8775 /*-----------------------------------------------------------------*/
8776 /* genPointerGet - generate code for pointer get */
8777 /*-----------------------------------------------------------------*/
8779 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8781 operand *left, *result;
8782 sym_link *type, *etype;
8785 D(emitcode ("; genPointerGet",""));
8787 left = IC_LEFT (ic);
8788 result = IC_RESULT (ic);
8790 if (getSize (operandType (result))>1)
8793 /* depending on the type of pointer we need to
8794 move it to the correct pointer register */
8795 type = operandType (left);
8796 etype = getSpec (type);
8797 /* if left is of type of pointer then it is simple */
8798 if (IS_PTR (type) && !IS_FUNC (type->next))
8799 p_type = DCL_TYPE (type);
8802 /* we have to go by the storage class */
8803 p_type = PTR_TYPE (SPEC_OCLS (etype));
8806 /* special case when cast remat */
8807 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8808 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8809 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8810 type = operandType (left);
8811 p_type = DCL_TYPE (type);
8813 /* now that we have the pointer type we assign
8814 the pointer values */
8820 genNearPointerGet (left, result, ic, pi, ifx);
8824 genPagedPointerGet (left, result, ic, pi, ifx);
8828 genFarPointerGet (left, result, ic, pi, ifx);
8832 genCodePointerGet (left, result, ic, pi, ifx);
8836 genGenPointerGet (left, result, ic, pi, ifx);
8844 /*-----------------------------------------------------------------*/
8845 /* genPackBits - generates code for packed bit storage */
8846 /*-----------------------------------------------------------------*/
8848 genPackBits (sym_link * etype,
8850 char *rname, int p_type)
8852 int offset = 0; /* source byte offset */
8853 int rlen = 0; /* remaining bitfield length */
8854 int blen; /* bitfield length */
8855 int bstr; /* bitfield starting bit within byte */
8856 int litval; /* source literal value (if AOP_LIT) */
8857 unsigned char mask; /* bitmask within current byte */
8859 D(emitcode ("; genPackBits",""));
8861 blen = SPEC_BLEN (etype);
8862 bstr = SPEC_BSTR (etype);
8864 /* If the bitfield length is less than a byte */
8867 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8868 (unsigned char) (0xFF >> (8 - bstr)));
8870 if (AOP_TYPE (right) == AOP_LIT)
8872 /* Case with a bitfield length <8 and literal source
8874 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8876 litval &= (~mask) & 0xff;
8877 emitPtrByteGet (rname, p_type, FALSE);
8878 if ((mask|litval)!=0xff)
8879 emitcode ("anl","a,#0x%02x", mask);
8881 emitcode ("orl","a,#0x%02x", litval);
8885 if ((blen==1) && (p_type!=GPOINTER))
8887 /* Case with a bitfield length == 1 and no generic pointer
8889 if (AOP_TYPE (right) == AOP_CRY)
8890 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8893 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8894 emitcode ("rrc","a");
8896 emitPtrByteGet (rname, p_type, FALSE);
8897 emitcode ("mov","acc.%d,c",bstr);
8902 /* Case with a bitfield length < 8 and arbitrary source
8904 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8905 /* shift and mask source value */
8907 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8910 /* transfer A to B and get next byte */
8911 emitPtrByteGet (rname, p_type, TRUE);
8913 emitcode ("anl", "a,#0x%02x", mask);
8914 emitcode ("orl", "a,b");
8915 if (p_type == GPOINTER)
8916 emitcode ("pop", "b");
8922 emitPtrByteSet (rname, p_type, "a");
8926 /* Bit length is greater than 7 bits. In this case, copy */
8927 /* all except the partial byte at the end */
8928 for (rlen=blen;rlen>=8;rlen-=8)
8930 emitPtrByteSet (rname, p_type,
8931 aopGet (AOP (right), offset++, FALSE, TRUE) );
8933 emitcode ("inc", "%s", rname);
8936 /* If there was a partial byte at the end */
8939 mask = (((unsigned char) -1 << rlen) & 0xff);
8941 if (AOP_TYPE (right) == AOP_LIT)
8943 /* Case with partial byte and literal source
8945 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8946 litval >>= (blen-rlen);
8947 litval &= (~mask) & 0xff;
8948 emitPtrByteGet (rname, p_type, FALSE);
8949 if ((mask|litval)!=0xff)
8950 emitcode ("anl","a,#0x%02x", mask);
8952 emitcode ("orl","a,#0x%02x", litval);
8957 /* Case with partial byte and arbitrary source
8959 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8960 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8963 /* transfer A to B and get next byte */
8964 emitPtrByteGet (rname, p_type, TRUE);
8966 emitcode ("anl", "a,#0x%02x", mask);
8967 emitcode ("orl", "a,b");
8968 if (p_type == GPOINTER)
8969 emitcode ("pop", "b");
8973 emitPtrByteSet (rname, p_type, "a");
8979 /*-----------------------------------------------------------------*/
8980 /* genDataPointerSet - remat pointer to data space */
8981 /*-----------------------------------------------------------------*/
8983 genDataPointerSet (operand * right,
8987 int size, offset = 0;
8988 char *l, buffer[256];
8990 D(emitcode ("; genDataPointerSet",""));
8992 aopOp (right, ic, FALSE);
8994 l = aopGet (AOP (result), 0, FALSE, TRUE);
8995 size = AOP_SIZE (right);
8999 sprintf (buffer, "(%s + %d)", l + 1, offset);
9001 sprintf (buffer, "%s", l + 1);
9002 emitcode ("mov", "%s,%s", buffer,
9003 aopGet (AOP (right), offset++, FALSE, FALSE));
9006 freeAsmop (right, NULL, ic, TRUE);
9007 freeAsmop (result, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genNearPointerSet - emitcode for near pointer put */
9012 /*-----------------------------------------------------------------*/
9014 genNearPointerSet (operand * right,
9022 sym_link *retype, *letype;
9023 sym_link *ptype = operandType (result);
9025 D(emitcode ("; genNearPointerSet",""));
9027 retype = getSpec (operandType (right));
9028 letype = getSpec (ptype);
9029 aopOp (result, ic, FALSE);
9031 /* if the result is rematerializable &
9032 in data space & not a bit variable */
9033 if (AOP_TYPE (result) == AOP_IMMD &&
9034 DCL_TYPE (ptype) == POINTER &&
9035 !IS_BITVAR (retype) &&
9036 !IS_BITVAR (letype))
9038 genDataPointerSet (right, result, ic);
9042 /* if the value is already in a pointer register
9043 then don't need anything more */
9044 if (!AOP_INPREG (AOP (result)))
9047 //AOP_TYPE (result) == AOP_STK
9051 // Aha, it is a pointer, just in disguise.
9052 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9055 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9056 __FILE__, __LINE__);
9061 emitcode ("mov", "a%s,%s", rname + 1, rname);
9062 rname++; // skip the '@'.
9067 /* otherwise get a free pointer register */
9069 preg = getFreePtr (ic, &aop, FALSE);
9070 emitcode ("mov", "%s,%s",
9072 aopGet (AOP (result), 0, FALSE, TRUE));
9078 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9081 aopOp (right, ic, FALSE);
9083 /* if bitfield then unpack the bits */
9084 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9085 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9088 /* we have can just get the values */
9089 int size = AOP_SIZE (right);
9094 l = aopGet (AOP (right), offset, FALSE, TRUE);
9098 emitcode ("mov", "@%s,a", rname);
9101 emitcode ("mov", "@%s,%s", rname, l);
9103 emitcode ("inc", "%s", rname);
9108 /* now some housekeeping stuff */
9109 if (aop) /* we had to allocate for this iCode */
9112 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9113 freeAsmop (NULL, aop, ic, TRUE);
9117 /* we did not allocate which means left
9118 already in a pointer register, then
9119 if size > 0 && this could be used again
9120 we have to point it back to where it
9122 if ((AOP_SIZE (right) > 1 &&
9123 !OP_SYMBOL (result)->remat &&
9124 (OP_SYMBOL (result)->liveTo > ic->seq ||
9128 int size = AOP_SIZE (right) - 1;
9130 emitcode ("dec", "%s", rname);
9135 if (pi) pi->generated = 1;
9136 freeAsmop (result, NULL, ic, TRUE);
9137 freeAsmop (right, NULL, ic, TRUE);
9140 /*-----------------------------------------------------------------*/
9141 /* genPagedPointerSet - emitcode for Paged pointer put */
9142 /*-----------------------------------------------------------------*/
9144 genPagedPointerSet (operand * right,
9152 sym_link *retype, *letype;
9154 D(emitcode ("; genPagedPointerSet",""));
9156 retype = getSpec (operandType (right));
9157 letype = getSpec (operandType (result));
9159 aopOp (result, ic, FALSE);
9161 /* if the value is already in a pointer register
9162 then don't need anything more */
9163 if (!AOP_INPREG (AOP (result)))
9165 /* otherwise get a free pointer register */
9167 preg = getFreePtr (ic, &aop, FALSE);
9168 emitcode ("mov", "%s,%s",
9170 aopGet (AOP (result), 0, FALSE, TRUE));
9174 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9176 aopOp (right, ic, FALSE);
9178 /* if bitfield then unpack the bits */
9179 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9180 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9183 /* we have can just get the values */
9184 int size = AOP_SIZE (right);
9189 l = aopGet (AOP (right), offset, FALSE, TRUE);
9192 emitcode ("movx", "@%s,a", rname);
9195 emitcode ("inc", "%s", rname);
9201 /* now some housekeeping stuff */
9202 if (aop) /* we had to allocate for this iCode */
9205 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9206 freeAsmop (NULL, aop, ic, TRUE);
9210 /* we did not allocate which means left
9211 already in a pointer register, then
9212 if size > 0 && this could be used again
9213 we have to point it back to where it
9215 if (AOP_SIZE (right) > 1 &&
9216 !OP_SYMBOL (result)->remat &&
9217 (OP_SYMBOL (result)->liveTo > ic->seq ||
9220 int size = AOP_SIZE (right) - 1;
9222 emitcode ("dec", "%s", rname);
9227 if (pi) pi->generated = 1;
9228 freeAsmop (result, NULL, ic, TRUE);
9229 freeAsmop (right, NULL, ic, TRUE);
9234 /*-----------------------------------------------------------------*/
9235 /* genFarPointerSet - set value from far space */
9236 /*-----------------------------------------------------------------*/
9238 genFarPointerSet (operand * right,
9239 operand * result, iCode * ic, iCode * pi)
9242 sym_link *retype = getSpec (operandType (right));
9243 sym_link *letype = getSpec (operandType (result));
9245 D(emitcode ("; genFarPointerSet",""));
9247 aopOp (result, ic, FALSE);
9248 loadDptrFromOperand (result, FALSE);
9250 /* so dptr know contains the address */
9251 aopOp (right, ic, FALSE);
9253 /* if bit then unpack */
9254 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9255 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9258 size = AOP_SIZE (right);
9263 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9265 emitcode ("movx", "@dptr,a");
9267 emitcode ("inc", "dptr");
9270 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9271 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9272 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9275 freeAsmop (result, NULL, ic, TRUE);
9276 freeAsmop (right, NULL, ic, TRUE);
9279 /*-----------------------------------------------------------------*/
9280 /* genGenPointerSet - set value from generic pointer space */
9281 /*-----------------------------------------------------------------*/
9283 genGenPointerSet (operand * right,
9284 operand * result, iCode * ic, iCode * pi)
9287 sym_link *retype = getSpec (operandType (right));
9288 sym_link *letype = getSpec (operandType (result));
9290 D(emitcode ("; genGenPointerSet",""));
9292 aopOp (result, ic, FALSE);
9293 loadDptrFromOperand (result, TRUE);
9295 /* so dptr know contains the address */
9296 aopOp (right, ic, FALSE);
9298 /* if bit then unpack */
9299 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9300 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9303 size = AOP_SIZE (right);
9308 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9310 emitcode ("lcall", "__gptrput");
9312 emitcode ("inc", "dptr");
9316 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9317 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9318 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9321 freeAsmop (result, NULL, ic, TRUE);
9322 freeAsmop (right, NULL, ic, TRUE);
9325 /*-----------------------------------------------------------------*/
9326 /* genPointerSet - stores the value into a pointer location */
9327 /*-----------------------------------------------------------------*/
9329 genPointerSet (iCode * ic, iCode *pi)
9331 operand *right, *result;
9332 sym_link *type, *etype;
9335 D(emitcode ("; genPointerSet",""));
9337 right = IC_RIGHT (ic);
9338 result = IC_RESULT (ic);
9340 /* depending on the type of pointer we need to
9341 move it to the correct pointer register */
9342 type = operandType (result);
9343 etype = getSpec (type);
9344 /* if left is of type of pointer then it is simple */
9345 if (IS_PTR (type) && !IS_FUNC (type->next))
9347 p_type = DCL_TYPE (type);
9351 /* we have to go by the storage class */
9352 p_type = PTR_TYPE (SPEC_OCLS (etype));
9355 /* special case when cast remat */
9356 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9357 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9358 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9359 type = operandType (result);
9360 p_type = DCL_TYPE (type);
9362 /* now that we have the pointer type we assign
9363 the pointer values */
9369 genNearPointerSet (right, result, ic, pi);
9373 genPagedPointerSet (right, result, ic, pi);
9377 genFarPointerSet (right, result, ic, pi);
9381 genGenPointerSet (right, result, ic, pi);
9385 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9386 "genPointerSet: illegal pointer type");
9391 /*-----------------------------------------------------------------*/
9392 /* genIfx - generate code for Ifx statement */
9393 /*-----------------------------------------------------------------*/
9395 genIfx (iCode * ic, iCode * popIc)
9397 operand *cond = IC_COND (ic);
9400 D(emitcode ("; genIfx",""));
9402 aopOp (cond, ic, FALSE);
9404 /* get the value into acc */
9405 if (AOP_TYPE (cond) != AOP_CRY)
9409 /* the result is now in the accumulator */
9410 freeAsmop (cond, NULL, ic, TRUE);
9412 /* if there was something to be popped then do it */
9416 /* if the condition is a bit variable */
9417 if (isbit && IS_ITEMP (cond) &&
9419 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9420 else if (isbit && !IS_ITEMP (cond))
9421 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9423 genIfxJump (ic, "a", NULL, NULL, NULL);
9428 /*-----------------------------------------------------------------*/
9429 /* genAddrOf - generates code for address of */
9430 /*-----------------------------------------------------------------*/
9432 genAddrOf (iCode * ic)
9434 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9437 D(emitcode ("; genAddrOf",""));
9439 aopOp (IC_RESULT (ic), ic, FALSE);
9441 /* if the operand is on the stack then we
9442 need to get the stack offset of this
9446 /* if it has an offset then we need to compute
9450 emitcode ("mov", "a,_bp");
9451 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9452 ((char) (sym->stack - _G.nRegsSaved)) :
9453 ((char) sym->stack)) & 0xff);
9454 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9458 /* we can just move _bp */
9459 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9461 /* fill the result with zero */
9462 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9467 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9473 /* object not on stack then we need the name */
9474 size = AOP_SIZE (IC_RESULT (ic));
9479 char s[SDCC_NAME_MAX];
9481 sprintf (s, "#(%s >> %d)",
9485 sprintf (s, "#%s", sym->rname);
9486 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9490 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9494 /*-----------------------------------------------------------------*/
9495 /* genFarFarAssign - assignment when both are in far space */
9496 /*-----------------------------------------------------------------*/
9498 genFarFarAssign (operand * result, operand * right, iCode * ic)
9500 int size = AOP_SIZE (right);
9504 D(emitcode ("; genFarFarAssign",""));
9506 /* first push the right side on to the stack */
9509 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9511 emitcode ("push", "acc");
9514 freeAsmop (right, NULL, ic, FALSE);
9515 /* now assign DPTR to result */
9516 aopOp (result, ic, FALSE);
9517 size = AOP_SIZE (result);
9520 emitcode ("pop", "acc");
9521 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9523 freeAsmop (result, NULL, ic, FALSE);
9527 /*-----------------------------------------------------------------*/
9528 /* genAssign - generate code for assignment */
9529 /*-----------------------------------------------------------------*/
9531 genAssign (iCode * ic)
9533 operand *result, *right;
9535 unsigned long lit = 0L;
9537 D(emitcode("; genAssign",""));
9539 result = IC_RESULT (ic);
9540 right = IC_RIGHT (ic);
9542 /* if they are the same */
9543 if (operandsEqu (result, right) &&
9544 !isOperandVolatile (result, FALSE) &&
9545 !isOperandVolatile (right, FALSE))
9548 aopOp (right, ic, FALSE);
9550 /* special case both in far space */
9551 if (AOP_TYPE (right) == AOP_DPTR &&
9552 IS_TRUE_SYMOP (result) &&
9553 isOperandInFarSpace (result))
9556 genFarFarAssign (result, right, ic);
9560 aopOp (result, ic, TRUE);
9562 /* if they are the same registers */
9563 if (sameRegs (AOP (right), AOP (result)) &&
9564 !isOperandVolatile (result, FALSE) &&
9565 !isOperandVolatile (right, FALSE))
9568 /* if the result is a bit */
9569 if (AOP_TYPE (result) == AOP_CRY)
9572 /* if the right size is a literal then
9573 we know what the value is */
9574 if (AOP_TYPE (right) == AOP_LIT)
9576 if (((int) operandLitValue (right)))
9577 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9579 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9583 /* the right is also a bit variable */
9584 if (AOP_TYPE (right) == AOP_CRY)
9586 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9587 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9593 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9597 /* bit variables done */
9599 size = AOP_SIZE (result);
9601 if (AOP_TYPE (right) == AOP_LIT)
9602 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9604 (AOP_TYPE (result) != AOP_REG) &&
9605 (AOP_TYPE (right) == AOP_LIT) &&
9606 !IS_FLOAT (operandType (right)) &&
9609 emitcode ("clr", "a");
9612 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9613 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9615 aopPut (AOP (result),
9616 aopGet (AOP (right), size, FALSE, FALSE),
9618 isOperandVolatile (result, FALSE));
9625 aopPut (AOP (result),
9626 aopGet (AOP (right), offset, FALSE, FALSE),
9628 isOperandVolatile (result, FALSE));
9634 freeAsmop (right, NULL, ic, TRUE);
9635 freeAsmop (result, NULL, ic, TRUE);
9638 /*-----------------------------------------------------------------*/
9639 /* genJumpTab - genrates code for jump table */
9640 /*-----------------------------------------------------------------*/
9642 genJumpTab (iCode * ic)
9644 symbol *jtab,*jtablo,*jtabhi;
9648 D(emitcode ("; genJumpTab",""));
9650 count = elementsInSet( IC_JTLABELS (ic) );
9654 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9655 if the switch argument is in a register.
9656 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9657 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9658 How will multiply by three be updated ???*/
9659 aopOp (IC_JTCOND (ic), ic, FALSE);
9660 /* get the condition into accumulator */
9661 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9663 /* multiply by three */
9664 emitcode ("add", "a,acc");
9665 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9666 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9668 jtab = newiTempLabel (NULL);
9669 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9670 emitcode ("jmp", "@a+dptr");
9671 emitcode ("", "%05d$:", jtab->key + 100);
9672 /* now generate the jump labels */
9673 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9674 jtab = setNextItem (IC_JTLABELS (ic)))
9675 emitcode ("ljmp", "%05d$", jtab->key + 100);
9679 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9680 if the switch argument is in a register.
9681 For n>6 this algorithm may be more compact */
9682 jtablo = newiTempLabel (NULL);
9683 jtabhi = newiTempLabel (NULL);
9685 /* get the condition into accumulator.
9686 Using b as temporary storage, if register push/pop is needed */
9687 aopOp (IC_JTCOND (ic), ic, FALSE);
9688 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9689 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9690 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9692 // (MB) what if B is in use???
9693 wassertl(!_G.BInUse, "B was in use");
9694 emitcode ("mov", "b,%s", l);
9697 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9701 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9702 emitcode ("movc", "a,@a+pc");
9703 emitcode ("push", "acc");
9706 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9707 emitcode ("movc", "a,@a+pc");
9708 emitcode ("push", "acc");
9712 /* this scales up to n<=255, but needs two more bytes
9714 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9715 emitcode ("movc", "a,@a+dptr");
9716 emitcode ("push", "acc");
9719 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9720 emitcode ("movc", "a,@a+dptr");
9721 emitcode ("push", "acc");
9724 emitcode ("ret", "");
9726 /* now generate jump table, LSB */
9727 emitcode ("", "%05d$:", jtablo->key + 100);
9728 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9729 jtab = setNextItem (IC_JTLABELS (ic)))
9730 emitcode (".db", "%05d$", jtab->key + 100);
9732 /* now generate jump table, MSB */
9733 emitcode ("", "%05d$:", jtabhi->key + 100);
9734 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9735 jtab = setNextItem (IC_JTLABELS (ic)))
9736 emitcode (".db", "%05d$>>8", jtab->key + 100);
9740 /*-----------------------------------------------------------------*/
9741 /* genCast - gen code for casting */
9742 /*-----------------------------------------------------------------*/
9744 genCast (iCode * ic)
9746 operand *result = IC_RESULT (ic);
9747 sym_link *ctype = operandType (IC_LEFT (ic));
9748 sym_link *rtype = operandType (IC_RIGHT (ic));
9749 operand *right = IC_RIGHT (ic);
9752 D(emitcode("; genCast",""));
9754 /* if they are equivalent then do nothing */
9755 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9758 aopOp (right, ic, FALSE);
9759 aopOp (result, ic, FALSE);
9761 /* if the result is a bit (and not a bitfield) */
9762 // if (AOP_TYPE (result) == AOP_CRY)
9763 if (IS_BITVAR (OP_SYMBOL (result)->type)
9764 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9766 /* if the right size is a literal then
9767 we know what the value is */
9768 if (AOP_TYPE (right) == AOP_LIT)
9770 if (((int) operandLitValue (right)))
9771 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9773 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9778 /* the right is also a bit variable */
9779 if (AOP_TYPE (right) == AOP_CRY)
9781 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9782 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9788 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9793 /* if they are the same size : or less */
9794 if (AOP_SIZE (result) <= AOP_SIZE (right))
9797 /* if they are in the same place */
9798 if (sameRegs (AOP (right), AOP (result)))
9801 /* if they in different places then copy */
9802 size = AOP_SIZE (result);
9806 aopPut (AOP (result),
9807 aopGet (AOP (right), offset, FALSE, FALSE),
9809 isOperandVolatile (result, FALSE));
9816 /* if the result is of type pointer */
9821 sym_link *type = operandType (right);
9822 sym_link *etype = getSpec (type);
9824 /* pointer to generic pointer */
9825 if (IS_GENPTR (ctype))
9828 p_type = DCL_TYPE (type);
9831 if (SPEC_SCLS(etype)==S_REGISTER) {
9832 // let's assume it is a generic pointer
9835 /* we have to go by the storage class */
9836 p_type = PTR_TYPE (SPEC_OCLS (etype));
9840 /* the first two bytes are known */
9841 size = GPTRSIZE - 1;
9845 aopPut (AOP (result),
9846 aopGet (AOP (right), offset, FALSE, FALSE),
9848 isOperandVolatile (result, FALSE));
9851 /* the last byte depending on type */
9853 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9858 // pointerTypeToGPByte will have bitched.
9862 sprintf(gpValStr, "#0x%d", gpVal);
9863 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9868 /* just copy the pointers */
9869 size = AOP_SIZE (result);
9873 aopPut (AOP (result),
9874 aopGet (AOP (right), offset, FALSE, FALSE),
9876 isOperandVolatile (result, FALSE));
9882 /* so we now know that the size of destination is greater
9883 than the size of the source */
9884 /* we move to result for the size of source */
9885 size = AOP_SIZE (right);
9889 aopPut (AOP (result),
9890 aopGet (AOP (right), offset, FALSE, FALSE),
9892 isOperandVolatile (result, FALSE));
9896 /* now depending on the sign of the source && destination */
9897 size = AOP_SIZE (result) - AOP_SIZE (right);
9898 /* if unsigned or not an integral type */
9899 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9902 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9906 /* we need to extend the sign :{ */
9907 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9910 emitcode ("rlc", "a");
9911 emitcode ("subb", "a,acc");
9913 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9916 /* we are done hurray !!!! */
9919 freeAsmop (right, NULL, ic, TRUE);
9920 freeAsmop (result, NULL, ic, TRUE);
9924 /*-----------------------------------------------------------------*/
9925 /* genDjnz - generate decrement & jump if not zero instrucion */
9926 /*-----------------------------------------------------------------*/
9928 genDjnz (iCode * ic, iCode * ifx)
9934 D(emitcode ("; genDjnz",""));
9936 /* if the if condition has a false label
9937 then we cannot save */
9941 /* if the minus is not of the form
9943 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9944 !IS_OP_LITERAL (IC_RIGHT (ic)))
9947 if (operandLitValue (IC_RIGHT (ic)) != 1)
9950 /* if the size of this greater than one then no
9952 if (getSize (operandType (IC_RESULT (ic))) > 1)
9955 /* otherwise we can save BIG */
9956 lbl = newiTempLabel (NULL);
9957 lbl1 = newiTempLabel (NULL);
9959 aopOp (IC_RESULT (ic), ic, FALSE);
9961 if (AOP_NEEDSACC(IC_RESULT(ic)))
9963 /* If the result is accessed indirectly via
9964 * the accumulator, we must explicitly write
9965 * it back after the decrement.
9967 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9969 if (strcmp(rByte, "a"))
9971 /* Something is hopelessly wrong */
9972 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9973 __FILE__, __LINE__);
9974 /* We can just give up; the generated code will be inefficient,
9977 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9980 emitcode ("dec", "%s", rByte);
9981 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9982 emitcode ("jnz", "%05d$", lbl->key + 100);
9984 else if (IS_AOP_PREG (IC_RESULT (ic)))
9986 emitcode ("dec", "%s",
9987 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9988 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9989 emitcode ("jnz", "%05d$", lbl->key + 100);
9993 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9996 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9997 emitcode ("", "%05d$:", lbl->key + 100);
9998 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9999 emitcode ("", "%05d$:", lbl1->key + 100);
10001 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10002 ifx->generated = 1;
10006 /*-----------------------------------------------------------------*/
10007 /* genReceive - generate code for a receive iCode */
10008 /*-----------------------------------------------------------------*/
10010 genReceive (iCode * ic)
10012 int size = getSize (operandType (IC_RESULT (ic)));
10014 D(emitcode ("; genReceive",""));
10016 if (ic->argreg == 1) { /* first parameter */
10017 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10018 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10019 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10022 int receivingA = 0;
10025 for (offset = 0; offset<size; offset++)
10026 if (!strcmp (fReturn[offset], "a"))
10031 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10033 for (offset = size-1; offset>0; offset--)
10034 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10035 emitcode("mov","a,%s", fReturn[0]);
10037 aopOp (IC_RESULT (ic), ic, FALSE);
10039 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10040 isOperandVolatile (IC_RESULT (ic), FALSE));
10041 for (offset = 1; offset<size; offset++)
10042 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10043 isOperandVolatile (IC_RESULT (ic), FALSE));
10049 if (getTempRegs(tempRegs, size, ic))
10051 for (offset = 0; offset<size; offset++)
10052 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10053 aopOp (IC_RESULT (ic), ic, FALSE);
10054 for (offset = 0; offset<size; offset++)
10055 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10056 isOperandVolatile (IC_RESULT (ic), FALSE));
10061 offset = fReturnSizeMCS51 - size;
10063 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10064 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10067 aopOp (IC_RESULT (ic), ic, FALSE);
10068 size = AOP_SIZE (IC_RESULT (ic));
10071 emitcode ("pop", "acc");
10072 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10077 aopOp (IC_RESULT (ic), ic, FALSE);
10079 assignResultValue (IC_RESULT (ic));
10081 } else { /* second receive onwards */
10083 aopOp (IC_RESULT (ic), ic, FALSE);
10084 rb1off = ic->argreg;
10086 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10091 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10094 /*-----------------------------------------------------------------*/
10095 /* genDummyRead - generate code for dummy read of volatiles */
10096 /*-----------------------------------------------------------------*/
10098 genDummyRead (iCode * ic)
10103 D(emitcode("; genDummyRead",""));
10105 op = IC_RIGHT (ic);
10106 if (op && IS_SYMOP (op))
10108 aopOp (op, ic, FALSE);
10110 /* if the result is a bit */
10111 if (AOP_TYPE (op) == AOP_CRY)
10112 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10115 /* bit variables done */
10117 size = AOP_SIZE (op);
10121 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10126 freeAsmop (op, NULL, ic, TRUE);
10130 if (op && IS_SYMOP (op))
10132 aopOp (op, ic, FALSE);
10134 /* if the result is a bit */
10135 if (AOP_TYPE (op) == AOP_CRY)
10136 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10139 /* bit variables done */
10141 size = AOP_SIZE (op);
10145 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10150 freeAsmop (op, NULL, ic, TRUE);
10154 /*-----------------------------------------------------------------*/
10155 /* genCritical - generate code for start of a critical sequence */
10156 /*-----------------------------------------------------------------*/
10158 genCritical (iCode *ic)
10160 symbol *tlbl = newiTempLabel (NULL);
10162 D(emitcode("; genCritical",""));
10164 if (IC_RESULT (ic))
10165 aopOp (IC_RESULT (ic), ic, TRUE);
10167 emitcode ("setb", "c");
10168 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10169 emitcode ("clr", "c");
10170 emitcode ("", "%05d$:", (tlbl->key + 100));
10172 if (IC_RESULT (ic))
10173 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
10175 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10177 if (IC_RESULT (ic))
10178 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10181 /*-----------------------------------------------------------------*/
10182 /* genEndCritical - generate code for end of a critical sequence */
10183 /*-----------------------------------------------------------------*/
10185 genEndCritical (iCode *ic)
10187 D(emitcode("; genEndCritical",""));
10191 aopOp (IC_RIGHT (ic), ic, FALSE);
10192 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10194 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10195 emitcode ("mov", "ea,c");
10199 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10200 emitcode ("rrc", "a");
10201 emitcode ("mov", "ea,c");
10203 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10207 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10208 emitcode ("mov", "ea,c");
10212 /*-----------------------------------------------------------------*/
10213 /* gen51Code - generate code for 8051 based controllers */
10214 /*-----------------------------------------------------------------*/
10216 gen51Code (iCode * lic)
10220 /* int cseq = 0; */
10222 _G.currentFunc = NULL;
10223 lineHead = lineCurr = NULL;
10225 /* print the allocation information */
10226 if (allocInfo && currFunc)
10227 printAllocInfo (currFunc, codeOutFile);
10228 /* if debug information required */
10229 if (options.debug && currFunc)
10231 debugFile->writeFunction (currFunc, lic);
10233 /* stack pointer name */
10234 if (options.useXstack)
10240 for (ic = lic; ic; ic = ic->next)
10242 _G.current_iCode = ic;
10244 if (ic->lineno && cln != ic->lineno)
10248 debugFile->writeCLine (ic);
10250 if (!options.noCcodeInAsm) {
10251 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10252 printCLine(ic->filename, ic->lineno));
10257 if (ic->seqPoint && ic->seqPoint != cseq)
10259 emitcode ("", "; sequence point %d", ic->seqPoint);
10260 cseq = ic->seqPoint;
10263 if (options.iCodeInAsm) {
10264 char regsInUse[80];
10267 for (i=0; i<8; i++) {
10268 sprintf (®sInUse[i],
10269 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10272 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10274 /* if the result is marked as
10275 spilt and rematerializable or code for
10276 this has already been generated then
10278 if (resultRemat (ic) || ic->generated)
10281 /* depending on the operation */
10301 /* IPOP happens only when trying to restore a
10302 spilt live range, if there is an ifx statement
10303 following this pop then the if statement might
10304 be using some of the registers being popped which
10305 would destory the contents of the register so
10306 we need to check for this condition and handle it */
10308 ic->next->op == IFX &&
10309 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10310 genIfx (ic->next, ic);
10328 genEndFunction (ic);
10348 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10365 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10369 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10376 /* note these two are xlated by algebraic equivalence
10377 during parsing SDCC.y */
10378 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10379 "got '>=' or '<=' shouldn't have come here");
10383 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10395 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10399 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10403 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10427 genRightShift (ic);
10430 case GET_VALUE_AT_ADDRESS:
10432 hasInc (IC_LEFT (ic), ic,
10433 getSize (operandType (IC_RESULT (ic)))),
10434 ifxForOp (IC_RESULT (ic), ic) );
10438 if (POINTER_SET (ic))
10439 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10465 addSet (&_G.sendSet, ic);
10468 case DUMMY_READ_VOLATILE:
10477 genEndCritical (ic);
10489 _G.current_iCode = NULL;
10491 /* now we are ready to call the
10492 peep hole optimizer */
10493 if (!options.nopeep)
10494 peepHole (&lineHead);
10496 /* now do the actual printing */
10497 printLine (lineHead, codeOutFile);