1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
75 short r0InB : 2;//2 so we can see it overflow
76 short r1InB : 2;//2 so we can see it overflow
77 short OpInB : 2;//2 so we can see it overflow
91 static char *rb1regs[] = {
92 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
95 extern int mcs51_ptrRegReq;
96 extern int mcs51_nRegs;
97 extern FILE *codeOutFile;
98 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, const char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
140 SNPRINTF (lb, sizeof(lb), "%s", inst);
141 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
144 tvsprintf (lb, sizeof(lb), fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
155 lineCurr->ic = _G.current_iCode;
156 lineCurr->isComment = (*lbp==';');
160 /*-----------------------------------------------------------------*/
161 /* mcs51_emitDebuggerSymbol - associate the current code location */
162 /* with a debugger symbol */
163 /*-----------------------------------------------------------------*/
165 mcs51_emitDebuggerSymbol (char * debugSym)
168 emitcode ("", "%s ==.", debugSym);
172 /*-----------------------------------------------------------------*/
173 /* mova - moves specified value into accumulator */
174 /*-----------------------------------------------------------------*/
178 /* do some early peephole optimization */
179 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
182 emitcode("mov","a,%s", x);
185 /*-----------------------------------------------------------------*/
186 /* pushB - saves register B if necessary */
187 /*-----------------------------------------------------------------*/
191 bool pushedB = FALSE;
195 emitcode ("push", "b");
196 // printf("B was in use !\n");
206 /*-----------------------------------------------------------------*/
207 /* popB - restores value of register B if necessary */
208 /*-----------------------------------------------------------------*/
214 emitcode ("pop", "b");
222 /*-----------------------------------------------------------------*/
223 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
224 /*-----------------------------------------------------------------*/
226 getFreePtr (iCode * ic, asmop ** aopp, bool result)
231 /* the logic: if r0 & r1 used in the instruction
232 then we are in trouble otherwise */
234 /* first check if r0 & r1 are used by this
235 instruction, in which case we are in trouble */
236 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
237 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
242 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
243 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
245 /* if no usage of r0 then return it */
248 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
249 (*aopp)->type = AOP_R0;
251 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
254 /* if no usage of r1 then return it */
257 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
258 (*aopp)->type = AOP_R1;
260 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
263 /* now we know they both have usage */
264 /* if r0 not used in this instruction */
267 /* push it if not already pushed */
270 emitcode ("mov", "b,%s",
271 mcs51_regWithIdx (R0_IDX)->dname);
274 else if (!_G.r0Pushed)
276 emitcode ("push", "%s",
277 mcs51_regWithIdx (R0_IDX)->dname);
281 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
282 (*aopp)->type = AOP_R0;
284 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
287 /* if r1 not used then */
291 /* push it if not already pushed */
294 emitcode ("mov", "b,%s",
295 mcs51_regWithIdx (R1_IDX)->dname);
298 else if (!_G.r1Pushed)
300 emitcode ("push", "%s",
301 mcs51_regWithIdx (R1_IDX)->dname);
305 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
306 (*aopp)->type = AOP_R1;
307 return mcs51_regWithIdx (R1_IDX);
310 /* I said end of world, but not quite end of world yet */
312 /* we can push it on the stack */
313 (*aopp)->type = AOP_STK;
316 /* in the case that result AND left AND right needs a pointer reg
317 we can safely use the result's */
318 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
319 (*aopp)->type = AOP_R0;
320 return mcs51_regWithIdx (R0_IDX);
322 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
323 (*aopp)->type = AOP_R1;
324 return mcs51_regWithIdx (R1_IDX);
328 /* now this is REALLY the end of the world */
329 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
330 "getFreePtr should never reach here");
335 /*-----------------------------------------------------------------*/
336 /* getTempRegs - initialize an array of pointers to GPR registers */
337 /* that are not in use. Returns 1 if the requested */
338 /* number of registers were available, 0 otherwise. */
339 /*-----------------------------------------------------------------*/
341 getTempRegs(regs **tempRegs, int size, iCode *ic)
348 ic = _G.current_iCode;
354 freeRegs = newBitVect(8);
355 bitVectSetBit (freeRegs, R2_IDX);
356 bitVectSetBit (freeRegs, R3_IDX);
357 bitVectSetBit (freeRegs, R4_IDX);
358 bitVectSetBit (freeRegs, R5_IDX);
359 bitVectSetBit (freeRegs, R6_IDX);
360 bitVectSetBit (freeRegs, R7_IDX);
362 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
364 bitVect * newfreeRegs;
365 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
366 freeBitVect(freeRegs);
367 freeRegs = newfreeRegs;
369 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
372 for (i=0; i<freeRegs->size; i++)
374 if (bitVectBitValue(freeRegs,i))
375 tempRegs[offset++] = mcs51_regWithIdx(i);
378 freeBitVect(freeRegs);
383 freeBitVect(freeRegs);
388 /*-----------------------------------------------------------------*/
389 /* newAsmop - creates a new asmOp */
390 /*-----------------------------------------------------------------*/
392 newAsmop (short type)
396 aop = Safe_calloc (1, sizeof (asmop));
401 /*-----------------------------------------------------------------*/
402 /* pointerCode - returns the code for a pointer type */
403 /*-----------------------------------------------------------------*/
405 pointerCode (sym_link * etype)
408 return PTR_TYPE (SPEC_OCLS (etype));
412 /*-----------------------------------------------------------------*/
413 /* leftRightUseAcc - returns size of accumulator use by operands */
414 /*-----------------------------------------------------------------*/
416 leftRightUseAcc(iCode *ic)
425 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
426 "null iCode pointer");
433 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
436 size = getSize (OP_SYMBOL (op)->type);
441 else if (ic->op == JUMPTABLE)
444 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
447 size = getSize (OP_SYMBOL (op)->type);
455 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
458 size = getSize (OP_SYMBOL (op)->type);
463 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
466 size = getSize (OP_SYMBOL (op)->type);
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol */
480 /*-----------------------------------------------------------------*/
482 aopForSym (iCode * ic, symbol * sym, bool result)
487 wassertl (ic != NULL, "Got a null iCode");
488 wassertl (sym != NULL, "Got a null symbol");
490 space = SPEC_OCLS (sym->etype);
492 /* if already has one */
496 /* assign depending on the storage class */
497 /* if it is on the stack or indirectly addressable */
498 /* space we need to assign either r0 or r1 to it */
499 if (sym->onStack || sym->iaccess)
501 sym->aop = aop = newAsmop (0);
502 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
503 aop->size = getSize (sym->type);
505 /* now assign the address of the variable to
506 the pointer register */
507 if (aop->type != AOP_STK)
512 if (_G.accInUse || leftRightUseAcc (ic))
513 emitcode ("push", "acc");
515 emitcode ("mov", "a,_bp");
516 emitcode ("add", "a,#0x%02x",
518 ((char) (sym->stack - _G.nRegsSaved)) :
519 ((char) sym->stack)) & 0xff);
520 emitcode ("mov", "%s,a",
521 aop->aopu.aop_ptr->name);
523 if (_G.accInUse || leftRightUseAcc (ic))
524 emitcode ("pop", "acc");
527 emitcode ("mov", "%s,#%s",
528 aop->aopu.aop_ptr->name,
530 aop->paged = space->paged;
533 aop->aopu.aop_stk = sym->stack;
537 /* if in bit space */
538 if (IN_BITSPACE (space))
540 sym->aop = aop = newAsmop (AOP_CRY);
541 aop->aopu.aop_dir = sym->rname;
542 aop->size = getSize (sym->type);
545 /* if it is in direct space */
546 if (IN_DIRSPACE (space))
548 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
549 //printTypeChainRaw(sym->type, NULL);
550 //printf("space = %s\n", space ? space->sname : "NULL");
551 sym->aop = aop = newAsmop (AOP_DIR);
552 aop->aopu.aop_dir = sym->rname;
553 aop->size = getSize (sym->type);
557 /* special case for a function */
558 if (IS_FUNC (sym->type))
560 sym->aop = aop = newAsmop (AOP_IMMD);
561 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
562 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
563 aop->size = FPTRSIZE;
567 /* only remaining is far space */
568 /* in which case DPTR gets the address */
569 sym->aop = aop = newAsmop (AOP_DPTR);
570 emitcode ("mov", "dptr,#%s", sym->rname);
571 aop->size = getSize (sym->type);
573 /* if it is in code space */
574 if (IN_CODESPACE (space))
580 /*-----------------------------------------------------------------*/
581 /* aopForRemat - rematerialzes an object */
582 /*-----------------------------------------------------------------*/
584 aopForRemat (symbol * sym)
586 iCode *ic = sym->rematiCode;
587 asmop *aop = newAsmop (AOP_IMMD);
594 val += (int) operandLitValue (IC_RIGHT (ic));
595 else if (ic->op == '-')
596 val -= (int) operandLitValue (IC_RIGHT (ic));
597 else if (IS_CAST_ICODE(ic)) {
598 sym_link *from_type = operandType(IC_RIGHT(ic));
599 aop->aopu.aop_immd.from_cast_remat = 1;
600 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
601 ptr_type = DCL_TYPE(from_type);
602 if (ptr_type == IPOINTER) {
609 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
613 sprintf (buffer, "(%s %c 0x%04x)",
614 OP_SYMBOL (IC_LEFT (ic))->rname,
615 val >= 0 ? '+' : '-',
618 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
620 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
621 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
622 /* set immd2 field if required */
623 if (aop->aopu.aop_immd.from_cast_remat) {
624 sprintf(buffer,"#0x%02x",ptr_type);
625 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
626 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
632 /*-----------------------------------------------------------------*/
633 /* regsInCommon - two operands have some registers in common */
634 /*-----------------------------------------------------------------*/
636 regsInCommon (operand * op1, operand * op2)
641 /* if they have registers in common */
642 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
645 sym1 = OP_SYMBOL (op1);
646 sym2 = OP_SYMBOL (op2);
648 if (sym1->nRegs == 0 || sym2->nRegs == 0)
651 for (i = 0; i < sym1->nRegs; i++)
657 for (j = 0; j < sym2->nRegs; j++)
662 if (sym2->regs[j] == sym1->regs[i])
670 /*-----------------------------------------------------------------*/
671 /* operandsEqu - equivalent */
672 /*-----------------------------------------------------------------*/
674 operandsEqu (operand * op1, operand * op2)
678 /* if they're not symbols */
679 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
682 sym1 = OP_SYMBOL (op1);
683 sym2 = OP_SYMBOL (op2);
685 /* if both are itemps & one is spilt
686 and the other is not then false */
687 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
688 sym1->isspilt != sym2->isspilt)
691 /* if they are the same */
695 /* if they have the same rname */
696 if (sym1->rname[0] && sym2->rname[0]
697 && strcmp (sym1->rname, sym2->rname) == 0)
700 /* if left is a tmp & right is not */
701 if (IS_ITEMP (op1) &&
704 (sym1->usl.spillLoc == sym2))
707 if (IS_ITEMP (op2) &&
711 (sym2->usl.spillLoc == sym1))
717 /*-----------------------------------------------------------------*/
718 /* sameRegs - two asmops have the same registers */
719 /*-----------------------------------------------------------------*/
721 sameRegs (asmop * aop1, asmop * aop2)
728 if (aop1->type != AOP_REG ||
729 aop2->type != AOP_REG)
732 if (aop1->size != aop2->size)
735 for (i = 0; i < aop1->size; i++)
736 if (aop1->aopu.aop_reg[i] !=
737 aop2->aopu.aop_reg[i])
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand : */
745 /*-----------------------------------------------------------------*/
747 aopOp (operand * op, iCode * ic, bool result)
756 /* if this a literal */
757 if (IS_OP_LITERAL (op))
759 op->aop = aop = newAsmop (AOP_LIT);
760 aop->aopu.aop_lit = op->operand.valOperand;
761 aop->size = getSize (operandType (op));
765 /* if already has a asmop then continue */
769 /* if the underlying symbol has a aop */
770 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
772 op->aop = OP_SYMBOL (op)->aop;
776 /* if this is a true symbol */
777 if (IS_TRUE_SYMOP (op))
779 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
783 /* this is a temporary : this has
789 e) can be a return use only */
791 sym = OP_SYMBOL (op);
793 /* if the type is a conditional */
794 if (sym->regType == REG_CND)
796 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
801 /* if it is spilt then two situations
803 b) has a spill location */
804 if (sym->isspilt || sym->nRegs == 0)
807 /* rematerialize it NOW */
810 sym->aop = op->aop = aop =
812 aop->size = getSize (sym->type);
819 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
820 aop->size = getSize (sym->type);
821 for (i = 0; i < 2; i++)
822 aop->aopu.aop_str[i] = accUse[i];
830 aop = op->aop = sym->aop = newAsmop (AOP_STR);
831 aop->size = getSize (sym->type);
832 for (i = 0; i < fReturnSizeMCS51; i++)
833 aop->aopu.aop_str[i] = fReturn[i];
837 if (sym->usl.spillLoc)
839 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
841 /* force a new aop if sizes differ */
842 sym->usl.spillLoc->aop = NULL;
844 sym->aop = op->aop = aop =
845 aopForSym (ic, sym->usl.spillLoc, result);
846 aop->size = getSize (sym->type);
850 /* else must be a dummy iTemp */
851 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
852 aop->size = getSize (sym->type);
856 /* must be in a register */
857 sym->aop = op->aop = aop = newAsmop (AOP_REG);
858 aop->size = sym->nRegs;
859 for (i = 0; i < sym->nRegs; i++)
860 aop->aopu.aop_reg[i] = sym->regs[i];
863 /*-----------------------------------------------------------------*/
864 /* freeAsmop - free up the asmop given to an operand */
865 /*----------------------------------------------------------------*/
867 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
884 /* depending on the asmop type only three cases need work AOP_RO
885 , AOP_R1 && AOP_STK */
891 emitcode ("mov", "r0,b");
894 else if (_G.r0Pushed)
898 emitcode ("pop", "ar0");
902 bitVectUnSetBit (ic->rUsed, R0_IDX);
908 emitcode ("mov", "r1,b");
915 emitcode ("pop", "ar1");
919 bitVectUnSetBit (ic->rUsed, R1_IDX);
925 int stk = aop->aopu.aop_stk + aop->size - 1;
926 bitVectUnSetBit (ic->rUsed, R0_IDX);
927 bitVectUnSetBit (ic->rUsed, R1_IDX);
929 getFreePtr (ic, &aop, FALSE);
933 emitcode ("mov", "a,_bp");
934 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
935 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
939 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
944 emitcode ("pop", "acc");
945 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
948 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
951 freeAsmop (op, NULL, ic, TRUE);
954 emitcode ("pop", "ar1");
960 emitcode ("pop", "ar0");
967 /* all other cases just dealloc */
973 OP_SYMBOL (op)->aop = NULL;
974 /* if the symbol has a spill */
976 SPIL_LOC (op)->aop = NULL;
981 /*------------------------------------------------------------------*/
982 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
983 /* pop r0 or r1 off stack if pushed */
984 /*------------------------------------------------------------------*/
986 freeForBranchAsmop (operand * op)
1006 emitcode ("mov", "r0,b");
1008 else if (_G.r0Pushed)
1010 emitcode ("pop", "ar0");
1017 emitcode ("mov", "r1,b");
1019 else if (_G.r1Pushed)
1021 emitcode ("pop", "ar1");
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1030 emitcode ("mov", "b,r0");
1033 emitcode ("mov", "a,_bp");
1034 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1035 emitcode ("mov", "r0,a");
1039 emitcode ("mov", "r0,_bp");
1044 emitcode ("pop", "acc");
1045 emitcode ("mov", "@r0,a");
1048 emitcode ("dec", "r0");
1050 emitcode ("mov", "r0,b");
1056 /*-----------------------------------------------------------------*/
1057 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1058 /* clobber the accumulator */
1059 /*-----------------------------------------------------------------*/
1061 aopGetUsesAcc (asmop *aop, int offset)
1063 if (offset > (aop->size - 1))
1081 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1090 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1096 /* Error case --- will have been caught already */
1102 /*-----------------------------------------------------------------*/
1103 /* aopGet - for fetching value of the aop */
1104 /*-----------------------------------------------------------------*/
1106 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1111 /* offset is greater than
1113 if (offset > (aop->size - 1) &&
1114 aop->type != AOP_LIT)
1117 /* depending on type */
1125 /* if we need to increment it */
1126 while (offset > aop->coff)
1128 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1132 while (offset < aop->coff)
1134 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1141 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1142 return (dname ? "acc" : "a");
1144 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1145 rs = Safe_calloc (1, strlen (s) + 1);
1150 if (aop->code && aop->coff==0 && offset>=1) {
1151 emitcode ("mov", "a,#0x%02x", offset);
1152 emitcode ("movc", "a,@a+dptr");
1153 return (dname ? "acc" : "a");
1156 while (offset > aop->coff)
1158 emitcode ("inc", "dptr");
1162 while (offset < aop->coff)
1164 emitcode ("lcall", "__decdptr");
1171 emitcode ("clr", "a");
1172 emitcode ("movc", "a,@a+dptr");
1176 emitcode ("movx", "a,@dptr");
1178 return (dname ? "acc" : "a");
1182 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1183 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1185 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1187 sprintf (s, "#(%s >> %d)",
1188 aop->aopu.aop_immd.aop_immd1,
1192 aop->aopu.aop_immd.aop_immd1);
1193 rs = Safe_calloc (1, strlen (s) + 1);
1199 sprintf (s, "(%s + %d)",
1203 sprintf (s, "%s", aop->aopu.aop_dir);
1204 rs = Safe_calloc (1, strlen (s) + 1);
1210 return aop->aopu.aop_reg[offset]->dname;
1212 return aop->aopu.aop_reg[offset]->name;
1215 emitcode ("clr", "a");
1216 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1217 emitcode ("rlc", "a");
1218 return (dname ? "acc" : "a");
1221 if (!offset && dname)
1223 return aop->aopu.aop_str[offset];
1226 return aopLiteral (aop->aopu.aop_lit, offset);
1230 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1234 return aop->aopu.aop_str[offset];
1238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1239 "aopget got unsupported aop->type");
1242 /*-----------------------------------------------------------------*/
1243 /* aopPut - puts a string for a aop */
1244 /*-----------------------------------------------------------------*/
1246 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1250 if (aop->size && offset > (aop->size - 1))
1252 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1253 "aopPut got offset > aop->size");
1257 /* will assign value to value */
1258 /* depending on where it is ofcourse */
1262 MOVA (s); /* read s in case it was volatile */
1267 sprintf (d, "(%s + %d)",
1268 aop->aopu.aop_dir, offset);
1270 sprintf (d, "%s", aop->aopu.aop_dir);
1272 if (strcmp (d, s) ||
1274 emitcode ("mov", "%s,%s", d, s);
1279 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1280 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1283 strcmp (s, "r0") == 0 ||
1284 strcmp (s, "r1") == 0 ||
1285 strcmp (s, "r2") == 0 ||
1286 strcmp (s, "r3") == 0 ||
1287 strcmp (s, "r4") == 0 ||
1288 strcmp (s, "r5") == 0 ||
1289 strcmp (s, "r6") == 0 ||
1290 strcmp (s, "r7") == 0)
1291 emitcode ("mov", "%s,%s",
1292 aop->aopu.aop_reg[offset]->dname, s);
1294 emitcode ("mov", "%s,%s",
1295 aop->aopu.aop_reg[offset]->name, s);
1302 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1303 "aopPut writing to code space");
1307 while (offset > aop->coff)
1310 emitcode ("inc", "dptr");
1313 while (offset < aop->coff)
1316 emitcode ("lcall", "__decdptr");
1321 /* if not in accumulater */
1324 emitcode ("movx", "@dptr,a");
1329 while (offset > aop->coff)
1332 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1334 while (offset < aop->coff)
1337 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1344 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1350 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1352 else if (strcmp (s, "r0") == 0 ||
1353 strcmp (s, "r1") == 0 ||
1354 strcmp (s, "r2") == 0 ||
1355 strcmp (s, "r3") == 0 ||
1356 strcmp (s, "r4") == 0 ||
1357 strcmp (s, "r5") == 0 ||
1358 strcmp (s, "r6") == 0 ||
1359 strcmp (s, "r7") == 0)
1362 sprintf (buffer, "a%s", s);
1363 emitcode ("mov", "@%s,%s",
1364 aop->aopu.aop_ptr->name, buffer);
1367 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1372 if (strcmp (s, "a") == 0)
1373 emitcode ("push", "acc");
1377 emitcode ("push", "acc");
1379 emitcode ("push", s);
1385 /* if bit variable */
1386 if (!aop->aopu.aop_dir)
1388 emitcode ("clr", "a");
1389 emitcode ("rlc", "a");
1394 emitcode ("clr", "%s", aop->aopu.aop_dir);
1396 emitcode ("setb", "%s", aop->aopu.aop_dir);
1397 else if (!strcmp (s, "c"))
1398 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1401 if (strcmp (s, "a"))
1406 /* set C, if a >= 1 */
1407 emitcode ("add", "a,#0xff");
1408 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1416 if (strcmp (aop->aopu.aop_str[offset], s) ||
1418 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1423 if (!offset && (strcmp (s, "acc") == 0) &&
1427 if (strcmp (aop->aopu.aop_str[offset], s) &&
1429 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1433 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1434 "aopPut got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* pointToEnd :- points to the last byte of the operand */
1444 /*-----------------------------------------------------------------*/
1446 pointToEnd (asmop * aop)
1452 aop->coff = count = (aop->size - 1);
1458 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1462 emitcode ("inc", "dptr");
1469 /*-----------------------------------------------------------------*/
1470 /* reAdjustPreg - points a register back to where it should */
1471 /*-----------------------------------------------------------------*/
1473 reAdjustPreg (asmop * aop)
1475 if ((aop->coff==0) || aop->size <= 1)
1483 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1488 emitcode ("lcall", "__decdptr");
1495 #define AOP(op) op->aop
1496 #define AOP_TYPE(op) AOP(op)->type
1497 #define AOP_SIZE(op) AOP(op)->size
1498 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1499 AOP_TYPE(x) == AOP_R0))
1501 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1502 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1504 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1505 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1506 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is */
1511 /* a generic pointer type. */
1512 /*-----------------------------------------------------------------*/
1514 opIsGptr (operand * op)
1516 sym_link *type = operandType (op);
1518 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size */
1527 /*-----------------------------------------------------------------*/
1529 getDataSize (operand * op)
1532 size = AOP_SIZE (op);
1533 if (size == GPTRSIZE)
1535 sym_link *type = operandType (op);
1536 if (IS_GENPTR (type))
1538 /* generic pointer; arithmetic operations
1539 * should ignore the high byte (pointer type).
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc */
1549 /*-----------------------------------------------------------------*/
1551 outAcc (operand * result)
1554 size = getDataSize (result);
1557 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1560 /* unsigned or positive */
1563 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C */
1570 /*-----------------------------------------------------------------*/
1572 outBitC (operand * result)
1574 /* if the result is bit */
1575 if (AOP_TYPE (result) == AOP_CRY)
1576 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1579 emitcode ("clr", "a");
1580 emitcode ("rlc", "a");
1585 /*-----------------------------------------------------------------*/
1586 /* toBoolean - emit code for orl a,operator(sizeop) */
1587 /*-----------------------------------------------------------------*/
1589 toBoolean (operand * oper)
1591 int size = AOP_SIZE (oper) - 1;
1593 bool AccUsed = FALSE;
1596 while (!AccUsed && size--)
1598 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1601 size = AOP_SIZE (oper) - 1;
1603 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1604 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1607 emitcode("mov", "b,a");
1610 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1611 emitcode ("orl", "b,a");
1619 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1625 /*-----------------------------------------------------------------*/
1626 /* genNot - generate code for ! operation */
1627 /*-----------------------------------------------------------------*/
1633 D(emitcode ("; genNot",""));
1635 /* assign asmOps to operand & result */
1636 aopOp (IC_LEFT (ic), ic, FALSE);
1637 aopOp (IC_RESULT (ic), ic, TRUE);
1639 /* if in bit space then a special case */
1640 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1642 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1643 emitcode ("cpl", "c");
1644 outBitC (IC_RESULT (ic));
1648 toBoolean (IC_LEFT (ic));
1650 tlbl = newiTempLabel (NULL);
1651 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1652 emitcode ("", "%05d$:", tlbl->key + 100);
1653 outBitC (IC_RESULT (ic));
1656 /* release the aops */
1657 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genCpl - generate code for complement */
1664 /*-----------------------------------------------------------------*/
1671 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1673 D(emitcode (";", "genCpl"));
1675 /* assign asmOps to operand & result */
1676 aopOp (IC_LEFT (ic), ic, FALSE);
1677 aopOp (IC_RESULT (ic), ic, TRUE);
1679 /* special case if in bit space */
1680 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1684 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1685 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1687 /* promotion rules are responsible for this strange result:
1688 bit -> int -> ~int -> bit
1689 uchar -> int -> ~int -> bit
1691 werror(W_COMPLEMENT);
1692 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1696 tlbl=newiTempLabel(NULL);
1697 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1698 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1699 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1700 IS_AOP_PREG (IC_LEFT (ic)))
1702 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1707 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1709 emitcode ("", "%05d$:", tlbl->key + 100);
1710 outBitC (IC_RESULT(ic));
1714 size = AOP_SIZE (IC_RESULT (ic));
1717 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1719 emitcode ("cpl", "a");
1720 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1725 /* release the aops */
1726 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1730 /*-----------------------------------------------------------------*/
1731 /* genUminusFloat - unary minus for floating points */
1732 /*-----------------------------------------------------------------*/
1734 genUminusFloat (operand * op, operand * result)
1736 int size, offset = 0;
1739 D(emitcode ("; genUminusFloat",""));
1741 /* for this we just copy and then flip the bit */
1743 size = AOP_SIZE (op) - 1;
1747 aopPut (AOP (result),
1748 aopGet (AOP (op), offset, FALSE, FALSE),
1750 isOperandVolatile (result, FALSE));
1754 l = aopGet (AOP (op), offset, FALSE, FALSE);
1758 emitcode ("cpl", "acc.7");
1759 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1762 /*-----------------------------------------------------------------*/
1763 /* genUminus - unary minus code generation */
1764 /*-----------------------------------------------------------------*/
1766 genUminus (iCode * ic)
1769 sym_link *optype, *rtype;
1772 D(emitcode ("; genUminus",""));
1775 aopOp (IC_LEFT (ic), ic, FALSE);
1776 aopOp (IC_RESULT (ic), ic, TRUE);
1778 /* if both in bit space then special
1780 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1781 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1784 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1785 emitcode ("cpl", "c");
1786 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1790 optype = operandType (IC_LEFT (ic));
1791 rtype = operandType (IC_RESULT (ic));
1793 /* if float then do float stuff */
1794 if (IS_FLOAT (optype))
1796 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1800 /* otherwise subtract from zero */
1801 size = AOP_SIZE (IC_LEFT (ic));
1806 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1807 if (!strcmp (l, "a"))
1811 emitcode ("cpl", "a");
1812 emitcode ("addc", "a,#0");
1818 emitcode ("clr", "a");
1819 emitcode ("subb", "a,%s", l);
1821 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1824 /* if any remaining bytes in the result */
1825 /* we just need to propagate the sign */
1826 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1828 emitcode ("rlc", "a");
1829 emitcode ("subb", "a,acc");
1831 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1835 /* release the aops */
1836 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1840 /*-----------------------------------------------------------------*/
1841 /* saveRegisters - will look for a call and save the registers */
1842 /*-----------------------------------------------------------------*/
1844 saveRegisters (iCode * lic)
1851 for (ic = lic; ic; ic = ic->next)
1852 if (ic->op == CALL || ic->op == PCALL)
1857 fprintf (stderr, "found parameter push with no function call\n");
1861 /* if the registers have been saved already or don't need to be then
1865 if (IS_SYMOP(IC_LEFT(ic)) &&
1866 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1867 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1870 /* save the registers in use at this time but skip the
1871 ones for the result */
1872 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1873 mcs51_rUmaskForOp (IC_RESULT(ic)));
1876 if (options.useXstack)
1878 int count = bitVectnBitsOn (rsave);
1882 i = bitVectFirstBit (rsave);
1883 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1884 emitcode ("mov", "r0,%s", spname);
1885 emitcode ("inc", "%s", spname);// allocate before use
1886 emitcode ("movx", "@r0,a");
1887 if (bitVectBitValue (rsave, R0_IDX))
1888 emitcode ("mov", "r0,a");
1890 else if (count != 0)
1892 if (bitVectBitValue (rsave, R0_IDX))
1894 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1896 emitcode ("mov", "r0,%s", spname);
1898 emitcode ("add", "a,#%d", count);
1899 emitcode ("mov", "%s,a", spname);
1900 for (i = 0; i < mcs51_nRegs; i++)
1902 if (bitVectBitValue (rsave, i))
1906 emitcode ("pop", "acc");
1907 emitcode ("push", "acc");
1911 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1913 emitcode ("movx", "@r0,a");
1916 emitcode ("inc", "r0");
1920 if (bitVectBitValue (rsave, R0_IDX))
1922 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1927 for (i = 0; i < mcs51_nRegs; i++)
1929 if (bitVectBitValue (rsave, i))
1930 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1934 /*-----------------------------------------------------------------*/
1935 /* unsaveRegisters - pop the pushed registers */
1936 /*-----------------------------------------------------------------*/
1938 unsaveRegisters (iCode * ic)
1943 /* restore the registers in use at this time but skip the
1944 ones for the result */
1945 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1946 mcs51_rUmaskForOp (IC_RESULT(ic)));
1948 if (options.useXstack)
1950 int count = bitVectnBitsOn (rsave);
1954 emitcode ("mov", "r0,%s", spname);
1955 emitcode ("dec", "r0");
1956 emitcode ("movx", "a,@r0");
1957 i = bitVectFirstBit (rsave);
1958 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1959 emitcode ("dec", "%s", spname);
1963 emitcode ("mov", "r0,%s", spname);
1964 for (i = mcs51_nRegs; i >= 0; i--)
1966 if (bitVectBitValue (rsave, i))
1968 emitcode ("dec", "r0");
1969 emitcode ("movx", "a,@r0");
1971 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1974 emitcode ("mov", "%s,r0", spname);
1975 if (bitVectBitValue (rsave, R0_IDX))
1977 emitcode ("mov", "r0,a");
1982 for (i = mcs51_nRegs; i >= 0; i--)
1984 if (bitVectBitValue (rsave, i))
1985 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1990 /*-----------------------------------------------------------------*/
1992 /*-----------------------------------------------------------------*/
1994 pushSide (operand * oper, int size)
1999 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2000 if (AOP_TYPE (oper) != AOP_REG &&
2001 AOP_TYPE (oper) != AOP_DIR &&
2005 emitcode ("push", "acc");
2008 emitcode ("push", "%s", l);
2012 /*-----------------------------------------------------------------*/
2013 /* assignResultValue - */
2014 /*-----------------------------------------------------------------*/
2016 assignResultValue (operand * oper)
2019 int size = AOP_SIZE (oper);
2022 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2028 /*-----------------------------------------------------------------*/
2029 /* genXpush - pushes onto the external stack */
2030 /*-----------------------------------------------------------------*/
2032 genXpush (iCode * ic)
2034 asmop *aop = newAsmop (0);
2036 int size, offset = 0;
2038 D(emitcode ("; genXpush",""));
2040 aopOp (IC_LEFT (ic), ic, FALSE);
2041 r = getFreePtr (ic, &aop, FALSE);
2043 size = AOP_SIZE (IC_LEFT (ic));
2047 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2048 emitcode ("mov", "%s,%s", r->name, spname);
2049 emitcode ("inc", "%s", spname); // allocate space first
2050 emitcode ("movx", "@%s,a", r->name);
2054 // allocate space first
2055 emitcode ("mov", "%s,%s", r->name, spname);
2057 emitcode ("add", "a,#%d", size);
2058 emitcode ("mov", "%s,a", spname);
2062 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2063 emitcode ("movx", "@%s,a", r->name);
2064 emitcode ("inc", "%s", r->name);
2068 freeAsmop (NULL, aop, ic, TRUE);
2069 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2072 /*-----------------------------------------------------------------*/
2073 /* genIpush - genrate code for pushing this gets a little complex */
2074 /*-----------------------------------------------------------------*/
2076 genIpush (iCode * ic)
2078 int size, offset = 0;
2081 D(emitcode ("; genIpush",""));
2083 /* if this is not a parm push : ie. it is spill push
2084 and spill push is always done on the local stack */
2088 /* and the item is spilt then do nothing */
2089 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2092 aopOp (IC_LEFT (ic), ic, FALSE);
2093 size = AOP_SIZE (IC_LEFT (ic));
2094 /* push it on the stack */
2097 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2103 emitcode ("push", "%s", l);
2108 /* this is a paramter push: in this case we call
2109 the routine to find the call and save those
2110 registers that need to be saved */
2113 /* if use external stack then call the external
2114 stack pushing routine */
2115 if (options.useXstack)
2121 /* then do the push */
2122 aopOp (IC_LEFT (ic), ic, FALSE);
2124 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2125 size = AOP_SIZE (IC_LEFT (ic));
2129 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2130 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2131 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2135 emitcode ("push", "acc");
2138 emitcode ("push", "%s", l);
2141 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2144 /*-----------------------------------------------------------------*/
2145 /* genIpop - recover the registers: can happen only for spilling */
2146 /*-----------------------------------------------------------------*/
2148 genIpop (iCode * ic)
2152 D(emitcode ("; genIpop",""));
2154 /* if the temp was not pushed then */
2155 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2158 aopOp (IC_LEFT (ic), ic, FALSE);
2159 size = AOP_SIZE (IC_LEFT (ic));
2160 offset = (size - 1);
2162 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2165 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2168 /*-----------------------------------------------------------------*/
2169 /* saveRBank - saves an entire register bank on the stack */
2170 /*-----------------------------------------------------------------*/
2172 saveRBank (int bank, iCode * ic, bool pushPsw)
2175 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2179 if (options.useXstack)
2183 /* Assume r0 is available for use. */
2184 r = mcs51_regWithIdx (R0_IDX);;
2189 r = getFreePtr (ic, &aop, FALSE);
2191 // allocate space first
2192 emitcode ("mov", "%s,%s", r->name, spname);
2194 emitcode ("add", "a,#%d", count);
2195 emitcode ("mov", "%s,a", spname);
2198 for (i = 0; i < mcs51_nRegs; i++)
2200 if (options.useXstack)
2202 emitcode ("mov", "a,(%s+%d)",
2203 regs8051[i].base, 8 * bank + regs8051[i].offset);
2204 emitcode ("movx", "@%s,a", r->name);
2206 emitcode ("inc", "%s", r->name);
2209 emitcode ("push", "(%s+%d)",
2210 regs8051[i].base, 8 * bank + regs8051[i].offset);
2215 if (options.useXstack)
2217 emitcode ("mov", "a,psw");
2218 emitcode ("movx", "@%s,a", r->name);
2223 emitcode ("push", "psw");
2226 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2231 freeAsmop (NULL, aop, ic, TRUE);
2240 /*-----------------------------------------------------------------*/
2241 /* unsaveRBank - restores the register bank from stack */
2242 /*-----------------------------------------------------------------*/
2244 unsaveRBank (int bank, iCode * ic, bool popPsw)
2250 if (options.useXstack)
2254 /* Assume r0 is available for use. */
2255 r = mcs51_regWithIdx (R0_IDX);;
2260 r = getFreePtr (ic, &aop, FALSE);
2262 emitcode ("mov", "%s,%s", r->name, spname);
2267 if (options.useXstack)
2269 emitcode ("dec", "%s", r->name);
2270 emitcode ("movx", "a,@%s", r->name);
2271 emitcode ("mov", "psw,a");
2275 emitcode ("pop", "psw");
2279 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2281 if (options.useXstack)
2283 emitcode ("dec", "%s", r->name);
2284 emitcode ("movx", "a,@%s", r->name);
2285 emitcode ("mov", "(%s+%d),a",
2286 regs8051[i].base, 8 * bank + regs8051[i].offset);
2290 emitcode ("pop", "(%s+%d)",
2291 regs8051[i].base, 8 * bank + regs8051[i].offset);
2295 if (options.useXstack)
2297 emitcode ("mov", "%s,%s", spname, r->name);
2302 freeAsmop (NULL, aop, ic, TRUE);
2306 /*-----------------------------------------------------------------*/
2307 /* genSend - gen code for SEND */
2308 /*-----------------------------------------------------------------*/
2309 static void genSend(set *sendSet)
2314 for (sic = setFirstItem (sendSet); sic;
2315 sic = setNextItem (sendSet)) {
2316 int size, offset = 0;
2317 aopOp (IC_LEFT (sic), sic, FALSE);
2318 size = AOP_SIZE (IC_LEFT (sic));
2320 if (sic->argreg == 1) {
2322 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2324 if (strcmp (l, fReturn[offset]))
2325 emitcode ("mov", "%s,%s", fReturn[offset], l);
2331 emitcode ("mov","b1_%d,%s",rb1_count++,
2332 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2335 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2339 /*-----------------------------------------------------------------*/
2340 /* genCall - generates a call statement */
2341 /*-----------------------------------------------------------------*/
2343 genCall (iCode * ic)
2346 // bool restoreBank = FALSE;
2347 bool swapBanks = FALSE;
2349 D(emitcode("; genCall",""));
2351 dtype = operandType (IC_LEFT (ic));
2352 /* if send set is not empty then assign */
2355 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2356 genSend(reverseSet(_G.sendSet));
2358 genSend(_G.sendSet);
2364 /* if we are calling a not _naked function that is not using
2365 the same register bank then we need to save the
2366 destination registers on the stack */
2367 dtype = operandType (IC_LEFT (ic));
2368 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2369 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2370 !IFFUNC_ISISR (dtype))
2375 /* if caller saves & we have not saved then */
2381 emitcode ("mov", "psw,#0x%02x",
2382 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2386 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2387 OP_SYMBOL (IC_LEFT (ic))->rname :
2388 OP_SYMBOL (IC_LEFT (ic))->name));
2392 emitcode ("mov", "psw,#0x%02x",
2393 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2396 /* if we need assign a result value */
2397 if ((IS_ITEMP (IC_RESULT (ic)) &&
2398 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2399 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2400 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2401 IS_TRUE_SYMOP (IC_RESULT (ic)))
2405 aopOp (IC_RESULT (ic), ic, FALSE);
2408 assignResultValue (IC_RESULT (ic));
2410 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2413 /* adjust the stack for parameters if
2418 if (ic->parmBytes > 3)
2420 emitcode ("mov", "a,%s", spname);
2421 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2422 emitcode ("mov", "%s,a", spname);
2425 for (i = 0; i < ic->parmBytes; i++)
2426 emitcode ("dec", "%s", spname);
2429 /* if we hade saved some registers then unsave them */
2430 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2431 unsaveRegisters (ic);
2433 // /* if register bank was saved then pop them */
2435 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2438 /*-----------------------------------------------------------------*/
2439 /* -10l - generates a call by pointer statement */
2440 /*-----------------------------------------------------------------*/
2442 genPcall (iCode * ic)
2445 symbol *rlbl = newiTempLabel (NULL);
2446 // bool restoreBank=FALSE;
2447 bool swapBanks = FALSE;
2449 D(emitcode("; genPCall",""));
2451 /* if caller saves & we have not saved then */
2455 /* if we are calling a not _naked function that is not using
2456 the same register bank then we need to save the
2457 destination registers on the stack */
2458 dtype = operandType (IC_LEFT (ic))->next;
2459 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2460 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2461 !IFFUNC_ISISR (dtype))
2463 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2464 // restoreBank=TRUE;
2466 // need caution message to user here
2469 /* push the return address on to the stack */
2470 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2471 emitcode ("push", "acc");
2472 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2473 emitcode ("push", "acc");
2475 /* now push the calling address */
2476 aopOp (IC_LEFT (ic), ic, FALSE);
2478 pushSide (IC_LEFT (ic), FPTRSIZE);
2480 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2482 /* if send set is not empty the assign */
2485 genSend(reverseSet(_G.sendSet));
2491 emitcode ("mov", "psw,#0x%02x",
2492 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2496 emitcode ("ret", "");
2497 emitcode ("", "%05d$:", (rlbl->key + 100));
2502 emitcode ("mov", "psw,#0x%02x",
2503 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2506 /* if we need assign a result value */
2507 if ((IS_ITEMP (IC_RESULT (ic)) &&
2508 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2509 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2510 IS_TRUE_SYMOP (IC_RESULT (ic)))
2514 aopOp (IC_RESULT (ic), ic, FALSE);
2517 assignResultValue (IC_RESULT (ic));
2519 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2522 /* adjust the stack for parameters if
2527 if (ic->parmBytes > 3)
2529 emitcode ("mov", "a,%s", spname);
2530 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2531 emitcode ("mov", "%s,a", spname);
2534 for (i = 0; i < ic->parmBytes; i++)
2535 emitcode ("dec", "%s", spname);
2539 // /* if register bank was saved then unsave them */
2541 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2543 /* if we hade saved some registers then
2545 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2546 unsaveRegisters (ic);
2549 /*-----------------------------------------------------------------*/
2550 /* resultRemat - result is rematerializable */
2551 /*-----------------------------------------------------------------*/
2553 resultRemat (iCode * ic)
2555 if (SKIP_IC (ic) || ic->op == IFX)
2558 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2560 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2561 if (sym->remat && !POINTER_SET (ic))
2568 #if defined(__BORLANDC__) || defined(_MSC_VER)
2569 #define STRCASECMP stricmp
2571 #define STRCASECMP strcasecmp
2574 /*-----------------------------------------------------------------*/
2575 /* inExcludeList - return 1 if the string is in exclude Reg list */
2576 /*-----------------------------------------------------------------*/
2578 regsCmp(void *p1, void *p2)
2580 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2584 inExcludeList (char *s)
2586 const char *p = setFirstItem(options.excludeRegsSet);
2588 if (p == NULL || STRCASECMP(p, "none") == 0)
2592 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2595 /*-----------------------------------------------------------------*/
2596 /* genFunction - generated code for function entry */
2597 /*-----------------------------------------------------------------*/
2599 genFunction (iCode * ic)
2601 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2603 bool switchedPSW = FALSE;
2604 int calleesaves_saved_register = -1;
2605 int stackAdjust = sym->stack;
2606 int accIsFree = sym->recvSize < 4;
2607 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2608 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2611 /* create the function header */
2612 emitcode (";", "-----------------------------------------");
2613 emitcode (";", " function %s", sym->name);
2614 emitcode (";", "-----------------------------------------");
2616 emitcode ("", "%s:", sym->rname);
2617 ftype = operandType (IC_LEFT (ic));
2618 _G.currentFunc = sym;
2620 if (IFFUNC_ISNAKED(ftype))
2622 emitcode(";", "naked function: no prologue.");
2626 /* here we need to generate the equates for the
2627 register bank if required */
2628 if (FUNC_REGBANK (ftype) != rbank)
2632 rbank = FUNC_REGBANK (ftype);
2633 for (i = 0; i < mcs51_nRegs; i++)
2635 if (strcmp (regs8051[i].base, "0") == 0)
2636 emitcode ("", "%s = 0x%02x",
2638 8 * rbank + regs8051[i].offset);
2640 emitcode ("", "%s = %s + 0x%02x",
2643 8 * rbank + regs8051[i].offset);
2647 /* if this is an interrupt service routine then
2648 save acc, b, dpl, dph */
2649 if (IFFUNC_ISISR (sym->type))
2652 if (!inExcludeList ("acc"))
2653 emitcode ("push", "acc");
2654 if (!inExcludeList ("b"))
2655 emitcode ("push", "b");
2656 if (!inExcludeList ("dpl"))
2657 emitcode ("push", "dpl");
2658 if (!inExcludeList ("dph"))
2659 emitcode ("push", "dph");
2660 /* if this isr has no bank i.e. is going to
2661 run with bank 0 , then we need to save more
2663 if (!FUNC_REGBANK (sym->type))
2666 /* if this function does not call any other
2667 function then we can be economical and
2668 save only those registers that are used */
2669 if (!IFFUNC_HASFCALL(sym->type))
2673 /* if any registers used */
2676 /* save the registers used */
2677 for (i = 0; i < sym->regsUsed->size; i++)
2679 if (bitVectBitValue (sym->regsUsed, i))
2680 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2687 /* this function has a function call. We cannot
2688 determines register usage so we will have to push the
2690 saveRBank (0, ic, FALSE);
2691 if (options.parms_in_bank1) {
2693 for (i=0; i < 8 ; i++ ) {
2694 emitcode ("push","%s",rb1regs[i]);
2701 /* This ISR uses a non-zero bank.
2703 * We assume that the bank is available for our
2706 * However, if this ISR calls a function which uses some
2707 * other bank, we must save that bank entirely.
2709 unsigned long banksToSave = 0;
2711 if (IFFUNC_HASFCALL(sym->type))
2714 #define MAX_REGISTER_BANKS 4
2719 for (i = ic; i; i = i->next)
2721 if (i->op == ENDFUNCTION)
2723 /* we got to the end OK. */
2731 dtype = operandType (IC_LEFT(i));
2733 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2735 /* Mark this bank for saving. */
2736 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2738 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2742 banksToSave |= (1 << FUNC_REGBANK(dtype));
2745 /* And note that we don't need to do it in
2753 /* This is a mess; we have no idea what
2754 * register bank the called function might
2757 * The only thing I can think of to do is
2758 * throw a warning and hope.
2760 werror(W_FUNCPTR_IN_USING_ISR);
2764 if (banksToSave && options.useXstack)
2766 /* Since we aren't passing it an ic,
2767 * saveRBank will assume r0 is available to abuse.
2769 * So switch to our (trashable) bank now, so
2770 * the caller's R0 isn't trashed.
2772 emitcode ("push", "psw");
2773 emitcode ("mov", "psw,#0x%02x",
2774 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2778 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2780 if (banksToSave & (1 << ix))
2782 saveRBank(ix, NULL, FALSE);
2786 // TODO: this needs a closer look
2787 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2790 /* Set the register bank to the desired value if nothing else */
2791 /* has done so yet. */
2794 emitcode ("push", "psw");
2795 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2800 /* This is a non-ISR function. The caller has already switched register */
2801 /* banks, if necessary, so just handle the callee-saves option. */
2803 /* if callee-save to be used for this function
2804 then save the registers being used in this function */
2805 if (IFFUNC_CALLEESAVES(sym->type))
2809 /* if any registers used */
2812 /* save the registers used */
2813 for (i = 0; i < sym->regsUsed->size; i++)
2815 if (bitVectBitValue (sym->regsUsed, i))
2817 /* remember one saved register for later usage */
2818 if (calleesaves_saved_register < 0)
2819 calleesaves_saved_register = i;
2820 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2831 if (options.useXstack)
2833 emitcode ("mov", "r0,%s", spname);
2834 emitcode ("inc", "%s", spname);
2835 emitcode ("xch", "a,_bp");
2836 emitcode ("movx", "@r0,a");
2837 emitcode ("inc", "r0");
2838 emitcode ("mov", "a,r0");
2839 emitcode ("xch", "a,_bp");
2843 /* set up the stack */
2844 emitcode ("push", "_bp"); /* save the callers stack */
2845 emitcode ("mov", "_bp,%s", spname);
2849 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2850 /* before setting up the stack frame completely. */
2851 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2853 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2857 if (rsym && rsym->regType == REG_CND)
2859 if (rsym && (rsym->accuse || rsym->ruonly))
2861 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2862 rsym = rsym->usl.spillLoc;
2865 /* If the RECEIVE operand immediately spills to the first entry on the */
2866 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2867 /* rather than the usual @r0/r1 machinations. */
2868 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2872 _G.current_iCode = ric;
2873 D(emitcode ("; genReceive",""));
2874 for (ofs=0; ofs < sym->recvSize; ofs++)
2876 if (!strcmp (fReturn[ofs], "a"))
2877 emitcode ("push", "acc");
2879 emitcode ("push", fReturn[ofs]);
2881 stackAdjust -= sym->recvSize;
2884 assert (stackAdjust>=0);
2887 _G.current_iCode = ic;
2891 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2892 /* to free up the accumulator. */
2893 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2897 _G.current_iCode = ric;
2898 D(emitcode ("; genReceive",""));
2899 for (ofs=0; ofs < sym->recvSize; ofs++)
2901 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2903 _G.current_iCode = ic;
2909 /* adjust the stack for the function */
2912 int i = stackAdjust;
2914 werror (W_STACK_OVERFLOW, sym->name);
2916 if (i > 3 && accIsFree)
2918 emitcode ("mov", "a,sp");
2919 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2920 emitcode ("mov", "sp,a");
2924 /* The accumulator is not free, so we will need another register */
2925 /* to clobber. No need to worry about a possible conflict with */
2926 /* the above early RECEIVE optimizations since they would have */
2927 /* freed the accumulator if they were generated. */
2929 if (IFFUNC_CALLEESAVES(sym->type))
2931 /* if it's a callee-saves function we need a saved register */
2932 if (calleesaves_saved_register >= 0)
2934 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2935 emitcode ("mov", "a,sp");
2936 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2937 emitcode ("mov", "sp,a");
2938 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2941 /* do it the hard way */
2943 emitcode ("inc", "sp");
2947 /* not callee-saves, we can clobber r0 */
2948 emitcode ("mov", "r0,a");
2949 emitcode ("mov", "a,sp");
2950 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2951 emitcode ("mov", "sp,a");
2952 emitcode ("mov", "a,r0");
2957 emitcode ("inc", "sp");
2962 char i = ((char) sym->xstack & 0xff);
2964 if (i > 3 && accIsFree)
2966 emitcode ("mov", "a,_spx");
2967 emitcode ("add", "a,#0x%02x", i);
2968 emitcode ("mov", "_spx,a");
2972 emitcode ("push", "acc");
2973 emitcode ("mov", "a,_spx");
2974 emitcode ("add", "a,#0x%02x", i);
2975 emitcode ("mov", "_spx,a");
2976 emitcode ("pop", "acc");
2981 emitcode ("inc", "_spx");
2985 /* if critical function then turn interrupts off */
2986 if (IFFUNC_ISCRITICAL (ftype))
2988 symbol *tlbl = newiTempLabel (NULL);
2989 emitcode ("setb", "c");
2990 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2991 emitcode ("clr", "c");
2992 emitcode ("", "%05d$:", (tlbl->key + 100));
2993 emitcode ("push", "psw"); /* save old ea via c in psw */
2997 /*-----------------------------------------------------------------*/
2998 /* genEndFunction - generates epilogue for functions */
2999 /*-----------------------------------------------------------------*/
3001 genEndFunction (iCode * ic)
3003 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3004 lineNode *lnp = lineCurr;
3006 bitVect *regsUsedPrologue;
3007 bitVect *regsUnneeded;
3008 int accIsFree = sym->recvSize < 4;
3011 _G.currentFunc = NULL;
3012 if (IFFUNC_ISNAKED(sym->type))
3014 emitcode(";", "naked function: no epilogue.");
3015 if (options.debug && currFunc)
3016 debugFile->writeEndFunction (currFunc, ic, 0);
3020 if (IFFUNC_ISCRITICAL (sym->type))
3022 emitcode ("pop", "psw"); /* restore ea via c in psw */
3023 emitcode ("mov", "ea,c");
3026 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3028 emitcode ("mov", "%s,_bp", spname);
3031 /* if use external stack but some variables were
3032 added to the local stack then decrement the
3034 if (options.useXstack && sym->stack)
3036 char count = sym->stack;
3038 if ((count>3) && accIsFree)
3040 emitcode ("mov", "a,sp");
3041 emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3042 emitcode ("mov", "sp,a");
3047 emitcode ("dec", "sp");
3051 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3053 if (options.useXstack)
3055 emitcode ("xch", "a,_bp");
3056 emitcode ("mov", "r0,a");
3057 emitcode ("dec", "r0");
3058 emitcode ("movx", "a,@r0");
3059 emitcode ("xch", "a,_bp");
3060 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3064 emitcode ("pop", "_bp");
3068 /* restore the register bank */
3069 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3071 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3072 || !options.useXstack)
3074 /* Special case of ISR using non-zero bank with useXstack
3077 emitcode ("pop", "psw");
3081 if (IFFUNC_ISISR (sym->type))
3084 /* now we need to restore the registers */
3085 /* if this isr has no bank i.e. is going to
3086 run with bank 0 , then we need to save more
3088 if (!FUNC_REGBANK (sym->type))
3090 /* if this function does not call any other
3091 function then we can be economical and
3092 save only those registers that are used */
3093 if (!IFFUNC_HASFCALL(sym->type))
3097 /* if any registers used */
3100 /* save the registers used */
3101 for (i = sym->regsUsed->size; i >= 0; i--)
3103 if (bitVectBitValue (sym->regsUsed, i))
3104 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3110 if (options.parms_in_bank1) {
3112 for (i = 7 ; i >= 0 ; i-- ) {
3113 emitcode ("pop","%s",rb1regs[i]);
3116 /* this function has a function call cannot
3117 determines register usage so we will have to pop the
3119 unsaveRBank (0, ic, FALSE);
3124 /* This ISR uses a non-zero bank.
3126 * Restore any register banks saved by genFunction
3129 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3132 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3134 if (savedBanks & (1 << ix))
3136 unsaveRBank(ix, NULL, FALSE);
3140 if (options.useXstack)
3142 /* Restore bank AFTER calling unsaveRBank,
3143 * since it can trash r0.
3145 emitcode ("pop", "psw");
3149 if (!inExcludeList ("dph"))
3150 emitcode ("pop", "dph");
3151 if (!inExcludeList ("dpl"))
3152 emitcode ("pop", "dpl");
3153 if (!inExcludeList ("b"))
3154 emitcode ("pop", "b");
3155 if (!inExcludeList ("acc"))
3156 emitcode ("pop", "acc");
3158 /* if debug then send end of function */
3159 if (options.debug && currFunc)
3161 debugFile->writeEndFunction (currFunc, ic, 1);
3164 emitcode ("reti", "");
3168 if (IFFUNC_CALLEESAVES(sym->type))
3172 /* if any registers used */
3175 /* save the registers used */
3176 for (i = sym->regsUsed->size; i >= 0; i--)
3178 if (bitVectBitValue (sym->regsUsed, i) ||
3179 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3180 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3183 else if (mcs51_ptrRegReq)
3185 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3186 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3191 /* if debug then send end of function */
3192 if (options.debug && currFunc)
3194 debugFile->writeEndFunction (currFunc, ic, 1);
3197 emitcode ("ret", "");
3200 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3203 /* If this was an interrupt handler using bank 0 that called another */
3204 /* function, then all registers must be saved; nothing to optimized. */
3205 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3206 && !FUNC_REGBANK(sym->type))
3209 /* There are no push/pops to optimize if not callee-saves or ISR */
3210 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3213 /* If there were stack parameters, we cannot optimize without also */
3214 /* fixing all of the stack offsets; this is too dificult to consider. */
3215 if (FUNC_HASSTACKPARM(sym->type))
3218 /* Compute the registers actually used */
3219 regsUsed = newBitVect (mcs51_nRegs);
3220 regsUsedPrologue = newBitVect (mcs51_nRegs);
3223 if (lnp->ic && lnp->ic->op == FUNCTION)
3224 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3226 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3228 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3229 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3236 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3237 && !bitVectBitValue (regsUsed, CND_IDX))
3239 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3240 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3241 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3242 bitVectUnSetBit (regsUsed, CND_IDX);
3245 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3247 /* If this was an interrupt handler that called another function */
3248 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3249 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3251 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3252 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3253 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3254 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3255 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3258 /* Remove the unneeded push/pops */
3259 regsUnneeded = newBitVect (mcs51_nRegs);
3262 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3264 if (!strncmp(lnp->line, "push", 4))
3266 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3267 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3269 connectLine (lnp->prev, lnp->next);
3270 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3273 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3275 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3276 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3278 connectLine (lnp->prev, lnp->next);
3279 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3286 for (idx = 0; idx < regsUnneeded->size; idx++)
3287 if (bitVectBitValue (regsUnneeded, idx))
3288 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3290 freeBitVect (regsUnneeded);
3291 freeBitVect (regsUsed);
3292 freeBitVect (regsUsedPrologue);
3295 /*-----------------------------------------------------------------*/
3296 /* genRet - generate code for return statement */
3297 /*-----------------------------------------------------------------*/
3301 int size, offset = 0, pushed = 0;
3303 D(emitcode ("; genRet",""));
3305 /* if we have no return value then
3306 just generate the "ret" */
3310 /* we have something to return then
3311 move the return value into place */
3312 aopOp (IC_LEFT (ic), ic, FALSE);
3313 size = AOP_SIZE (IC_LEFT (ic));
3318 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3321 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3323 emitcode ("push", "%s", l);
3328 l = aopGet (AOP (IC_LEFT (ic)), offset,
3330 if (strcmp (fReturn[offset], l))
3331 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3340 if (strcmp (fReturn[pushed], "a"))
3341 emitcode ("pop", fReturn[pushed]);
3343 emitcode ("pop", "acc");
3346 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3349 /* generate a jump to the return label
3350 if the next is not the return statement */
3351 if (!(ic->next && ic->next->op == LABEL &&
3352 IC_LABEL (ic->next) == returnLabel))
3354 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3358 /*-----------------------------------------------------------------*/
3359 /* genLabel - generates a label */
3360 /*-----------------------------------------------------------------*/
3362 genLabel (iCode * ic)
3364 /* special case never generate */
3365 if (IC_LABEL (ic) == entryLabel)
3368 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3371 /*-----------------------------------------------------------------*/
3372 /* genGoto - generates a ljmp */
3373 /*-----------------------------------------------------------------*/
3375 genGoto (iCode * ic)
3377 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3380 /*-----------------------------------------------------------------*/
3381 /* findLabelBackwards: walks back through the iCode chain looking */
3382 /* for the given label. Returns number of iCode instructions */
3383 /* between that label and given ic. */
3384 /* Returns zero if label not found. */
3385 /*-----------------------------------------------------------------*/
3387 findLabelBackwards (iCode * ic, int key)
3396 /* If we have any pushes or pops, we cannot predict the distance.
3397 I don't like this at all, this should be dealt with in the
3399 if (ic->op == IPUSH || ic->op == IPOP) {
3403 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3412 /*-----------------------------------------------------------------*/
3413 /* genPlusIncr :- does addition with increment if possible */
3414 /*-----------------------------------------------------------------*/
3416 genPlusIncr (iCode * ic)
3418 unsigned int icount;
3419 unsigned int size = getDataSize (IC_RESULT (ic));
3421 /* will try to generate an increment */
3422 /* if the right side is not a literal
3424 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3427 /* if the literal value of the right hand side
3428 is greater than 4 then it is not worth it */
3429 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3432 D(emitcode ("; genPlusIncr",""));
3434 /* if increment >=16 bits in register or direct space */
3435 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3436 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3444 /* If the next instruction is a goto and the goto target
3445 * is < 10 instructions previous to this, we can generate
3446 * jumps straight to that target.
3448 if (ic->next && ic->next->op == GOTO
3449 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3450 && labelRange <= 10)
3452 emitcode (";", "tail increment optimized");
3453 tlbl = IC_LABEL (ic->next);
3458 tlbl = newiTempLabel (NULL);
3461 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3462 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3463 IS_AOP_PREG (IC_RESULT (ic)))
3464 emitcode ("cjne", "%s,#0x00,%05d$",
3465 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3469 emitcode ("clr", "a");
3470 emitcode ("cjne", "a,%s,%05d$",
3471 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3475 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3478 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3479 IS_AOP_PREG (IC_RESULT (ic)))
3480 emitcode ("cjne", "%s,#0x00,%05d$",
3481 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3484 emitcode ("cjne", "a,%s,%05d$",
3485 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3488 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3492 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3493 IS_AOP_PREG (IC_RESULT (ic)))
3494 emitcode ("cjne", "%s,#0x00,%05d$",
3495 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3499 emitcode ("cjne", "a,%s,%05d$",
3500 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3503 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3508 emitcode ("", "%05d$:", tlbl->key + 100);
3513 /* if the sizes are greater than 1 then we cannot */
3514 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3515 AOP_SIZE (IC_LEFT (ic)) > 1)
3518 /* we can if the aops of the left & result match or
3519 if they are in registers and the registers are the
3521 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3526 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3527 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3528 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3534 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3543 /*-----------------------------------------------------------------*/
3544 /* outBitAcc - output a bit in acc */
3545 /*-----------------------------------------------------------------*/
3547 outBitAcc (operand * result)
3549 symbol *tlbl = newiTempLabel (NULL);
3550 /* if the result is a bit */
3551 if (AOP_TYPE (result) == AOP_CRY)
3553 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3557 emitcode ("jz", "%05d$", tlbl->key + 100);
3558 emitcode ("mov", "a,%s", one);
3559 emitcode ("", "%05d$:", tlbl->key + 100);
3564 /*-----------------------------------------------------------------*/
3565 /* genPlusBits - generates code for addition of two bits */
3566 /*-----------------------------------------------------------------*/
3568 genPlusBits (iCode * ic)
3570 D(emitcode ("; genPlusBits",""));
3572 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3574 symbol *lbl = newiTempLabel (NULL);
3575 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3576 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3577 emitcode ("cpl", "c");
3578 emitcode ("", "%05d$:", (lbl->key + 100));
3579 outBitC (IC_RESULT (ic));
3583 emitcode ("clr", "a");
3584 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3585 emitcode ("rlc", "a");
3586 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3587 emitcode ("addc", "a,#0x00");
3588 outAcc (IC_RESULT (ic));
3593 /* This is the original version of this code.
3595 * This is being kept around for reference,
3596 * because I am not entirely sure I got it right...
3599 adjustArithmeticResult (iCode * ic)
3601 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3602 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3603 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3604 aopPut (AOP (IC_RESULT (ic)),
3605 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3607 isOperandVolatile (IC_RESULT (ic), FALSE));
3609 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3610 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3611 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3612 aopPut (AOP (IC_RESULT (ic)),
3613 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3615 isOperandVolatile (IC_RESULT (ic), FALSE));
3617 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3618 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3619 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3620 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3621 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3624 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3625 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3629 /* This is the pure and virtuous version of this code.
3630 * I'm pretty certain it's right, but not enough to toss the old
3634 adjustArithmeticResult (iCode * ic)
3636 if (opIsGptr (IC_RESULT (ic)) &&
3637 opIsGptr (IC_LEFT (ic)) &&
3638 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3640 aopPut (AOP (IC_RESULT (ic)),
3641 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3643 isOperandVolatile (IC_RESULT (ic), FALSE));
3646 if (opIsGptr (IC_RESULT (ic)) &&
3647 opIsGptr (IC_RIGHT (ic)) &&
3648 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3650 aopPut (AOP (IC_RESULT (ic)),
3651 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3653 isOperandVolatile (IC_RESULT (ic), FALSE));
3656 if (opIsGptr (IC_RESULT (ic)) &&
3657 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3658 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3659 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3660 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3663 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3664 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3669 /*-----------------------------------------------------------------*/
3670 /* genPlus - generates code for addition */
3671 /*-----------------------------------------------------------------*/
3673 genPlus (iCode * ic)
3675 int size, offset = 0;
3678 asmop *leftOp, *rightOp;
3681 /* special cases :- */
3683 D(emitcode ("; genPlus",""));
3685 aopOp (IC_LEFT (ic), ic, FALSE);
3686 aopOp (IC_RIGHT (ic), ic, FALSE);
3687 aopOp (IC_RESULT (ic), ic, TRUE);
3689 /* if literal, literal on the right or
3690 if left requires ACC or right is already
3692 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3693 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3694 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3696 operand *t = IC_RIGHT (ic);
3697 IC_RIGHT (ic) = IC_LEFT (ic);
3701 /* if both left & right are in bit
3703 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3704 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3710 /* if left in bit space & right literal */
3711 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3712 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3714 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3715 /* if result in bit space */
3716 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3718 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3719 emitcode ("cpl", "c");
3720 outBitC (IC_RESULT (ic));
3724 size = getDataSize (IC_RESULT (ic));
3727 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3728 emitcode ("addc", "a,#00");
3729 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3735 /* if I can do an increment instead
3736 of add then GOOD for ME */
3737 if (genPlusIncr (ic) == TRUE)
3740 size = getDataSize (IC_RESULT (ic));
3741 leftOp = AOP(IC_LEFT(ic));
3742 rightOp = AOP(IC_RIGHT(ic));
3745 /* if this is an add for an array access
3746 at a 256 byte boundary */
3748 && AOP_TYPE (op) == AOP_IMMD
3750 && IS_SPEC (OP_SYM_ETYPE (op))
3751 && SPEC_ABSA (OP_SYM_ETYPE (op))
3752 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3755 D(emitcode ("; genPlus aligned array",""));
3756 aopPut (AOP (IC_RESULT (ic)),
3757 aopGet (rightOp, 0, FALSE, FALSE),
3759 isOperandVolatile (IC_RESULT (ic), FALSE));
3761 if( 1 == getDataSize (IC_RIGHT (ic)) )
3763 aopPut (AOP (IC_RESULT (ic)),
3764 aopGet (leftOp, 1, FALSE, FALSE),
3766 isOperandVolatile (IC_RESULT (ic), FALSE));
3770 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3771 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3772 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3777 /* if the lower bytes of a literal are zero skip the addition */
3778 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3780 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3781 (skip_bytes+1 < size))
3786 D(emitcode ("; genPlus shortcut",""));
3791 if( offset >= skip_bytes )
3793 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3796 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3798 emitcode("xch", "a,b");
3799 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3800 emitcode (add, "a,b");
3803 else if (aopGetUsesAcc (leftOp, offset))
3805 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3806 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3810 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3811 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3813 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3814 add = "addc"; /* further adds must propagate carry */
3818 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3819 isOperandVolatile (IC_RESULT (ic), FALSE))
3822 aopPut (AOP (IC_RESULT (ic)),
3823 aopGet (leftOp, offset, FALSE, FALSE),
3825 isOperandVolatile (IC_RESULT (ic), FALSE));
3831 adjustArithmeticResult (ic);
3834 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3835 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3836 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3839 /*-----------------------------------------------------------------*/
3840 /* genMinusDec :- does subtraction with deccrement if possible */
3841 /*-----------------------------------------------------------------*/
3843 genMinusDec (iCode * ic)
3845 unsigned int icount;
3846 unsigned int size = getDataSize (IC_RESULT (ic));
3848 /* will try to generate an increment */
3849 /* if the right side is not a literal
3851 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3854 /* if the literal value of the right hand side
3855 is greater than 4 then it is not worth it */
3856 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3859 D(emitcode ("; genMinusDec",""));
3861 /* if decrement >=16 bits in register or direct space */
3862 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3863 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3871 /* If the next instruction is a goto and the goto target
3872 * is <= 10 instructions previous to this, we can generate
3873 * jumps straight to that target.
3875 if (ic->next && ic->next->op == GOTO
3876 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3877 && labelRange <= 10)
3879 emitcode (";", "tail decrement optimized");
3880 tlbl = IC_LABEL (ic->next);
3885 tlbl = newiTempLabel (NULL);
3889 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3890 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3891 IS_AOP_PREG (IC_RESULT (ic)))
3892 emitcode ("cjne", "%s,#0xff,%05d$"
3893 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3897 emitcode ("mov", "a,#0xff");
3898 emitcode ("cjne", "a,%s,%05d$"
3899 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3902 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3905 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3906 IS_AOP_PREG (IC_RESULT (ic)))
3907 emitcode ("cjne", "%s,#0xff,%05d$"
3908 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3912 emitcode ("cjne", "a,%s,%05d$"
3913 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3916 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3921 IS_AOP_PREG (IC_RESULT (ic)))
3922 emitcode ("cjne", "%s,#0xff,%05d$"
3923 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3927 emitcode ("cjne", "a,%s,%05d$"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3931 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3935 emitcode ("", "%05d$:", tlbl->key + 100);
3940 /* if the sizes are greater than 1 then we cannot */
3941 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942 AOP_SIZE (IC_LEFT (ic)) > 1)
3945 /* we can if the aops of the left & result match or
3946 if they are in registers and the registers are the
3948 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3952 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3960 /*-----------------------------------------------------------------*/
3961 /* addSign - complete with sign */
3962 /*-----------------------------------------------------------------*/
3964 addSign (operand * result, int offset, int sign)
3966 int size = (getDataSize (result) - offset);
3971 emitcode ("rlc", "a");
3972 emitcode ("subb", "a,acc");
3974 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3978 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3982 /*-----------------------------------------------------------------*/
3983 /* genMinusBits - generates code for subtraction of two bits */
3984 /*-----------------------------------------------------------------*/
3986 genMinusBits (iCode * ic)
3988 symbol *lbl = newiTempLabel (NULL);
3990 D(emitcode ("; genMinusBits",""));
3992 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3994 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3995 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3996 emitcode ("cpl", "c");
3997 emitcode ("", "%05d$:", (lbl->key + 100));
3998 outBitC (IC_RESULT (ic));
4002 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4003 emitcode ("subb", "a,acc");
4004 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4005 emitcode ("inc", "a");
4006 emitcode ("", "%05d$:", (lbl->key + 100));
4007 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4008 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4012 /*-----------------------------------------------------------------*/
4013 /* genMinus - generates code for subtraction */
4014 /*-----------------------------------------------------------------*/
4016 genMinus (iCode * ic)
4018 int size, offset = 0;
4020 D(emitcode ("; genMinus",""));
4022 aopOp (IC_LEFT (ic), ic, FALSE);
4023 aopOp (IC_RIGHT (ic), ic, FALSE);
4024 aopOp (IC_RESULT (ic), ic, TRUE);
4026 /* special cases :- */
4027 /* if both left & right are in bit space */
4028 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4029 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4035 /* if I can do an decrement instead
4036 of subtract then GOOD for ME */
4037 if (genMinusDec (ic) == TRUE)
4040 size = getDataSize (IC_RESULT (ic));
4042 /* if literal, add a,#-lit, else normal subb */
4043 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4045 unsigned long lit = 0L;
4047 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4052 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4053 /* first add without previous c */
4055 if (!size && lit== (unsigned long) -1) {
4056 emitcode ("dec", "a");
4058 emitcode ("add", "a,#0x%02x",
4059 (unsigned int) (lit & 0x0FFL));
4062 emitcode ("addc", "a,#0x%02x",
4063 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4065 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4070 asmop *leftOp, *rightOp;
4072 leftOp = AOP(IC_LEFT(ic));
4073 rightOp = AOP(IC_RIGHT(ic));
4077 if (aopGetUsesAcc(rightOp, offset)) {
4078 if (aopGetUsesAcc(leftOp, offset)) {
4081 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4083 emitcode ("mov", "b,a");
4086 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4087 emitcode ("subb", "a,b");
4090 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4091 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4093 emitcode( "setb", "c");
4095 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4096 emitcode("cpl", "a");
4099 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4102 emitcode ("subb", "a,%s",
4103 aopGet(rightOp, offset, FALSE, TRUE));
4106 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4111 adjustArithmeticResult (ic);
4114 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4115 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4120 /*-----------------------------------------------------------------*/
4121 /* genMultbits :- multiplication of bits */
4122 /*-----------------------------------------------------------------*/
4124 genMultbits (operand * left,
4128 D(emitcode ("; genMultbits",""));
4130 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4131 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4135 /*-----------------------------------------------------------------*/
4136 /* genMultOneByte : 8*8=8/16 bit multiplication */
4137 /*-----------------------------------------------------------------*/
4139 genMultOneByte (operand * left,
4144 int size = AOP_SIZE (result);
4145 bool runtimeSign, compiletimeSign;
4146 bool lUnsigned, rUnsigned, pushedB;
4148 D(emitcode ("; genMultOneByte",""));
4150 if (size < 1 || size > 2)
4152 /* this should never happen */
4153 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4154 AOP_SIZE(result), __FILE__, lineno);
4158 /* (if two literals: the value is computed before) */
4159 /* if one literal, literal on the right */
4160 if (AOP_TYPE (left) == AOP_LIT)
4165 /* emitcode (";", "swapped left and right"); */
4167 /* if no literal, unsigned on the right: shorter code */
4168 if ( AOP_TYPE (right) != AOP_LIT
4169 && SPEC_USIGN (getSpec (operandType (left))))
4176 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4177 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4181 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4182 no need to take care about the signedness! */
4183 || (lUnsigned && rUnsigned))
4185 /* just an unsigned 8 * 8 = 8 multiply
4187 /* emitcode (";","unsigned"); */
4188 /* TODO: check for accumulator clash between left & right aops? */
4190 if (AOP_TYPE (right) == AOP_LIT)
4192 /* moving to accumulator first helps peepholes */
4193 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4194 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4198 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4199 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4202 emitcode ("mul", "ab");
4203 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4205 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4211 /* we have to do a signed multiply */
4212 /* emitcode (";", "signed"); */
4214 /* now sign adjust for both left & right */
4216 /* let's see what's needed: */
4217 /* apply negative sign during runtime */
4218 runtimeSign = FALSE;
4219 /* negative sign from literals */
4220 compiletimeSign = FALSE;
4224 if (AOP_TYPE(left) == AOP_LIT)
4226 /* signed literal */
4227 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4229 compiletimeSign = TRUE;
4232 /* signed but not literal */
4238 if (AOP_TYPE(right) == AOP_LIT)
4240 /* signed literal */
4241 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4243 compiletimeSign ^= TRUE;
4246 /* signed but not literal */
4250 /* initialize F0, which stores the runtime sign */
4253 if (compiletimeSign)
4254 emitcode ("setb", "F0"); /* set sign flag */
4256 emitcode ("clr", "F0"); /* reset sign flag */
4259 /* save the signs of the operands */
4260 if (AOP_TYPE(right) == AOP_LIT)
4262 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4264 if (!rUnsigned && val < 0)
4265 emitcode ("mov", "b,#0x%02x", -val);
4267 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4269 else /* ! literal */
4271 if (rUnsigned) /* emitcode (";", "signed"); */
4273 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4276 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4277 lbl = newiTempLabel (NULL);
4278 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4279 emitcode ("cpl", "F0"); /* complement sign flag */
4280 emitcode ("cpl", "a"); /* 2's complement */
4281 emitcode ("inc", "a");
4282 emitcode ("", "%05d$:", (lbl->key + 100));
4283 emitcode ("mov", "b,a");
4287 if (AOP_TYPE(left) == AOP_LIT)
4289 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4291 if (!lUnsigned && val < 0)
4292 emitcode ("mov", "a,#0x%02x", -val);
4294 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4296 else /* ! literal */
4298 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4302 lbl = newiTempLabel (NULL);
4303 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4304 emitcode ("cpl", "F0"); /* complement sign flag */
4305 emitcode ("cpl", "a"); /* 2's complement */
4306 emitcode ("inc", "a");
4307 emitcode ("", "%05d$:", (lbl->key + 100));
4311 /* now the multiplication */
4312 emitcode ("mul", "ab");
4313 if (runtimeSign || compiletimeSign)
4315 lbl = newiTempLabel (NULL);
4317 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4318 emitcode ("cpl", "a"); /* lsb 2's complement */
4320 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4323 emitcode ("add", "a,#1"); /* this sets carry flag */
4324 emitcode ("xch", "a,b");
4325 emitcode ("cpl", "a"); /* msb 2's complement */
4326 emitcode ("addc", "a,#0");
4327 emitcode ("xch", "a,b");
4329 emitcode ("", "%05d$:", (lbl->key + 100));
4331 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4333 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4338 /*-----------------------------------------------------------------*/
4339 /* genMult - generates code for multiplication */
4340 /*-----------------------------------------------------------------*/
4342 genMult (iCode * ic)
4344 operand *left = IC_LEFT (ic);
4345 operand *right = IC_RIGHT (ic);
4346 operand *result = IC_RESULT (ic);
4348 D(emitcode ("; genMult",""));
4350 /* assign the amsops */
4351 aopOp (left, ic, FALSE);
4352 aopOp (right, ic, FALSE);
4353 aopOp (result, ic, TRUE);
4355 /* special cases first */
4357 if (AOP_TYPE (left) == AOP_CRY &&
4358 AOP_TYPE (right) == AOP_CRY)
4360 genMultbits (left, right, result);
4364 /* if both are of size == 1 */
4365 #if 0 // one of them can be a sloc shared with the result
4366 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4368 if (getSize(operandType(left)) == 1 &&
4369 getSize(operandType(right)) == 1)
4372 genMultOneByte (left, right, result);
4376 /* should have been converted to function call */
4377 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4378 getSize(OP_SYMBOL(right)->type));
4382 freeAsmop (result, NULL, ic, TRUE);
4383 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4384 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4387 /*-----------------------------------------------------------------*/
4388 /* genDivbits :- division of bits */
4389 /*-----------------------------------------------------------------*/
4391 genDivbits (operand * left,
4398 D(emitcode ("; genDivbits",""));
4402 /* the result must be bit */
4403 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4404 l = aopGet (AOP (left), 0, FALSE, FALSE);
4408 emitcode ("div", "ab");
4409 emitcode ("rrc", "a");
4413 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4416 /*-----------------------------------------------------------------*/
4417 /* genDivOneByte : 8 bit division */
4418 /*-----------------------------------------------------------------*/
4420 genDivOneByte (operand * left,
4424 bool lUnsigned, rUnsigned, pushedB;
4425 bool runtimeSign, compiletimeSign;
4429 D(emitcode ("; genDivOneByte",""));
4431 /* Why is it necessary that genDivOneByte() can return an int result?
4434 volatile unsigned char uc;
4435 volatile signed char sc1, sc2;
4448 In all cases a one byte result would overflow, the following cast to int
4449 would return the wrong result.
4451 Two possible solution:
4452 a) cast operands to int, if ((unsigned) / (signed)) or
4453 ((signed) / (signed))
4454 b) return an 16 bit signed int; this is what we're doing here!
4457 size = AOP_SIZE (result) - 1;
4459 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4460 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4464 /* signed or unsigned */
4465 if (lUnsigned && rUnsigned)
4467 /* unsigned is easy */
4468 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4469 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4470 emitcode ("div", "ab");
4471 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4473 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4479 /* signed is a little bit more difficult */
4481 /* now sign adjust for both left & right */
4483 /* let's see what's needed: */
4484 /* apply negative sign during runtime */
4485 runtimeSign = FALSE;
4486 /* negative sign from literals */
4487 compiletimeSign = FALSE;
4491 if (AOP_TYPE(left) == AOP_LIT)
4493 /* signed literal */
4494 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4496 compiletimeSign = TRUE;
4499 /* signed but not literal */
4505 if (AOP_TYPE(right) == AOP_LIT)
4507 /* signed literal */
4508 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4510 compiletimeSign ^= TRUE;
4513 /* signed but not literal */
4517 /* initialize F0, which stores the runtime sign */
4520 if (compiletimeSign)
4521 emitcode ("setb", "F0"); /* set sign flag */
4523 emitcode ("clr", "F0"); /* reset sign flag */
4526 /* save the signs of the operands */
4527 if (AOP_TYPE(right) == AOP_LIT)
4529 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4531 if (!rUnsigned && val < 0)
4532 emitcode ("mov", "b,#0x%02x", -val);
4534 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4536 else /* ! literal */
4539 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4542 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4543 lbl = newiTempLabel (NULL);
4544 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4545 emitcode ("cpl", "F0"); /* complement sign flag */
4546 emitcode ("cpl", "a"); /* 2's complement */
4547 emitcode ("inc", "a");
4548 emitcode ("", "%05d$:", (lbl->key + 100));
4549 emitcode ("mov", "b,a");
4553 if (AOP_TYPE(left) == AOP_LIT)
4555 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4557 if (!lUnsigned && val < 0)
4558 emitcode ("mov", "a,#0x%02x", -val);
4560 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4562 else /* ! literal */
4564 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4568 lbl = newiTempLabel (NULL);
4569 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4570 emitcode ("cpl", "F0"); /* complement sign flag */
4571 emitcode ("cpl", "a"); /* 2's complement */
4572 emitcode ("inc", "a");
4573 emitcode ("", "%05d$:", (lbl->key + 100));
4577 /* now the division */
4578 emitcode ("div", "ab");
4580 if (runtimeSign || compiletimeSign)
4582 lbl = newiTempLabel (NULL);
4584 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4585 emitcode ("cpl", "a"); /* lsb 2's complement */
4586 emitcode ("inc", "a");
4587 emitcode ("", "%05d$:", (lbl->key + 100));
4589 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4592 /* msb is 0x00 or 0xff depending on the sign */
4595 emitcode ("mov", "c,F0");
4596 emitcode ("subb", "a,acc");
4598 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4600 else /* compiletimeSign */
4602 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4607 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4609 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4615 /*-----------------------------------------------------------------*/
4616 /* genDiv - generates code for division */
4617 /*-----------------------------------------------------------------*/
4621 operand *left = IC_LEFT (ic);
4622 operand *right = IC_RIGHT (ic);
4623 operand *result = IC_RESULT (ic);
4625 D(emitcode ("; genDiv",""));
4627 /* assign the amsops */
4628 aopOp (left, ic, FALSE);
4629 aopOp (right, ic, FALSE);
4630 aopOp (result, ic, TRUE);
4632 /* special cases first */
4634 if (AOP_TYPE (left) == AOP_CRY &&
4635 AOP_TYPE (right) == AOP_CRY)
4637 genDivbits (left, right, result);
4641 /* if both are of size == 1 */
4642 if (AOP_SIZE (left) == 1 &&
4643 AOP_SIZE (right) == 1)
4645 genDivOneByte (left, right, result);
4649 /* should have been converted to function call */
4652 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4654 freeAsmop (result, NULL, ic, TRUE);
4657 /*-----------------------------------------------------------------*/
4658 /* genModbits :- modulus of bits */
4659 /*-----------------------------------------------------------------*/
4661 genModbits (operand * left,
4668 D(emitcode ("; genModbits",""));
4672 /* the result must be bit */
4673 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4674 l = aopGet (AOP (left), 0, FALSE, FALSE);
4678 emitcode ("div", "ab");
4679 emitcode ("mov", "a,b");
4680 emitcode ("rrc", "a");
4684 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4687 /*-----------------------------------------------------------------*/
4688 /* genModOneByte : 8 bit modulus */
4689 /*-----------------------------------------------------------------*/
4691 genModOneByte (operand * left,
4695 bool lUnsigned, rUnsigned, pushedB;
4696 bool runtimeSign, compiletimeSign;
4700 D(emitcode ("; genModOneByte",""));
4702 size = AOP_SIZE (result) - 1;
4704 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4705 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4707 /* if right is a literal, check it for 2^n */
4708 if (AOP_TYPE(right) == AOP_LIT)
4710 unsigned char val = abs(operandLitValue(right));
4711 symbol *lbl2 = NULL;
4715 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4724 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4725 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4726 /* because iCode should have been changed to genAnd */
4727 /* see file "SDCCopt.c", function "convertToFcall()" */
4729 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4730 emitcode ("mov", "c,acc.7");
4731 emitcode ("anl", "a,#0x%02x", val - 1);
4732 lbl = newiTempLabel (NULL);
4733 emitcode ("jz", "%05d$", (lbl->key + 100));
4734 emitcode ("jnc", "%05d$", (lbl->key + 100));
4735 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4741 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4743 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4744 lbl2 = newiTempLabel (NULL);
4745 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4747 emitcode ("", "%05d$:", (lbl->key + 100));
4748 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4750 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4753 emitcode ("", "%05d$:", (lbl2->key + 100));
4764 /* signed or unsigned */
4765 if (lUnsigned && rUnsigned)
4767 /* unsigned is easy */
4768 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4769 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4770 emitcode ("div", "ab");
4771 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4773 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4779 /* signed is a little bit more difficult */
4781 /* now sign adjust for both left & right */
4783 /* modulus: sign of the right operand has no influence on the result! */
4784 if (AOP_TYPE(right) == AOP_LIT)
4786 signed char val = (char) operandLitValue(right);
4788 if (!rUnsigned && val < 0)
4789 emitcode ("mov", "b,#0x%02x", -val);
4791 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4793 else /* not literal */
4796 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4799 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4800 lbl = newiTempLabel (NULL);
4801 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4802 emitcode ("cpl", "a"); /* 2's complement */
4803 emitcode ("inc", "a");
4804 emitcode ("", "%05d$:", (lbl->key + 100));
4805 emitcode ("mov", "b,a");
4809 /* let's see what's needed: */
4810 /* apply negative sign during runtime */
4811 runtimeSign = FALSE;
4812 /* negative sign from literals */
4813 compiletimeSign = FALSE;
4815 /* sign adjust left side */
4816 if (AOP_TYPE(left) == AOP_LIT)
4818 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4820 if (!lUnsigned && val < 0)
4822 compiletimeSign = TRUE; /* set sign flag */
4823 emitcode ("mov", "a,#0x%02x", -val);
4826 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4828 else /* ! literal */
4830 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4835 emitcode ("clr", "F0"); /* clear sign flag */
4837 lbl = newiTempLabel (NULL);
4838 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4839 emitcode ("setb", "F0"); /* set sign flag */
4840 emitcode ("cpl", "a"); /* 2's complement */
4841 emitcode ("inc", "a");
4842 emitcode ("", "%05d$:", (lbl->key + 100));
4846 /* now the modulus */
4847 emitcode ("div", "ab");
4849 if (runtimeSign || compiletimeSign)
4851 emitcode ("mov", "a,b");
4852 lbl = newiTempLabel (NULL);
4854 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4855 emitcode ("cpl", "a"); /* 2's complement */
4856 emitcode ("inc", "a");
4857 emitcode ("", "%05d$:", (lbl->key + 100));
4859 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4862 /* msb is 0x00 or 0xff depending on the sign */
4865 emitcode ("mov", "c,F0");
4866 emitcode ("subb", "a,acc");
4868 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4870 else /* compiletimeSign */
4872 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4877 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4879 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4885 /*-----------------------------------------------------------------*/
4886 /* genMod - generates code for division */
4887 /*-----------------------------------------------------------------*/
4891 operand *left = IC_LEFT (ic);
4892 operand *right = IC_RIGHT (ic);
4893 operand *result = IC_RESULT (ic);
4895 D(emitcode ("; genMod",""));
4897 /* assign the asmops */
4898 aopOp (left, ic, FALSE);
4899 aopOp (right, ic, FALSE);
4900 aopOp (result, ic, TRUE);
4902 /* special cases first */
4904 if (AOP_TYPE (left) == AOP_CRY &&
4905 AOP_TYPE (right) == AOP_CRY)
4907 genModbits (left, right, result);
4911 /* if both are of size == 1 */
4912 if (AOP_SIZE (left) == 1 &&
4913 AOP_SIZE (right) == 1)
4915 genModOneByte (left, right, result);
4919 /* should have been converted to function call */
4923 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (result, NULL, ic, TRUE);
4928 /*-----------------------------------------------------------------*/
4929 /* genIfxJump :- will create a jump depending on the ifx */
4930 /*-----------------------------------------------------------------*/
4932 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4935 symbol *tlbl = newiTempLabel (NULL);
4938 D(emitcode ("; genIfxJump",""));
4940 /* if true label then we jump if condition
4944 jlbl = IC_TRUE (ic);
4945 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4946 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4950 /* false label is present */
4951 jlbl = IC_FALSE (ic);
4952 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4953 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4955 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4956 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4958 emitcode (inst, "%05d$", tlbl->key + 100);
4959 freeForBranchAsmop (result);
4960 freeForBranchAsmop (right);
4961 freeForBranchAsmop (left);
4962 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4963 emitcode ("", "%05d$:", tlbl->key + 100);
4965 /* mark the icode as generated */
4969 /*-----------------------------------------------------------------*/
4970 /* genCmp :- greater or less than comparison */
4971 /*-----------------------------------------------------------------*/
4973 genCmp (operand * left, operand * right,
4974 operand * result, iCode * ifx, int sign, iCode *ic)
4976 int size, offset = 0;
4977 unsigned long lit = 0L;
4980 D(emitcode ("; genCmp",""));
4982 /* if left & right are bit variables */
4983 if (AOP_TYPE (left) == AOP_CRY &&
4984 AOP_TYPE (right) == AOP_CRY)
4986 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4987 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4991 /* subtract right from left if at the
4992 end the carry flag is set then we know that
4993 left is greater than right */
4994 size = max (AOP_SIZE (left), AOP_SIZE (right));
4996 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4997 if ((size == 1) && !sign &&
4998 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5000 symbol *lbl = newiTempLabel (NULL);
5001 emitcode ("cjne", "%s,%s,%05d$",
5002 aopGet (AOP (left), offset, FALSE, FALSE),
5003 aopGet (AOP (right), offset, FALSE, FALSE),
5005 emitcode ("", "%05d$:", lbl->key + 100);
5009 if (AOP_TYPE (right) == AOP_LIT)
5011 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5012 /* optimize if(x < 0) or if(x >= 0) */
5021 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5022 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5024 genIfxJump (ifx, "acc.7", left, right, result);
5025 freeAsmop (right, NULL, ic, TRUE);
5026 freeAsmop (left, NULL, ic, TRUE);
5031 emitcode ("rlc", "a");
5039 bool pushedB = FALSE;
5040 rightInB = aopGetUsesAcc(AOP (right), offset);
5044 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5046 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5047 if (sign && size == 0)
5049 emitcode ("xrl", "a,#0x80");
5050 if (AOP_TYPE (right) == AOP_LIT)
5052 unsigned long lit = (unsigned long)
5053 floatFromVal (AOP (right)->aopu.aop_lit);
5054 emitcode ("subb", "a,#0x%02x",
5055 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5063 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5065 emitcode ("xrl", "b,#0x80");
5066 emitcode ("subb", "a,b");
5072 emitcode ("subb", "a,b");
5074 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5084 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5092 /* if the result is used in the next
5093 ifx conditional branch then generate
5094 code a little differently */
5096 genIfxJump (ifx, "c", NULL, NULL, result);
5099 /* leave the result in acc */
5103 /*-----------------------------------------------------------------*/
5104 /* genCmpGt :- greater than comparison */
5105 /*-----------------------------------------------------------------*/
5107 genCmpGt (iCode * ic, iCode * ifx)
5109 operand *left, *right, *result;
5110 sym_link *letype, *retype;
5113 D(emitcode ("; genCmpGt",""));
5115 left = IC_LEFT (ic);
5116 right = IC_RIGHT (ic);
5117 result = IC_RESULT (ic);
5119 letype = getSpec (operandType (left));
5120 retype = getSpec (operandType (right));
5121 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5122 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5123 /* assign the amsops */
5124 aopOp (left, ic, FALSE);
5125 aopOp (right, ic, FALSE);
5126 aopOp (result, ic, TRUE);
5128 genCmp (right, left, result, ifx, sign, ic);
5130 freeAsmop (result, NULL, ic, TRUE);
5133 /*-----------------------------------------------------------------*/
5134 /* genCmpLt - less than comparisons */
5135 /*-----------------------------------------------------------------*/
5137 genCmpLt (iCode * ic, iCode * ifx)
5139 operand *left, *right, *result;
5140 sym_link *letype, *retype;
5143 D(emitcode ("; genCmpLt",""));
5145 left = IC_LEFT (ic);
5146 right = IC_RIGHT (ic);
5147 result = IC_RESULT (ic);
5149 letype = getSpec (operandType (left));
5150 retype = getSpec (operandType (right));
5151 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5152 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5153 /* assign the amsops */
5154 aopOp (left, ic, FALSE);
5155 aopOp (right, ic, FALSE);
5156 aopOp (result, ic, TRUE);
5158 genCmp (left, right, result, ifx, sign,ic);
5160 freeAsmop (result, NULL, ic, TRUE);
5163 /*-----------------------------------------------------------------*/
5164 /* gencjneshort - compare and jump if not equal */
5165 /*-----------------------------------------------------------------*/
5167 gencjneshort (operand * left, operand * right, symbol * lbl)
5169 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5171 unsigned long lit = 0L;
5173 /* if the left side is a literal or
5174 if the right is in a pointer register and left
5176 if ((AOP_TYPE (left) == AOP_LIT) ||
5177 (AOP_TYPE (left) == AOP_IMMD) ||
5178 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5185 if (AOP_TYPE (right) == AOP_LIT)
5186 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5188 /* if the right side is a literal then anything goes */
5189 if (AOP_TYPE (right) == AOP_LIT &&
5190 AOP_TYPE (left) != AOP_DIR &&
5191 AOP_TYPE (left) != AOP_IMMD)
5195 emitcode ("cjne", "%s,%s,%05d$",
5196 aopGet (AOP (left), offset, FALSE, FALSE),
5197 aopGet (AOP (right), offset, FALSE, FALSE),
5203 /* if the right side is in a register or in direct space or
5204 if the left is a pointer register & right is not */
5205 else if (AOP_TYPE (right) == AOP_REG ||
5206 AOP_TYPE (right) == AOP_DIR ||
5207 AOP_TYPE (right) == AOP_LIT ||
5208 AOP_TYPE (right) == AOP_IMMD ||
5209 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5210 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5214 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5215 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5216 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5217 emitcode ("jnz", "%05d$", lbl->key + 100);
5219 emitcode ("cjne", "a,%s,%05d$",
5220 aopGet (AOP (right), offset, FALSE, TRUE),
5227 /* right is a pointer reg need both a & b */
5231 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5232 wassertl(!_G.BInUse, "B was in use");
5233 l = aopGet (AOP (left), offset, FALSE, FALSE);
5234 if (strcmp (l, "b"))
5235 emitcode ("mov", "b,%s", l);
5236 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5237 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5243 /*-----------------------------------------------------------------*/
5244 /* gencjne - compare and jump if not equal */
5245 /*-----------------------------------------------------------------*/
5247 gencjne (operand * left, operand * right, symbol * lbl)
5249 symbol *tlbl = newiTempLabel (NULL);
5251 gencjneshort (left, right, lbl);
5253 emitcode ("mov", "a,%s", one);
5254 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5255 emitcode ("", "%05d$:", lbl->key + 100);
5256 emitcode ("clr", "a");
5257 emitcode ("", "%05d$:", tlbl->key + 100);
5260 /*-----------------------------------------------------------------*/
5261 /* genCmpEq - generates code for equal to */
5262 /*-----------------------------------------------------------------*/
5264 genCmpEq (iCode * ic, iCode * ifx)
5266 operand *left, *right, *result;
5268 D(emitcode ("; genCmpEq",""));
5270 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5271 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5272 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5274 /* if literal, literal on the right or
5275 if the right is in a pointer register and left
5277 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5278 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5280 operand *t = IC_RIGHT (ic);
5281 IC_RIGHT (ic) = IC_LEFT (ic);
5285 if (ifx && !AOP_SIZE (result))
5288 /* if they are both bit variables */
5289 if (AOP_TYPE (left) == AOP_CRY &&
5290 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5292 if (AOP_TYPE (right) == AOP_LIT)
5294 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5297 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5298 emitcode ("cpl", "c");
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5306 emitcode ("clr", "c");
5308 /* AOP_TYPE(right) == AOP_CRY */
5312 symbol *lbl = newiTempLabel (NULL);
5313 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5314 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5315 emitcode ("cpl", "c");
5316 emitcode ("", "%05d$:", (lbl->key + 100));
5318 /* if true label then we jump if condition
5320 tlbl = newiTempLabel (NULL);
5323 emitcode ("jnc", "%05d$", tlbl->key + 100);
5324 freeForBranchAsmop (result);
5325 freeForBranchAsmop (right);
5326 freeForBranchAsmop (left);
5327 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5331 emitcode ("jc", "%05d$", tlbl->key + 100);
5332 freeForBranchAsmop (result);
5333 freeForBranchAsmop (right);
5334 freeForBranchAsmop (left);
5335 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5337 emitcode ("", "%05d$:", tlbl->key + 100);
5341 tlbl = newiTempLabel (NULL);
5342 gencjneshort (left, right, tlbl);
5345 freeForBranchAsmop (result);
5346 freeForBranchAsmop (right);
5347 freeForBranchAsmop (left);
5348 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5349 emitcode ("", "%05d$:", tlbl->key + 100);
5353 symbol *lbl = newiTempLabel (NULL);
5354 emitcode ("sjmp", "%05d$", lbl->key + 100);
5355 emitcode ("", "%05d$:", tlbl->key + 100);
5356 freeForBranchAsmop (result);
5357 freeForBranchAsmop (right);
5358 freeForBranchAsmop (left);
5359 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5360 emitcode ("", "%05d$:", lbl->key + 100);
5363 /* mark the icode as generated */
5368 /* if they are both bit variables */
5369 if (AOP_TYPE (left) == AOP_CRY &&
5370 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5372 if (AOP_TYPE (right) == AOP_LIT)
5374 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5377 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5378 emitcode ("cpl", "c");
5382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5386 emitcode ("clr", "c");
5388 /* AOP_TYPE(right) == AOP_CRY */
5392 symbol *lbl = newiTempLabel (NULL);
5393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5394 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5395 emitcode ("cpl", "c");
5396 emitcode ("", "%05d$:", (lbl->key + 100));
5399 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5406 genIfxJump (ifx, "c", left, right, result);
5409 /* if the result is used in an arithmetic operation
5410 then put the result in place */
5415 gencjne (left, right, newiTempLabel (NULL));
5416 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5418 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5423 genIfxJump (ifx, "a", left, right, result);
5426 /* if the result is used in an arithmetic operation
5427 then put the result in place */
5428 if (AOP_TYPE (result) != AOP_CRY)
5430 /* leave the result in acc */
5434 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5435 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5436 freeAsmop (result, NULL, ic, TRUE);
5439 /*-----------------------------------------------------------------*/
5440 /* ifxForOp - returns the icode containing the ifx for operand */
5441 /*-----------------------------------------------------------------*/
5443 ifxForOp (operand * op, iCode * ic)
5445 /* if true symbol then needs to be assigned */
5446 if (IS_TRUE_SYMOP (op))
5449 /* if this has register type condition and
5450 the next instruction is ifx with the same operand
5451 and live to of the operand is upto the ifx only then */
5453 ic->next->op == IFX &&
5454 IC_COND (ic->next)->key == op->key &&
5455 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5461 /*-----------------------------------------------------------------*/
5462 /* hasInc - operand is incremented before any other use */
5463 /*-----------------------------------------------------------------*/
5465 hasInc (operand *op, iCode *ic,int osize)
5467 sym_link *type = operandType(op);
5468 sym_link *retype = getSpec (type);
5469 iCode *lic = ic->next;
5472 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5473 if (!IS_SYMOP(op)) return NULL;
5475 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5476 if (IS_AGGREGATE(type->next)) return NULL;
5477 if (osize != (isize = getSize(type->next))) return NULL;
5480 /* if operand of the form op = op + <sizeof *op> */
5481 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5482 isOperandEqual(IC_RESULT(lic),op) &&
5483 isOperandLiteral(IC_RIGHT(lic)) &&
5484 operandLitValue(IC_RIGHT(lic)) == isize) {
5487 /* if the operand used or deffed */
5488 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5491 /* if GOTO or IFX */
5492 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5498 /*-----------------------------------------------------------------*/
5499 /* genAndOp - for && operation */
5500 /*-----------------------------------------------------------------*/
5502 genAndOp (iCode * ic)
5504 operand *left, *right, *result;
5507 D(emitcode ("; genAndOp",""));
5509 /* note here that && operations that are in an
5510 if statement are taken away by backPatchLabels
5511 only those used in arthmetic operations remain */
5512 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5513 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5514 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5516 /* if both are bit variables */
5517 if (AOP_TYPE (left) == AOP_CRY &&
5518 AOP_TYPE (right) == AOP_CRY)
5520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5521 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5526 tlbl = newiTempLabel (NULL);
5528 emitcode ("jz", "%05d$", tlbl->key + 100);
5530 emitcode ("", "%05d$:", tlbl->key + 100);
5534 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5535 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536 freeAsmop (result, NULL, ic, TRUE);
5540 /*-----------------------------------------------------------------*/
5541 /* genOrOp - for || operation */
5542 /*-----------------------------------------------------------------*/
5544 genOrOp (iCode * ic)
5546 operand *left, *right, *result;
5549 D(emitcode ("; genOrOp",""));
5551 /* note here that || operations that are in an
5552 if statement are taken away by backPatchLabels
5553 only those used in arthmetic operations remain */
5554 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5556 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5558 /* if both are bit variables */
5559 if (AOP_TYPE (left) == AOP_CRY &&
5560 AOP_TYPE (right) == AOP_CRY)
5562 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5563 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5568 tlbl = newiTempLabel (NULL);
5570 emitcode ("jnz", "%05d$", tlbl->key + 100);
5572 emitcode ("", "%05d$:", tlbl->key + 100);
5576 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5577 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5578 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* isLiteralBit - test if lit == 2^n */
5583 /*-----------------------------------------------------------------*/
5585 isLiteralBit (unsigned long lit)
5587 unsigned long pw[32] =
5588 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5589 0x100L, 0x200L, 0x400L, 0x800L,
5590 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5591 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5592 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5593 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5594 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5597 for (idx = 0; idx < 32; idx++)
5603 /*-----------------------------------------------------------------*/
5604 /* continueIfTrue - */
5605 /*-----------------------------------------------------------------*/
5607 continueIfTrue (iCode * ic)
5610 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5614 /*-----------------------------------------------------------------*/
5616 /*-----------------------------------------------------------------*/
5618 jumpIfTrue (iCode * ic)
5621 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5625 /*-----------------------------------------------------------------*/
5626 /* jmpTrueOrFalse - */
5627 /*-----------------------------------------------------------------*/
5629 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5631 // ugly but optimized by peephole
5634 symbol *nlbl = newiTempLabel (NULL);
5635 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5636 emitcode ("", "%05d$:", tlbl->key + 100);
5637 freeForBranchAsmop (result);
5638 freeForBranchAsmop (right);
5639 freeForBranchAsmop (left);
5640 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5641 emitcode ("", "%05d$:", nlbl->key + 100);
5645 freeForBranchAsmop (result);
5646 freeForBranchAsmop (right);
5647 freeForBranchAsmop (left);
5648 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5649 emitcode ("", "%05d$:", tlbl->key + 100);
5654 /*-----------------------------------------------------------------*/
5655 /* genAnd - code for and */
5656 /*-----------------------------------------------------------------*/
5658 genAnd (iCode * ic, iCode * ifx)
5660 operand *left, *right, *result;
5661 int size, offset = 0;
5662 unsigned long lit = 0L;
5666 D(emitcode ("; genAnd",""));
5668 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5669 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5670 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5673 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5675 AOP_TYPE (left), AOP_TYPE (right));
5676 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5678 AOP_SIZE (left), AOP_SIZE (right));
5681 /* if left is a literal & right is not then exchange them */
5682 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5683 AOP_NEEDSACC (left))
5685 operand *tmp = right;
5690 /* if result = right then exchange left and right */
5691 if (sameRegs (AOP (result), AOP (right)))
5693 operand *tmp = right;
5698 /* if right is bit then exchange them */
5699 if (AOP_TYPE (right) == AOP_CRY &&
5700 AOP_TYPE (left) != AOP_CRY)
5702 operand *tmp = right;
5706 if (AOP_TYPE (right) == AOP_LIT)
5707 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5709 size = AOP_SIZE (result);
5712 // result = bit & yy;
5713 if (AOP_TYPE (left) == AOP_CRY)
5715 // c = bit & literal;
5716 if (AOP_TYPE (right) == AOP_LIT)
5720 if (size && sameRegs (AOP (result), AOP (left)))
5723 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5728 if (size && (AOP_TYPE (result) == AOP_CRY))
5730 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5733 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5738 emitcode ("clr", "c");
5743 if (AOP_TYPE (right) == AOP_CRY)
5746 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5747 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5752 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5754 emitcode ("rrc", "a");
5755 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5763 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5764 genIfxJump (ifx, "c", left, right, result);
5768 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5769 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5770 if ((AOP_TYPE (right) == AOP_LIT) &&
5771 (AOP_TYPE (result) == AOP_CRY) &&
5772 (AOP_TYPE (left) != AOP_CRY))
5774 int posbit = isLiteralBit (lit);
5779 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5783 switch (posbit & 0x07)
5785 case 0: emitcode ("rrc", "a");
5787 case 7: emitcode ("rlc", "a");
5789 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5798 SNPRINTF (buffer, sizeof(buffer),
5799 "acc.%d", posbit & 0x07);
5800 genIfxJump (ifx, buffer, left, right, result);
5803 {// what is this case? just found it in ds390/gen.c
5804 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5811 symbol *tlbl = newiTempLabel (NULL);
5812 int sizel = AOP_SIZE (left);
5814 emitcode ("setb", "c");
5817 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5819 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5821 if ((posbit = isLiteralBit (bytelit)) != 0)
5822 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5825 if (bytelit != 0x0FFL)
5826 emitcode ("anl", "a,%s",
5827 aopGet (AOP (right), offset, FALSE, TRUE));
5828 emitcode ("jnz", "%05d$", tlbl->key + 100);
5833 // bit = left & literal
5836 emitcode ("clr", "c");
5837 emitcode ("", "%05d$:", tlbl->key + 100);
5839 // if(left & literal)
5843 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5845 emitcode ("", "%05d$:", tlbl->key + 100);
5853 /* if left is same as result */
5854 if (sameRegs (AOP (result), AOP (left)))
5856 for (; size--; offset++)
5858 if (AOP_TYPE (right) == AOP_LIT)
5860 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5861 if (bytelit == 0x0FF)
5863 /* dummy read of volatile operand */
5864 if (isOperandVolatile (left, FALSE))
5865 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5869 else if (bytelit == 0)
5871 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5873 else if (IS_AOP_PREG (result))
5875 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5876 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5877 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5880 emitcode ("anl", "%s,%s",
5881 aopGet (AOP (left), offset, FALSE, TRUE),
5882 aopGet (AOP (right), offset, FALSE, FALSE));
5886 if (AOP_TYPE (left) == AOP_ACC)
5887 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5890 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5891 if (IS_AOP_PREG (result))
5893 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5894 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5897 emitcode ("anl", "%s,a",
5898 aopGet (AOP (left), offset, FALSE, TRUE));
5905 // left & result in different registers
5906 if (AOP_TYPE (result) == AOP_CRY)
5909 // if(size), result in bit
5910 // if(!size && ifx), conditional oper: if(left & right)
5911 symbol *tlbl = newiTempLabel (NULL);
5912 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5914 emitcode ("setb", "c");
5917 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5918 emitcode ("anl", "a,%s",
5919 aopGet (AOP (right), offset, FALSE, FALSE));
5921 if (AOP_TYPE(left)==AOP_ACC) {
5922 bool pushedB = pushB ();
5923 emitcode("mov", "b,a");
5924 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5925 emitcode("anl", "a,b");
5928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5929 emitcode ("anl", "a,%s",
5930 aopGet (AOP (left), offset, FALSE, FALSE));
5933 emitcode ("jnz", "%05d$", tlbl->key + 100);
5939 emitcode ("", "%05d$:", tlbl->key + 100);
5943 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5945 emitcode ("", "%05d$:", tlbl->key + 100);
5949 for (; (size--); offset++)
5952 // result = left & right
5953 if (AOP_TYPE (right) == AOP_LIT)
5955 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5956 if (bytelit == 0x0FF)
5958 aopPut (AOP (result),
5959 aopGet (AOP (left), offset, FALSE, FALSE),
5961 isOperandVolatile (result, FALSE));
5964 else if (bytelit == 0)
5966 /* dummy read of volatile operand */
5967 if (isOperandVolatile (left, FALSE))
5968 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5969 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5973 // faster than result <- left, anl result,right
5974 // and better if result is SFR
5975 if (AOP_TYPE (left) == AOP_ACC)
5976 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5979 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5980 emitcode ("anl", "a,%s",
5981 aopGet (AOP (left), offset, FALSE, FALSE));
5983 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5989 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5990 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5991 freeAsmop (result, NULL, ic, TRUE);
5994 /*-----------------------------------------------------------------*/
5995 /* genOr - code for or */
5996 /*-----------------------------------------------------------------*/
5998 genOr (iCode * ic, iCode * ifx)
6000 operand *left, *right, *result;
6001 int size, offset = 0;
6002 unsigned long lit = 0L;
6005 D(emitcode ("; genOr",""));
6007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6009 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6012 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6014 AOP_TYPE (left), AOP_TYPE (right));
6015 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6017 AOP_SIZE (left), AOP_SIZE (right));
6020 /* if left is a literal & right is not then exchange them */
6021 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6022 AOP_NEEDSACC (left))
6024 operand *tmp = right;
6029 /* if result = right then exchange them */
6030 if (sameRegs (AOP (result), AOP (right)))
6032 operand *tmp = right;
6037 /* if right is bit then exchange them */
6038 if (AOP_TYPE (right) == AOP_CRY &&
6039 AOP_TYPE (left) != AOP_CRY)
6041 operand *tmp = right;
6045 if (AOP_TYPE (right) == AOP_LIT)
6046 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6048 size = AOP_SIZE (result);
6052 if (AOP_TYPE (left) == AOP_CRY)
6054 if (AOP_TYPE (right) == AOP_LIT)
6056 // c = bit | literal;
6059 // lit != 0 => result = 1
6060 if (AOP_TYPE (result) == AOP_CRY)
6063 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6065 continueIfTrue (ifx);
6068 emitcode ("setb", "c");
6072 // lit == 0 => result = left
6073 if (size && sameRegs (AOP (result), AOP (left)))
6075 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6080 if (AOP_TYPE (right) == AOP_CRY)
6083 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6084 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6089 symbol *tlbl = newiTempLabel (NULL);
6090 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6091 emitcode ("setb", "c");
6092 emitcode ("jb", "%s,%05d$",
6093 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6095 emitcode ("jnz", "%05d$", tlbl->key + 100);
6096 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6098 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6104 emitcode ("", "%05d$:", tlbl->key + 100);
6113 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6114 genIfxJump (ifx, "c", left, right, result);
6118 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6119 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6120 if ((AOP_TYPE (right) == AOP_LIT) &&
6121 (AOP_TYPE (result) == AOP_CRY) &&
6122 (AOP_TYPE (left) != AOP_CRY))
6128 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6130 continueIfTrue (ifx);
6135 // lit = 0, result = boolean(left)
6137 emitcode ("setb", "c");
6141 symbol *tlbl = newiTempLabel (NULL);
6142 emitcode ("jnz", "%05d$", tlbl->key + 100);
6144 emitcode ("", "%05d$:", tlbl->key + 100);
6148 genIfxJump (ifx, "a", left, right, result);
6156 /* if left is same as result */
6157 if (sameRegs (AOP (result), AOP (left)))
6159 for (; size--; offset++)
6161 if (AOP_TYPE (right) == AOP_LIT)
6163 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6166 /* dummy read of volatile operand */
6167 if (isOperandVolatile (left, FALSE))
6168 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6172 else if (bytelit == 0x0FF)
6174 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6176 else if (IS_AOP_PREG (left))
6178 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6179 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6180 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6184 emitcode ("orl", "%s,%s",
6185 aopGet (AOP (left), offset, FALSE, TRUE),
6186 aopGet (AOP (right), offset, FALSE, FALSE));
6191 if (AOP_TYPE (left) == AOP_ACC)
6192 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6195 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6196 if (IS_AOP_PREG (left))
6198 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6199 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6203 emitcode ("orl", "%s,a",
6204 aopGet (AOP (left), offset, FALSE, TRUE));
6212 // left & result in different registers
6213 if (AOP_TYPE (result) == AOP_CRY)
6216 // if(size), result in bit
6217 // if(!size && ifx), conditional oper: if(left | right)
6218 symbol *tlbl = newiTempLabel (NULL);
6219 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6221 emitcode ("setb", "c");
6224 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6225 emitcode ("orl", "a,%s",
6226 aopGet (AOP (right), offset, FALSE, FALSE));
6228 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6229 emitcode ("orl", "a,%s",
6230 aopGet (AOP (left), offset, FALSE, FALSE));
6232 emitcode ("jnz", "%05d$", tlbl->key + 100);
6238 emitcode ("", "%05d$:", tlbl->key + 100);
6242 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6244 emitcode ("", "%05d$:", tlbl->key + 100);
6248 for (; (size--); offset++)
6251 // result = left | right
6252 if (AOP_TYPE (right) == AOP_LIT)
6254 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6257 aopPut (AOP (result),
6258 aopGet (AOP (left), offset, FALSE, FALSE),
6260 isOperandVolatile (result, FALSE));
6263 else if (bytelit == 0x0FF)
6265 /* dummy read of volatile operand */
6266 if (isOperandVolatile (left, FALSE))
6267 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6268 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6272 // faster than result <- left, anl result,right
6273 // and better if result is SFR
6274 if (AOP_TYPE (left) == AOP_ACC)
6275 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6278 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6279 emitcode ("orl", "a,%s",
6280 aopGet (AOP (left), offset, FALSE, FALSE));
6282 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6288 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6289 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6290 freeAsmop (result, NULL, ic, TRUE);
6293 /*-----------------------------------------------------------------*/
6294 /* genXor - code for xclusive or */
6295 /*-----------------------------------------------------------------*/
6297 genXor (iCode * ic, iCode * ifx)
6299 operand *left, *right, *result;
6300 int size, offset = 0;
6301 unsigned long lit = 0L;
6304 D(emitcode ("; genXor",""));
6306 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6307 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6308 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6311 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6313 AOP_TYPE (left), AOP_TYPE (right));
6314 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6316 AOP_SIZE (left), AOP_SIZE (right));
6319 /* if left is a literal & right is not ||
6320 if left needs acc & right does not */
6321 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6322 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6324 operand *tmp = right;
6329 /* if result = right then exchange them */
6330 if (sameRegs (AOP (result), AOP (right)))
6332 operand *tmp = right;
6337 /* if right is bit then exchange them */
6338 if (AOP_TYPE (right) == AOP_CRY &&
6339 AOP_TYPE (left) != AOP_CRY)
6341 operand *tmp = right;
6345 if (AOP_TYPE (right) == AOP_LIT)
6346 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6348 size = AOP_SIZE (result);
6352 if (AOP_TYPE (left) == AOP_CRY)
6354 if (AOP_TYPE (right) == AOP_LIT)
6356 // c = bit & literal;
6359 // lit>>1 != 0 => result = 1
6360 if (AOP_TYPE (result) == AOP_CRY)
6363 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6365 continueIfTrue (ifx);
6368 emitcode ("setb", "c");
6375 // lit == 0, result = left
6376 if (size && sameRegs (AOP (result), AOP (left)))
6378 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6382 // lit == 1, result = not(left)
6383 if (size && sameRegs (AOP (result), AOP (left)))
6385 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6390 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6391 emitcode ("cpl", "c");
6400 symbol *tlbl = newiTempLabel (NULL);
6401 if (AOP_TYPE (right) == AOP_CRY)
6404 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6408 int sizer = AOP_SIZE (right);
6410 // if val>>1 != 0, result = 1
6411 emitcode ("setb", "c");
6414 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6416 // test the msb of the lsb
6417 emitcode ("anl", "a,#0xfe");
6418 emitcode ("jnz", "%05d$", tlbl->key + 100);
6422 emitcode ("rrc", "a");
6424 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6425 emitcode ("cpl", "c");
6426 emitcode ("", "%05d$:", (tlbl->key + 100));
6433 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6434 genIfxJump (ifx, "c", left, right, result);
6438 /* if left is same as result */
6439 if (sameRegs (AOP (result), AOP (left)))
6441 for (; size--; offset++)
6443 if (AOP_TYPE (right) == AOP_LIT)
6445 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6448 /* dummy read of volatile operand */
6449 if (isOperandVolatile (left, FALSE))
6450 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6454 else if (IS_AOP_PREG (left))
6456 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6457 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6458 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6462 emitcode ("xrl", "%s,%s",
6463 aopGet (AOP (left), offset, FALSE, TRUE),
6464 aopGet (AOP (right), offset, FALSE, FALSE));
6469 if (AOP_TYPE (left) == AOP_ACC)
6470 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6473 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6474 if (IS_AOP_PREG (left))
6476 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6477 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6480 emitcode ("xrl", "%s,a",
6481 aopGet (AOP (left), offset, FALSE, TRUE));
6488 // left & result in different registers
6489 if (AOP_TYPE (result) == AOP_CRY)
6492 // if(size), result in bit
6493 // if(!size && ifx), conditional oper: if(left ^ right)
6494 symbol *tlbl = newiTempLabel (NULL);
6495 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6497 emitcode ("setb", "c");
6500 if ((AOP_TYPE (right) == AOP_LIT) &&
6501 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6503 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6507 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6508 emitcode ("xrl", "a,%s",
6509 aopGet (AOP (right), offset, FALSE, FALSE));
6511 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6512 emitcode ("xrl", "a,%s",
6513 aopGet (AOP (left), offset, FALSE, FALSE));
6516 emitcode ("jnz", "%05d$", tlbl->key + 100);
6522 emitcode ("", "%05d$:", tlbl->key + 100);
6526 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6530 for (; (size--); offset++)
6533 // result = left & right
6534 if (AOP_TYPE (right) == AOP_LIT)
6536 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6539 aopPut (AOP (result),
6540 aopGet (AOP (left), offset, FALSE, FALSE),
6542 isOperandVolatile (result, FALSE));
6546 // faster than result <- left, anl result,right
6547 // and better if result is SFR
6548 if (AOP_TYPE (left) == AOP_ACC)
6549 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6552 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6553 emitcode ("xrl", "a,%s",
6554 aopGet (AOP (left), offset, FALSE, TRUE));
6556 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6562 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6564 freeAsmop (result, NULL, ic, TRUE);
6567 /*-----------------------------------------------------------------*/
6568 /* genInline - write the inline code out */
6569 /*-----------------------------------------------------------------*/
6571 genInline (iCode * ic)
6573 char *buffer, *bp, *bp1;
6575 D(emitcode ("; genInline",""));
6577 _G.inLine += (!options.asmpeep);
6579 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6580 strcpy (buffer, IC_INLINE (ic));
6582 /* emit each line as a code */
6593 /* Add \n for labels, not dirs such as c:\mydir */
6594 if ( (*bp == ':') && (isspace(bp[1])) )
6608 /* emitcode("",buffer); */
6609 _G.inLine -= (!options.asmpeep);
6612 /*-----------------------------------------------------------------*/
6613 /* genRRC - rotate right with carry */
6614 /*-----------------------------------------------------------------*/
6618 operand *left, *result;
6619 int size, offset = 0;
6622 D(emitcode ("; genRRC",""));
6624 /* rotate right with carry */
6625 left = IC_LEFT (ic);
6626 result = IC_RESULT (ic);
6627 aopOp (left, ic, FALSE);
6628 aopOp (result, ic, FALSE);
6630 /* move it to the result */
6631 size = AOP_SIZE (result);
6633 if (size == 1) { /* special case for 1 byte */
6634 l = aopGet (AOP (left), offset, FALSE, FALSE);
6636 emitcode ("rr", "a");
6639 /* no need to clear carry, bit7 will be written later */
6642 l = aopGet (AOP (left), offset, FALSE, FALSE);
6644 emitcode ("rrc", "a");
6645 if (AOP_SIZE (result) > 1)
6646 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6648 /* now we need to put the carry into the
6649 highest order byte of the result */
6650 if (AOP_SIZE (result) > 1)
6652 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6655 emitcode ("mov", "acc.7,c");
6657 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6658 freeAsmop (left, NULL, ic, TRUE);
6659 freeAsmop (result, NULL, ic, TRUE);
6662 /*-----------------------------------------------------------------*/
6663 /* genRLC - generate code for rotate left with carry */
6664 /*-----------------------------------------------------------------*/
6668 operand *left, *result;
6669 int size, offset = 0;
6672 D(emitcode ("; genRLC",""));
6674 /* rotate right with carry */
6675 left = IC_LEFT (ic);
6676 result = IC_RESULT (ic);
6677 aopOp (left, ic, FALSE);
6678 aopOp (result, ic, FALSE);
6680 /* move it to the result */
6681 size = AOP_SIZE (result);
6685 l = aopGet (AOP (left), offset, FALSE, FALSE);
6687 if (size == 0) { /* special case for 1 byte */
6691 emitcode("rlc","a"); /* bit0 will be written later */
6692 if (AOP_SIZE (result) > 1)
6693 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6696 l = aopGet (AOP (left), offset, FALSE, FALSE);
6698 emitcode ("rlc", "a");
6699 if (AOP_SIZE (result) > 1)
6700 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6703 /* now we need to put the carry into the
6704 highest order byte of the result */
6705 if (AOP_SIZE (result) > 1)
6707 l = aopGet (AOP (result), 0, FALSE, FALSE);
6710 emitcode ("mov", "acc.0,c");
6712 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6713 freeAsmop (left, NULL, ic, TRUE);
6714 freeAsmop (result, NULL, ic, TRUE);
6717 /*-----------------------------------------------------------------*/
6718 /* genGetHbit - generates code get highest order bit */
6719 /*-----------------------------------------------------------------*/
6721 genGetHbit (iCode * ic)
6723 operand *left, *result;
6725 D(emitcode ("; genGetHbit",""));
6727 left = IC_LEFT (ic);
6728 result = IC_RESULT (ic);
6729 aopOp (left, ic, FALSE);
6730 aopOp (result, ic, FALSE);
6732 /* get the highest order byte into a */
6733 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6734 if (AOP_TYPE (result) == AOP_CRY)
6736 emitcode ("rlc", "a");
6741 emitcode ("rl", "a");
6742 emitcode ("anl", "a,#0x01");
6747 freeAsmop (left, NULL, ic, TRUE);
6748 freeAsmop (result, NULL, ic, TRUE);
6751 /*-----------------------------------------------------------------*/
6752 /* genSwap - generates code to swap nibbles or bytes */
6753 /*-----------------------------------------------------------------*/
6755 genSwap (iCode * ic)
6757 operand *left, *result;
6759 D(emitcode ("; genSwap",""));
6761 left = IC_LEFT (ic);
6762 result = IC_RESULT (ic);
6763 aopOp (left, ic, FALSE);
6764 aopOp (result, ic, FALSE);
6766 switch (AOP_SIZE (left))
6768 case 1: /* swap nibbles in byte */
6769 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6770 emitcode ("swap", "a");
6771 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6773 case 2: /* swap bytes in word */
6774 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6776 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6777 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6778 0, isOperandVolatile (result, FALSE));
6779 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6781 else if (operandsEqu (left, result))
6784 bool pushedB = FALSE, leftInB = FALSE;
6786 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6787 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6790 emitcode ("mov", "b,a");
6794 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6795 0, isOperandVolatile (result, FALSE));
6796 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6803 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6804 0, isOperandVolatile (result, FALSE));
6805 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6806 1, isOperandVolatile (result, FALSE));
6810 wassertl(FALSE, "unsupported SWAP operand size");
6813 freeAsmop (left, NULL, ic, TRUE);
6814 freeAsmop (result, NULL, ic, TRUE);
6818 /*-----------------------------------------------------------------*/
6819 /* AccRol - rotate left accumulator by known count */
6820 /*-----------------------------------------------------------------*/
6822 AccRol (int shCount)
6824 shCount &= 0x0007; // shCount : 0..7
6831 emitcode ("rl", "a");
6834 emitcode ("rl", "a");
6835 emitcode ("rl", "a");
6838 emitcode ("swap", "a");
6839 emitcode ("rr", "a");
6842 emitcode ("swap", "a");
6845 emitcode ("swap", "a");
6846 emitcode ("rl", "a");
6849 emitcode ("rr", "a");
6850 emitcode ("rr", "a");
6853 emitcode ("rr", "a");
6858 /*-----------------------------------------------------------------*/
6859 /* AccLsh - left shift accumulator by known count */
6860 /*-----------------------------------------------------------------*/
6862 AccLsh (int shCount)
6867 emitcode ("add", "a,acc");
6868 else if (shCount == 2)
6870 emitcode ("add", "a,acc");
6871 emitcode ("add", "a,acc");
6875 /* rotate left accumulator */
6877 /* and kill the lower order bits */
6878 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6883 /*-----------------------------------------------------------------*/
6884 /* AccRsh - right shift accumulator by known count */
6885 /*-----------------------------------------------------------------*/
6887 AccRsh (int shCount)
6894 emitcode ("rrc", "a");
6898 /* rotate right accumulator */
6899 AccRol (8 - shCount);
6900 /* and kill the higher order bits */
6901 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6906 /*-----------------------------------------------------------------*/
6907 /* AccSRsh - signed right shift accumulator by known count */
6908 /*-----------------------------------------------------------------*/
6910 AccSRsh (int shCount)
6917 emitcode ("mov", "c,acc.7");
6918 emitcode ("rrc", "a");
6920 else if (shCount == 2)
6922 emitcode ("mov", "c,acc.7");
6923 emitcode ("rrc", "a");
6924 emitcode ("mov", "c,acc.7");
6925 emitcode ("rrc", "a");
6929 tlbl = newiTempLabel (NULL);
6930 /* rotate right accumulator */
6931 AccRol (8 - shCount);
6932 /* and kill the higher order bits */
6933 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6934 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6935 emitcode ("orl", "a,#0x%02x",
6936 (unsigned char) ~SRMask[shCount]);
6937 emitcode ("", "%05d$:", tlbl->key + 100);
6942 /*-----------------------------------------------------------------*/
6943 /* shiftR1Left2Result - shift right one byte from left to result */
6944 /*-----------------------------------------------------------------*/
6946 shiftR1Left2Result (operand * left, int offl,
6947 operand * result, int offr,
6948 int shCount, int sign)
6950 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6951 /* shift right accumulator */
6956 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6959 /*-----------------------------------------------------------------*/
6960 /* shiftL1Left2Result - shift left one byte from left to result */
6961 /*-----------------------------------------------------------------*/
6963 shiftL1Left2Result (operand * left, int offl,
6964 operand * result, int offr, int shCount)
6967 l = aopGet (AOP (left), offl, FALSE, FALSE);
6969 /* shift left accumulator */
6971 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6974 /*-----------------------------------------------------------------*/
6975 /* movLeft2Result - move byte from left to result */
6976 /*-----------------------------------------------------------------*/
6978 movLeft2Result (operand * left, int offl,
6979 operand * result, int offr, int sign)
6982 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6984 l = aopGet (AOP (left), offl, FALSE, FALSE);
6986 if (*l == '@' && (IS_AOP_PREG (result)))
6988 emitcode ("mov", "a,%s", l);
6989 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6994 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6997 /* MSB sign in acc.7 ! */
6998 if (getDataSize (left) == offl + 1)
7000 emitcode ("mov", "a,%s", l);
7001 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7008 /*-----------------------------------------------------------------*/
7009 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7010 /*-----------------------------------------------------------------*/
7014 emitcode ("rrc", "a");
7015 emitcode ("xch", "a,%s", x);
7016 emitcode ("rrc", "a");
7017 emitcode ("xch", "a,%s", x);
7020 /*-----------------------------------------------------------------*/
7021 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7022 /*-----------------------------------------------------------------*/
7026 emitcode ("xch", "a,%s", x);
7027 emitcode ("rlc", "a");
7028 emitcode ("xch", "a,%s", x);
7029 emitcode ("rlc", "a");
7032 /*-----------------------------------------------------------------*/
7033 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7034 /*-----------------------------------------------------------------*/
7038 emitcode ("xch", "a,%s", x);
7039 emitcode ("add", "a,acc");
7040 emitcode ("xch", "a,%s", x);
7041 emitcode ("rlc", "a");
7044 /*-----------------------------------------------------------------*/
7045 /* AccAXLsh - left shift a:x by known count (0..7) */
7046 /*-----------------------------------------------------------------*/
7048 AccAXLsh (char *x, int shCount)
7063 case 5: // AAAAABBB:CCCCCDDD
7065 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7067 emitcode ("anl", "a,#0x%02x",
7068 SLMask[shCount]); // BBB00000:CCCCCDDD
7070 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7072 AccRol (shCount); // DDDCCCCC:BBB00000
7074 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7076 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7078 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7080 emitcode ("anl", "a,#0x%02x",
7081 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7083 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7085 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7088 case 6: // AAAAAABB:CCCCCCDD
7089 emitcode ("anl", "a,#0x%02x",
7090 SRMask[shCount]); // 000000BB:CCCCCCDD
7091 emitcode ("mov", "c,acc.0"); // c = B
7092 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7094 AccAXRrl1 (x); // BCCCCCCD:D000000B
7095 AccAXRrl1 (x); // BBCCCCCC:DD000000
7097 emitcode("rrc","a");
7098 emitcode("xch","a,%s", x);
7099 emitcode("rrc","a");
7100 emitcode("mov","c,acc.0"); //<< get correct bit
7101 emitcode("xch","a,%s", x);
7103 emitcode("rrc","a");
7104 emitcode("xch","a,%s", x);
7105 emitcode("rrc","a");
7106 emitcode("xch","a,%s", x);
7109 case 7: // a:x <<= 7
7111 emitcode ("anl", "a,#0x%02x",
7112 SRMask[shCount]); // 0000000B:CCCCCCCD
7114 emitcode ("mov", "c,acc.0"); // c = B
7116 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7118 AccAXRrl1 (x); // BCCCCCCC:D0000000
7126 /*-----------------------------------------------------------------*/
7127 /* AccAXRsh - right shift a:x known count (0..7) */
7128 /*-----------------------------------------------------------------*/
7130 AccAXRsh (char *x, int shCount)
7138 AccAXRrl1 (x); // 0->a:x
7143 AccAXRrl1 (x); // 0->a:x
7146 AccAXRrl1 (x); // 0->a:x
7151 case 5: // AAAAABBB:CCCCCDDD = a:x
7153 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7155 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7157 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7159 emitcode ("anl", "a,#0x%02x",
7160 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7162 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7164 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7166 emitcode ("anl", "a,#0x%02x",
7167 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7169 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7171 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7173 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7176 case 6: // AABBBBBB:CCDDDDDD
7178 emitcode ("mov", "c,acc.7");
7179 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7181 emitcode ("mov", "c,acc.7");
7182 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7184 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7186 emitcode ("anl", "a,#0x%02x",
7187 SRMask[shCount]); // 000000AA:BBBBBBCC
7190 case 7: // ABBBBBBB:CDDDDDDD
7192 emitcode ("mov", "c,acc.7"); // c = A
7194 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7196 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7198 emitcode ("anl", "a,#0x%02x",
7199 SRMask[shCount]); // 0000000A:BBBBBBBC
7207 /*-----------------------------------------------------------------*/
7208 /* AccAXRshS - right shift signed a:x known count (0..7) */
7209 /*-----------------------------------------------------------------*/
7211 AccAXRshS (char *x, int shCount)
7219 emitcode ("mov", "c,acc.7");
7220 AccAXRrl1 (x); // s->a:x
7224 emitcode ("mov", "c,acc.7");
7225 AccAXRrl1 (x); // s->a:x
7227 emitcode ("mov", "c,acc.7");
7228 AccAXRrl1 (x); // s->a:x
7233 case 5: // AAAAABBB:CCCCCDDD = a:x
7235 tlbl = newiTempLabel (NULL);
7236 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7238 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7240 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7242 emitcode ("anl", "a,#0x%02x",
7243 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7245 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7247 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7249 emitcode ("anl", "a,#0x%02x",
7250 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7252 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7254 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7256 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7258 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7259 emitcode ("orl", "a,#0x%02x",
7260 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7262 emitcode ("", "%05d$:", tlbl->key + 100);
7263 break; // SSSSAAAA:BBBCCCCC
7265 case 6: // AABBBBBB:CCDDDDDD
7267 tlbl = newiTempLabel (NULL);
7268 emitcode ("mov", "c,acc.7");
7269 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7271 emitcode ("mov", "c,acc.7");
7272 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7274 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7276 emitcode ("anl", "a,#0x%02x",
7277 SRMask[shCount]); // 000000AA:BBBBBBCC
7279 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7280 emitcode ("orl", "a,#0x%02x",
7281 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7283 emitcode ("", "%05d$:", tlbl->key + 100);
7285 case 7: // ABBBBBBB:CDDDDDDD
7287 tlbl = newiTempLabel (NULL);
7288 emitcode ("mov", "c,acc.7"); // c = A
7290 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7292 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7294 emitcode ("anl", "a,#0x%02x",
7295 SRMask[shCount]); // 0000000A:BBBBBBBC
7297 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7298 emitcode ("orl", "a,#0x%02x",
7299 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7301 emitcode ("", "%05d$:", tlbl->key + 100);
7308 /*-----------------------------------------------------------------*/
7309 /* shiftL2Left2Result - shift left two bytes from left to result */
7310 /*-----------------------------------------------------------------*/
7312 shiftL2Left2Result (operand * left, int offl,
7313 operand * result, int offr, int shCount)
7315 if (sameRegs (AOP (result), AOP (left)) &&
7316 ((offl + MSB16) == offr))
7318 /* don't crash result[offr] */
7319 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7320 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7324 movLeft2Result (left, offl, result, offr, 0);
7325 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7327 /* ax << shCount (x = lsb(result)) */
7328 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7329 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7333 /*-----------------------------------------------------------------*/
7334 /* shiftR2Left2Result - shift right two bytes from left to result */
7335 /*-----------------------------------------------------------------*/
7337 shiftR2Left2Result (operand * left, int offl,
7338 operand * result, int offr,
7339 int shCount, int sign)
7341 if (sameRegs (AOP (result), AOP (left)) &&
7342 ((offl + MSB16) == offr))
7344 /* don't crash result[offr] */
7345 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7346 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7350 movLeft2Result (left, offl, result, offr, 0);
7351 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7353 /* a:x >> shCount (x = lsb(result)) */
7355 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7357 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7358 if (getDataSize (result) > 1)
7359 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7362 /*-----------------------------------------------------------------*/
7363 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7364 /*-----------------------------------------------------------------*/
7366 shiftLLeftOrResult (operand * left, int offl,
7367 operand * result, int offr, int shCount)
7369 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7370 /* shift left accumulator */
7372 /* or with result */
7373 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7374 /* back to result */
7375 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7378 /*-----------------------------------------------------------------*/
7379 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7380 /*-----------------------------------------------------------------*/
7382 shiftRLeftOrResult (operand * left, int offl,
7383 operand * result, int offr, int shCount)
7385 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7386 /* shift right accumulator */
7388 /* or with result */
7389 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7390 /* back to result */
7391 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7394 /*-----------------------------------------------------------------*/
7395 /* genlshOne - left shift a one byte quantity by known count */
7396 /*-----------------------------------------------------------------*/
7398 genlshOne (operand * result, operand * left, int shCount)
7400 D(emitcode ("; genlshOne",""));
7402 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7405 /*-----------------------------------------------------------------*/
7406 /* genlshTwo - left shift two bytes by known amount != 0 */
7407 /*-----------------------------------------------------------------*/
7409 genlshTwo (operand * result, operand * left, int shCount)
7413 D(emitcode ("; genlshTwo",""));
7415 size = getDataSize (result);
7417 /* if shCount >= 8 */
7425 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7427 movLeft2Result (left, LSB, result, MSB16, 0);
7429 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7432 /* 1 <= shCount <= 7 */
7436 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7438 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7442 /*-----------------------------------------------------------------*/
7443 /* shiftLLong - shift left one long from left to result */
7444 /* offl = LSB or MSB16 */
7445 /*-----------------------------------------------------------------*/
7447 shiftLLong (operand * left, operand * result, int offr)
7450 int size = AOP_SIZE (result);
7452 if (size >= LSB + offr)
7454 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7456 emitcode ("add", "a,acc");
7457 if (sameRegs (AOP (left), AOP (result)) &&
7458 size >= MSB16 + offr && offr != LSB)
7459 emitcode ("xch", "a,%s",
7460 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7462 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7465 if (size >= MSB16 + offr)
7467 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7469 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7472 emitcode ("rlc", "a");
7473 if (sameRegs (AOP (left), AOP (result)) &&
7474 size >= MSB24 + offr && offr != LSB)
7475 emitcode ("xch", "a,%s",
7476 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7478 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7481 if (size >= MSB24 + offr)
7483 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7485 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7488 emitcode ("rlc", "a");
7489 if (sameRegs (AOP (left), AOP (result)) &&
7490 size >= MSB32 + offr && offr != LSB)
7491 emitcode ("xch", "a,%s",
7492 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7494 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7497 if (size > MSB32 + offr)
7499 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7501 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7504 emitcode ("rlc", "a");
7505 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7508 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7511 /*-----------------------------------------------------------------*/
7512 /* genlshFour - shift four byte by a known amount != 0 */
7513 /*-----------------------------------------------------------------*/
7515 genlshFour (operand * result, operand * left, int shCount)
7519 D(emitcode ("; genlshFour",""));
7521 size = AOP_SIZE (result);
7523 /* if shifting more that 3 bytes */
7528 /* lowest order of left goes to the highest
7529 order of the destination */
7530 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7532 movLeft2Result (left, LSB, result, MSB32, 0);
7533 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7534 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7535 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7539 /* more than two bytes */
7540 else if (shCount >= 16)
7542 /* lower order two bytes goes to higher order two bytes */
7544 /* if some more remaining */
7546 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7549 movLeft2Result (left, MSB16, result, MSB32, 0);
7550 movLeft2Result (left, LSB, result, MSB24, 0);
7552 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7553 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7557 /* if more than 1 byte */
7558 else if (shCount >= 8)
7560 /* lower order three bytes goes to higher order three bytes */
7565 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7567 movLeft2Result (left, LSB, result, MSB16, 0);
7573 movLeft2Result (left, MSB24, result, MSB32, 0);
7574 movLeft2Result (left, MSB16, result, MSB24, 0);
7575 movLeft2Result (left, LSB, result, MSB16, 0);
7576 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7578 else if (shCount == 1)
7579 shiftLLong (left, result, MSB16);
7582 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7583 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7584 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7585 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7590 /* 1 <= shCount <= 7 */
7591 else if (shCount <= 2)
7593 shiftLLong (left, result, LSB);
7595 shiftLLong (result, result, LSB);
7597 /* 3 <= shCount <= 7, optimize */
7600 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7601 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7602 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7606 /*-----------------------------------------------------------------*/
7607 /* genLeftShiftLiteral - left shifting by known count */
7608 /*-----------------------------------------------------------------*/
7610 genLeftShiftLiteral (operand * left,
7615 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7618 D(emitcode ("; genLeftShiftLiteral",""));
7620 freeAsmop (right, NULL, ic, TRUE);
7622 aopOp (left, ic, FALSE);
7623 aopOp (result, ic, FALSE);
7625 size = getSize (operandType (result));
7628 emitcode ("; shift left ", "result %d, left %d", size,
7632 /* I suppose that the left size >= result size */
7637 movLeft2Result (left, size, result, size, 0);
7641 else if (shCount >= (size * 8))
7643 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7649 genlshOne (result, left, shCount);
7653 genlshTwo (result, left, shCount);
7657 genlshFour (result, left, shCount);
7660 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7661 "*** ack! mystery literal shift!\n");
7665 freeAsmop (left, NULL, ic, TRUE);
7666 freeAsmop (result, NULL, ic, TRUE);
7669 /*-----------------------------------------------------------------*/
7670 /* genLeftShift - generates code for left shifting */
7671 /*-----------------------------------------------------------------*/
7673 genLeftShift (iCode * ic)
7675 operand *left, *right, *result;
7678 symbol *tlbl, *tlbl1;
7681 D(emitcode ("; genLeftShift",""));
7683 right = IC_RIGHT (ic);
7684 left = IC_LEFT (ic);
7685 result = IC_RESULT (ic);
7687 aopOp (right, ic, FALSE);
7689 /* if the shift count is known then do it
7690 as efficiently as possible */
7691 if (AOP_TYPE (right) == AOP_LIT)
7693 genLeftShiftLiteral (left, right, result, ic);
7697 /* shift count is unknown then we have to form
7698 a loop get the loop count in B : Note: we take
7699 only the lower order byte since shifting
7700 more that 32 bits make no sense anyway, ( the
7701 largest size of an object can be only 32 bits ) */
7704 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7705 emitcode ("inc", "b");
7706 freeAsmop (right, NULL, ic, TRUE);
7707 aopOp (left, ic, FALSE);
7708 aopOp (result, ic, FALSE);
7710 /* now move the left to the result if they are not the same */
7711 if (!sameRegs (AOP (left), AOP (result)) &&
7712 AOP_SIZE (result) > 1)
7715 size = AOP_SIZE (result);
7719 l = aopGet (AOP (left), offset, FALSE, TRUE);
7720 if (*l == '@' && (IS_AOP_PREG (result)))
7723 emitcode ("mov", "a,%s", l);
7724 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7727 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7732 tlbl = newiTempLabel (NULL);
7733 size = AOP_SIZE (result);
7735 tlbl1 = newiTempLabel (NULL);
7737 /* if it is only one byte then */
7740 symbol *tlbl1 = newiTempLabel (NULL);
7742 l = aopGet (AOP (left), 0, FALSE, FALSE);
7744 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7745 emitcode ("", "%05d$:", tlbl->key + 100);
7746 emitcode ("add", "a,acc");
7747 emitcode ("", "%05d$:", tlbl1->key + 100);
7748 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7750 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7754 reAdjustPreg (AOP (result));
7756 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7757 emitcode ("", "%05d$:", tlbl->key + 100);
7758 l = aopGet (AOP (result), offset, FALSE, FALSE);
7760 emitcode ("add", "a,acc");
7761 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7764 l = aopGet (AOP (result), offset, FALSE, FALSE);
7766 emitcode ("rlc", "a");
7767 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7769 reAdjustPreg (AOP (result));
7771 emitcode ("", "%05d$:", tlbl1->key + 100);
7772 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7775 freeAsmop (left, NULL, ic, TRUE);
7776 freeAsmop (result, NULL, ic, TRUE);
7779 /*-----------------------------------------------------------------*/
7780 /* genrshOne - right shift a one byte quantity by known count */
7781 /*-----------------------------------------------------------------*/
7783 genrshOne (operand * result, operand * left,
7784 int shCount, int sign)
7786 D(emitcode ("; genrshOne",""));
7788 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7791 /*-----------------------------------------------------------------*/
7792 /* genrshTwo - right shift two bytes by known amount != 0 */
7793 /*-----------------------------------------------------------------*/
7795 genrshTwo (operand * result, operand * left,
7796 int shCount, int sign)
7798 D(emitcode ("; genrshTwo",""));
7800 /* if shCount >= 8 */
7805 shiftR1Left2Result (left, MSB16, result, LSB,
7808 movLeft2Result (left, MSB16, result, LSB, sign);
7809 addSign (result, MSB16, sign);
7812 /* 1 <= shCount <= 7 */
7814 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7817 /*-----------------------------------------------------------------*/
7818 /* shiftRLong - shift right one long from left to result */
7819 /* offl = LSB or MSB16 */
7820 /*-----------------------------------------------------------------*/
7822 shiftRLong (operand * left, int offl,
7823 operand * result, int sign)
7825 int isSameRegs=sameRegs(AOP(left),AOP(result));
7827 if (isSameRegs && offl>1) {
7828 // we are in big trouble, but this shouldn't happen
7829 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7832 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7837 emitcode ("rlc", "a");
7838 emitcode ("subb", "a,acc");
7840 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7842 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7843 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7846 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7851 emitcode ("clr", "c");
7853 emitcode ("mov", "c,acc.7");
7856 emitcode ("rrc", "a");
7858 if (isSameRegs && offl==MSB16) {
7859 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7861 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7862 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7865 emitcode ("rrc", "a");
7866 if (isSameRegs && offl==1) {
7867 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7869 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7870 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7872 emitcode ("rrc", "a");
7873 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7877 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7878 emitcode ("rrc", "a");
7879 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7883 /*-----------------------------------------------------------------*/
7884 /* genrshFour - shift four byte by a known amount != 0 */
7885 /*-----------------------------------------------------------------*/
7887 genrshFour (operand * result, operand * left,
7888 int shCount, int sign)
7890 D(emitcode ("; genrshFour",""));
7892 /* if shifting more that 3 bytes */
7897 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7899 movLeft2Result (left, MSB32, result, LSB, sign);
7900 addSign (result, MSB16, sign);
7902 else if (shCount >= 16)
7906 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7909 movLeft2Result (left, MSB24, result, LSB, 0);
7910 movLeft2Result (left, MSB32, result, MSB16, sign);
7912 addSign (result, MSB24, sign);
7914 else if (shCount >= 8)
7918 shiftRLong (left, MSB16, result, sign);
7919 else if (shCount == 0)
7921 movLeft2Result (left, MSB16, result, LSB, 0);
7922 movLeft2Result (left, MSB24, result, MSB16, 0);
7923 movLeft2Result (left, MSB32, result, MSB24, sign);
7924 addSign (result, MSB32, sign);
7928 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7929 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7930 /* the last shift is signed */
7931 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7932 addSign (result, MSB32, sign);
7936 { /* 1 <= shCount <= 7 */
7939 shiftRLong (left, LSB, result, sign);
7941 shiftRLong (result, LSB, result, sign);
7945 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7946 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7947 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7952 /*-----------------------------------------------------------------*/
7953 /* genRightShiftLiteral - right shifting by known count */
7954 /*-----------------------------------------------------------------*/
7956 genRightShiftLiteral (operand * left,
7962 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7965 D(emitcode ("; genRightShiftLiteral",""));
7967 freeAsmop (right, NULL, ic, TRUE);
7969 aopOp (left, ic, FALSE);
7970 aopOp (result, ic, FALSE);
7973 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7977 size = getDataSize (left);
7978 /* test the LEFT size !!! */
7980 /* I suppose that the left size >= result size */
7983 size = getDataSize (result);
7985 movLeft2Result (left, size, result, size, 0);
7988 else if (shCount >= (size * 8))
7991 /* get sign in acc.7 */
7992 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7994 addSign (result, LSB, sign);
8001 genrshOne (result, left, shCount, sign);
8005 genrshTwo (result, left, shCount, sign);
8009 genrshFour (result, left, shCount, sign);
8015 freeAsmop (left, NULL, ic, TRUE);
8016 freeAsmop (result, NULL, ic, TRUE);
8019 /*-----------------------------------------------------------------*/
8020 /* genSignedRightShift - right shift of signed number */
8021 /*-----------------------------------------------------------------*/
8023 genSignedRightShift (iCode * ic)
8025 operand *right, *left, *result;
8028 symbol *tlbl, *tlbl1;
8031 D(emitcode ("; genSignedRightShift",""));
8033 /* we do it the hard way put the shift count in b
8034 and loop thru preserving the sign */
8036 right = IC_RIGHT (ic);
8037 left = IC_LEFT (ic);
8038 result = IC_RESULT (ic);
8040 aopOp (right, ic, FALSE);
8043 if (AOP_TYPE (right) == AOP_LIT)
8045 genRightShiftLiteral (left, right, result, ic, 1);
8048 /* shift count is unknown then we have to form
8049 a loop get the loop count in B : Note: we take
8050 only the lower order byte since shifting
8051 more that 32 bits make no sense anyway, ( the
8052 largest size of an object can be only 32 bits ) */
8055 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8056 emitcode ("inc", "b");
8057 freeAsmop (right, NULL, ic, TRUE);
8058 aopOp (left, ic, FALSE);
8059 aopOp (result, ic, FALSE);
8061 /* now move the left to the result if they are not the
8063 if (!sameRegs (AOP (left), AOP (result)) &&
8064 AOP_SIZE (result) > 1)
8067 size = AOP_SIZE (result);
8071 l = aopGet (AOP (left), offset, FALSE, TRUE);
8072 if (*l == '@' && IS_AOP_PREG (result))
8075 emitcode ("mov", "a,%s", l);
8076 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8079 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8084 /* mov the highest order bit to OVR */
8085 tlbl = newiTempLabel (NULL);
8086 tlbl1 = newiTempLabel (NULL);
8088 size = AOP_SIZE (result);
8090 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8091 emitcode ("rlc", "a");
8092 emitcode ("mov", "ov,c");
8093 /* if it is only one byte then */
8096 l = aopGet (AOP (left), 0, FALSE, FALSE);
8098 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8099 emitcode ("", "%05d$:", tlbl->key + 100);
8100 emitcode ("mov", "c,ov");
8101 emitcode ("rrc", "a");
8102 emitcode ("", "%05d$:", tlbl1->key + 100);
8103 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8105 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8109 reAdjustPreg (AOP (result));
8110 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8111 emitcode ("", "%05d$:", tlbl->key + 100);
8112 emitcode ("mov", "c,ov");
8115 l = aopGet (AOP (result), offset, FALSE, FALSE);
8117 emitcode ("rrc", "a");
8118 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8120 reAdjustPreg (AOP (result));
8121 emitcode ("", "%05d$:", tlbl1->key + 100);
8122 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8126 freeAsmop (left, NULL, ic, TRUE);
8127 freeAsmop (result, NULL, ic, TRUE);
8130 /*-----------------------------------------------------------------*/
8131 /* genRightShift - generate code for right shifting */
8132 /*-----------------------------------------------------------------*/
8134 genRightShift (iCode * ic)
8136 operand *right, *left, *result;
8140 symbol *tlbl, *tlbl1;
8143 D(emitcode ("; genRightShift",""));
8145 /* if signed then we do it the hard way preserve the
8146 sign bit moving it inwards */
8147 letype = getSpec (operandType (IC_LEFT (ic)));
8149 if (!SPEC_USIGN (letype))
8151 genSignedRightShift (ic);
8155 /* signed & unsigned types are treated the same : i.e. the
8156 signed is NOT propagated inwards : quoting from the
8157 ANSI - standard : "for E1 >> E2, is equivalent to division
8158 by 2**E2 if unsigned or if it has a non-negative value,
8159 otherwise the result is implementation defined ", MY definition
8160 is that the sign does not get propagated */
8162 right = IC_RIGHT (ic);
8163 left = IC_LEFT (ic);
8164 result = IC_RESULT (ic);
8166 aopOp (right, ic, FALSE);
8168 /* if the shift count is known then do it
8169 as efficiently as possible */
8170 if (AOP_TYPE (right) == AOP_LIT)
8172 genRightShiftLiteral (left, right, result, ic, 0);
8176 /* shift count is unknown then we have to form
8177 a loop get the loop count in B : Note: we take
8178 only the lower order byte since shifting
8179 more that 32 bits make no sense anyway, ( the
8180 largest size of an object can be only 32 bits ) */
8183 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8184 emitcode ("inc", "b");
8185 freeAsmop (right, NULL, ic, TRUE);
8186 aopOp (left, ic, FALSE);
8187 aopOp (result, ic, FALSE);
8189 /* now move the left to the result if they are not the
8191 if (!sameRegs (AOP (left), AOP (result)) &&
8192 AOP_SIZE (result) > 1)
8195 size = AOP_SIZE (result);
8199 l = aopGet (AOP (left), offset, FALSE, TRUE);
8200 if (*l == '@' && IS_AOP_PREG (result))
8203 emitcode ("mov", "a,%s", l);
8204 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8207 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8212 tlbl = newiTempLabel (NULL);
8213 tlbl1 = newiTempLabel (NULL);
8214 size = AOP_SIZE (result);
8217 /* if it is only one byte then */
8220 l = aopGet (AOP (left), 0, FALSE, FALSE);
8222 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8223 emitcode ("", "%05d$:", tlbl->key + 100);
8225 emitcode ("rrc", "a");
8226 emitcode ("", "%05d$:", tlbl1->key + 100);
8227 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8229 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8233 reAdjustPreg (AOP (result));
8234 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8235 emitcode ("", "%05d$:", tlbl->key + 100);
8239 l = aopGet (AOP (result), offset, FALSE, FALSE);
8241 emitcode ("rrc", "a");
8242 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8244 reAdjustPreg (AOP (result));
8246 emitcode ("", "%05d$:", tlbl1->key + 100);
8247 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8251 freeAsmop (left, NULL, ic, TRUE);
8252 freeAsmop (result, NULL, ic, TRUE);
8255 /*-----------------------------------------------------------------*/
8256 /* emitPtrByteGet - emits code to get a byte into A through a */
8257 /* pointer register (R0, R1, or DPTR). The */
8258 /* original value of A can be preserved in B. */
8259 /*-----------------------------------------------------------------*/
8261 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8268 emitcode ("mov", "b,a");
8269 emitcode ("mov", "a,@%s", rname);
8274 emitcode ("mov", "b,a");
8275 emitcode ("movx", "a,@%s", rname);
8280 emitcode ("mov", "b,a");
8281 emitcode ("movx", "a,@dptr");
8286 emitcode ("mov", "b,a");
8287 emitcode ("clr", "a");
8288 emitcode ("movc", "a,@a+dptr");
8294 emitcode ("push", "b");
8295 emitcode ("push", "acc");
8297 emitcode ("lcall", "__gptrget");
8299 emitcode ("pop", "b");
8304 /*-----------------------------------------------------------------*/
8305 /* emitPtrByteSet - emits code to set a byte from src through a */
8306 /* pointer register (R0, R1, or DPTR). */
8307 /*-----------------------------------------------------------------*/
8309 emitPtrByteSet (char *rname, int p_type, char *src)
8318 emitcode ("mov", "@%s,a", rname);
8321 emitcode ("mov", "@%s,%s", rname, src);
8326 emitcode ("movx", "@%s,a", rname);
8331 emitcode ("movx", "@dptr,a");
8336 emitcode ("lcall", "__gptrput");
8341 /*-----------------------------------------------------------------*/
8342 /* genUnpackBits - generates code for unpacking bits */
8343 /*-----------------------------------------------------------------*/
8345 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8347 int offset = 0; /* result byte offset */
8348 int rsize; /* result size */
8349 int rlen = 0; /* remaining bitfield length */
8350 sym_link *etype; /* bitfield type information */
8351 int blen; /* bitfield length */
8352 int bstr; /* bitfield starting bit within byte */
8355 D(emitcode ("; genUnpackBits",""));
8357 etype = getSpec (operandType (result));
8358 rsize = getSize (operandType (result));
8359 blen = SPEC_BLEN (etype);
8360 bstr = SPEC_BSTR (etype);
8362 if (ifx && blen <= 8)
8364 emitPtrByteGet (rname, ptype, FALSE);
8367 SNPRINTF (buffer, sizeof(buffer),
8369 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8374 emitcode ("anl", "a,#0x%02x",
8375 (((unsigned char) -1) >> (8 - blen)) << bstr);
8376 genIfxJump (ifx, "a", NULL, NULL, NULL);
8382 /* If the bitfield length is less than a byte */
8385 emitPtrByteGet (rname, ptype, FALSE);
8387 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8388 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8392 /* Bit field did not fit in a byte. Copy all
8393 but the partial byte at the end. */
8394 for (rlen=blen;rlen>=8;rlen-=8)
8396 emitPtrByteGet (rname, ptype, FALSE);
8397 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8399 emitcode ("inc", "%s", rname);
8402 /* Handle the partial byte at the end */
8405 emitPtrByteGet (rname, ptype, FALSE);
8406 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8407 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8415 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8420 /*-----------------------------------------------------------------*/
8421 /* genDataPointerGet - generates code when ptr offset is known */
8422 /*-----------------------------------------------------------------*/
8424 genDataPointerGet (operand * left,
8430 int size, offset = 0;
8432 D(emitcode ("; genDataPointerGet",""));
8434 aopOp (result, ic, TRUE);
8436 /* get the string representation of the name */
8437 l = aopGet (AOP (left), 0, FALSE, TRUE);
8438 size = AOP_SIZE (result);
8442 sprintf (buffer, "(%s + %d)", l + 1, offset);
8444 sprintf (buffer, "%s", l + 1);
8445 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8448 freeAsmop (left, NULL, ic, TRUE);
8449 freeAsmop (result, NULL, ic, TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* genNearPointerGet - emitcode for near pointer fetch */
8454 /*-----------------------------------------------------------------*/
8456 genNearPointerGet (operand * left,
8465 sym_link *rtype, *retype;
8466 sym_link *ltype = operandType (left);
8469 D(emitcode ("; genNearPointerGet",""));
8471 rtype = operandType (result);
8472 retype = getSpec (rtype);
8474 aopOp (left, ic, FALSE);
8476 /* if left is rematerialisable and
8477 result is not bitfield variable type and
8478 the left is pointer to data space i.e
8479 lower 128 bytes of space */
8480 if (AOP_TYPE (left) == AOP_IMMD &&
8481 !IS_BITFIELD (retype) &&
8482 DCL_TYPE (ltype) == POINTER)
8484 genDataPointerGet (left, result, ic);
8488 /* if the value is already in a pointer register
8489 then don't need anything more */
8490 if (!AOP_INPREG (AOP (left)))
8492 if (IS_AOP_PREG (left))
8494 // Aha, it is a pointer, just in disguise.
8495 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8498 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8499 __FILE__, __LINE__);
8504 emitcode ("mov", "a%s,%s", rname + 1, rname);
8505 rname++; // skip the '@'.
8510 /* otherwise get a free pointer register */
8512 preg = getFreePtr (ic, &aop, FALSE);
8513 emitcode ("mov", "%s,%s",
8515 aopGet (AOP (left), 0, FALSE, TRUE));
8520 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8522 //aopOp (result, ic, FALSE);
8523 aopOp (result, ic, result?TRUE:FALSE);
8525 /* if bitfield then unpack the bits */
8526 if (IS_BITFIELD (retype))
8527 genUnpackBits (result, rname, POINTER, ifx);
8530 /* we have can just get the values */
8531 int size = AOP_SIZE (result);
8536 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8539 emitcode ("mov", "a,@%s", rname);
8541 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8545 sprintf (buffer, "@%s", rname);
8546 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8550 emitcode ("inc", "%s", rname);
8554 /* now some housekeeping stuff */
8555 if (aop) /* we had to allocate for this iCode */
8557 if (pi) { /* post increment present */
8558 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8560 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8564 /* we did not allocate which means left
8565 already in a pointer register, then
8566 if size > 0 && this could be used again
8567 we have to point it back to where it
8569 if ((AOP_SIZE (result) > 1 &&
8570 !OP_SYMBOL (left)->remat &&
8571 (OP_SYMBOL (left)->liveTo > ic->seq ||
8575 int size = AOP_SIZE (result) - 1;
8577 emitcode ("dec", "%s", rname);
8581 if (ifx && !ifx->generated)
8583 genIfxJump (ifx, "a", left, NULL, result);
8587 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8588 freeAsmop (left, NULL, ic, TRUE);
8589 if (pi) pi->generated = 1;
8592 /*-----------------------------------------------------------------*/
8593 /* genPagedPointerGet - emitcode for paged pointer fetch */
8594 /*-----------------------------------------------------------------*/
8596 genPagedPointerGet (operand * left,
8605 sym_link *rtype, *retype;
8607 D(emitcode ("; genPagedPointerGet",""));
8609 rtype = operandType (result);
8610 retype = getSpec (rtype);
8612 aopOp (left, ic, FALSE);
8614 /* if the value is already in a pointer register
8615 then don't need anything more */
8616 if (!AOP_INPREG (AOP (left)))
8618 /* otherwise get a free pointer register */
8620 preg = getFreePtr (ic, &aop, FALSE);
8621 emitcode ("mov", "%s,%s",
8623 aopGet (AOP (left), 0, FALSE, TRUE));
8627 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8629 aopOp (result, ic, FALSE);
8631 /* if bitfield then unpack the bits */
8632 if (IS_BITFIELD (retype))
8633 genUnpackBits (result, rname, PPOINTER, ifx);
8636 /* we have can just get the values */
8637 int size = AOP_SIZE (result);
8643 emitcode ("movx", "a,@%s", rname);
8645 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8650 emitcode ("inc", "%s", rname);
8654 /* now some housekeeping stuff */
8655 if (aop) /* we had to allocate for this iCode */
8657 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8658 freeAsmop (NULL, aop, ic, TRUE);
8662 /* we did not allocate which means left
8663 already in a pointer register, then
8664 if size > 0 && this could be used again
8665 we have to point it back to where it
8667 if ((AOP_SIZE (result) > 1 &&
8668 !OP_SYMBOL (left)->remat &&
8669 (OP_SYMBOL (left)->liveTo > ic->seq ||
8673 int size = AOP_SIZE (result) - 1;
8675 emitcode ("dec", "%s", rname);
8679 if (ifx && !ifx->generated)
8681 genIfxJump (ifx, "a", left, NULL, result);
8685 freeAsmop (left, NULL, ic, TRUE);
8686 freeAsmop (result, NULL, ic, TRUE);
8687 if (pi) pi->generated = 1;
8691 /*--------------------------------------------------------------------*/
8692 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8693 /*--------------------------------------------------------------------*/
8695 loadDptrFromOperand (operand *op, bool loadBToo)
8697 if (AOP_TYPE (op) != AOP_STR)
8699 /* if this is rematerializable */
8700 if (AOP_TYPE (op) == AOP_IMMD)
8702 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8705 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8706 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8709 wassertl(FALSE, "need pointerCode");
8710 emitcode ("", "; mov b,???");
8711 /* genPointerGet and genPointerSet originally did different
8712 ** things for this case. Both seem wrong.
8713 ** from genPointerGet:
8714 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8715 ** from genPointerSet:
8716 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8721 else if (AOP_TYPE (op) == AOP_DPTR)
8725 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8726 emitcode ("push", "acc");
8727 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8728 emitcode ("push", "acc");
8729 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8730 emitcode ("pop", "dph");
8731 emitcode ("pop", "dpl");
8735 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8736 emitcode ("push", "acc");
8737 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8738 emitcode ("pop", "dpl");
8742 { /* we need to get it byte by byte */
8743 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8744 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8746 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8751 /*-----------------------------------------------------------------*/
8752 /* genFarPointerGet - gget value from far space */
8753 /*-----------------------------------------------------------------*/
8755 genFarPointerGet (operand * left,
8756 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8759 sym_link *retype = getSpec (operandType (result));
8761 D(emitcode ("; genFarPointerGet",""));
8763 aopOp (left, ic, FALSE);
8764 loadDptrFromOperand (left, FALSE);
8766 /* so dptr now contains the address */
8767 aopOp (result, ic, FALSE);
8769 /* if bit then unpack */
8770 if (IS_BITFIELD (retype))
8771 genUnpackBits (result, "dptr", FPOINTER, ifx);
8774 size = AOP_SIZE (result);
8779 emitcode ("movx", "a,@dptr");
8781 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8783 emitcode ("inc", "dptr");
8787 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8789 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8790 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8794 if (ifx && !ifx->generated)
8796 genIfxJump (ifx, "a", left, NULL, result);
8799 freeAsmop (left, NULL, ic, TRUE);
8800 freeAsmop (result, NULL, ic, TRUE);
8803 /*-----------------------------------------------------------------*/
8804 /* genCodePointerGet - gget value from code space */
8805 /*-----------------------------------------------------------------*/
8807 genCodePointerGet (operand * left,
8808 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8811 sym_link *retype = getSpec (operandType (result));
8813 D(emitcode ("; genCodePointerGet",""));
8815 aopOp (left, ic, FALSE);
8816 loadDptrFromOperand (left, FALSE);
8818 /* so dptr now contains the address */
8819 aopOp (result, ic, FALSE);
8821 /* if bit then unpack */
8822 if (IS_BITFIELD (retype))
8823 genUnpackBits (result, "dptr", CPOINTER, ifx);
8826 size = AOP_SIZE (result);
8833 emitcode ("clr", "a");
8834 emitcode ("movc", "a,@a+dptr");
8836 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8837 emitcode ("inc", "dptr");
8841 emitcode ("mov", "a,#0x%02x", offset);
8842 emitcode ("movc", "a,@a+dptr");
8844 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8849 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8851 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8852 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8856 if (ifx && !ifx->generated)
8858 genIfxJump (ifx, "a", left, NULL, result);
8861 freeAsmop (left, NULL, ic, TRUE);
8862 freeAsmop (result, NULL, ic, TRUE);
8865 /*-----------------------------------------------------------------*/
8866 /* genGenPointerGet - gget value from generic pointer space */
8867 /*-----------------------------------------------------------------*/
8869 genGenPointerGet (operand * left,
8870 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8873 sym_link *retype = getSpec (operandType (result));
8875 D(emitcode ("; genGenPointerGet",""));
8877 aopOp (left, ic, FALSE);
8878 loadDptrFromOperand (left, TRUE);
8880 /* so dptr know contains the address */
8881 aopOp (result, ic, FALSE);
8883 /* if bit then unpack */
8884 if (IS_BITFIELD (retype))
8885 genUnpackBits (result, "dptr", GPOINTER, ifx);
8888 size = AOP_SIZE (result);
8893 emitcode ("lcall", "__gptrget");
8895 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8897 emitcode ("inc", "dptr");
8901 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8903 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8904 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8908 if (ifx && !ifx->generated)
8910 genIfxJump (ifx, "a", left, NULL, result);
8914 freeAsmop (left, NULL, ic, TRUE);
8915 freeAsmop (result, NULL, ic, TRUE);
8918 /*-----------------------------------------------------------------*/
8919 /* genPointerGet - generate code for pointer get */
8920 /*-----------------------------------------------------------------*/
8922 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8924 operand *left, *result;
8925 sym_link *type, *etype;
8928 D(emitcode ("; genPointerGet",""));
8930 left = IC_LEFT (ic);
8931 result = IC_RESULT (ic);
8933 if (getSize (operandType (result))>1)
8936 /* depending on the type of pointer we need to
8937 move it to the correct pointer register */
8938 type = operandType (left);
8939 etype = getSpec (type);
8940 /* if left is of type of pointer then it is simple */
8941 if (IS_PTR (type) && !IS_FUNC (type->next))
8942 p_type = DCL_TYPE (type);
8945 /* we have to go by the storage class */
8946 p_type = PTR_TYPE (SPEC_OCLS (etype));
8949 /* special case when cast remat */
8950 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8951 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8952 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8953 type = operandType (left);
8954 p_type = DCL_TYPE (type);
8956 /* now that we have the pointer type we assign
8957 the pointer values */
8963 genNearPointerGet (left, result, ic, pi, ifx);
8967 genPagedPointerGet (left, result, ic, pi, ifx);
8971 genFarPointerGet (left, result, ic, pi, ifx);
8975 genCodePointerGet (left, result, ic, pi, ifx);
8979 genGenPointerGet (left, result, ic, pi, ifx);
8987 /*-----------------------------------------------------------------*/
8988 /* genPackBits - generates code for packed bit storage */
8989 /*-----------------------------------------------------------------*/
8991 genPackBits (sym_link * etype,
8993 char *rname, int p_type)
8995 int offset = 0; /* source byte offset */
8996 int rlen = 0; /* remaining bitfield length */
8997 int blen; /* bitfield length */
8998 int bstr; /* bitfield starting bit within byte */
8999 int litval; /* source literal value (if AOP_LIT) */
9000 unsigned char mask; /* bitmask within current byte */
9002 D(emitcode ("; genPackBits",""));
9004 blen = SPEC_BLEN (etype);
9005 bstr = SPEC_BSTR (etype);
9007 /* If the bitfield length is less than a byte */
9010 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9011 (unsigned char) (0xFF >> (8 - bstr)));
9013 if (AOP_TYPE (right) == AOP_LIT)
9015 /* Case with a bitfield length <8 and literal source
9017 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9019 litval &= (~mask) & 0xff;
9020 emitPtrByteGet (rname, p_type, FALSE);
9021 if ((mask|litval)!=0xff)
9022 emitcode ("anl","a,#0x%02x", mask);
9024 emitcode ("orl","a,#0x%02x", litval);
9028 if ((blen==1) && (p_type!=GPOINTER))
9030 /* Case with a bitfield length == 1 and no generic pointer
9032 if (AOP_TYPE (right) == AOP_CRY)
9033 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9036 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9037 emitcode ("rrc","a");
9039 emitPtrByteGet (rname, p_type, FALSE);
9040 emitcode ("mov","acc.%d,c",bstr);
9045 /* Case with a bitfield length < 8 and arbitrary source
9047 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9048 /* shift and mask source value */
9050 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9053 /* transfer A to B and get next byte */
9054 emitPtrByteGet (rname, p_type, TRUE);
9056 emitcode ("anl", "a,#0x%02x", mask);
9057 emitcode ("orl", "a,b");
9058 if (p_type == GPOINTER)
9059 emitcode ("pop", "b");
9065 emitPtrByteSet (rname, p_type, "a");
9069 /* Bit length is greater than 7 bits. In this case, copy */
9070 /* all except the partial byte at the end */
9071 for (rlen=blen;rlen>=8;rlen-=8)
9073 emitPtrByteSet (rname, p_type,
9074 aopGet (AOP (right), offset++, FALSE, TRUE) );
9076 emitcode ("inc", "%s", rname);
9079 /* If there was a partial byte at the end */
9082 mask = (((unsigned char) -1 << rlen) & 0xff);
9084 if (AOP_TYPE (right) == AOP_LIT)
9086 /* Case with partial byte and literal source
9088 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9089 litval >>= (blen-rlen);
9090 litval &= (~mask) & 0xff;
9091 emitPtrByteGet (rname, p_type, FALSE);
9092 if ((mask|litval)!=0xff)
9093 emitcode ("anl","a,#0x%02x", mask);
9095 emitcode ("orl","a,#0x%02x", litval);
9100 /* Case with partial byte and arbitrary source
9102 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9103 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9106 /* transfer A to B and get next byte */
9107 emitPtrByteGet (rname, p_type, TRUE);
9109 emitcode ("anl", "a,#0x%02x", mask);
9110 emitcode ("orl", "a,b");
9111 if (p_type == GPOINTER)
9112 emitcode ("pop", "b");
9116 emitPtrByteSet (rname, p_type, "a");
9122 /*-----------------------------------------------------------------*/
9123 /* genDataPointerSet - remat pointer to data space */
9124 /*-----------------------------------------------------------------*/
9126 genDataPointerSet (operand * right,
9130 int size, offset = 0;
9131 char *l, buffer[256];
9133 D(emitcode ("; genDataPointerSet",""));
9135 aopOp (right, ic, FALSE);
9137 l = aopGet (AOP (result), 0, FALSE, TRUE);
9138 size = AOP_SIZE (right);
9142 sprintf (buffer, "(%s + %d)", l + 1, offset);
9144 sprintf (buffer, "%s", l + 1);
9145 emitcode ("mov", "%s,%s", buffer,
9146 aopGet (AOP (right), offset++, FALSE, FALSE));
9149 freeAsmop (right, NULL, ic, TRUE);
9150 freeAsmop (result, NULL, ic, TRUE);
9153 /*-----------------------------------------------------------------*/
9154 /* genNearPointerSet - emitcode for near pointer put */
9155 /*-----------------------------------------------------------------*/
9157 genNearPointerSet (operand * right,
9165 sym_link *retype, *letype;
9166 sym_link *ptype = operandType (result);
9168 D(emitcode ("; genNearPointerSet",""));
9170 retype = getSpec (operandType (right));
9171 letype = getSpec (ptype);
9172 aopOp (result, ic, FALSE);
9174 /* if the result is rematerializable &
9175 in data space & not a bit variable */
9176 if (AOP_TYPE (result) == AOP_IMMD &&
9177 DCL_TYPE (ptype) == POINTER &&
9178 !IS_BITVAR (retype) &&
9179 !IS_BITVAR (letype))
9181 genDataPointerSet (right, result, ic);
9185 /* if the value is already in a pointer register
9186 then don't need anything more */
9187 if (!AOP_INPREG (AOP (result)))
9190 //AOP_TYPE (result) == AOP_STK
9194 // Aha, it is a pointer, just in disguise.
9195 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9198 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9199 __FILE__, __LINE__);
9204 emitcode ("mov", "a%s,%s", rname + 1, rname);
9205 rname++; // skip the '@'.
9210 /* otherwise get a free pointer register */
9212 preg = getFreePtr (ic, &aop, FALSE);
9213 emitcode ("mov", "%s,%s",
9215 aopGet (AOP (result), 0, FALSE, TRUE));
9221 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9224 aopOp (right, ic, FALSE);
9226 /* if bitfield then unpack the bits */
9227 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9228 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9231 /* we have can just get the values */
9232 int size = AOP_SIZE (right);
9237 l = aopGet (AOP (right), offset, FALSE, TRUE);
9241 emitcode ("mov", "@%s,a", rname);
9244 emitcode ("mov", "@%s,%s", rname, l);
9246 emitcode ("inc", "%s", rname);
9251 /* now some housekeeping stuff */
9252 if (aop) /* we had to allocate for this iCode */
9255 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9256 freeAsmop (NULL, aop, ic, TRUE);
9260 /* we did not allocate which means left
9261 already in a pointer register, then
9262 if size > 0 && this could be used again
9263 we have to point it back to where it
9265 if ((AOP_SIZE (right) > 1 &&
9266 !OP_SYMBOL (result)->remat &&
9267 (OP_SYMBOL (result)->liveTo > ic->seq ||
9271 int size = AOP_SIZE (right) - 1;
9273 emitcode ("dec", "%s", rname);
9278 if (pi) pi->generated = 1;
9279 freeAsmop (result, NULL, ic, TRUE);
9280 freeAsmop (right, NULL, ic, TRUE);
9283 /*-----------------------------------------------------------------*/
9284 /* genPagedPointerSet - emitcode for Paged pointer put */
9285 /*-----------------------------------------------------------------*/
9287 genPagedPointerSet (operand * right,
9295 sym_link *retype, *letype;
9297 D(emitcode ("; genPagedPointerSet",""));
9299 retype = getSpec (operandType (right));
9300 letype = getSpec (operandType (result));
9302 aopOp (result, ic, FALSE);
9304 /* if the value is already in a pointer register
9305 then don't need anything more */
9306 if (!AOP_INPREG (AOP (result)))
9308 /* otherwise get a free pointer register */
9310 preg = getFreePtr (ic, &aop, FALSE);
9311 emitcode ("mov", "%s,%s",
9313 aopGet (AOP (result), 0, FALSE, TRUE));
9317 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9319 aopOp (right, ic, FALSE);
9321 /* if bitfield then unpack the bits */
9322 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9323 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9326 /* we have can just get the values */
9327 int size = AOP_SIZE (right);
9332 l = aopGet (AOP (right), offset, FALSE, TRUE);
9335 emitcode ("movx", "@%s,a", rname);
9338 emitcode ("inc", "%s", rname);
9344 /* now some housekeeping stuff */
9345 if (aop) /* we had to allocate for this iCode */
9348 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9349 freeAsmop (NULL, aop, ic, TRUE);
9353 /* we did not allocate which means left
9354 already in a pointer register, then
9355 if size > 0 && this could be used again
9356 we have to point it back to where it
9358 if (AOP_SIZE (right) > 1 &&
9359 !OP_SYMBOL (result)->remat &&
9360 (OP_SYMBOL (result)->liveTo > ic->seq ||
9363 int size = AOP_SIZE (right) - 1;
9365 emitcode ("dec", "%s", rname);
9370 if (pi) pi->generated = 1;
9371 freeAsmop (result, NULL, ic, TRUE);
9372 freeAsmop (right, NULL, ic, TRUE);
9377 /*-----------------------------------------------------------------*/
9378 /* genFarPointerSet - set value from far space */
9379 /*-----------------------------------------------------------------*/
9381 genFarPointerSet (operand * right,
9382 operand * result, iCode * ic, iCode * pi)
9385 sym_link *retype = getSpec (operandType (right));
9386 sym_link *letype = getSpec (operandType (result));
9388 D(emitcode ("; genFarPointerSet",""));
9390 aopOp (result, ic, FALSE);
9391 loadDptrFromOperand (result, FALSE);
9393 /* so dptr know contains the address */
9394 aopOp (right, ic, FALSE);
9396 /* if bit then unpack */
9397 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9398 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9401 size = AOP_SIZE (right);
9406 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9408 emitcode ("movx", "@dptr,a");
9410 emitcode ("inc", "dptr");
9413 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9414 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9415 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9418 freeAsmop (result, NULL, ic, TRUE);
9419 freeAsmop (right, NULL, ic, TRUE);
9422 /*-----------------------------------------------------------------*/
9423 /* genGenPointerSet - set value from generic pointer space */
9424 /*-----------------------------------------------------------------*/
9426 genGenPointerSet (operand * right,
9427 operand * result, iCode * ic, iCode * pi)
9430 sym_link *retype = getSpec (operandType (right));
9431 sym_link *letype = getSpec (operandType (result));
9433 D(emitcode ("; genGenPointerSet",""));
9435 aopOp (result, ic, FALSE);
9436 loadDptrFromOperand (result, TRUE);
9438 /* so dptr know contains the address */
9439 aopOp (right, ic, FALSE);
9441 /* if bit then unpack */
9442 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9443 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9446 size = AOP_SIZE (right);
9451 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9453 emitcode ("lcall", "__gptrput");
9455 emitcode ("inc", "dptr");
9459 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9460 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9461 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9464 freeAsmop (result, NULL, ic, TRUE);
9465 freeAsmop (right, NULL, ic, TRUE);
9468 /*-----------------------------------------------------------------*/
9469 /* genPointerSet - stores the value into a pointer location */
9470 /*-----------------------------------------------------------------*/
9472 genPointerSet (iCode * ic, iCode *pi)
9474 operand *right, *result;
9475 sym_link *type, *etype;
9478 D(emitcode ("; genPointerSet",""));
9480 right = IC_RIGHT (ic);
9481 result = IC_RESULT (ic);
9483 /* depending on the type of pointer we need to
9484 move it to the correct pointer register */
9485 type = operandType (result);
9486 etype = getSpec (type);
9487 /* if left is of type of pointer then it is simple */
9488 if (IS_PTR (type) && !IS_FUNC (type->next))
9490 p_type = DCL_TYPE (type);
9494 /* we have to go by the storage class */
9495 p_type = PTR_TYPE (SPEC_OCLS (etype));
9498 /* special case when cast remat */
9499 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9500 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9501 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9502 type = operandType (result);
9503 p_type = DCL_TYPE (type);
9505 /* now that we have the pointer type we assign
9506 the pointer values */
9512 genNearPointerSet (right, result, ic, pi);
9516 genPagedPointerSet (right, result, ic, pi);
9520 genFarPointerSet (right, result, ic, pi);
9524 genGenPointerSet (right, result, ic, pi);
9528 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9529 "genPointerSet: illegal pointer type");
9534 /*-----------------------------------------------------------------*/
9535 /* genIfx - generate code for Ifx statement */
9536 /*-----------------------------------------------------------------*/
9538 genIfx (iCode * ic, iCode * popIc)
9540 operand *cond = IC_COND (ic);
9543 D(emitcode ("; genIfx",""));
9545 aopOp (cond, ic, FALSE);
9547 /* get the value into acc */
9548 if (AOP_TYPE (cond) != AOP_CRY)
9552 /* the result is now in the accumulator */
9553 freeAsmop (cond, NULL, ic, TRUE);
9555 /* if there was something to be popped then do it */
9559 /* if the condition is a bit variable */
9560 if (isbit && IS_ITEMP (cond) &&
9562 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9563 else if (isbit && !IS_ITEMP (cond))
9564 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9566 genIfxJump (ic, "a", NULL, NULL, NULL);
9571 /*-----------------------------------------------------------------*/
9572 /* genAddrOf - generates code for address of */
9573 /*-----------------------------------------------------------------*/
9575 genAddrOf (iCode * ic)
9577 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9580 D(emitcode ("; genAddrOf",""));
9582 aopOp (IC_RESULT (ic), ic, FALSE);
9584 /* if the operand is on the stack then we
9585 need to get the stack offset of this
9589 /* if it has an offset then we need to compute
9593 emitcode ("mov", "a,_bp");
9594 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9595 ((char) (sym->stack - _G.nRegsSaved)) :
9596 ((char) sym->stack)) & 0xff);
9597 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9601 /* we can just move _bp */
9602 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9604 /* fill the result with zero */
9605 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9610 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9616 /* object not on stack then we need the name */
9617 size = AOP_SIZE (IC_RESULT (ic));
9622 char s[SDCC_NAME_MAX];
9624 sprintf (s, "#(%s >> %d)",
9628 sprintf (s, "#%s", sym->rname);
9629 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9633 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9637 /*-----------------------------------------------------------------*/
9638 /* genFarFarAssign - assignment when both are in far space */
9639 /*-----------------------------------------------------------------*/
9641 genFarFarAssign (operand * result, operand * right, iCode * ic)
9643 int size = AOP_SIZE (right);
9647 D(emitcode ("; genFarFarAssign",""));
9649 /* first push the right side on to the stack */
9652 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9654 emitcode ("push", "acc");
9657 freeAsmop (right, NULL, ic, FALSE);
9658 /* now assign DPTR to result */
9659 aopOp (result, ic, FALSE);
9660 size = AOP_SIZE (result);
9663 emitcode ("pop", "acc");
9664 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9666 freeAsmop (result, NULL, ic, FALSE);
9670 /*-----------------------------------------------------------------*/
9671 /* genAssign - generate code for assignment */
9672 /*-----------------------------------------------------------------*/
9674 genAssign (iCode * ic)
9676 operand *result, *right;
9678 unsigned long lit = 0L;
9680 D(emitcode("; genAssign",""));
9682 result = IC_RESULT (ic);
9683 right = IC_RIGHT (ic);
9685 /* if they are the same */
9686 if (operandsEqu (result, right) &&
9687 !isOperandVolatile (result, FALSE) &&
9688 !isOperandVolatile (right, FALSE))
9691 aopOp (right, ic, FALSE);
9693 /* special case both in far space */
9694 if (AOP_TYPE (right) == AOP_DPTR &&
9695 IS_TRUE_SYMOP (result) &&
9696 isOperandInFarSpace (result))
9699 genFarFarAssign (result, right, ic);
9703 aopOp (result, ic, TRUE);
9705 /* if they are the same registers */
9706 if (sameRegs (AOP (right), AOP (result)) &&
9707 !isOperandVolatile (result, FALSE) &&
9708 !isOperandVolatile (right, FALSE))
9711 /* if the result is a bit */
9712 if (AOP_TYPE (result) == AOP_CRY)
9715 /* if the right size is a literal then
9716 we know what the value is */
9717 if (AOP_TYPE (right) == AOP_LIT)
9719 if (((int) operandLitValue (right)))
9720 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9722 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9726 /* the right is also a bit variable */
9727 if (AOP_TYPE (right) == AOP_CRY)
9729 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9730 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9736 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9740 /* bit variables done */
9742 size = AOP_SIZE (result);
9744 if (AOP_TYPE (right) == AOP_LIT)
9745 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9747 (AOP_TYPE (result) != AOP_REG) &&
9748 (AOP_TYPE (right) == AOP_LIT) &&
9749 !IS_FLOAT (operandType (right)) &&
9752 while ((size) && (lit))
9754 aopPut (AOP (result),
9755 aopGet (AOP (right), offset, FALSE, FALSE),
9757 isOperandVolatile (result, FALSE));
9762 emitcode ("clr", "a");
9765 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9773 aopPut (AOP (result),
9774 aopGet (AOP (right), offset, FALSE, FALSE),
9776 isOperandVolatile (result, FALSE));
9782 freeAsmop (right, NULL, ic, TRUE);
9783 freeAsmop (result, NULL, ic, TRUE);
9786 /*-----------------------------------------------------------------*/
9787 /* genJumpTab - genrates code for jump table */
9788 /*-----------------------------------------------------------------*/
9790 genJumpTab (iCode * ic)
9792 symbol *jtab,*jtablo,*jtabhi;
9796 D(emitcode ("; genJumpTab",""));
9798 count = elementsInSet( IC_JTLABELS (ic) );
9802 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9803 if the switch argument is in a register.
9804 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9805 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9806 How will multiply by three be updated ???*/
9807 aopOp (IC_JTCOND (ic), ic, FALSE);
9808 /* get the condition into accumulator */
9809 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9811 /* multiply by three */
9812 emitcode ("add", "a,acc");
9813 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9814 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9816 jtab = newiTempLabel (NULL);
9817 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9818 emitcode ("jmp", "@a+dptr");
9819 emitcode ("", "%05d$:", jtab->key + 100);
9820 /* now generate the jump labels */
9821 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9822 jtab = setNextItem (IC_JTLABELS (ic)))
9823 emitcode ("ljmp", "%05d$", jtab->key + 100);
9827 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9828 if the switch argument is in a register.
9829 For n>6 this algorithm may be more compact */
9830 jtablo = newiTempLabel (NULL);
9831 jtabhi = newiTempLabel (NULL);
9833 /* get the condition into accumulator.
9834 Using b as temporary storage, if register push/pop is needed */
9835 aopOp (IC_JTCOND (ic), ic, FALSE);
9836 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9837 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9838 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9840 // (MB) what if B is in use???
9841 wassertl(!_G.BInUse, "B was in use");
9842 emitcode ("mov", "b,%s", l);
9845 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9849 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9850 emitcode ("movc", "a,@a+pc");
9851 emitcode ("push", "acc");
9854 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9855 emitcode ("movc", "a,@a+pc");
9856 emitcode ("push", "acc");
9860 /* this scales up to n<=255, but needs two more bytes
9862 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9863 emitcode ("movc", "a,@a+dptr");
9864 emitcode ("push", "acc");
9867 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9868 emitcode ("movc", "a,@a+dptr");
9869 emitcode ("push", "acc");
9872 emitcode ("ret", "");
9874 /* now generate jump table, LSB */
9875 emitcode ("", "%05d$:", jtablo->key + 100);
9876 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9877 jtab = setNextItem (IC_JTLABELS (ic)))
9878 emitcode (".db", "%05d$", jtab->key + 100);
9880 /* now generate jump table, MSB */
9881 emitcode ("", "%05d$:", jtabhi->key + 100);
9882 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9883 jtab = setNextItem (IC_JTLABELS (ic)))
9884 emitcode (".db", "%05d$>>8", jtab->key + 100);
9888 /*-----------------------------------------------------------------*/
9889 /* genCast - gen code for casting */
9890 /*-----------------------------------------------------------------*/
9892 genCast (iCode * ic)
9894 operand *result = IC_RESULT (ic);
9895 sym_link *ctype = operandType (IC_LEFT (ic));
9896 sym_link *rtype = operandType (IC_RIGHT (ic));
9897 operand *right = IC_RIGHT (ic);
9900 D(emitcode("; genCast",""));
9902 /* if they are equivalent then do nothing */
9903 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9906 aopOp (right, ic, FALSE);
9907 aopOp (result, ic, FALSE);
9909 /* if the result is a bit (and not a bitfield) */
9910 // if (AOP_TYPE (result) == AOP_CRY)
9911 if (IS_BITVAR (OP_SYMBOL (result)->type)
9912 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9914 /* if the right size is a literal then
9915 we know what the value is */
9916 if (AOP_TYPE (right) == AOP_LIT)
9918 if (((int) operandLitValue (right)))
9919 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9921 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9926 /* the right is also a bit variable */
9927 if (AOP_TYPE (right) == AOP_CRY)
9929 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9930 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9936 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9941 /* if they are the same size : or less */
9942 if (AOP_SIZE (result) <= AOP_SIZE (right))
9945 /* if they are in the same place */
9946 if (sameRegs (AOP (right), AOP (result)))
9949 /* if they in different places then copy */
9950 size = AOP_SIZE (result);
9954 aopPut (AOP (result),
9955 aopGet (AOP (right), offset, FALSE, FALSE),
9957 isOperandVolatile (result, FALSE));
9964 /* if the result is of type pointer */
9969 sym_link *type = operandType (right);
9970 sym_link *etype = getSpec (type);
9972 /* pointer to generic pointer */
9973 if (IS_GENPTR (ctype))
9976 p_type = DCL_TYPE (type);
9979 if (SPEC_SCLS(etype)==S_REGISTER) {
9980 // let's assume it is a generic pointer
9983 /* we have to go by the storage class */
9984 p_type = PTR_TYPE (SPEC_OCLS (etype));
9988 /* the first two bytes are known */
9989 size = GPTRSIZE - 1;
9993 aopPut (AOP (result),
9994 aopGet (AOP (right), offset, FALSE, FALSE),
9996 isOperandVolatile (result, FALSE));
9999 /* the last byte depending on type */
10001 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10006 // pointerTypeToGPByte will have bitched.
10010 sprintf(gpValStr, "#0x%d", gpVal);
10011 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10016 /* just copy the pointers */
10017 size = AOP_SIZE (result);
10021 aopPut (AOP (result),
10022 aopGet (AOP (right), offset, FALSE, FALSE),
10024 isOperandVolatile (result, FALSE));
10030 /* so we now know that the size of destination is greater
10031 than the size of the source */
10032 /* we move to result for the size of source */
10033 size = AOP_SIZE (right);
10037 aopPut (AOP (result),
10038 aopGet (AOP (right), offset, FALSE, FALSE),
10040 isOperandVolatile (result, FALSE));
10044 /* now depending on the sign of the source && destination */
10045 size = AOP_SIZE (result) - AOP_SIZE (right);
10046 /* if unsigned or not an integral type */
10047 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10050 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10054 /* we need to extend the sign :{ */
10055 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10058 emitcode ("rlc", "a");
10059 emitcode ("subb", "a,acc");
10061 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10064 /* we are done hurray !!!! */
10067 freeAsmop (right, NULL, ic, TRUE);
10068 freeAsmop (result, NULL, ic, TRUE);
10072 /*-----------------------------------------------------------------*/
10073 /* genDjnz - generate decrement & jump if not zero instrucion */
10074 /*-----------------------------------------------------------------*/
10076 genDjnz (iCode * ic, iCode * ifx)
10078 symbol *lbl, *lbl1;
10082 D(emitcode ("; genDjnz",""));
10084 /* if the if condition has a false label
10085 then we cannot save */
10086 if (IC_FALSE (ifx))
10089 /* if the minus is not of the form
10091 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10092 !IS_OP_LITERAL (IC_RIGHT (ic)))
10095 if (operandLitValue (IC_RIGHT (ic)) != 1)
10098 /* if the size of this greater than one then no
10100 if (getSize (operandType (IC_RESULT (ic))) > 1)
10103 /* otherwise we can save BIG */
10104 lbl = newiTempLabel (NULL);
10105 lbl1 = newiTempLabel (NULL);
10107 aopOp (IC_RESULT (ic), ic, FALSE);
10109 if (AOP_NEEDSACC(IC_RESULT(ic)))
10111 /* If the result is accessed indirectly via
10112 * the accumulator, we must explicitly write
10113 * it back after the decrement.
10115 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10117 if (strcmp(rByte, "a"))
10119 /* Something is hopelessly wrong */
10120 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10121 __FILE__, __LINE__);
10122 /* We can just give up; the generated code will be inefficient,
10123 * but what the hey.
10125 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10128 emitcode ("dec", "%s", rByte);
10129 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10130 emitcode ("jnz", "%05d$", lbl->key + 100);
10132 else if (IS_AOP_PREG (IC_RESULT (ic)))
10134 emitcode ("dec", "%s",
10135 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10136 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10137 emitcode ("jnz", "%05d$", lbl->key + 100);
10141 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10144 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10145 emitcode ("", "%05d$:", lbl->key + 100);
10146 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10147 emitcode ("", "%05d$:", lbl1->key + 100);
10149 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10150 ifx->generated = 1;
10154 /*-----------------------------------------------------------------*/
10155 /* genReceive - generate code for a receive iCode */
10156 /*-----------------------------------------------------------------*/
10158 genReceive (iCode * ic)
10160 int size = getSize (operandType (IC_RESULT (ic)));
10162 D(emitcode ("; genReceive",""));
10164 if (ic->argreg == 1) { /* first parameter */
10165 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10166 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10167 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10170 int receivingA = 0;
10173 for (offset = 0; offset<size; offset++)
10174 if (!strcmp (fReturn[offset], "a"))
10179 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10181 for (offset = size-1; offset>0; offset--)
10182 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10183 emitcode("mov","a,%s", fReturn[0]);
10185 aopOp (IC_RESULT (ic), ic, FALSE);
10187 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10188 isOperandVolatile (IC_RESULT (ic), FALSE));
10189 for (offset = 1; offset<size; offset++)
10190 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10191 isOperandVolatile (IC_RESULT (ic), FALSE));
10197 if (getTempRegs(tempRegs, size, ic))
10199 for (offset = 0; offset<size; offset++)
10200 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10201 aopOp (IC_RESULT (ic), ic, FALSE);
10202 for (offset = 0; offset<size; offset++)
10203 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10204 isOperandVolatile (IC_RESULT (ic), FALSE));
10209 offset = fReturnSizeMCS51 - size;
10211 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10212 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10215 aopOp (IC_RESULT (ic), ic, FALSE);
10216 size = AOP_SIZE (IC_RESULT (ic));
10219 emitcode ("pop", "acc");
10220 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10225 aopOp (IC_RESULT (ic), ic, FALSE);
10227 assignResultValue (IC_RESULT (ic));
10229 } else { /* second receive onwards */
10231 aopOp (IC_RESULT (ic), ic, FALSE);
10232 rb1off = ic->argreg;
10234 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10239 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10242 /*-----------------------------------------------------------------*/
10243 /* genDummyRead - generate code for dummy read of volatiles */
10244 /*-----------------------------------------------------------------*/
10246 genDummyRead (iCode * ic)
10251 D(emitcode("; genDummyRead",""));
10253 op = IC_RIGHT (ic);
10254 if (op && IS_SYMOP (op))
10256 aopOp (op, ic, FALSE);
10258 /* if the result is a bit */
10259 if (AOP_TYPE (op) == AOP_CRY)
10260 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10263 /* bit variables done */
10265 size = AOP_SIZE (op);
10269 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10274 freeAsmop (op, NULL, ic, TRUE);
10278 if (op && IS_SYMOP (op))
10280 aopOp (op, ic, FALSE);
10282 /* if the result is a bit */
10283 if (AOP_TYPE (op) == AOP_CRY)
10284 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10287 /* bit variables done */
10289 size = AOP_SIZE (op);
10293 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10298 freeAsmop (op, NULL, ic, TRUE);
10302 /*-----------------------------------------------------------------*/
10303 /* genCritical - generate code for start of a critical sequence */
10304 /*-----------------------------------------------------------------*/
10306 genCritical (iCode *ic)
10308 symbol *tlbl = newiTempLabel (NULL);
10310 D(emitcode("; genCritical",""));
10312 if (IC_RESULT (ic))
10314 aopOp (IC_RESULT (ic), ic, TRUE);
10315 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10316 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10317 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10318 emitcode ("", "%05d$:", (tlbl->key + 100));
10319 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10323 emitcode ("setb", "c");
10324 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10325 emitcode ("clr", "c");
10326 emitcode ("", "%05d$:", (tlbl->key + 100));
10327 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10331 /*-----------------------------------------------------------------*/
10332 /* genEndCritical - generate code for end of a critical sequence */
10333 /*-----------------------------------------------------------------*/
10335 genEndCritical (iCode *ic)
10337 D(emitcode("; genEndCritical",""));
10341 aopOp (IC_RIGHT (ic), ic, FALSE);
10342 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10344 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10345 emitcode ("mov", "ea,c");
10349 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10350 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10351 emitcode ("rrc", "a");
10352 emitcode ("mov", "ea,c");
10354 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10358 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10359 emitcode ("mov", "ea,c");
10363 /*-----------------------------------------------------------------*/
10364 /* gen51Code - generate code for 8051 based controllers */
10365 /*-----------------------------------------------------------------*/
10367 gen51Code (iCode * lic)
10371 /* int cseq = 0; */
10373 _G.currentFunc = NULL;
10374 lineHead = lineCurr = NULL;
10376 /* print the allocation information */
10377 if (allocInfo && currFunc)
10378 printAllocInfo (currFunc, codeOutFile);
10379 /* if debug information required */
10380 if (options.debug && currFunc)
10382 debugFile->writeFunction (currFunc, lic);
10384 /* stack pointer name */
10385 if (options.useXstack)
10391 for (ic = lic; ic; ic = ic->next)
10393 _G.current_iCode = ic;
10395 if (ic->lineno && cln != ic->lineno)
10399 debugFile->writeCLine (ic);
10401 if (!options.noCcodeInAsm) {
10402 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10403 printCLine(ic->filename, ic->lineno));
10408 if (ic->seqPoint && ic->seqPoint != cseq)
10410 emitcode ("", "; sequence point %d", ic->seqPoint);
10411 cseq = ic->seqPoint;
10414 if (options.iCodeInAsm) {
10415 char regsInUse[80];
10418 for (i=0; i<8; i++) {
10419 sprintf (®sInUse[i],
10420 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10423 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10425 /* if the result is marked as
10426 spilt and rematerializable or code for
10427 this has already been generated then
10429 if (resultRemat (ic) || ic->generated)
10432 /* depending on the operation */
10452 /* IPOP happens only when trying to restore a
10453 spilt live range, if there is an ifx statement
10454 following this pop then the if statement might
10455 be using some of the registers being popped which
10456 would destory the contents of the register so
10457 we need to check for this condition and handle it */
10459 ic->next->op == IFX &&
10460 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10461 genIfx (ic->next, ic);
10479 genEndFunction (ic);
10499 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10516 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10520 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10527 /* note these two are xlated by algebraic equivalence
10528 during parsing SDCC.y */
10529 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10530 "got '>=' or '<=' shouldn't have come here");
10534 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10546 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10550 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10554 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10578 genRightShift (ic);
10581 case GET_VALUE_AT_ADDRESS:
10583 hasInc (IC_LEFT (ic), ic,
10584 getSize (operandType (IC_RESULT (ic)))),
10585 ifxForOp (IC_RESULT (ic), ic) );
10589 if (POINTER_SET (ic))
10590 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10616 addSet (&_G.sendSet, ic);
10619 case DUMMY_READ_VOLATILE:
10628 genEndCritical (ic);
10640 _G.current_iCode = NULL;
10642 /* now we are ready to call the
10643 peep hole optimizer */
10644 if (!options.nopeep)
10645 peepHole (&lineHead);
10647 /* now do the actual printing */
10648 printLine (lineHead, codeOutFile);