1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
75 short r0InB : 2;//2 so we can see it overflow
76 short r1InB : 2;//2 so we can see it overflow
77 short OpInB : 2;//2 so we can see it overflow
91 static char *rb1regs[] = {
92 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
95 extern int mcs51_ptrRegReq;
96 extern int mcs51_nRegs;
97 extern FILE *codeOutFile;
98 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, const char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
140 SNPRINTF (lb, sizeof(lb), "%s", inst);
141 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
144 tvsprintf (lb, sizeof(lb), fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
155 lineCurr->ic = _G.current_iCode;
156 lineCurr->isComment = (*lbp==';');
160 /*-----------------------------------------------------------------*/
161 /* mcs51_emitDebuggerSymbol - associate the current code location */
162 /* with a debugger symbol */
163 /*-----------------------------------------------------------------*/
165 mcs51_emitDebuggerSymbol (char * debugSym)
168 emitcode ("", "%s ==.", debugSym);
172 /*-----------------------------------------------------------------*/
173 /* mova - moves specified value into accumulator */
174 /*-----------------------------------------------------------------*/
178 /* do some early peephole optimization */
179 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
182 emitcode("mov","a,%s", x);
185 /*-----------------------------------------------------------------*/
186 /* pushB - saves register B if necessary */
187 /*-----------------------------------------------------------------*/
191 bool pushedB = FALSE;
195 emitcode ("push", "b");
196 // printf("B was in use !\n");
206 /*-----------------------------------------------------------------*/
207 /* popB - restores value of register B if necessary */
208 /*-----------------------------------------------------------------*/
214 emitcode ("pop", "b");
222 /*-----------------------------------------------------------------*/
223 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
224 /*-----------------------------------------------------------------*/
226 getFreePtr (iCode * ic, asmop ** aopp, bool result)
231 /* the logic: if r0 & r1 used in the instruction
232 then we are in trouble otherwise */
234 /* first check if r0 & r1 are used by this
235 instruction, in which case we are in trouble */
236 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
237 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
242 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
243 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
245 /* if no usage of r0 then return it */
248 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
249 (*aopp)->type = AOP_R0;
251 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
254 /* if no usage of r1 then return it */
257 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
258 (*aopp)->type = AOP_R1;
260 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
263 /* now we know they both have usage */
264 /* if r0 not used in this instruction */
267 /* push it if not already pushed */
270 emitcode ("mov", "b,%s",
271 mcs51_regWithIdx (R0_IDX)->dname);
274 else if (!_G.r0Pushed)
276 emitcode ("push", "%s",
277 mcs51_regWithIdx (R0_IDX)->dname);
281 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
282 (*aopp)->type = AOP_R0;
284 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
287 /* if r1 not used then */
291 /* push it if not already pushed */
294 emitcode ("mov", "b,%s",
295 mcs51_regWithIdx (R1_IDX)->dname);
298 else if (!_G.r1Pushed)
300 emitcode ("push", "%s",
301 mcs51_regWithIdx (R1_IDX)->dname);
305 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
306 (*aopp)->type = AOP_R1;
307 return mcs51_regWithIdx (R1_IDX);
310 /* I said end of world, but not quite end of world yet */
312 /* we can push it on the stack */
313 (*aopp)->type = AOP_STK;
316 /* in the case that result AND left AND right needs a pointer reg
317 we can safely use the result's */
318 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
319 (*aopp)->type = AOP_R0;
320 return mcs51_regWithIdx (R0_IDX);
322 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
323 (*aopp)->type = AOP_R1;
324 return mcs51_regWithIdx (R1_IDX);
328 /* now this is REALLY the end of the world */
329 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
330 "getFreePtr should never reach here");
335 /*-----------------------------------------------------------------*/
336 /* getTempRegs - initialize an array of pointers to GPR registers */
337 /* that are not in use. Returns 1 if the requested */
338 /* number of registers were available, 0 otherwise. */
339 /*-----------------------------------------------------------------*/
341 getTempRegs(regs **tempRegs, int size, iCode *ic)
348 ic = _G.current_iCode;
354 freeRegs = newBitVect(8);
355 bitVectSetBit (freeRegs, R2_IDX);
356 bitVectSetBit (freeRegs, R3_IDX);
357 bitVectSetBit (freeRegs, R4_IDX);
358 bitVectSetBit (freeRegs, R5_IDX);
359 bitVectSetBit (freeRegs, R6_IDX);
360 bitVectSetBit (freeRegs, R7_IDX);
362 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
364 bitVect * newfreeRegs;
365 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
366 freeBitVect(freeRegs);
367 freeRegs = newfreeRegs;
369 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
372 for (i=0; i<freeRegs->size; i++)
374 if (bitVectBitValue(freeRegs,i))
375 tempRegs[offset++] = mcs51_regWithIdx(i);
378 freeBitVect(freeRegs);
383 freeBitVect(freeRegs);
388 /*-----------------------------------------------------------------*/
389 /* newAsmop - creates a new asmOp */
390 /*-----------------------------------------------------------------*/
392 newAsmop (short type)
396 aop = Safe_calloc (1, sizeof (asmop));
401 /*-----------------------------------------------------------------*/
402 /* pointerCode - returns the code for a pointer type */
403 /*-----------------------------------------------------------------*/
405 pointerCode (sym_link * etype)
408 return PTR_TYPE (SPEC_OCLS (etype));
412 /*-----------------------------------------------------------------*/
413 /* leftRightUseAcc - returns size of accumulator use by operands */
414 /*-----------------------------------------------------------------*/
416 leftRightUseAcc(iCode *ic)
425 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
426 "null iCode pointer");
433 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
436 size = getSize (OP_SYMBOL (op)->type);
441 else if (ic->op == JUMPTABLE)
444 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
447 size = getSize (OP_SYMBOL (op)->type);
455 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
458 size = getSize (OP_SYMBOL (op)->type);
463 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
466 size = getSize (OP_SYMBOL (op)->type);
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol */
480 /*-----------------------------------------------------------------*/
482 aopForSym (iCode * ic, symbol * sym, bool result)
487 wassertl (ic != NULL, "Got a null iCode");
488 wassertl (sym != NULL, "Got a null symbol");
490 space = SPEC_OCLS (sym->etype);
492 /* if already has one */
496 /* assign depending on the storage class */
497 /* if it is on the stack or indirectly addressable */
498 /* space we need to assign either r0 or r1 to it */
499 if (sym->onStack || sym->iaccess)
501 sym->aop = aop = newAsmop (0);
502 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
503 aop->size = getSize (sym->type);
505 /* now assign the address of the variable to
506 the pointer register */
507 if (aop->type != AOP_STK)
512 if (_G.accInUse || leftRightUseAcc (ic))
513 emitcode ("push", "acc");
515 emitcode ("mov", "a,_bp");
516 emitcode ("add", "a,#0x%02x",
518 ((char) (sym->stack - _G.nRegsSaved)) :
519 ((char) sym->stack)) & 0xff);
520 emitcode ("mov", "%s,a",
521 aop->aopu.aop_ptr->name);
523 if (_G.accInUse || leftRightUseAcc (ic))
524 emitcode ("pop", "acc");
527 emitcode ("mov", "%s,#%s",
528 aop->aopu.aop_ptr->name,
530 aop->paged = space->paged;
533 aop->aopu.aop_stk = sym->stack;
537 /* if in bit space */
538 if (IN_BITSPACE (space))
540 sym->aop = aop = newAsmop (AOP_CRY);
541 aop->aopu.aop_dir = sym->rname;
542 aop->size = getSize (sym->type);
545 /* if it is in direct space */
546 if (IN_DIRSPACE (space))
548 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
549 //printTypeChainRaw(sym->type, NULL);
550 //printf("space = %s\n", space ? space->sname : "NULL");
551 sym->aop = aop = newAsmop (AOP_DIR);
552 aop->aopu.aop_dir = sym->rname;
553 aop->size = getSize (sym->type);
557 /* special case for a function */
558 if (IS_FUNC (sym->type))
560 sym->aop = aop = newAsmop (AOP_IMMD);
561 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
562 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
563 aop->size = FPTRSIZE;
567 /* only remaining is far space */
568 /* in which case DPTR gets the address */
569 sym->aop = aop = newAsmop (AOP_DPTR);
570 emitcode ("mov", "dptr,#%s", sym->rname);
571 aop->size = getSize (sym->type);
573 /* if it is in code space */
574 if (IN_CODESPACE (space))
580 /*-----------------------------------------------------------------*/
581 /* aopForRemat - rematerialzes an object */
582 /*-----------------------------------------------------------------*/
584 aopForRemat (symbol * sym)
586 iCode *ic = sym->rematiCode;
587 asmop *aop = newAsmop (AOP_IMMD);
594 val += (int) operandLitValue (IC_RIGHT (ic));
595 else if (ic->op == '-')
596 val -= (int) operandLitValue (IC_RIGHT (ic));
597 else if (IS_CAST_ICODE(ic)) {
598 sym_link *from_type = operandType(IC_RIGHT(ic));
599 aop->aopu.aop_immd.from_cast_remat = 1;
600 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
601 ptr_type = DCL_TYPE(from_type);
602 if (ptr_type == IPOINTER) {
609 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
613 sprintf (buffer, "(%s %c 0x%04x)",
614 OP_SYMBOL (IC_LEFT (ic))->rname,
615 val >= 0 ? '+' : '-',
618 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
620 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
621 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
622 /* set immd2 field if required */
623 if (aop->aopu.aop_immd.from_cast_remat) {
624 sprintf(buffer,"#0x%02x",ptr_type);
625 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
626 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
632 /*-----------------------------------------------------------------*/
633 /* regsInCommon - two operands have some registers in common */
634 /*-----------------------------------------------------------------*/
636 regsInCommon (operand * op1, operand * op2)
641 /* if they have registers in common */
642 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645 sym1 = OP_SYMBOL (op1);
646 sym2 = OP_SYMBOL (op2);
648 if (sym1->nRegs == 0 || sym2->nRegs == 0)
651 for (i = 0; i < sym1->nRegs; i++)
657 for (j = 0; j < sym2->nRegs; j++)
662 if (sym2->regs[j] == sym1->regs[i])
670 /*-----------------------------------------------------------------*/
671 /* operandsEqu - equivalent */
672 /*-----------------------------------------------------------------*/
674 operandsEqu (operand * op1, operand * op2)
678 /* if they're not symbols */
679 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
682 sym1 = OP_SYMBOL (op1);
683 sym2 = OP_SYMBOL (op2);
685 /* if both are itemps & one is spilt
686 and the other is not then false */
687 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
688 sym1->isspilt != sym2->isspilt)
691 /* if they are the same */
695 /* if they have the same rname */
696 if (sym1->rname[0] && sym2->rname[0]
697 && strcmp (sym1->rname, sym2->rname) == 0)
700 /* if left is a tmp & right is not */
701 if (IS_ITEMP (op1) &&
704 (sym1->usl.spillLoc == sym2))
707 if (IS_ITEMP (op2) &&
711 (sym2->usl.spillLoc == sym1))
717 /*-----------------------------------------------------------------*/
718 /* sameRegs - two asmops have the same registers */
719 /*-----------------------------------------------------------------*/
721 sameRegs (asmop * aop1, asmop * aop2)
728 if (aop1->type != AOP_REG ||
729 aop2->type != AOP_REG)
732 if (aop1->size != aop2->size)
735 for (i = 0; i < aop1->size; i++)
736 if (aop1->aopu.aop_reg[i] !=
737 aop2->aopu.aop_reg[i])
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand : */
745 /*-----------------------------------------------------------------*/
747 aopOp (operand * op, iCode * ic, bool result)
756 /* if this a literal */
757 if (IS_OP_LITERAL (op))
759 op->aop = aop = newAsmop (AOP_LIT);
760 aop->aopu.aop_lit = op->operand.valOperand;
761 aop->size = getSize (operandType (op));
765 /* if already has a asmop then continue */
769 /* if the underlying symbol has a aop */
770 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
772 op->aop = OP_SYMBOL (op)->aop;
776 /* if this is a true symbol */
777 if (IS_TRUE_SYMOP (op))
779 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
783 /* this is a temporary : this has
789 e) can be a return use only */
791 sym = OP_SYMBOL (op);
793 /* if the type is a conditional */
794 if (sym->regType == REG_CND)
796 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
801 /* if it is spilt then two situations
803 b) has a spill location */
804 if (sym->isspilt || sym->nRegs == 0)
807 /* rematerialize it NOW */
810 sym->aop = op->aop = aop =
812 aop->size = getSize (sym->type);
819 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
820 aop->size = getSize (sym->type);
821 for (i = 0; i < 2; i++)
822 aop->aopu.aop_str[i] = accUse[i];
830 aop = op->aop = sym->aop = newAsmop (AOP_STR);
831 aop->size = getSize (sym->type);
832 for (i = 0; i < fReturnSizeMCS51; i++)
833 aop->aopu.aop_str[i] = fReturn[i];
837 if (sym->usl.spillLoc)
839 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
841 /* force a new aop if sizes differ */
842 sym->usl.spillLoc->aop = NULL;
844 sym->aop = op->aop = aop =
845 aopForSym (ic, sym->usl.spillLoc, result);
846 aop->size = getSize (sym->type);
850 /* else must be a dummy iTemp */
851 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
852 aop->size = getSize (sym->type);
856 /* must be in a register */
857 sym->aop = op->aop = aop = newAsmop (AOP_REG);
858 aop->size = sym->nRegs;
859 for (i = 0; i < sym->nRegs; i++)
860 aop->aopu.aop_reg[i] = sym->regs[i];
863 /*-----------------------------------------------------------------*/
864 /* freeAsmop - free up the asmop given to an operand */
865 /*----------------------------------------------------------------*/
867 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
884 /* depending on the asmop type only three cases need work AOP_RO
885 , AOP_R1 && AOP_STK */
891 emitcode ("mov", "r0,b");
894 else if (_G.r0Pushed)
898 emitcode ("pop", "ar0");
902 bitVectUnSetBit (ic->rUsed, R0_IDX);
908 emitcode ("mov", "r1,b");
915 emitcode ("pop", "ar1");
919 bitVectUnSetBit (ic->rUsed, R1_IDX);
925 int stk = aop->aopu.aop_stk + aop->size - 1;
926 bitVectUnSetBit (ic->rUsed, R0_IDX);
927 bitVectUnSetBit (ic->rUsed, R1_IDX);
929 getFreePtr (ic, &aop, FALSE);
933 emitcode ("mov", "a,_bp");
934 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
935 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
939 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
944 emitcode ("pop", "acc");
945 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
948 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 freeAsmop (op, NULL, ic, TRUE);
954 emitcode ("pop", "ar1");
960 emitcode ("pop", "ar0");
967 /* all other cases just dealloc */
973 OP_SYMBOL (op)->aop = NULL;
974 /* if the symbol has a spill */
976 SPIL_LOC (op)->aop = NULL;
981 /*------------------------------------------------------------------*/
982 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
983 /* pop r0 or r1 off stack if pushed */
984 /*------------------------------------------------------------------*/
986 freeForBranchAsmop (operand * op)
1006 emitcode ("mov", "r0,b");
1008 else if (_G.r0Pushed)
1010 emitcode ("pop", "ar0");
1017 emitcode ("mov", "r1,b");
1019 else if (_G.r1Pushed)
1021 emitcode ("pop", "ar1");
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1030 emitcode ("mov", "b,r0");
1033 emitcode ("mov", "a,_bp");
1034 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1035 emitcode ("mov", "r0,a");
1039 emitcode ("mov", "r0,_bp");
1044 emitcode ("pop", "acc");
1045 emitcode ("mov", "@r0,a");
1048 emitcode ("dec", "r0");
1050 emitcode ("mov", "r0,b");
1056 /*-----------------------------------------------------------------*/
1057 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1058 /* clobber the accumulator */
1059 /*-----------------------------------------------------------------*/
1061 aopGetUsesAcc (asmop *aop, int offset)
1063 if (offset > (aop->size - 1))
1081 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1090 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1096 /* Error case --- will have been caught already */
1102 /*-----------------------------------------------------------------*/
1103 /* aopGet - for fetching value of the aop */
1104 /*-----------------------------------------------------------------*/
1106 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1111 /* offset is greater than
1113 if (offset > (aop->size - 1) &&
1114 aop->type != AOP_LIT)
1117 /* depending on type */
1125 /* if we need to increment it */
1126 while (offset > aop->coff)
1128 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1132 while (offset < aop->coff)
1134 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1141 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1142 return (dname ? "acc" : "a");
1144 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1145 rs = Safe_calloc (1, strlen (s) + 1);
1150 if (aop->code && aop->coff==0 && offset>=1) {
1151 emitcode ("mov", "a,#0x%02x", offset);
1152 emitcode ("movc", "a,@a+dptr");
1153 return (dname ? "acc" : "a");
1156 while (offset > aop->coff)
1158 emitcode ("inc", "dptr");
1162 while (offset < aop->coff)
1164 emitcode ("lcall", "__decdptr");
1171 emitcode ("clr", "a");
1172 emitcode ("movc", "a,@a+dptr");
1176 emitcode ("movx", "a,@dptr");
1178 return (dname ? "acc" : "a");
1182 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1183 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1185 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1187 sprintf (s, "#(%s >> %d)",
1188 aop->aopu.aop_immd.aop_immd1,
1192 aop->aopu.aop_immd.aop_immd1);
1193 rs = Safe_calloc (1, strlen (s) + 1);
1199 sprintf (s, "(%s + %d)",
1203 sprintf (s, "%s", aop->aopu.aop_dir);
1204 rs = Safe_calloc (1, strlen (s) + 1);
1210 return aop->aopu.aop_reg[offset]->dname;
1212 return aop->aopu.aop_reg[offset]->name;
1215 emitcode ("clr", "a");
1216 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1217 emitcode ("rlc", "a");
1218 return (dname ? "acc" : "a");
1221 if (!offset && dname)
1223 return aop->aopu.aop_str[offset];
1226 return aopLiteral (aop->aopu.aop_lit, offset);
1230 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1234 return aop->aopu.aop_str[offset];
1238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1239 "aopget got unsupported aop->type");
1242 /*-----------------------------------------------------------------*/
1243 /* aopPut - puts a string for a aop */
1244 /*-----------------------------------------------------------------*/
1246 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1250 if (aop->size && offset > (aop->size - 1))
1252 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1253 "aopPut got offset > aop->size");
1257 /* will assign value to value */
1258 /* depending on where it is ofcourse */
1262 MOVA (s); /* read s in case it was volatile */
1267 sprintf (d, "(%s + %d)",
1268 aop->aopu.aop_dir, offset);
1270 sprintf (d, "%s", aop->aopu.aop_dir);
1272 if (strcmp (d, s) ||
1274 emitcode ("mov", "%s,%s", d, s);
1279 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1280 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1283 strcmp (s, "r0") == 0 ||
1284 strcmp (s, "r1") == 0 ||
1285 strcmp (s, "r2") == 0 ||
1286 strcmp (s, "r3") == 0 ||
1287 strcmp (s, "r4") == 0 ||
1288 strcmp (s, "r5") == 0 ||
1289 strcmp (s, "r6") == 0 ||
1290 strcmp (s, "r7") == 0)
1291 emitcode ("mov", "%s,%s",
1292 aop->aopu.aop_reg[offset]->dname, s);
1294 emitcode ("mov", "%s,%s",
1295 aop->aopu.aop_reg[offset]->name, s);
1302 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1303 "aopPut writing to code space");
1307 while (offset > aop->coff)
1310 emitcode ("inc", "dptr");
1313 while (offset < aop->coff)
1316 emitcode ("lcall", "__decdptr");
1321 /* if not in accumulater */
1324 emitcode ("movx", "@dptr,a");
1329 while (offset > aop->coff)
1332 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1334 while (offset < aop->coff)
1337 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1344 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1350 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1352 else if (strcmp (s, "r0") == 0 ||
1353 strcmp (s, "r1") == 0 ||
1354 strcmp (s, "r2") == 0 ||
1355 strcmp (s, "r3") == 0 ||
1356 strcmp (s, "r4") == 0 ||
1357 strcmp (s, "r5") == 0 ||
1358 strcmp (s, "r6") == 0 ||
1359 strcmp (s, "r7") == 0)
1362 sprintf (buffer, "a%s", s);
1363 emitcode ("mov", "@%s,%s",
1364 aop->aopu.aop_ptr->name, buffer);
1367 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1372 if (strcmp (s, "a") == 0)
1373 emitcode ("push", "acc");
1377 emitcode ("push", "acc");
1379 emitcode ("push", s);
1385 /* if bit variable */
1386 if (!aop->aopu.aop_dir)
1388 emitcode ("clr", "a");
1389 emitcode ("rlc", "a");
1394 emitcode ("clr", "%s", aop->aopu.aop_dir);
1396 emitcode ("setb", "%s", aop->aopu.aop_dir);
1397 else if (!strcmp (s, "c"))
1398 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1401 if (strcmp (s, "a"))
1406 /* set C, if a >= 1 */
1407 emitcode ("add", "a,#0xff");
1408 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1416 if (strcmp (aop->aopu.aop_str[offset], s) ||
1418 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1423 if (!offset && (strcmp (s, "acc") == 0) &&
1427 if (strcmp (aop->aopu.aop_str[offset], s) &&
1429 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1433 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1434 "aopPut got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* pointToEnd :- points to the last byte of the operand */
1444 /*-----------------------------------------------------------------*/
1446 pointToEnd (asmop * aop)
1452 aop->coff = count = (aop->size - 1);
1458 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1462 emitcode ("inc", "dptr");
1469 /*-----------------------------------------------------------------*/
1470 /* reAdjustPreg - points a register back to where it should */
1471 /*-----------------------------------------------------------------*/
1473 reAdjustPreg (asmop * aop)
1475 if ((aop->coff==0) || aop->size <= 1)
1483 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1488 emitcode ("lcall", "__decdptr");
1495 #define AOP(op) op->aop
1496 #define AOP_TYPE(op) AOP(op)->type
1497 #define AOP_SIZE(op) AOP(op)->size
1498 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1499 AOP_TYPE(x) == AOP_R0))
1501 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1502 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1504 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1505 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1506 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is */
1511 /* a generic pointer type. */
1512 /*-----------------------------------------------------------------*/
1514 opIsGptr (operand * op)
1516 sym_link *type = operandType (op);
1518 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size */
1527 /*-----------------------------------------------------------------*/
1529 getDataSize (operand * op)
1532 size = AOP_SIZE (op);
1533 if (size == GPTRSIZE)
1535 sym_link *type = operandType (op);
1536 if (IS_GENPTR (type))
1538 /* generic pointer; arithmetic operations
1539 * should ignore the high byte (pointer type).
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc */
1549 /*-----------------------------------------------------------------*/
1551 outAcc (operand * result)
1554 size = getDataSize (result);
1557 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1560 /* unsigned or positive */
1563 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C */
1570 /*-----------------------------------------------------------------*/
1572 outBitC (operand * result)
1574 /* if the result is bit */
1575 if (AOP_TYPE (result) == AOP_CRY)
1576 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1579 emitcode ("clr", "a");
1580 emitcode ("rlc", "a");
1585 /*-----------------------------------------------------------------*/
1586 /* toBoolean - emit code for orl a,operator(sizeop) */
1587 /*-----------------------------------------------------------------*/
1589 toBoolean (operand * oper)
1591 int size = AOP_SIZE (oper) - 1;
1593 bool AccUsed = FALSE;
1596 while (!AccUsed && size--)
1598 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1601 size = AOP_SIZE (oper) - 1;
1603 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1604 if (AccUsed && (AOP (oper)->type != AOP_ACC))
1607 emitcode("mov", "b,a");
1610 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1611 emitcode ("orl", "b,a");
1619 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1625 /*-----------------------------------------------------------------*/
1626 /* genNot - generate code for ! operation */
1627 /*-----------------------------------------------------------------*/
1633 D(emitcode ("; genNot",""));
1635 /* assign asmOps to operand & result */
1636 aopOp (IC_LEFT (ic), ic, FALSE);
1637 aopOp (IC_RESULT (ic), ic, TRUE);
1639 /* if in bit space then a special case */
1640 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1643 emitcode ("cpl", "c");
1644 outBitC (IC_RESULT (ic));
1648 toBoolean (IC_LEFT (ic));
1650 tlbl = newiTempLabel (NULL);
1651 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1652 emitcode ("", "%05d$:", tlbl->key + 100);
1653 outBitC (IC_RESULT (ic));
1656 /* release the aops */
1657 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genCpl - generate code for complement */
1664 /*-----------------------------------------------------------------*/
1672 D(emitcode ("; genCpl",""));
1674 /* assign asmOps to operand & result */
1675 aopOp (IC_LEFT (ic), ic, FALSE);
1676 aopOp (IC_RESULT (ic), ic, TRUE);
1678 /* special case if in bit space */
1679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1681 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1683 /* promotion rules are responsible for this strange result: */
1684 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1688 tlbl=newiTempLabel(NULL);
1689 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1690 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1691 IS_AOP_PREG (IC_LEFT (ic)))
1693 emitcode ("cjne", "%s,#0x01,%05d$",
1694 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1699 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1701 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1703 emitcode ("", "%05d$:", tlbl->key + 100);
1704 outBitC (IC_RESULT(ic));
1708 size = AOP_SIZE (IC_RESULT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1713 emitcode ("cpl", "a");
1714 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1719 /* release the aops */
1720 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 /*-----------------------------------------------------------------*/
1725 /* genUminusFloat - unary minus for floating points */
1726 /*-----------------------------------------------------------------*/
1728 genUminusFloat (operand * op, operand * result)
1730 int size, offset = 0;
1733 D(emitcode ("; genUminusFloat",""));
1735 /* for this we just copy and then flip the bit */
1737 size = AOP_SIZE (op) - 1;
1741 aopPut (AOP (result),
1742 aopGet (AOP (op), offset, FALSE, FALSE),
1744 isOperandVolatile (result, FALSE));
1748 l = aopGet (AOP (op), offset, FALSE, FALSE);
1752 emitcode ("cpl", "acc.7");
1753 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1756 /*-----------------------------------------------------------------*/
1757 /* genUminus - unary minus code generation */
1758 /*-----------------------------------------------------------------*/
1760 genUminus (iCode * ic)
1763 sym_link *optype, *rtype;
1766 D(emitcode ("; genUminus",""));
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1770 aopOp (IC_RESULT (ic), ic, TRUE);
1772 /* if both in bit space then special
1774 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1775 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1778 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1779 emitcode ("cpl", "c");
1780 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1784 optype = operandType (IC_LEFT (ic));
1785 rtype = operandType (IC_RESULT (ic));
1787 /* if float then do float stuff */
1788 if (IS_FLOAT (optype))
1790 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1794 /* otherwise subtract from zero */
1795 size = AOP_SIZE (IC_LEFT (ic));
1800 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1801 if (!strcmp (l, "a"))
1805 emitcode ("cpl", "a");
1806 emitcode ("addc", "a,#0");
1812 emitcode ("clr", "a");
1813 emitcode ("subb", "a,%s", l);
1815 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1818 /* if any remaining bytes in the result */
1819 /* we just need to propagate the sign */
1820 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1822 emitcode ("rlc", "a");
1823 emitcode ("subb", "a,acc");
1825 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1829 /* release the aops */
1830 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1834 /*-----------------------------------------------------------------*/
1835 /* saveRegisters - will look for a call and save the registers */
1836 /*-----------------------------------------------------------------*/
1838 saveRegisters (iCode * lic)
1845 for (ic = lic; ic; ic = ic->next)
1846 if (ic->op == CALL || ic->op == PCALL)
1851 fprintf (stderr, "found parameter push with no function call\n");
1855 /* if the registers have been saved already or don't need to be then
1859 if (IS_SYMOP(IC_LEFT(ic)) &&
1860 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1861 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1864 /* save the registers in use at this time but skip the
1865 ones for the result */
1866 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1867 mcs51_rUmaskForOp (IC_RESULT(ic)));
1870 if (options.useXstack)
1872 if (bitVectBitValue (rsave, R0_IDX))
1874 emitcode ("mov", "a,r0");
1875 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1877 emitcode ("mov", "r0,%s", spname);
1878 for (i = 0; i < mcs51_nRegs; i++)
1880 if (bitVectBitValue (rsave, i))
1883 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1884 emitcode ("movx", "@r0,a");
1885 emitcode ("inc", "r0");
1888 emitcode ("mov", "%s,r0", spname);
1889 if (bitVectBitValue (rsave, R0_IDX))
1891 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1895 for (i = 0; i < mcs51_nRegs; i++)
1897 if (bitVectBitValue (rsave, i))
1898 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1902 /*-----------------------------------------------------------------*/
1903 /* unsaveRegisters - pop the pushed registers */
1904 /*-----------------------------------------------------------------*/
1906 unsaveRegisters (iCode * ic)
1911 /* restore the registers in use at this time but skip the
1912 ones for the result */
1913 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1914 mcs51_rUmaskForOp (IC_RESULT(ic)));
1916 if (options.useXstack)
1918 emitcode ("mov", "r0,%s", spname);
1919 for (i = mcs51_nRegs; i >= 0; i--)
1921 if (bitVectBitValue (rsave, i))
1923 emitcode ("dec", "r0");
1924 emitcode ("movx", "a,@r0");
1926 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1930 emitcode ("mov", "%s,r0", spname);
1931 if (bitVectBitValue (rsave, R0_IDX))
1933 emitcode ("mov", "r0,a");
1937 for (i = mcs51_nRegs; i >= 0; i--)
1939 if (bitVectBitValue (rsave, i))
1940 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1946 /*-----------------------------------------------------------------*/
1948 /*-----------------------------------------------------------------*/
1950 pushSide (operand * oper, int size)
1955 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1956 if (AOP_TYPE (oper) != AOP_REG &&
1957 AOP_TYPE (oper) != AOP_DIR &&
1961 emitcode ("push", "acc");
1964 emitcode ("push", "%s", l);
1968 /*-----------------------------------------------------------------*/
1969 /* assignResultValue - */
1970 /*-----------------------------------------------------------------*/
1972 assignResultValue (operand * oper)
1975 int size = AOP_SIZE (oper);
1978 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1984 /*-----------------------------------------------------------------*/
1985 /* genXpush - pushes onto the external stack */
1986 /*-----------------------------------------------------------------*/
1988 genXpush (iCode * ic)
1990 asmop *aop = newAsmop (0);
1992 int size, offset = 0;
1994 D(emitcode ("; genXpush",""));
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1997 r = getFreePtr (ic, &aop, FALSE);
2000 emitcode ("mov", "%s,_spx", r->name);
2002 size = AOP_SIZE (IC_LEFT (ic));
2006 char *l = aopGet (AOP (IC_LEFT (ic)),
2007 offset++, FALSE, FALSE);
2009 emitcode ("movx", "@%s,a", r->name);
2010 emitcode ("inc", "%s", r->name);
2015 emitcode ("mov", "_spx,%s", r->name);
2017 freeAsmop (NULL, aop, ic, TRUE);
2018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2021 /*-----------------------------------------------------------------*/
2022 /* genIpush - genrate code for pushing this gets a little complex */
2023 /*-----------------------------------------------------------------*/
2025 genIpush (iCode * ic)
2027 int size, offset = 0;
2030 D(emitcode ("; genIpush",""));
2032 /* if this is not a parm push : ie. it is spill push
2033 and spill push is always done on the local stack */
2037 /* and the item is spilt then do nothing */
2038 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2041 aopOp (IC_LEFT (ic), ic, FALSE);
2042 size = AOP_SIZE (IC_LEFT (ic));
2043 /* push it on the stack */
2046 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2052 emitcode ("push", "%s", l);
2057 /* this is a paramter push: in this case we call
2058 the routine to find the call and save those
2059 registers that need to be saved */
2062 /* if use external stack then call the external
2063 stack pushing routine */
2064 if (options.useXstack)
2070 /* then do the push */
2071 aopOp (IC_LEFT (ic), ic, FALSE);
2074 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2075 size = AOP_SIZE (IC_LEFT (ic));
2079 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2080 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2081 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2085 emitcode ("push", "acc");
2088 emitcode ("push", "%s", l);
2091 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2094 /*-----------------------------------------------------------------*/
2095 /* genIpop - recover the registers: can happen only for spilling */
2096 /*-----------------------------------------------------------------*/
2098 genIpop (iCode * ic)
2102 D(emitcode ("; genIpop",""));
2104 /* if the temp was not pushed then */
2105 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2108 aopOp (IC_LEFT (ic), ic, FALSE);
2109 size = AOP_SIZE (IC_LEFT (ic));
2110 offset = (size - 1);
2112 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2115 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2118 /*-----------------------------------------------------------------*/
2119 /* unsaveRBank - restores the resgister bank from stack */
2120 /*-----------------------------------------------------------------*/
2122 unsaveRBank (int bank, iCode * ic, bool popPsw)
2128 if (options.useXstack)
2132 /* Assume r0 is available for use. */
2133 r = mcs51_regWithIdx (R0_IDX);;
2138 r = getFreePtr (ic, &aop, FALSE);
2140 emitcode ("mov", "%s,_spx", r->name);
2145 if (options.useXstack)
2147 emitcode ("movx", "a,@%s", r->name);
2148 emitcode ("mov", "psw,a");
2149 emitcode ("dec", "%s", r->name);
2153 emitcode ("pop", "psw");
2157 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2159 if (options.useXstack)
2161 emitcode ("movx", "a,@%s", r->name);
2162 emitcode ("mov", "(%s+%d),a",
2163 regs8051[i].base, 8 * bank + regs8051[i].offset);
2164 emitcode ("dec", "%s", r->name);
2168 emitcode ("pop", "(%s+%d)",
2169 regs8051[i].base, 8 * bank + regs8051[i].offset);
2172 if (options.useXstack)
2174 emitcode ("mov", "_spx,%s", r->name);
2179 freeAsmop (NULL, aop, ic, TRUE);
2183 /*-----------------------------------------------------------------*/
2184 /* saveRBank - saves an entire register bank on the stack */
2185 /*-----------------------------------------------------------------*/
2187 saveRBank (int bank, iCode * ic, bool pushPsw)
2193 if (options.useXstack)
2197 /* Assume r0 is available for use. */
2198 r = mcs51_regWithIdx (R0_IDX);;
2203 r = getFreePtr (ic, &aop, FALSE);
2205 emitcode ("mov", "%s,_spx", r->name);
2208 for (i = 0; i < mcs51_nRegs; i++)
2210 if (options.useXstack)
2212 emitcode ("inc", "%s", r->name);
2213 emitcode ("mov", "a,(%s+%d)",
2214 regs8051[i].base, 8 * bank + regs8051[i].offset);
2215 emitcode ("movx", "@%s,a", r->name);
2218 emitcode ("push", "(%s+%d)",
2219 regs8051[i].base, 8 * bank + regs8051[i].offset);
2224 if (options.useXstack)
2226 emitcode ("mov", "a,psw");
2227 emitcode ("movx", "@%s,a", r->name);
2228 emitcode ("inc", "%s", r->name);
2229 emitcode ("mov", "_spx,%s", r->name);
2234 emitcode ("push", "psw");
2237 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2242 freeAsmop (NULL, aop, ic, TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* genSend - gen code for SEND */
2253 /*-----------------------------------------------------------------*/
2254 static void genSend(set *sendSet)
2259 for (sic = setFirstItem (sendSet); sic;
2260 sic = setNextItem (sendSet)) {
2261 int size, offset = 0;
2262 aopOp (IC_LEFT (sic), sic, FALSE);
2263 size = AOP_SIZE (IC_LEFT (sic));
2265 if (sic->argreg == 1) {
2267 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2269 if (strcmp (l, fReturn[offset]))
2270 emitcode ("mov", "%s,%s", fReturn[offset], l);
2276 emitcode ("mov","b1_%d,%s",rb1_count++,
2277 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2280 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2284 /*-----------------------------------------------------------------*/
2285 /* genCall - generates a call statement */
2286 /*-----------------------------------------------------------------*/
2288 genCall (iCode * ic)
2291 // bool restoreBank = FALSE;
2292 bool swapBanks = FALSE;
2294 D(emitcode("; genCall",""));
2296 dtype = operandType (IC_LEFT (ic));
2297 /* if send set is not empty then assign */
2300 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2301 genSend(reverseSet(_G.sendSet));
2303 genSend(_G.sendSet);
2309 /* if we are calling a not _naked function that is not using
2310 the same register bank then we need to save the
2311 destination registers on the stack */
2312 dtype = operandType (IC_LEFT (ic));
2313 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2314 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2315 !IFFUNC_ISISR (dtype))
2320 /* if caller saves & we have not saved then */
2326 emitcode ("mov", "psw,#0x%02x",
2327 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2331 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2332 OP_SYMBOL (IC_LEFT (ic))->rname :
2333 OP_SYMBOL (IC_LEFT (ic))->name));
2337 emitcode ("mov", "psw,#0x%02x",
2338 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2341 /* if we need assign a result value */
2342 if ((IS_ITEMP (IC_RESULT (ic)) &&
2343 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2344 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2345 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2346 IS_TRUE_SYMOP (IC_RESULT (ic)))
2350 aopOp (IC_RESULT (ic), ic, FALSE);
2353 assignResultValue (IC_RESULT (ic));
2355 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2358 /* adjust the stack for parameters if
2363 if (ic->parmBytes > 3)
2365 emitcode ("mov", "a,%s", spname);
2366 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2367 emitcode ("mov", "%s,a", spname);
2370 for (i = 0; i < ic->parmBytes; i++)
2371 emitcode ("dec", "%s", spname);
2374 /* if we hade saved some registers then unsave them */
2375 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2376 unsaveRegisters (ic);
2378 // /* if register bank was saved then pop them */
2380 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2383 /*-----------------------------------------------------------------*/
2384 /* -10l - generates a call by pointer statement */
2385 /*-----------------------------------------------------------------*/
2387 genPcall (iCode * ic)
2390 symbol *rlbl = newiTempLabel (NULL);
2391 // bool restoreBank=FALSE;
2392 bool swapBanks = FALSE;
2394 D(emitcode("; genPCall",""));
2396 /* if caller saves & we have not saved then */
2400 /* if we are calling a not _naked function that is not using
2401 the same register bank then we need to save the
2402 destination registers on the stack */
2403 dtype = operandType (IC_LEFT (ic))->next;
2404 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2405 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2406 !IFFUNC_ISISR (dtype))
2408 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2409 // restoreBank=TRUE;
2411 // need caution message to user here
2414 /* push the return address on to the stack */
2415 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2416 emitcode ("push", "acc");
2417 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2418 emitcode ("push", "acc");
2420 /* now push the calling address */
2421 aopOp (IC_LEFT (ic), ic, FALSE);
2423 pushSide (IC_LEFT (ic), FPTRSIZE);
2425 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2427 /* if send set is not empty the assign */
2430 genSend(reverseSet(_G.sendSet));
2436 emitcode ("mov", "psw,#0x%02x",
2437 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2441 emitcode ("ret", "");
2442 emitcode ("", "%05d$:", (rlbl->key + 100));
2447 emitcode ("mov", "psw,#0x%02x",
2448 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2451 /* if we need assign a result value */
2452 if ((IS_ITEMP (IC_RESULT (ic)) &&
2453 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2454 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2455 IS_TRUE_SYMOP (IC_RESULT (ic)))
2459 aopOp (IC_RESULT (ic), ic, FALSE);
2462 assignResultValue (IC_RESULT (ic));
2464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2467 /* adjust the stack for parameters if
2472 if (ic->parmBytes > 3)
2474 emitcode ("mov", "a,%s", spname);
2475 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2476 emitcode ("mov", "%s,a", spname);
2479 for (i = 0; i < ic->parmBytes; i++)
2480 emitcode ("dec", "%s", spname);
2484 // /* if register bank was saved then unsave them */
2486 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2488 /* if we hade saved some registers then
2490 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2491 unsaveRegisters (ic);
2494 /*-----------------------------------------------------------------*/
2495 /* resultRemat - result is rematerializable */
2496 /*-----------------------------------------------------------------*/
2498 resultRemat (iCode * ic)
2500 if (SKIP_IC (ic) || ic->op == IFX)
2503 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2505 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2506 if (sym->remat && !POINTER_SET (ic))
2513 #if defined(__BORLANDC__) || defined(_MSC_VER)
2514 #define STRCASECMP stricmp
2516 #define STRCASECMP strcasecmp
2519 /*-----------------------------------------------------------------*/
2520 /* inExcludeList - return 1 if the string is in exclude Reg list */
2521 /*-----------------------------------------------------------------*/
2523 regsCmp(void *p1, void *p2)
2525 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2529 inExcludeList (char *s)
2531 const char *p = setFirstItem(options.excludeRegsSet);
2533 if (p == NULL || STRCASECMP(p, "none") == 0)
2537 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2540 /*-----------------------------------------------------------------*/
2541 /* genFunction - generated code for function entry */
2542 /*-----------------------------------------------------------------*/
2544 genFunction (iCode * ic)
2546 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2548 bool switchedPSW = FALSE;
2549 int calleesaves_saved_register = -1;
2550 int stackAdjust = sym->stack;
2551 int accIsFree = sym->recvSize < 4;
2552 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2555 /* create the function header */
2556 emitcode (";", "-----------------------------------------");
2557 emitcode (";", " function %s", sym->name);
2558 emitcode (";", "-----------------------------------------");
2560 emitcode ("", "%s:", sym->rname);
2561 ftype = operandType (IC_LEFT (ic));
2562 _G.currentFunc = sym;
2564 if (IFFUNC_ISNAKED(ftype))
2566 emitcode(";", "naked function: no prologue.");
2570 /* here we need to generate the equates for the
2571 register bank if required */
2572 if (FUNC_REGBANK (ftype) != rbank)
2576 rbank = FUNC_REGBANK (ftype);
2577 for (i = 0; i < mcs51_nRegs; i++)
2579 if (strcmp (regs8051[i].base, "0") == 0)
2580 emitcode ("", "%s = 0x%02x",
2582 8 * rbank + regs8051[i].offset);
2584 emitcode ("", "%s = %s + 0x%02x",
2587 8 * rbank + regs8051[i].offset);
2591 /* if this is an interrupt service routine then
2592 save acc, b, dpl, dph */
2593 if (IFFUNC_ISISR (sym->type))
2596 if (!inExcludeList ("acc"))
2597 emitcode ("push", "acc");
2598 if (!inExcludeList ("b"))
2599 emitcode ("push", "b");
2600 if (!inExcludeList ("dpl"))
2601 emitcode ("push", "dpl");
2602 if (!inExcludeList ("dph"))
2603 emitcode ("push", "dph");
2604 /* if this isr has no bank i.e. is going to
2605 run with bank 0 , then we need to save more
2607 if (!FUNC_REGBANK (sym->type))
2610 /* if this function does not call any other
2611 function then we can be economical and
2612 save only those registers that are used */
2613 if (!IFFUNC_HASFCALL(sym->type))
2617 /* if any registers used */
2620 /* save the registers used */
2621 for (i = 0; i < sym->regsUsed->size; i++)
2623 if (bitVectBitValue (sym->regsUsed, i))
2624 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2631 /* this function has a function call. We cannot
2632 determines register usage so we will have to push the
2634 saveRBank (0, ic, FALSE);
2635 if (options.parms_in_bank1) {
2637 for (i=0; i < 8 ; i++ ) {
2638 emitcode ("push","%s",rb1regs[i]);
2645 /* This ISR uses a non-zero bank.
2647 * We assume that the bank is available for our
2650 * However, if this ISR calls a function which uses some
2651 * other bank, we must save that bank entirely.
2653 unsigned long banksToSave = 0;
2655 if (IFFUNC_HASFCALL(sym->type))
2658 #define MAX_REGISTER_BANKS 4
2663 for (i = ic; i; i = i->next)
2665 if (i->op == ENDFUNCTION)
2667 /* we got to the end OK. */
2675 dtype = operandType (IC_LEFT(i));
2677 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2679 /* Mark this bank for saving. */
2680 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2682 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2686 banksToSave |= (1 << FUNC_REGBANK(dtype));
2689 /* And note that we don't need to do it in
2697 /* This is a mess; we have no idea what
2698 * register bank the called function might
2701 * The only thing I can think of to do is
2702 * throw a warning and hope.
2704 werror(W_FUNCPTR_IN_USING_ISR);
2708 if (banksToSave && options.useXstack)
2710 /* Since we aren't passing it an ic,
2711 * saveRBank will assume r0 is available to abuse.
2713 * So switch to our (trashable) bank now, so
2714 * the caller's R0 isn't trashed.
2716 emitcode ("push", "psw");
2717 emitcode ("mov", "psw,#0x%02x",
2718 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2722 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2724 if (banksToSave & (1 << ix))
2726 saveRBank(ix, NULL, FALSE);
2730 // TODO: this needs a closer look
2731 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2734 /* Set the register bank to the desired value if nothing else */
2735 /* has done so yet. */
2738 emitcode ("push", "psw");
2739 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2744 /* This is a non-ISR function. The caller has already switched register */
2745 /* banks, if necessary, so just handle the callee-saves option. */
2747 /* if callee-save to be used for this function
2748 then save the registers being used in this function */
2749 if (IFFUNC_CALLEESAVES(sym->type))
2753 /* if any registers used */
2756 /* save the registers used */
2757 for (i = 0; i < sym->regsUsed->size; i++)
2759 if (bitVectBitValue (sym->regsUsed, i))
2761 /* remember one saved register for later usage */
2762 if (calleesaves_saved_register < 0)
2763 calleesaves_saved_register = i;
2764 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2775 if (options.useXstack)
2777 emitcode ("inc", "%s", spname);
2778 emitcode ("mov", "r0,%s", spname);
2779 emitcode ("xch", "a,_bp");
2780 emitcode ("movx", "@r0,a");
2781 emitcode ("mov", "a,r0");
2782 emitcode ("xch", "a,_bp");
2786 /* set up the stack */
2787 emitcode ("push", "_bp"); /* save the callers stack */
2788 emitcode ("mov", "_bp,%s", spname);
2792 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2793 /* before setting up the stack frame completely. */
2794 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2796 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2800 if (rsym && rsym->regType == REG_CND)
2802 if (rsym && (rsym->accuse || rsym->ruonly))
2804 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2805 rsym = rsym->usl.spillLoc;
2808 /* If the RECEIVE operand immediately spills to the first entry on the */
2809 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2810 /* rather than the usual @r0/r1 machinations. */
2811 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2815 _G.current_iCode = ric;
2816 D(emitcode ("; genReceive",""));
2817 for (ofs=0; ofs < sym->recvSize; ofs++)
2819 if (!strcmp (fReturn[ofs], "a"))
2820 emitcode ("push", "acc");
2822 emitcode ("push", fReturn[ofs]);
2824 stackAdjust -= sym->recvSize;
2827 assert (stackAdjust>=0);
2830 _G.current_iCode = ic;
2834 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2835 /* to free up the accumulator. */
2836 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2840 _G.current_iCode = ric;
2841 D(emitcode ("; genReceive",""));
2842 for (ofs=0; ofs < sym->recvSize; ofs++)
2844 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2846 _G.current_iCode = ic;
2852 /* adjust the stack for the function */
2855 int i = stackAdjust;
2857 werror (W_STACK_OVERFLOW, sym->name);
2859 if (i > 3 && accIsFree)
2862 emitcode ("mov", "a,sp");
2863 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2864 emitcode ("mov", "sp,a");
2869 /* The accumulator is not free, so we will need another register */
2870 /* to clobber. No need to worry about a possible conflict with */
2871 /* the above early RECEIVE optimizations since they would have */
2872 /* freed the accumulator if they were generated. */
2874 if (IFFUNC_CALLEESAVES(sym->type))
2876 /* if it's a callee-saves function we need a saved register */
2877 if (calleesaves_saved_register >= 0)
2879 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2880 emitcode ("mov", "a,sp");
2881 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2882 emitcode ("mov", "sp,a");
2883 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2886 /* do it the hard way */
2888 emitcode ("inc", "sp");
2892 /* not callee-saves, we can clobber r0 */
2893 emitcode ("mov", "r0,a");
2894 emitcode ("mov", "a,sp");
2895 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2896 emitcode ("mov", "sp,a");
2897 emitcode ("mov", "a,r0");
2902 emitcode ("inc", "sp");
2909 emitcode ("push", "acc");
2910 emitcode ("mov", "a,_spx");
2911 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2912 emitcode ("mov", "_spx,a");
2914 emitcode ("pop", "acc");
2917 /* if critical function then turn interrupts off */
2918 if (IFFUNC_ISCRITICAL (ftype))
2920 symbol *tlbl = newiTempLabel (NULL);
2921 emitcode ("setb", "c");
2922 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2923 emitcode ("clr", "c");
2924 emitcode ("", "%05d$:", (tlbl->key + 100));
2925 emitcode ("push", "psw"); /* save old ea via c in psw */
2929 /*-----------------------------------------------------------------*/
2930 /* genEndFunction - generates epilogue for functions */
2931 /*-----------------------------------------------------------------*/
2933 genEndFunction (iCode * ic)
2935 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2936 lineNode *lnp = lineCurr;
2938 bitVect *regsUsedPrologue;
2939 bitVect *regsUnneeded;
2940 int accIsFree = sym->recvSize < 4;
2943 _G.currentFunc = NULL;
2944 if (IFFUNC_ISNAKED(sym->type))
2946 emitcode(";", "naked function: no epilogue.");
2947 if (options.debug && currFunc)
2948 debugFile->writeEndFunction (currFunc, ic, 0);
2952 if (IFFUNC_ISCRITICAL (sym->type))
2954 emitcode ("pop", "psw"); /* restore ea via c in psw */
2955 emitcode ("mov", "ea,c");
2958 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2960 emitcode ("mov", "%s,_bp", spname);
2963 /* if use external stack but some variables were
2964 added to the local stack then decrement the
2966 if (options.useXstack && sym->stack)
2969 emitcode ("push", "acc");
2970 emitcode ("mov", "a,sp");
2971 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2972 emitcode ("mov", "sp,a");
2974 emitcode ("pop", "acc");
2977 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2979 if (options.useXstack)
2981 emitcode ("xch", "a,_bp");
2982 emitcode ("mov", "r0,%s", spname);
2983 emitcode ("movx", "a,@r0");
2984 emitcode ("xch", "a,_bp");
2985 emitcode ("dec", "%s", spname); //read before freeing stack space (interrupts)
2989 emitcode ("pop", "_bp");
2993 /* restore the register bank */
2994 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2996 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2997 || !options.useXstack)
2999 /* Special case of ISR using non-zero bank with useXstack
3002 emitcode ("pop", "psw");
3006 if (IFFUNC_ISISR (sym->type))
3009 /* now we need to restore the registers */
3010 /* if this isr has no bank i.e. is going to
3011 run with bank 0 , then we need to save more
3013 if (!FUNC_REGBANK (sym->type))
3015 /* if this function does not call any other
3016 function then we can be economical and
3017 save only those registers that are used */
3018 if (!IFFUNC_HASFCALL(sym->type))
3022 /* if any registers used */
3025 /* save the registers used */
3026 for (i = sym->regsUsed->size; i >= 0; i--)
3028 if (bitVectBitValue (sym->regsUsed, i))
3029 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3035 if (options.parms_in_bank1) {
3037 for (i = 7 ; i >= 0 ; i-- ) {
3038 emitcode ("pop","%s",rb1regs[i]);
3041 /* this function has a function call cannot
3042 determines register usage so we will have to pop the
3044 unsaveRBank (0, ic, FALSE);
3049 /* This ISR uses a non-zero bank.
3051 * Restore any register banks saved by genFunction
3054 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3057 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3059 if (savedBanks & (1 << ix))
3061 unsaveRBank(ix, NULL, FALSE);
3065 if (options.useXstack)
3067 /* Restore bank AFTER calling unsaveRBank,
3068 * since it can trash r0.
3070 emitcode ("pop", "psw");
3074 if (!inExcludeList ("dph"))
3075 emitcode ("pop", "dph");
3076 if (!inExcludeList ("dpl"))
3077 emitcode ("pop", "dpl");
3078 if (!inExcludeList ("b"))
3079 emitcode ("pop", "b");
3080 if (!inExcludeList ("acc"))
3081 emitcode ("pop", "acc");
3083 /* if debug then send end of function */
3084 if (options.debug && currFunc)
3086 debugFile->writeEndFunction (currFunc, ic, 1);
3089 emitcode ("reti", "");
3093 if (IFFUNC_CALLEESAVES(sym->type))
3097 /* if any registers used */
3100 /* save the registers used */
3101 for (i = sym->regsUsed->size; i >= 0; i--)
3103 if (bitVectBitValue (sym->regsUsed, i) ||
3104 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3105 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3108 else if (mcs51_ptrRegReq)
3110 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3111 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3116 /* if debug then send end of function */
3117 if (options.debug && currFunc)
3119 debugFile->writeEndFunction (currFunc, ic, 1);
3122 emitcode ("ret", "");
3125 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3128 /* If this was an interrupt handler using bank 0 that called another */
3129 /* function, then all registers must be saved; nothing to optimized. */
3130 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3131 && !FUNC_REGBANK(sym->type))
3134 /* There are no push/pops to optimize if not callee-saves or ISR */
3135 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3138 /* If there were stack parameters, we cannot optimize without also */
3139 /* fixing all of the stack offsets; this is too dificult to consider. */
3140 if (FUNC_HASSTACKPARM(sym->type))
3143 /* Compute the registers actually used */
3144 regsUsed = newBitVect (mcs51_nRegs);
3145 regsUsedPrologue = newBitVect (mcs51_nRegs);
3148 if (lnp->ic && lnp->ic->op == FUNCTION)
3149 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3151 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3153 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3154 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3161 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3162 && !bitVectBitValue (regsUsed, CND_IDX))
3164 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3165 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3166 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3167 bitVectUnSetBit (regsUsed, CND_IDX);
3170 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3172 /* If this was an interrupt handler that called another function */
3173 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3174 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3176 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3177 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3178 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3179 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3180 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3183 /* Remove the unneeded push/pops */
3184 regsUnneeded = newBitVect (mcs51_nRegs);
3187 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3189 if (!strncmp(lnp->line, "push", 4))
3191 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3192 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3194 connectLine (lnp->prev, lnp->next);
3195 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3198 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3200 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3201 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3203 connectLine (lnp->prev, lnp->next);
3204 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3211 for (idx = 0; idx < regsUnneeded->size; idx++)
3212 if (bitVectBitValue (regsUnneeded, idx))
3213 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3215 freeBitVect (regsUnneeded);
3216 freeBitVect (regsUsed);
3217 freeBitVect (regsUsedPrologue);
3220 /*-----------------------------------------------------------------*/
3221 /* genRet - generate code for return statement */
3222 /*-----------------------------------------------------------------*/
3226 int size, offset = 0, pushed = 0;
3228 D(emitcode ("; genRet",""));
3230 /* if we have no return value then
3231 just generate the "ret" */
3235 /* we have something to return then
3236 move the return value into place */
3237 aopOp (IC_LEFT (ic), ic, FALSE);
3238 size = AOP_SIZE (IC_LEFT (ic));
3243 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3246 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3248 emitcode ("push", "%s", l);
3253 l = aopGet (AOP (IC_LEFT (ic)), offset,
3255 if (strcmp (fReturn[offset], l))
3256 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3265 if (strcmp (fReturn[pushed], "a"))
3266 emitcode ("pop", fReturn[pushed]);
3268 emitcode ("pop", "acc");
3271 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3274 /* generate a jump to the return label
3275 if the next is not the return statement */
3276 if (!(ic->next && ic->next->op == LABEL &&
3277 IC_LABEL (ic->next) == returnLabel))
3279 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3283 /*-----------------------------------------------------------------*/
3284 /* genLabel - generates a label */
3285 /*-----------------------------------------------------------------*/
3287 genLabel (iCode * ic)
3289 /* special case never generate */
3290 if (IC_LABEL (ic) == entryLabel)
3293 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3296 /*-----------------------------------------------------------------*/
3297 /* genGoto - generates a ljmp */
3298 /*-----------------------------------------------------------------*/
3300 genGoto (iCode * ic)
3302 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3305 /*-----------------------------------------------------------------*/
3306 /* findLabelBackwards: walks back through the iCode chain looking */
3307 /* for the given label. Returns number of iCode instructions */
3308 /* between that label and given ic. */
3309 /* Returns zero if label not found. */
3310 /*-----------------------------------------------------------------*/
3312 findLabelBackwards (iCode * ic, int key)
3321 /* If we have any pushes or pops, we cannot predict the distance.
3322 I don't like this at all, this should be dealt with in the
3324 if (ic->op == IPUSH || ic->op == IPOP) {
3328 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3337 /*-----------------------------------------------------------------*/
3338 /* genPlusIncr :- does addition with increment if possible */
3339 /*-----------------------------------------------------------------*/
3341 genPlusIncr (iCode * ic)
3343 unsigned int icount;
3344 unsigned int size = getDataSize (IC_RESULT (ic));
3346 /* will try to generate an increment */
3347 /* if the right side is not a literal
3349 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3352 /* if the literal value of the right hand side
3353 is greater than 4 then it is not worth it */
3354 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3357 D(emitcode ("; genPlusIncr",""));
3359 /* if increment >=16 bits in register or direct space */
3360 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3361 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3369 /* If the next instruction is a goto and the goto target
3370 * is < 10 instructions previous to this, we can generate
3371 * jumps straight to that target.
3373 if (ic->next && ic->next->op == GOTO
3374 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3375 && labelRange <= 10)
3377 emitcode (";", "tail increment optimized");
3378 tlbl = IC_LABEL (ic->next);
3383 tlbl = newiTempLabel (NULL);
3386 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3387 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3388 IS_AOP_PREG (IC_RESULT (ic)))
3389 emitcode ("cjne", "%s,#0x00,%05d$",
3390 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3394 emitcode ("clr", "a");
3395 emitcode ("cjne", "a,%s,%05d$",
3396 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3400 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3403 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3404 IS_AOP_PREG (IC_RESULT (ic)))
3405 emitcode ("cjne", "%s,#0x00,%05d$",
3406 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3409 emitcode ("cjne", "a,%s,%05d$",
3410 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3413 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3417 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3418 IS_AOP_PREG (IC_RESULT (ic)))
3419 emitcode ("cjne", "%s,#0x00,%05d$",
3420 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3424 emitcode ("cjne", "a,%s,%05d$",
3425 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3428 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3433 emitcode ("", "%05d$:", tlbl->key + 100);
3438 /* if the sizes are greater than 1 then we cannot */
3439 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3440 AOP_SIZE (IC_LEFT (ic)) > 1)
3443 /* we can if the aops of the left & result match or
3444 if they are in registers and the registers are the
3446 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3451 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3452 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3453 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3459 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3468 /*-----------------------------------------------------------------*/
3469 /* outBitAcc - output a bit in acc */
3470 /*-----------------------------------------------------------------*/
3472 outBitAcc (operand * result)
3474 symbol *tlbl = newiTempLabel (NULL);
3475 /* if the result is a bit */
3476 if (AOP_TYPE (result) == AOP_CRY)
3478 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3482 emitcode ("jz", "%05d$", tlbl->key + 100);
3483 emitcode ("mov", "a,%s", one);
3484 emitcode ("", "%05d$:", tlbl->key + 100);
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusBits - generates code for addition of two bits */
3491 /*-----------------------------------------------------------------*/
3493 genPlusBits (iCode * ic)
3495 D(emitcode ("; genPlusBits",""));
3497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3499 symbol *lbl = newiTempLabel (NULL);
3500 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3501 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3502 emitcode ("cpl", "c");
3503 emitcode ("", "%05d$:", (lbl->key + 100));
3504 outBitC (IC_RESULT (ic));
3508 emitcode ("clr", "a");
3509 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510 emitcode ("rlc", "a");
3511 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3512 emitcode ("addc", "a,#0x00");
3513 outAcc (IC_RESULT (ic));
3518 /* This is the original version of this code.
3520 * This is being kept around for reference,
3521 * because I am not entirely sure I got it right...
3524 adjustArithmeticResult (iCode * ic)
3526 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3527 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3528 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3529 aopPut (AOP (IC_RESULT (ic)),
3530 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3532 isOperandVolatile (IC_RESULT (ic), FALSE));
3534 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3535 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3536 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3537 aopPut (AOP (IC_RESULT (ic)),
3538 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3540 isOperandVolatile (IC_RESULT (ic), FALSE));
3542 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3543 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3544 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3545 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3546 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3549 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3550 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 /* This is the pure and virtuous version of this code.
3555 * I'm pretty certain it's right, but not enough to toss the old
3559 adjustArithmeticResult (iCode * ic)
3561 if (opIsGptr (IC_RESULT (ic)) &&
3562 opIsGptr (IC_LEFT (ic)) &&
3563 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3565 aopPut (AOP (IC_RESULT (ic)),
3566 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3568 isOperandVolatile (IC_RESULT (ic), FALSE));
3571 if (opIsGptr (IC_RESULT (ic)) &&
3572 opIsGptr (IC_RIGHT (ic)) &&
3573 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3575 aopPut (AOP (IC_RESULT (ic)),
3576 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3578 isOperandVolatile (IC_RESULT (ic), FALSE));
3581 if (opIsGptr (IC_RESULT (ic)) &&
3582 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3583 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3584 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3585 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3588 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3589 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3594 /*-----------------------------------------------------------------*/
3595 /* genPlus - generates code for addition */
3596 /*-----------------------------------------------------------------*/
3598 genPlus (iCode * ic)
3600 int size, offset = 0;
3603 asmop *leftOp, *rightOp;
3606 /* special cases :- */
3608 D(emitcode ("; genPlus",""));
3610 aopOp (IC_LEFT (ic), ic, FALSE);
3611 aopOp (IC_RIGHT (ic), ic, FALSE);
3612 aopOp (IC_RESULT (ic), ic, TRUE);
3614 /* if literal, literal on the right or
3615 if left requires ACC or right is already
3617 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3618 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3619 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3621 operand *t = IC_RIGHT (ic);
3622 IC_RIGHT (ic) = IC_LEFT (ic);
3626 /* if both left & right are in bit
3628 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3629 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3635 /* if left in bit space & right literal */
3636 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3637 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3639 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3640 /* if result in bit space */
3641 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3643 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3644 emitcode ("cpl", "c");
3645 outBitC (IC_RESULT (ic));
3649 size = getDataSize (IC_RESULT (ic));
3652 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3653 emitcode ("addc", "a,#00");
3654 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3660 /* if I can do an increment instead
3661 of add then GOOD for ME */
3662 if (genPlusIncr (ic) == TRUE)
3665 size = getDataSize (IC_RESULT (ic));
3666 leftOp = AOP(IC_LEFT(ic));
3667 rightOp = AOP(IC_RIGHT(ic));
3670 /* if this is an add for an array access
3671 at a 256 byte boundary */
3673 && AOP_TYPE (op) == AOP_IMMD
3675 && IS_SPEC (OP_SYM_ETYPE (op))
3676 && SPEC_ABSA (OP_SYM_ETYPE (op))
3677 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3680 D(emitcode ("; genPlus aligned array",""));
3681 aopPut (AOP (IC_RESULT (ic)),
3682 aopGet (rightOp, 0, FALSE, FALSE),
3684 isOperandVolatile (IC_RESULT (ic), FALSE));
3686 if( 1 == getDataSize (IC_RIGHT (ic)) )
3688 aopPut (AOP (IC_RESULT (ic)),
3689 aopGet (leftOp, 1, FALSE, FALSE),
3691 isOperandVolatile (IC_RESULT (ic), FALSE));
3695 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3696 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3697 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3702 /* if the lower bytes of a literal are zero skip the addition */
3703 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3705 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3706 (skip_bytes+1 < size))
3711 D(emitcode ("; genPlus shortcut",""));
3716 if( offset >= skip_bytes )
3718 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3721 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3723 emitcode("xch", "a,b");
3724 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3725 emitcode (add, "a,b");
3728 else if (aopGetUsesAcc (leftOp, offset))
3730 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3731 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3735 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3736 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3738 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3739 add = "addc"; /* further adds must propagate carry */
3743 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3744 isOperandVolatile (IC_RESULT (ic), FALSE))
3747 aopPut (AOP (IC_RESULT (ic)),
3748 aopGet (leftOp, offset, FALSE, FALSE),
3750 isOperandVolatile (IC_RESULT (ic), FALSE));
3756 adjustArithmeticResult (ic);
3759 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3760 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3761 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3764 /*-----------------------------------------------------------------*/
3765 /* genMinusDec :- does subtraction with deccrement if possible */
3766 /*-----------------------------------------------------------------*/
3768 genMinusDec (iCode * ic)
3770 unsigned int icount;
3771 unsigned int size = getDataSize (IC_RESULT (ic));
3773 /* will try to generate an increment */
3774 /* if the right side is not a literal
3776 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3779 /* if the literal value of the right hand side
3780 is greater than 4 then it is not worth it */
3781 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3784 D(emitcode ("; genMinusDec",""));
3786 /* if decrement >=16 bits in register or direct space */
3787 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3788 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3796 /* If the next instruction is a goto and the goto target
3797 * is <= 10 instructions previous to this, we can generate
3798 * jumps straight to that target.
3800 if (ic->next && ic->next->op == GOTO
3801 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3802 && labelRange <= 10)
3804 emitcode (";", "tail decrement optimized");
3805 tlbl = IC_LABEL (ic->next);
3810 tlbl = newiTempLabel (NULL);
3814 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3815 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3816 IS_AOP_PREG (IC_RESULT (ic)))
3817 emitcode ("cjne", "%s,#0xff,%05d$"
3818 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3822 emitcode ("mov", "a,#0xff");
3823 emitcode ("cjne", "a,%s,%05d$"
3824 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3827 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3830 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3831 IS_AOP_PREG (IC_RESULT (ic)))
3832 emitcode ("cjne", "%s,#0xff,%05d$"
3833 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3837 emitcode ("cjne", "a,%s,%05d$"
3838 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3841 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3845 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3846 IS_AOP_PREG (IC_RESULT (ic)))
3847 emitcode ("cjne", "%s,#0xff,%05d$"
3848 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3852 emitcode ("cjne", "a,%s,%05d$"
3853 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3856 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3860 emitcode ("", "%05d$:", tlbl->key + 100);
3865 /* if the sizes are greater than 1 then we cannot */
3866 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3867 AOP_SIZE (IC_LEFT (ic)) > 1)
3870 /* we can if the aops of the left & result match or
3871 if they are in registers and the registers are the
3873 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3877 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3885 /*-----------------------------------------------------------------*/
3886 /* addSign - complete with sign */
3887 /*-----------------------------------------------------------------*/
3889 addSign (operand * result, int offset, int sign)
3891 int size = (getDataSize (result) - offset);
3896 emitcode ("rlc", "a");
3897 emitcode ("subb", "a,acc");
3899 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3903 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3907 /*-----------------------------------------------------------------*/
3908 /* genMinusBits - generates code for subtraction of two bits */
3909 /*-----------------------------------------------------------------*/
3911 genMinusBits (iCode * ic)
3913 symbol *lbl = newiTempLabel (NULL);
3915 D(emitcode ("; genMinusBits",""));
3917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3919 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3920 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3921 emitcode ("cpl", "c");
3922 emitcode ("", "%05d$:", (lbl->key + 100));
3923 outBitC (IC_RESULT (ic));
3927 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3928 emitcode ("subb", "a,acc");
3929 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3930 emitcode ("inc", "a");
3931 emitcode ("", "%05d$:", (lbl->key + 100));
3932 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3933 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3937 /*-----------------------------------------------------------------*/
3938 /* genMinus - generates code for subtraction */
3939 /*-----------------------------------------------------------------*/
3941 genMinus (iCode * ic)
3943 int size, offset = 0;
3945 D(emitcode ("; genMinus",""));
3947 aopOp (IC_LEFT (ic), ic, FALSE);
3948 aopOp (IC_RIGHT (ic), ic, FALSE);
3949 aopOp (IC_RESULT (ic), ic, TRUE);
3951 /* special cases :- */
3952 /* if both left & right are in bit space */
3953 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3954 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3960 /* if I can do an decrement instead
3961 of subtract then GOOD for ME */
3962 if (genMinusDec (ic) == TRUE)
3965 size = getDataSize (IC_RESULT (ic));
3967 /* if literal, add a,#-lit, else normal subb */
3968 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3970 unsigned long lit = 0L;
3972 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3977 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3978 /* first add without previous c */
3980 if (!size && lit== (unsigned long) -1) {
3981 emitcode ("dec", "a");
3983 emitcode ("add", "a,#0x%02x",
3984 (unsigned int) (lit & 0x0FFL));
3987 emitcode ("addc", "a,#0x%02x",
3988 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3990 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3995 asmop *leftOp, *rightOp;
3997 leftOp = AOP(IC_LEFT(ic));
3998 rightOp = AOP(IC_RIGHT(ic));
4002 if (aopGetUsesAcc(rightOp, offset)) {
4003 if (aopGetUsesAcc(leftOp, offset)) {
4006 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4008 emitcode ("mov", "b,a");
4011 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4012 emitcode ("subb", "a,b");
4015 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4016 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4018 emitcode( "setb", "c");
4020 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4021 emitcode("cpl", "a");
4024 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4027 emitcode ("subb", "a,%s",
4028 aopGet(rightOp, offset, FALSE, TRUE));
4031 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4036 adjustArithmeticResult (ic);
4039 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4040 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4041 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4045 /*-----------------------------------------------------------------*/
4046 /* genMultbits :- multiplication of bits */
4047 /*-----------------------------------------------------------------*/
4049 genMultbits (operand * left,
4053 D(emitcode ("; genMultbits",""));
4055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4056 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4060 /*-----------------------------------------------------------------*/
4061 /* genMultOneByte : 8*8=8/16 bit multiplication */
4062 /*-----------------------------------------------------------------*/
4064 genMultOneByte (operand * left,
4069 int size = AOP_SIZE (result);
4070 bool runtimeSign, compiletimeSign;
4071 bool lUnsigned, rUnsigned, pushedB;
4073 D(emitcode ("; genMultOneByte",""));
4075 if (size < 1 || size > 2)
4077 /* this should never happen */
4078 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4079 AOP_SIZE(result), __FILE__, lineno);
4083 /* (if two literals: the value is computed before) */
4084 /* if one literal, literal on the right */
4085 if (AOP_TYPE (left) == AOP_LIT)
4090 /* emitcode (";", "swapped left and right"); */
4092 /* if no literal, unsigned on the right: shorter code */
4093 if ( AOP_TYPE (right) != AOP_LIT
4094 && SPEC_USIGN (getSpec (operandType (left))))
4101 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4102 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4106 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4107 no need to take care about the signedness! */
4108 || (lUnsigned && rUnsigned))
4110 /* just an unsigned 8 * 8 = 8 multiply
4112 /* emitcode (";","unsigned"); */
4113 /* TODO: check for accumulator clash between left & right aops? */
4115 if (AOP_TYPE (right) == AOP_LIT)
4117 /* moving to accumulator first helps peepholes */
4118 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4119 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4123 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4124 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4127 emitcode ("mul", "ab");
4128 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4130 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4136 /* we have to do a signed multiply */
4137 /* emitcode (";", "signed"); */
4139 /* now sign adjust for both left & right */
4141 /* let's see what's needed: */
4142 /* apply negative sign during runtime */
4143 runtimeSign = FALSE;
4144 /* negative sign from literals */
4145 compiletimeSign = FALSE;
4149 if (AOP_TYPE(left) == AOP_LIT)
4151 /* signed literal */
4152 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4154 compiletimeSign = TRUE;
4157 /* signed but not literal */
4163 if (AOP_TYPE(right) == AOP_LIT)
4165 /* signed literal */
4166 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4168 compiletimeSign ^= TRUE;
4171 /* signed but not literal */
4175 /* initialize F0, which stores the runtime sign */
4178 if (compiletimeSign)
4179 emitcode ("setb", "F0"); /* set sign flag */
4181 emitcode ("clr", "F0"); /* reset sign flag */
4184 /* save the signs of the operands */
4185 if (AOP_TYPE(right) == AOP_LIT)
4187 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4189 if (!rUnsigned && val < 0)
4190 emitcode ("mov", "b,#0x%02x", -val);
4192 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4194 else /* ! literal */
4196 if (rUnsigned) /* emitcode (";", "signed"); */
4198 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4201 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4202 lbl = newiTempLabel (NULL);
4203 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4204 emitcode ("cpl", "F0"); /* complement sign flag */
4205 emitcode ("cpl", "a"); /* 2's complement */
4206 emitcode ("inc", "a");
4207 emitcode ("", "%05d$:", (lbl->key + 100));
4208 emitcode ("mov", "b,a");
4212 if (AOP_TYPE(left) == AOP_LIT)
4214 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4216 if (!lUnsigned && val < 0)
4217 emitcode ("mov", "a,#0x%02x", -val);
4219 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4221 else /* ! literal */
4223 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4227 lbl = newiTempLabel (NULL);
4228 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4229 emitcode ("cpl", "F0"); /* complement sign flag */
4230 emitcode ("cpl", "a"); /* 2's complement */
4231 emitcode ("inc", "a");
4232 emitcode ("", "%05d$:", (lbl->key + 100));
4236 /* now the multiplication */
4237 emitcode ("mul", "ab");
4238 if (runtimeSign || compiletimeSign)
4240 lbl = newiTempLabel (NULL);
4242 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4243 emitcode ("cpl", "a"); /* lsb 2's complement */
4245 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4248 emitcode ("add", "a,#1"); /* this sets carry flag */
4249 emitcode ("xch", "a,b");
4250 emitcode ("cpl", "a"); /* msb 2's complement */
4251 emitcode ("addc", "a,#0");
4252 emitcode ("xch", "a,b");
4254 emitcode ("", "%05d$:", (lbl->key + 100));
4256 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4258 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4263 /*-----------------------------------------------------------------*/
4264 /* genMult - generates code for multiplication */
4265 /*-----------------------------------------------------------------*/
4267 genMult (iCode * ic)
4269 operand *left = IC_LEFT (ic);
4270 operand *right = IC_RIGHT (ic);
4271 operand *result = IC_RESULT (ic);
4273 D(emitcode ("; genMult",""));
4275 /* assign the amsops */
4276 aopOp (left, ic, FALSE);
4277 aopOp (right, ic, FALSE);
4278 aopOp (result, ic, TRUE);
4280 /* special cases first */
4282 if (AOP_TYPE (left) == AOP_CRY &&
4283 AOP_TYPE (right) == AOP_CRY)
4285 genMultbits (left, right, result);
4289 /* if both are of size == 1 */
4290 #if 0 // one of them can be a sloc shared with the result
4291 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4293 if (getSize(operandType(left)) == 1 &&
4294 getSize(operandType(right)) == 1)
4297 genMultOneByte (left, right, result);
4301 /* should have been converted to function call */
4302 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4303 getSize(OP_SYMBOL(right)->type));
4307 freeAsmop (result, NULL, ic, TRUE);
4308 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312 /*-----------------------------------------------------------------*/
4313 /* genDivbits :- division of bits */
4314 /*-----------------------------------------------------------------*/
4316 genDivbits (operand * left,
4323 D(emitcode ("; genDivbits",""));
4327 /* the result must be bit */
4328 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4329 l = aopGet (AOP (left), 0, FALSE, FALSE);
4333 emitcode ("div", "ab");
4334 emitcode ("rrc", "a");
4338 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4341 /*-----------------------------------------------------------------*/
4342 /* genDivOneByte : 8 bit division */
4343 /*-----------------------------------------------------------------*/
4345 genDivOneByte (operand * left,
4349 bool lUnsigned, rUnsigned, pushedB;
4350 bool runtimeSign, compiletimeSign;
4354 D(emitcode ("; genDivOneByte",""));
4356 /* Why is it necessary that genDivOneByte() can return an int result?
4359 volatile unsigned char uc;
4360 volatile signed char sc1, sc2;
4373 In all cases a one byte result would overflow, the following cast to int
4374 would return the wrong result.
4376 Two possible solution:
4377 a) cast operands to int, if ((unsigned) / (signed)) or
4378 ((signed) / (signed))
4379 b) return an 16 bit signed int; this is what we're doing here!
4382 size = AOP_SIZE (result) - 1;
4384 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4385 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4389 /* signed or unsigned */
4390 if (lUnsigned && rUnsigned)
4392 /* unsigned is easy */
4393 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4394 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4395 emitcode ("div", "ab");
4396 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4398 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4404 /* signed is a little bit more difficult */
4406 /* now sign adjust for both left & right */
4408 /* let's see what's needed: */
4409 /* apply negative sign during runtime */
4410 runtimeSign = FALSE;
4411 /* negative sign from literals */
4412 compiletimeSign = FALSE;
4416 if (AOP_TYPE(left) == AOP_LIT)
4418 /* signed literal */
4419 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4421 compiletimeSign = TRUE;
4424 /* signed but not literal */
4430 if (AOP_TYPE(right) == AOP_LIT)
4432 /* signed literal */
4433 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4435 compiletimeSign ^= TRUE;
4438 /* signed but not literal */
4442 /* initialize F0, which stores the runtime sign */
4445 if (compiletimeSign)
4446 emitcode ("setb", "F0"); /* set sign flag */
4448 emitcode ("clr", "F0"); /* reset sign flag */
4451 /* save the signs of the operands */
4452 if (AOP_TYPE(right) == AOP_LIT)
4454 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4456 if (!rUnsigned && val < 0)
4457 emitcode ("mov", "b,#0x%02x", -val);
4459 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4461 else /* ! literal */
4464 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4467 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4468 lbl = newiTempLabel (NULL);
4469 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4470 emitcode ("cpl", "F0"); /* complement sign flag */
4471 emitcode ("cpl", "a"); /* 2's complement */
4472 emitcode ("inc", "a");
4473 emitcode ("", "%05d$:", (lbl->key + 100));
4474 emitcode ("mov", "b,a");
4478 if (AOP_TYPE(left) == AOP_LIT)
4480 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4482 if (!lUnsigned && val < 0)
4483 emitcode ("mov", "a,#0x%02x", -val);
4485 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4487 else /* ! literal */
4489 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4493 lbl = newiTempLabel (NULL);
4494 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4495 emitcode ("cpl", "F0"); /* complement sign flag */
4496 emitcode ("cpl", "a"); /* 2's complement */
4497 emitcode ("inc", "a");
4498 emitcode ("", "%05d$:", (lbl->key + 100));
4502 /* now the division */
4503 emitcode ("div", "ab");
4505 if (runtimeSign || compiletimeSign)
4507 lbl = newiTempLabel (NULL);
4509 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4510 emitcode ("cpl", "a"); /* lsb 2's complement */
4511 emitcode ("inc", "a");
4512 emitcode ("", "%05d$:", (lbl->key + 100));
4514 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4517 /* msb is 0x00 or 0xff depending on the sign */
4520 emitcode ("mov", "c,F0");
4521 emitcode ("subb", "a,acc");
4523 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4525 else /* compiletimeSign */
4527 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4532 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4534 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4540 /*-----------------------------------------------------------------*/
4541 /* genDiv - generates code for division */
4542 /*-----------------------------------------------------------------*/
4546 operand *left = IC_LEFT (ic);
4547 operand *right = IC_RIGHT (ic);
4548 operand *result = IC_RESULT (ic);
4550 D(emitcode ("; genDiv",""));
4552 /* assign the amsops */
4553 aopOp (left, ic, FALSE);
4554 aopOp (right, ic, FALSE);
4555 aopOp (result, ic, TRUE);
4557 /* special cases first */
4559 if (AOP_TYPE (left) == AOP_CRY &&
4560 AOP_TYPE (right) == AOP_CRY)
4562 genDivbits (left, right, result);
4566 /* if both are of size == 1 */
4567 if (AOP_SIZE (left) == 1 &&
4568 AOP_SIZE (right) == 1)
4570 genDivOneByte (left, right, result);
4574 /* should have been converted to function call */
4577 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4579 freeAsmop (result, NULL, ic, TRUE);
4582 /*-----------------------------------------------------------------*/
4583 /* genModbits :- modulus of bits */
4584 /*-----------------------------------------------------------------*/
4586 genModbits (operand * left,
4593 D(emitcode ("; genModbits",""));
4597 /* the result must be bit */
4598 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4599 l = aopGet (AOP (left), 0, FALSE, FALSE);
4603 emitcode ("div", "ab");
4604 emitcode ("mov", "a,b");
4605 emitcode ("rrc", "a");
4609 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4612 /*-----------------------------------------------------------------*/
4613 /* genModOneByte : 8 bit modulus */
4614 /*-----------------------------------------------------------------*/
4616 genModOneByte (operand * left,
4620 bool lUnsigned, rUnsigned, pushedB;
4621 bool runtimeSign, compiletimeSign;
4625 D(emitcode ("; genModOneByte",""));
4627 size = AOP_SIZE (result) - 1;
4629 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4630 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4634 /* signed or unsigned */
4635 if (lUnsigned && rUnsigned)
4637 /* unsigned is easy */
4638 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4639 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4640 emitcode ("div", "ab");
4641 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4643 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4649 /* signed is a little bit more difficult */
4651 /* now sign adjust for both left & right */
4653 /* modulus: sign of the right operand has no influence on the result! */
4654 if (AOP_TYPE(right) == AOP_LIT)
4656 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4658 if (!rUnsigned && val < 0)
4659 emitcode ("mov", "b,#0x%02x", -val);
4661 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4663 else /* not literal */
4666 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4669 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4670 lbl = newiTempLabel (NULL);
4671 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4672 emitcode ("cpl", "a"); /* 2's complement */
4673 emitcode ("inc", "a");
4674 emitcode ("", "%05d$:", (lbl->key + 100));
4675 emitcode ("mov", "b,a");
4679 /* let's see what's needed: */
4680 /* apply negative sign during runtime */
4681 runtimeSign = FALSE;
4682 /* negative sign from literals */
4683 compiletimeSign = FALSE;
4685 /* sign adjust left side */
4686 if (AOP_TYPE(left) == AOP_LIT)
4688 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4690 if (!lUnsigned && val < 0)
4692 compiletimeSign = TRUE; /* set sign flag */
4693 emitcode ("mov", "a,#0x%02x", -val);
4696 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4698 else /* ! literal */
4700 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4705 emitcode ("clr", "F0"); /* clear sign flag */
4707 lbl = newiTempLabel (NULL);
4708 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4709 emitcode ("setb", "F0"); /* set sign flag */
4710 emitcode ("cpl", "a"); /* 2's complement */
4711 emitcode ("inc", "a");
4712 emitcode ("", "%05d$:", (lbl->key + 100));
4716 /* now the modulus */
4717 emitcode ("div", "ab");
4719 if (runtimeSign || compiletimeSign)
4721 emitcode ("mov", "a,b");
4722 lbl = newiTempLabel (NULL);
4724 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4725 emitcode ("cpl", "a"); /* 2's complement */
4726 emitcode ("inc", "a");
4727 emitcode ("", "%05d$:", (lbl->key + 100));
4729 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4732 /* msb is 0x00 or 0xff depending on the sign */
4735 emitcode ("mov", "c,F0");
4736 emitcode ("subb", "a,acc");
4738 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4740 else /* compiletimeSign */
4742 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4747 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4749 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4755 /*-----------------------------------------------------------------*/
4756 /* genMod - generates code for division */
4757 /*-----------------------------------------------------------------*/
4761 operand *left = IC_LEFT (ic);
4762 operand *right = IC_RIGHT (ic);
4763 operand *result = IC_RESULT (ic);
4765 D(emitcode ("; genMod",""));
4767 /* assign the amsops */
4768 aopOp (left, ic, FALSE);
4769 aopOp (right, ic, FALSE);
4770 aopOp (result, ic, TRUE);
4772 /* special cases first */
4774 if (AOP_TYPE (left) == AOP_CRY &&
4775 AOP_TYPE (right) == AOP_CRY)
4777 genModbits (left, right, result);
4781 /* if both are of size == 1 */
4782 if (AOP_SIZE (left) == 1 &&
4783 AOP_SIZE (right) == 1)
4785 genModOneByte (left, right, result);
4789 /* should have been converted to function call */
4793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795 freeAsmop (result, NULL, ic, TRUE);
4798 /*-----------------------------------------------------------------*/
4799 /* genIfxJump :- will create a jump depending on the ifx */
4800 /*-----------------------------------------------------------------*/
4802 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4805 symbol *tlbl = newiTempLabel (NULL);
4808 D(emitcode ("; genIfxJump",""));
4810 /* if true label then we jump if condition
4814 jlbl = IC_TRUE (ic);
4815 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4816 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4820 /* false label is present */
4821 jlbl = IC_FALSE (ic);
4822 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4823 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4825 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4826 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4828 emitcode (inst, "%05d$", tlbl->key + 100);
4829 freeForBranchAsmop (result);
4830 freeForBranchAsmop (right);
4831 freeForBranchAsmop (left);
4832 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4833 emitcode ("", "%05d$:", tlbl->key + 100);
4835 /* mark the icode as generated */
4839 /*-----------------------------------------------------------------*/
4840 /* genCmp :- greater or less than comparison */
4841 /*-----------------------------------------------------------------*/
4843 genCmp (operand * left, operand * right,
4844 operand * result, iCode * ifx, int sign, iCode *ic)
4846 int size, offset = 0;
4847 unsigned long lit = 0L;
4850 D(emitcode ("; genCmp",""));
4852 /* if left & right are bit variables */
4853 if (AOP_TYPE (left) == AOP_CRY &&
4854 AOP_TYPE (right) == AOP_CRY)
4856 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4857 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4861 /* subtract right from left if at the
4862 end the carry flag is set then we know that
4863 left is greater than right */
4864 size = max (AOP_SIZE (left), AOP_SIZE (right));
4866 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4867 if ((size == 1) && !sign &&
4868 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4870 symbol *lbl = newiTempLabel (NULL);
4871 emitcode ("cjne", "%s,%s,%05d$",
4872 aopGet (AOP (left), offset, FALSE, FALSE),
4873 aopGet (AOP (right), offset, FALSE, FALSE),
4875 emitcode ("", "%05d$:", lbl->key + 100);
4879 if (AOP_TYPE (right) == AOP_LIT)
4881 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4882 /* optimize if(x < 0) or if(x >= 0) */
4891 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4892 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4894 genIfxJump (ifx, "acc.7", left, right, result);
4895 freeAsmop (right, NULL, ic, TRUE);
4896 freeAsmop (left, NULL, ic, TRUE);
4901 emitcode ("rlc", "a");
4909 bool pushedB = FALSE;
4910 rightInB = aopGetUsesAcc(AOP (right), offset);
4914 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4916 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4917 if (sign && size == 0)
4919 emitcode ("xrl", "a,#0x80");
4920 if (AOP_TYPE (right) == AOP_LIT)
4922 unsigned long lit = (unsigned long)
4923 floatFromVal (AOP (right)->aopu.aop_lit);
4924 emitcode ("subb", "a,#0x%02x",
4925 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4933 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4935 emitcode ("xrl", "b,#0x80");
4936 emitcode ("subb", "a,b");
4942 emitcode ("subb", "a,b");
4944 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4955 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4956 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4962 /* if the result is used in the next
4963 ifx conditional branch then generate
4964 code a little differently */
4966 genIfxJump (ifx, "c", NULL, NULL, result);
4969 /* leave the result in acc */
4973 /*-----------------------------------------------------------------*/
4974 /* genCmpGt :- greater than comparison */
4975 /*-----------------------------------------------------------------*/
4977 genCmpGt (iCode * ic, iCode * ifx)
4979 operand *left, *right, *result;
4980 sym_link *letype, *retype;
4983 D(emitcode ("; genCmpGt",""));
4985 left = IC_LEFT (ic);
4986 right = IC_RIGHT (ic);
4987 result = IC_RESULT (ic);
4989 letype = getSpec (operandType (left));
4990 retype = getSpec (operandType (right));
4991 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4992 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4993 /* assign the amsops */
4994 aopOp (left, ic, FALSE);
4995 aopOp (right, ic, FALSE);
4996 aopOp (result, ic, TRUE);
4998 genCmp (right, left, result, ifx, sign, ic);
5000 freeAsmop (result, NULL, ic, TRUE);
5003 /*-----------------------------------------------------------------*/
5004 /* genCmpLt - less than comparisons */
5005 /*-----------------------------------------------------------------*/
5007 genCmpLt (iCode * ic, iCode * ifx)
5009 operand *left, *right, *result;
5010 sym_link *letype, *retype;
5013 D(emitcode ("; genCmpLt",""));
5015 left = IC_LEFT (ic);
5016 right = IC_RIGHT (ic);
5017 result = IC_RESULT (ic);
5019 letype = getSpec (operandType (left));
5020 retype = getSpec (operandType (right));
5021 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5022 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5023 /* assign the amsops */
5024 aopOp (left, ic, FALSE);
5025 aopOp (right, ic, FALSE);
5026 aopOp (result, ic, TRUE);
5028 genCmp (left, right, result, ifx, sign,ic);
5030 freeAsmop (result, NULL, ic, TRUE);
5033 /*-----------------------------------------------------------------*/
5034 /* gencjneshort - compare and jump if not equal */
5035 /*-----------------------------------------------------------------*/
5037 gencjneshort (operand * left, operand * right, symbol * lbl)
5039 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5041 unsigned long lit = 0L;
5043 /* if the left side is a literal or
5044 if the right is in a pointer register and left
5046 if ((AOP_TYPE (left) == AOP_LIT) ||
5047 (AOP_TYPE (left) == AOP_IMMD) ||
5048 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5055 if (AOP_TYPE (right) == AOP_LIT)
5056 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5058 /* if the right side is a literal then anything goes */
5059 if (AOP_TYPE (right) == AOP_LIT &&
5060 AOP_TYPE (left) != AOP_DIR &&
5061 AOP_TYPE (left) != AOP_IMMD)
5065 emitcode ("cjne", "%s,%s,%05d$",
5066 aopGet (AOP (left), offset, FALSE, FALSE),
5067 aopGet (AOP (right), offset, FALSE, FALSE),
5073 /* if the right side is in a register or in direct space or
5074 if the left is a pointer register & right is not */
5075 else if (AOP_TYPE (right) == AOP_REG ||
5076 AOP_TYPE (right) == AOP_DIR ||
5077 AOP_TYPE (right) == AOP_LIT ||
5078 AOP_TYPE (right) == AOP_IMMD ||
5079 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5080 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5084 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5085 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5086 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5087 emitcode ("jnz", "%05d$", lbl->key + 100);
5089 emitcode ("cjne", "a,%s,%05d$",
5090 aopGet (AOP (right), offset, FALSE, TRUE),
5097 /* right is a pointer reg need both a & b */
5101 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5102 wassertl(!_G.BInUse, "B was in use");
5103 l = aopGet (AOP (left), offset, FALSE, FALSE);
5104 if (strcmp (l, "b"))
5105 emitcode ("mov", "b,%s", l);
5106 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5107 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5113 /*-----------------------------------------------------------------*/
5114 /* gencjne - compare and jump if not equal */
5115 /*-----------------------------------------------------------------*/
5117 gencjne (operand * left, operand * right, symbol * lbl)
5119 symbol *tlbl = newiTempLabel (NULL);
5121 gencjneshort (left, right, lbl);
5123 emitcode ("mov", "a,%s", one);
5124 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5125 emitcode ("", "%05d$:", lbl->key + 100);
5126 emitcode ("clr", "a");
5127 emitcode ("", "%05d$:", tlbl->key + 100);
5130 /*-----------------------------------------------------------------*/
5131 /* genCmpEq - generates code for equal to */
5132 /*-----------------------------------------------------------------*/
5134 genCmpEq (iCode * ic, iCode * ifx)
5136 operand *left, *right, *result;
5138 D(emitcode ("; genCmpEq",""));
5140 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5141 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5142 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5144 /* if literal, literal on the right or
5145 if the right is in a pointer register and left
5147 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5148 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5150 operand *t = IC_RIGHT (ic);
5151 IC_RIGHT (ic) = IC_LEFT (ic);
5155 if (ifx && !AOP_SIZE (result))
5158 /* if they are both bit variables */
5159 if (AOP_TYPE (left) == AOP_CRY &&
5160 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5162 if (AOP_TYPE (right) == AOP_LIT)
5164 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5167 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5168 emitcode ("cpl", "c");
5172 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5176 emitcode ("clr", "c");
5178 /* AOP_TYPE(right) == AOP_CRY */
5182 symbol *lbl = newiTempLabel (NULL);
5183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5184 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5185 emitcode ("cpl", "c");
5186 emitcode ("", "%05d$:", (lbl->key + 100));
5188 /* if true label then we jump if condition
5190 tlbl = newiTempLabel (NULL);
5193 emitcode ("jnc", "%05d$", tlbl->key + 100);
5194 freeForBranchAsmop (result);
5195 freeForBranchAsmop (right);
5196 freeForBranchAsmop (left);
5197 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5201 emitcode ("jc", "%05d$", tlbl->key + 100);
5202 freeForBranchAsmop (result);
5203 freeForBranchAsmop (right);
5204 freeForBranchAsmop (left);
5205 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5207 emitcode ("", "%05d$:", tlbl->key + 100);
5211 tlbl = newiTempLabel (NULL);
5212 gencjneshort (left, right, tlbl);
5215 freeForBranchAsmop (result);
5216 freeForBranchAsmop (right);
5217 freeForBranchAsmop (left);
5218 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5219 emitcode ("", "%05d$:", tlbl->key + 100);
5223 symbol *lbl = newiTempLabel (NULL);
5224 emitcode ("sjmp", "%05d$", lbl->key + 100);
5225 emitcode ("", "%05d$:", tlbl->key + 100);
5226 freeForBranchAsmop (result);
5227 freeForBranchAsmop (right);
5228 freeForBranchAsmop (left);
5229 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5230 emitcode ("", "%05d$:", lbl->key + 100);
5233 /* mark the icode as generated */
5238 /* if they are both bit variables */
5239 if (AOP_TYPE (left) == AOP_CRY &&
5240 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5242 if (AOP_TYPE (right) == AOP_LIT)
5244 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5247 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5248 emitcode ("cpl", "c");
5252 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5256 emitcode ("clr", "c");
5258 /* AOP_TYPE(right) == AOP_CRY */
5262 symbol *lbl = newiTempLabel (NULL);
5263 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5264 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5265 emitcode ("cpl", "c");
5266 emitcode ("", "%05d$:", (lbl->key + 100));
5269 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5276 genIfxJump (ifx, "c", left, right, result);
5279 /* if the result is used in an arithmetic operation
5280 then put the result in place */
5285 gencjne (left, right, newiTempLabel (NULL));
5286 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5288 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5293 genIfxJump (ifx, "a", left, right, result);
5296 /* if the result is used in an arithmetic operation
5297 then put the result in place */
5298 if (AOP_TYPE (result) != AOP_CRY)
5300 /* leave the result in acc */
5304 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5305 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306 freeAsmop (result, NULL, ic, TRUE);
5309 /*-----------------------------------------------------------------*/
5310 /* ifxForOp - returns the icode containing the ifx for operand */
5311 /*-----------------------------------------------------------------*/
5313 ifxForOp (operand * op, iCode * ic)
5315 /* if true symbol then needs to be assigned */
5316 if (IS_TRUE_SYMOP (op))
5319 /* if this has register type condition and
5320 the next instruction is ifx with the same operand
5321 and live to of the operand is upto the ifx only then */
5323 ic->next->op == IFX &&
5324 IC_COND (ic->next)->key == op->key &&
5325 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5331 /*-----------------------------------------------------------------*/
5332 /* hasInc - operand is incremented before any other use */
5333 /*-----------------------------------------------------------------*/
5335 hasInc (operand *op, iCode *ic,int osize)
5337 sym_link *type = operandType(op);
5338 sym_link *retype = getSpec (type);
5339 iCode *lic = ic->next;
5342 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5343 if (!IS_SYMOP(op)) return NULL;
5345 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5346 if (IS_AGGREGATE(type->next)) return NULL;
5347 if (osize != (isize = getSize(type->next))) return NULL;
5350 /* if operand of the form op = op + <sizeof *op> */
5351 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5352 isOperandEqual(IC_RESULT(lic),op) &&
5353 isOperandLiteral(IC_RIGHT(lic)) &&
5354 operandLitValue(IC_RIGHT(lic)) == isize) {
5357 /* if the operand used or deffed */
5358 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5361 /* if GOTO or IFX */
5362 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5368 /*-----------------------------------------------------------------*/
5369 /* genAndOp - for && operation */
5370 /*-----------------------------------------------------------------*/
5372 genAndOp (iCode * ic)
5374 operand *left, *right, *result;
5377 D(emitcode ("; genAndOp",""));
5379 /* note here that && operations that are in an
5380 if statement are taken away by backPatchLabels
5381 only those used in arthmetic operations remain */
5382 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5383 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5384 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5386 /* if both are bit variables */
5387 if (AOP_TYPE (left) == AOP_CRY &&
5388 AOP_TYPE (right) == AOP_CRY)
5390 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5391 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5396 tlbl = newiTempLabel (NULL);
5398 emitcode ("jz", "%05d$", tlbl->key + 100);
5400 emitcode ("", "%05d$:", tlbl->key + 100);
5404 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406 freeAsmop (result, NULL, ic, TRUE);
5410 /*-----------------------------------------------------------------*/
5411 /* genOrOp - for || operation */
5412 /*-----------------------------------------------------------------*/
5414 genOrOp (iCode * ic)
5416 operand *left, *right, *result;
5419 D(emitcode ("; genOrOp",""));
5421 /* note here that || operations that are in an
5422 if statement are taken away by backPatchLabels
5423 only those used in arthmetic operations remain */
5424 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5425 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5426 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5428 /* if both are bit variables */
5429 if (AOP_TYPE (left) == AOP_CRY &&
5430 AOP_TYPE (right) == AOP_CRY)
5432 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5433 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5438 tlbl = newiTempLabel (NULL);
5440 emitcode ("jnz", "%05d$", tlbl->key + 100);
5442 emitcode ("", "%05d$:", tlbl->key + 100);
5446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5447 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448 freeAsmop (result, NULL, ic, TRUE);
5451 /*-----------------------------------------------------------------*/
5452 /* isLiteralBit - test if lit == 2^n */
5453 /*-----------------------------------------------------------------*/
5455 isLiteralBit (unsigned long lit)
5457 unsigned long pw[32] =
5458 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5459 0x100L, 0x200L, 0x400L, 0x800L,
5460 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5461 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5462 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5463 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5464 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5467 for (idx = 0; idx < 32; idx++)
5473 /*-----------------------------------------------------------------*/
5474 /* continueIfTrue - */
5475 /*-----------------------------------------------------------------*/
5477 continueIfTrue (iCode * ic)
5480 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5484 /*-----------------------------------------------------------------*/
5486 /*-----------------------------------------------------------------*/
5488 jumpIfTrue (iCode * ic)
5491 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5495 /*-----------------------------------------------------------------*/
5496 /* jmpTrueOrFalse - */
5497 /*-----------------------------------------------------------------*/
5499 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5501 // ugly but optimized by peephole
5504 symbol *nlbl = newiTempLabel (NULL);
5505 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5506 emitcode ("", "%05d$:", tlbl->key + 100);
5507 freeForBranchAsmop (result);
5508 freeForBranchAsmop (right);
5509 freeForBranchAsmop (left);
5510 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5511 emitcode ("", "%05d$:", nlbl->key + 100);
5515 freeForBranchAsmop (result);
5516 freeForBranchAsmop (right);
5517 freeForBranchAsmop (left);
5518 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5519 emitcode ("", "%05d$:", tlbl->key + 100);
5524 /*-----------------------------------------------------------------*/
5525 /* genAnd - code for and */
5526 /*-----------------------------------------------------------------*/
5528 genAnd (iCode * ic, iCode * ifx)
5530 operand *left, *right, *result;
5531 int size, offset = 0;
5532 unsigned long lit = 0L;
5536 D(emitcode ("; genAnd",""));
5538 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5539 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5540 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5543 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5545 AOP_TYPE (left), AOP_TYPE (right));
5546 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5548 AOP_SIZE (left), AOP_SIZE (right));
5551 /* if left is a literal & right is not then exchange them */
5552 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5553 AOP_NEEDSACC (left))
5555 operand *tmp = right;
5560 /* if result = right then exchange left and right */
5561 if (sameRegs (AOP (result), AOP (right)))
5563 operand *tmp = right;
5568 /* if right is bit then exchange them */
5569 if (AOP_TYPE (right) == AOP_CRY &&
5570 AOP_TYPE (left) != AOP_CRY)
5572 operand *tmp = right;
5576 if (AOP_TYPE (right) == AOP_LIT)
5577 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5579 size = AOP_SIZE (result);
5582 // result = bit & yy;
5583 if (AOP_TYPE (left) == AOP_CRY)
5585 // c = bit & literal;
5586 if (AOP_TYPE (right) == AOP_LIT)
5590 if (size && sameRegs (AOP (result), AOP (left)))
5593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5598 if (size && (AOP_TYPE (result) == AOP_CRY))
5600 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5603 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5608 emitcode ("clr", "c");
5613 if (AOP_TYPE (right) == AOP_CRY)
5616 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5617 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5622 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5624 emitcode ("rrc", "a");
5625 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5633 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5634 genIfxJump (ifx, "c", left, right, result);
5638 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5639 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5640 if ((AOP_TYPE (right) == AOP_LIT) &&
5641 (AOP_TYPE (result) == AOP_CRY) &&
5642 (AOP_TYPE (left) != AOP_CRY))
5644 int posbit = isLiteralBit (lit);
5649 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5652 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5658 SNPRINTF (buffer, sizeof(buffer),
5659 "acc.%d", posbit & 0x07);
5660 genIfxJump (ifx, buffer, left, right, result);
5663 {// what is this case? just found it in ds390/gen.c
5664 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5671 symbol *tlbl = newiTempLabel (NULL);
5672 int sizel = AOP_SIZE (left);
5674 emitcode ("setb", "c");
5677 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5679 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5681 if ((posbit = isLiteralBit (bytelit)) != 0)
5682 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5685 if (bytelit != 0x0FFL)
5686 emitcode ("anl", "a,%s",
5687 aopGet (AOP (right), offset, FALSE, TRUE));
5688 emitcode ("jnz", "%05d$", tlbl->key + 100);
5693 // bit = left & literal
5696 emitcode ("clr", "c");
5697 emitcode ("", "%05d$:", tlbl->key + 100);
5699 // if(left & literal)
5703 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5705 emitcode ("", "%05d$:", tlbl->key + 100);
5713 /* if left is same as result */
5714 if (sameRegs (AOP (result), AOP (left)))
5716 for (; size--; offset++)
5718 if (AOP_TYPE (right) == AOP_LIT)
5720 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5721 if (bytelit == 0x0FF)
5723 /* dummy read of volatile operand */
5724 if (isOperandVolatile (left, FALSE))
5725 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5729 else if (bytelit == 0)
5731 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5733 else if (IS_AOP_PREG (result))
5735 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5736 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5737 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5740 emitcode ("anl", "%s,%s",
5741 aopGet (AOP (left), offset, FALSE, TRUE),
5742 aopGet (AOP (right), offset, FALSE, FALSE));
5746 if (AOP_TYPE (left) == AOP_ACC)
5747 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5750 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5751 if (IS_AOP_PREG (result))
5753 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5754 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5757 emitcode ("anl", "%s,a",
5758 aopGet (AOP (left), offset, FALSE, TRUE));
5765 // left & result in different registers
5766 if (AOP_TYPE (result) == AOP_CRY)
5769 // if(size), result in bit
5770 // if(!size && ifx), conditional oper: if(left & right)
5771 symbol *tlbl = newiTempLabel (NULL);
5772 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5774 emitcode ("setb", "c");
5777 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5778 emitcode ("anl", "a,%s",
5779 aopGet (AOP (right), offset, FALSE, FALSE));
5781 if (AOP_TYPE(left)==AOP_ACC) {
5782 bool pushedB = pushB ();
5783 emitcode("mov", "b,a");
5784 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5785 emitcode("anl", "a,b");
5788 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5789 emitcode ("anl", "a,%s",
5790 aopGet (AOP (left), offset, FALSE, FALSE));
5793 emitcode ("jnz", "%05d$", tlbl->key + 100);
5799 emitcode ("", "%05d$:", tlbl->key + 100);
5803 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5805 emitcode ("", "%05d$:", tlbl->key + 100);
5809 for (; (size--); offset++)
5812 // result = left & right
5813 if (AOP_TYPE (right) == AOP_LIT)
5815 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5816 if (bytelit == 0x0FF)
5818 aopPut (AOP (result),
5819 aopGet (AOP (left), offset, FALSE, FALSE),
5821 isOperandVolatile (result, FALSE));
5824 else if (bytelit == 0)
5826 /* dummy read of volatile operand */
5827 if (isOperandVolatile (left, FALSE))
5828 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5829 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5833 // faster than result <- left, anl result,right
5834 // and better if result is SFR
5835 if (AOP_TYPE (left) == AOP_ACC)
5836 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5839 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5840 emitcode ("anl", "a,%s",
5841 aopGet (AOP (left), offset, FALSE, FALSE));
5843 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5849 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5851 freeAsmop (result, NULL, ic, TRUE);
5854 /*-----------------------------------------------------------------*/
5855 /* genOr - code for or */
5856 /*-----------------------------------------------------------------*/
5858 genOr (iCode * ic, iCode * ifx)
5860 operand *left, *right, *result;
5861 int size, offset = 0;
5862 unsigned long lit = 0L;
5865 D(emitcode ("; genOr",""));
5867 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5868 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5869 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5872 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5874 AOP_TYPE (left), AOP_TYPE (right));
5875 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5877 AOP_SIZE (left), AOP_SIZE (right));
5880 /* if left is a literal & right is not then exchange them */
5881 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5882 AOP_NEEDSACC (left))
5884 operand *tmp = right;
5889 /* if result = right then exchange them */
5890 if (sameRegs (AOP (result), AOP (right)))
5892 operand *tmp = right;
5897 /* if right is bit then exchange them */
5898 if (AOP_TYPE (right) == AOP_CRY &&
5899 AOP_TYPE (left) != AOP_CRY)
5901 operand *tmp = right;
5905 if (AOP_TYPE (right) == AOP_LIT)
5906 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5908 size = AOP_SIZE (result);
5912 if (AOP_TYPE (left) == AOP_CRY)
5914 if (AOP_TYPE (right) == AOP_LIT)
5916 // c = bit | literal;
5919 // lit != 0 => result = 1
5920 if (AOP_TYPE (result) == AOP_CRY)
5923 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5925 continueIfTrue (ifx);
5928 emitcode ("setb", "c");
5932 // lit == 0 => result = left
5933 if (size && sameRegs (AOP (result), AOP (left)))
5935 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5940 if (AOP_TYPE (right) == AOP_CRY)
5943 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5944 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5949 symbol *tlbl = newiTempLabel (NULL);
5950 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5951 emitcode ("setb", "c");
5952 emitcode ("jb", "%s,%05d$",
5953 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5955 emitcode ("jnz", "%05d$", tlbl->key + 100);
5956 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5958 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5964 emitcode ("", "%05d$:", tlbl->key + 100);
5973 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5974 genIfxJump (ifx, "c", left, right, result);
5978 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5979 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5980 if ((AOP_TYPE (right) == AOP_LIT) &&
5981 (AOP_TYPE (result) == AOP_CRY) &&
5982 (AOP_TYPE (left) != AOP_CRY))
5988 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5990 continueIfTrue (ifx);
5995 // lit = 0, result = boolean(left)
5997 emitcode ("setb", "c");
6001 symbol *tlbl = newiTempLabel (NULL);
6002 emitcode ("jnz", "%05d$", tlbl->key + 100);
6004 emitcode ("", "%05d$:", tlbl->key + 100);
6008 genIfxJump (ifx, "a", left, right, result);
6016 /* if left is same as result */
6017 if (sameRegs (AOP (result), AOP (left)))
6019 for (; size--; offset++)
6021 if (AOP_TYPE (right) == AOP_LIT)
6023 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6026 /* dummy read of volatile operand */
6027 if (isOperandVolatile (left, FALSE))
6028 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6032 else if (bytelit == 0x0FF)
6034 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6036 else if (IS_AOP_PREG (left))
6038 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6039 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6040 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6044 emitcode ("orl", "%s,%s",
6045 aopGet (AOP (left), offset, FALSE, TRUE),
6046 aopGet (AOP (right), offset, FALSE, FALSE));
6051 if (AOP_TYPE (left) == AOP_ACC)
6052 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6055 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6056 if (IS_AOP_PREG (left))
6058 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6059 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6063 emitcode ("orl", "%s,a",
6064 aopGet (AOP (left), offset, FALSE, TRUE));
6072 // left & result in different registers
6073 if (AOP_TYPE (result) == AOP_CRY)
6076 // if(size), result in bit
6077 // if(!size && ifx), conditional oper: if(left | right)
6078 symbol *tlbl = newiTempLabel (NULL);
6079 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6081 emitcode ("setb", "c");
6084 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6085 emitcode ("orl", "a,%s",
6086 aopGet (AOP (right), offset, FALSE, FALSE));
6088 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6089 emitcode ("orl", "a,%s",
6090 aopGet (AOP (left), offset, FALSE, FALSE));
6092 emitcode ("jnz", "%05d$", tlbl->key + 100);
6098 emitcode ("", "%05d$:", tlbl->key + 100);
6102 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6104 emitcode ("", "%05d$:", tlbl->key + 100);
6108 for (; (size--); offset++)
6111 // result = left | right
6112 if (AOP_TYPE (right) == AOP_LIT)
6114 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6117 aopPut (AOP (result),
6118 aopGet (AOP (left), offset, FALSE, FALSE),
6120 isOperandVolatile (result, FALSE));
6123 else if (bytelit == 0x0FF)
6125 /* dummy read of volatile operand */
6126 if (isOperandVolatile (left, FALSE))
6127 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6128 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6132 // faster than result <- left, anl result,right
6133 // and better if result is SFR
6134 if (AOP_TYPE (left) == AOP_ACC)
6135 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6138 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6139 emitcode ("orl", "a,%s",
6140 aopGet (AOP (left), offset, FALSE, FALSE));
6142 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6148 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6149 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6150 freeAsmop (result, NULL, ic, TRUE);
6153 /*-----------------------------------------------------------------*/
6154 /* genXor - code for xclusive or */
6155 /*-----------------------------------------------------------------*/
6157 genXor (iCode * ic, iCode * ifx)
6159 operand *left, *right, *result;
6160 int size, offset = 0;
6161 unsigned long lit = 0L;
6164 D(emitcode ("; genXor",""));
6166 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6167 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6168 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6171 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6173 AOP_TYPE (left), AOP_TYPE (right));
6174 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6176 AOP_SIZE (left), AOP_SIZE (right));
6179 /* if left is a literal & right is not ||
6180 if left needs acc & right does not */
6181 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6182 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6184 operand *tmp = right;
6189 /* if result = right then exchange them */
6190 if (sameRegs (AOP (result), AOP (right)))
6192 operand *tmp = right;
6197 /* if right is bit then exchange them */
6198 if (AOP_TYPE (right) == AOP_CRY &&
6199 AOP_TYPE (left) != AOP_CRY)
6201 operand *tmp = right;
6205 if (AOP_TYPE (right) == AOP_LIT)
6206 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6208 size = AOP_SIZE (result);
6212 if (AOP_TYPE (left) == AOP_CRY)
6214 if (AOP_TYPE (right) == AOP_LIT)
6216 // c = bit & literal;
6219 // lit>>1 != 0 => result = 1
6220 if (AOP_TYPE (result) == AOP_CRY)
6223 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6225 continueIfTrue (ifx);
6228 emitcode ("setb", "c");
6235 // lit == 0, result = left
6236 if (size && sameRegs (AOP (result), AOP (left)))
6238 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6242 // lit == 1, result = not(left)
6243 if (size && sameRegs (AOP (result), AOP (left)))
6245 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6251 emitcode ("cpl", "c");
6260 symbol *tlbl = newiTempLabel (NULL);
6261 if (AOP_TYPE (right) == AOP_CRY)
6264 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6268 int sizer = AOP_SIZE (right);
6270 // if val>>1 != 0, result = 1
6271 emitcode ("setb", "c");
6274 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6276 // test the msb of the lsb
6277 emitcode ("anl", "a,#0xfe");
6278 emitcode ("jnz", "%05d$", tlbl->key + 100);
6282 emitcode ("rrc", "a");
6284 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6285 emitcode ("cpl", "c");
6286 emitcode ("", "%05d$:", (tlbl->key + 100));
6293 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294 genIfxJump (ifx, "c", left, right, result);
6298 /* if left is same as result */
6299 if (sameRegs (AOP (result), AOP (left)))
6301 for (; size--; offset++)
6303 if (AOP_TYPE (right) == AOP_LIT)
6305 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6308 /* dummy read of volatile operand */
6309 if (isOperandVolatile (left, FALSE))
6310 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6314 else if (IS_AOP_PREG (left))
6316 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6317 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6318 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6322 emitcode ("xrl", "%s,%s",
6323 aopGet (AOP (left), offset, FALSE, TRUE),
6324 aopGet (AOP (right), offset, FALSE, FALSE));
6329 if (AOP_TYPE (left) == AOP_ACC)
6330 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6333 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6334 if (IS_AOP_PREG (left))
6336 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6337 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6340 emitcode ("xrl", "%s,a",
6341 aopGet (AOP (left), offset, FALSE, TRUE));
6348 // left & result in different registers
6349 if (AOP_TYPE (result) == AOP_CRY)
6352 // if(size), result in bit
6353 // if(!size && ifx), conditional oper: if(left ^ right)
6354 symbol *tlbl = newiTempLabel (NULL);
6355 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6357 emitcode ("setb", "c");
6360 if ((AOP_TYPE (right) == AOP_LIT) &&
6361 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6363 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6367 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6368 emitcode ("xrl", "a,%s",
6369 aopGet (AOP (right), offset, FALSE, FALSE));
6371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6372 emitcode ("xrl", "a,%s",
6373 aopGet (AOP (left), offset, FALSE, FALSE));
6376 emitcode ("jnz", "%05d$", tlbl->key + 100);
6382 emitcode ("", "%05d$:", tlbl->key + 100);
6386 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6390 for (; (size--); offset++)
6393 // result = left & right
6394 if (AOP_TYPE (right) == AOP_LIT)
6396 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6399 aopPut (AOP (result),
6400 aopGet (AOP (left), offset, FALSE, FALSE),
6402 isOperandVolatile (result, FALSE));
6406 // faster than result <- left, anl result,right
6407 // and better if result is SFR
6408 if (AOP_TYPE (left) == AOP_ACC)
6409 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6412 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6413 emitcode ("xrl", "a,%s",
6414 aopGet (AOP (left), offset, FALSE, TRUE));
6416 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 freeAsmop (result, NULL, ic, TRUE);
6427 /*-----------------------------------------------------------------*/
6428 /* genInline - write the inline code out */
6429 /*-----------------------------------------------------------------*/
6431 genInline (iCode * ic)
6433 char *buffer, *bp, *bp1;
6435 D(emitcode ("; genInline",""));
6437 _G.inLine += (!options.asmpeep);
6439 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6440 strcpy (buffer, IC_INLINE (ic));
6442 /* emit each line as a code */
6453 /* Add \n for labels, not dirs such as c:\mydir */
6454 if ( (*bp == ':') && (isspace(bp[1])) )
6468 /* emitcode("",buffer); */
6469 _G.inLine -= (!options.asmpeep);
6472 /*-----------------------------------------------------------------*/
6473 /* genRRC - rotate right with carry */
6474 /*-----------------------------------------------------------------*/
6478 operand *left, *result;
6479 int size, offset = 0;
6482 D(emitcode ("; genRRC",""));
6484 /* rotate right with carry */
6485 left = IC_LEFT (ic);
6486 result = IC_RESULT (ic);
6487 aopOp (left, ic, FALSE);
6488 aopOp (result, ic, FALSE);
6490 /* move it to the result */
6491 size = AOP_SIZE (result);
6493 if (size == 1) { /* special case for 1 byte */
6494 l = aopGet (AOP (left), offset, FALSE, FALSE);
6496 emitcode ("rr", "a");
6502 l = aopGet (AOP (left), offset, FALSE, FALSE);
6504 emitcode ("rrc", "a");
6505 if (AOP_SIZE (result) > 1)
6506 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6508 /* now we need to put the carry into the
6509 highest order byte of the result */
6510 if (AOP_SIZE (result) > 1)
6512 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6515 emitcode ("mov", "acc.7,c");
6517 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6518 freeAsmop (left, NULL, ic, TRUE);
6519 freeAsmop (result, NULL, ic, TRUE);
6522 /*-----------------------------------------------------------------*/
6523 /* genRLC - generate code for rotate left with carry */
6524 /*-----------------------------------------------------------------*/
6528 operand *left, *result;
6529 int size, offset = 0;
6532 D(emitcode ("; genRLC",""));
6534 /* rotate right with carry */
6535 left = IC_LEFT (ic);
6536 result = IC_RESULT (ic);
6537 aopOp (left, ic, FALSE);
6538 aopOp (result, ic, FALSE);
6540 /* move it to the result */
6541 size = AOP_SIZE (result);
6545 l = aopGet (AOP (left), offset, FALSE, FALSE);
6547 if (size == 0) { /* special case for 1 byte */
6551 emitcode ("add", "a,acc");
6552 if (AOP_SIZE (result) > 1)
6553 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6556 l = aopGet (AOP (left), offset, FALSE, FALSE);
6558 emitcode ("rlc", "a");
6559 if (AOP_SIZE (result) > 1)
6560 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6563 /* now we need to put the carry into the
6564 highest order byte of the result */
6565 if (AOP_SIZE (result) > 1)
6567 l = aopGet (AOP (result), 0, FALSE, FALSE);
6570 emitcode ("mov", "acc.0,c");
6572 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6573 freeAsmop (left, NULL, ic, TRUE);
6574 freeAsmop (result, NULL, ic, TRUE);
6577 /*-----------------------------------------------------------------*/
6578 /* genGetHbit - generates code get highest order bit */
6579 /*-----------------------------------------------------------------*/
6581 genGetHbit (iCode * ic)
6583 operand *left, *result;
6585 D(emitcode ("; genGetHbit",""));
6587 left = IC_LEFT (ic);
6588 result = IC_RESULT (ic);
6589 aopOp (left, ic, FALSE);
6590 aopOp (result, ic, FALSE);
6592 /* get the highest order byte into a */
6593 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6594 if (AOP_TYPE (result) == AOP_CRY)
6596 emitcode ("rlc", "a");
6601 emitcode ("rl", "a");
6602 emitcode ("anl", "a,#0x01");
6607 freeAsmop (left, NULL, ic, TRUE);
6608 freeAsmop (result, NULL, ic, TRUE);
6611 /*-----------------------------------------------------------------*/
6612 /* genSwap - generates code to swap nibbles or bytes */
6613 /*-----------------------------------------------------------------*/
6615 genSwap (iCode * ic)
6617 operand *left, *result;
6619 D(emitcode ("; genSwap",""));
6621 left = IC_LEFT (ic);
6622 result = IC_RESULT (ic);
6623 aopOp (left, ic, FALSE);
6624 aopOp (result, ic, FALSE);
6626 switch (AOP_SIZE (left))
6628 case 1: /* swap nibbles in byte */
6629 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6630 emitcode ("swap", "a");
6631 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6633 case 2: /* swap bytes in word */
6634 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6636 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6637 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6638 0, isOperandVolatile (result, FALSE));
6639 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6641 else if (operandsEqu (left, result))
6644 bool pushedB = FALSE, leftInB = FALSE;
6646 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6647 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6650 emitcode ("mov", "b,a");
6654 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6655 0, isOperandVolatile (result, FALSE));
6656 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6663 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6664 0, isOperandVolatile (result, FALSE));
6665 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6666 1, isOperandVolatile (result, FALSE));
6670 wassertl(FALSE, "unsupported SWAP operand size");
6673 freeAsmop (left, NULL, ic, TRUE);
6674 freeAsmop (result, NULL, ic, TRUE);
6678 /*-----------------------------------------------------------------*/
6679 /* AccRol - rotate left accumulator by known count */
6680 /*-----------------------------------------------------------------*/
6682 AccRol (int shCount)
6684 shCount &= 0x0007; // shCount : 0..7
6691 emitcode ("rl", "a");
6694 emitcode ("rl", "a");
6695 emitcode ("rl", "a");
6698 emitcode ("swap", "a");
6699 emitcode ("rr", "a");
6702 emitcode ("swap", "a");
6705 emitcode ("swap", "a");
6706 emitcode ("rl", "a");
6709 emitcode ("rr", "a");
6710 emitcode ("rr", "a");
6713 emitcode ("rr", "a");
6718 /*-----------------------------------------------------------------*/
6719 /* AccLsh - left shift accumulator by known count */
6720 /*-----------------------------------------------------------------*/
6722 AccLsh (int shCount)
6727 emitcode ("add", "a,acc");
6728 else if (shCount == 2)
6730 emitcode ("add", "a,acc");
6731 emitcode ("add", "a,acc");
6735 /* rotate left accumulator */
6737 /* and kill the lower order bits */
6738 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6743 /*-----------------------------------------------------------------*/
6744 /* AccRsh - right shift accumulator by known count */
6745 /*-----------------------------------------------------------------*/
6747 AccRsh (int shCount)
6754 emitcode ("rrc", "a");
6758 /* rotate right accumulator */
6759 AccRol (8 - shCount);
6760 /* and kill the higher order bits */
6761 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6766 /*-----------------------------------------------------------------*/
6767 /* AccSRsh - signed right shift accumulator by known count */
6768 /*-----------------------------------------------------------------*/
6770 AccSRsh (int shCount)
6777 emitcode ("mov", "c,acc.7");
6778 emitcode ("rrc", "a");
6780 else if (shCount == 2)
6782 emitcode ("mov", "c,acc.7");
6783 emitcode ("rrc", "a");
6784 emitcode ("mov", "c,acc.7");
6785 emitcode ("rrc", "a");
6789 tlbl = newiTempLabel (NULL);
6790 /* rotate right accumulator */
6791 AccRol (8 - shCount);
6792 /* and kill the higher order bits */
6793 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6794 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6795 emitcode ("orl", "a,#0x%02x",
6796 (unsigned char) ~SRMask[shCount]);
6797 emitcode ("", "%05d$:", tlbl->key + 100);
6802 /*-----------------------------------------------------------------*/
6803 /* shiftR1Left2Result - shift right one byte from left to result */
6804 /*-----------------------------------------------------------------*/
6806 shiftR1Left2Result (operand * left, int offl,
6807 operand * result, int offr,
6808 int shCount, int sign)
6810 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6811 /* shift right accumulator */
6816 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6819 /*-----------------------------------------------------------------*/
6820 /* shiftL1Left2Result - shift left one byte from left to result */
6821 /*-----------------------------------------------------------------*/
6823 shiftL1Left2Result (operand * left, int offl,
6824 operand * result, int offr, int shCount)
6827 l = aopGet (AOP (left), offl, FALSE, FALSE);
6829 /* shift left accumulator */
6831 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6834 /*-----------------------------------------------------------------*/
6835 /* movLeft2Result - move byte from left to result */
6836 /*-----------------------------------------------------------------*/
6838 movLeft2Result (operand * left, int offl,
6839 operand * result, int offr, int sign)
6842 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6844 l = aopGet (AOP (left), offl, FALSE, FALSE);
6846 if (*l == '@' && (IS_AOP_PREG (result)))
6848 emitcode ("mov", "a,%s", l);
6849 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6854 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6857 /* MSB sign in acc.7 ! */
6858 if (getDataSize (left) == offl + 1)
6860 emitcode ("mov", "a,%s", l);
6861 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6868 /*-----------------------------------------------------------------*/
6869 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6870 /*-----------------------------------------------------------------*/
6874 emitcode ("rrc", "a");
6875 emitcode ("xch", "a,%s", x);
6876 emitcode ("rrc", "a");
6877 emitcode ("xch", "a,%s", x);
6880 /*-----------------------------------------------------------------*/
6881 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6882 /*-----------------------------------------------------------------*/
6886 emitcode ("xch", "a,%s", x);
6887 emitcode ("rlc", "a");
6888 emitcode ("xch", "a,%s", x);
6889 emitcode ("rlc", "a");
6892 /*-----------------------------------------------------------------*/
6893 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6894 /*-----------------------------------------------------------------*/
6898 emitcode ("xch", "a,%s", x);
6899 emitcode ("add", "a,acc");
6900 emitcode ("xch", "a,%s", x);
6901 emitcode ("rlc", "a");
6904 /*-----------------------------------------------------------------*/
6905 /* AccAXLsh - left shift a:x by known count (0..7) */
6906 /*-----------------------------------------------------------------*/
6908 AccAXLsh (char *x, int shCount)
6923 case 5: // AAAAABBB:CCCCCDDD
6925 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6927 emitcode ("anl", "a,#0x%02x",
6928 SLMask[shCount]); // BBB00000:CCCCCDDD
6930 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6932 AccRol (shCount); // DDDCCCCC:BBB00000
6934 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6936 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6938 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6940 emitcode ("anl", "a,#0x%02x",
6941 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6943 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6945 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6948 case 6: // AAAAAABB:CCCCCCDD
6949 emitcode ("anl", "a,#0x%02x",
6950 SRMask[shCount]); // 000000BB:CCCCCCDD
6951 emitcode ("mov", "c,acc.0"); // c = B
6952 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6954 AccAXRrl1 (x); // BCCCCCCD:D000000B
6955 AccAXRrl1 (x); // BBCCCCCC:DD000000
6957 emitcode("rrc","a");
6958 emitcode("xch","a,%s", x);
6959 emitcode("rrc","a");
6960 emitcode("mov","c,acc.0"); //<< get correct bit
6961 emitcode("xch","a,%s", x);
6963 emitcode("rrc","a");
6964 emitcode("xch","a,%s", x);
6965 emitcode("rrc","a");
6966 emitcode("xch","a,%s", x);
6969 case 7: // a:x <<= 7
6971 emitcode ("anl", "a,#0x%02x",
6972 SRMask[shCount]); // 0000000B:CCCCCCCD
6974 emitcode ("mov", "c,acc.0"); // c = B
6976 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6978 AccAXRrl1 (x); // BCCCCCCC:D0000000
6986 /*-----------------------------------------------------------------*/
6987 /* AccAXRsh - right shift a:x known count (0..7) */
6988 /*-----------------------------------------------------------------*/
6990 AccAXRsh (char *x, int shCount)
6998 AccAXRrl1 (x); // 0->a:x
7003 AccAXRrl1 (x); // 0->a:x
7006 AccAXRrl1 (x); // 0->a:x
7011 case 5: // AAAAABBB:CCCCCDDD = a:x
7013 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7015 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7017 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7019 emitcode ("anl", "a,#0x%02x",
7020 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7022 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7024 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7026 emitcode ("anl", "a,#0x%02x",
7027 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7029 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7031 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7033 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7036 case 6: // AABBBBBB:CCDDDDDD
7038 emitcode ("mov", "c,acc.7");
7039 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7041 emitcode ("mov", "c,acc.7");
7042 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7044 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7046 emitcode ("anl", "a,#0x%02x",
7047 SRMask[shCount]); // 000000AA:BBBBBBCC
7050 case 7: // ABBBBBBB:CDDDDDDD
7052 emitcode ("mov", "c,acc.7"); // c = A
7054 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7056 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7058 emitcode ("anl", "a,#0x%02x",
7059 SRMask[shCount]); // 0000000A:BBBBBBBC
7067 /*-----------------------------------------------------------------*/
7068 /* AccAXRshS - right shift signed a:x known count (0..7) */
7069 /*-----------------------------------------------------------------*/
7071 AccAXRshS (char *x, int shCount)
7079 emitcode ("mov", "c,acc.7");
7080 AccAXRrl1 (x); // s->a:x
7084 emitcode ("mov", "c,acc.7");
7085 AccAXRrl1 (x); // s->a:x
7087 emitcode ("mov", "c,acc.7");
7088 AccAXRrl1 (x); // s->a:x
7093 case 5: // AAAAABBB:CCCCCDDD = a:x
7095 tlbl = newiTempLabel (NULL);
7096 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7098 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7100 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7102 emitcode ("anl", "a,#0x%02x",
7103 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7105 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7107 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7109 emitcode ("anl", "a,#0x%02x",
7110 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7112 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7114 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7116 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7118 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7119 emitcode ("orl", "a,#0x%02x",
7120 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7122 emitcode ("", "%05d$:", tlbl->key + 100);
7123 break; // SSSSAAAA:BBBCCCCC
7125 case 6: // AABBBBBB:CCDDDDDD
7127 tlbl = newiTempLabel (NULL);
7128 emitcode ("mov", "c,acc.7");
7129 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7131 emitcode ("mov", "c,acc.7");
7132 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7134 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7136 emitcode ("anl", "a,#0x%02x",
7137 SRMask[shCount]); // 000000AA:BBBBBBCC
7139 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7140 emitcode ("orl", "a,#0x%02x",
7141 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7143 emitcode ("", "%05d$:", tlbl->key + 100);
7145 case 7: // ABBBBBBB:CDDDDDDD
7147 tlbl = newiTempLabel (NULL);
7148 emitcode ("mov", "c,acc.7"); // c = A
7150 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7152 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7154 emitcode ("anl", "a,#0x%02x",
7155 SRMask[shCount]); // 0000000A:BBBBBBBC
7157 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7158 emitcode ("orl", "a,#0x%02x",
7159 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7161 emitcode ("", "%05d$:", tlbl->key + 100);
7168 /*-----------------------------------------------------------------*/
7169 /* shiftL2Left2Result - shift left two bytes from left to result */
7170 /*-----------------------------------------------------------------*/
7172 shiftL2Left2Result (operand * left, int offl,
7173 operand * result, int offr, int shCount)
7175 if (sameRegs (AOP (result), AOP (left)) &&
7176 ((offl + MSB16) == offr))
7178 /* don't crash result[offr] */
7179 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7180 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7184 movLeft2Result (left, offl, result, offr, 0);
7185 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7187 /* ax << shCount (x = lsb(result)) */
7188 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7189 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7193 /*-----------------------------------------------------------------*/
7194 /* shiftR2Left2Result - shift right two bytes from left to result */
7195 /*-----------------------------------------------------------------*/
7197 shiftR2Left2Result (operand * left, int offl,
7198 operand * result, int offr,
7199 int shCount, int sign)
7201 if (sameRegs (AOP (result), AOP (left)) &&
7202 ((offl + MSB16) == offr))
7204 /* don't crash result[offr] */
7205 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7206 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7210 movLeft2Result (left, offl, result, offr, 0);
7211 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7213 /* a:x >> shCount (x = lsb(result)) */
7215 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7217 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7218 if (getDataSize (result) > 1)
7219 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7222 /*-----------------------------------------------------------------*/
7223 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7224 /*-----------------------------------------------------------------*/
7226 shiftLLeftOrResult (operand * left, int offl,
7227 operand * result, int offr, int shCount)
7229 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7230 /* shift left accumulator */
7232 /* or with result */
7233 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7234 /* back to result */
7235 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7238 /*-----------------------------------------------------------------*/
7239 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7240 /*-----------------------------------------------------------------*/
7242 shiftRLeftOrResult (operand * left, int offl,
7243 operand * result, int offr, int shCount)
7245 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7246 /* shift right accumulator */
7248 /* or with result */
7249 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7250 /* back to result */
7251 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7254 /*-----------------------------------------------------------------*/
7255 /* genlshOne - left shift a one byte quantity by known count */
7256 /*-----------------------------------------------------------------*/
7258 genlshOne (operand * result, operand * left, int shCount)
7260 D(emitcode ("; genlshOne",""));
7262 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7265 /*-----------------------------------------------------------------*/
7266 /* genlshTwo - left shift two bytes by known amount != 0 */
7267 /*-----------------------------------------------------------------*/
7269 genlshTwo (operand * result, operand * left, int shCount)
7273 D(emitcode ("; genlshTwo",""));
7275 size = getDataSize (result);
7277 /* if shCount >= 8 */
7285 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7287 movLeft2Result (left, LSB, result, MSB16, 0);
7289 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7292 /* 1 <= shCount <= 7 */
7296 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7298 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7302 /*-----------------------------------------------------------------*/
7303 /* shiftLLong - shift left one long from left to result */
7304 /* offl = LSB or MSB16 */
7305 /*-----------------------------------------------------------------*/
7307 shiftLLong (operand * left, operand * result, int offr)
7310 int size = AOP_SIZE (result);
7312 if (size >= LSB + offr)
7314 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7316 emitcode ("add", "a,acc");
7317 if (sameRegs (AOP (left), AOP (result)) &&
7318 size >= MSB16 + offr && offr != LSB)
7319 emitcode ("xch", "a,%s",
7320 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7322 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7325 if (size >= MSB16 + offr)
7327 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7329 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7332 emitcode ("rlc", "a");
7333 if (sameRegs (AOP (left), AOP (result)) &&
7334 size >= MSB24 + offr && offr != LSB)
7335 emitcode ("xch", "a,%s",
7336 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7338 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7341 if (size >= MSB24 + offr)
7343 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7345 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7348 emitcode ("rlc", "a");
7349 if (sameRegs (AOP (left), AOP (result)) &&
7350 size >= MSB32 + offr && offr != LSB)
7351 emitcode ("xch", "a,%s",
7352 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7354 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7357 if (size > MSB32 + offr)
7359 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7361 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7364 emitcode ("rlc", "a");
7365 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7368 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7371 /*-----------------------------------------------------------------*/
7372 /* genlshFour - shift four byte by a known amount != 0 */
7373 /*-----------------------------------------------------------------*/
7375 genlshFour (operand * result, operand * left, int shCount)
7379 D(emitcode ("; genlshFour",""));
7381 size = AOP_SIZE (result);
7383 /* if shifting more that 3 bytes */
7388 /* lowest order of left goes to the highest
7389 order of the destination */
7390 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7392 movLeft2Result (left, LSB, result, MSB32, 0);
7393 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7394 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7395 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7399 /* more than two bytes */
7400 else if (shCount >= 16)
7402 /* lower order two bytes goes to higher order two bytes */
7404 /* if some more remaining */
7406 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7409 movLeft2Result (left, MSB16, result, MSB32, 0);
7410 movLeft2Result (left, LSB, result, MSB24, 0);
7412 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7413 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7417 /* if more than 1 byte */
7418 else if (shCount >= 8)
7420 /* lower order three bytes goes to higher order three bytes */
7425 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7427 movLeft2Result (left, LSB, result, MSB16, 0);
7433 movLeft2Result (left, MSB24, result, MSB32, 0);
7434 movLeft2Result (left, MSB16, result, MSB24, 0);
7435 movLeft2Result (left, LSB, result, MSB16, 0);
7436 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7438 else if (shCount == 1)
7439 shiftLLong (left, result, MSB16);
7442 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7443 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7444 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7445 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7450 /* 1 <= shCount <= 7 */
7451 else if (shCount <= 2)
7453 shiftLLong (left, result, LSB);
7455 shiftLLong (result, result, LSB);
7457 /* 3 <= shCount <= 7, optimize */
7460 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7461 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7462 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7466 /*-----------------------------------------------------------------*/
7467 /* genLeftShiftLiteral - left shifting by known count */
7468 /*-----------------------------------------------------------------*/
7470 genLeftShiftLiteral (operand * left,
7475 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7478 D(emitcode ("; genLeftShiftLiteral",""));
7480 freeAsmop (right, NULL, ic, TRUE);
7482 aopOp (left, ic, FALSE);
7483 aopOp (result, ic, FALSE);
7485 size = getSize (operandType (result));
7488 emitcode ("; shift left ", "result %d, left %d", size,
7492 /* I suppose that the left size >= result size */
7497 movLeft2Result (left, size, result, size, 0);
7501 else if (shCount >= (size * 8))
7503 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7509 genlshOne (result, left, shCount);
7513 genlshTwo (result, left, shCount);
7517 genlshFour (result, left, shCount);
7520 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7521 "*** ack! mystery literal shift!\n");
7525 freeAsmop (left, NULL, ic, TRUE);
7526 freeAsmop (result, NULL, ic, TRUE);
7529 /*-----------------------------------------------------------------*/
7530 /* genLeftShift - generates code for left shifting */
7531 /*-----------------------------------------------------------------*/
7533 genLeftShift (iCode * ic)
7535 operand *left, *right, *result;
7538 symbol *tlbl, *tlbl1;
7541 D(emitcode ("; genLeftShift",""));
7543 right = IC_RIGHT (ic);
7544 left = IC_LEFT (ic);
7545 result = IC_RESULT (ic);
7547 aopOp (right, ic, FALSE);
7549 /* if the shift count is known then do it
7550 as efficiently as possible */
7551 if (AOP_TYPE (right) == AOP_LIT)
7553 genLeftShiftLiteral (left, right, result, ic);
7557 /* shift count is unknown then we have to form
7558 a loop get the loop count in B : Note: we take
7559 only the lower order byte since shifting
7560 more that 32 bits make no sense anyway, ( the
7561 largest size of an object can be only 32 bits ) */
7564 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7565 emitcode ("inc", "b");
7566 freeAsmop (right, NULL, ic, TRUE);
7567 aopOp (left, ic, FALSE);
7568 aopOp (result, ic, FALSE);
7570 /* now move the left to the result if they are not the same */
7571 if (!sameRegs (AOP (left), AOP (result)) &&
7572 AOP_SIZE (result) > 1)
7575 size = AOP_SIZE (result);
7579 l = aopGet (AOP (left), offset, FALSE, TRUE);
7580 if (*l == '@' && (IS_AOP_PREG (result)))
7583 emitcode ("mov", "a,%s", l);
7584 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7587 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7592 tlbl = newiTempLabel (NULL);
7593 size = AOP_SIZE (result);
7595 tlbl1 = newiTempLabel (NULL);
7597 /* if it is only one byte then */
7600 symbol *tlbl1 = newiTempLabel (NULL);
7602 l = aopGet (AOP (left), 0, FALSE, FALSE);
7604 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7605 emitcode ("", "%05d$:", tlbl->key + 100);
7606 emitcode ("add", "a,acc");
7607 emitcode ("", "%05d$:", tlbl1->key + 100);
7608 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7610 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7614 reAdjustPreg (AOP (result));
7616 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7617 emitcode ("", "%05d$:", tlbl->key + 100);
7618 l = aopGet (AOP (result), offset, FALSE, FALSE);
7620 emitcode ("add", "a,acc");
7621 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7624 l = aopGet (AOP (result), offset, FALSE, FALSE);
7626 emitcode ("rlc", "a");
7627 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7629 reAdjustPreg (AOP (result));
7631 emitcode ("", "%05d$:", tlbl1->key + 100);
7632 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7635 freeAsmop (left, NULL, ic, TRUE);
7636 freeAsmop (result, NULL, ic, TRUE);
7639 /*-----------------------------------------------------------------*/
7640 /* genrshOne - right shift a one byte quantity by known count */
7641 /*-----------------------------------------------------------------*/
7643 genrshOne (operand * result, operand * left,
7644 int shCount, int sign)
7646 D(emitcode ("; genrshOne",""));
7648 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7651 /*-----------------------------------------------------------------*/
7652 /* genrshTwo - right shift two bytes by known amount != 0 */
7653 /*-----------------------------------------------------------------*/
7655 genrshTwo (operand * result, operand * left,
7656 int shCount, int sign)
7658 D(emitcode ("; genrshTwo",""));
7660 /* if shCount >= 8 */
7665 shiftR1Left2Result (left, MSB16, result, LSB,
7668 movLeft2Result (left, MSB16, result, LSB, sign);
7669 addSign (result, MSB16, sign);
7672 /* 1 <= shCount <= 7 */
7674 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7677 /*-----------------------------------------------------------------*/
7678 /* shiftRLong - shift right one long from left to result */
7679 /* offl = LSB or MSB16 */
7680 /*-----------------------------------------------------------------*/
7682 shiftRLong (operand * left, int offl,
7683 operand * result, int sign)
7685 int isSameRegs=sameRegs(AOP(left),AOP(result));
7687 if (isSameRegs && offl>1) {
7688 // we are in big trouble, but this shouldn't happen
7689 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7692 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7697 emitcode ("rlc", "a");
7698 emitcode ("subb", "a,acc");
7700 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7702 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7703 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7706 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7711 emitcode ("clr", "c");
7713 emitcode ("mov", "c,acc.7");
7716 emitcode ("rrc", "a");
7718 if (isSameRegs && offl==MSB16) {
7719 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7721 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7722 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7725 emitcode ("rrc", "a");
7726 if (isSameRegs && offl==1) {
7727 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7729 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7730 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7732 emitcode ("rrc", "a");
7733 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7737 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7738 emitcode ("rrc", "a");
7739 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7743 /*-----------------------------------------------------------------*/
7744 /* genrshFour - shift four byte by a known amount != 0 */
7745 /*-----------------------------------------------------------------*/
7747 genrshFour (operand * result, operand * left,
7748 int shCount, int sign)
7750 D(emitcode ("; genrshFour",""));
7752 /* if shifting more that 3 bytes */
7757 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7759 movLeft2Result (left, MSB32, result, LSB, sign);
7760 addSign (result, MSB16, sign);
7762 else if (shCount >= 16)
7766 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7769 movLeft2Result (left, MSB24, result, LSB, 0);
7770 movLeft2Result (left, MSB32, result, MSB16, sign);
7772 addSign (result, MSB24, sign);
7774 else if (shCount >= 8)
7778 shiftRLong (left, MSB16, result, sign);
7779 else if (shCount == 0)
7781 movLeft2Result (left, MSB16, result, LSB, 0);
7782 movLeft2Result (left, MSB24, result, MSB16, 0);
7783 movLeft2Result (left, MSB32, result, MSB24, sign);
7784 addSign (result, MSB32, sign);
7788 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7789 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7790 /* the last shift is signed */
7791 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7792 addSign (result, MSB32, sign);
7796 { /* 1 <= shCount <= 7 */
7799 shiftRLong (left, LSB, result, sign);
7801 shiftRLong (result, LSB, result, sign);
7805 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7806 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7807 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7812 /*-----------------------------------------------------------------*/
7813 /* genRightShiftLiteral - right shifting by known count */
7814 /*-----------------------------------------------------------------*/
7816 genRightShiftLiteral (operand * left,
7822 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7825 D(emitcode ("; genRightShiftLiteral",""));
7827 freeAsmop (right, NULL, ic, TRUE);
7829 aopOp (left, ic, FALSE);
7830 aopOp (result, ic, FALSE);
7833 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7837 size = getDataSize (left);
7838 /* test the LEFT size !!! */
7840 /* I suppose that the left size >= result size */
7843 size = getDataSize (result);
7845 movLeft2Result (left, size, result, size, 0);
7848 else if (shCount >= (size * 8))
7851 /* get sign in acc.7 */
7852 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7854 addSign (result, LSB, sign);
7861 genrshOne (result, left, shCount, sign);
7865 genrshTwo (result, left, shCount, sign);
7869 genrshFour (result, left, shCount, sign);
7875 freeAsmop (left, NULL, ic, TRUE);
7876 freeAsmop (result, NULL, ic, TRUE);
7879 /*-----------------------------------------------------------------*/
7880 /* genSignedRightShift - right shift of signed number */
7881 /*-----------------------------------------------------------------*/
7883 genSignedRightShift (iCode * ic)
7885 operand *right, *left, *result;
7888 symbol *tlbl, *tlbl1;
7891 D(emitcode ("; genSignedRightShift",""));
7893 /* we do it the hard way put the shift count in b
7894 and loop thru preserving the sign */
7896 right = IC_RIGHT (ic);
7897 left = IC_LEFT (ic);
7898 result = IC_RESULT (ic);
7900 aopOp (right, ic, FALSE);
7903 if (AOP_TYPE (right) == AOP_LIT)
7905 genRightShiftLiteral (left, right, result, ic, 1);
7908 /* shift count is unknown then we have to form
7909 a loop get the loop count in B : Note: we take
7910 only the lower order byte since shifting
7911 more that 32 bits make no sense anyway, ( the
7912 largest size of an object can be only 32 bits ) */
7915 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7916 emitcode ("inc", "b");
7917 freeAsmop (right, NULL, ic, TRUE);
7918 aopOp (left, ic, FALSE);
7919 aopOp (result, ic, FALSE);
7921 /* now move the left to the result if they are not the
7923 if (!sameRegs (AOP (left), AOP (result)) &&
7924 AOP_SIZE (result) > 1)
7927 size = AOP_SIZE (result);
7931 l = aopGet (AOP (left), offset, FALSE, TRUE);
7932 if (*l == '@' && IS_AOP_PREG (result))
7935 emitcode ("mov", "a,%s", l);
7936 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7939 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7944 /* mov the highest order bit to OVR */
7945 tlbl = newiTempLabel (NULL);
7946 tlbl1 = newiTempLabel (NULL);
7948 size = AOP_SIZE (result);
7950 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7951 emitcode ("rlc", "a");
7952 emitcode ("mov", "ov,c");
7953 /* if it is only one byte then */
7956 l = aopGet (AOP (left), 0, FALSE, FALSE);
7958 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7959 emitcode ("", "%05d$:", tlbl->key + 100);
7960 emitcode ("mov", "c,ov");
7961 emitcode ("rrc", "a");
7962 emitcode ("", "%05d$:", tlbl1->key + 100);
7963 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7965 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7969 reAdjustPreg (AOP (result));
7970 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7971 emitcode ("", "%05d$:", tlbl->key + 100);
7972 emitcode ("mov", "c,ov");
7975 l = aopGet (AOP (result), offset, FALSE, FALSE);
7977 emitcode ("rrc", "a");
7978 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7980 reAdjustPreg (AOP (result));
7981 emitcode ("", "%05d$:", tlbl1->key + 100);
7982 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7986 freeAsmop (left, NULL, ic, TRUE);
7987 freeAsmop (result, NULL, ic, TRUE);
7990 /*-----------------------------------------------------------------*/
7991 /* genRightShift - generate code for right shifting */
7992 /*-----------------------------------------------------------------*/
7994 genRightShift (iCode * ic)
7996 operand *right, *left, *result;
8000 symbol *tlbl, *tlbl1;
8003 D(emitcode ("; genRightShift",""));
8005 /* if signed then we do it the hard way preserve the
8006 sign bit moving it inwards */
8007 letype = getSpec (operandType (IC_LEFT (ic)));
8009 if (!SPEC_USIGN (letype))
8011 genSignedRightShift (ic);
8015 /* signed & unsigned types are treated the same : i.e. the
8016 signed is NOT propagated inwards : quoting from the
8017 ANSI - standard : "for E1 >> E2, is equivalent to division
8018 by 2**E2 if unsigned or if it has a non-negative value,
8019 otherwise the result is implementation defined ", MY definition
8020 is that the sign does not get propagated */
8022 right = IC_RIGHT (ic);
8023 left = IC_LEFT (ic);
8024 result = IC_RESULT (ic);
8026 aopOp (right, ic, FALSE);
8028 /* if the shift count is known then do it
8029 as efficiently as possible */
8030 if (AOP_TYPE (right) == AOP_LIT)
8032 genRightShiftLiteral (left, right, result, ic, 0);
8036 /* shift count is unknown then we have to form
8037 a loop get the loop count in B : Note: we take
8038 only the lower order byte since shifting
8039 more that 32 bits make no sense anyway, ( the
8040 largest size of an object can be only 32 bits ) */
8043 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8044 emitcode ("inc", "b");
8045 freeAsmop (right, NULL, ic, TRUE);
8046 aopOp (left, ic, FALSE);
8047 aopOp (result, ic, FALSE);
8049 /* now move the left to the result if they are not the
8051 if (!sameRegs (AOP (left), AOP (result)) &&
8052 AOP_SIZE (result) > 1)
8055 size = AOP_SIZE (result);
8059 l = aopGet (AOP (left), offset, FALSE, TRUE);
8060 if (*l == '@' && IS_AOP_PREG (result))
8063 emitcode ("mov", "a,%s", l);
8064 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8067 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8072 tlbl = newiTempLabel (NULL);
8073 tlbl1 = newiTempLabel (NULL);
8074 size = AOP_SIZE (result);
8077 /* if it is only one byte then */
8080 l = aopGet (AOP (left), 0, FALSE, FALSE);
8082 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8083 emitcode ("", "%05d$:", tlbl->key + 100);
8085 emitcode ("rrc", "a");
8086 emitcode ("", "%05d$:", tlbl1->key + 100);
8087 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8089 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8093 reAdjustPreg (AOP (result));
8094 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8095 emitcode ("", "%05d$:", tlbl->key + 100);
8099 l = aopGet (AOP (result), offset, FALSE, FALSE);
8101 emitcode ("rrc", "a");
8102 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8104 reAdjustPreg (AOP (result));
8106 emitcode ("", "%05d$:", tlbl1->key + 100);
8107 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8111 freeAsmop (left, NULL, ic, TRUE);
8112 freeAsmop (result, NULL, ic, TRUE);
8115 /*-----------------------------------------------------------------*/
8116 /* emitPtrByteGet - emits code to get a byte into A through a */
8117 /* pointer register (R0, R1, or DPTR). The */
8118 /* original value of A can be preserved in B. */
8119 /*-----------------------------------------------------------------*/
8121 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8128 emitcode ("mov", "b,a");
8129 emitcode ("mov", "a,@%s", rname);
8134 emitcode ("mov", "b,a");
8135 emitcode ("movx", "a,@%s", rname);
8140 emitcode ("mov", "b,a");
8141 emitcode ("movx", "a,@dptr");
8146 emitcode ("mov", "b,a");
8147 emitcode ("clr", "a");
8148 emitcode ("movc", "a,@a+dptr");
8154 emitcode ("push", "b");
8155 emitcode ("push", "acc");
8157 emitcode ("lcall", "__gptrget");
8159 emitcode ("pop", "b");
8164 /*-----------------------------------------------------------------*/
8165 /* emitPtrByteSet - emits code to set a byte from src through a */
8166 /* pointer register (R0, R1, or DPTR). */
8167 /*-----------------------------------------------------------------*/
8169 emitPtrByteSet (char *rname, int p_type, char *src)
8178 emitcode ("mov", "@%s,a", rname);
8181 emitcode ("mov", "@%s,%s", rname, src);
8186 emitcode ("movx", "@%s,a", rname);
8191 emitcode ("movx", "@dptr,a");
8196 emitcode ("lcall", "__gptrput");
8201 /*-----------------------------------------------------------------*/
8202 /* genUnpackBits - generates code for unpacking bits */
8203 /*-----------------------------------------------------------------*/
8205 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8207 int offset = 0; /* result byte offset */
8208 int rsize; /* result size */
8209 int rlen = 0; /* remaining bitfield length */
8210 sym_link *etype; /* bitfield type information */
8211 int blen; /* bitfield length */
8212 int bstr; /* bitfield starting bit within byte */
8215 D(emitcode ("; genUnpackBits",""));
8217 etype = getSpec (operandType (result));
8218 rsize = getSize (operandType (result));
8219 blen = SPEC_BLEN (etype);
8220 bstr = SPEC_BSTR (etype);
8222 if (ifx && blen <= 8)
8224 emitPtrByteGet (rname, ptype, FALSE);
8227 SNPRINTF (buffer, sizeof(buffer),
8229 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8234 emitcode ("anl", "a,#0x%02x",
8235 (((unsigned char) -1) >> (8 - blen)) << bstr);
8236 genIfxJump (ifx, "a", NULL, NULL, NULL);
8242 /* If the bitfield length is less than a byte */
8245 emitPtrByteGet (rname, ptype, FALSE);
8247 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8248 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8252 /* Bit field did not fit in a byte. Copy all
8253 but the partial byte at the end. */
8254 for (rlen=blen;rlen>=8;rlen-=8)
8256 emitPtrByteGet (rname, ptype, FALSE);
8257 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8259 emitcode ("inc", "%s", rname);
8262 /* Handle the partial byte at the end */
8265 emitPtrByteGet (rname, ptype, FALSE);
8266 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8267 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8275 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8280 /*-----------------------------------------------------------------*/
8281 /* genDataPointerGet - generates code when ptr offset is known */
8282 /*-----------------------------------------------------------------*/
8284 genDataPointerGet (operand * left,
8290 int size, offset = 0;
8292 D(emitcode ("; genDataPointerGet",""));
8294 aopOp (result, ic, TRUE);
8296 /* get the string representation of the name */
8297 l = aopGet (AOP (left), 0, FALSE, TRUE);
8298 size = AOP_SIZE (result);
8302 sprintf (buffer, "(%s + %d)", l + 1, offset);
8304 sprintf (buffer, "%s", l + 1);
8305 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8308 freeAsmop (left, NULL, ic, TRUE);
8309 freeAsmop (result, NULL, ic, TRUE);
8312 /*-----------------------------------------------------------------*/
8313 /* genNearPointerGet - emitcode for near pointer fetch */
8314 /*-----------------------------------------------------------------*/
8316 genNearPointerGet (operand * left,
8325 sym_link *rtype, *retype;
8326 sym_link *ltype = operandType (left);
8329 D(emitcode ("; genNearPointerGet",""));
8331 rtype = operandType (result);
8332 retype = getSpec (rtype);
8334 aopOp (left, ic, FALSE);
8336 /* if left is rematerialisable and
8337 result is not bitfield variable type and
8338 the left is pointer to data space i.e
8339 lower 128 bytes of space */
8340 if (AOP_TYPE (left) == AOP_IMMD &&
8341 !IS_BITFIELD (retype) &&
8342 DCL_TYPE (ltype) == POINTER)
8344 genDataPointerGet (left, result, ic);
8348 /* if the value is already in a pointer register
8349 then don't need anything more */
8350 if (!AOP_INPREG (AOP (left)))
8352 if (IS_AOP_PREG (left))
8354 // Aha, it is a pointer, just in disguise.
8355 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8358 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8359 __FILE__, __LINE__);
8364 emitcode ("mov", "a%s,%s", rname + 1, rname);
8365 rname++; // skip the '@'.
8370 /* otherwise get a free pointer register */
8372 preg = getFreePtr (ic, &aop, FALSE);
8373 emitcode ("mov", "%s,%s",
8375 aopGet (AOP (left), 0, FALSE, TRUE));
8380 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8382 //aopOp (result, ic, FALSE);
8383 aopOp (result, ic, result?TRUE:FALSE);
8385 /* if bitfield then unpack the bits */
8386 if (IS_BITFIELD (retype))
8387 genUnpackBits (result, rname, POINTER, ifx);
8390 /* we have can just get the values */
8391 int size = AOP_SIZE (result);
8396 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8399 emitcode ("mov", "a,@%s", rname);
8401 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8405 sprintf (buffer, "@%s", rname);
8406 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8410 emitcode ("inc", "%s", rname);
8414 /* now some housekeeping stuff */
8415 if (aop) /* we had to allocate for this iCode */
8417 if (pi) { /* post increment present */
8418 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8420 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8424 /* we did not allocate which means left
8425 already in a pointer register, then
8426 if size > 0 && this could be used again
8427 we have to point it back to where it
8429 if ((AOP_SIZE (result) > 1 &&
8430 !OP_SYMBOL (left)->remat &&
8431 (OP_SYMBOL (left)->liveTo > ic->seq ||
8435 int size = AOP_SIZE (result) - 1;
8437 emitcode ("dec", "%s", rname);
8441 if (ifx && !ifx->generated)
8443 genIfxJump (ifx, "a", left, NULL, result);
8447 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8448 freeAsmop (left, NULL, ic, TRUE);
8449 if (pi) pi->generated = 1;
8452 /*-----------------------------------------------------------------*/
8453 /* genPagedPointerGet - emitcode for paged pointer fetch */
8454 /*-----------------------------------------------------------------*/
8456 genPagedPointerGet (operand * left,
8465 sym_link *rtype, *retype;
8467 D(emitcode ("; genPagedPointerGet",""));
8469 rtype = operandType (result);
8470 retype = getSpec (rtype);
8472 aopOp (left, ic, FALSE);
8474 /* if the value is already in a pointer register
8475 then don't need anything more */
8476 if (!AOP_INPREG (AOP (left)))
8478 /* otherwise get a free pointer register */
8480 preg = getFreePtr (ic, &aop, FALSE);
8481 emitcode ("mov", "%s,%s",
8483 aopGet (AOP (left), 0, FALSE, TRUE));
8487 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8489 aopOp (result, ic, FALSE);
8491 /* if bitfield then unpack the bits */
8492 if (IS_BITFIELD (retype))
8493 genUnpackBits (result, rname, PPOINTER, ifx);
8496 /* we have can just get the values */
8497 int size = AOP_SIZE (result);
8503 emitcode ("movx", "a,@%s", rname);
8505 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8510 emitcode ("inc", "%s", rname);
8514 /* now some housekeeping stuff */
8515 if (aop) /* we had to allocate for this iCode */
8517 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8518 freeAsmop (NULL, aop, ic, TRUE);
8522 /* we did not allocate which means left
8523 already in a pointer register, then
8524 if size > 0 && this could be used again
8525 we have to point it back to where it
8527 if ((AOP_SIZE (result) > 1 &&
8528 !OP_SYMBOL (left)->remat &&
8529 (OP_SYMBOL (left)->liveTo > ic->seq ||
8533 int size = AOP_SIZE (result) - 1;
8535 emitcode ("dec", "%s", rname);
8539 if (ifx && !ifx->generated)
8541 genIfxJump (ifx, "a", left, NULL, result);
8545 freeAsmop (left, NULL, ic, TRUE);
8546 freeAsmop (result, NULL, ic, TRUE);
8547 if (pi) pi->generated = 1;
8551 /*--------------------------------------------------------------------*/
8552 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8553 /*--------------------------------------------------------------------*/
8555 loadDptrFromOperand (operand *op, bool loadBToo)
8557 if (AOP_TYPE (op) != AOP_STR)
8559 /* if this is rematerializable */
8560 if (AOP_TYPE (op) == AOP_IMMD)
8562 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8565 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8566 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8569 wassertl(FALSE, "need pointerCode");
8570 emitcode ("", "; mov b,???");
8571 /* genPointerGet and genPointerSet originally did different
8572 ** things for this case. Both seem wrong.
8573 ** from genPointerGet:
8574 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8575 ** from genPointerSet:
8576 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8581 else if (AOP_TYPE (op) == AOP_DPTR)
8585 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8586 emitcode ("push", "acc");
8587 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8588 emitcode ("push", "acc");
8589 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8590 emitcode ("pop", "dph");
8591 emitcode ("pop", "dpl");
8595 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8596 emitcode ("push", "acc");
8597 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8598 emitcode ("pop", "dpl");
8602 { /* we need to get it byte by byte */
8603 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8604 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8606 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8611 /*-----------------------------------------------------------------*/
8612 /* genFarPointerGet - gget value from far space */
8613 /*-----------------------------------------------------------------*/
8615 genFarPointerGet (operand * left,
8616 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8619 sym_link *retype = getSpec (operandType (result));
8621 D(emitcode ("; genFarPointerGet",""));
8623 aopOp (left, ic, FALSE);
8624 loadDptrFromOperand (left, FALSE);
8626 /* so dptr now contains the address */
8627 aopOp (result, ic, FALSE);
8629 /* if bit then unpack */
8630 if (IS_BITFIELD (retype))
8631 genUnpackBits (result, "dptr", FPOINTER, ifx);
8634 size = AOP_SIZE (result);
8639 emitcode ("movx", "a,@dptr");
8641 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8643 emitcode ("inc", "dptr");
8647 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8649 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8650 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8654 if (ifx && !ifx->generated)
8656 genIfxJump (ifx, "a", left, NULL, result);
8659 freeAsmop (left, NULL, ic, TRUE);
8660 freeAsmop (result, NULL, ic, TRUE);
8663 /*-----------------------------------------------------------------*/
8664 /* genCodePointerGet - gget value from code space */
8665 /*-----------------------------------------------------------------*/
8667 genCodePointerGet (operand * left,
8668 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8671 sym_link *retype = getSpec (operandType (result));
8673 D(emitcode ("; genCodePointerGet",""));
8675 aopOp (left, ic, FALSE);
8676 loadDptrFromOperand (left, FALSE);
8678 /* so dptr now contains the address */
8679 aopOp (result, ic, FALSE);
8681 /* if bit then unpack */
8682 if (IS_BITFIELD (retype))
8683 genUnpackBits (result, "dptr", CPOINTER, ifx);
8686 size = AOP_SIZE (result);
8693 emitcode ("clr", "a");
8694 emitcode ("movc", "a,@a+dptr");
8696 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8697 emitcode ("inc", "dptr");
8701 emitcode ("mov", "a,#0x%02x", offset);
8702 emitcode ("movc", "a,@a+dptr");
8704 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8709 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8711 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8712 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8716 if (ifx && !ifx->generated)
8718 genIfxJump (ifx, "a", left, NULL, result);
8721 freeAsmop (left, NULL, ic, TRUE);
8722 freeAsmop (result, NULL, ic, TRUE);
8725 /*-----------------------------------------------------------------*/
8726 /* genGenPointerGet - gget value from generic pointer space */
8727 /*-----------------------------------------------------------------*/
8729 genGenPointerGet (operand * left,
8730 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8733 sym_link *retype = getSpec (operandType (result));
8735 D(emitcode ("; genGenPointerGet",""));
8737 aopOp (left, ic, FALSE);
8738 loadDptrFromOperand (left, TRUE);
8740 /* so dptr know contains the address */
8741 aopOp (result, ic, FALSE);
8743 /* if bit then unpack */
8744 if (IS_BITFIELD (retype))
8745 genUnpackBits (result, "dptr", GPOINTER, ifx);
8748 size = AOP_SIZE (result);
8753 emitcode ("lcall", "__gptrget");
8755 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8757 emitcode ("inc", "dptr");
8761 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8763 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8764 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8768 if (ifx && !ifx->generated)
8770 genIfxJump (ifx, "a", left, NULL, result);
8774 freeAsmop (left, NULL, ic, TRUE);
8775 freeAsmop (result, NULL, ic, TRUE);
8778 /*-----------------------------------------------------------------*/
8779 /* genPointerGet - generate code for pointer get */
8780 /*-----------------------------------------------------------------*/
8782 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8784 operand *left, *result;
8785 sym_link *type, *etype;
8788 D(emitcode ("; genPointerGet",""));
8790 left = IC_LEFT (ic);
8791 result = IC_RESULT (ic);
8793 if (getSize (operandType (result))>1)
8796 /* depending on the type of pointer we need to
8797 move it to the correct pointer register */
8798 type = operandType (left);
8799 etype = getSpec (type);
8800 /* if left is of type of pointer then it is simple */
8801 if (IS_PTR (type) && !IS_FUNC (type->next))
8802 p_type = DCL_TYPE (type);
8805 /* we have to go by the storage class */
8806 p_type = PTR_TYPE (SPEC_OCLS (etype));
8809 /* special case when cast remat */
8810 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8811 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8812 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8813 type = operandType (left);
8814 p_type = DCL_TYPE (type);
8816 /* now that we have the pointer type we assign
8817 the pointer values */
8823 genNearPointerGet (left, result, ic, pi, ifx);
8827 genPagedPointerGet (left, result, ic, pi, ifx);
8831 genFarPointerGet (left, result, ic, pi, ifx);
8835 genCodePointerGet (left, result, ic, pi, ifx);
8839 genGenPointerGet (left, result, ic, pi, ifx);
8847 /*-----------------------------------------------------------------*/
8848 /* genPackBits - generates code for packed bit storage */
8849 /*-----------------------------------------------------------------*/
8851 genPackBits (sym_link * etype,
8853 char *rname, int p_type)
8855 int offset = 0; /* source byte offset */
8856 int rlen = 0; /* remaining bitfield length */
8857 int blen; /* bitfield length */
8858 int bstr; /* bitfield starting bit within byte */
8859 int litval; /* source literal value (if AOP_LIT) */
8860 unsigned char mask; /* bitmask within current byte */
8862 D(emitcode ("; genPackBits",""));
8864 blen = SPEC_BLEN (etype);
8865 bstr = SPEC_BSTR (etype);
8867 /* If the bitfield length is less than a byte */
8870 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8871 (unsigned char) (0xFF >> (8 - bstr)));
8873 if (AOP_TYPE (right) == AOP_LIT)
8875 /* Case with a bitfield length <8 and literal source
8877 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8879 litval &= (~mask) & 0xff;
8880 emitPtrByteGet (rname, p_type, FALSE);
8881 if ((mask|litval)!=0xff)
8882 emitcode ("anl","a,#0x%02x", mask);
8884 emitcode ("orl","a,#0x%02x", litval);
8888 if ((blen==1) && (p_type!=GPOINTER))
8890 /* Case with a bitfield length == 1 and no generic pointer
8892 if (AOP_TYPE (right) == AOP_CRY)
8893 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8896 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8897 emitcode ("rrc","a");
8899 emitPtrByteGet (rname, p_type, FALSE);
8900 emitcode ("mov","acc.%d,c",bstr);
8905 /* Case with a bitfield length < 8 and arbitrary source
8907 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8908 /* shift and mask source value */
8910 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8913 /* transfer A to B and get next byte */
8914 emitPtrByteGet (rname, p_type, TRUE);
8916 emitcode ("anl", "a,#0x%02x", mask);
8917 emitcode ("orl", "a,b");
8918 if (p_type == GPOINTER)
8919 emitcode ("pop", "b");
8925 emitPtrByteSet (rname, p_type, "a");
8929 /* Bit length is greater than 7 bits. In this case, copy */
8930 /* all except the partial byte at the end */
8931 for (rlen=blen;rlen>=8;rlen-=8)
8933 emitPtrByteSet (rname, p_type,
8934 aopGet (AOP (right), offset++, FALSE, TRUE) );
8936 emitcode ("inc", "%s", rname);
8939 /* If there was a partial byte at the end */
8942 mask = (((unsigned char) -1 << rlen) & 0xff);
8944 if (AOP_TYPE (right) == AOP_LIT)
8946 /* Case with partial byte and literal source
8948 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8949 litval >>= (blen-rlen);
8950 litval &= (~mask) & 0xff;
8951 emitPtrByteGet (rname, p_type, FALSE);
8952 if ((mask|litval)!=0xff)
8953 emitcode ("anl","a,#0x%02x", mask);
8955 emitcode ("orl","a,#0x%02x", litval);
8960 /* Case with partial byte and arbitrary source
8962 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8963 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8966 /* transfer A to B and get next byte */
8967 emitPtrByteGet (rname, p_type, TRUE);
8969 emitcode ("anl", "a,#0x%02x", mask);
8970 emitcode ("orl", "a,b");
8971 if (p_type == GPOINTER)
8972 emitcode ("pop", "b");
8976 emitPtrByteSet (rname, p_type, "a");
8982 /*-----------------------------------------------------------------*/
8983 /* genDataPointerSet - remat pointer to data space */
8984 /*-----------------------------------------------------------------*/
8986 genDataPointerSet (operand * right,
8990 int size, offset = 0;
8991 char *l, buffer[256];
8993 D(emitcode ("; genDataPointerSet",""));
8995 aopOp (right, ic, FALSE);
8997 l = aopGet (AOP (result), 0, FALSE, TRUE);
8998 size = AOP_SIZE (right);
9002 sprintf (buffer, "(%s + %d)", l + 1, offset);
9004 sprintf (buffer, "%s", l + 1);
9005 emitcode ("mov", "%s,%s", buffer,
9006 aopGet (AOP (right), offset++, FALSE, FALSE));
9009 freeAsmop (right, NULL, ic, TRUE);
9010 freeAsmop (result, NULL, ic, TRUE);
9013 /*-----------------------------------------------------------------*/
9014 /* genNearPointerSet - emitcode for near pointer put */
9015 /*-----------------------------------------------------------------*/
9017 genNearPointerSet (operand * right,
9025 sym_link *retype, *letype;
9026 sym_link *ptype = operandType (result);
9028 D(emitcode ("; genNearPointerSet",""));
9030 retype = getSpec (operandType (right));
9031 letype = getSpec (ptype);
9032 aopOp (result, ic, FALSE);
9034 /* if the result is rematerializable &
9035 in data space & not a bit variable */
9036 if (AOP_TYPE (result) == AOP_IMMD &&
9037 DCL_TYPE (ptype) == POINTER &&
9038 !IS_BITVAR (retype) &&
9039 !IS_BITVAR (letype))
9041 genDataPointerSet (right, result, ic);
9045 /* if the value is already in a pointer register
9046 then don't need anything more */
9047 if (!AOP_INPREG (AOP (result)))
9050 //AOP_TYPE (result) == AOP_STK
9054 // Aha, it is a pointer, just in disguise.
9055 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9058 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9059 __FILE__, __LINE__);
9064 emitcode ("mov", "a%s,%s", rname + 1, rname);
9065 rname++; // skip the '@'.
9070 /* otherwise get a free pointer register */
9072 preg = getFreePtr (ic, &aop, FALSE);
9073 emitcode ("mov", "%s,%s",
9075 aopGet (AOP (result), 0, FALSE, TRUE));
9081 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9084 aopOp (right, ic, FALSE);
9086 /* if bitfield then unpack the bits */
9087 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9088 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9091 /* we have can just get the values */
9092 int size = AOP_SIZE (right);
9097 l = aopGet (AOP (right), offset, FALSE, TRUE);
9101 emitcode ("mov", "@%s,a", rname);
9104 emitcode ("mov", "@%s,%s", rname, l);
9106 emitcode ("inc", "%s", rname);
9111 /* now some housekeeping stuff */
9112 if (aop) /* we had to allocate for this iCode */
9115 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9116 freeAsmop (NULL, aop, ic, TRUE);
9120 /* we did not allocate which means left
9121 already in a pointer register, then
9122 if size > 0 && this could be used again
9123 we have to point it back to where it
9125 if ((AOP_SIZE (right) > 1 &&
9126 !OP_SYMBOL (result)->remat &&
9127 (OP_SYMBOL (result)->liveTo > ic->seq ||
9131 int size = AOP_SIZE (right) - 1;
9133 emitcode ("dec", "%s", rname);
9138 if (pi) pi->generated = 1;
9139 freeAsmop (result, NULL, ic, TRUE);
9140 freeAsmop (right, NULL, ic, TRUE);
9143 /*-----------------------------------------------------------------*/
9144 /* genPagedPointerSet - emitcode for Paged pointer put */
9145 /*-----------------------------------------------------------------*/
9147 genPagedPointerSet (operand * right,
9155 sym_link *retype, *letype;
9157 D(emitcode ("; genPagedPointerSet",""));
9159 retype = getSpec (operandType (right));
9160 letype = getSpec (operandType (result));
9162 aopOp (result, ic, FALSE);
9164 /* if the value is already in a pointer register
9165 then don't need anything more */
9166 if (!AOP_INPREG (AOP (result)))
9168 /* otherwise get a free pointer register */
9170 preg = getFreePtr (ic, &aop, FALSE);
9171 emitcode ("mov", "%s,%s",
9173 aopGet (AOP (result), 0, FALSE, TRUE));
9177 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9179 aopOp (right, ic, FALSE);
9181 /* if bitfield then unpack the bits */
9182 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9183 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9186 /* we have can just get the values */
9187 int size = AOP_SIZE (right);
9192 l = aopGet (AOP (right), offset, FALSE, TRUE);
9195 emitcode ("movx", "@%s,a", rname);
9198 emitcode ("inc", "%s", rname);
9204 /* now some housekeeping stuff */
9205 if (aop) /* we had to allocate for this iCode */
9208 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9209 freeAsmop (NULL, aop, ic, TRUE);
9213 /* we did not allocate which means left
9214 already in a pointer register, then
9215 if size > 0 && this could be used again
9216 we have to point it back to where it
9218 if (AOP_SIZE (right) > 1 &&
9219 !OP_SYMBOL (result)->remat &&
9220 (OP_SYMBOL (result)->liveTo > ic->seq ||
9223 int size = AOP_SIZE (right) - 1;
9225 emitcode ("dec", "%s", rname);
9230 if (pi) pi->generated = 1;
9231 freeAsmop (result, NULL, ic, TRUE);
9232 freeAsmop (right, NULL, ic, TRUE);
9237 /*-----------------------------------------------------------------*/
9238 /* genFarPointerSet - set value from far space */
9239 /*-----------------------------------------------------------------*/
9241 genFarPointerSet (operand * right,
9242 operand * result, iCode * ic, iCode * pi)
9245 sym_link *retype = getSpec (operandType (right));
9246 sym_link *letype = getSpec (operandType (result));
9248 D(emitcode ("; genFarPointerSet",""));
9250 aopOp (result, ic, FALSE);
9251 loadDptrFromOperand (result, FALSE);
9253 /* so dptr know contains the address */
9254 aopOp (right, ic, FALSE);
9256 /* if bit then unpack */
9257 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9258 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9261 size = AOP_SIZE (right);
9266 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9268 emitcode ("movx", "@dptr,a");
9270 emitcode ("inc", "dptr");
9273 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9274 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9275 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9278 freeAsmop (result, NULL, ic, TRUE);
9279 freeAsmop (right, NULL, ic, TRUE);
9282 /*-----------------------------------------------------------------*/
9283 /* genGenPointerSet - set value from generic pointer space */
9284 /*-----------------------------------------------------------------*/
9286 genGenPointerSet (operand * right,
9287 operand * result, iCode * ic, iCode * pi)
9290 sym_link *retype = getSpec (operandType (right));
9291 sym_link *letype = getSpec (operandType (result));
9293 D(emitcode ("; genGenPointerSet",""));
9295 aopOp (result, ic, FALSE);
9296 loadDptrFromOperand (result, TRUE);
9298 /* so dptr know contains the address */
9299 aopOp (right, ic, FALSE);
9301 /* if bit then unpack */
9302 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9303 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9306 size = AOP_SIZE (right);
9311 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9313 emitcode ("lcall", "__gptrput");
9315 emitcode ("inc", "dptr");
9319 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9320 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9321 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9324 freeAsmop (result, NULL, ic, TRUE);
9325 freeAsmop (right, NULL, ic, TRUE);
9328 /*-----------------------------------------------------------------*/
9329 /* genPointerSet - stores the value into a pointer location */
9330 /*-----------------------------------------------------------------*/
9332 genPointerSet (iCode * ic, iCode *pi)
9334 operand *right, *result;
9335 sym_link *type, *etype;
9338 D(emitcode ("; genPointerSet",""));
9340 right = IC_RIGHT (ic);
9341 result = IC_RESULT (ic);
9343 /* depending on the type of pointer we need to
9344 move it to the correct pointer register */
9345 type = operandType (result);
9346 etype = getSpec (type);
9347 /* if left is of type of pointer then it is simple */
9348 if (IS_PTR (type) && !IS_FUNC (type->next))
9350 p_type = DCL_TYPE (type);
9354 /* we have to go by the storage class */
9355 p_type = PTR_TYPE (SPEC_OCLS (etype));
9358 /* special case when cast remat */
9359 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9360 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9361 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9362 type = operandType (result);
9363 p_type = DCL_TYPE (type);
9365 /* now that we have the pointer type we assign
9366 the pointer values */
9372 genNearPointerSet (right, result, ic, pi);
9376 genPagedPointerSet (right, result, ic, pi);
9380 genFarPointerSet (right, result, ic, pi);
9384 genGenPointerSet (right, result, ic, pi);
9388 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9389 "genPointerSet: illegal pointer type");
9394 /*-----------------------------------------------------------------*/
9395 /* genIfx - generate code for Ifx statement */
9396 /*-----------------------------------------------------------------*/
9398 genIfx (iCode * ic, iCode * popIc)
9400 operand *cond = IC_COND (ic);
9403 D(emitcode ("; genIfx",""));
9405 aopOp (cond, ic, FALSE);
9407 /* get the value into acc */
9408 if (AOP_TYPE (cond) != AOP_CRY)
9412 /* the result is now in the accumulator */
9413 freeAsmop (cond, NULL, ic, TRUE);
9415 /* if there was something to be popped then do it */
9419 /* if the condition is a bit variable */
9420 if (isbit && IS_ITEMP (cond) &&
9422 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9423 else if (isbit && !IS_ITEMP (cond))
9424 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9426 genIfxJump (ic, "a", NULL, NULL, NULL);
9431 /*-----------------------------------------------------------------*/
9432 /* genAddrOf - generates code for address of */
9433 /*-----------------------------------------------------------------*/
9435 genAddrOf (iCode * ic)
9437 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9440 D(emitcode ("; genAddrOf",""));
9442 aopOp (IC_RESULT (ic), ic, FALSE);
9444 /* if the operand is on the stack then we
9445 need to get the stack offset of this
9449 /* if it has an offset then we need to compute
9453 emitcode ("mov", "a,_bp");
9454 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9455 ((char) (sym->stack - _G.nRegsSaved)) :
9456 ((char) sym->stack)) & 0xff);
9457 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9461 /* we can just move _bp */
9462 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9464 /* fill the result with zero */
9465 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9470 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9476 /* object not on stack then we need the name */
9477 size = AOP_SIZE (IC_RESULT (ic));
9482 char s[SDCC_NAME_MAX];
9484 sprintf (s, "#(%s >> %d)",
9488 sprintf (s, "#%s", sym->rname);
9489 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9493 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9497 /*-----------------------------------------------------------------*/
9498 /* genFarFarAssign - assignment when both are in far space */
9499 /*-----------------------------------------------------------------*/
9501 genFarFarAssign (operand * result, operand * right, iCode * ic)
9503 int size = AOP_SIZE (right);
9507 D(emitcode ("; genFarFarAssign",""));
9509 /* first push the right side on to the stack */
9512 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9514 emitcode ("push", "acc");
9517 freeAsmop (right, NULL, ic, FALSE);
9518 /* now assign DPTR to result */
9519 aopOp (result, ic, FALSE);
9520 size = AOP_SIZE (result);
9523 emitcode ("pop", "acc");
9524 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9526 freeAsmop (result, NULL, ic, FALSE);
9530 /*-----------------------------------------------------------------*/
9531 /* genAssign - generate code for assignment */
9532 /*-----------------------------------------------------------------*/
9534 genAssign (iCode * ic)
9536 operand *result, *right;
9538 unsigned long lit = 0L;
9540 D(emitcode("; genAssign",""));
9542 result = IC_RESULT (ic);
9543 right = IC_RIGHT (ic);
9545 /* if they are the same */
9546 if (operandsEqu (result, right) &&
9547 !isOperandVolatile (result, FALSE) &&
9548 !isOperandVolatile (right, FALSE))
9551 aopOp (right, ic, FALSE);
9553 /* special case both in far space */
9554 if (AOP_TYPE (right) == AOP_DPTR &&
9555 IS_TRUE_SYMOP (result) &&
9556 isOperandInFarSpace (result))
9559 genFarFarAssign (result, right, ic);
9563 aopOp (result, ic, TRUE);
9565 /* if they are the same registers */
9566 if (sameRegs (AOP (right), AOP (result)) &&
9567 !isOperandVolatile (result, FALSE) &&
9568 !isOperandVolatile (right, FALSE))
9571 /* if the result is a bit */
9572 if (AOP_TYPE (result) == AOP_CRY)
9575 /* if the right size is a literal then
9576 we know what the value is */
9577 if (AOP_TYPE (right) == AOP_LIT)
9579 if (((int) operandLitValue (right)))
9580 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9582 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9586 /* the right is also a bit variable */
9587 if (AOP_TYPE (right) == AOP_CRY)
9589 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9590 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9596 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9600 /* bit variables done */
9602 size = AOP_SIZE (result);
9604 if (AOP_TYPE (right) == AOP_LIT)
9605 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9607 (AOP_TYPE (result) != AOP_REG) &&
9608 (AOP_TYPE (right) == AOP_LIT) &&
9609 !IS_FLOAT (operandType (right)) &&
9612 emitcode ("clr", "a");
9615 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9616 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9618 aopPut (AOP (result),
9619 aopGet (AOP (right), size, FALSE, FALSE),
9621 isOperandVolatile (result, FALSE));
9628 aopPut (AOP (result),
9629 aopGet (AOP (right), offset, FALSE, FALSE),
9631 isOperandVolatile (result, FALSE));
9637 freeAsmop (right, NULL, ic, TRUE);
9638 freeAsmop (result, NULL, ic, TRUE);
9641 /*-----------------------------------------------------------------*/
9642 /* genJumpTab - genrates code for jump table */
9643 /*-----------------------------------------------------------------*/
9645 genJumpTab (iCode * ic)
9647 symbol *jtab,*jtablo,*jtabhi;
9651 D(emitcode ("; genJumpTab",""));
9653 count = elementsInSet( IC_JTLABELS (ic) );
9657 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9658 if the switch argument is in a register.
9659 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9660 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9661 How will multiply by three be updated ???*/
9662 aopOp (IC_JTCOND (ic), ic, FALSE);
9663 /* get the condition into accumulator */
9664 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9666 /* multiply by three */
9667 emitcode ("add", "a,acc");
9668 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9669 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9671 jtab = newiTempLabel (NULL);
9672 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9673 emitcode ("jmp", "@a+dptr");
9674 emitcode ("", "%05d$:", jtab->key + 100);
9675 /* now generate the jump labels */
9676 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9677 jtab = setNextItem (IC_JTLABELS (ic)))
9678 emitcode ("ljmp", "%05d$", jtab->key + 100);
9682 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9683 if the switch argument is in a register.
9684 For n>6 this algorithm may be more compact */
9685 jtablo = newiTempLabel (NULL);
9686 jtabhi = newiTempLabel (NULL);
9688 /* get the condition into accumulator.
9689 Using b as temporary storage, if register push/pop is needed */
9690 aopOp (IC_JTCOND (ic), ic, FALSE);
9691 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9692 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9693 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9695 // (MB) what if B is in use???
9696 wassertl(!_G.BInUse, "B was in use");
9697 emitcode ("mov", "b,%s", l);
9700 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9704 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9705 emitcode ("movc", "a,@a+pc");
9706 emitcode ("push", "acc");
9709 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9710 emitcode ("movc", "a,@a+pc");
9711 emitcode ("push", "acc");
9715 /* this scales up to n<=255, but needs two more bytes
9717 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9718 emitcode ("movc", "a,@a+dptr");
9719 emitcode ("push", "acc");
9722 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9723 emitcode ("movc", "a,@a+dptr");
9724 emitcode ("push", "acc");
9727 emitcode ("ret", "");
9729 /* now generate jump table, LSB */
9730 emitcode ("", "%05d$:", jtablo->key + 100);
9731 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9732 jtab = setNextItem (IC_JTLABELS (ic)))
9733 emitcode (".db", "%05d$", jtab->key + 100);
9735 /* now generate jump table, MSB */
9736 emitcode ("", "%05d$:", jtabhi->key + 100);
9737 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9738 jtab = setNextItem (IC_JTLABELS (ic)))
9739 emitcode (".db", "%05d$>>8", jtab->key + 100);
9743 /*-----------------------------------------------------------------*/
9744 /* genCast - gen code for casting */
9745 /*-----------------------------------------------------------------*/
9747 genCast (iCode * ic)
9749 operand *result = IC_RESULT (ic);
9750 sym_link *ctype = operandType (IC_LEFT (ic));
9751 sym_link *rtype = operandType (IC_RIGHT (ic));
9752 operand *right = IC_RIGHT (ic);
9755 D(emitcode("; genCast",""));
9757 /* if they are equivalent then do nothing */
9758 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9761 aopOp (right, ic, FALSE);
9762 aopOp (result, ic, FALSE);
9764 /* if the result is a bit (and not a bitfield) */
9765 // if (AOP_TYPE (result) == AOP_CRY)
9766 if (IS_BITVAR (OP_SYMBOL (result)->type)
9767 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9769 /* if the right size is a literal then
9770 we know what the value is */
9771 if (AOP_TYPE (right) == AOP_LIT)
9773 if (((int) operandLitValue (right)))
9774 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9776 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9781 /* the right is also a bit variable */
9782 if (AOP_TYPE (right) == AOP_CRY)
9784 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9785 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9791 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9796 /* if they are the same size : or less */
9797 if (AOP_SIZE (result) <= AOP_SIZE (right))
9800 /* if they are in the same place */
9801 if (sameRegs (AOP (right), AOP (result)))
9804 /* if they in different places then copy */
9805 size = AOP_SIZE (result);
9809 aopPut (AOP (result),
9810 aopGet (AOP (right), offset, FALSE, FALSE),
9812 isOperandVolatile (result, FALSE));
9819 /* if the result is of type pointer */
9824 sym_link *type = operandType (right);
9825 sym_link *etype = getSpec (type);
9827 /* pointer to generic pointer */
9828 if (IS_GENPTR (ctype))
9831 p_type = DCL_TYPE (type);
9834 if (SPEC_SCLS(etype)==S_REGISTER) {
9835 // let's assume it is a generic pointer
9838 /* we have to go by the storage class */
9839 p_type = PTR_TYPE (SPEC_OCLS (etype));
9843 /* the first two bytes are known */
9844 size = GPTRSIZE - 1;
9848 aopPut (AOP (result),
9849 aopGet (AOP (right), offset, FALSE, FALSE),
9851 isOperandVolatile (result, FALSE));
9854 /* the last byte depending on type */
9856 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9861 // pointerTypeToGPByte will have bitched.
9865 sprintf(gpValStr, "#0x%d", gpVal);
9866 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9871 /* just copy the pointers */
9872 size = AOP_SIZE (result);
9876 aopPut (AOP (result),
9877 aopGet (AOP (right), offset, FALSE, FALSE),
9879 isOperandVolatile (result, FALSE));
9885 /* so we now know that the size of destination is greater
9886 than the size of the source */
9887 /* we move to result for the size of source */
9888 size = AOP_SIZE (right);
9892 aopPut (AOP (result),
9893 aopGet (AOP (right), offset, FALSE, FALSE),
9895 isOperandVolatile (result, FALSE));
9899 /* now depending on the sign of the source && destination */
9900 size = AOP_SIZE (result) - AOP_SIZE (right);
9901 /* if unsigned or not an integral type */
9902 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9905 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9909 /* we need to extend the sign :{ */
9910 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9913 emitcode ("rlc", "a");
9914 emitcode ("subb", "a,acc");
9916 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9919 /* we are done hurray !!!! */
9922 freeAsmop (right, NULL, ic, TRUE);
9923 freeAsmop (result, NULL, ic, TRUE);
9927 /*-----------------------------------------------------------------*/
9928 /* genDjnz - generate decrement & jump if not zero instrucion */
9929 /*-----------------------------------------------------------------*/
9931 genDjnz (iCode * ic, iCode * ifx)
9937 D(emitcode ("; genDjnz",""));
9939 /* if the if condition has a false label
9940 then we cannot save */
9944 /* if the minus is not of the form
9946 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9947 !IS_OP_LITERAL (IC_RIGHT (ic)))
9950 if (operandLitValue (IC_RIGHT (ic)) != 1)
9953 /* if the size of this greater than one then no
9955 if (getSize (operandType (IC_RESULT (ic))) > 1)
9958 /* otherwise we can save BIG */
9959 lbl = newiTempLabel (NULL);
9960 lbl1 = newiTempLabel (NULL);
9962 aopOp (IC_RESULT (ic), ic, FALSE);
9964 if (AOP_NEEDSACC(IC_RESULT(ic)))
9966 /* If the result is accessed indirectly via
9967 * the accumulator, we must explicitly write
9968 * it back after the decrement.
9970 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9972 if (strcmp(rByte, "a"))
9974 /* Something is hopelessly wrong */
9975 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9976 __FILE__, __LINE__);
9977 /* We can just give up; the generated code will be inefficient,
9980 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9983 emitcode ("dec", "%s", rByte);
9984 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9985 emitcode ("jnz", "%05d$", lbl->key + 100);
9987 else if (IS_AOP_PREG (IC_RESULT (ic)))
9989 emitcode ("dec", "%s",
9990 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9991 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9992 emitcode ("jnz", "%05d$", lbl->key + 100);
9996 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9999 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10000 emitcode ("", "%05d$:", lbl->key + 100);
10001 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10002 emitcode ("", "%05d$:", lbl1->key + 100);
10004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10005 ifx->generated = 1;
10009 /*-----------------------------------------------------------------*/
10010 /* genReceive - generate code for a receive iCode */
10011 /*-----------------------------------------------------------------*/
10013 genReceive (iCode * ic)
10015 int size = getSize (operandType (IC_RESULT (ic)));
10017 D(emitcode ("; genReceive",""));
10019 if (ic->argreg == 1) { /* first parameter */
10020 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10021 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10022 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10025 int receivingA = 0;
10028 for (offset = 0; offset<size; offset++)
10029 if (!strcmp (fReturn[offset], "a"))
10034 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10036 for (offset = size-1; offset>0; offset--)
10037 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10038 emitcode("mov","a,%s", fReturn[0]);
10040 aopOp (IC_RESULT (ic), ic, FALSE);
10042 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10043 isOperandVolatile (IC_RESULT (ic), FALSE));
10044 for (offset = 1; offset<size; offset++)
10045 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10046 isOperandVolatile (IC_RESULT (ic), FALSE));
10052 if (getTempRegs(tempRegs, size, ic))
10054 for (offset = 0; offset<size; offset++)
10055 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10056 aopOp (IC_RESULT (ic), ic, FALSE);
10057 for (offset = 0; offset<size; offset++)
10058 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10059 isOperandVolatile (IC_RESULT (ic), FALSE));
10064 offset = fReturnSizeMCS51 - size;
10066 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10067 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10070 aopOp (IC_RESULT (ic), ic, FALSE);
10071 size = AOP_SIZE (IC_RESULT (ic));
10074 emitcode ("pop", "acc");
10075 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10080 aopOp (IC_RESULT (ic), ic, FALSE);
10082 assignResultValue (IC_RESULT (ic));
10084 } else { /* second receive onwards */
10086 aopOp (IC_RESULT (ic), ic, FALSE);
10087 rb1off = ic->argreg;
10089 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10097 /*-----------------------------------------------------------------*/
10098 /* genDummyRead - generate code for dummy read of volatiles */
10099 /*-----------------------------------------------------------------*/
10101 genDummyRead (iCode * ic)
10106 D(emitcode("; genDummyRead",""));
10108 op = IC_RIGHT (ic);
10109 if (op && IS_SYMOP (op))
10111 aopOp (op, ic, FALSE);
10113 /* if the result is a bit */
10114 if (AOP_TYPE (op) == AOP_CRY)
10115 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10118 /* bit variables done */
10120 size = AOP_SIZE (op);
10124 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10129 freeAsmop (op, NULL, ic, TRUE);
10133 if (op && IS_SYMOP (op))
10135 aopOp (op, ic, FALSE);
10137 /* if the result is a bit */
10138 if (AOP_TYPE (op) == AOP_CRY)
10139 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10142 /* bit variables done */
10144 size = AOP_SIZE (op);
10148 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10153 freeAsmop (op, NULL, ic, TRUE);
10157 /*-----------------------------------------------------------------*/
10158 /* genCritical - generate code for start of a critical sequence */
10159 /*-----------------------------------------------------------------*/
10161 genCritical (iCode *ic)
10163 symbol *tlbl = newiTempLabel (NULL);
10165 D(emitcode("; genCritical",""));
10167 if (IC_RESULT (ic))
10169 aopOp (IC_RESULT (ic), ic, TRUE);
10170 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10171 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10172 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10173 emitcode ("", "%05d$:", (tlbl->key + 100));
10174 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10178 emitcode ("setb", "c");
10179 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10180 emitcode ("clr", "c");
10181 emitcode ("", "%05d$:", (tlbl->key + 100));
10182 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10186 /*-----------------------------------------------------------------*/
10187 /* genEndCritical - generate code for end of a critical sequence */
10188 /*-----------------------------------------------------------------*/
10190 genEndCritical (iCode *ic)
10192 D(emitcode("; genEndCritical",""));
10196 aopOp (IC_RIGHT (ic), ic, FALSE);
10197 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10199 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10200 emitcode ("mov", "ea,c");
10204 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10205 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10206 emitcode ("rrc", "a");
10207 emitcode ("mov", "ea,c");
10209 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10213 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10214 emitcode ("mov", "ea,c");
10218 /*-----------------------------------------------------------------*/
10219 /* gen51Code - generate code for 8051 based controllers */
10220 /*-----------------------------------------------------------------*/
10222 gen51Code (iCode * lic)
10226 /* int cseq = 0; */
10228 _G.currentFunc = NULL;
10229 lineHead = lineCurr = NULL;
10231 /* print the allocation information */
10232 if (allocInfo && currFunc)
10233 printAllocInfo (currFunc, codeOutFile);
10234 /* if debug information required */
10235 if (options.debug && currFunc)
10237 debugFile->writeFunction (currFunc, lic);
10239 /* stack pointer name */
10240 if (options.useXstack)
10246 for (ic = lic; ic; ic = ic->next)
10248 _G.current_iCode = ic;
10250 if (ic->lineno && cln != ic->lineno)
10254 debugFile->writeCLine (ic);
10256 if (!options.noCcodeInAsm) {
10257 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10258 printCLine(ic->filename, ic->lineno));
10263 if (ic->seqPoint && ic->seqPoint != cseq)
10265 emitcode ("", "; sequence point %d", ic->seqPoint);
10266 cseq = ic->seqPoint;
10269 if (options.iCodeInAsm) {
10270 char regsInUse[80];
10273 for (i=0; i<8; i++) {
10274 sprintf (®sInUse[i],
10275 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10278 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10280 /* if the result is marked as
10281 spilt and rematerializable or code for
10282 this has already been generated then
10284 if (resultRemat (ic) || ic->generated)
10287 /* depending on the operation */
10307 /* IPOP happens only when trying to restore a
10308 spilt live range, if there is an ifx statement
10309 following this pop then the if statement might
10310 be using some of the registers being popped which
10311 would destory the contents of the register so
10312 we need to check for this condition and handle it */
10314 ic->next->op == IFX &&
10315 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10316 genIfx (ic->next, ic);
10334 genEndFunction (ic);
10354 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10371 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10375 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10382 /* note these two are xlated by algebraic equivalence
10383 during parsing SDCC.y */
10384 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10385 "got '>=' or '<=' shouldn't have come here");
10389 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10401 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10405 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10409 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10433 genRightShift (ic);
10436 case GET_VALUE_AT_ADDRESS:
10438 hasInc (IC_LEFT (ic), ic,
10439 getSize (operandType (IC_RESULT (ic)))),
10440 ifxForOp (IC_RESULT (ic), ic) );
10444 if (POINTER_SET (ic))
10445 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10471 addSet (&_G.sendSet, ic);
10474 case DUMMY_READ_VOLATILE:
10483 genEndCritical (ic);
10495 _G.current_iCode = NULL;
10497 /* now we are ready to call the
10498 peep hole optimizer */
10499 if (!options.nopeep)
10500 peepHole (&lineHead);
10502 /* now do the actual printing */
10503 printLine (lineHead, codeOutFile);