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 /*-----------------------------------------------------------------*/
1672 D(emitcode ("; genCpl",""));
1674 /* assign asmOps to operand & result */
1675 aopOp (IC_LEFT (ic), ic, FALSE);
1676 aopOp (IC_RESULT (ic), ic, TRUE);
1678 /* special case if in bit space */
1679 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1681 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1683 /* promotion rules are responsible for this strange result: */
1684 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1688 tlbl=newiTempLabel(NULL);
1689 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1690 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1691 IS_AOP_PREG (IC_LEFT (ic)))
1693 emitcode ("cjne", "%s,#0x01,%05d$",
1694 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1699 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1701 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1703 emitcode ("", "%05d$:", tlbl->key + 100);
1704 outBitC (IC_RESULT(ic));
1708 size = AOP_SIZE (IC_RESULT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1713 emitcode ("cpl", "a");
1714 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1719 /* release the aops */
1720 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1721 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1724 /*-----------------------------------------------------------------*/
1725 /* genUminusFloat - unary minus for floating points */
1726 /*-----------------------------------------------------------------*/
1728 genUminusFloat (operand * op, operand * result)
1730 int size, offset = 0;
1733 D(emitcode ("; genUminusFloat",""));
1735 /* for this we just copy and then flip the bit */
1737 size = AOP_SIZE (op) - 1;
1741 aopPut (AOP (result),
1742 aopGet (AOP (op), offset, FALSE, FALSE),
1744 isOperandVolatile (result, FALSE));
1748 l = aopGet (AOP (op), offset, FALSE, FALSE);
1752 emitcode ("cpl", "acc.7");
1753 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1756 /*-----------------------------------------------------------------*/
1757 /* genUminus - unary minus code generation */
1758 /*-----------------------------------------------------------------*/
1760 genUminus (iCode * ic)
1763 sym_link *optype, *rtype;
1766 D(emitcode ("; genUminus",""));
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1770 aopOp (IC_RESULT (ic), ic, TRUE);
1772 /* if both in bit space then special
1774 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1775 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1778 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1779 emitcode ("cpl", "c");
1780 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1784 optype = operandType (IC_LEFT (ic));
1785 rtype = operandType (IC_RESULT (ic));
1787 /* if float then do float stuff */
1788 if (IS_FLOAT (optype))
1790 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1794 /* otherwise subtract from zero */
1795 size = AOP_SIZE (IC_LEFT (ic));
1800 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1801 if (!strcmp (l, "a"))
1805 emitcode ("cpl", "a");
1806 emitcode ("addc", "a,#0");
1812 emitcode ("clr", "a");
1813 emitcode ("subb", "a,%s", l);
1815 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1818 /* if any remaining bytes in the result */
1819 /* we just need to propagate the sign */
1820 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1822 emitcode ("rlc", "a");
1823 emitcode ("subb", "a,acc");
1825 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1829 /* release the aops */
1830 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1831 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1834 /*-----------------------------------------------------------------*/
1835 /* saveRegisters - will look for a call and save the registers */
1836 /*-----------------------------------------------------------------*/
1838 saveRegisters (iCode * lic)
1845 for (ic = lic; ic; ic = ic->next)
1846 if (ic->op == CALL || ic->op == PCALL)
1851 fprintf (stderr, "found parameter push with no function call\n");
1855 /* if the registers have been saved already or don't need to be then
1859 if (IS_SYMOP(IC_LEFT(ic)) &&
1860 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1861 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1864 /* save the registers in use at this time but skip the
1865 ones for the result */
1866 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1867 mcs51_rUmaskForOp (IC_RESULT(ic)));
1870 if (options.useXstack)
1872 int count = bitVectnBitsOn (rsave);
1876 i = bitVectFirstBit (rsave);
1877 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1878 emitcode ("mov", "r0,%s", spname);
1879 emitcode ("inc", "%s", spname);// allocate before use
1880 emitcode ("movx", "@r0,a");
1881 if (bitVectBitValue (rsave, R0_IDX))
1882 emitcode ("mov", "r0,a");
1884 else if (count != 0)
1886 if (bitVectBitValue (rsave, R0_IDX))
1888 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1890 emitcode ("mov", "r0,%s", spname);
1892 emitcode ("add", "a,#%d", count);
1893 emitcode ("mov", "%s,a", spname);
1894 for (i = 0; i < mcs51_nRegs; i++)
1896 if (bitVectBitValue (rsave, i))
1900 emitcode ("pop", "acc");
1901 emitcode ("push", "acc");
1905 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1907 emitcode ("movx", "@r0,a");
1910 emitcode ("inc", "r0");
1914 if (bitVectBitValue (rsave, R0_IDX))
1916 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1921 for (i = 0; i < mcs51_nRegs; i++)
1923 if (bitVectBitValue (rsave, i))
1924 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1928 /*-----------------------------------------------------------------*/
1929 /* unsaveRegisters - pop the pushed registers */
1930 /*-----------------------------------------------------------------*/
1932 unsaveRegisters (iCode * ic)
1937 /* restore the registers in use at this time but skip the
1938 ones for the result */
1939 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1940 mcs51_rUmaskForOp (IC_RESULT(ic)));
1942 if (options.useXstack)
1944 int count = bitVectnBitsOn (rsave);
1948 emitcode ("mov", "r0,%s", spname);
1949 emitcode ("dec", "r0");
1950 emitcode ("movx", "a,@r0");
1951 i = bitVectFirstBit (rsave);
1952 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1953 emitcode ("dec", "%s", spname);
1957 emitcode ("mov", "r0,%s", spname);
1958 for (i = mcs51_nRegs; i >= 0; i--)
1960 if (bitVectBitValue (rsave, i))
1962 emitcode ("dec", "r0");
1963 emitcode ("movx", "a,@r0");
1965 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1968 emitcode ("mov", "%s,r0", spname);
1969 if (bitVectBitValue (rsave, R0_IDX))
1971 emitcode ("mov", "r0,a");
1976 for (i = mcs51_nRegs; i >= 0; i--)
1978 if (bitVectBitValue (rsave, i))
1979 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1984 /*-----------------------------------------------------------------*/
1986 /*-----------------------------------------------------------------*/
1988 pushSide (operand * oper, int size)
1993 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1994 if (AOP_TYPE (oper) != AOP_REG &&
1995 AOP_TYPE (oper) != AOP_DIR &&
1999 emitcode ("push", "acc");
2002 emitcode ("push", "%s", l);
2006 /*-----------------------------------------------------------------*/
2007 /* assignResultValue - */
2008 /*-----------------------------------------------------------------*/
2010 assignResultValue (operand * oper)
2013 int size = AOP_SIZE (oper);
2016 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2022 /*-----------------------------------------------------------------*/
2023 /* genXpush - pushes onto the external stack */
2024 /*-----------------------------------------------------------------*/
2026 genXpush (iCode * ic)
2028 asmop *aop = newAsmop (0);
2030 int size, offset = 0;
2032 D(emitcode ("; genXpush",""));
2034 aopOp (IC_LEFT (ic), ic, FALSE);
2035 r = getFreePtr (ic, &aop, FALSE);
2037 size = AOP_SIZE (IC_LEFT (ic));
2041 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2042 emitcode ("mov", "%s,%s", r->name, spname);
2043 emitcode ("inc", "%s", spname); // allocate space first
2044 emitcode ("movx", "@%s,a", r->name);
2048 // allocate space first
2049 emitcode ("mov", "%s,%s", r->name, spname);
2051 emitcode ("add", "a,#%d", size);
2052 emitcode ("mov", "%s,a", spname);
2056 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2057 emitcode ("movx", "@%s,a", r->name);
2058 emitcode ("inc", "%s", r->name);
2062 freeAsmop (NULL, aop, ic, TRUE);
2063 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2066 /*-----------------------------------------------------------------*/
2067 /* genIpush - genrate code for pushing this gets a little complex */
2068 /*-----------------------------------------------------------------*/
2070 genIpush (iCode * ic)
2072 int size, offset = 0;
2075 D(emitcode ("; genIpush",""));
2077 /* if this is not a parm push : ie. it is spill push
2078 and spill push is always done on the local stack */
2082 /* and the item is spilt then do nothing */
2083 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2086 aopOp (IC_LEFT (ic), ic, FALSE);
2087 size = AOP_SIZE (IC_LEFT (ic));
2088 /* push it on the stack */
2091 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2097 emitcode ("push", "%s", l);
2102 /* this is a paramter push: in this case we call
2103 the routine to find the call and save those
2104 registers that need to be saved */
2107 /* if use external stack then call the external
2108 stack pushing routine */
2109 if (options.useXstack)
2115 /* then do the push */
2116 aopOp (IC_LEFT (ic), ic, FALSE);
2118 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2119 size = AOP_SIZE (IC_LEFT (ic));
2123 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2124 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2125 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2129 emitcode ("push", "acc");
2132 emitcode ("push", "%s", l);
2135 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2138 /*-----------------------------------------------------------------*/
2139 /* genIpop - recover the registers: can happen only for spilling */
2140 /*-----------------------------------------------------------------*/
2142 genIpop (iCode * ic)
2146 D(emitcode ("; genIpop",""));
2148 /* if the temp was not pushed then */
2149 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2152 aopOp (IC_LEFT (ic), ic, FALSE);
2153 size = AOP_SIZE (IC_LEFT (ic));
2154 offset = (size - 1);
2156 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2159 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2162 /*-----------------------------------------------------------------*/
2163 /* saveRBank - saves an entire register bank on the stack */
2164 /*-----------------------------------------------------------------*/
2166 saveRBank (int bank, iCode * ic, bool pushPsw)
2169 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2173 if (options.useXstack)
2177 /* Assume r0 is available for use. */
2178 r = mcs51_regWithIdx (R0_IDX);;
2183 r = getFreePtr (ic, &aop, FALSE);
2185 // allocate space first
2186 emitcode ("mov", "%s,%s", r->name, spname);
2188 emitcode ("add", "a,#%d", count);
2189 emitcode ("mov", "%s,a", spname);
2192 for (i = 0; i < mcs51_nRegs; i++)
2194 if (options.useXstack)
2196 emitcode ("mov", "a,(%s+%d)",
2197 regs8051[i].base, 8 * bank + regs8051[i].offset);
2198 emitcode ("movx", "@%s,a", r->name);
2200 emitcode ("inc", "%s", r->name);
2203 emitcode ("push", "(%s+%d)",
2204 regs8051[i].base, 8 * bank + regs8051[i].offset);
2209 if (options.useXstack)
2211 emitcode ("mov", "a,psw");
2212 emitcode ("movx", "@%s,a", r->name);
2217 emitcode ("push", "psw");
2220 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2225 freeAsmop (NULL, aop, ic, TRUE);
2234 /*-----------------------------------------------------------------*/
2235 /* unsaveRBank - restores the register bank from stack */
2236 /*-----------------------------------------------------------------*/
2238 unsaveRBank (int bank, iCode * ic, bool popPsw)
2244 if (options.useXstack)
2248 /* Assume r0 is available for use. */
2249 r = mcs51_regWithIdx (R0_IDX);;
2254 r = getFreePtr (ic, &aop, FALSE);
2256 emitcode ("mov", "%s,%s", r->name, spname);
2261 if (options.useXstack)
2263 emitcode ("dec", "%s", r->name);
2264 emitcode ("movx", "a,@%s", r->name);
2265 emitcode ("mov", "psw,a");
2269 emitcode ("pop", "psw");
2273 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2275 if (options.useXstack)
2277 emitcode ("dec", "%s", r->name);
2278 emitcode ("movx", "a,@%s", r->name);
2279 emitcode ("mov", "(%s+%d),a",
2280 regs8051[i].base, 8 * bank + regs8051[i].offset);
2284 emitcode ("pop", "(%s+%d)",
2285 regs8051[i].base, 8 * bank + regs8051[i].offset);
2289 if (options.useXstack)
2291 emitcode ("mov", "%s,%s", spname, r->name);
2296 freeAsmop (NULL, aop, ic, TRUE);
2300 /*-----------------------------------------------------------------*/
2301 /* genSend - gen code for SEND */
2302 /*-----------------------------------------------------------------*/
2303 static void genSend(set *sendSet)
2308 for (sic = setFirstItem (sendSet); sic;
2309 sic = setNextItem (sendSet)) {
2310 int size, offset = 0;
2311 aopOp (IC_LEFT (sic), sic, FALSE);
2312 size = AOP_SIZE (IC_LEFT (sic));
2314 if (sic->argreg == 1) {
2316 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2318 if (strcmp (l, fReturn[offset]))
2319 emitcode ("mov", "%s,%s", fReturn[offset], l);
2325 emitcode ("mov","b1_%d,%s",rb1_count++,
2326 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2329 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2333 /*-----------------------------------------------------------------*/
2334 /* genCall - generates a call statement */
2335 /*-----------------------------------------------------------------*/
2337 genCall (iCode * ic)
2340 // bool restoreBank = FALSE;
2341 bool swapBanks = FALSE;
2343 D(emitcode("; genCall",""));
2345 dtype = operandType (IC_LEFT (ic));
2346 /* if send set is not empty then assign */
2349 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2350 genSend(reverseSet(_G.sendSet));
2352 genSend(_G.sendSet);
2358 /* if we are calling a not _naked function that is not using
2359 the same register bank then we need to save the
2360 destination registers on the stack */
2361 dtype = operandType (IC_LEFT (ic));
2362 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2363 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2364 !IFFUNC_ISISR (dtype))
2369 /* if caller saves & we have not saved then */
2375 emitcode ("mov", "psw,#0x%02x",
2376 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2380 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2381 OP_SYMBOL (IC_LEFT (ic))->rname :
2382 OP_SYMBOL (IC_LEFT (ic))->name));
2386 emitcode ("mov", "psw,#0x%02x",
2387 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2390 /* if we need assign a result value */
2391 if ((IS_ITEMP (IC_RESULT (ic)) &&
2392 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2393 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2394 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2395 IS_TRUE_SYMOP (IC_RESULT (ic)))
2399 aopOp (IC_RESULT (ic), ic, FALSE);
2402 assignResultValue (IC_RESULT (ic));
2404 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2407 /* adjust the stack for parameters if
2412 if (ic->parmBytes > 3)
2414 emitcode ("mov", "a,%s", spname);
2415 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2416 emitcode ("mov", "%s,a", spname);
2419 for (i = 0; i < ic->parmBytes; i++)
2420 emitcode ("dec", "%s", spname);
2423 /* if we hade saved some registers then unsave them */
2424 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2425 unsaveRegisters (ic);
2427 // /* if register bank was saved then pop them */
2429 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2432 /*-----------------------------------------------------------------*/
2433 /* -10l - generates a call by pointer statement */
2434 /*-----------------------------------------------------------------*/
2436 genPcall (iCode * ic)
2439 symbol *rlbl = newiTempLabel (NULL);
2440 // bool restoreBank=FALSE;
2441 bool swapBanks = FALSE;
2443 D(emitcode("; genPCall",""));
2445 /* if caller saves & we have not saved then */
2449 /* if we are calling a not _naked function that is not using
2450 the same register bank then we need to save the
2451 destination registers on the stack */
2452 dtype = operandType (IC_LEFT (ic))->next;
2453 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2454 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2455 !IFFUNC_ISISR (dtype))
2457 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2458 // restoreBank=TRUE;
2460 // need caution message to user here
2463 /* push the return address on to the stack */
2464 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2465 emitcode ("push", "acc");
2466 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2467 emitcode ("push", "acc");
2469 /* now push the calling address */
2470 aopOp (IC_LEFT (ic), ic, FALSE);
2472 pushSide (IC_LEFT (ic), FPTRSIZE);
2474 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2476 /* if send set is not empty the assign */
2479 genSend(reverseSet(_G.sendSet));
2485 emitcode ("mov", "psw,#0x%02x",
2486 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2490 emitcode ("ret", "");
2491 emitcode ("", "%05d$:", (rlbl->key + 100));
2496 emitcode ("mov", "psw,#0x%02x",
2497 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2500 /* if we need assign a result value */
2501 if ((IS_ITEMP (IC_RESULT (ic)) &&
2502 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2503 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2504 IS_TRUE_SYMOP (IC_RESULT (ic)))
2508 aopOp (IC_RESULT (ic), ic, FALSE);
2511 assignResultValue (IC_RESULT (ic));
2513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2516 /* adjust the stack for parameters if
2521 if (ic->parmBytes > 3)
2523 emitcode ("mov", "a,%s", spname);
2524 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2525 emitcode ("mov", "%s,a", spname);
2528 for (i = 0; i < ic->parmBytes; i++)
2529 emitcode ("dec", "%s", spname);
2533 // /* if register bank was saved then unsave them */
2535 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2537 /* if we hade saved some registers then
2539 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2540 unsaveRegisters (ic);
2543 /*-----------------------------------------------------------------*/
2544 /* resultRemat - result is rematerializable */
2545 /*-----------------------------------------------------------------*/
2547 resultRemat (iCode * ic)
2549 if (SKIP_IC (ic) || ic->op == IFX)
2552 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2554 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2555 if (sym->remat && !POINTER_SET (ic))
2562 #if defined(__BORLANDC__) || defined(_MSC_VER)
2563 #define STRCASECMP stricmp
2565 #define STRCASECMP strcasecmp
2568 /*-----------------------------------------------------------------*/
2569 /* inExcludeList - return 1 if the string is in exclude Reg list */
2570 /*-----------------------------------------------------------------*/
2572 regsCmp(void *p1, void *p2)
2574 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2578 inExcludeList (char *s)
2580 const char *p = setFirstItem(options.excludeRegsSet);
2582 if (p == NULL || STRCASECMP(p, "none") == 0)
2586 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2589 /*-----------------------------------------------------------------*/
2590 /* genFunction - generated code for function entry */
2591 /*-----------------------------------------------------------------*/
2593 genFunction (iCode * ic)
2595 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2597 bool switchedPSW = FALSE;
2598 int calleesaves_saved_register = -1;
2599 int stackAdjust = sym->stack;
2600 int accIsFree = sym->recvSize < 4;
2601 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2602 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2605 /* create the function header */
2606 emitcode (";", "-----------------------------------------");
2607 emitcode (";", " function %s", sym->name);
2608 emitcode (";", "-----------------------------------------");
2610 emitcode ("", "%s:", sym->rname);
2611 ftype = operandType (IC_LEFT (ic));
2612 _G.currentFunc = sym;
2614 if (IFFUNC_ISNAKED(ftype))
2616 emitcode(";", "naked function: no prologue.");
2620 /* here we need to generate the equates for the
2621 register bank if required */
2622 if (FUNC_REGBANK (ftype) != rbank)
2626 rbank = FUNC_REGBANK (ftype);
2627 for (i = 0; i < mcs51_nRegs; i++)
2629 if (strcmp (regs8051[i].base, "0") == 0)
2630 emitcode ("", "%s = 0x%02x",
2632 8 * rbank + regs8051[i].offset);
2634 emitcode ("", "%s = %s + 0x%02x",
2637 8 * rbank + regs8051[i].offset);
2641 /* if this is an interrupt service routine then
2642 save acc, b, dpl, dph */
2643 if (IFFUNC_ISISR (sym->type))
2646 if (!inExcludeList ("acc"))
2647 emitcode ("push", "acc");
2648 if (!inExcludeList ("b"))
2649 emitcode ("push", "b");
2650 if (!inExcludeList ("dpl"))
2651 emitcode ("push", "dpl");
2652 if (!inExcludeList ("dph"))
2653 emitcode ("push", "dph");
2654 /* if this isr has no bank i.e. is going to
2655 run with bank 0 , then we need to save more
2657 if (!FUNC_REGBANK (sym->type))
2660 /* if this function does not call any other
2661 function then we can be economical and
2662 save only those registers that are used */
2663 if (!IFFUNC_HASFCALL(sym->type))
2667 /* if any registers used */
2670 /* save the registers used */
2671 for (i = 0; i < sym->regsUsed->size; i++)
2673 if (bitVectBitValue (sym->regsUsed, i))
2674 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2681 /* this function has a function call. We cannot
2682 determines register usage so we will have to push the
2684 saveRBank (0, ic, FALSE);
2685 if (options.parms_in_bank1) {
2687 for (i=0; i < 8 ; i++ ) {
2688 emitcode ("push","%s",rb1regs[i]);
2695 /* This ISR uses a non-zero bank.
2697 * We assume that the bank is available for our
2700 * However, if this ISR calls a function which uses some
2701 * other bank, we must save that bank entirely.
2703 unsigned long banksToSave = 0;
2705 if (IFFUNC_HASFCALL(sym->type))
2708 #define MAX_REGISTER_BANKS 4
2713 for (i = ic; i; i = i->next)
2715 if (i->op == ENDFUNCTION)
2717 /* we got to the end OK. */
2725 dtype = operandType (IC_LEFT(i));
2727 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2729 /* Mark this bank for saving. */
2730 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2732 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2736 banksToSave |= (1 << FUNC_REGBANK(dtype));
2739 /* And note that we don't need to do it in
2747 /* This is a mess; we have no idea what
2748 * register bank the called function might
2751 * The only thing I can think of to do is
2752 * throw a warning and hope.
2754 werror(W_FUNCPTR_IN_USING_ISR);
2758 if (banksToSave && options.useXstack)
2760 /* Since we aren't passing it an ic,
2761 * saveRBank will assume r0 is available to abuse.
2763 * So switch to our (trashable) bank now, so
2764 * the caller's R0 isn't trashed.
2766 emitcode ("push", "psw");
2767 emitcode ("mov", "psw,#0x%02x",
2768 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2772 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2774 if (banksToSave & (1 << ix))
2776 saveRBank(ix, NULL, FALSE);
2780 // TODO: this needs a closer look
2781 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2784 /* Set the register bank to the desired value if nothing else */
2785 /* has done so yet. */
2788 emitcode ("push", "psw");
2789 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2794 /* This is a non-ISR function. The caller has already switched register */
2795 /* banks, if necessary, so just handle the callee-saves option. */
2797 /* if callee-save to be used for this function
2798 then save the registers being used in this function */
2799 if (IFFUNC_CALLEESAVES(sym->type))
2803 /* if any registers used */
2806 /* save the registers used */
2807 for (i = 0; i < sym->regsUsed->size; i++)
2809 if (bitVectBitValue (sym->regsUsed, i))
2811 /* remember one saved register for later usage */
2812 if (calleesaves_saved_register < 0)
2813 calleesaves_saved_register = i;
2814 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2825 if (options.useXstack)
2827 emitcode ("mov", "r0,%s", spname);
2828 emitcode ("inc", "%s", spname);
2829 emitcode ("xch", "a,_bp");
2830 emitcode ("movx", "@r0,a");
2831 emitcode ("inc", "r0");
2832 emitcode ("mov", "a,r0");
2833 emitcode ("xch", "a,_bp");
2837 /* set up the stack */
2838 emitcode ("push", "_bp"); /* save the callers stack */
2839 emitcode ("mov", "_bp,%s", spname);
2843 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2844 /* before setting up the stack frame completely. */
2845 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2847 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2851 if (rsym && rsym->regType == REG_CND)
2853 if (rsym && (rsym->accuse || rsym->ruonly))
2855 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2856 rsym = rsym->usl.spillLoc;
2859 /* If the RECEIVE operand immediately spills to the first entry on the */
2860 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2861 /* rather than the usual @r0/r1 machinations. */
2862 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2866 _G.current_iCode = ric;
2867 D(emitcode ("; genReceive",""));
2868 for (ofs=0; ofs < sym->recvSize; ofs++)
2870 if (!strcmp (fReturn[ofs], "a"))
2871 emitcode ("push", "acc");
2873 emitcode ("push", fReturn[ofs]);
2875 stackAdjust -= sym->recvSize;
2878 assert (stackAdjust>=0);
2881 _G.current_iCode = ic;
2885 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2886 /* to free up the accumulator. */
2887 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2891 _G.current_iCode = ric;
2892 D(emitcode ("; genReceive",""));
2893 for (ofs=0; ofs < sym->recvSize; ofs++)
2895 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2897 _G.current_iCode = ic;
2903 /* adjust the stack for the function */
2906 int i = stackAdjust;
2908 werror (W_STACK_OVERFLOW, sym->name);
2910 if (i > 3 && accIsFree)
2912 emitcode ("mov", "a,sp");
2913 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2914 emitcode ("mov", "sp,a");
2918 /* The accumulator is not free, so we will need another register */
2919 /* to clobber. No need to worry about a possible conflict with */
2920 /* the above early RECEIVE optimizations since they would have */
2921 /* freed the accumulator if they were generated. */
2923 if (IFFUNC_CALLEESAVES(sym->type))
2925 /* if it's a callee-saves function we need a saved register */
2926 if (calleesaves_saved_register >= 0)
2928 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2929 emitcode ("mov", "a,sp");
2930 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2931 emitcode ("mov", "sp,a");
2932 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2935 /* do it the hard way */
2937 emitcode ("inc", "sp");
2941 /* not callee-saves, we can clobber r0 */
2942 emitcode ("mov", "r0,a");
2943 emitcode ("mov", "a,sp");
2944 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2945 emitcode ("mov", "sp,a");
2946 emitcode ("mov", "a,r0");
2951 emitcode ("inc", "sp");
2956 char i = ((char) sym->xstack & 0xff);
2958 if (i > 3 && accIsFree)
2960 emitcode ("mov", "a,_spx");
2961 emitcode ("add", "a,#0x%02x", i);
2962 emitcode ("mov", "_spx,a");
2966 emitcode ("push", "acc");
2967 emitcode ("mov", "a,_spx");
2968 emitcode ("add", "a,#0x%02x", i);
2969 emitcode ("mov", "_spx,a");
2970 emitcode ("pop", "acc");
2975 emitcode ("inc", "_spx");
2979 /* if critical function then turn interrupts off */
2980 if (IFFUNC_ISCRITICAL (ftype))
2982 symbol *tlbl = newiTempLabel (NULL);
2983 emitcode ("setb", "c");
2984 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2985 emitcode ("clr", "c");
2986 emitcode ("", "%05d$:", (tlbl->key + 100));
2987 emitcode ("push", "psw"); /* save old ea via c in psw */
2991 /*-----------------------------------------------------------------*/
2992 /* genEndFunction - generates epilogue for functions */
2993 /*-----------------------------------------------------------------*/
2995 genEndFunction (iCode * ic)
2997 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2998 lineNode *lnp = lineCurr;
3000 bitVect *regsUsedPrologue;
3001 bitVect *regsUnneeded;
3002 int accIsFree = sym->recvSize < 4;
3005 _G.currentFunc = NULL;
3006 if (IFFUNC_ISNAKED(sym->type))
3008 emitcode(";", "naked function: no epilogue.");
3009 if (options.debug && currFunc)
3010 debugFile->writeEndFunction (currFunc, ic, 0);
3014 if (IFFUNC_ISCRITICAL (sym->type))
3016 emitcode ("pop", "psw"); /* restore ea via c in psw */
3017 emitcode ("mov", "ea,c");
3020 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3022 emitcode ("mov", "%s,_bp", spname);
3025 /* if use external stack but some variables were
3026 added to the local stack then decrement the
3028 if (options.useXstack && sym->stack)
3030 char count = sym->stack;
3032 if ((count>3) && accIsFree)
3034 emitcode ("mov", "a,sp");
3035 emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3036 emitcode ("mov", "sp,a");
3041 emitcode ("dec", "sp");
3045 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3047 if (options.useXstack)
3049 emitcode ("xch", "a,_bp");
3050 emitcode ("mov", "r0,a");
3051 emitcode ("dec", "r0");
3052 emitcode ("movx", "a,@r0");
3053 emitcode ("xch", "a,_bp");
3054 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3058 emitcode ("pop", "_bp");
3062 /* restore the register bank */
3063 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3065 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3066 || !options.useXstack)
3068 /* Special case of ISR using non-zero bank with useXstack
3071 emitcode ("pop", "psw");
3075 if (IFFUNC_ISISR (sym->type))
3078 /* now we need to restore the registers */
3079 /* if this isr has no bank i.e. is going to
3080 run with bank 0 , then we need to save more
3082 if (!FUNC_REGBANK (sym->type))
3084 /* if this function does not call any other
3085 function then we can be economical and
3086 save only those registers that are used */
3087 if (!IFFUNC_HASFCALL(sym->type))
3091 /* if any registers used */
3094 /* save the registers used */
3095 for (i = sym->regsUsed->size; i >= 0; i--)
3097 if (bitVectBitValue (sym->regsUsed, i))
3098 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3104 if (options.parms_in_bank1) {
3106 for (i = 7 ; i >= 0 ; i-- ) {
3107 emitcode ("pop","%s",rb1regs[i]);
3110 /* this function has a function call cannot
3111 determines register usage so we will have to pop the
3113 unsaveRBank (0, ic, FALSE);
3118 /* This ISR uses a non-zero bank.
3120 * Restore any register banks saved by genFunction
3123 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3126 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3128 if (savedBanks & (1 << ix))
3130 unsaveRBank(ix, NULL, FALSE);
3134 if (options.useXstack)
3136 /* Restore bank AFTER calling unsaveRBank,
3137 * since it can trash r0.
3139 emitcode ("pop", "psw");
3143 if (!inExcludeList ("dph"))
3144 emitcode ("pop", "dph");
3145 if (!inExcludeList ("dpl"))
3146 emitcode ("pop", "dpl");
3147 if (!inExcludeList ("b"))
3148 emitcode ("pop", "b");
3149 if (!inExcludeList ("acc"))
3150 emitcode ("pop", "acc");
3152 /* if debug then send end of function */
3153 if (options.debug && currFunc)
3155 debugFile->writeEndFunction (currFunc, ic, 1);
3158 emitcode ("reti", "");
3162 if (IFFUNC_CALLEESAVES(sym->type))
3166 /* if any registers used */
3169 /* save the registers used */
3170 for (i = sym->regsUsed->size; i >= 0; i--)
3172 if (bitVectBitValue (sym->regsUsed, i) ||
3173 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3174 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3177 else if (mcs51_ptrRegReq)
3179 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3180 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3185 /* if debug then send end of function */
3186 if (options.debug && currFunc)
3188 debugFile->writeEndFunction (currFunc, ic, 1);
3191 emitcode ("ret", "");
3194 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3197 /* If this was an interrupt handler using bank 0 that called another */
3198 /* function, then all registers must be saved; nothing to optimized. */
3199 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3200 && !FUNC_REGBANK(sym->type))
3203 /* There are no push/pops to optimize if not callee-saves or ISR */
3204 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3207 /* If there were stack parameters, we cannot optimize without also */
3208 /* fixing all of the stack offsets; this is too dificult to consider. */
3209 if (FUNC_HASSTACKPARM(sym->type))
3212 /* Compute the registers actually used */
3213 regsUsed = newBitVect (mcs51_nRegs);
3214 regsUsedPrologue = newBitVect (mcs51_nRegs);
3217 if (lnp->ic && lnp->ic->op == FUNCTION)
3218 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3220 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3222 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3223 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3230 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3231 && !bitVectBitValue (regsUsed, CND_IDX))
3233 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3234 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3235 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3236 bitVectUnSetBit (regsUsed, CND_IDX);
3239 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3241 /* If this was an interrupt handler that called another function */
3242 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3243 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3245 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3246 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3247 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3248 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3249 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3252 /* Remove the unneeded push/pops */
3253 regsUnneeded = newBitVect (mcs51_nRegs);
3256 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3258 if (!strncmp(lnp->line, "push", 4))
3260 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3261 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3263 connectLine (lnp->prev, lnp->next);
3264 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3267 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3269 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3270 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3272 connectLine (lnp->prev, lnp->next);
3273 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3280 for (idx = 0; idx < regsUnneeded->size; idx++)
3281 if (bitVectBitValue (regsUnneeded, idx))
3282 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3284 freeBitVect (regsUnneeded);
3285 freeBitVect (regsUsed);
3286 freeBitVect (regsUsedPrologue);
3289 /*-----------------------------------------------------------------*/
3290 /* genRet - generate code for return statement */
3291 /*-----------------------------------------------------------------*/
3295 int size, offset = 0, pushed = 0;
3297 D(emitcode ("; genRet",""));
3299 /* if we have no return value then
3300 just generate the "ret" */
3304 /* we have something to return then
3305 move the return value into place */
3306 aopOp (IC_LEFT (ic), ic, FALSE);
3307 size = AOP_SIZE (IC_LEFT (ic));
3312 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3315 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3317 emitcode ("push", "%s", l);
3322 l = aopGet (AOP (IC_LEFT (ic)), offset,
3324 if (strcmp (fReturn[offset], l))
3325 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3334 if (strcmp (fReturn[pushed], "a"))
3335 emitcode ("pop", fReturn[pushed]);
3337 emitcode ("pop", "acc");
3340 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3343 /* generate a jump to the return label
3344 if the next is not the return statement */
3345 if (!(ic->next && ic->next->op == LABEL &&
3346 IC_LABEL (ic->next) == returnLabel))
3348 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3352 /*-----------------------------------------------------------------*/
3353 /* genLabel - generates a label */
3354 /*-----------------------------------------------------------------*/
3356 genLabel (iCode * ic)
3358 /* special case never generate */
3359 if (IC_LABEL (ic) == entryLabel)
3362 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3365 /*-----------------------------------------------------------------*/
3366 /* genGoto - generates a ljmp */
3367 /*-----------------------------------------------------------------*/
3369 genGoto (iCode * ic)
3371 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3374 /*-----------------------------------------------------------------*/
3375 /* findLabelBackwards: walks back through the iCode chain looking */
3376 /* for the given label. Returns number of iCode instructions */
3377 /* between that label and given ic. */
3378 /* Returns zero if label not found. */
3379 /*-----------------------------------------------------------------*/
3381 findLabelBackwards (iCode * ic, int key)
3390 /* If we have any pushes or pops, we cannot predict the distance.
3391 I don't like this at all, this should be dealt with in the
3393 if (ic->op == IPUSH || ic->op == IPOP) {
3397 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3406 /*-----------------------------------------------------------------*/
3407 /* genPlusIncr :- does addition with increment if possible */
3408 /*-----------------------------------------------------------------*/
3410 genPlusIncr (iCode * ic)
3412 unsigned int icount;
3413 unsigned int size = getDataSize (IC_RESULT (ic));
3415 /* will try to generate an increment */
3416 /* if the right side is not a literal
3418 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3421 /* if the literal value of the right hand side
3422 is greater than 4 then it is not worth it */
3423 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3426 D(emitcode ("; genPlusIncr",""));
3428 /* if increment >=16 bits in register or direct space */
3429 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3430 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3438 /* If the next instruction is a goto and the goto target
3439 * is < 10 instructions previous to this, we can generate
3440 * jumps straight to that target.
3442 if (ic->next && ic->next->op == GOTO
3443 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3444 && labelRange <= 10)
3446 emitcode (";", "tail increment optimized");
3447 tlbl = IC_LABEL (ic->next);
3452 tlbl = newiTempLabel (NULL);
3455 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3456 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3457 IS_AOP_PREG (IC_RESULT (ic)))
3458 emitcode ("cjne", "%s,#0x00,%05d$",
3459 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3463 emitcode ("clr", "a");
3464 emitcode ("cjne", "a,%s,%05d$",
3465 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3469 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3472 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3473 IS_AOP_PREG (IC_RESULT (ic)))
3474 emitcode ("cjne", "%s,#0x00,%05d$",
3475 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3478 emitcode ("cjne", "a,%s,%05d$",
3479 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3482 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3486 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3487 IS_AOP_PREG (IC_RESULT (ic)))
3488 emitcode ("cjne", "%s,#0x00,%05d$",
3489 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3493 emitcode ("cjne", "a,%s,%05d$",
3494 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3497 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3502 emitcode ("", "%05d$:", tlbl->key + 100);
3507 /* if the sizes are greater than 1 then we cannot */
3508 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3509 AOP_SIZE (IC_LEFT (ic)) > 1)
3512 /* we can if the aops of the left & result match or
3513 if they are in registers and the registers are the
3515 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3520 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3521 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3522 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3528 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3537 /*-----------------------------------------------------------------*/
3538 /* outBitAcc - output a bit in acc */
3539 /*-----------------------------------------------------------------*/
3541 outBitAcc (operand * result)
3543 symbol *tlbl = newiTempLabel (NULL);
3544 /* if the result is a bit */
3545 if (AOP_TYPE (result) == AOP_CRY)
3547 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3551 emitcode ("jz", "%05d$", tlbl->key + 100);
3552 emitcode ("mov", "a,%s", one);
3553 emitcode ("", "%05d$:", tlbl->key + 100);
3558 /*-----------------------------------------------------------------*/
3559 /* genPlusBits - generates code for addition of two bits */
3560 /*-----------------------------------------------------------------*/
3562 genPlusBits (iCode * ic)
3564 D(emitcode ("; genPlusBits",""));
3566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3568 symbol *lbl = newiTempLabel (NULL);
3569 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3570 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3571 emitcode ("cpl", "c");
3572 emitcode ("", "%05d$:", (lbl->key + 100));
3573 outBitC (IC_RESULT (ic));
3577 emitcode ("clr", "a");
3578 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3579 emitcode ("rlc", "a");
3580 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3581 emitcode ("addc", "a,#0x00");
3582 outAcc (IC_RESULT (ic));
3587 /* This is the original version of this code.
3589 * This is being kept around for reference,
3590 * because I am not entirely sure I got it right...
3593 adjustArithmeticResult (iCode * ic)
3595 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3596 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3597 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3598 aopPut (AOP (IC_RESULT (ic)),
3599 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3601 isOperandVolatile (IC_RESULT (ic), FALSE));
3603 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3604 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3605 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3606 aopPut (AOP (IC_RESULT (ic)),
3607 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3609 isOperandVolatile (IC_RESULT (ic), FALSE));
3611 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3612 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3613 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3614 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3615 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3618 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3619 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3623 /* This is the pure and virtuous version of this code.
3624 * I'm pretty certain it's right, but not enough to toss the old
3628 adjustArithmeticResult (iCode * ic)
3630 if (opIsGptr (IC_RESULT (ic)) &&
3631 opIsGptr (IC_LEFT (ic)) &&
3632 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3634 aopPut (AOP (IC_RESULT (ic)),
3635 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3637 isOperandVolatile (IC_RESULT (ic), FALSE));
3640 if (opIsGptr (IC_RESULT (ic)) &&
3641 opIsGptr (IC_RIGHT (ic)) &&
3642 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3644 aopPut (AOP (IC_RESULT (ic)),
3645 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3647 isOperandVolatile (IC_RESULT (ic), FALSE));
3650 if (opIsGptr (IC_RESULT (ic)) &&
3651 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3652 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3653 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3654 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3657 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3658 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3663 /*-----------------------------------------------------------------*/
3664 /* genPlus - generates code for addition */
3665 /*-----------------------------------------------------------------*/
3667 genPlus (iCode * ic)
3669 int size, offset = 0;
3672 asmop *leftOp, *rightOp;
3675 /* special cases :- */
3677 D(emitcode ("; genPlus",""));
3679 aopOp (IC_LEFT (ic), ic, FALSE);
3680 aopOp (IC_RIGHT (ic), ic, FALSE);
3681 aopOp (IC_RESULT (ic), ic, TRUE);
3683 /* if literal, literal on the right or
3684 if left requires ACC or right is already
3686 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3687 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3688 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3690 operand *t = IC_RIGHT (ic);
3691 IC_RIGHT (ic) = IC_LEFT (ic);
3695 /* if both left & right are in bit
3697 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3698 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3704 /* if left in bit space & right literal */
3705 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3706 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3708 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3709 /* if result in bit space */
3710 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3712 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3713 emitcode ("cpl", "c");
3714 outBitC (IC_RESULT (ic));
3718 size = getDataSize (IC_RESULT (ic));
3721 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3722 emitcode ("addc", "a,#00");
3723 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3729 /* if I can do an increment instead
3730 of add then GOOD for ME */
3731 if (genPlusIncr (ic) == TRUE)
3734 size = getDataSize (IC_RESULT (ic));
3735 leftOp = AOP(IC_LEFT(ic));
3736 rightOp = AOP(IC_RIGHT(ic));
3739 /* if this is an add for an array access
3740 at a 256 byte boundary */
3742 && AOP_TYPE (op) == AOP_IMMD
3744 && IS_SPEC (OP_SYM_ETYPE (op))
3745 && SPEC_ABSA (OP_SYM_ETYPE (op))
3746 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3749 D(emitcode ("; genPlus aligned array",""));
3750 aopPut (AOP (IC_RESULT (ic)),
3751 aopGet (rightOp, 0, FALSE, FALSE),
3753 isOperandVolatile (IC_RESULT (ic), FALSE));
3755 if( 1 == getDataSize (IC_RIGHT (ic)) )
3757 aopPut (AOP (IC_RESULT (ic)),
3758 aopGet (leftOp, 1, FALSE, FALSE),
3760 isOperandVolatile (IC_RESULT (ic), FALSE));
3764 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3765 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3766 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3771 /* if the lower bytes of a literal are zero skip the addition */
3772 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3774 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3775 (skip_bytes+1 < size))
3780 D(emitcode ("; genPlus shortcut",""));
3785 if( offset >= skip_bytes )
3787 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3790 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3792 emitcode("xch", "a,b");
3793 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3794 emitcode (add, "a,b");
3797 else if (aopGetUsesAcc (leftOp, offset))
3799 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3800 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3804 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3805 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3807 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3808 add = "addc"; /* further adds must propagate carry */
3812 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3813 isOperandVolatile (IC_RESULT (ic), FALSE))
3816 aopPut (AOP (IC_RESULT (ic)),
3817 aopGet (leftOp, offset, FALSE, FALSE),
3819 isOperandVolatile (IC_RESULT (ic), FALSE));
3825 adjustArithmeticResult (ic);
3828 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3829 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3830 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3833 /*-----------------------------------------------------------------*/
3834 /* genMinusDec :- does subtraction with deccrement if possible */
3835 /*-----------------------------------------------------------------*/
3837 genMinusDec (iCode * ic)
3839 unsigned int icount;
3840 unsigned int size = getDataSize (IC_RESULT (ic));
3842 /* will try to generate an increment */
3843 /* if the right side is not a literal
3845 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848 /* if the literal value of the right hand side
3849 is greater than 4 then it is not worth it */
3850 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3853 D(emitcode ("; genMinusDec",""));
3855 /* if decrement >=16 bits in register or direct space */
3856 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3857 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3865 /* If the next instruction is a goto and the goto target
3866 * is <= 10 instructions previous to this, we can generate
3867 * jumps straight to that target.
3869 if (ic->next && ic->next->op == GOTO
3870 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3871 && labelRange <= 10)
3873 emitcode (";", "tail decrement optimized");
3874 tlbl = IC_LABEL (ic->next);
3879 tlbl = newiTempLabel (NULL);
3883 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3884 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3885 IS_AOP_PREG (IC_RESULT (ic)))
3886 emitcode ("cjne", "%s,#0xff,%05d$"
3887 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3891 emitcode ("mov", "a,#0xff");
3892 emitcode ("cjne", "a,%s,%05d$"
3893 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3896 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3899 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3900 IS_AOP_PREG (IC_RESULT (ic)))
3901 emitcode ("cjne", "%s,#0xff,%05d$"
3902 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3906 emitcode ("cjne", "a,%s,%05d$"
3907 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3910 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3914 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3915 IS_AOP_PREG (IC_RESULT (ic)))
3916 emitcode ("cjne", "%s,#0xff,%05d$"
3917 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3921 emitcode ("cjne", "a,%s,%05d$"
3922 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3925 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3929 emitcode ("", "%05d$:", tlbl->key + 100);
3934 /* if the sizes are greater than 1 then we cannot */
3935 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3936 AOP_SIZE (IC_LEFT (ic)) > 1)
3939 /* we can if the aops of the left & result match or
3940 if they are in registers and the registers are the
3942 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3946 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3954 /*-----------------------------------------------------------------*/
3955 /* addSign - complete with sign */
3956 /*-----------------------------------------------------------------*/
3958 addSign (operand * result, int offset, int sign)
3960 int size = (getDataSize (result) - offset);
3965 emitcode ("rlc", "a");
3966 emitcode ("subb", "a,acc");
3968 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3972 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3976 /*-----------------------------------------------------------------*/
3977 /* genMinusBits - generates code for subtraction of two bits */
3978 /*-----------------------------------------------------------------*/
3980 genMinusBits (iCode * ic)
3982 symbol *lbl = newiTempLabel (NULL);
3984 D(emitcode ("; genMinusBits",""));
3986 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3988 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3989 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3990 emitcode ("cpl", "c");
3991 emitcode ("", "%05d$:", (lbl->key + 100));
3992 outBitC (IC_RESULT (ic));
3996 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3997 emitcode ("subb", "a,acc");
3998 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3999 emitcode ("inc", "a");
4000 emitcode ("", "%05d$:", (lbl->key + 100));
4001 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4002 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4006 /*-----------------------------------------------------------------*/
4007 /* genMinus - generates code for subtraction */
4008 /*-----------------------------------------------------------------*/
4010 genMinus (iCode * ic)
4012 int size, offset = 0;
4014 D(emitcode ("; genMinus",""));
4016 aopOp (IC_LEFT (ic), ic, FALSE);
4017 aopOp (IC_RIGHT (ic), ic, FALSE);
4018 aopOp (IC_RESULT (ic), ic, TRUE);
4020 /* special cases :- */
4021 /* if both left & right are in bit space */
4022 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4023 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4029 /* if I can do an decrement instead
4030 of subtract then GOOD for ME */
4031 if (genMinusDec (ic) == TRUE)
4034 size = getDataSize (IC_RESULT (ic));
4036 /* if literal, add a,#-lit, else normal subb */
4037 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4039 unsigned long lit = 0L;
4041 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4046 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4047 /* first add without previous c */
4049 if (!size && lit== (unsigned long) -1) {
4050 emitcode ("dec", "a");
4052 emitcode ("add", "a,#0x%02x",
4053 (unsigned int) (lit & 0x0FFL));
4056 emitcode ("addc", "a,#0x%02x",
4057 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4059 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4064 asmop *leftOp, *rightOp;
4066 leftOp = AOP(IC_LEFT(ic));
4067 rightOp = AOP(IC_RIGHT(ic));
4071 if (aopGetUsesAcc(rightOp, offset)) {
4072 if (aopGetUsesAcc(leftOp, offset)) {
4075 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4077 emitcode ("mov", "b,a");
4080 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4081 emitcode ("subb", "a,b");
4084 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4085 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4087 emitcode( "setb", "c");
4089 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4090 emitcode("cpl", "a");
4093 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4096 emitcode ("subb", "a,%s",
4097 aopGet(rightOp, offset, FALSE, TRUE));
4100 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4105 adjustArithmeticResult (ic);
4108 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4109 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4114 /*-----------------------------------------------------------------*/
4115 /* genMultbits :- multiplication of bits */
4116 /*-----------------------------------------------------------------*/
4118 genMultbits (operand * left,
4122 D(emitcode ("; genMultbits",""));
4124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4125 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4129 /*-----------------------------------------------------------------*/
4130 /* genMultOneByte : 8*8=8/16 bit multiplication */
4131 /*-----------------------------------------------------------------*/
4133 genMultOneByte (operand * left,
4138 int size = AOP_SIZE (result);
4139 bool runtimeSign, compiletimeSign;
4140 bool lUnsigned, rUnsigned, pushedB;
4142 D(emitcode ("; genMultOneByte",""));
4144 if (size < 1 || size > 2)
4146 /* this should never happen */
4147 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4148 AOP_SIZE(result), __FILE__, lineno);
4152 /* (if two literals: the value is computed before) */
4153 /* if one literal, literal on the right */
4154 if (AOP_TYPE (left) == AOP_LIT)
4159 /* emitcode (";", "swapped left and right"); */
4161 /* if no literal, unsigned on the right: shorter code */
4162 if ( AOP_TYPE (right) != AOP_LIT
4163 && SPEC_USIGN (getSpec (operandType (left))))
4170 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4171 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4175 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4176 no need to take care about the signedness! */
4177 || (lUnsigned && rUnsigned))
4179 /* just an unsigned 8 * 8 = 8 multiply
4181 /* emitcode (";","unsigned"); */
4182 /* TODO: check for accumulator clash between left & right aops? */
4184 if (AOP_TYPE (right) == AOP_LIT)
4186 /* moving to accumulator first helps peepholes */
4187 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4192 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4193 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4196 emitcode ("mul", "ab");
4197 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4199 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4205 /* we have to do a signed multiply */
4206 /* emitcode (";", "signed"); */
4208 /* now sign adjust for both left & right */
4210 /* let's see what's needed: */
4211 /* apply negative sign during runtime */
4212 runtimeSign = FALSE;
4213 /* negative sign from literals */
4214 compiletimeSign = FALSE;
4218 if (AOP_TYPE(left) == AOP_LIT)
4220 /* signed literal */
4221 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4223 compiletimeSign = TRUE;
4226 /* signed but not literal */
4232 if (AOP_TYPE(right) == AOP_LIT)
4234 /* signed literal */
4235 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4237 compiletimeSign ^= TRUE;
4240 /* signed but not literal */
4244 /* initialize F0, which stores the runtime sign */
4247 if (compiletimeSign)
4248 emitcode ("setb", "F0"); /* set sign flag */
4250 emitcode ("clr", "F0"); /* reset sign flag */
4253 /* save the signs of the operands */
4254 if (AOP_TYPE(right) == AOP_LIT)
4256 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4258 if (!rUnsigned && val < 0)
4259 emitcode ("mov", "b,#0x%02x", -val);
4261 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4263 else /* ! literal */
4265 if (rUnsigned) /* emitcode (";", "signed"); */
4267 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4270 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4271 lbl = newiTempLabel (NULL);
4272 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4273 emitcode ("cpl", "F0"); /* complement sign flag */
4274 emitcode ("cpl", "a"); /* 2's complement */
4275 emitcode ("inc", "a");
4276 emitcode ("", "%05d$:", (lbl->key + 100));
4277 emitcode ("mov", "b,a");
4281 if (AOP_TYPE(left) == AOP_LIT)
4283 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4285 if (!lUnsigned && val < 0)
4286 emitcode ("mov", "a,#0x%02x", -val);
4288 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4290 else /* ! literal */
4292 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4296 lbl = newiTempLabel (NULL);
4297 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4298 emitcode ("cpl", "F0"); /* complement sign flag */
4299 emitcode ("cpl", "a"); /* 2's complement */
4300 emitcode ("inc", "a");
4301 emitcode ("", "%05d$:", (lbl->key + 100));
4305 /* now the multiplication */
4306 emitcode ("mul", "ab");
4307 if (runtimeSign || compiletimeSign)
4309 lbl = newiTempLabel (NULL);
4311 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4312 emitcode ("cpl", "a"); /* lsb 2's complement */
4314 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4317 emitcode ("add", "a,#1"); /* this sets carry flag */
4318 emitcode ("xch", "a,b");
4319 emitcode ("cpl", "a"); /* msb 2's complement */
4320 emitcode ("addc", "a,#0");
4321 emitcode ("xch", "a,b");
4323 emitcode ("", "%05d$:", (lbl->key + 100));
4325 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4327 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4332 /*-----------------------------------------------------------------*/
4333 /* genMult - generates code for multiplication */
4334 /*-----------------------------------------------------------------*/
4336 genMult (iCode * ic)
4338 operand *left = IC_LEFT (ic);
4339 operand *right = IC_RIGHT (ic);
4340 operand *result = IC_RESULT (ic);
4342 D(emitcode ("; genMult",""));
4344 /* assign the amsops */
4345 aopOp (left, ic, FALSE);
4346 aopOp (right, ic, FALSE);
4347 aopOp (result, ic, TRUE);
4349 /* special cases first */
4351 if (AOP_TYPE (left) == AOP_CRY &&
4352 AOP_TYPE (right) == AOP_CRY)
4354 genMultbits (left, right, result);
4358 /* if both are of size == 1 */
4359 #if 0 // one of them can be a sloc shared with the result
4360 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4362 if (getSize(operandType(left)) == 1 &&
4363 getSize(operandType(right)) == 1)
4366 genMultOneByte (left, right, result);
4370 /* should have been converted to function call */
4371 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4372 getSize(OP_SYMBOL(right)->type));
4376 freeAsmop (result, NULL, ic, TRUE);
4377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4378 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4381 /*-----------------------------------------------------------------*/
4382 /* genDivbits :- division of bits */
4383 /*-----------------------------------------------------------------*/
4385 genDivbits (operand * left,
4392 D(emitcode ("; genDivbits",""));
4396 /* the result must be bit */
4397 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4398 l = aopGet (AOP (left), 0, FALSE, FALSE);
4402 emitcode ("div", "ab");
4403 emitcode ("rrc", "a");
4407 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division */
4412 /*-----------------------------------------------------------------*/
4414 genDivOneByte (operand * left,
4418 bool lUnsigned, rUnsigned, pushedB;
4419 bool runtimeSign, compiletimeSign;
4423 D(emitcode ("; genDivOneByte",""));
4425 /* Why is it necessary that genDivOneByte() can return an int result?
4428 volatile unsigned char uc;
4429 volatile signed char sc1, sc2;
4442 In all cases a one byte result would overflow, the following cast to int
4443 would return the wrong result.
4445 Two possible solution:
4446 a) cast operands to int, if ((unsigned) / (signed)) or
4447 ((signed) / (signed))
4448 b) return an 16 bit signed int; this is what we're doing here!
4451 size = AOP_SIZE (result) - 1;
4453 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4454 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4458 /* signed or unsigned */
4459 if (lUnsigned && rUnsigned)
4461 /* unsigned is easy */
4462 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4463 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4464 emitcode ("div", "ab");
4465 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4467 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4473 /* signed is a little bit more difficult */
4475 /* now sign adjust for both left & right */
4477 /* let's see what's needed: */
4478 /* apply negative sign during runtime */
4479 runtimeSign = FALSE;
4480 /* negative sign from literals */
4481 compiletimeSign = FALSE;
4485 if (AOP_TYPE(left) == AOP_LIT)
4487 /* signed literal */
4488 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4490 compiletimeSign = TRUE;
4493 /* signed but not literal */
4499 if (AOP_TYPE(right) == AOP_LIT)
4501 /* signed literal */
4502 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4504 compiletimeSign ^= TRUE;
4507 /* signed but not literal */
4511 /* initialize F0, which stores the runtime sign */
4514 if (compiletimeSign)
4515 emitcode ("setb", "F0"); /* set sign flag */
4517 emitcode ("clr", "F0"); /* reset sign flag */
4520 /* save the signs of the operands */
4521 if (AOP_TYPE(right) == AOP_LIT)
4523 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4525 if (!rUnsigned && val < 0)
4526 emitcode ("mov", "b,#0x%02x", -val);
4528 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4530 else /* ! literal */
4533 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4536 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4537 lbl = newiTempLabel (NULL);
4538 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4539 emitcode ("cpl", "F0"); /* complement sign flag */
4540 emitcode ("cpl", "a"); /* 2's complement */
4541 emitcode ("inc", "a");
4542 emitcode ("", "%05d$:", (lbl->key + 100));
4543 emitcode ("mov", "b,a");
4547 if (AOP_TYPE(left) == AOP_LIT)
4549 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4551 if (!lUnsigned && val < 0)
4552 emitcode ("mov", "a,#0x%02x", -val);
4554 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4556 else /* ! literal */
4558 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4562 lbl = newiTempLabel (NULL);
4563 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4564 emitcode ("cpl", "F0"); /* complement sign flag */
4565 emitcode ("cpl", "a"); /* 2's complement */
4566 emitcode ("inc", "a");
4567 emitcode ("", "%05d$:", (lbl->key + 100));
4571 /* now the division */
4572 emitcode ("div", "ab");
4574 if (runtimeSign || compiletimeSign)
4576 lbl = newiTempLabel (NULL);
4578 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4579 emitcode ("cpl", "a"); /* lsb 2's complement */
4580 emitcode ("inc", "a");
4581 emitcode ("", "%05d$:", (lbl->key + 100));
4583 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4586 /* msb is 0x00 or 0xff depending on the sign */
4589 emitcode ("mov", "c,F0");
4590 emitcode ("subb", "a,acc");
4592 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4594 else /* compiletimeSign */
4596 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4601 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4603 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4609 /*-----------------------------------------------------------------*/
4610 /* genDiv - generates code for division */
4611 /*-----------------------------------------------------------------*/
4615 operand *left = IC_LEFT (ic);
4616 operand *right = IC_RIGHT (ic);
4617 operand *result = IC_RESULT (ic);
4619 D(emitcode ("; genDiv",""));
4621 /* assign the amsops */
4622 aopOp (left, ic, FALSE);
4623 aopOp (right, ic, FALSE);
4624 aopOp (result, ic, TRUE);
4626 /* special cases first */
4628 if (AOP_TYPE (left) == AOP_CRY &&
4629 AOP_TYPE (right) == AOP_CRY)
4631 genDivbits (left, right, result);
4635 /* if both are of size == 1 */
4636 if (AOP_SIZE (left) == 1 &&
4637 AOP_SIZE (right) == 1)
4639 genDivOneByte (left, right, result);
4643 /* should have been converted to function call */
4646 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4648 freeAsmop (result, NULL, ic, TRUE);
4651 /*-----------------------------------------------------------------*/
4652 /* genModbits :- modulus of bits */
4653 /*-----------------------------------------------------------------*/
4655 genModbits (operand * left,
4662 D(emitcode ("; genModbits",""));
4666 /* the result must be bit */
4667 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4668 l = aopGet (AOP (left), 0, FALSE, FALSE);
4672 emitcode ("div", "ab");
4673 emitcode ("mov", "a,b");
4674 emitcode ("rrc", "a");
4678 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4681 /*-----------------------------------------------------------------*/
4682 /* genModOneByte : 8 bit modulus */
4683 /*-----------------------------------------------------------------*/
4685 genModOneByte (operand * left,
4689 bool lUnsigned, rUnsigned, pushedB;
4690 bool runtimeSign, compiletimeSign;
4694 D(emitcode ("; genModOneByte",""));
4696 size = AOP_SIZE (result) - 1;
4698 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4699 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4701 /* if right is a literal, check it for 2^n */
4702 if (AOP_TYPE(right) == AOP_LIT)
4704 unsigned char val = abs(operandLitValue(right));
4705 symbol *lbl2 = NULL;
4709 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4718 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4719 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4720 /* because iCode should have been changed to genAnd */
4721 /* see file "SDCCopt.c", function "convertToFcall()" */
4723 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4724 emitcode ("mov", "c,acc.7");
4725 emitcode ("anl", "a,#0x%02x", val - 1);
4726 lbl = newiTempLabel (NULL);
4727 emitcode ("jz", "%05d$", (lbl->key + 100));
4728 emitcode ("jnc", "%05d$", (lbl->key + 100));
4729 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4735 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4737 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4738 lbl2 = newiTempLabel (NULL);
4739 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4741 emitcode ("", "%05d$:", (lbl->key + 100));
4742 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4744 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4747 emitcode ("", "%05d$:", (lbl2->key + 100));
4758 /* signed or unsigned */
4759 if (lUnsigned && rUnsigned)
4761 /* unsigned is easy */
4762 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4763 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4764 emitcode ("div", "ab");
4765 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4767 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4773 /* signed is a little bit more difficult */
4775 /* now sign adjust for both left & right */
4777 /* modulus: sign of the right operand has no influence on the result! */
4778 if (AOP_TYPE(right) == AOP_LIT)
4780 signed char val = (char) operandLitValue(right);
4782 if (!rUnsigned && val < 0)
4783 emitcode ("mov", "b,#0x%02x", -val);
4785 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4787 else /* not literal */
4790 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4793 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4794 lbl = newiTempLabel (NULL);
4795 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4796 emitcode ("cpl", "a"); /* 2's complement */
4797 emitcode ("inc", "a");
4798 emitcode ("", "%05d$:", (lbl->key + 100));
4799 emitcode ("mov", "b,a");
4803 /* let's see what's needed: */
4804 /* apply negative sign during runtime */
4805 runtimeSign = FALSE;
4806 /* negative sign from literals */
4807 compiletimeSign = FALSE;
4809 /* sign adjust left side */
4810 if (AOP_TYPE(left) == AOP_LIT)
4812 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4814 if (!lUnsigned && val < 0)
4816 compiletimeSign = TRUE; /* set sign flag */
4817 emitcode ("mov", "a,#0x%02x", -val);
4820 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4822 else /* ! literal */
4824 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4829 emitcode ("clr", "F0"); /* clear sign flag */
4831 lbl = newiTempLabel (NULL);
4832 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4833 emitcode ("setb", "F0"); /* set sign flag */
4834 emitcode ("cpl", "a"); /* 2's complement */
4835 emitcode ("inc", "a");
4836 emitcode ("", "%05d$:", (lbl->key + 100));
4840 /* now the modulus */
4841 emitcode ("div", "ab");
4843 if (runtimeSign || compiletimeSign)
4845 emitcode ("mov", "a,b");
4846 lbl = newiTempLabel (NULL);
4848 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4849 emitcode ("cpl", "a"); /* 2's complement */
4850 emitcode ("inc", "a");
4851 emitcode ("", "%05d$:", (lbl->key + 100));
4853 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4856 /* msb is 0x00 or 0xff depending on the sign */
4859 emitcode ("mov", "c,F0");
4860 emitcode ("subb", "a,acc");
4862 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4864 else /* compiletimeSign */
4866 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4871 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4873 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4879 /*-----------------------------------------------------------------*/
4880 /* genMod - generates code for division */
4881 /*-----------------------------------------------------------------*/
4885 operand *left = IC_LEFT (ic);
4886 operand *right = IC_RIGHT (ic);
4887 operand *result = IC_RESULT (ic);
4889 D(emitcode ("; genMod",""));
4891 /* assign the asmops */
4892 aopOp (left, ic, FALSE);
4893 aopOp (right, ic, FALSE);
4894 aopOp (result, ic, TRUE);
4896 /* special cases first */
4898 if (AOP_TYPE (left) == AOP_CRY &&
4899 AOP_TYPE (right) == AOP_CRY)
4901 genModbits (left, right, result);
4905 /* if both are of size == 1 */
4906 if (AOP_SIZE (left) == 1 &&
4907 AOP_SIZE (right) == 1)
4909 genModOneByte (left, right, result);
4913 /* should have been converted to function call */
4917 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4918 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4919 freeAsmop (result, NULL, ic, TRUE);
4922 /*-----------------------------------------------------------------*/
4923 /* genIfxJump :- will create a jump depending on the ifx */
4924 /*-----------------------------------------------------------------*/
4926 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4929 symbol *tlbl = newiTempLabel (NULL);
4932 D(emitcode ("; genIfxJump",""));
4934 /* if true label then we jump if condition
4938 jlbl = IC_TRUE (ic);
4939 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4940 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4944 /* false label is present */
4945 jlbl = IC_FALSE (ic);
4946 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4947 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4949 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4950 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4952 emitcode (inst, "%05d$", tlbl->key + 100);
4953 freeForBranchAsmop (result);
4954 freeForBranchAsmop (right);
4955 freeForBranchAsmop (left);
4956 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4957 emitcode ("", "%05d$:", tlbl->key + 100);
4959 /* mark the icode as generated */
4963 /*-----------------------------------------------------------------*/
4964 /* genCmp :- greater or less than comparison */
4965 /*-----------------------------------------------------------------*/
4967 genCmp (operand * left, operand * right,
4968 operand * result, iCode * ifx, int sign, iCode *ic)
4970 int size, offset = 0;
4971 unsigned long lit = 0L;
4974 D(emitcode ("; genCmp",""));
4976 /* if left & right are bit variables */
4977 if (AOP_TYPE (left) == AOP_CRY &&
4978 AOP_TYPE (right) == AOP_CRY)
4980 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4981 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4985 /* subtract right from left if at the
4986 end the carry flag is set then we know that
4987 left is greater than right */
4988 size = max (AOP_SIZE (left), AOP_SIZE (right));
4990 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4991 if ((size == 1) && !sign &&
4992 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4994 symbol *lbl = newiTempLabel (NULL);
4995 emitcode ("cjne", "%s,%s,%05d$",
4996 aopGet (AOP (left), offset, FALSE, FALSE),
4997 aopGet (AOP (right), offset, FALSE, FALSE),
4999 emitcode ("", "%05d$:", lbl->key + 100);
5003 if (AOP_TYPE (right) == AOP_LIT)
5005 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5006 /* optimize if(x < 0) or if(x >= 0) */
5015 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5016 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5018 genIfxJump (ifx, "acc.7", left, right, result);
5019 freeAsmop (right, NULL, ic, TRUE);
5020 freeAsmop (left, NULL, ic, TRUE);
5025 emitcode ("rlc", "a");
5033 bool pushedB = FALSE;
5034 rightInB = aopGetUsesAcc(AOP (right), offset);
5038 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5040 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5041 if (sign && size == 0)
5043 emitcode ("xrl", "a,#0x80");
5044 if (AOP_TYPE (right) == AOP_LIT)
5046 unsigned long lit = (unsigned long)
5047 floatFromVal (AOP (right)->aopu.aop_lit);
5048 emitcode ("subb", "a,#0x%02x",
5049 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5057 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5059 emitcode ("xrl", "b,#0x80");
5060 emitcode ("subb", "a,b");
5066 emitcode ("subb", "a,b");
5068 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5078 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5080 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5086 /* if the result is used in the next
5087 ifx conditional branch then generate
5088 code a little differently */
5090 genIfxJump (ifx, "c", NULL, NULL, result);
5093 /* leave the result in acc */
5097 /*-----------------------------------------------------------------*/
5098 /* genCmpGt :- greater than comparison */
5099 /*-----------------------------------------------------------------*/
5101 genCmpGt (iCode * ic, iCode * ifx)
5103 operand *left, *right, *result;
5104 sym_link *letype, *retype;
5107 D(emitcode ("; genCmpGt",""));
5109 left = IC_LEFT (ic);
5110 right = IC_RIGHT (ic);
5111 result = IC_RESULT (ic);
5113 letype = getSpec (operandType (left));
5114 retype = getSpec (operandType (right));
5115 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5116 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5117 /* assign the amsops */
5118 aopOp (left, ic, FALSE);
5119 aopOp (right, ic, FALSE);
5120 aopOp (result, ic, TRUE);
5122 genCmp (right, left, result, ifx, sign, ic);
5124 freeAsmop (result, NULL, ic, TRUE);
5127 /*-----------------------------------------------------------------*/
5128 /* genCmpLt - less than comparisons */
5129 /*-----------------------------------------------------------------*/
5131 genCmpLt (iCode * ic, iCode * ifx)
5133 operand *left, *right, *result;
5134 sym_link *letype, *retype;
5137 D(emitcode ("; genCmpLt",""));
5139 left = IC_LEFT (ic);
5140 right = IC_RIGHT (ic);
5141 result = IC_RESULT (ic);
5143 letype = getSpec (operandType (left));
5144 retype = getSpec (operandType (right));
5145 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5146 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5147 /* assign the amsops */
5148 aopOp (left, ic, FALSE);
5149 aopOp (right, ic, FALSE);
5150 aopOp (result, ic, TRUE);
5152 genCmp (left, right, result, ifx, sign,ic);
5154 freeAsmop (result, NULL, ic, TRUE);
5157 /*-----------------------------------------------------------------*/
5158 /* gencjneshort - compare and jump if not equal */
5159 /*-----------------------------------------------------------------*/
5161 gencjneshort (operand * left, operand * right, symbol * lbl)
5163 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5165 unsigned long lit = 0L;
5167 /* if the left side is a literal or
5168 if the right is in a pointer register and left
5170 if ((AOP_TYPE (left) == AOP_LIT) ||
5171 (AOP_TYPE (left) == AOP_IMMD) ||
5172 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5179 if (AOP_TYPE (right) == AOP_LIT)
5180 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5182 /* if the right side is a literal then anything goes */
5183 if (AOP_TYPE (right) == AOP_LIT &&
5184 AOP_TYPE (left) != AOP_DIR &&
5185 AOP_TYPE (left) != AOP_IMMD)
5189 emitcode ("cjne", "%s,%s,%05d$",
5190 aopGet (AOP (left), offset, FALSE, FALSE),
5191 aopGet (AOP (right), offset, FALSE, FALSE),
5197 /* if the right side is in a register or in direct space or
5198 if the left is a pointer register & right is not */
5199 else if (AOP_TYPE (right) == AOP_REG ||
5200 AOP_TYPE (right) == AOP_DIR ||
5201 AOP_TYPE (right) == AOP_LIT ||
5202 AOP_TYPE (right) == AOP_IMMD ||
5203 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5204 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5208 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5209 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5210 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5211 emitcode ("jnz", "%05d$", lbl->key + 100);
5213 emitcode ("cjne", "a,%s,%05d$",
5214 aopGet (AOP (right), offset, FALSE, TRUE),
5221 /* right is a pointer reg need both a & b */
5225 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5226 wassertl(!_G.BInUse, "B was in use");
5227 l = aopGet (AOP (left), offset, FALSE, FALSE);
5228 if (strcmp (l, "b"))
5229 emitcode ("mov", "b,%s", l);
5230 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5231 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5237 /*-----------------------------------------------------------------*/
5238 /* gencjne - compare and jump if not equal */
5239 /*-----------------------------------------------------------------*/
5241 gencjne (operand * left, operand * right, symbol * lbl)
5243 symbol *tlbl = newiTempLabel (NULL);
5245 gencjneshort (left, right, lbl);
5247 emitcode ("mov", "a,%s", one);
5248 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5249 emitcode ("", "%05d$:", lbl->key + 100);
5250 emitcode ("clr", "a");
5251 emitcode ("", "%05d$:", tlbl->key + 100);
5254 /*-----------------------------------------------------------------*/
5255 /* genCmpEq - generates code for equal to */
5256 /*-----------------------------------------------------------------*/
5258 genCmpEq (iCode * ic, iCode * ifx)
5260 operand *left, *right, *result;
5262 D(emitcode ("; genCmpEq",""));
5264 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5265 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5266 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5268 /* if literal, literal on the right or
5269 if the right is in a pointer register and left
5271 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5272 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5274 operand *t = IC_RIGHT (ic);
5275 IC_RIGHT (ic) = IC_LEFT (ic);
5279 if (ifx && !AOP_SIZE (result))
5282 /* if they are both bit variables */
5283 if (AOP_TYPE (left) == AOP_CRY &&
5284 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5286 if (AOP_TYPE (right) == AOP_LIT)
5288 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5291 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5292 emitcode ("cpl", "c");
5296 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5300 emitcode ("clr", "c");
5302 /* AOP_TYPE(right) == AOP_CRY */
5306 symbol *lbl = newiTempLabel (NULL);
5307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5308 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5309 emitcode ("cpl", "c");
5310 emitcode ("", "%05d$:", (lbl->key + 100));
5312 /* if true label then we jump if condition
5314 tlbl = newiTempLabel (NULL);
5317 emitcode ("jnc", "%05d$", tlbl->key + 100);
5318 freeForBranchAsmop (result);
5319 freeForBranchAsmop (right);
5320 freeForBranchAsmop (left);
5321 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5325 emitcode ("jc", "%05d$", tlbl->key + 100);
5326 freeForBranchAsmop (result);
5327 freeForBranchAsmop (right);
5328 freeForBranchAsmop (left);
5329 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5331 emitcode ("", "%05d$:", tlbl->key + 100);
5335 tlbl = newiTempLabel (NULL);
5336 gencjneshort (left, right, tlbl);
5339 freeForBranchAsmop (result);
5340 freeForBranchAsmop (right);
5341 freeForBranchAsmop (left);
5342 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5343 emitcode ("", "%05d$:", tlbl->key + 100);
5347 symbol *lbl = newiTempLabel (NULL);
5348 emitcode ("sjmp", "%05d$", lbl->key + 100);
5349 emitcode ("", "%05d$:", tlbl->key + 100);
5350 freeForBranchAsmop (result);
5351 freeForBranchAsmop (right);
5352 freeForBranchAsmop (left);
5353 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5354 emitcode ("", "%05d$:", lbl->key + 100);
5357 /* mark the icode as generated */
5362 /* if they are both bit variables */
5363 if (AOP_TYPE (left) == AOP_CRY &&
5364 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5366 if (AOP_TYPE (right) == AOP_LIT)
5368 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5372 emitcode ("cpl", "c");
5376 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5380 emitcode ("clr", "c");
5382 /* AOP_TYPE(right) == AOP_CRY */
5386 symbol *lbl = newiTempLabel (NULL);
5387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5388 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5389 emitcode ("cpl", "c");
5390 emitcode ("", "%05d$:", (lbl->key + 100));
5393 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5400 genIfxJump (ifx, "c", left, right, result);
5403 /* if the result is used in an arithmetic operation
5404 then put the result in place */
5409 gencjne (left, right, newiTempLabel (NULL));
5410 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5412 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5417 genIfxJump (ifx, "a", left, right, result);
5420 /* if the result is used in an arithmetic operation
5421 then put the result in place */
5422 if (AOP_TYPE (result) != AOP_CRY)
5424 /* leave the result in acc */
5428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5429 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5430 freeAsmop (result, NULL, ic, TRUE);
5433 /*-----------------------------------------------------------------*/
5434 /* ifxForOp - returns the icode containing the ifx for operand */
5435 /*-----------------------------------------------------------------*/
5437 ifxForOp (operand * op, iCode * ic)
5439 /* if true symbol then needs to be assigned */
5440 if (IS_TRUE_SYMOP (op))
5443 /* if this has register type condition and
5444 the next instruction is ifx with the same operand
5445 and live to of the operand is upto the ifx only then */
5447 ic->next->op == IFX &&
5448 IC_COND (ic->next)->key == op->key &&
5449 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5455 /*-----------------------------------------------------------------*/
5456 /* hasInc - operand is incremented before any other use */
5457 /*-----------------------------------------------------------------*/
5459 hasInc (operand *op, iCode *ic,int osize)
5461 sym_link *type = operandType(op);
5462 sym_link *retype = getSpec (type);
5463 iCode *lic = ic->next;
5466 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5467 if (!IS_SYMOP(op)) return NULL;
5469 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5470 if (IS_AGGREGATE(type->next)) return NULL;
5471 if (osize != (isize = getSize(type->next))) return NULL;
5474 /* if operand of the form op = op + <sizeof *op> */
5475 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5476 isOperandEqual(IC_RESULT(lic),op) &&
5477 isOperandLiteral(IC_RIGHT(lic)) &&
5478 operandLitValue(IC_RIGHT(lic)) == isize) {
5481 /* if the operand used or deffed */
5482 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5485 /* if GOTO or IFX */
5486 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5492 /*-----------------------------------------------------------------*/
5493 /* genAndOp - for && operation */
5494 /*-----------------------------------------------------------------*/
5496 genAndOp (iCode * ic)
5498 operand *left, *right, *result;
5501 D(emitcode ("; genAndOp",""));
5503 /* note here that && operations that are in an
5504 if statement are taken away by backPatchLabels
5505 only those used in arthmetic operations remain */
5506 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5507 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5508 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5510 /* if both are bit variables */
5511 if (AOP_TYPE (left) == AOP_CRY &&
5512 AOP_TYPE (right) == AOP_CRY)
5514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5515 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5520 tlbl = newiTempLabel (NULL);
5522 emitcode ("jz", "%05d$", tlbl->key + 100);
5524 emitcode ("", "%05d$:", tlbl->key + 100);
5528 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5529 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5530 freeAsmop (result, NULL, ic, TRUE);
5534 /*-----------------------------------------------------------------*/
5535 /* genOrOp - for || operation */
5536 /*-----------------------------------------------------------------*/
5538 genOrOp (iCode * ic)
5540 operand *left, *right, *result;
5543 D(emitcode ("; genOrOp",""));
5545 /* note here that || operations that are in an
5546 if statement are taken away by backPatchLabels
5547 only those used in arthmetic operations remain */
5548 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5549 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5550 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5552 /* if both are bit variables */
5553 if (AOP_TYPE (left) == AOP_CRY &&
5554 AOP_TYPE (right) == AOP_CRY)
5556 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5557 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5562 tlbl = newiTempLabel (NULL);
5564 emitcode ("jnz", "%05d$", tlbl->key + 100);
5566 emitcode ("", "%05d$:", tlbl->key + 100);
5570 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5571 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5572 freeAsmop (result, NULL, ic, TRUE);
5575 /*-----------------------------------------------------------------*/
5576 /* isLiteralBit - test if lit == 2^n */
5577 /*-----------------------------------------------------------------*/
5579 isLiteralBit (unsigned long lit)
5581 unsigned long pw[32] =
5582 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5583 0x100L, 0x200L, 0x400L, 0x800L,
5584 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5585 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5586 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5587 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5588 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5591 for (idx = 0; idx < 32; idx++)
5597 /*-----------------------------------------------------------------*/
5598 /* continueIfTrue - */
5599 /*-----------------------------------------------------------------*/
5601 continueIfTrue (iCode * ic)
5604 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5608 /*-----------------------------------------------------------------*/
5610 /*-----------------------------------------------------------------*/
5612 jumpIfTrue (iCode * ic)
5615 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5619 /*-----------------------------------------------------------------*/
5620 /* jmpTrueOrFalse - */
5621 /*-----------------------------------------------------------------*/
5623 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5625 // ugly but optimized by peephole
5628 symbol *nlbl = newiTempLabel (NULL);
5629 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5630 emitcode ("", "%05d$:", tlbl->key + 100);
5631 freeForBranchAsmop (result);
5632 freeForBranchAsmop (right);
5633 freeForBranchAsmop (left);
5634 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5635 emitcode ("", "%05d$:", nlbl->key + 100);
5639 freeForBranchAsmop (result);
5640 freeForBranchAsmop (right);
5641 freeForBranchAsmop (left);
5642 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5643 emitcode ("", "%05d$:", tlbl->key + 100);
5648 /*-----------------------------------------------------------------*/
5649 /* genAnd - code for and */
5650 /*-----------------------------------------------------------------*/
5652 genAnd (iCode * ic, iCode * ifx)
5654 operand *left, *right, *result;
5655 int size, offset = 0;
5656 unsigned long lit = 0L;
5660 D(emitcode ("; genAnd",""));
5662 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5663 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5664 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5667 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5669 AOP_TYPE (left), AOP_TYPE (right));
5670 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5672 AOP_SIZE (left), AOP_SIZE (right));
5675 /* if left is a literal & right is not then exchange them */
5676 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5677 AOP_NEEDSACC (left))
5679 operand *tmp = right;
5684 /* if result = right then exchange left and right */
5685 if (sameRegs (AOP (result), AOP (right)))
5687 operand *tmp = right;
5692 /* if right is bit then exchange them */
5693 if (AOP_TYPE (right) == AOP_CRY &&
5694 AOP_TYPE (left) != AOP_CRY)
5696 operand *tmp = right;
5700 if (AOP_TYPE (right) == AOP_LIT)
5701 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5703 size = AOP_SIZE (result);
5706 // result = bit & yy;
5707 if (AOP_TYPE (left) == AOP_CRY)
5709 // c = bit & literal;
5710 if (AOP_TYPE (right) == AOP_LIT)
5714 if (size && sameRegs (AOP (result), AOP (left)))
5717 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5722 if (size && (AOP_TYPE (result) == AOP_CRY))
5724 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5727 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5732 emitcode ("clr", "c");
5737 if (AOP_TYPE (right) == AOP_CRY)
5740 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5741 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5746 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5748 emitcode ("rrc", "a");
5749 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5757 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5758 genIfxJump (ifx, "c", left, right, result);
5762 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5763 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5764 if ((AOP_TYPE (right) == AOP_LIT) &&
5765 (AOP_TYPE (result) == AOP_CRY) &&
5766 (AOP_TYPE (left) != AOP_CRY))
5768 int posbit = isLiteralBit (lit);
5773 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5776 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5782 SNPRINTF (buffer, sizeof(buffer),
5783 "acc.%d", posbit & 0x07);
5784 genIfxJump (ifx, buffer, left, right, result);
5787 {// what is this case? just found it in ds390/gen.c
5788 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5795 symbol *tlbl = newiTempLabel (NULL);
5796 int sizel = AOP_SIZE (left);
5798 emitcode ("setb", "c");
5801 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5803 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5805 if ((posbit = isLiteralBit (bytelit)) != 0)
5806 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5809 if (bytelit != 0x0FFL)
5810 emitcode ("anl", "a,%s",
5811 aopGet (AOP (right), offset, FALSE, TRUE));
5812 emitcode ("jnz", "%05d$", tlbl->key + 100);
5817 // bit = left & literal
5820 emitcode ("clr", "c");
5821 emitcode ("", "%05d$:", tlbl->key + 100);
5823 // if(left & literal)
5827 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5829 emitcode ("", "%05d$:", tlbl->key + 100);
5837 /* if left is same as result */
5838 if (sameRegs (AOP (result), AOP (left)))
5840 for (; size--; offset++)
5842 if (AOP_TYPE (right) == AOP_LIT)
5844 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5845 if (bytelit == 0x0FF)
5847 /* dummy read of volatile operand */
5848 if (isOperandVolatile (left, FALSE))
5849 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5853 else if (bytelit == 0)
5855 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5857 else if (IS_AOP_PREG (result))
5859 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5860 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5861 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5864 emitcode ("anl", "%s,%s",
5865 aopGet (AOP (left), offset, FALSE, TRUE),
5866 aopGet (AOP (right), offset, FALSE, FALSE));
5870 if (AOP_TYPE (left) == AOP_ACC)
5871 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5874 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5875 if (IS_AOP_PREG (result))
5877 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5878 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5881 emitcode ("anl", "%s,a",
5882 aopGet (AOP (left), offset, FALSE, TRUE));
5889 // left & result in different registers
5890 if (AOP_TYPE (result) == AOP_CRY)
5893 // if(size), result in bit
5894 // if(!size && ifx), conditional oper: if(left & right)
5895 symbol *tlbl = newiTempLabel (NULL);
5896 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5898 emitcode ("setb", "c");
5901 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5902 emitcode ("anl", "a,%s",
5903 aopGet (AOP (right), offset, FALSE, FALSE));
5905 if (AOP_TYPE(left)==AOP_ACC) {
5906 bool pushedB = pushB ();
5907 emitcode("mov", "b,a");
5908 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5909 emitcode("anl", "a,b");
5912 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5913 emitcode ("anl", "a,%s",
5914 aopGet (AOP (left), offset, FALSE, FALSE));
5917 emitcode ("jnz", "%05d$", tlbl->key + 100);
5923 emitcode ("", "%05d$:", tlbl->key + 100);
5927 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5929 emitcode ("", "%05d$:", tlbl->key + 100);
5933 for (; (size--); offset++)
5936 // result = left & right
5937 if (AOP_TYPE (right) == AOP_LIT)
5939 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5940 if (bytelit == 0x0FF)
5942 aopPut (AOP (result),
5943 aopGet (AOP (left), offset, FALSE, FALSE),
5945 isOperandVolatile (result, FALSE));
5948 else if (bytelit == 0)
5950 /* dummy read of volatile operand */
5951 if (isOperandVolatile (left, FALSE))
5952 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5953 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5957 // faster than result <- left, anl result,right
5958 // and better if result is SFR
5959 if (AOP_TYPE (left) == AOP_ACC)
5960 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5963 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5964 emitcode ("anl", "a,%s",
5965 aopGet (AOP (left), offset, FALSE, FALSE));
5967 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5974 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5975 freeAsmop (result, NULL, ic, TRUE);
5978 /*-----------------------------------------------------------------*/
5979 /* genOr - code for or */
5980 /*-----------------------------------------------------------------*/
5982 genOr (iCode * ic, iCode * ifx)
5984 operand *left, *right, *result;
5985 int size, offset = 0;
5986 unsigned long lit = 0L;
5989 D(emitcode ("; genOr",""));
5991 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5992 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5993 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5996 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5998 AOP_TYPE (left), AOP_TYPE (right));
5999 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6001 AOP_SIZE (left), AOP_SIZE (right));
6004 /* if left is a literal & right is not then exchange them */
6005 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6006 AOP_NEEDSACC (left))
6008 operand *tmp = right;
6013 /* if result = right then exchange them */
6014 if (sameRegs (AOP (result), AOP (right)))
6016 operand *tmp = right;
6021 /* if right is bit then exchange them */
6022 if (AOP_TYPE (right) == AOP_CRY &&
6023 AOP_TYPE (left) != AOP_CRY)
6025 operand *tmp = right;
6029 if (AOP_TYPE (right) == AOP_LIT)
6030 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6032 size = AOP_SIZE (result);
6036 if (AOP_TYPE (left) == AOP_CRY)
6038 if (AOP_TYPE (right) == AOP_LIT)
6040 // c = bit | literal;
6043 // lit != 0 => result = 1
6044 if (AOP_TYPE (result) == AOP_CRY)
6047 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6049 continueIfTrue (ifx);
6052 emitcode ("setb", "c");
6056 // lit == 0 => result = left
6057 if (size && sameRegs (AOP (result), AOP (left)))
6059 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6064 if (AOP_TYPE (right) == AOP_CRY)
6067 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6068 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6073 symbol *tlbl = newiTempLabel (NULL);
6074 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6075 emitcode ("setb", "c");
6076 emitcode ("jb", "%s,%05d$",
6077 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6079 emitcode ("jnz", "%05d$", tlbl->key + 100);
6080 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6082 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6088 emitcode ("", "%05d$:", tlbl->key + 100);
6097 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6098 genIfxJump (ifx, "c", left, right, result);
6102 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6103 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6104 if ((AOP_TYPE (right) == AOP_LIT) &&
6105 (AOP_TYPE (result) == AOP_CRY) &&
6106 (AOP_TYPE (left) != AOP_CRY))
6112 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6114 continueIfTrue (ifx);
6119 // lit = 0, result = boolean(left)
6121 emitcode ("setb", "c");
6125 symbol *tlbl = newiTempLabel (NULL);
6126 emitcode ("jnz", "%05d$", tlbl->key + 100);
6128 emitcode ("", "%05d$:", tlbl->key + 100);
6132 genIfxJump (ifx, "a", left, right, result);
6140 /* if left is same as result */
6141 if (sameRegs (AOP (result), AOP (left)))
6143 for (; size--; offset++)
6145 if (AOP_TYPE (right) == AOP_LIT)
6147 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6150 /* dummy read of volatile operand */
6151 if (isOperandVolatile (left, FALSE))
6152 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6156 else if (bytelit == 0x0FF)
6158 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6160 else if (IS_AOP_PREG (left))
6162 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6163 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6164 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6168 emitcode ("orl", "%s,%s",
6169 aopGet (AOP (left), offset, FALSE, TRUE),
6170 aopGet (AOP (right), offset, FALSE, FALSE));
6175 if (AOP_TYPE (left) == AOP_ACC)
6176 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6179 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6180 if (IS_AOP_PREG (left))
6182 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6183 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6187 emitcode ("orl", "%s,a",
6188 aopGet (AOP (left), offset, FALSE, TRUE));
6196 // left & result in different registers
6197 if (AOP_TYPE (result) == AOP_CRY)
6200 // if(size), result in bit
6201 // if(!size && ifx), conditional oper: if(left | right)
6202 symbol *tlbl = newiTempLabel (NULL);
6203 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6205 emitcode ("setb", "c");
6208 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6209 emitcode ("orl", "a,%s",
6210 aopGet (AOP (right), offset, FALSE, FALSE));
6212 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6213 emitcode ("orl", "a,%s",
6214 aopGet (AOP (left), offset, FALSE, FALSE));
6216 emitcode ("jnz", "%05d$", tlbl->key + 100);
6222 emitcode ("", "%05d$:", tlbl->key + 100);
6226 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6228 emitcode ("", "%05d$:", tlbl->key + 100);
6232 for (; (size--); offset++)
6235 // result = left | right
6236 if (AOP_TYPE (right) == AOP_LIT)
6238 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6241 aopPut (AOP (result),
6242 aopGet (AOP (left), offset, FALSE, FALSE),
6244 isOperandVolatile (result, FALSE));
6247 else if (bytelit == 0x0FF)
6249 /* dummy read of volatile operand */
6250 if (isOperandVolatile (left, FALSE))
6251 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6252 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6256 // faster than result <- left, anl result,right
6257 // and better if result is SFR
6258 if (AOP_TYPE (left) == AOP_ACC)
6259 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6262 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6263 emitcode ("orl", "a,%s",
6264 aopGet (AOP (left), offset, FALSE, FALSE));
6266 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6272 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6273 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6274 freeAsmop (result, NULL, ic, TRUE);
6277 /*-----------------------------------------------------------------*/
6278 /* genXor - code for xclusive or */
6279 /*-----------------------------------------------------------------*/
6281 genXor (iCode * ic, iCode * ifx)
6283 operand *left, *right, *result;
6284 int size, offset = 0;
6285 unsigned long lit = 0L;
6288 D(emitcode ("; genXor",""));
6290 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6291 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6292 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6295 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6297 AOP_TYPE (left), AOP_TYPE (right));
6298 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6300 AOP_SIZE (left), AOP_SIZE (right));
6303 /* if left is a literal & right is not ||
6304 if left needs acc & right does not */
6305 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6306 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6308 operand *tmp = right;
6313 /* if result = right then exchange them */
6314 if (sameRegs (AOP (result), AOP (right)))
6316 operand *tmp = right;
6321 /* if right is bit then exchange them */
6322 if (AOP_TYPE (right) == AOP_CRY &&
6323 AOP_TYPE (left) != AOP_CRY)
6325 operand *tmp = right;
6329 if (AOP_TYPE (right) == AOP_LIT)
6330 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6332 size = AOP_SIZE (result);
6336 if (AOP_TYPE (left) == AOP_CRY)
6338 if (AOP_TYPE (right) == AOP_LIT)
6340 // c = bit & literal;
6343 // lit>>1 != 0 => result = 1
6344 if (AOP_TYPE (result) == AOP_CRY)
6347 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6349 continueIfTrue (ifx);
6352 emitcode ("setb", "c");
6359 // lit == 0, result = left
6360 if (size && sameRegs (AOP (result), AOP (left)))
6362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366 // lit == 1, result = not(left)
6367 if (size && sameRegs (AOP (result), AOP (left)))
6369 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6374 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6375 emitcode ("cpl", "c");
6384 symbol *tlbl = newiTempLabel (NULL);
6385 if (AOP_TYPE (right) == AOP_CRY)
6388 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6392 int sizer = AOP_SIZE (right);
6394 // if val>>1 != 0, result = 1
6395 emitcode ("setb", "c");
6398 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6400 // test the msb of the lsb
6401 emitcode ("anl", "a,#0xfe");
6402 emitcode ("jnz", "%05d$", tlbl->key + 100);
6406 emitcode ("rrc", "a");
6408 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6409 emitcode ("cpl", "c");
6410 emitcode ("", "%05d$:", (tlbl->key + 100));
6417 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6418 genIfxJump (ifx, "c", left, right, result);
6422 /* if left is same as result */
6423 if (sameRegs (AOP (result), AOP (left)))
6425 for (; size--; offset++)
6427 if (AOP_TYPE (right) == AOP_LIT)
6429 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6432 /* dummy read of volatile operand */
6433 if (isOperandVolatile (left, FALSE))
6434 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6438 else if (IS_AOP_PREG (left))
6440 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6441 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6442 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6446 emitcode ("xrl", "%s,%s",
6447 aopGet (AOP (left), offset, FALSE, TRUE),
6448 aopGet (AOP (right), offset, FALSE, FALSE));
6453 if (AOP_TYPE (left) == AOP_ACC)
6454 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6457 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6458 if (IS_AOP_PREG (left))
6460 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6461 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6464 emitcode ("xrl", "%s,a",
6465 aopGet (AOP (left), offset, FALSE, TRUE));
6472 // left & result in different registers
6473 if (AOP_TYPE (result) == AOP_CRY)
6476 // if(size), result in bit
6477 // if(!size && ifx), conditional oper: if(left ^ right)
6478 symbol *tlbl = newiTempLabel (NULL);
6479 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6481 emitcode ("setb", "c");
6484 if ((AOP_TYPE (right) == AOP_LIT) &&
6485 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6487 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6491 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6492 emitcode ("xrl", "a,%s",
6493 aopGet (AOP (right), offset, FALSE, FALSE));
6495 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6496 emitcode ("xrl", "a,%s",
6497 aopGet (AOP (left), offset, FALSE, FALSE));
6500 emitcode ("jnz", "%05d$", tlbl->key + 100);
6506 emitcode ("", "%05d$:", tlbl->key + 100);
6510 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6514 for (; (size--); offset++)
6517 // result = left & right
6518 if (AOP_TYPE (right) == AOP_LIT)
6520 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6523 aopPut (AOP (result),
6524 aopGet (AOP (left), offset, FALSE, FALSE),
6526 isOperandVolatile (result, FALSE));
6530 // faster than result <- left, anl result,right
6531 // and better if result is SFR
6532 if (AOP_TYPE (left) == AOP_ACC)
6533 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6536 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6537 emitcode ("xrl", "a,%s",
6538 aopGet (AOP (left), offset, FALSE, TRUE));
6540 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6546 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6547 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6548 freeAsmop (result, NULL, ic, TRUE);
6551 /*-----------------------------------------------------------------*/
6552 /* genInline - write the inline code out */
6553 /*-----------------------------------------------------------------*/
6555 genInline (iCode * ic)
6557 char *buffer, *bp, *bp1;
6559 D(emitcode ("; genInline",""));
6561 _G.inLine += (!options.asmpeep);
6563 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6564 strcpy (buffer, IC_INLINE (ic));
6566 /* emit each line as a code */
6577 /* Add \n for labels, not dirs such as c:\mydir */
6578 if ( (*bp == ':') && (isspace(bp[1])) )
6592 /* emitcode("",buffer); */
6593 _G.inLine -= (!options.asmpeep);
6596 /*-----------------------------------------------------------------*/
6597 /* genRRC - rotate right with carry */
6598 /*-----------------------------------------------------------------*/
6602 operand *left, *result;
6603 int size, offset = 0;
6606 D(emitcode ("; genRRC",""));
6608 /* rotate right with carry */
6609 left = IC_LEFT (ic);
6610 result = IC_RESULT (ic);
6611 aopOp (left, ic, FALSE);
6612 aopOp (result, ic, FALSE);
6614 /* move it to the result */
6615 size = AOP_SIZE (result);
6617 if (size == 1) { /* special case for 1 byte */
6618 l = aopGet (AOP (left), offset, FALSE, FALSE);
6620 emitcode ("rr", "a");
6623 /* no need to clear carry, bit7 will be written later */
6626 l = aopGet (AOP (left), offset, FALSE, FALSE);
6628 emitcode ("rrc", "a");
6629 if (AOP_SIZE (result) > 1)
6630 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6632 /* now we need to put the carry into the
6633 highest order byte of the result */
6634 if (AOP_SIZE (result) > 1)
6636 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6639 emitcode ("mov", "acc.7,c");
6641 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6642 freeAsmop (left, NULL, ic, TRUE);
6643 freeAsmop (result, NULL, ic, TRUE);
6646 /*-----------------------------------------------------------------*/
6647 /* genRLC - generate code for rotate left with carry */
6648 /*-----------------------------------------------------------------*/
6652 operand *left, *result;
6653 int size, offset = 0;
6656 D(emitcode ("; genRLC",""));
6658 /* rotate right with carry */
6659 left = IC_LEFT (ic);
6660 result = IC_RESULT (ic);
6661 aopOp (left, ic, FALSE);
6662 aopOp (result, ic, FALSE);
6664 /* move it to the result */
6665 size = AOP_SIZE (result);
6669 l = aopGet (AOP (left), offset, FALSE, FALSE);
6671 if (size == 0) { /* special case for 1 byte */
6675 emitcode("rlc","a"); /* bit0 will be written later */
6676 if (AOP_SIZE (result) > 1)
6677 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6680 l = aopGet (AOP (left), offset, FALSE, FALSE);
6682 emitcode ("rlc", "a");
6683 if (AOP_SIZE (result) > 1)
6684 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6687 /* now we need to put the carry into the
6688 highest order byte of the result */
6689 if (AOP_SIZE (result) > 1)
6691 l = aopGet (AOP (result), 0, FALSE, FALSE);
6694 emitcode ("mov", "acc.0,c");
6696 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6697 freeAsmop (left, NULL, ic, TRUE);
6698 freeAsmop (result, NULL, ic, TRUE);
6701 /*-----------------------------------------------------------------*/
6702 /* genGetHbit - generates code get highest order bit */
6703 /*-----------------------------------------------------------------*/
6705 genGetHbit (iCode * ic)
6707 operand *left, *result;
6709 D(emitcode ("; genGetHbit",""));
6711 left = IC_LEFT (ic);
6712 result = IC_RESULT (ic);
6713 aopOp (left, ic, FALSE);
6714 aopOp (result, ic, FALSE);
6716 /* get the highest order byte into a */
6717 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6718 if (AOP_TYPE (result) == AOP_CRY)
6720 emitcode ("rlc", "a");
6725 emitcode ("rl", "a");
6726 emitcode ("anl", "a,#0x01");
6731 freeAsmop (left, NULL, ic, TRUE);
6732 freeAsmop (result, NULL, ic, TRUE);
6735 /*-----------------------------------------------------------------*/
6736 /* genSwap - generates code to swap nibbles or bytes */
6737 /*-----------------------------------------------------------------*/
6739 genSwap (iCode * ic)
6741 operand *left, *result;
6743 D(emitcode ("; genSwap",""));
6745 left = IC_LEFT (ic);
6746 result = IC_RESULT (ic);
6747 aopOp (left, ic, FALSE);
6748 aopOp (result, ic, FALSE);
6750 switch (AOP_SIZE (left))
6752 case 1: /* swap nibbles in byte */
6753 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6754 emitcode ("swap", "a");
6755 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6757 case 2: /* swap bytes in word */
6758 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6760 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6761 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6762 0, isOperandVolatile (result, FALSE));
6763 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6765 else if (operandsEqu (left, result))
6768 bool pushedB = FALSE, leftInB = FALSE;
6770 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6771 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6774 emitcode ("mov", "b,a");
6778 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6779 0, isOperandVolatile (result, FALSE));
6780 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6787 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6788 0, isOperandVolatile (result, FALSE));
6789 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6790 1, isOperandVolatile (result, FALSE));
6794 wassertl(FALSE, "unsupported SWAP operand size");
6797 freeAsmop (left, NULL, ic, TRUE);
6798 freeAsmop (result, NULL, ic, TRUE);
6802 /*-----------------------------------------------------------------*/
6803 /* AccRol - rotate left accumulator by known count */
6804 /*-----------------------------------------------------------------*/
6806 AccRol (int shCount)
6808 shCount &= 0x0007; // shCount : 0..7
6815 emitcode ("rl", "a");
6818 emitcode ("rl", "a");
6819 emitcode ("rl", "a");
6822 emitcode ("swap", "a");
6823 emitcode ("rr", "a");
6826 emitcode ("swap", "a");
6829 emitcode ("swap", "a");
6830 emitcode ("rl", "a");
6833 emitcode ("rr", "a");
6834 emitcode ("rr", "a");
6837 emitcode ("rr", "a");
6842 /*-----------------------------------------------------------------*/
6843 /* AccLsh - left shift accumulator by known count */
6844 /*-----------------------------------------------------------------*/
6846 AccLsh (int shCount)
6851 emitcode ("add", "a,acc");
6852 else if (shCount == 2)
6854 emitcode ("add", "a,acc");
6855 emitcode ("add", "a,acc");
6859 /* rotate left accumulator */
6861 /* and kill the lower order bits */
6862 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6867 /*-----------------------------------------------------------------*/
6868 /* AccRsh - right shift accumulator by known count */
6869 /*-----------------------------------------------------------------*/
6871 AccRsh (int shCount)
6878 emitcode ("rrc", "a");
6882 /* rotate right accumulator */
6883 AccRol (8 - shCount);
6884 /* and kill the higher order bits */
6885 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6890 /*-----------------------------------------------------------------*/
6891 /* AccSRsh - signed right shift accumulator by known count */
6892 /*-----------------------------------------------------------------*/
6894 AccSRsh (int shCount)
6901 emitcode ("mov", "c,acc.7");
6902 emitcode ("rrc", "a");
6904 else if (shCount == 2)
6906 emitcode ("mov", "c,acc.7");
6907 emitcode ("rrc", "a");
6908 emitcode ("mov", "c,acc.7");
6909 emitcode ("rrc", "a");
6913 tlbl = newiTempLabel (NULL);
6914 /* rotate right accumulator */
6915 AccRol (8 - shCount);
6916 /* and kill the higher order bits */
6917 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6918 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6919 emitcode ("orl", "a,#0x%02x",
6920 (unsigned char) ~SRMask[shCount]);
6921 emitcode ("", "%05d$:", tlbl->key + 100);
6926 /*-----------------------------------------------------------------*/
6927 /* shiftR1Left2Result - shift right one byte from left to result */
6928 /*-----------------------------------------------------------------*/
6930 shiftR1Left2Result (operand * left, int offl,
6931 operand * result, int offr,
6932 int shCount, int sign)
6934 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6935 /* shift right accumulator */
6940 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6943 /*-----------------------------------------------------------------*/
6944 /* shiftL1Left2Result - shift left one byte from left to result */
6945 /*-----------------------------------------------------------------*/
6947 shiftL1Left2Result (operand * left, int offl,
6948 operand * result, int offr, int shCount)
6951 l = aopGet (AOP (left), offl, FALSE, FALSE);
6953 /* shift left accumulator */
6955 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6958 /*-----------------------------------------------------------------*/
6959 /* movLeft2Result - move byte from left to result */
6960 /*-----------------------------------------------------------------*/
6962 movLeft2Result (operand * left, int offl,
6963 operand * result, int offr, int sign)
6966 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6968 l = aopGet (AOP (left), offl, FALSE, FALSE);
6970 if (*l == '@' && (IS_AOP_PREG (result)))
6972 emitcode ("mov", "a,%s", l);
6973 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6978 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6981 /* MSB sign in acc.7 ! */
6982 if (getDataSize (left) == offl + 1)
6984 emitcode ("mov", "a,%s", l);
6985 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6992 /*-----------------------------------------------------------------*/
6993 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6994 /*-----------------------------------------------------------------*/
6998 emitcode ("rrc", "a");
6999 emitcode ("xch", "a,%s", x);
7000 emitcode ("rrc", "a");
7001 emitcode ("xch", "a,%s", x);
7004 /*-----------------------------------------------------------------*/
7005 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7006 /*-----------------------------------------------------------------*/
7010 emitcode ("xch", "a,%s", x);
7011 emitcode ("rlc", "a");
7012 emitcode ("xch", "a,%s", x);
7013 emitcode ("rlc", "a");
7016 /*-----------------------------------------------------------------*/
7017 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7018 /*-----------------------------------------------------------------*/
7022 emitcode ("xch", "a,%s", x);
7023 emitcode ("add", "a,acc");
7024 emitcode ("xch", "a,%s", x);
7025 emitcode ("rlc", "a");
7028 /*-----------------------------------------------------------------*/
7029 /* AccAXLsh - left shift a:x by known count (0..7) */
7030 /*-----------------------------------------------------------------*/
7032 AccAXLsh (char *x, int shCount)
7047 case 5: // AAAAABBB:CCCCCDDD
7049 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7051 emitcode ("anl", "a,#0x%02x",
7052 SLMask[shCount]); // BBB00000:CCCCCDDD
7054 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7056 AccRol (shCount); // DDDCCCCC:BBB00000
7058 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7060 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7062 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7064 emitcode ("anl", "a,#0x%02x",
7065 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7067 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7069 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7072 case 6: // AAAAAABB:CCCCCCDD
7073 emitcode ("anl", "a,#0x%02x",
7074 SRMask[shCount]); // 000000BB:CCCCCCDD
7075 emitcode ("mov", "c,acc.0"); // c = B
7076 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7078 AccAXRrl1 (x); // BCCCCCCD:D000000B
7079 AccAXRrl1 (x); // BBCCCCCC:DD000000
7081 emitcode("rrc","a");
7082 emitcode("xch","a,%s", x);
7083 emitcode("rrc","a");
7084 emitcode("mov","c,acc.0"); //<< get correct bit
7085 emitcode("xch","a,%s", x);
7087 emitcode("rrc","a");
7088 emitcode("xch","a,%s", x);
7089 emitcode("rrc","a");
7090 emitcode("xch","a,%s", x);
7093 case 7: // a:x <<= 7
7095 emitcode ("anl", "a,#0x%02x",
7096 SRMask[shCount]); // 0000000B:CCCCCCCD
7098 emitcode ("mov", "c,acc.0"); // c = B
7100 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7102 AccAXRrl1 (x); // BCCCCCCC:D0000000
7110 /*-----------------------------------------------------------------*/
7111 /* AccAXRsh - right shift a:x known count (0..7) */
7112 /*-----------------------------------------------------------------*/
7114 AccAXRsh (char *x, int shCount)
7122 AccAXRrl1 (x); // 0->a:x
7127 AccAXRrl1 (x); // 0->a:x
7130 AccAXRrl1 (x); // 0->a:x
7135 case 5: // AAAAABBB:CCCCCDDD = a:x
7137 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7139 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7141 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7143 emitcode ("anl", "a,#0x%02x",
7144 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7146 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7148 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7150 emitcode ("anl", "a,#0x%02x",
7151 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7153 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7155 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7157 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7160 case 6: // AABBBBBB:CCDDDDDD
7162 emitcode ("mov", "c,acc.7");
7163 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7165 emitcode ("mov", "c,acc.7");
7166 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7168 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7170 emitcode ("anl", "a,#0x%02x",
7171 SRMask[shCount]); // 000000AA:BBBBBBCC
7174 case 7: // ABBBBBBB:CDDDDDDD
7176 emitcode ("mov", "c,acc.7"); // c = A
7178 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7180 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7182 emitcode ("anl", "a,#0x%02x",
7183 SRMask[shCount]); // 0000000A:BBBBBBBC
7191 /*-----------------------------------------------------------------*/
7192 /* AccAXRshS - right shift signed a:x known count (0..7) */
7193 /*-----------------------------------------------------------------*/
7195 AccAXRshS (char *x, int shCount)
7203 emitcode ("mov", "c,acc.7");
7204 AccAXRrl1 (x); // s->a:x
7208 emitcode ("mov", "c,acc.7");
7209 AccAXRrl1 (x); // s->a:x
7211 emitcode ("mov", "c,acc.7");
7212 AccAXRrl1 (x); // s->a:x
7217 case 5: // AAAAABBB:CCCCCDDD = a:x
7219 tlbl = newiTempLabel (NULL);
7220 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7222 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7224 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7226 emitcode ("anl", "a,#0x%02x",
7227 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7229 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7231 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7233 emitcode ("anl", "a,#0x%02x",
7234 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7236 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7238 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7240 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7242 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7243 emitcode ("orl", "a,#0x%02x",
7244 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7246 emitcode ("", "%05d$:", tlbl->key + 100);
7247 break; // SSSSAAAA:BBBCCCCC
7249 case 6: // AABBBBBB:CCDDDDDD
7251 tlbl = newiTempLabel (NULL);
7252 emitcode ("mov", "c,acc.7");
7253 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7255 emitcode ("mov", "c,acc.7");
7256 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7258 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7260 emitcode ("anl", "a,#0x%02x",
7261 SRMask[shCount]); // 000000AA:BBBBBBCC
7263 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7264 emitcode ("orl", "a,#0x%02x",
7265 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7267 emitcode ("", "%05d$:", tlbl->key + 100);
7269 case 7: // ABBBBBBB:CDDDDDDD
7271 tlbl = newiTempLabel (NULL);
7272 emitcode ("mov", "c,acc.7"); // c = A
7274 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7276 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7278 emitcode ("anl", "a,#0x%02x",
7279 SRMask[shCount]); // 0000000A:BBBBBBBC
7281 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7282 emitcode ("orl", "a,#0x%02x",
7283 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7285 emitcode ("", "%05d$:", tlbl->key + 100);
7292 /*-----------------------------------------------------------------*/
7293 /* shiftL2Left2Result - shift left two bytes from left to result */
7294 /*-----------------------------------------------------------------*/
7296 shiftL2Left2Result (operand * left, int offl,
7297 operand * result, int offr, int shCount)
7299 if (sameRegs (AOP (result), AOP (left)) &&
7300 ((offl + MSB16) == offr))
7302 /* don't crash result[offr] */
7303 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7304 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7308 movLeft2Result (left, offl, result, offr, 0);
7309 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7311 /* ax << shCount (x = lsb(result)) */
7312 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7313 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7317 /*-----------------------------------------------------------------*/
7318 /* shiftR2Left2Result - shift right two bytes from left to result */
7319 /*-----------------------------------------------------------------*/
7321 shiftR2Left2Result (operand * left, int offl,
7322 operand * result, int offr,
7323 int shCount, int sign)
7325 if (sameRegs (AOP (result), AOP (left)) &&
7326 ((offl + MSB16) == offr))
7328 /* don't crash result[offr] */
7329 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7330 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7334 movLeft2Result (left, offl, result, offr, 0);
7335 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7337 /* a:x >> shCount (x = lsb(result)) */
7339 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7341 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7342 if (getDataSize (result) > 1)
7343 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7346 /*-----------------------------------------------------------------*/
7347 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7348 /*-----------------------------------------------------------------*/
7350 shiftLLeftOrResult (operand * left, int offl,
7351 operand * result, int offr, int shCount)
7353 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7354 /* shift left accumulator */
7356 /* or with result */
7357 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7358 /* back to result */
7359 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7362 /*-----------------------------------------------------------------*/
7363 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7364 /*-----------------------------------------------------------------*/
7366 shiftRLeftOrResult (operand * left, int offl,
7367 operand * result, int offr, int shCount)
7369 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7370 /* shift right 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 /* genlshOne - left shift a one byte quantity by known count */
7380 /*-----------------------------------------------------------------*/
7382 genlshOne (operand * result, operand * left, int shCount)
7384 D(emitcode ("; genlshOne",""));
7386 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7389 /*-----------------------------------------------------------------*/
7390 /* genlshTwo - left shift two bytes by known amount != 0 */
7391 /*-----------------------------------------------------------------*/
7393 genlshTwo (operand * result, operand * left, int shCount)
7397 D(emitcode ("; genlshTwo",""));
7399 size = getDataSize (result);
7401 /* if shCount >= 8 */
7409 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7411 movLeft2Result (left, LSB, result, MSB16, 0);
7413 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7416 /* 1 <= shCount <= 7 */
7420 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7422 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7426 /*-----------------------------------------------------------------*/
7427 /* shiftLLong - shift left one long from left to result */
7428 /* offl = LSB or MSB16 */
7429 /*-----------------------------------------------------------------*/
7431 shiftLLong (operand * left, operand * result, int offr)
7434 int size = AOP_SIZE (result);
7436 if (size >= LSB + offr)
7438 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7440 emitcode ("add", "a,acc");
7441 if (sameRegs (AOP (left), AOP (result)) &&
7442 size >= MSB16 + offr && offr != LSB)
7443 emitcode ("xch", "a,%s",
7444 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7446 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7449 if (size >= MSB16 + offr)
7451 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7453 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7456 emitcode ("rlc", "a");
7457 if (sameRegs (AOP (left), AOP (result)) &&
7458 size >= MSB24 + offr && offr != LSB)
7459 emitcode ("xch", "a,%s",
7460 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7462 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7465 if (size >= MSB24 + offr)
7467 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7469 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7472 emitcode ("rlc", "a");
7473 if (sameRegs (AOP (left), AOP (result)) &&
7474 size >= MSB32 + offr && offr != LSB)
7475 emitcode ("xch", "a,%s",
7476 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7478 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7481 if (size > MSB32 + offr)
7483 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7485 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7488 emitcode ("rlc", "a");
7489 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7492 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7495 /*-----------------------------------------------------------------*/
7496 /* genlshFour - shift four byte by a known amount != 0 */
7497 /*-----------------------------------------------------------------*/
7499 genlshFour (operand * result, operand * left, int shCount)
7503 D(emitcode ("; genlshFour",""));
7505 size = AOP_SIZE (result);
7507 /* if shifting more that 3 bytes */
7512 /* lowest order of left goes to the highest
7513 order of the destination */
7514 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7516 movLeft2Result (left, LSB, result, MSB32, 0);
7517 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7518 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7519 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7523 /* more than two bytes */
7524 else if (shCount >= 16)
7526 /* lower order two bytes goes to higher order two bytes */
7528 /* if some more remaining */
7530 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7533 movLeft2Result (left, MSB16, result, MSB32, 0);
7534 movLeft2Result (left, LSB, result, MSB24, 0);
7536 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7537 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7541 /* if more than 1 byte */
7542 else if (shCount >= 8)
7544 /* lower order three bytes goes to higher order three bytes */
7549 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7551 movLeft2Result (left, LSB, result, MSB16, 0);
7557 movLeft2Result (left, MSB24, result, MSB32, 0);
7558 movLeft2Result (left, MSB16, result, MSB24, 0);
7559 movLeft2Result (left, LSB, result, MSB16, 0);
7560 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7562 else if (shCount == 1)
7563 shiftLLong (left, result, MSB16);
7566 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7567 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7568 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7569 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7574 /* 1 <= shCount <= 7 */
7575 else if (shCount <= 2)
7577 shiftLLong (left, result, LSB);
7579 shiftLLong (result, result, LSB);
7581 /* 3 <= shCount <= 7, optimize */
7584 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7585 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7586 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7590 /*-----------------------------------------------------------------*/
7591 /* genLeftShiftLiteral - left shifting by known count */
7592 /*-----------------------------------------------------------------*/
7594 genLeftShiftLiteral (operand * left,
7599 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7602 D(emitcode ("; genLeftShiftLiteral",""));
7604 freeAsmop (right, NULL, ic, TRUE);
7606 aopOp (left, ic, FALSE);
7607 aopOp (result, ic, FALSE);
7609 size = getSize (operandType (result));
7612 emitcode ("; shift left ", "result %d, left %d", size,
7616 /* I suppose that the left size >= result size */
7621 movLeft2Result (left, size, result, size, 0);
7625 else if (shCount >= (size * 8))
7627 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7633 genlshOne (result, left, shCount);
7637 genlshTwo (result, left, shCount);
7641 genlshFour (result, left, shCount);
7644 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7645 "*** ack! mystery literal shift!\n");
7649 freeAsmop (left, NULL, ic, TRUE);
7650 freeAsmop (result, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genLeftShift - generates code for left shifting */
7655 /*-----------------------------------------------------------------*/
7657 genLeftShift (iCode * ic)
7659 operand *left, *right, *result;
7662 symbol *tlbl, *tlbl1;
7665 D(emitcode ("; genLeftShift",""));
7667 right = IC_RIGHT (ic);
7668 left = IC_LEFT (ic);
7669 result = IC_RESULT (ic);
7671 aopOp (right, ic, FALSE);
7673 /* if the shift count is known then do it
7674 as efficiently as possible */
7675 if (AOP_TYPE (right) == AOP_LIT)
7677 genLeftShiftLiteral (left, right, result, ic);
7681 /* shift count is unknown then we have to form
7682 a loop get the loop count in B : Note: we take
7683 only the lower order byte since shifting
7684 more that 32 bits make no sense anyway, ( the
7685 largest size of an object can be only 32 bits ) */
7688 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7689 emitcode ("inc", "b");
7690 freeAsmop (right, NULL, ic, TRUE);
7691 aopOp (left, ic, FALSE);
7692 aopOp (result, ic, FALSE);
7694 /* now move the left to the result if they are not the same */
7695 if (!sameRegs (AOP (left), AOP (result)) &&
7696 AOP_SIZE (result) > 1)
7699 size = AOP_SIZE (result);
7703 l = aopGet (AOP (left), offset, FALSE, TRUE);
7704 if (*l == '@' && (IS_AOP_PREG (result)))
7707 emitcode ("mov", "a,%s", l);
7708 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7711 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7716 tlbl = newiTempLabel (NULL);
7717 size = AOP_SIZE (result);
7719 tlbl1 = newiTempLabel (NULL);
7721 /* if it is only one byte then */
7724 symbol *tlbl1 = newiTempLabel (NULL);
7726 l = aopGet (AOP (left), 0, FALSE, FALSE);
7728 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7729 emitcode ("", "%05d$:", tlbl->key + 100);
7730 emitcode ("add", "a,acc");
7731 emitcode ("", "%05d$:", tlbl1->key + 100);
7732 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7734 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7738 reAdjustPreg (AOP (result));
7740 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7741 emitcode ("", "%05d$:", tlbl->key + 100);
7742 l = aopGet (AOP (result), offset, FALSE, FALSE);
7744 emitcode ("add", "a,acc");
7745 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7748 l = aopGet (AOP (result), offset, FALSE, FALSE);
7750 emitcode ("rlc", "a");
7751 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7753 reAdjustPreg (AOP (result));
7755 emitcode ("", "%05d$:", tlbl1->key + 100);
7756 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7759 freeAsmop (left, NULL, ic, TRUE);
7760 freeAsmop (result, NULL, ic, TRUE);
7763 /*-----------------------------------------------------------------*/
7764 /* genrshOne - right shift a one byte quantity by known count */
7765 /*-----------------------------------------------------------------*/
7767 genrshOne (operand * result, operand * left,
7768 int shCount, int sign)
7770 D(emitcode ("; genrshOne",""));
7772 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7775 /*-----------------------------------------------------------------*/
7776 /* genrshTwo - right shift two bytes by known amount != 0 */
7777 /*-----------------------------------------------------------------*/
7779 genrshTwo (operand * result, operand * left,
7780 int shCount, int sign)
7782 D(emitcode ("; genrshTwo",""));
7784 /* if shCount >= 8 */
7789 shiftR1Left2Result (left, MSB16, result, LSB,
7792 movLeft2Result (left, MSB16, result, LSB, sign);
7793 addSign (result, MSB16, sign);
7796 /* 1 <= shCount <= 7 */
7798 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7801 /*-----------------------------------------------------------------*/
7802 /* shiftRLong - shift right one long from left to result */
7803 /* offl = LSB or MSB16 */
7804 /*-----------------------------------------------------------------*/
7806 shiftRLong (operand * left, int offl,
7807 operand * result, int sign)
7809 int isSameRegs=sameRegs(AOP(left),AOP(result));
7811 if (isSameRegs && offl>1) {
7812 // we are in big trouble, but this shouldn't happen
7813 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7816 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7821 emitcode ("rlc", "a");
7822 emitcode ("subb", "a,acc");
7824 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7826 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7827 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7830 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7835 emitcode ("clr", "c");
7837 emitcode ("mov", "c,acc.7");
7840 emitcode ("rrc", "a");
7842 if (isSameRegs && offl==MSB16) {
7843 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7845 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7846 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7849 emitcode ("rrc", "a");
7850 if (isSameRegs && offl==1) {
7851 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7853 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7854 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7856 emitcode ("rrc", "a");
7857 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7861 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7862 emitcode ("rrc", "a");
7863 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7867 /*-----------------------------------------------------------------*/
7868 /* genrshFour - shift four byte by a known amount != 0 */
7869 /*-----------------------------------------------------------------*/
7871 genrshFour (operand * result, operand * left,
7872 int shCount, int sign)
7874 D(emitcode ("; genrshFour",""));
7876 /* if shifting more that 3 bytes */
7881 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7883 movLeft2Result (left, MSB32, result, LSB, sign);
7884 addSign (result, MSB16, sign);
7886 else if (shCount >= 16)
7890 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7893 movLeft2Result (left, MSB24, result, LSB, 0);
7894 movLeft2Result (left, MSB32, result, MSB16, sign);
7896 addSign (result, MSB24, sign);
7898 else if (shCount >= 8)
7902 shiftRLong (left, MSB16, result, sign);
7903 else if (shCount == 0)
7905 movLeft2Result (left, MSB16, result, LSB, 0);
7906 movLeft2Result (left, MSB24, result, MSB16, 0);
7907 movLeft2Result (left, MSB32, result, MSB24, sign);
7908 addSign (result, MSB32, sign);
7912 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7913 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7914 /* the last shift is signed */
7915 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7916 addSign (result, MSB32, sign);
7920 { /* 1 <= shCount <= 7 */
7923 shiftRLong (left, LSB, result, sign);
7925 shiftRLong (result, LSB, result, sign);
7929 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7930 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7931 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7936 /*-----------------------------------------------------------------*/
7937 /* genRightShiftLiteral - right shifting by known count */
7938 /*-----------------------------------------------------------------*/
7940 genRightShiftLiteral (operand * left,
7946 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7949 D(emitcode ("; genRightShiftLiteral",""));
7951 freeAsmop (right, NULL, ic, TRUE);
7953 aopOp (left, ic, FALSE);
7954 aopOp (result, ic, FALSE);
7957 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7961 size = getDataSize (left);
7962 /* test the LEFT size !!! */
7964 /* I suppose that the left size >= result size */
7967 size = getDataSize (result);
7969 movLeft2Result (left, size, result, size, 0);
7972 else if (shCount >= (size * 8))
7975 /* get sign in acc.7 */
7976 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7978 addSign (result, LSB, sign);
7985 genrshOne (result, left, shCount, sign);
7989 genrshTwo (result, left, shCount, sign);
7993 genrshFour (result, left, shCount, sign);
7999 freeAsmop (left, NULL, ic, TRUE);
8000 freeAsmop (result, NULL, ic, TRUE);
8003 /*-----------------------------------------------------------------*/
8004 /* genSignedRightShift - right shift of signed number */
8005 /*-----------------------------------------------------------------*/
8007 genSignedRightShift (iCode * ic)
8009 operand *right, *left, *result;
8012 symbol *tlbl, *tlbl1;
8015 D(emitcode ("; genSignedRightShift",""));
8017 /* we do it the hard way put the shift count in b
8018 and loop thru preserving the sign */
8020 right = IC_RIGHT (ic);
8021 left = IC_LEFT (ic);
8022 result = IC_RESULT (ic);
8024 aopOp (right, ic, FALSE);
8027 if (AOP_TYPE (right) == AOP_LIT)
8029 genRightShiftLiteral (left, right, result, ic, 1);
8032 /* shift count is unknown then we have to form
8033 a loop get the loop count in B : Note: we take
8034 only the lower order byte since shifting
8035 more that 32 bits make no sense anyway, ( the
8036 largest size of an object can be only 32 bits ) */
8039 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8040 emitcode ("inc", "b");
8041 freeAsmop (right, NULL, ic, TRUE);
8042 aopOp (left, ic, FALSE);
8043 aopOp (result, ic, FALSE);
8045 /* now move the left to the result if they are not the
8047 if (!sameRegs (AOP (left), AOP (result)) &&
8048 AOP_SIZE (result) > 1)
8051 size = AOP_SIZE (result);
8055 l = aopGet (AOP (left), offset, FALSE, TRUE);
8056 if (*l == '@' && IS_AOP_PREG (result))
8059 emitcode ("mov", "a,%s", l);
8060 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8063 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8068 /* mov the highest order bit to OVR */
8069 tlbl = newiTempLabel (NULL);
8070 tlbl1 = newiTempLabel (NULL);
8072 size = AOP_SIZE (result);
8074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8075 emitcode ("rlc", "a");
8076 emitcode ("mov", "ov,c");
8077 /* if it is only one byte then */
8080 l = aopGet (AOP (left), 0, FALSE, FALSE);
8082 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8083 emitcode ("", "%05d$:", tlbl->key + 100);
8084 emitcode ("mov", "c,ov");
8085 emitcode ("rrc", "a");
8086 emitcode ("", "%05d$:", tlbl1->key + 100);
8087 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8089 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8093 reAdjustPreg (AOP (result));
8094 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8095 emitcode ("", "%05d$:", tlbl->key + 100);
8096 emitcode ("mov", "c,ov");
8099 l = aopGet (AOP (result), offset, FALSE, FALSE);
8101 emitcode ("rrc", "a");
8102 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8104 reAdjustPreg (AOP (result));
8105 emitcode ("", "%05d$:", tlbl1->key + 100);
8106 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8110 freeAsmop (left, NULL, ic, TRUE);
8111 freeAsmop (result, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genRightShift - generate code for right shifting */
8116 /*-----------------------------------------------------------------*/
8118 genRightShift (iCode * ic)
8120 operand *right, *left, *result;
8124 symbol *tlbl, *tlbl1;
8127 D(emitcode ("; genRightShift",""));
8129 /* if signed then we do it the hard way preserve the
8130 sign bit moving it inwards */
8131 letype = getSpec (operandType (IC_LEFT (ic)));
8133 if (!SPEC_USIGN (letype))
8135 genSignedRightShift (ic);
8139 /* signed & unsigned types are treated the same : i.e. the
8140 signed is NOT propagated inwards : quoting from the
8141 ANSI - standard : "for E1 >> E2, is equivalent to division
8142 by 2**E2 if unsigned or if it has a non-negative value,
8143 otherwise the result is implementation defined ", MY definition
8144 is that the sign does not get propagated */
8146 right = IC_RIGHT (ic);
8147 left = IC_LEFT (ic);
8148 result = IC_RESULT (ic);
8150 aopOp (right, ic, FALSE);
8152 /* if the shift count is known then do it
8153 as efficiently as possible */
8154 if (AOP_TYPE (right) == AOP_LIT)
8156 genRightShiftLiteral (left, right, result, ic, 0);
8160 /* shift count is unknown then we have to form
8161 a loop get the loop count in B : Note: we take
8162 only the lower order byte since shifting
8163 more that 32 bits make no sense anyway, ( the
8164 largest size of an object can be only 32 bits ) */
8167 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8168 emitcode ("inc", "b");
8169 freeAsmop (right, NULL, ic, TRUE);
8170 aopOp (left, ic, FALSE);
8171 aopOp (result, ic, FALSE);
8173 /* now move the left to the result if they are not the
8175 if (!sameRegs (AOP (left), AOP (result)) &&
8176 AOP_SIZE (result) > 1)
8179 size = AOP_SIZE (result);
8183 l = aopGet (AOP (left), offset, FALSE, TRUE);
8184 if (*l == '@' && IS_AOP_PREG (result))
8187 emitcode ("mov", "a,%s", l);
8188 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8191 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8196 tlbl = newiTempLabel (NULL);
8197 tlbl1 = newiTempLabel (NULL);
8198 size = AOP_SIZE (result);
8201 /* if it is only one byte then */
8204 l = aopGet (AOP (left), 0, FALSE, FALSE);
8206 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8207 emitcode ("", "%05d$:", tlbl->key + 100);
8209 emitcode ("rrc", "a");
8210 emitcode ("", "%05d$:", tlbl1->key + 100);
8211 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8213 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8217 reAdjustPreg (AOP (result));
8218 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8219 emitcode ("", "%05d$:", tlbl->key + 100);
8223 l = aopGet (AOP (result), offset, FALSE, FALSE);
8225 emitcode ("rrc", "a");
8226 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8228 reAdjustPreg (AOP (result));
8230 emitcode ("", "%05d$:", tlbl1->key + 100);
8231 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8235 freeAsmop (left, NULL, ic, TRUE);
8236 freeAsmop (result, NULL, ic, TRUE);
8239 /*-----------------------------------------------------------------*/
8240 /* emitPtrByteGet - emits code to get a byte into A through a */
8241 /* pointer register (R0, R1, or DPTR). The */
8242 /* original value of A can be preserved in B. */
8243 /*-----------------------------------------------------------------*/
8245 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8252 emitcode ("mov", "b,a");
8253 emitcode ("mov", "a,@%s", rname);
8258 emitcode ("mov", "b,a");
8259 emitcode ("movx", "a,@%s", rname);
8264 emitcode ("mov", "b,a");
8265 emitcode ("movx", "a,@dptr");
8270 emitcode ("mov", "b,a");
8271 emitcode ("clr", "a");
8272 emitcode ("movc", "a,@a+dptr");
8278 emitcode ("push", "b");
8279 emitcode ("push", "acc");
8281 emitcode ("lcall", "__gptrget");
8283 emitcode ("pop", "b");
8288 /*-----------------------------------------------------------------*/
8289 /* emitPtrByteSet - emits code to set a byte from src through a */
8290 /* pointer register (R0, R1, or DPTR). */
8291 /*-----------------------------------------------------------------*/
8293 emitPtrByteSet (char *rname, int p_type, char *src)
8302 emitcode ("mov", "@%s,a", rname);
8305 emitcode ("mov", "@%s,%s", rname, src);
8310 emitcode ("movx", "@%s,a", rname);
8315 emitcode ("movx", "@dptr,a");
8320 emitcode ("lcall", "__gptrput");
8325 /*-----------------------------------------------------------------*/
8326 /* genUnpackBits - generates code for unpacking bits */
8327 /*-----------------------------------------------------------------*/
8329 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8331 int offset = 0; /* result byte offset */
8332 int rsize; /* result size */
8333 int rlen = 0; /* remaining bitfield length */
8334 sym_link *etype; /* bitfield type information */
8335 int blen; /* bitfield length */
8336 int bstr; /* bitfield starting bit within byte */
8339 D(emitcode ("; genUnpackBits",""));
8341 etype = getSpec (operandType (result));
8342 rsize = getSize (operandType (result));
8343 blen = SPEC_BLEN (etype);
8344 bstr = SPEC_BSTR (etype);
8346 if (ifx && blen <= 8)
8348 emitPtrByteGet (rname, ptype, FALSE);
8351 SNPRINTF (buffer, sizeof(buffer),
8353 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8358 emitcode ("anl", "a,#0x%02x",
8359 (((unsigned char) -1) >> (8 - blen)) << bstr);
8360 genIfxJump (ifx, "a", NULL, NULL, NULL);
8366 /* If the bitfield length is less than a byte */
8369 emitPtrByteGet (rname, ptype, FALSE);
8371 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8372 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8376 /* Bit field did not fit in a byte. Copy all
8377 but the partial byte at the end. */
8378 for (rlen=blen;rlen>=8;rlen-=8)
8380 emitPtrByteGet (rname, ptype, FALSE);
8381 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8383 emitcode ("inc", "%s", rname);
8386 /* Handle the partial byte at the end */
8389 emitPtrByteGet (rname, ptype, FALSE);
8390 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8391 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8399 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8404 /*-----------------------------------------------------------------*/
8405 /* genDataPointerGet - generates code when ptr offset is known */
8406 /*-----------------------------------------------------------------*/
8408 genDataPointerGet (operand * left,
8414 int size, offset = 0;
8416 D(emitcode ("; genDataPointerGet",""));
8418 aopOp (result, ic, TRUE);
8420 /* get the string representation of the name */
8421 l = aopGet (AOP (left), 0, FALSE, TRUE);
8422 size = AOP_SIZE (result);
8426 sprintf (buffer, "(%s + %d)", l + 1, offset);
8428 sprintf (buffer, "%s", l + 1);
8429 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8432 freeAsmop (left, NULL, ic, TRUE);
8433 freeAsmop (result, NULL, ic, TRUE);
8436 /*-----------------------------------------------------------------*/
8437 /* genNearPointerGet - emitcode for near pointer fetch */
8438 /*-----------------------------------------------------------------*/
8440 genNearPointerGet (operand * left,
8449 sym_link *rtype, *retype;
8450 sym_link *ltype = operandType (left);
8453 D(emitcode ("; genNearPointerGet",""));
8455 rtype = operandType (result);
8456 retype = getSpec (rtype);
8458 aopOp (left, ic, FALSE);
8460 /* if left is rematerialisable and
8461 result is not bitfield variable type and
8462 the left is pointer to data space i.e
8463 lower 128 bytes of space */
8464 if (AOP_TYPE (left) == AOP_IMMD &&
8465 !IS_BITFIELD (retype) &&
8466 DCL_TYPE (ltype) == POINTER)
8468 genDataPointerGet (left, result, ic);
8472 /* if the value is already in a pointer register
8473 then don't need anything more */
8474 if (!AOP_INPREG (AOP (left)))
8476 if (IS_AOP_PREG (left))
8478 // Aha, it is a pointer, just in disguise.
8479 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8482 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8483 __FILE__, __LINE__);
8488 emitcode ("mov", "a%s,%s", rname + 1, rname);
8489 rname++; // skip the '@'.
8494 /* otherwise get a free pointer register */
8496 preg = getFreePtr (ic, &aop, FALSE);
8497 emitcode ("mov", "%s,%s",
8499 aopGet (AOP (left), 0, FALSE, TRUE));
8504 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8506 //aopOp (result, ic, FALSE);
8507 aopOp (result, ic, result?TRUE:FALSE);
8509 /* if bitfield then unpack the bits */
8510 if (IS_BITFIELD (retype))
8511 genUnpackBits (result, rname, POINTER, ifx);
8514 /* we have can just get the values */
8515 int size = AOP_SIZE (result);
8520 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8523 emitcode ("mov", "a,@%s", rname);
8525 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8529 sprintf (buffer, "@%s", rname);
8530 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8534 emitcode ("inc", "%s", rname);
8538 /* now some housekeeping stuff */
8539 if (aop) /* we had to allocate for this iCode */
8541 if (pi) { /* post increment present */
8542 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8544 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8548 /* we did not allocate which means left
8549 already in a pointer register, then
8550 if size > 0 && this could be used again
8551 we have to point it back to where it
8553 if ((AOP_SIZE (result) > 1 &&
8554 !OP_SYMBOL (left)->remat &&
8555 (OP_SYMBOL (left)->liveTo > ic->seq ||
8559 int size = AOP_SIZE (result) - 1;
8561 emitcode ("dec", "%s", rname);
8565 if (ifx && !ifx->generated)
8567 genIfxJump (ifx, "a", left, NULL, result);
8571 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8572 freeAsmop (left, NULL, ic, TRUE);
8573 if (pi) pi->generated = 1;
8576 /*-----------------------------------------------------------------*/
8577 /* genPagedPointerGet - emitcode for paged pointer fetch */
8578 /*-----------------------------------------------------------------*/
8580 genPagedPointerGet (operand * left,
8589 sym_link *rtype, *retype;
8591 D(emitcode ("; genPagedPointerGet",""));
8593 rtype = operandType (result);
8594 retype = getSpec (rtype);
8596 aopOp (left, ic, FALSE);
8598 /* if the value is already in a pointer register
8599 then don't need anything more */
8600 if (!AOP_INPREG (AOP (left)))
8602 /* otherwise get a free pointer register */
8604 preg = getFreePtr (ic, &aop, FALSE);
8605 emitcode ("mov", "%s,%s",
8607 aopGet (AOP (left), 0, FALSE, TRUE));
8611 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8613 aopOp (result, ic, FALSE);
8615 /* if bitfield then unpack the bits */
8616 if (IS_BITFIELD (retype))
8617 genUnpackBits (result, rname, PPOINTER, ifx);
8620 /* we have can just get the values */
8621 int size = AOP_SIZE (result);
8627 emitcode ("movx", "a,@%s", rname);
8629 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8634 emitcode ("inc", "%s", rname);
8638 /* now some housekeeping stuff */
8639 if (aop) /* we had to allocate for this iCode */
8641 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8642 freeAsmop (NULL, aop, ic, TRUE);
8646 /* we did not allocate which means left
8647 already in a pointer register, then
8648 if size > 0 && this could be used again
8649 we have to point it back to where it
8651 if ((AOP_SIZE (result) > 1 &&
8652 !OP_SYMBOL (left)->remat &&
8653 (OP_SYMBOL (left)->liveTo > ic->seq ||
8657 int size = AOP_SIZE (result) - 1;
8659 emitcode ("dec", "%s", rname);
8663 if (ifx && !ifx->generated)
8665 genIfxJump (ifx, "a", left, NULL, result);
8669 freeAsmop (left, NULL, ic, TRUE);
8670 freeAsmop (result, NULL, ic, TRUE);
8671 if (pi) pi->generated = 1;
8675 /*--------------------------------------------------------------------*/
8676 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8677 /*--------------------------------------------------------------------*/
8679 loadDptrFromOperand (operand *op, bool loadBToo)
8681 if (AOP_TYPE (op) != AOP_STR)
8683 /* if this is rematerializable */
8684 if (AOP_TYPE (op) == AOP_IMMD)
8686 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8689 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8690 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8693 wassertl(FALSE, "need pointerCode");
8694 emitcode ("", "; mov b,???");
8695 /* genPointerGet and genPointerSet originally did different
8696 ** things for this case. Both seem wrong.
8697 ** from genPointerGet:
8698 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8699 ** from genPointerSet:
8700 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8705 else if (AOP_TYPE (op) == AOP_DPTR)
8709 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8710 emitcode ("push", "acc");
8711 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8712 emitcode ("push", "acc");
8713 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8714 emitcode ("pop", "dph");
8715 emitcode ("pop", "dpl");
8719 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8720 emitcode ("push", "acc");
8721 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8722 emitcode ("pop", "dpl");
8726 { /* we need to get it byte by byte */
8727 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8728 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8730 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8735 /*-----------------------------------------------------------------*/
8736 /* genFarPointerGet - gget value from far space */
8737 /*-----------------------------------------------------------------*/
8739 genFarPointerGet (operand * left,
8740 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8743 sym_link *retype = getSpec (operandType (result));
8745 D(emitcode ("; genFarPointerGet",""));
8747 aopOp (left, ic, FALSE);
8748 loadDptrFromOperand (left, FALSE);
8750 /* so dptr now contains the address */
8751 aopOp (result, ic, FALSE);
8753 /* if bit then unpack */
8754 if (IS_BITFIELD (retype))
8755 genUnpackBits (result, "dptr", FPOINTER, ifx);
8758 size = AOP_SIZE (result);
8763 emitcode ("movx", "a,@dptr");
8765 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8767 emitcode ("inc", "dptr");
8771 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8773 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8774 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8778 if (ifx && !ifx->generated)
8780 genIfxJump (ifx, "a", left, NULL, result);
8783 freeAsmop (left, NULL, ic, TRUE);
8784 freeAsmop (result, NULL, ic, TRUE);
8787 /*-----------------------------------------------------------------*/
8788 /* genCodePointerGet - gget value from code space */
8789 /*-----------------------------------------------------------------*/
8791 genCodePointerGet (operand * left,
8792 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8795 sym_link *retype = getSpec (operandType (result));
8797 D(emitcode ("; genCodePointerGet",""));
8799 aopOp (left, ic, FALSE);
8800 loadDptrFromOperand (left, FALSE);
8802 /* so dptr now contains the address */
8803 aopOp (result, ic, FALSE);
8805 /* if bit then unpack */
8806 if (IS_BITFIELD (retype))
8807 genUnpackBits (result, "dptr", CPOINTER, ifx);
8810 size = AOP_SIZE (result);
8817 emitcode ("clr", "a");
8818 emitcode ("movc", "a,@a+dptr");
8820 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8821 emitcode ("inc", "dptr");
8825 emitcode ("mov", "a,#0x%02x", offset);
8826 emitcode ("movc", "a,@a+dptr");
8828 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8833 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8835 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8836 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8840 if (ifx && !ifx->generated)
8842 genIfxJump (ifx, "a", left, NULL, result);
8845 freeAsmop (left, NULL, ic, TRUE);
8846 freeAsmop (result, NULL, ic, TRUE);
8849 /*-----------------------------------------------------------------*/
8850 /* genGenPointerGet - gget value from generic pointer space */
8851 /*-----------------------------------------------------------------*/
8853 genGenPointerGet (operand * left,
8854 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8857 sym_link *retype = getSpec (operandType (result));
8859 D(emitcode ("; genGenPointerGet",""));
8861 aopOp (left, ic, FALSE);
8862 loadDptrFromOperand (left, TRUE);
8864 /* so dptr know contains the address */
8865 aopOp (result, ic, FALSE);
8867 /* if bit then unpack */
8868 if (IS_BITFIELD (retype))
8869 genUnpackBits (result, "dptr", GPOINTER, ifx);
8872 size = AOP_SIZE (result);
8877 emitcode ("lcall", "__gptrget");
8879 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8881 emitcode ("inc", "dptr");
8885 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8887 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8888 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8892 if (ifx && !ifx->generated)
8894 genIfxJump (ifx, "a", left, NULL, result);
8898 freeAsmop (left, NULL, ic, TRUE);
8899 freeAsmop (result, NULL, ic, TRUE);
8902 /*-----------------------------------------------------------------*/
8903 /* genPointerGet - generate code for pointer get */
8904 /*-----------------------------------------------------------------*/
8906 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8908 operand *left, *result;
8909 sym_link *type, *etype;
8912 D(emitcode ("; genPointerGet",""));
8914 left = IC_LEFT (ic);
8915 result = IC_RESULT (ic);
8917 if (getSize (operandType (result))>1)
8920 /* depending on the type of pointer we need to
8921 move it to the correct pointer register */
8922 type = operandType (left);
8923 etype = getSpec (type);
8924 /* if left is of type of pointer then it is simple */
8925 if (IS_PTR (type) && !IS_FUNC (type->next))
8926 p_type = DCL_TYPE (type);
8929 /* we have to go by the storage class */
8930 p_type = PTR_TYPE (SPEC_OCLS (etype));
8933 /* special case when cast remat */
8934 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8935 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8936 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8937 type = operandType (left);
8938 p_type = DCL_TYPE (type);
8940 /* now that we have the pointer type we assign
8941 the pointer values */
8947 genNearPointerGet (left, result, ic, pi, ifx);
8951 genPagedPointerGet (left, result, ic, pi, ifx);
8955 genFarPointerGet (left, result, ic, pi, ifx);
8959 genCodePointerGet (left, result, ic, pi, ifx);
8963 genGenPointerGet (left, result, ic, pi, ifx);
8971 /*-----------------------------------------------------------------*/
8972 /* genPackBits - generates code for packed bit storage */
8973 /*-----------------------------------------------------------------*/
8975 genPackBits (sym_link * etype,
8977 char *rname, int p_type)
8979 int offset = 0; /* source byte offset */
8980 int rlen = 0; /* remaining bitfield length */
8981 int blen; /* bitfield length */
8982 int bstr; /* bitfield starting bit within byte */
8983 int litval; /* source literal value (if AOP_LIT) */
8984 unsigned char mask; /* bitmask within current byte */
8986 D(emitcode ("; genPackBits",""));
8988 blen = SPEC_BLEN (etype);
8989 bstr = SPEC_BSTR (etype);
8991 /* If the bitfield length is less than a byte */
8994 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8995 (unsigned char) (0xFF >> (8 - bstr)));
8997 if (AOP_TYPE (right) == AOP_LIT)
8999 /* Case with a bitfield length <8 and literal source
9001 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9003 litval &= (~mask) & 0xff;
9004 emitPtrByteGet (rname, p_type, FALSE);
9005 if ((mask|litval)!=0xff)
9006 emitcode ("anl","a,#0x%02x", mask);
9008 emitcode ("orl","a,#0x%02x", litval);
9012 if ((blen==1) && (p_type!=GPOINTER))
9014 /* Case with a bitfield length == 1 and no generic pointer
9016 if (AOP_TYPE (right) == AOP_CRY)
9017 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9020 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9021 emitcode ("rrc","a");
9023 emitPtrByteGet (rname, p_type, FALSE);
9024 emitcode ("mov","acc.%d,c",bstr);
9029 /* Case with a bitfield length < 8 and arbitrary source
9031 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9032 /* shift and mask source value */
9034 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9037 /* transfer A to B and get next byte */
9038 emitPtrByteGet (rname, p_type, TRUE);
9040 emitcode ("anl", "a,#0x%02x", mask);
9041 emitcode ("orl", "a,b");
9042 if (p_type == GPOINTER)
9043 emitcode ("pop", "b");
9049 emitPtrByteSet (rname, p_type, "a");
9053 /* Bit length is greater than 7 bits. In this case, copy */
9054 /* all except the partial byte at the end */
9055 for (rlen=blen;rlen>=8;rlen-=8)
9057 emitPtrByteSet (rname, p_type,
9058 aopGet (AOP (right), offset++, FALSE, TRUE) );
9060 emitcode ("inc", "%s", rname);
9063 /* If there was a partial byte at the end */
9066 mask = (((unsigned char) -1 << rlen) & 0xff);
9068 if (AOP_TYPE (right) == AOP_LIT)
9070 /* Case with partial byte and literal source
9072 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9073 litval >>= (blen-rlen);
9074 litval &= (~mask) & 0xff;
9075 emitPtrByteGet (rname, p_type, FALSE);
9076 if ((mask|litval)!=0xff)
9077 emitcode ("anl","a,#0x%02x", mask);
9079 emitcode ("orl","a,#0x%02x", litval);
9084 /* Case with partial byte and arbitrary source
9086 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9087 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9090 /* transfer A to B and get next byte */
9091 emitPtrByteGet (rname, p_type, TRUE);
9093 emitcode ("anl", "a,#0x%02x", mask);
9094 emitcode ("orl", "a,b");
9095 if (p_type == GPOINTER)
9096 emitcode ("pop", "b");
9100 emitPtrByteSet (rname, p_type, "a");
9106 /*-----------------------------------------------------------------*/
9107 /* genDataPointerSet - remat pointer to data space */
9108 /*-----------------------------------------------------------------*/
9110 genDataPointerSet (operand * right,
9114 int size, offset = 0;
9115 char *l, buffer[256];
9117 D(emitcode ("; genDataPointerSet",""));
9119 aopOp (right, ic, FALSE);
9121 l = aopGet (AOP (result), 0, FALSE, TRUE);
9122 size = AOP_SIZE (right);
9126 sprintf (buffer, "(%s + %d)", l + 1, offset);
9128 sprintf (buffer, "%s", l + 1);
9129 emitcode ("mov", "%s,%s", buffer,
9130 aopGet (AOP (right), offset++, FALSE, FALSE));
9133 freeAsmop (right, NULL, ic, TRUE);
9134 freeAsmop (result, NULL, ic, TRUE);
9137 /*-----------------------------------------------------------------*/
9138 /* genNearPointerSet - emitcode for near pointer put */
9139 /*-----------------------------------------------------------------*/
9141 genNearPointerSet (operand * right,
9149 sym_link *retype, *letype;
9150 sym_link *ptype = operandType (result);
9152 D(emitcode ("; genNearPointerSet",""));
9154 retype = getSpec (operandType (right));
9155 letype = getSpec (ptype);
9156 aopOp (result, ic, FALSE);
9158 /* if the result is rematerializable &
9159 in data space & not a bit variable */
9160 if (AOP_TYPE (result) == AOP_IMMD &&
9161 DCL_TYPE (ptype) == POINTER &&
9162 !IS_BITVAR (retype) &&
9163 !IS_BITVAR (letype))
9165 genDataPointerSet (right, result, ic);
9169 /* if the value is already in a pointer register
9170 then don't need anything more */
9171 if (!AOP_INPREG (AOP (result)))
9174 //AOP_TYPE (result) == AOP_STK
9178 // Aha, it is a pointer, just in disguise.
9179 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9182 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9183 __FILE__, __LINE__);
9188 emitcode ("mov", "a%s,%s", rname + 1, rname);
9189 rname++; // skip the '@'.
9194 /* otherwise get a free pointer register */
9196 preg = getFreePtr (ic, &aop, FALSE);
9197 emitcode ("mov", "%s,%s",
9199 aopGet (AOP (result), 0, FALSE, TRUE));
9205 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9208 aopOp (right, ic, FALSE);
9210 /* if bitfield then unpack the bits */
9211 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9212 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9215 /* we have can just get the values */
9216 int size = AOP_SIZE (right);
9221 l = aopGet (AOP (right), offset, FALSE, TRUE);
9225 emitcode ("mov", "@%s,a", rname);
9228 emitcode ("mov", "@%s,%s", rname, l);
9230 emitcode ("inc", "%s", rname);
9235 /* now some housekeeping stuff */
9236 if (aop) /* we had to allocate for this iCode */
9239 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9240 freeAsmop (NULL, aop, ic, TRUE);
9244 /* we did not allocate which means left
9245 already in a pointer register, then
9246 if size > 0 && this could be used again
9247 we have to point it back to where it
9249 if ((AOP_SIZE (right) > 1 &&
9250 !OP_SYMBOL (result)->remat &&
9251 (OP_SYMBOL (result)->liveTo > ic->seq ||
9255 int size = AOP_SIZE (right) - 1;
9257 emitcode ("dec", "%s", rname);
9262 if (pi) pi->generated = 1;
9263 freeAsmop (result, NULL, ic, TRUE);
9264 freeAsmop (right, NULL, ic, TRUE);
9267 /*-----------------------------------------------------------------*/
9268 /* genPagedPointerSet - emitcode for Paged pointer put */
9269 /*-----------------------------------------------------------------*/
9271 genPagedPointerSet (operand * right,
9279 sym_link *retype, *letype;
9281 D(emitcode ("; genPagedPointerSet",""));
9283 retype = getSpec (operandType (right));
9284 letype = getSpec (operandType (result));
9286 aopOp (result, ic, FALSE);
9288 /* if the value is already in a pointer register
9289 then don't need anything more */
9290 if (!AOP_INPREG (AOP (result)))
9292 /* otherwise get a free pointer register */
9294 preg = getFreePtr (ic, &aop, FALSE);
9295 emitcode ("mov", "%s,%s",
9297 aopGet (AOP (result), 0, FALSE, TRUE));
9301 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9303 aopOp (right, ic, FALSE);
9305 /* if bitfield then unpack the bits */
9306 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9307 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9310 /* we have can just get the values */
9311 int size = AOP_SIZE (right);
9316 l = aopGet (AOP (right), offset, FALSE, TRUE);
9319 emitcode ("movx", "@%s,a", rname);
9322 emitcode ("inc", "%s", rname);
9328 /* now some housekeeping stuff */
9329 if (aop) /* we had to allocate for this iCode */
9332 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9333 freeAsmop (NULL, aop, ic, TRUE);
9337 /* we did not allocate which means left
9338 already in a pointer register, then
9339 if size > 0 && this could be used again
9340 we have to point it back to where it
9342 if (AOP_SIZE (right) > 1 &&
9343 !OP_SYMBOL (result)->remat &&
9344 (OP_SYMBOL (result)->liveTo > ic->seq ||
9347 int size = AOP_SIZE (right) - 1;
9349 emitcode ("dec", "%s", rname);
9354 if (pi) pi->generated = 1;
9355 freeAsmop (result, NULL, ic, TRUE);
9356 freeAsmop (right, NULL, ic, TRUE);
9361 /*-----------------------------------------------------------------*/
9362 /* genFarPointerSet - set value from far space */
9363 /*-----------------------------------------------------------------*/
9365 genFarPointerSet (operand * right,
9366 operand * result, iCode * ic, iCode * pi)
9369 sym_link *retype = getSpec (operandType (right));
9370 sym_link *letype = getSpec (operandType (result));
9372 D(emitcode ("; genFarPointerSet",""));
9374 aopOp (result, ic, FALSE);
9375 loadDptrFromOperand (result, FALSE);
9377 /* so dptr know contains the address */
9378 aopOp (right, ic, FALSE);
9380 /* if bit then unpack */
9381 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9382 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9385 size = AOP_SIZE (right);
9390 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9392 emitcode ("movx", "@dptr,a");
9394 emitcode ("inc", "dptr");
9397 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9398 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9399 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9402 freeAsmop (result, NULL, ic, TRUE);
9403 freeAsmop (right, NULL, ic, TRUE);
9406 /*-----------------------------------------------------------------*/
9407 /* genGenPointerSet - set value from generic pointer space */
9408 /*-----------------------------------------------------------------*/
9410 genGenPointerSet (operand * right,
9411 operand * result, iCode * ic, iCode * pi)
9414 sym_link *retype = getSpec (operandType (right));
9415 sym_link *letype = getSpec (operandType (result));
9417 D(emitcode ("; genGenPointerSet",""));
9419 aopOp (result, ic, FALSE);
9420 loadDptrFromOperand (result, TRUE);
9422 /* so dptr know contains the address */
9423 aopOp (right, ic, FALSE);
9425 /* if bit then unpack */
9426 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9427 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9430 size = AOP_SIZE (right);
9435 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9437 emitcode ("lcall", "__gptrput");
9439 emitcode ("inc", "dptr");
9443 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9444 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9445 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9448 freeAsmop (result, NULL, ic, TRUE);
9449 freeAsmop (right, NULL, ic, TRUE);
9452 /*-----------------------------------------------------------------*/
9453 /* genPointerSet - stores the value into a pointer location */
9454 /*-----------------------------------------------------------------*/
9456 genPointerSet (iCode * ic, iCode *pi)
9458 operand *right, *result;
9459 sym_link *type, *etype;
9462 D(emitcode ("; genPointerSet",""));
9464 right = IC_RIGHT (ic);
9465 result = IC_RESULT (ic);
9467 /* depending on the type of pointer we need to
9468 move it to the correct pointer register */
9469 type = operandType (result);
9470 etype = getSpec (type);
9471 /* if left is of type of pointer then it is simple */
9472 if (IS_PTR (type) && !IS_FUNC (type->next))
9474 p_type = DCL_TYPE (type);
9478 /* we have to go by the storage class */
9479 p_type = PTR_TYPE (SPEC_OCLS (etype));
9482 /* special case when cast remat */
9483 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9484 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9485 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9486 type = operandType (result);
9487 p_type = DCL_TYPE (type);
9489 /* now that we have the pointer type we assign
9490 the pointer values */
9496 genNearPointerSet (right, result, ic, pi);
9500 genPagedPointerSet (right, result, ic, pi);
9504 genFarPointerSet (right, result, ic, pi);
9508 genGenPointerSet (right, result, ic, pi);
9512 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9513 "genPointerSet: illegal pointer type");
9518 /*-----------------------------------------------------------------*/
9519 /* genIfx - generate code for Ifx statement */
9520 /*-----------------------------------------------------------------*/
9522 genIfx (iCode * ic, iCode * popIc)
9524 operand *cond = IC_COND (ic);
9527 D(emitcode ("; genIfx",""));
9529 aopOp (cond, ic, FALSE);
9531 /* get the value into acc */
9532 if (AOP_TYPE (cond) != AOP_CRY)
9536 /* the result is now in the accumulator */
9537 freeAsmop (cond, NULL, ic, TRUE);
9539 /* if there was something to be popped then do it */
9543 /* if the condition is a bit variable */
9544 if (isbit && IS_ITEMP (cond) &&
9546 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9547 else if (isbit && !IS_ITEMP (cond))
9548 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9550 genIfxJump (ic, "a", NULL, NULL, NULL);
9555 /*-----------------------------------------------------------------*/
9556 /* genAddrOf - generates code for address of */
9557 /*-----------------------------------------------------------------*/
9559 genAddrOf (iCode * ic)
9561 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9564 D(emitcode ("; genAddrOf",""));
9566 aopOp (IC_RESULT (ic), ic, FALSE);
9568 /* if the operand is on the stack then we
9569 need to get the stack offset of this
9573 /* if it has an offset then we need to compute
9577 emitcode ("mov", "a,_bp");
9578 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9579 ((char) (sym->stack - _G.nRegsSaved)) :
9580 ((char) sym->stack)) & 0xff);
9581 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9585 /* we can just move _bp */
9586 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9588 /* fill the result with zero */
9589 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9594 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9600 /* object not on stack then we need the name */
9601 size = AOP_SIZE (IC_RESULT (ic));
9606 char s[SDCC_NAME_MAX];
9608 sprintf (s, "#(%s >> %d)",
9612 sprintf (s, "#%s", sym->rname);
9613 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9621 /*-----------------------------------------------------------------*/
9622 /* genFarFarAssign - assignment when both are in far space */
9623 /*-----------------------------------------------------------------*/
9625 genFarFarAssign (operand * result, operand * right, iCode * ic)
9627 int size = AOP_SIZE (right);
9631 D(emitcode ("; genFarFarAssign",""));
9633 /* first push the right side on to the stack */
9636 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9638 emitcode ("push", "acc");
9641 freeAsmop (right, NULL, ic, FALSE);
9642 /* now assign DPTR to result */
9643 aopOp (result, ic, FALSE);
9644 size = AOP_SIZE (result);
9647 emitcode ("pop", "acc");
9648 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9650 freeAsmop (result, NULL, ic, FALSE);
9654 /*-----------------------------------------------------------------*/
9655 /* genAssign - generate code for assignment */
9656 /*-----------------------------------------------------------------*/
9658 genAssign (iCode * ic)
9660 operand *result, *right;
9662 unsigned long lit = 0L;
9664 D(emitcode("; genAssign",""));
9666 result = IC_RESULT (ic);
9667 right = IC_RIGHT (ic);
9669 /* if they are the same */
9670 if (operandsEqu (result, right) &&
9671 !isOperandVolatile (result, FALSE) &&
9672 !isOperandVolatile (right, FALSE))
9675 aopOp (right, ic, FALSE);
9677 /* special case both in far space */
9678 if (AOP_TYPE (right) == AOP_DPTR &&
9679 IS_TRUE_SYMOP (result) &&
9680 isOperandInFarSpace (result))
9683 genFarFarAssign (result, right, ic);
9687 aopOp (result, ic, TRUE);
9689 /* if they are the same registers */
9690 if (sameRegs (AOP (right), AOP (result)) &&
9691 !isOperandVolatile (result, FALSE) &&
9692 !isOperandVolatile (right, FALSE))
9695 /* if the result is a bit */
9696 if (AOP_TYPE (result) == AOP_CRY)
9699 /* if the right size is a literal then
9700 we know what the value is */
9701 if (AOP_TYPE (right) == AOP_LIT)
9703 if (((int) operandLitValue (right)))
9704 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9706 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9710 /* the right is also a bit variable */
9711 if (AOP_TYPE (right) == AOP_CRY)
9713 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9714 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9720 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9724 /* bit variables done */
9726 size = AOP_SIZE (result);
9728 if (AOP_TYPE (right) == AOP_LIT)
9729 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9731 (AOP_TYPE (result) != AOP_REG) &&
9732 (AOP_TYPE (right) == AOP_LIT) &&
9733 !IS_FLOAT (operandType (right)) &&
9736 while ((size) && (lit))
9738 aopPut (AOP (result),
9739 aopGet (AOP (right), offset, FALSE, FALSE),
9741 isOperandVolatile (result, FALSE));
9746 emitcode ("clr", "a");
9749 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9757 aopPut (AOP (result),
9758 aopGet (AOP (right), offset, FALSE, FALSE),
9760 isOperandVolatile (result, FALSE));
9766 freeAsmop (right, NULL, ic, TRUE);
9767 freeAsmop (result, NULL, ic, TRUE);
9770 /*-----------------------------------------------------------------*/
9771 /* genJumpTab - genrates code for jump table */
9772 /*-----------------------------------------------------------------*/
9774 genJumpTab (iCode * ic)
9776 symbol *jtab,*jtablo,*jtabhi;
9780 D(emitcode ("; genJumpTab",""));
9782 count = elementsInSet( IC_JTLABELS (ic) );
9786 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9787 if the switch argument is in a register.
9788 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9789 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9790 How will multiply by three be updated ???*/
9791 aopOp (IC_JTCOND (ic), ic, FALSE);
9792 /* get the condition into accumulator */
9793 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9795 /* multiply by three */
9796 emitcode ("add", "a,acc");
9797 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9798 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9800 jtab = newiTempLabel (NULL);
9801 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9802 emitcode ("jmp", "@a+dptr");
9803 emitcode ("", "%05d$:", jtab->key + 100);
9804 /* now generate the jump labels */
9805 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9806 jtab = setNextItem (IC_JTLABELS (ic)))
9807 emitcode ("ljmp", "%05d$", jtab->key + 100);
9811 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9812 if the switch argument is in a register.
9813 For n>6 this algorithm may be more compact */
9814 jtablo = newiTempLabel (NULL);
9815 jtabhi = newiTempLabel (NULL);
9817 /* get the condition into accumulator.
9818 Using b as temporary storage, if register push/pop is needed */
9819 aopOp (IC_JTCOND (ic), ic, FALSE);
9820 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9821 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9822 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9824 // (MB) what if B is in use???
9825 wassertl(!_G.BInUse, "B was in use");
9826 emitcode ("mov", "b,%s", l);
9829 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9833 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9834 emitcode ("movc", "a,@a+pc");
9835 emitcode ("push", "acc");
9838 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9839 emitcode ("movc", "a,@a+pc");
9840 emitcode ("push", "acc");
9844 /* this scales up to n<=255, but needs two more bytes
9846 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9847 emitcode ("movc", "a,@a+dptr");
9848 emitcode ("push", "acc");
9851 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9852 emitcode ("movc", "a,@a+dptr");
9853 emitcode ("push", "acc");
9856 emitcode ("ret", "");
9858 /* now generate jump table, LSB */
9859 emitcode ("", "%05d$:", jtablo->key + 100);
9860 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9861 jtab = setNextItem (IC_JTLABELS (ic)))
9862 emitcode (".db", "%05d$", jtab->key + 100);
9864 /* now generate jump table, MSB */
9865 emitcode ("", "%05d$:", jtabhi->key + 100);
9866 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9867 jtab = setNextItem (IC_JTLABELS (ic)))
9868 emitcode (".db", "%05d$>>8", jtab->key + 100);
9872 /*-----------------------------------------------------------------*/
9873 /* genCast - gen code for casting */
9874 /*-----------------------------------------------------------------*/
9876 genCast (iCode * ic)
9878 operand *result = IC_RESULT (ic);
9879 sym_link *ctype = operandType (IC_LEFT (ic));
9880 sym_link *rtype = operandType (IC_RIGHT (ic));
9881 operand *right = IC_RIGHT (ic);
9884 D(emitcode("; genCast",""));
9886 /* if they are equivalent then do nothing */
9887 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9890 aopOp (right, ic, FALSE);
9891 aopOp (result, ic, FALSE);
9893 /* if the result is a bit (and not a bitfield) */
9894 // if (AOP_TYPE (result) == AOP_CRY)
9895 if (IS_BITVAR (OP_SYMBOL (result)->type)
9896 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9898 /* if the right size is a literal then
9899 we know what the value is */
9900 if (AOP_TYPE (right) == AOP_LIT)
9902 if (((int) operandLitValue (right)))
9903 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9905 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9910 /* the right is also a bit variable */
9911 if (AOP_TYPE (right) == AOP_CRY)
9913 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9914 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9920 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9925 /* if they are the same size : or less */
9926 if (AOP_SIZE (result) <= AOP_SIZE (right))
9929 /* if they are in the same place */
9930 if (sameRegs (AOP (right), AOP (result)))
9933 /* if they in different places then copy */
9934 size = AOP_SIZE (result);
9938 aopPut (AOP (result),
9939 aopGet (AOP (right), offset, FALSE, FALSE),
9941 isOperandVolatile (result, FALSE));
9948 /* if the result is of type pointer */
9953 sym_link *type = operandType (right);
9954 sym_link *etype = getSpec (type);
9956 /* pointer to generic pointer */
9957 if (IS_GENPTR (ctype))
9960 p_type = DCL_TYPE (type);
9963 if (SPEC_SCLS(etype)==S_REGISTER) {
9964 // let's assume it is a generic pointer
9967 /* we have to go by the storage class */
9968 p_type = PTR_TYPE (SPEC_OCLS (etype));
9972 /* the first two bytes are known */
9973 size = GPTRSIZE - 1;
9977 aopPut (AOP (result),
9978 aopGet (AOP (right), offset, FALSE, FALSE),
9980 isOperandVolatile (result, FALSE));
9983 /* the last byte depending on type */
9985 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9990 // pointerTypeToGPByte will have bitched.
9994 sprintf(gpValStr, "#0x%d", gpVal);
9995 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10000 /* just copy the pointers */
10001 size = AOP_SIZE (result);
10005 aopPut (AOP (result),
10006 aopGet (AOP (right), offset, FALSE, FALSE),
10008 isOperandVolatile (result, FALSE));
10014 /* so we now know that the size of destination is greater
10015 than the size of the source */
10016 /* we move to result for the size of source */
10017 size = AOP_SIZE (right);
10021 aopPut (AOP (result),
10022 aopGet (AOP (right), offset, FALSE, FALSE),
10024 isOperandVolatile (result, FALSE));
10028 /* now depending on the sign of the source && destination */
10029 size = AOP_SIZE (result) - AOP_SIZE (right);
10030 /* if unsigned or not an integral type */
10031 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10034 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10038 /* we need to extend the sign :{ */
10039 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10042 emitcode ("rlc", "a");
10043 emitcode ("subb", "a,acc");
10045 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10048 /* we are done hurray !!!! */
10051 freeAsmop (right, NULL, ic, TRUE);
10052 freeAsmop (result, NULL, ic, TRUE);
10056 /*-----------------------------------------------------------------*/
10057 /* genDjnz - generate decrement & jump if not zero instrucion */
10058 /*-----------------------------------------------------------------*/
10060 genDjnz (iCode * ic, iCode * ifx)
10062 symbol *lbl, *lbl1;
10066 D(emitcode ("; genDjnz",""));
10068 /* if the if condition has a false label
10069 then we cannot save */
10070 if (IC_FALSE (ifx))
10073 /* if the minus is not of the form
10075 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10076 !IS_OP_LITERAL (IC_RIGHT (ic)))
10079 if (operandLitValue (IC_RIGHT (ic)) != 1)
10082 /* if the size of this greater than one then no
10084 if (getSize (operandType (IC_RESULT (ic))) > 1)
10087 /* otherwise we can save BIG */
10088 lbl = newiTempLabel (NULL);
10089 lbl1 = newiTempLabel (NULL);
10091 aopOp (IC_RESULT (ic), ic, FALSE);
10093 if (AOP_NEEDSACC(IC_RESULT(ic)))
10095 /* If the result is accessed indirectly via
10096 * the accumulator, we must explicitly write
10097 * it back after the decrement.
10099 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10101 if (strcmp(rByte, "a"))
10103 /* Something is hopelessly wrong */
10104 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10105 __FILE__, __LINE__);
10106 /* We can just give up; the generated code will be inefficient,
10107 * but what the hey.
10109 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10112 emitcode ("dec", "%s", rByte);
10113 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10114 emitcode ("jnz", "%05d$", lbl->key + 100);
10116 else if (IS_AOP_PREG (IC_RESULT (ic)))
10118 emitcode ("dec", "%s",
10119 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10120 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10121 emitcode ("jnz", "%05d$", lbl->key + 100);
10125 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10128 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10129 emitcode ("", "%05d$:", lbl->key + 100);
10130 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10131 emitcode ("", "%05d$:", lbl1->key + 100);
10133 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10134 ifx->generated = 1;
10138 /*-----------------------------------------------------------------*/
10139 /* genReceive - generate code for a receive iCode */
10140 /*-----------------------------------------------------------------*/
10142 genReceive (iCode * ic)
10144 int size = getSize (operandType (IC_RESULT (ic)));
10146 D(emitcode ("; genReceive",""));
10148 if (ic->argreg == 1) { /* first parameter */
10149 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10150 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10151 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10154 int receivingA = 0;
10157 for (offset = 0; offset<size; offset++)
10158 if (!strcmp (fReturn[offset], "a"))
10163 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10165 for (offset = size-1; offset>0; offset--)
10166 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10167 emitcode("mov","a,%s", fReturn[0]);
10169 aopOp (IC_RESULT (ic), ic, FALSE);
10171 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10172 isOperandVolatile (IC_RESULT (ic), FALSE));
10173 for (offset = 1; offset<size; offset++)
10174 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10175 isOperandVolatile (IC_RESULT (ic), FALSE));
10181 if (getTempRegs(tempRegs, size, ic))
10183 for (offset = 0; offset<size; offset++)
10184 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10185 aopOp (IC_RESULT (ic), ic, FALSE);
10186 for (offset = 0; offset<size; offset++)
10187 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10188 isOperandVolatile (IC_RESULT (ic), FALSE));
10193 offset = fReturnSizeMCS51 - size;
10195 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10196 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10199 aopOp (IC_RESULT (ic), ic, FALSE);
10200 size = AOP_SIZE (IC_RESULT (ic));
10203 emitcode ("pop", "acc");
10204 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10209 aopOp (IC_RESULT (ic), ic, FALSE);
10211 assignResultValue (IC_RESULT (ic));
10213 } else { /* second receive onwards */
10215 aopOp (IC_RESULT (ic), ic, FALSE);
10216 rb1off = ic->argreg;
10218 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10223 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10226 /*-----------------------------------------------------------------*/
10227 /* genDummyRead - generate code for dummy read of volatiles */
10228 /*-----------------------------------------------------------------*/
10230 genDummyRead (iCode * ic)
10235 D(emitcode("; genDummyRead",""));
10237 op = IC_RIGHT (ic);
10238 if (op && IS_SYMOP (op))
10240 aopOp (op, ic, FALSE);
10242 /* if the result is a bit */
10243 if (AOP_TYPE (op) == AOP_CRY)
10244 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10247 /* bit variables done */
10249 size = AOP_SIZE (op);
10253 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10258 freeAsmop (op, NULL, ic, TRUE);
10262 if (op && IS_SYMOP (op))
10264 aopOp (op, ic, FALSE);
10266 /* if the result is a bit */
10267 if (AOP_TYPE (op) == AOP_CRY)
10268 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10271 /* bit variables done */
10273 size = AOP_SIZE (op);
10277 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10282 freeAsmop (op, NULL, ic, TRUE);
10286 /*-----------------------------------------------------------------*/
10287 /* genCritical - generate code for start of a critical sequence */
10288 /*-----------------------------------------------------------------*/
10290 genCritical (iCode *ic)
10292 symbol *tlbl = newiTempLabel (NULL);
10294 D(emitcode("; genCritical",""));
10296 if (IC_RESULT (ic))
10298 aopOp (IC_RESULT (ic), ic, TRUE);
10299 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10300 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10301 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10302 emitcode ("", "%05d$:", (tlbl->key + 100));
10303 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10307 emitcode ("setb", "c");
10308 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10309 emitcode ("clr", "c");
10310 emitcode ("", "%05d$:", (tlbl->key + 100));
10311 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10315 /*-----------------------------------------------------------------*/
10316 /* genEndCritical - generate code for end of a critical sequence */
10317 /*-----------------------------------------------------------------*/
10319 genEndCritical (iCode *ic)
10321 D(emitcode("; genEndCritical",""));
10325 aopOp (IC_RIGHT (ic), ic, FALSE);
10326 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10328 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10329 emitcode ("mov", "ea,c");
10333 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10334 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10335 emitcode ("rrc", "a");
10336 emitcode ("mov", "ea,c");
10338 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10342 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10343 emitcode ("mov", "ea,c");
10347 /*-----------------------------------------------------------------*/
10348 /* gen51Code - generate code for 8051 based controllers */
10349 /*-----------------------------------------------------------------*/
10351 gen51Code (iCode * lic)
10355 /* int cseq = 0; */
10357 _G.currentFunc = NULL;
10358 lineHead = lineCurr = NULL;
10360 /* print the allocation information */
10361 if (allocInfo && currFunc)
10362 printAllocInfo (currFunc, codeOutFile);
10363 /* if debug information required */
10364 if (options.debug && currFunc)
10366 debugFile->writeFunction (currFunc, lic);
10368 /* stack pointer name */
10369 if (options.useXstack)
10375 for (ic = lic; ic; ic = ic->next)
10377 _G.current_iCode = ic;
10379 if (ic->lineno && cln != ic->lineno)
10383 debugFile->writeCLine (ic);
10385 if (!options.noCcodeInAsm) {
10386 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10387 printCLine(ic->filename, ic->lineno));
10392 if (ic->seqPoint && ic->seqPoint != cseq)
10394 emitcode ("", "; sequence point %d", ic->seqPoint);
10395 cseq = ic->seqPoint;
10398 if (options.iCodeInAsm) {
10399 char regsInUse[80];
10402 for (i=0; i<8; i++) {
10403 sprintf (®sInUse[i],
10404 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10407 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10409 /* if the result is marked as
10410 spilt and rematerializable or code for
10411 this has already been generated then
10413 if (resultRemat (ic) || ic->generated)
10416 /* depending on the operation */
10436 /* IPOP happens only when trying to restore a
10437 spilt live range, if there is an ifx statement
10438 following this pop then the if statement might
10439 be using some of the registers being popped which
10440 would destory the contents of the register so
10441 we need to check for this condition and handle it */
10443 ic->next->op == IFX &&
10444 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10445 genIfx (ic->next, ic);
10463 genEndFunction (ic);
10483 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10500 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10504 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10511 /* note these two are xlated by algebraic equivalence
10512 during parsing SDCC.y */
10513 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10514 "got '>=' or '<=' shouldn't have come here");
10518 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10530 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10534 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10538 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10562 genRightShift (ic);
10565 case GET_VALUE_AT_ADDRESS:
10567 hasInc (IC_LEFT (ic), ic,
10568 getSize (operandType (IC_RESULT (ic)))),
10569 ifxForOp (IC_RESULT (ic), ic) );
10573 if (POINTER_SET (ic))
10574 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10600 addSet (&_G.sendSet, ic);
10603 case DUMMY_READ_VOLATILE:
10612 genEndCritical (ic);
10624 _G.current_iCode = NULL;
10626 /* now we are ready to call the
10627 peep hole optimizer */
10628 if (!options.nopeep)
10629 peepHole (&lineHead);
10631 /* now do the actual printing */
10632 printLine (lineHead, codeOutFile);