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;
83 static char *rb1regs[] = {
84 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
96 #define CLRC emitcode("clr","c")
97 #define SETC emitcode("setb","c")
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, const char *fmt,...)
121 char lb[INITIAL_INLINEASM];
129 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
131 SNPRINTF (lb, sizeof(lb), "%s", inst);
132 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
135 tvsprintf (lb, sizeof(lb), fmt, ap);
137 while (isspace (*lbp))
141 lineCurr = (lineCurr ?
142 connectLine (lineCurr, newLineNode (lb)) :
143 (lineHead = newLineNode (lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
146 lineCurr->ic = _G.current_iCode;
147 lineCurr->isComment = (*lbp==';');
151 /*-----------------------------------------------------------------*/
152 /* mcs51_emitDebuggerSymbol - associate the current code location */
153 /* with a debugger symbol */
154 /*-----------------------------------------------------------------*/
156 mcs51_emitDebuggerSymbol (char * debugSym)
159 emitcode ("", "%s ==.", debugSym);
163 /*-----------------------------------------------------------------*/
164 /* mova - moves specified value into accumulator */
165 /*-----------------------------------------------------------------*/
169 /* do some early peephole optimization */
170 if (!strcmp(x, "a") || !strcmp(x, "acc"))
173 emitcode("mov","a,%s", x);
176 /*-----------------------------------------------------------------*/
177 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
178 /*-----------------------------------------------------------------*/
180 getFreePtr (iCode * ic, asmop ** aopp, bool result)
185 /* the logic: if r0 & r1 used in the instruction
186 then we are in trouble otherwise */
188 /* first check if r0 & r1 are used by this
189 instruction, in which case we are in trouble */
190 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
191 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
196 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
197 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
199 /* if no usage of r0 then return it */
202 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
203 (*aopp)->type = AOP_R0;
205 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
208 /* if no usage of r1 then return it */
211 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
212 (*aopp)->type = AOP_R1;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
217 /* now we know they both have usage */
218 /* if r0 not used in this instruction */
221 /* push it if not already pushed */
224 emitcode ("mov", "b,%s",
225 mcs51_regWithIdx (R0_IDX)->dname);
228 else if (!_G.r0Pushed)
230 emitcode ("push", "%s",
231 mcs51_regWithIdx (R0_IDX)->dname);
235 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
236 (*aopp)->type = AOP_R0;
238 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
241 /* if r1 not used then */
245 /* push it if not already pushed */
248 emitcode ("mov", "b,%s",
249 mcs51_regWithIdx (R1_IDX)->dname);
252 else if (!_G.r1Pushed)
254 emitcode ("push", "%s",
255 mcs51_regWithIdx (R1_IDX)->dname);
259 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260 (*aopp)->type = AOP_R1;
261 return mcs51_regWithIdx (R1_IDX);
264 /* I said end of world, but not quite end of world yet */
266 /* we can push it on the stack */
267 (*aopp)->type = AOP_STK;
270 /* in the case that result AND left AND right needs a pointer reg
271 we can safely use the result's */
272 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
273 (*aopp)->type = AOP_R0;
274 return mcs51_regWithIdx (R0_IDX);
276 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
277 (*aopp)->type = AOP_R1;
278 return mcs51_regWithIdx (R1_IDX);
282 /* now this is REALLY the end of the world */
283 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
284 "getFreePtr should never reach here");
289 /*-----------------------------------------------------------------*/
290 /* getTempRegs - initialize an array of pointers to GPR registers */
291 /* that are not in use. Returns 1 if the requested */
292 /* number of registers were available, 0 otherwise. */
293 /*-----------------------------------------------------------------*/
295 getTempRegs(regs **tempRegs, int size, iCode *ic)
302 ic = _G.current_iCode;
308 freeRegs = newBitVect(8);
309 bitVectSetBit (freeRegs, R2_IDX);
310 bitVectSetBit (freeRegs, R3_IDX);
311 bitVectSetBit (freeRegs, R4_IDX);
312 bitVectSetBit (freeRegs, R5_IDX);
313 bitVectSetBit (freeRegs, R6_IDX);
314 bitVectSetBit (freeRegs, R7_IDX);
316 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
318 bitVect * newfreeRegs;
319 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
320 freeBitVect(freeRegs);
321 freeRegs = newfreeRegs;
323 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
326 for (i=0; i<freeRegs->size; i++)
328 if (bitVectBitValue(freeRegs,i))
329 tempRegs[offset++] = mcs51_regWithIdx(i);
332 freeBitVect(freeRegs);
337 freeBitVect(freeRegs);
342 /*-----------------------------------------------------------------*/
343 /* newAsmop - creates a new asmOp */
344 /*-----------------------------------------------------------------*/
346 newAsmop (short type)
350 aop = Safe_calloc (1, sizeof (asmop));
355 /*-----------------------------------------------------------------*/
356 /* pointerCode - returns the code for a pointer type */
357 /*-----------------------------------------------------------------*/
359 pointerCode (sym_link * etype)
362 return PTR_TYPE (SPEC_OCLS (etype));
367 /*-----------------------------------------------------------------*/
368 /* leftRightUseAcc - returns size of accumulator use by operands */
369 /*-----------------------------------------------------------------*/
371 leftRightUseAcc(iCode *ic)
380 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
381 "null iCode pointer");
388 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
391 size = getSize (OP_SYMBOL (op)->type);
396 else if (ic->op == JUMPTABLE)
399 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
402 size = getSize (OP_SYMBOL (op)->type);
410 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
413 size = getSize (OP_SYMBOL (op)->type);
418 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
421 size = getSize (OP_SYMBOL (op)->type);
434 /*-----------------------------------------------------------------*/
435 /* aopForSym - for a true symbol */
436 /*-----------------------------------------------------------------*/
438 aopForSym (iCode * ic, symbol * sym, bool result)
443 wassertl (ic != NULL, "Got a null iCode");
444 wassertl (sym != NULL, "Got a null symbol");
446 space = SPEC_OCLS (sym->etype);
448 /* if already has one */
452 /* assign depending on the storage class */
453 /* if it is on the stack or indirectly addressable */
454 /* space we need to assign either r0 or r1 to it */
455 if (sym->onStack || sym->iaccess)
457 sym->aop = aop = newAsmop (0);
458 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
459 aop->size = getSize (sym->type);
461 /* now assign the address of the variable to
462 the pointer register */
463 if (aop->type != AOP_STK)
468 if (_G.accInUse || leftRightUseAcc (ic))
469 emitcode ("push", "acc");
471 emitcode ("mov", "a,_bp");
472 emitcode ("add", "a,#0x%02x",
474 ((char) (sym->stack - _G.nRegsSaved)) :
475 ((char) sym->stack)) & 0xff);
476 emitcode ("mov", "%s,a",
477 aop->aopu.aop_ptr->name);
479 if (_G.accInUse || leftRightUseAcc (ic))
480 emitcode ("pop", "acc");
483 emitcode ("mov", "%s,#%s",
484 aop->aopu.aop_ptr->name,
486 aop->paged = space->paged;
489 aop->aopu.aop_stk = sym->stack;
493 /* if in bit space */
494 if (IN_BITSPACE (space))
496 sym->aop = aop = newAsmop (AOP_CRY);
497 aop->aopu.aop_dir = sym->rname;
498 aop->size = getSize (sym->type);
501 /* if it is in direct space */
502 if (IN_DIRSPACE (space))
504 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
505 //printTypeChainRaw(sym->type, NULL);
506 //printf("space = %s\n", space ? space->sname : "NULL");
507 sym->aop = aop = newAsmop (AOP_DIR);
508 aop->aopu.aop_dir = sym->rname;
509 aop->size = getSize (sym->type);
513 /* special case for a function */
514 if (IS_FUNC (sym->type))
516 sym->aop = aop = newAsmop (AOP_IMMD);
517 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
518 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
519 aop->size = FPTRSIZE;
523 /* only remaining is far space */
524 /* in which case DPTR gets the address */
525 sym->aop = aop = newAsmop (AOP_DPTR);
526 emitcode ("mov", "dptr,#%s", sym->rname);
527 aop->size = getSize (sym->type);
529 /* if it is in code space */
530 if (IN_CODESPACE (space))
536 /*-----------------------------------------------------------------*/
537 /* aopForRemat - rematerialzes an object */
538 /*-----------------------------------------------------------------*/
540 aopForRemat (symbol * sym)
542 iCode *ic = sym->rematiCode;
543 asmop *aop = newAsmop (AOP_IMMD);
550 val += (int) operandLitValue (IC_RIGHT (ic));
551 else if (ic->op == '-')
552 val -= (int) operandLitValue (IC_RIGHT (ic));
553 else if (IS_CAST_ICODE(ic)) {
554 sym_link *from_type = operandType(IC_RIGHT(ic));
555 aop->aopu.aop_immd.from_cast_remat = 1;
556 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
557 ptr_type = DCL_TYPE(from_type);
558 if (ptr_type == IPOINTER) {
565 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
569 sprintf (buffer, "(%s %c 0x%04x)",
570 OP_SYMBOL (IC_LEFT (ic))->rname,
571 val >= 0 ? '+' : '-',
574 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
576 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
577 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
578 /* set immd2 field if required */
579 if (aop->aopu.aop_immd.from_cast_remat) {
580 sprintf(buffer,"#0x%02x",ptr_type);
581 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
582 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
588 /*-----------------------------------------------------------------*/
589 /* regsInCommon - two operands have some registers in common */
590 /*-----------------------------------------------------------------*/
592 regsInCommon (operand * op1, operand * op2)
597 /* if they have registers in common */
598 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
601 sym1 = OP_SYMBOL (op1);
602 sym2 = OP_SYMBOL (op2);
604 if (sym1->nRegs == 0 || sym2->nRegs == 0)
607 for (i = 0; i < sym1->nRegs; i++)
613 for (j = 0; j < sym2->nRegs; j++)
618 if (sym2->regs[j] == sym1->regs[i])
626 /*-----------------------------------------------------------------*/
627 /* operandsEqu - equivalent */
628 /*-----------------------------------------------------------------*/
630 operandsEqu (operand * op1, operand * op2)
634 /* if they're not symbols */
635 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
638 sym1 = OP_SYMBOL (op1);
639 sym2 = OP_SYMBOL (op2);
641 /* if both are itemps & one is spilt
642 and the other is not then false */
643 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
644 sym1->isspilt != sym2->isspilt)
647 /* if they are the same */
651 /* if they have the same rname */
652 if (sym1->rname[0] && sym2->rname[0]
653 && strcmp (sym1->rname, sym2->rname) == 0)
656 /* if left is a tmp & right is not */
657 if (IS_ITEMP (op1) &&
660 (sym1->usl.spillLoc == sym2))
663 if (IS_ITEMP (op2) &&
667 (sym2->usl.spillLoc == sym1))
673 /*-----------------------------------------------------------------*/
674 /* sameRegs - two asmops have the same registers */
675 /*-----------------------------------------------------------------*/
677 sameRegs (asmop * aop1, asmop * aop2)
684 if (aop1->type != AOP_REG ||
685 aop2->type != AOP_REG)
688 if (aop1->size != aop2->size)
691 for (i = 0; i < aop1->size; i++)
692 if (aop1->aopu.aop_reg[i] !=
693 aop2->aopu.aop_reg[i])
699 /*-----------------------------------------------------------------*/
700 /* aopOp - allocates an asmop for an operand : */
701 /*-----------------------------------------------------------------*/
703 aopOp (operand * op, iCode * ic, bool result)
712 /* if this a literal */
713 if (IS_OP_LITERAL (op))
715 op->aop = aop = newAsmop (AOP_LIT);
716 aop->aopu.aop_lit = op->operand.valOperand;
717 aop->size = getSize (operandType (op));
721 /* if already has a asmop then continue */
725 /* if the underlying symbol has a aop */
726 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
728 op->aop = OP_SYMBOL (op)->aop;
732 /* if this is a true symbol */
733 if (IS_TRUE_SYMOP (op))
735 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
739 /* this is a temporary : this has
745 e) can be a return use only */
747 sym = OP_SYMBOL (op);
749 /* if the type is a conditional */
750 if (sym->regType == REG_CND)
752 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
757 /* if it is spilt then two situations
759 b) has a spill location */
760 if (sym->isspilt || sym->nRegs == 0)
763 /* rematerialize it NOW */
766 sym->aop = op->aop = aop =
768 aop->size = getSize (sym->type);
775 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
776 aop->size = getSize (sym->type);
777 for (i = 0; i < 2; i++)
778 aop->aopu.aop_str[i] = accUse[i];
786 aop = op->aop = sym->aop = newAsmop (AOP_STR);
787 aop->size = getSize (sym->type);
788 for (i = 0; i < fReturnSizeMCS51; i++)
789 aop->aopu.aop_str[i] = fReturn[i];
793 if (sym->usl.spillLoc)
795 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
797 /* force a new aop if sizes differ */
798 sym->usl.spillLoc->aop = NULL;
800 sym->aop = op->aop = aop =
801 aopForSym (ic, sym->usl.spillLoc, result);
802 aop->size = getSize (sym->type);
806 /* else must be a dummy iTemp */
807 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
808 aop->size = getSize (sym->type);
812 /* must be in a register */
813 sym->aop = op->aop = aop = newAsmop (AOP_REG);
814 aop->size = sym->nRegs;
815 for (i = 0; i < sym->nRegs; i++)
816 aop->aopu.aop_reg[i] = sym->regs[i];
819 /*-----------------------------------------------------------------*/
820 /* freeAsmop - free up the asmop given to an operand */
821 /*----------------------------------------------------------------*/
823 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
840 /* depending on the asmop type only three cases need work AOP_RO
841 , AOP_R1 && AOP_STK */
847 emitcode ("mov", "r0,b");
850 else if (_G.r0Pushed)
854 emitcode ("pop", "ar0");
858 bitVectUnSetBit (ic->rUsed, R0_IDX);
864 emitcode ("mov", "r1,b");
871 emitcode ("pop", "ar1");
875 bitVectUnSetBit (ic->rUsed, R1_IDX);
881 int stk = aop->aopu.aop_stk + aop->size - 1;
882 bitVectUnSetBit (ic->rUsed, R0_IDX);
883 bitVectUnSetBit (ic->rUsed, R1_IDX);
885 getFreePtr (ic, &aop, FALSE);
889 emitcode ("mov", "a,_bp");
890 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
891 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
895 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
900 emitcode ("pop", "acc");
901 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
904 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
907 freeAsmop (op, NULL, ic, TRUE);
910 emitcode ("pop", "ar1");
916 emitcode ("pop", "ar0");
923 /* all other cases just dealloc */
929 OP_SYMBOL (op)->aop = NULL;
930 /* if the symbol has a spill */
932 SPIL_LOC (op)->aop = NULL;
937 /*------------------------------------------------------------------*/
938 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
939 /* pop r0 or r1 off stack if pushed */
940 /*------------------------------------------------------------------*/
942 freeForBranchAsmop (operand * op)
962 emitcode ("mov", "r0,b");
964 else if (_G.r0Pushed)
966 emitcode ("pop", "ar0");
973 emitcode ("mov", "r1,b");
975 else if (_G.r1Pushed)
977 emitcode ("pop", "ar1");
984 int stk = aop->aopu.aop_stk + aop->size - 1;
986 emitcode ("mov", "b,r0");
989 emitcode ("mov", "a,_bp");
990 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
991 emitcode ("mov", "r0,a");
995 emitcode ("mov", "r0,_bp");
1000 emitcode ("pop", "acc");
1001 emitcode ("mov", "@r0,a");
1004 emitcode ("dec", "r0");
1006 emitcode ("mov", "r0,b");
1012 /*-----------------------------------------------------------------*/
1013 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1014 /* clobber the accumulator */
1015 /*-----------------------------------------------------------------*/
1017 aopGetUsesAcc (asmop *aop, int offset)
1019 if (offset > (aop->size - 1))
1037 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1046 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1052 /* Error case --- will have been caught already */
1058 /*-----------------------------------------------------------------*/
1059 /* aopGet - for fetching value of the aop */
1060 /*-----------------------------------------------------------------*/
1062 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1067 /* offset is greater than
1069 if (offset > (aop->size - 1) &&
1070 aop->type != AOP_LIT)
1073 /* depending on type */
1081 /* if we need to increment it */
1082 while (offset > aop->coff)
1084 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1088 while (offset < aop->coff)
1090 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1097 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1098 return (dname ? "acc" : "a");
1100 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1101 rs = Safe_calloc (1, strlen (s) + 1);
1106 if (aop->code && aop->coff==0 && offset>=1) {
1107 emitcode ("mov", "a,#0x%02x", offset);
1108 emitcode ("movc", "a,@a+dptr");
1109 return (dname ? "acc" : "a");
1112 while (offset > aop->coff)
1114 emitcode ("inc", "dptr");
1118 while (offset < aop->coff)
1120 emitcode ("lcall", "__decdptr");
1127 emitcode ("clr", "a");
1128 emitcode ("movc", "a,@a+dptr");
1132 emitcode ("movx", "a,@dptr");
1134 return (dname ? "acc" : "a");
1138 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1139 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1141 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1143 sprintf (s, "#(%s >> %d)",
1144 aop->aopu.aop_immd.aop_immd1,
1148 aop->aopu.aop_immd.aop_immd1);
1149 rs = Safe_calloc (1, strlen (s) + 1);
1155 sprintf (s, "(%s + %d)",
1159 sprintf (s, "%s", aop->aopu.aop_dir);
1160 rs = Safe_calloc (1, strlen (s) + 1);
1166 return aop->aopu.aop_reg[offset]->dname;
1168 return aop->aopu.aop_reg[offset]->name;
1171 emitcode ("clr", "a");
1172 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1173 emitcode ("rlc", "a");
1174 return (dname ? "acc" : "a");
1177 if (!offset && dname)
1179 return aop->aopu.aop_str[offset];
1182 return aopLiteral (aop->aopu.aop_lit, offset);
1186 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1190 return aop->aopu.aop_str[offset];
1194 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1195 "aopget got unsupported aop->type");
1198 /*-----------------------------------------------------------------*/
1199 /* aopPut - puts a string for a aop */
1200 /*-----------------------------------------------------------------*/
1202 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1206 if (aop->size && offset > (aop->size - 1))
1208 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1209 "aopPut got offset > aop->size");
1213 /* will assign value to value */
1214 /* depending on where it is ofcourse */
1218 MOVA (s); /* read s in case it was volatile */
1223 sprintf (d, "(%s + %d)",
1224 aop->aopu.aop_dir, offset);
1226 sprintf (d, "%s", aop->aopu.aop_dir);
1228 if (strcmp (d, s) ||
1230 emitcode ("mov", "%s,%s", d, s);
1235 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1236 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1239 strcmp (s, "r0") == 0 ||
1240 strcmp (s, "r1") == 0 ||
1241 strcmp (s, "r2") == 0 ||
1242 strcmp (s, "r3") == 0 ||
1243 strcmp (s, "r4") == 0 ||
1244 strcmp (s, "r5") == 0 ||
1245 strcmp (s, "r6") == 0 ||
1246 strcmp (s, "r7") == 0)
1247 emitcode ("mov", "%s,%s",
1248 aop->aopu.aop_reg[offset]->dname, s);
1250 emitcode ("mov", "%s,%s",
1251 aop->aopu.aop_reg[offset]->name, s);
1258 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1259 "aopPut writing to code space");
1263 while (offset > aop->coff)
1266 emitcode ("inc", "dptr");
1269 while (offset < aop->coff)
1272 emitcode ("lcall", "__decdptr");
1277 /* if not in accumulater */
1280 emitcode ("movx", "@dptr,a");
1285 while (offset > aop->coff)
1288 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1290 while (offset < aop->coff)
1293 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1300 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1306 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1308 else if (strcmp (s, "r0") == 0 ||
1309 strcmp (s, "r1") == 0 ||
1310 strcmp (s, "r2") == 0 ||
1311 strcmp (s, "r3") == 0 ||
1312 strcmp (s, "r4") == 0 ||
1313 strcmp (s, "r5") == 0 ||
1314 strcmp (s, "r6") == 0 ||
1315 strcmp (s, "r7") == 0)
1318 sprintf (buffer, "a%s", s);
1319 emitcode ("mov", "@%s,%s",
1320 aop->aopu.aop_ptr->name, buffer);
1323 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1328 if (strcmp (s, "a") == 0)
1329 emitcode ("push", "acc");
1333 emitcode ("push", "acc");
1335 emitcode ("push", s);
1341 /* if bit variable */
1342 if (!aop->aopu.aop_dir)
1344 emitcode ("clr", "a");
1345 emitcode ("rlc", "a");
1350 emitcode ("clr", "%s", aop->aopu.aop_dir);
1352 emitcode ("setb", "%s", aop->aopu.aop_dir);
1353 else if (!strcmp (s, "c"))
1354 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1357 if (strcmp (s, "a"))
1362 /* set C, if a >= 1 */
1363 emitcode ("add", "a,#0xff");
1364 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1372 if (strcmp (aop->aopu.aop_str[offset], s) ||
1374 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1379 if (!offset && (strcmp (s, "acc") == 0) &&
1383 if (strcmp (aop->aopu.aop_str[offset], s) &&
1385 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1389 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1390 "aopPut got unsupported aop->type");
1398 /*-----------------------------------------------------------------*/
1399 /* pointToEnd :- points to the last byte of the operand */
1400 /*-----------------------------------------------------------------*/
1402 pointToEnd (asmop * aop)
1408 aop->coff = count = (aop->size - 1);
1414 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1418 emitcode ("inc", "dptr");
1425 /*-----------------------------------------------------------------*/
1426 /* reAdjustPreg - points a register back to where it should */
1427 /*-----------------------------------------------------------------*/
1429 reAdjustPreg (asmop * aop)
1431 if ((aop->coff==0) || aop->size <= 1)
1439 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1444 emitcode ("lcall", "__decdptr");
1451 #define AOP(op) op->aop
1452 #define AOP_TYPE(op) AOP(op)->type
1453 #define AOP_SIZE(op) AOP(op)->size
1454 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1455 AOP_TYPE(x) == AOP_R0))
1457 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1458 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1460 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1461 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1462 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1465 /*-----------------------------------------------------------------*/
1466 /* opIsGptr: returns non-zero if the passed operand is */
1467 /* a generic pointer type. */
1468 /*-----------------------------------------------------------------*/
1470 opIsGptr (operand * op)
1472 sym_link *type = operandType (op);
1474 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1481 /*-----------------------------------------------------------------*/
1482 /* getDataSize - get the operand data size */
1483 /*-----------------------------------------------------------------*/
1485 getDataSize (operand * op)
1488 size = AOP_SIZE (op);
1489 if (size == GPTRSIZE)
1491 sym_link *type = operandType (op);
1492 if (IS_GENPTR (type))
1494 /* generic pointer; arithmetic operations
1495 * should ignore the high byte (pointer type).
1503 /*-----------------------------------------------------------------*/
1504 /* outAcc - output Acc */
1505 /*-----------------------------------------------------------------*/
1507 outAcc (operand * result)
1510 size = getDataSize (result);
1513 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1516 /* unsigned or positive */
1519 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1524 /*-----------------------------------------------------------------*/
1525 /* outBitC - output a bit C */
1526 /*-----------------------------------------------------------------*/
1528 outBitC (operand * result)
1530 /* if the result is bit */
1531 if (AOP_TYPE (result) == AOP_CRY)
1532 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1535 emitcode ("clr", "a");
1536 emitcode ("rlc", "a");
1541 /*-----------------------------------------------------------------*/
1542 /* toBoolean - emit code for orl a,operator(sizeop) */
1543 /*-----------------------------------------------------------------*/
1545 toBoolean (operand * oper)
1547 int size = AOP_SIZE (oper) - 1;
1549 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1551 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1555 /*-----------------------------------------------------------------*/
1556 /* genNot - generate code for ! operation */
1557 /*-----------------------------------------------------------------*/
1563 D(emitcode ("; genNot",""));
1565 /* assign asmOps to operand & result */
1566 aopOp (IC_LEFT (ic), ic, FALSE);
1567 aopOp (IC_RESULT (ic), ic, TRUE);
1569 /* if in bit space then a special case */
1570 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1572 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1573 emitcode ("cpl", "c");
1574 outBitC (IC_RESULT (ic));
1578 toBoolean (IC_LEFT (ic));
1580 tlbl = newiTempLabel (NULL);
1581 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1582 emitcode ("", "%05d$:", tlbl->key + 100);
1583 outBitC (IC_RESULT (ic));
1586 /* release the aops */
1587 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1588 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1592 /*-----------------------------------------------------------------*/
1593 /* genCpl - generate code for complement */
1594 /*-----------------------------------------------------------------*/
1602 D(emitcode ("; genCpl",""));
1604 /* assign asmOps to operand & result */
1605 aopOp (IC_LEFT (ic), ic, FALSE);
1606 aopOp (IC_RESULT (ic), ic, TRUE);
1608 /* special case if in bit space */
1609 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1611 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1613 /* promotion rules are responsible for this strange result: */
1614 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1618 tlbl=newiTempLabel(NULL);
1619 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1620 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1621 IS_AOP_PREG (IC_LEFT (ic)))
1623 emitcode ("cjne", "%s,#0x01,%05d$",
1624 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1629 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1631 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1633 emitcode ("", "%05d$:", tlbl->key + 100);
1634 outBitC (IC_RESULT(ic));
1638 size = AOP_SIZE (IC_RESULT (ic));
1641 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1643 emitcode ("cpl", "a");
1644 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1649 /* release the aops */
1650 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1651 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1654 /*-----------------------------------------------------------------*/
1655 /* genUminusFloat - unary minus for floating points */
1656 /*-----------------------------------------------------------------*/
1658 genUminusFloat (operand * op, operand * result)
1660 int size, offset = 0;
1663 D(emitcode ("; genUminusFloat",""));
1665 /* for this we just copy and then flip the bit */
1667 size = AOP_SIZE (op) - 1;
1671 aopPut (AOP (result),
1672 aopGet (AOP (op), offset, FALSE, FALSE),
1674 isOperandVolatile (result, FALSE));
1678 l = aopGet (AOP (op), offset, FALSE, FALSE);
1682 emitcode ("cpl", "acc.7");
1683 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1686 /*-----------------------------------------------------------------*/
1687 /* genUminus - unary minus code generation */
1688 /*-----------------------------------------------------------------*/
1690 genUminus (iCode * ic)
1693 sym_link *optype, *rtype;
1696 D(emitcode ("; genUminus",""));
1699 aopOp (IC_LEFT (ic), ic, FALSE);
1700 aopOp (IC_RESULT (ic), ic, TRUE);
1702 /* if both in bit space then special
1704 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1705 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1708 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1709 emitcode ("cpl", "c");
1710 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1714 optype = operandType (IC_LEFT (ic));
1715 rtype = operandType (IC_RESULT (ic));
1717 /* if float then do float stuff */
1718 if (IS_FLOAT (optype))
1720 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1724 /* otherwise subtract from zero */
1725 size = AOP_SIZE (IC_LEFT (ic));
1730 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1731 if (!strcmp (l, "a"))
1735 emitcode ("cpl", "a");
1736 emitcode ("addc", "a,#0");
1742 emitcode ("clr", "a");
1743 emitcode ("subb", "a,%s", l);
1745 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1748 /* if any remaining bytes in the result */
1749 /* we just need to propagate the sign */
1750 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1752 emitcode ("rlc", "a");
1753 emitcode ("subb", "a,acc");
1755 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1759 /* release the aops */
1760 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1761 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1764 /*-----------------------------------------------------------------*/
1765 /* saveRegisters - will look for a call and save the registers */
1766 /*-----------------------------------------------------------------*/
1768 saveRegisters (iCode * lic)
1775 for (ic = lic; ic; ic = ic->next)
1776 if (ic->op == CALL || ic->op == PCALL)
1781 fprintf (stderr, "found parameter push with no function call\n");
1785 /* if the registers have been saved already or don't need to be then
1789 if (IS_SYMOP(IC_LEFT(ic)) &&
1790 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1791 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1794 /* safe the registers in use at this time but skip the
1795 ones for the result */
1796 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1797 mcs51_rUmaskForOp (IC_RESULT(ic)));
1800 if (options.useXstack)
1802 if (bitVectBitValue (rsave, R0_IDX))
1803 emitcode ("mov", "b,r0");
1804 emitcode ("mov", "r0,%s", spname);
1805 for (i = 0; i < mcs51_nRegs; i++)
1807 if (bitVectBitValue (rsave, i))
1810 emitcode ("mov", "a,b");
1812 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1813 emitcode ("movx", "@r0,a");
1814 emitcode ("inc", "r0");
1817 emitcode ("mov", "%s,r0", spname);
1818 if (bitVectBitValue (rsave, R0_IDX))
1819 emitcode ("mov", "r0,b");
1822 for (i = 0; i < mcs51_nRegs; i++)
1824 if (bitVectBitValue (rsave, i))
1825 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1829 /*-----------------------------------------------------------------*/
1830 /* unsaveRegisters - pop the pushed registers */
1831 /*-----------------------------------------------------------------*/
1833 unsaveRegisters (iCode * ic)
1838 /* restore the registers in use at this time but skip the
1839 ones for the result */
1840 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1841 mcs51_rUmaskForOp (IC_RESULT(ic)));
1843 if (options.useXstack)
1845 emitcode ("mov", "r0,%s", spname);
1846 for (i = mcs51_nRegs; i >= 0; i--)
1848 if (bitVectBitValue (rsave, i))
1850 emitcode ("dec", "r0");
1851 emitcode ("movx", "a,@r0");
1853 emitcode ("mov", "b,a");
1855 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1859 emitcode ("mov", "%s,r0", spname);
1860 if (bitVectBitValue (rsave, R0_IDX))
1861 emitcode ("mov", "r0,b");
1864 for (i = mcs51_nRegs; i >= 0; i--)
1866 if (bitVectBitValue (rsave, i))
1867 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1873 /*-----------------------------------------------------------------*/
1875 /*-----------------------------------------------------------------*/
1877 pushSide (operand * oper, int size)
1882 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1883 if (AOP_TYPE (oper) != AOP_REG &&
1884 AOP_TYPE (oper) != AOP_DIR &&
1888 emitcode ("push", "acc");
1891 emitcode ("push", "%s", l);
1895 /*-----------------------------------------------------------------*/
1896 /* assignResultValue - */
1897 /*-----------------------------------------------------------------*/
1899 assignResultValue (operand * oper)
1902 int size = AOP_SIZE (oper);
1905 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1911 /*-----------------------------------------------------------------*/
1912 /* genXpush - pushes onto the external stack */
1913 /*-----------------------------------------------------------------*/
1915 genXpush (iCode * ic)
1917 asmop *aop = newAsmop (0);
1919 int size, offset = 0;
1921 D(emitcode ("; genXpush",""));
1923 aopOp (IC_LEFT (ic), ic, FALSE);
1924 r = getFreePtr (ic, &aop, FALSE);
1927 emitcode ("mov", "%s,_spx", r->name);
1929 size = AOP_SIZE (IC_LEFT (ic));
1933 char *l = aopGet (AOP (IC_LEFT (ic)),
1934 offset++, FALSE, FALSE);
1936 emitcode ("movx", "@%s,a", r->name);
1937 emitcode ("inc", "%s", r->name);
1942 emitcode ("mov", "_spx,%s", r->name);
1944 freeAsmop (NULL, aop, ic, TRUE);
1945 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1948 /*-----------------------------------------------------------------*/
1949 /* genIpush - genrate code for pushing this gets a little complex */
1950 /*-----------------------------------------------------------------*/
1952 genIpush (iCode * ic)
1954 int size, offset = 0;
1957 D(emitcode ("; genIpush",""));
1959 /* if this is not a parm push : ie. it is spill push
1960 and spill push is always done on the local stack */
1964 /* and the item is spilt then do nothing */
1965 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1968 aopOp (IC_LEFT (ic), ic, FALSE);
1969 size = AOP_SIZE (IC_LEFT (ic));
1970 /* push it on the stack */
1973 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1979 emitcode ("push", "%s", l);
1984 /* this is a paramter push: in this case we call
1985 the routine to find the call and save those
1986 registers that need to be saved */
1989 /* if use external stack then call the external
1990 stack pushing routine */
1991 if (options.useXstack)
1997 /* then do the push */
1998 aopOp (IC_LEFT (ic), ic, FALSE);
2001 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2002 size = AOP_SIZE (IC_LEFT (ic));
2006 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2007 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2008 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2012 emitcode ("push", "acc");
2015 emitcode ("push", "%s", l);
2018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling */
2023 /*-----------------------------------------------------------------*/
2025 genIpop (iCode * ic)
2029 D(emitcode ("; genIpop",""));
2031 /* if the temp was not pushed then */
2032 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2035 aopOp (IC_LEFT (ic), ic, FALSE);
2036 size = AOP_SIZE (IC_LEFT (ic));
2037 offset = (size - 1);
2039 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2042 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* unsaveRBank - restores the resgister bank from stack */
2047 /*-----------------------------------------------------------------*/
2049 unsaveRBank (int bank, iCode * ic, bool popPsw)
2055 if (options.useXstack)
2059 /* Assume r0 is available for use. */
2060 r = mcs51_regWithIdx (R0_IDX);;
2065 r = getFreePtr (ic, &aop, FALSE);
2067 emitcode ("mov", "%s,_spx", r->name);
2072 if (options.useXstack)
2074 emitcode ("movx", "a,@%s", r->name);
2075 emitcode ("mov", "psw,a");
2076 emitcode ("dec", "%s", r->name);
2080 emitcode ("pop", "psw");
2084 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2086 if (options.useXstack)
2088 emitcode ("movx", "a,@%s", r->name);
2089 emitcode ("mov", "(%s+%d),a",
2090 regs8051[i].base, 8 * bank + regs8051[i].offset);
2091 emitcode ("dec", "%s", r->name);
2095 emitcode ("pop", "(%s+%d)",
2096 regs8051[i].base, 8 * bank + regs8051[i].offset);
2099 if (options.useXstack)
2101 emitcode ("mov", "_spx,%s", r->name);
2106 freeAsmop (NULL, aop, ic, TRUE);
2110 /*-----------------------------------------------------------------*/
2111 /* saveRBank - saves an entire register bank on the stack */
2112 /*-----------------------------------------------------------------*/
2114 saveRBank (int bank, iCode * ic, bool pushPsw)
2120 if (options.useXstack)
2124 /* Assume r0 is available for use. */
2125 r = mcs51_regWithIdx (R0_IDX);;
2130 r = getFreePtr (ic, &aop, FALSE);
2132 emitcode ("mov", "%s,_spx", r->name);
2135 for (i = 0; i < mcs51_nRegs; i++)
2137 if (options.useXstack)
2139 emitcode ("inc", "%s", r->name);
2140 emitcode ("mov", "a,(%s+%d)",
2141 regs8051[i].base, 8 * bank + regs8051[i].offset);
2142 emitcode ("movx", "@%s,a", r->name);
2145 emitcode ("push", "(%s+%d)",
2146 regs8051[i].base, 8 * bank + regs8051[i].offset);
2151 if (options.useXstack)
2153 emitcode ("mov", "a,psw");
2154 emitcode ("movx", "@%s,a", r->name);
2155 emitcode ("inc", "%s", r->name);
2156 emitcode ("mov", "_spx,%s", r->name);
2161 emitcode ("push", "psw");
2164 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2169 freeAsmop (NULL, aop, ic, TRUE);
2178 /*-----------------------------------------------------------------*/
2179 /* genSend - gen code for SEND */
2180 /*-----------------------------------------------------------------*/
2181 static void genSend(set *sendSet)
2186 for (sic = setFirstItem (sendSet); sic;
2187 sic = setNextItem (sendSet)) {
2188 int size, offset = 0;
2189 aopOp (IC_LEFT (sic), sic, FALSE);
2190 size = AOP_SIZE (IC_LEFT (sic));
2192 if (sic->argreg == 1) {
2194 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2196 if (strcmp (l, fReturn[offset]))
2197 emitcode ("mov", "%s,%s", fReturn[offset], l);
2203 emitcode ("mov","b1_%d,%s",rb1_count++,
2204 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2207 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2211 /*-----------------------------------------------------------------*/
2212 /* genCall - generates a call statement */
2213 /*-----------------------------------------------------------------*/
2215 genCall (iCode * ic)
2218 // bool restoreBank = FALSE;
2219 bool swapBanks = FALSE;
2221 D(emitcode("; genCall",""));
2223 dtype = operandType (IC_LEFT (ic));
2224 /* if send set is not empty then assign */
2227 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2228 genSend(reverseSet(_G.sendSet));
2230 genSend(_G.sendSet);
2236 /* if we are calling a not _naked function that is not using
2237 the same register bank then we need to save the
2238 destination registers on the stack */
2239 dtype = operandType (IC_LEFT (ic));
2240 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2241 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2242 !IFFUNC_ISISR (dtype))
2247 /* if caller saves & we have not saved then */
2253 emitcode ("mov", "psw,#0x%02x",
2254 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2258 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2259 OP_SYMBOL (IC_LEFT (ic))->rname :
2260 OP_SYMBOL (IC_LEFT (ic))->name));
2264 emitcode ("mov", "psw,#0x%02x",
2265 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2268 /* if we need assign a result value */
2269 if ((IS_ITEMP (IC_RESULT (ic)) &&
2270 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2271 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2272 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2273 IS_TRUE_SYMOP (IC_RESULT (ic)))
2277 aopOp (IC_RESULT (ic), ic, FALSE);
2280 assignResultValue (IC_RESULT (ic));
2282 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2285 /* adjust the stack for parameters if
2290 if (ic->parmBytes > 3)
2292 emitcode ("mov", "a,%s", spname);
2293 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2294 emitcode ("mov", "%s,a", spname);
2297 for (i = 0; i < ic->parmBytes; i++)
2298 emitcode ("dec", "%s", spname);
2301 /* if we hade saved some registers then unsave them */
2302 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2303 unsaveRegisters (ic);
2305 // /* if register bank was saved then pop them */
2307 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2310 /*-----------------------------------------------------------------*/
2311 /* -10l - generates a call by pointer statement */
2312 /*-----------------------------------------------------------------*/
2314 genPcall (iCode * ic)
2317 symbol *rlbl = newiTempLabel (NULL);
2318 // bool restoreBank=FALSE;
2319 bool swapBanks = FALSE;
2321 D(emitcode("; genPCall",""));
2323 /* if caller saves & we have not saved then */
2327 /* if we are calling a not _naked function that is not using
2328 the same register bank then we need to save the
2329 destination registers on the stack */
2330 dtype = operandType (IC_LEFT (ic))->next;
2331 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2332 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2333 !IFFUNC_ISISR (dtype))
2335 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2336 // restoreBank=TRUE;
2338 // need caution message to user here
2341 /* push the return address on to the stack */
2342 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2343 emitcode ("push", "acc");
2344 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2345 emitcode ("push", "acc");
2347 /* now push the calling address */
2348 aopOp (IC_LEFT (ic), ic, FALSE);
2350 pushSide (IC_LEFT (ic), FPTRSIZE);
2352 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2354 /* if send set is not empty the assign */
2357 genSend(reverseSet(_G.sendSet));
2363 emitcode ("mov", "psw,#0x%02x",
2364 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2368 emitcode ("ret", "");
2369 emitcode ("", "%05d$:", (rlbl->key + 100));
2374 emitcode ("mov", "psw,#0x%02x",
2375 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2378 /* if we need assign a result value */
2379 if ((IS_ITEMP (IC_RESULT (ic)) &&
2380 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2381 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2382 IS_TRUE_SYMOP (IC_RESULT (ic)))
2386 aopOp (IC_RESULT (ic), ic, FALSE);
2389 assignResultValue (IC_RESULT (ic));
2391 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2394 /* adjust the stack for parameters if
2399 if (ic->parmBytes > 3)
2401 emitcode ("mov", "a,%s", spname);
2402 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2403 emitcode ("mov", "%s,a", spname);
2406 for (i = 0; i < ic->parmBytes; i++)
2407 emitcode ("dec", "%s", spname);
2411 // /* if register bank was saved then unsave them */
2413 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2415 /* if we hade saved some registers then
2417 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2418 unsaveRegisters (ic);
2421 /*-----------------------------------------------------------------*/
2422 /* resultRemat - result is rematerializable */
2423 /*-----------------------------------------------------------------*/
2425 resultRemat (iCode * ic)
2427 if (SKIP_IC (ic) || ic->op == IFX)
2430 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2432 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2433 if (sym->remat && !POINTER_SET (ic))
2440 #if defined(__BORLANDC__) || defined(_MSC_VER)
2441 #define STRCASECMP stricmp
2443 #define STRCASECMP strcasecmp
2446 /*-----------------------------------------------------------------*/
2447 /* inExcludeList - return 1 if the string is in exclude Reg list */
2448 /*-----------------------------------------------------------------*/
2450 regsCmp(void *p1, void *p2)
2452 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2456 inExcludeList (char *s)
2458 const char *p = setFirstItem(options.excludeRegsSet);
2460 if (p == NULL || STRCASECMP(p, "none") == 0)
2464 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2467 /*-----------------------------------------------------------------*/
2468 /* genFunction - generated code for function entry */
2469 /*-----------------------------------------------------------------*/
2471 genFunction (iCode * ic)
2473 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2475 bool switchedPSW = FALSE;
2476 int calleesaves_saved_register = -1;
2477 int stackAdjust = sym->stack;
2478 int accIsFree = sym->recvSize < 4;
2479 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2482 /* create the function header */
2483 emitcode (";", "-----------------------------------------");
2484 emitcode (";", " function %s", sym->name);
2485 emitcode (";", "-----------------------------------------");
2487 emitcode ("", "%s:", sym->rname);
2488 ftype = operandType (IC_LEFT (ic));
2489 _G.currentFunc = sym;
2491 if (IFFUNC_ISNAKED(ftype))
2493 emitcode(";", "naked function: no prologue.");
2497 /* here we need to generate the equates for the
2498 register bank if required */
2499 if (FUNC_REGBANK (ftype) != rbank)
2503 rbank = FUNC_REGBANK (ftype);
2504 for (i = 0; i < mcs51_nRegs; i++)
2506 if (strcmp (regs8051[i].base, "0") == 0)
2507 emitcode ("", "%s = 0x%02x",
2509 8 * rbank + regs8051[i].offset);
2511 emitcode ("", "%s = %s + 0x%02x",
2514 8 * rbank + regs8051[i].offset);
2518 /* if this is an interrupt service routine then
2519 save acc, b, dpl, dph */
2520 if (IFFUNC_ISISR (sym->type))
2523 if (!inExcludeList ("acc"))
2524 emitcode ("push", "acc");
2525 if (!inExcludeList ("b"))
2526 emitcode ("push", "b");
2527 if (!inExcludeList ("dpl"))
2528 emitcode ("push", "dpl");
2529 if (!inExcludeList ("dph"))
2530 emitcode ("push", "dph");
2531 /* if this isr has no bank i.e. is going to
2532 run with bank 0 , then we need to save more
2534 if (!FUNC_REGBANK (sym->type))
2537 /* if this function does not call any other
2538 function then we can be economical and
2539 save only those registers that are used */
2540 if (!IFFUNC_HASFCALL(sym->type))
2544 /* if any registers used */
2547 /* save the registers used */
2548 for (i = 0; i < sym->regsUsed->size; i++)
2550 if (bitVectBitValue (sym->regsUsed, i))
2551 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2558 /* this function has a function call. We cannot
2559 determines register usage so we will have to push the
2561 saveRBank (0, ic, FALSE);
2562 if (options.parms_in_bank1) {
2564 for (i=0; i < 8 ; i++ ) {
2565 emitcode ("push","%s",rb1regs[i]);
2572 /* This ISR uses a non-zero bank.
2574 * We assume that the bank is available for our
2577 * However, if this ISR calls a function which uses some
2578 * other bank, we must save that bank entirely.
2580 unsigned long banksToSave = 0;
2582 if (IFFUNC_HASFCALL(sym->type))
2585 #define MAX_REGISTER_BANKS 4
2590 for (i = ic; i; i = i->next)
2592 if (i->op == ENDFUNCTION)
2594 /* we got to the end OK. */
2602 dtype = operandType (IC_LEFT(i));
2604 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2606 /* Mark this bank for saving. */
2607 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2609 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2613 banksToSave |= (1 << FUNC_REGBANK(dtype));
2616 /* And note that we don't need to do it in
2624 /* This is a mess; we have no idea what
2625 * register bank the called function might
2628 * The only thing I can think of to do is
2629 * throw a warning and hope.
2631 werror(W_FUNCPTR_IN_USING_ISR);
2635 if (banksToSave && options.useXstack)
2637 /* Since we aren't passing it an ic,
2638 * saveRBank will assume r0 is available to abuse.
2640 * So switch to our (trashable) bank now, so
2641 * the caller's R0 isn't trashed.
2643 emitcode ("push", "psw");
2644 emitcode ("mov", "psw,#0x%02x",
2645 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2649 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2651 if (banksToSave & (1 << ix))
2653 saveRBank(ix, NULL, FALSE);
2657 // TODO: this needs a closer look
2658 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2661 /* Set the register bank to the desired value if nothing else */
2662 /* has done so yet. */
2665 emitcode ("push", "psw");
2666 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2671 /* This is a non-ISR function. The caller has already switched register */
2672 /* banks, if necessary, so just handle the callee-saves option. */
2674 /* if callee-save to be used for this function
2675 then save the registers being used in this function */
2676 if (IFFUNC_CALLEESAVES(sym->type))
2680 /* if any registers used */
2683 /* save the registers used */
2684 for (i = 0; i < sym->regsUsed->size; i++)
2686 if (bitVectBitValue (sym->regsUsed, i))
2688 /* remember one saved register for later usage */
2689 if (calleesaves_saved_register < 0)
2690 calleesaves_saved_register = i;
2691 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2700 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2703 if (options.useXstack)
2706 emitcode ("push", "acc");
2707 emitcode ("mov", "r0,%s", spname);
2708 emitcode ("mov", "a,_bp");
2709 emitcode ("movx", "@r0,a");
2710 emitcode ("inc", "%s", spname);
2712 emitcode ("pop", "acc");
2716 /* set up the stack */
2717 emitcode ("push", "_bp"); /* save the callers stack */
2719 emitcode ("mov", "_bp,%s", spname);
2722 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2723 /* before setting up the stack frame completely. */
2724 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2726 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2730 if (rsym && rsym->regType == REG_CND)
2732 if (rsym && (rsym->accuse || rsym->ruonly))
2734 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2735 rsym = rsym->usl.spillLoc;
2738 /* If the RECEIVE operand immediately spills to the first entry on the */
2739 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2740 /* rather than the usual @r0/r1 machinations. */
2741 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2745 _G.current_iCode = ric;
2746 D(emitcode ("; genReceive",""));
2747 for (ofs=0; ofs < sym->recvSize; ofs++)
2749 if (!strcmp (fReturn[ofs], "a"))
2750 emitcode ("push", "acc");
2752 emitcode ("push", fReturn[ofs]);
2754 stackAdjust -= sym->recvSize;
2757 assert (stackAdjust>=0);
2760 _G.current_iCode = ic;
2764 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2765 /* to free up the accumulator. */
2766 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2770 _G.current_iCode = ric;
2771 D(emitcode ("; genReceive",""));
2772 for (ofs=0; ofs < sym->recvSize; ofs++)
2774 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2776 _G.current_iCode = ic;
2782 /* adjust the stack for the function */
2786 int i = stackAdjust;
2788 werror (W_STACK_OVERFLOW, sym->name);
2790 if (i > 3 && accIsFree)
2793 emitcode ("mov", "a,sp");
2794 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2795 emitcode ("mov", "sp,a");
2800 /* The accumulator is not free, so we will need another register */
2801 /* to clobber. No need to worry about a possible conflict with */
2802 /* the above early RECEIVE optimizations since they would have */
2803 /* freed the accumulator if they were generated. */
2805 if (IFFUNC_CALLEESAVES(sym->type))
2807 /* if it's a callee-saves function we need a saved register */
2808 if (calleesaves_saved_register >= 0)
2810 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2811 emitcode ("mov", "a,sp");
2812 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2813 emitcode ("mov", "sp,a");
2814 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2817 /* do it the hard way */
2819 emitcode ("inc", "sp");
2823 /* not callee-saves, we can clobber r0 */
2824 emitcode ("mov", "r0,a");
2825 emitcode ("mov", "a,sp");
2826 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2827 emitcode ("mov", "sp,a");
2828 emitcode ("mov", "a,r0");
2833 emitcode ("inc", "sp");
2840 emitcode ("push", "acc");
2841 emitcode ("mov", "a,_spx");
2842 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2843 emitcode ("mov", "_spx,a");
2845 emitcode ("pop", "acc");
2848 /* if critical function then turn interrupts off */
2849 if (IFFUNC_ISCRITICAL (ftype))
2851 symbol *tlbl = newiTempLabel (NULL);
2852 emitcode ("setb", "c");
2853 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2854 emitcode ("clr", "c");
2855 emitcode ("", "%05d$:", (tlbl->key + 100));
2856 emitcode ("push", "psw"); /* save old ea via c in psw */
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions */
2862 /*-----------------------------------------------------------------*/
2864 genEndFunction (iCode * ic)
2866 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2867 lineNode *lnp = lineCurr;
2869 bitVect *regsUsedPrologue;
2870 bitVect *regsUnneeded;
2873 _G.currentFunc = NULL;
2874 if (IFFUNC_ISNAKED(sym->type))
2876 emitcode(";", "naked function: no epilogue.");
2877 if (options.debug && currFunc)
2878 debugFile->writeEndFunction (currFunc, ic, 0);
2882 if (IFFUNC_ISCRITICAL (sym->type))
2884 emitcode ("pop", "psw"); /* restore ea via c in psw */
2885 emitcode ("mov", "ea,c");
2888 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2890 emitcode ("mov", "%s,_bp", spname);
2893 /* if use external stack but some variables were
2894 added to the local stack then decrement the
2896 if (options.useXstack && sym->stack)
2898 emitcode ("mov", "a,sp");
2899 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2900 emitcode ("mov", "sp,a");
2904 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2906 if (options.useXstack)
2908 emitcode ("mov", "r0,%s", spname);
2909 emitcode ("movx", "a,@r0");
2910 emitcode ("mov", "_bp,a");
2911 emitcode ("dec", "%s", spname);
2915 emitcode ("pop", "_bp");
2919 /* restore the register bank */
2920 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2922 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2923 || !options.useXstack)
2925 /* Special case of ISR using non-zero bank with useXstack
2928 emitcode ("pop", "psw");
2932 if (IFFUNC_ISISR (sym->type))
2935 /* now we need to restore the registers */
2936 /* if this isr has no bank i.e. is going to
2937 run with bank 0 , then we need to save more
2939 if (!FUNC_REGBANK (sym->type))
2941 /* if this function does not call any other
2942 function then we can be economical and
2943 save only those registers that are used */
2944 if (!IFFUNC_HASFCALL(sym->type))
2948 /* if any registers used */
2951 /* save the registers used */
2952 for (i = sym->regsUsed->size; i >= 0; i--)
2954 if (bitVectBitValue (sym->regsUsed, i))
2955 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2961 if (options.parms_in_bank1) {
2963 for (i = 7 ; i >= 0 ; i-- ) {
2964 emitcode ("pop","%s",rb1regs[i]);
2967 /* this function has a function call cannot
2968 determines register usage so we will have to pop the
2970 unsaveRBank (0, ic, FALSE);
2975 /* This ISR uses a non-zero bank.
2977 * Restore any register banks saved by genFunction
2980 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2983 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2985 if (savedBanks & (1 << ix))
2987 unsaveRBank(ix, NULL, FALSE);
2991 if (options.useXstack)
2993 /* Restore bank AFTER calling unsaveRBank,
2994 * since it can trash r0.
2996 emitcode ("pop", "psw");
3000 if (!inExcludeList ("dph"))
3001 emitcode ("pop", "dph");
3002 if (!inExcludeList ("dpl"))
3003 emitcode ("pop", "dpl");
3004 if (!inExcludeList ("b"))
3005 emitcode ("pop", "b");
3006 if (!inExcludeList ("acc"))
3007 emitcode ("pop", "acc");
3009 /* if debug then send end of function */
3010 if (options.debug && currFunc)
3012 debugFile->writeEndFunction (currFunc, ic, 1);
3015 emitcode ("reti", "");
3019 if (IFFUNC_CALLEESAVES(sym->type))
3023 /* if any registers used */
3026 /* save the registers used */
3027 for (i = sym->regsUsed->size; i >= 0; i--)
3029 if (bitVectBitValue (sym->regsUsed, i) ||
3030 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3031 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3034 else if (mcs51_ptrRegReq)
3036 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3037 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3042 /* if debug then send end of function */
3043 if (options.debug && currFunc)
3045 debugFile->writeEndFunction (currFunc, ic, 1);
3048 emitcode ("ret", "");
3051 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3054 /* If this was an interrupt handler using bank 0 that called another */
3055 /* function, then all registers must be saved; nothing to optimized. */
3056 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3057 && !FUNC_REGBANK(sym->type))
3060 /* There are no push/pops to optimize if not callee-saves or ISR */
3061 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3064 /* If there were stack parameters, we cannot optimize without also */
3065 /* fixing all of the stack offsets; this is too dificult to consider. */
3066 if (FUNC_HASSTACKPARM(sym->type))
3069 /* Compute the registers actually used */
3070 regsUsed = newBitVect (mcs51_nRegs);
3071 regsUsedPrologue = newBitVect (mcs51_nRegs);
3074 if (lnp->ic && lnp->ic->op == FUNCTION)
3075 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3077 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3079 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3080 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3087 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3088 && !bitVectBitValue (regsUsed, CND_IDX))
3090 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3091 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3092 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3093 bitVectUnSetBit (regsUsed, CND_IDX);
3096 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3098 /* If this was an interrupt handler that called another function */
3099 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3100 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3102 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3103 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3104 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3105 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3106 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3109 /* Remove the unneeded push/pops */
3110 regsUnneeded = newBitVect (mcs51_nRegs);
3113 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3115 if (!strncmp(lnp->line, "push", 4))
3117 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3118 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3120 connectLine (lnp->prev, lnp->next);
3121 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3124 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3126 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3127 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3129 connectLine (lnp->prev, lnp->next);
3130 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3137 for (idx = 0; idx < regsUnneeded->size; idx++)
3138 if (bitVectBitValue (regsUnneeded, idx))
3139 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3141 freeBitVect (regsUnneeded);
3142 freeBitVect (regsUsed);
3143 freeBitVect (regsUsedPrologue);
3146 /*-----------------------------------------------------------------*/
3147 /* genRet - generate code for return statement */
3148 /*-----------------------------------------------------------------*/
3152 int size, offset = 0, pushed = 0;
3154 D(emitcode ("; genRet",""));
3156 /* if we have no return value then
3157 just generate the "ret" */
3161 /* we have something to return then
3162 move the return value into place */
3163 aopOp (IC_LEFT (ic), ic, FALSE);
3164 size = AOP_SIZE (IC_LEFT (ic));
3169 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3172 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3174 emitcode ("push", "%s", l);
3179 l = aopGet (AOP (IC_LEFT (ic)), offset,
3181 if (strcmp (fReturn[offset], l))
3182 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3191 if (strcmp (fReturn[pushed], "a"))
3192 emitcode ("pop", fReturn[pushed]);
3194 emitcode ("pop", "acc");
3197 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3200 /* generate a jump to the return label
3201 if the next is not the return statement */
3202 if (!(ic->next && ic->next->op == LABEL &&
3203 IC_LABEL (ic->next) == returnLabel))
3205 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3209 /*-----------------------------------------------------------------*/
3210 /* genLabel - generates a label */
3211 /*-----------------------------------------------------------------*/
3213 genLabel (iCode * ic)
3215 /* special case never generate */
3216 if (IC_LABEL (ic) == entryLabel)
3219 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3222 /*-----------------------------------------------------------------*/
3223 /* genGoto - generates a ljmp */
3224 /*-----------------------------------------------------------------*/
3226 genGoto (iCode * ic)
3228 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3231 /*-----------------------------------------------------------------*/
3232 /* findLabelBackwards: walks back through the iCode chain looking */
3233 /* for the given label. Returns number of iCode instructions */
3234 /* between that label and given ic. */
3235 /* Returns zero if label not found. */
3236 /*-----------------------------------------------------------------*/
3238 findLabelBackwards (iCode * ic, int key)
3247 /* If we have any pushes or pops, we cannot predict the distance.
3248 I don't like this at all, this should be dealt with in the
3250 if (ic->op == IPUSH || ic->op == IPOP) {
3254 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3263 /*-----------------------------------------------------------------*/
3264 /* genPlusIncr :- does addition with increment if possible */
3265 /*-----------------------------------------------------------------*/
3267 genPlusIncr (iCode * ic)
3269 unsigned int icount;
3270 unsigned int size = getDataSize (IC_RESULT (ic));
3272 /* will try to generate an increment */
3273 /* if the right side is not a literal
3275 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3278 /* if the literal value of the right hand side
3279 is greater than 4 then it is not worth it */
3280 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3283 D(emitcode ("; genPlusIncr",""));
3285 /* if increment >=16 bits in register or direct space */
3286 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3287 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3295 /* If the next instruction is a goto and the goto target
3296 * is < 10 instructions previous to this, we can generate
3297 * jumps straight to that target.
3299 if (ic->next && ic->next->op == GOTO
3300 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3301 && labelRange <= 10)
3303 emitcode (";", "tail increment optimized");
3304 tlbl = IC_LABEL (ic->next);
3309 tlbl = newiTempLabel (NULL);
3312 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3313 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3314 IS_AOP_PREG (IC_RESULT (ic)))
3315 emitcode ("cjne", "%s,#0x00,%05d$",
3316 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3320 emitcode ("clr", "a");
3321 emitcode ("cjne", "a,%s,%05d$",
3322 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3326 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3329 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3330 IS_AOP_PREG (IC_RESULT (ic)))
3331 emitcode ("cjne", "%s,#0x00,%05d$",
3332 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3335 emitcode ("cjne", "a,%s,%05d$",
3336 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3339 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3343 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3344 IS_AOP_PREG (IC_RESULT (ic)))
3345 emitcode ("cjne", "%s,#0x00,%05d$",
3346 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3350 emitcode ("cjne", "a,%s,%05d$",
3351 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3354 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3359 emitcode ("", "%05d$:", tlbl->key + 100);
3364 /* if the sizes are greater than 1 then we cannot */
3365 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3366 AOP_SIZE (IC_LEFT (ic)) > 1)
3369 /* we can if the aops of the left & result match or
3370 if they are in registers and the registers are the
3372 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3377 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3378 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3379 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3385 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3394 /*-----------------------------------------------------------------*/
3395 /* outBitAcc - output a bit in acc */
3396 /*-----------------------------------------------------------------*/
3398 outBitAcc (operand * result)
3400 symbol *tlbl = newiTempLabel (NULL);
3401 /* if the result is a bit */
3402 if (AOP_TYPE (result) == AOP_CRY)
3404 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3408 emitcode ("jz", "%05d$", tlbl->key + 100);
3409 emitcode ("mov", "a,%s", one);
3410 emitcode ("", "%05d$:", tlbl->key + 100);
3415 /*-----------------------------------------------------------------*/
3416 /* genPlusBits - generates code for addition of two bits */
3417 /*-----------------------------------------------------------------*/
3419 genPlusBits (iCode * ic)
3421 D(emitcode ("; genPlusBits",""));
3423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3425 symbol *lbl = newiTempLabel (NULL);
3426 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3427 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3428 emitcode ("cpl", "c");
3429 emitcode ("", "%05d$:", (lbl->key + 100));
3430 outBitC (IC_RESULT (ic));
3434 emitcode ("clr", "a");
3435 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3436 emitcode ("rlc", "a");
3437 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3438 emitcode ("addc", "a,#0x00");
3439 outAcc (IC_RESULT (ic));
3444 /* This is the original version of this code.
3446 * This is being kept around for reference,
3447 * because I am not entirely sure I got it right...
3450 adjustArithmeticResult (iCode * ic)
3452 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3453 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3454 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3455 aopPut (AOP (IC_RESULT (ic)),
3456 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3458 isOperandVolatile (IC_RESULT (ic), FALSE));
3460 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3461 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3462 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3463 aopPut (AOP (IC_RESULT (ic)),
3464 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3466 isOperandVolatile (IC_RESULT (ic), FALSE));
3468 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3469 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3470 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3471 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3475 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3476 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3480 /* This is the pure and virtuous version of this code.
3481 * I'm pretty certain it's right, but not enough to toss the old
3485 adjustArithmeticResult (iCode * ic)
3487 if (opIsGptr (IC_RESULT (ic)) &&
3488 opIsGptr (IC_LEFT (ic)) &&
3489 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3491 aopPut (AOP (IC_RESULT (ic)),
3492 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3494 isOperandVolatile (IC_RESULT (ic), FALSE));
3497 if (opIsGptr (IC_RESULT (ic)) &&
3498 opIsGptr (IC_RIGHT (ic)) &&
3499 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3501 aopPut (AOP (IC_RESULT (ic)),
3502 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3504 isOperandVolatile (IC_RESULT (ic), FALSE));
3507 if (opIsGptr (IC_RESULT (ic)) &&
3508 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3509 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3510 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3511 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3514 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3515 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3520 /*-----------------------------------------------------------------*/
3521 /* genPlus - generates code for addition */
3522 /*-----------------------------------------------------------------*/
3524 genPlus (iCode * ic)
3526 int size, offset = 0;
3529 asmop *leftOp, *rightOp;
3532 /* special cases :- */
3534 D(emitcode ("; genPlus",""));
3536 aopOp (IC_LEFT (ic), ic, FALSE);
3537 aopOp (IC_RIGHT (ic), ic, FALSE);
3538 aopOp (IC_RESULT (ic), ic, TRUE);
3540 /* if literal, literal on the right or
3541 if left requires ACC or right is already
3543 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3544 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3545 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3547 operand *t = IC_RIGHT (ic);
3548 IC_RIGHT (ic) = IC_LEFT (ic);
3552 /* if both left & right are in bit
3554 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3555 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3561 /* if left in bit space & right literal */
3562 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3563 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3565 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3566 /* if result in bit space */
3567 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3569 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3570 emitcode ("cpl", "c");
3571 outBitC (IC_RESULT (ic));
3575 size = getDataSize (IC_RESULT (ic));
3578 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3579 emitcode ("addc", "a,#00");
3580 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3586 /* if I can do an increment instead
3587 of add then GOOD for ME */
3588 if (genPlusIncr (ic) == TRUE)
3591 size = getDataSize (IC_RESULT (ic));
3592 leftOp = AOP(IC_LEFT(ic));
3593 rightOp = AOP(IC_RIGHT(ic));
3596 /* if this is an add for an array access
3597 at a 256 byte boundary */
3599 && AOP_TYPE (op) == AOP_IMMD
3601 && IS_SPEC (OP_SYM_ETYPE (op))
3602 && SPEC_ABSA (OP_SYM_ETYPE (op))
3603 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3606 D(emitcode ("; genPlus aligned array",""));
3607 aopPut (AOP (IC_RESULT (ic)),
3608 aopGet (rightOp, 0, FALSE, FALSE),
3610 isOperandVolatile (IC_RESULT (ic), FALSE));
3612 if( 1 == getDataSize (IC_RIGHT (ic)) )
3614 aopPut (AOP (IC_RESULT (ic)),
3615 aopGet (leftOp, 1, FALSE, FALSE),
3617 isOperandVolatile (IC_RESULT (ic), FALSE));
3621 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3622 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3623 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3628 /* if the lower bytes of a literal are zero skip the addition */
3629 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3631 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3632 (skip_bytes+1 < size))
3637 D(emitcode ("; genPlus shortcut",""));
3642 if( offset >= skip_bytes )
3644 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3646 emitcode("mov", "b,a");
3647 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3648 emitcode("xch", "a,b");
3649 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3650 emitcode (add, "a,b");
3652 else if (aopGetUsesAcc (leftOp, offset))
3654 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3655 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3659 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3660 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3662 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3663 add = "addc"; /* further adds must propagate carry */
3667 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3668 isOperandVolatile (IC_RESULT (ic), FALSE))
3671 aopPut (AOP (IC_RESULT (ic)),
3672 aopGet (leftOp, offset, FALSE, FALSE),
3674 isOperandVolatile (IC_RESULT (ic), FALSE));
3680 adjustArithmeticResult (ic);
3683 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3684 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3685 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3688 /*-----------------------------------------------------------------*/
3689 /* genMinusDec :- does subtraction with deccrement if possible */
3690 /*-----------------------------------------------------------------*/
3692 genMinusDec (iCode * ic)
3694 unsigned int icount;
3695 unsigned int size = getDataSize (IC_RESULT (ic));
3697 /* will try to generate an increment */
3698 /* if the right side is not a literal
3700 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3703 /* if the literal value of the right hand side
3704 is greater than 4 then it is not worth it */
3705 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3708 D(emitcode ("; genMinusDec",""));
3710 /* if decrement >=16 bits in register or direct space */
3711 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3712 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3720 /* If the next instruction is a goto and the goto target
3721 * is <= 10 instructions previous to this, we can generate
3722 * jumps straight to that target.
3724 if (ic->next && ic->next->op == GOTO
3725 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3726 && labelRange <= 10)
3728 emitcode (";", "tail decrement optimized");
3729 tlbl = IC_LABEL (ic->next);
3734 tlbl = newiTempLabel (NULL);
3738 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3739 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3740 IS_AOP_PREG (IC_RESULT (ic)))
3741 emitcode ("cjne", "%s,#0xff,%05d$"
3742 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3746 emitcode ("mov", "a,#0xff");
3747 emitcode ("cjne", "a,%s,%05d$"
3748 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3751 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3754 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3755 IS_AOP_PREG (IC_RESULT (ic)))
3756 emitcode ("cjne", "%s,#0xff,%05d$"
3757 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3761 emitcode ("cjne", "a,%s,%05d$"
3762 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3765 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3769 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3770 IS_AOP_PREG (IC_RESULT (ic)))
3771 emitcode ("cjne", "%s,#0xff,%05d$"
3772 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3776 emitcode ("cjne", "a,%s,%05d$"
3777 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3780 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3784 emitcode ("", "%05d$:", tlbl->key + 100);
3789 /* if the sizes are greater than 1 then we cannot */
3790 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3791 AOP_SIZE (IC_LEFT (ic)) > 1)
3794 /* we can if the aops of the left & result match or
3795 if they are in registers and the registers are the
3797 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3801 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3809 /*-----------------------------------------------------------------*/
3810 /* addSign - complete with sign */
3811 /*-----------------------------------------------------------------*/
3813 addSign (operand * result, int offset, int sign)
3815 int size = (getDataSize (result) - offset);
3820 emitcode ("rlc", "a");
3821 emitcode ("subb", "a,acc");
3823 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3827 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3831 /*-----------------------------------------------------------------*/
3832 /* genMinusBits - generates code for subtraction of two bits */
3833 /*-----------------------------------------------------------------*/
3835 genMinusBits (iCode * ic)
3837 symbol *lbl = newiTempLabel (NULL);
3839 D(emitcode ("; genMinusBits",""));
3841 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3843 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3844 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3845 emitcode ("cpl", "c");
3846 emitcode ("", "%05d$:", (lbl->key + 100));
3847 outBitC (IC_RESULT (ic));
3851 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3852 emitcode ("subb", "a,acc");
3853 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3854 emitcode ("inc", "a");
3855 emitcode ("", "%05d$:", (lbl->key + 100));
3856 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3857 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3861 /*-----------------------------------------------------------------*/
3862 /* genMinus - generates code for subtraction */
3863 /*-----------------------------------------------------------------*/
3865 genMinus (iCode * ic)
3867 int size, offset = 0;
3869 D(emitcode ("; genMinus",""));
3871 aopOp (IC_LEFT (ic), ic, FALSE);
3872 aopOp (IC_RIGHT (ic), ic, FALSE);
3873 aopOp (IC_RESULT (ic), ic, TRUE);
3875 /* special cases :- */
3876 /* if both left & right are in bit space */
3877 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3878 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3884 /* if I can do an decrement instead
3885 of subtract then GOOD for ME */
3886 if (genMinusDec (ic) == TRUE)
3889 size = getDataSize (IC_RESULT (ic));
3891 /* if literal, add a,#-lit, else normal subb */
3892 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3894 unsigned long lit = 0L;
3896 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3901 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3902 /* first add without previous c */
3904 if (!size && lit== (unsigned long) -1) {
3905 emitcode ("dec", "a");
3907 emitcode ("add", "a,#0x%02x",
3908 (unsigned int) (lit & 0x0FFL));
3911 emitcode ("addc", "a,#0x%02x",
3912 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3914 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3919 asmop *leftOp, *rightOp;
3921 leftOp = AOP(IC_LEFT(ic));
3922 rightOp = AOP(IC_RIGHT(ic));
3926 if (aopGetUsesAcc(rightOp, offset)) {
3927 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3928 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3930 emitcode( "setb", "c");
3932 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3933 emitcode("cpl", "a");
3935 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3938 emitcode ("subb", "a,%s",
3939 aopGet(rightOp, offset, FALSE, TRUE));
3942 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3947 adjustArithmeticResult (ic);
3950 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3951 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3952 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3956 /*-----------------------------------------------------------------*/
3957 /* genMultbits :- multiplication of bits */
3958 /*-----------------------------------------------------------------*/
3960 genMultbits (operand * left,
3964 D(emitcode ("; genMultbits",""));
3966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3967 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3971 /*-----------------------------------------------------------------*/
3972 /* genMultOneByte : 8*8=8/16 bit multiplication */
3973 /*-----------------------------------------------------------------*/
3975 genMultOneByte (operand * left,
3980 int size = AOP_SIZE (result);
3981 bool runtimeSign, compiletimeSign;
3982 bool lUnsigned, rUnsigned;
3984 D(emitcode ("; genMultOneByte",""));
3986 if (size < 1 || size > 2)
3988 /* this should never happen */
3989 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3990 AOP_SIZE(result), __FILE__, lineno);
3994 /* (if two literals: the value is computed before) */
3995 /* if one literal, literal on the right */
3996 if (AOP_TYPE (left) == AOP_LIT)
4001 /* emitcode (";", "swapped left and right"); */
4003 /* if no literal, unsigned on the right: shorter code */
4004 if ( AOP_TYPE (right) != AOP_LIT
4005 && SPEC_USIGN (getSpec (operandType (left))))
4012 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4013 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4015 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4016 no need to take care about the signedness! */
4017 || (lUnsigned && rUnsigned))
4019 /* just an unsigned 8 * 8 = 8 multiply
4021 /* emitcode (";","unsigned"); */
4022 /* TODO: check for accumulator clash between left & right aops? */
4024 if (AOP_TYPE (right) == AOP_LIT)
4026 /* moving to accumulator first helps peepholes */
4027 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4028 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4032 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4033 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4036 emitcode ("mul", "ab");
4037 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4039 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4043 /* we have to do a signed multiply */
4044 /* emitcode (";", "signed"); */
4046 /* now sign adjust for both left & right */
4048 /* let's see what's needed: */
4049 /* apply negative sign during runtime */
4050 runtimeSign = FALSE;
4051 /* negative sign from literals */
4052 compiletimeSign = FALSE;
4056 if (AOP_TYPE(left) == AOP_LIT)
4058 /* signed literal */
4059 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4061 compiletimeSign = TRUE;
4064 /* signed but not literal */
4070 if (AOP_TYPE(right) == AOP_LIT)
4072 /* signed literal */
4073 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4075 compiletimeSign ^= TRUE;
4078 /* signed but not literal */
4082 /* initialize F0, which stores the runtime sign */
4085 if (compiletimeSign)
4086 emitcode ("setb", "F0"); /* set sign flag */
4088 emitcode ("clr", "F0"); /* reset sign flag */
4091 /* save the signs of the operands */
4092 if (AOP_TYPE(right) == AOP_LIT)
4094 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4096 if (!rUnsigned && val < 0)
4097 emitcode ("mov", "b,#0x%02x", -val);
4099 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4101 else /* ! literal */
4103 if (rUnsigned) /* emitcode (";", "signed"); */
4105 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4108 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4109 lbl = newiTempLabel (NULL);
4110 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4111 emitcode ("cpl", "F0"); /* complement sign flag */
4112 emitcode ("cpl", "a"); /* 2's complement */
4113 emitcode ("inc", "a");
4114 emitcode ("", "%05d$:", (lbl->key + 100));
4115 emitcode ("mov", "b,a");
4119 if (AOP_TYPE(left) == AOP_LIT)
4121 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4123 if (!lUnsigned && val < 0)
4124 emitcode ("mov", "a,#0x%02x", -val);
4126 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4128 else /* ! literal */
4130 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4134 lbl = newiTempLabel (NULL);
4135 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4136 emitcode ("cpl", "F0"); /* complement sign flag */
4137 emitcode ("cpl", "a"); /* 2's complement */
4138 emitcode ("inc", "a");
4139 emitcode ("", "%05d$:", (lbl->key + 100));
4143 /* now the multiplication */
4144 emitcode ("mul", "ab");
4145 if (runtimeSign || compiletimeSign)
4147 lbl = newiTempLabel (NULL);
4149 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4150 emitcode ("cpl", "a"); /* lsb 2's complement */
4152 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4155 emitcode ("add", "a,#1"); /* this sets carry flag */
4156 emitcode ("xch", "a,b");
4157 emitcode ("cpl", "a"); /* msb 2's complement */
4158 emitcode ("addc", "a,#0");
4159 emitcode ("xch", "a,b");
4161 emitcode ("", "%05d$:", (lbl->key + 100));
4163 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4165 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4168 /*-----------------------------------------------------------------*/
4169 /* genMult - generates code for multiplication */
4170 /*-----------------------------------------------------------------*/
4172 genMult (iCode * ic)
4174 operand *left = IC_LEFT (ic);
4175 operand *right = IC_RIGHT (ic);
4176 operand *result = IC_RESULT (ic);
4178 D(emitcode ("; genMult",""));
4180 /* assign the amsops */
4181 aopOp (left, ic, FALSE);
4182 aopOp (right, ic, FALSE);
4183 aopOp (result, ic, TRUE);
4185 /* special cases first */
4187 if (AOP_TYPE (left) == AOP_CRY &&
4188 AOP_TYPE (right) == AOP_CRY)
4190 genMultbits (left, right, result);
4194 /* if both are of size == 1 */
4195 #if 0 // one of them can be a sloc shared with the result
4196 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4198 if (getSize(operandType(left)) == 1 &&
4199 getSize(operandType(right)) == 1)
4202 genMultOneByte (left, right, result);
4206 /* should have been converted to function call */
4207 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4208 getSize(OP_SYMBOL(right)->type));
4212 freeAsmop (result, NULL, ic, TRUE);
4213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4214 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4217 /*-----------------------------------------------------------------*/
4218 /* genDivbits :- division of bits */
4219 /*-----------------------------------------------------------------*/
4221 genDivbits (operand * left,
4228 D(emitcode ("; genDivbits",""));
4230 /* the result must be bit */
4231 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4232 l = aopGet (AOP (left), 0, FALSE, FALSE);
4236 emitcode ("div", "ab");
4237 emitcode ("rrc", "a");
4238 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4241 /*-----------------------------------------------------------------*/
4242 /* genDivOneByte : 8 bit division */
4243 /*-----------------------------------------------------------------*/
4245 genDivOneByte (operand * left,
4249 bool lUnsigned, rUnsigned;
4250 bool runtimeSign, compiletimeSign;
4254 D(emitcode ("; genDivOneByte",""));
4256 /* Why is it necessary that genDivOneByte() can return an int result?
4259 volatile unsigned char uc;
4260 volatile signed char sc1, sc2;
4273 In all cases a one byte result would overflow, the following cast to int
4274 would return the wrong result.
4276 Two possible solution:
4277 a) cast operands to int, if ((unsigned) / (signed)) or
4278 ((signed) / (signed))
4279 b) return an 16 bit signed int; this is what we're doing here!
4282 size = AOP_SIZE (result) - 1;
4284 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4285 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4287 /* signed or unsigned */
4288 if (lUnsigned && rUnsigned)
4290 /* unsigned is easy */
4291 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4292 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4293 emitcode ("div", "ab");
4294 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4296 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4300 /* signed is a little bit more difficult */
4302 /* now sign adjust for both left & right */
4304 /* let's see what's needed: */
4305 /* apply negative sign during runtime */
4306 runtimeSign = FALSE;
4307 /* negative sign from literals */
4308 compiletimeSign = FALSE;
4312 if (AOP_TYPE(left) == AOP_LIT)
4314 /* signed literal */
4315 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4317 compiletimeSign = TRUE;
4320 /* signed but not literal */
4326 if (AOP_TYPE(right) == AOP_LIT)
4328 /* signed literal */
4329 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4331 compiletimeSign ^= TRUE;
4334 /* signed but not literal */
4338 /* initialize F0, which stores the runtime sign */
4341 if (compiletimeSign)
4342 emitcode ("setb", "F0"); /* set sign flag */
4344 emitcode ("clr", "F0"); /* reset sign flag */
4347 /* save the signs of the operands */
4348 if (AOP_TYPE(right) == AOP_LIT)
4350 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4352 if (!rUnsigned && val < 0)
4353 emitcode ("mov", "b,#0x%02x", -val);
4355 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4357 else /* ! literal */
4360 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4363 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4364 lbl = newiTempLabel (NULL);
4365 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4366 emitcode ("cpl", "F0"); /* complement sign flag */
4367 emitcode ("cpl", "a"); /* 2's complement */
4368 emitcode ("inc", "a");
4369 emitcode ("", "%05d$:", (lbl->key + 100));
4370 emitcode ("mov", "b,a");
4374 if (AOP_TYPE(left) == AOP_LIT)
4376 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4378 if (!lUnsigned && val < 0)
4379 emitcode ("mov", "a,#0x%02x", -val);
4381 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4383 else /* ! literal */
4385 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4389 lbl = newiTempLabel (NULL);
4390 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4391 emitcode ("cpl", "F0"); /* complement sign flag */
4392 emitcode ("cpl", "a"); /* 2's complement */
4393 emitcode ("inc", "a");
4394 emitcode ("", "%05d$:", (lbl->key + 100));
4398 /* now the division */
4399 emitcode ("div", "ab");
4401 if (runtimeSign || compiletimeSign)
4403 lbl = newiTempLabel (NULL);
4405 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4406 emitcode ("cpl", "a"); /* lsb 2's complement */
4407 emitcode ("inc", "a");
4408 emitcode ("", "%05d$:", (lbl->key + 100));
4410 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4413 /* msb is 0x00 or 0xff depending on the sign */
4416 emitcode ("mov", "c,F0");
4417 emitcode ("subb", "a,acc");
4419 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4421 else /* compiletimeSign */
4423 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4428 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4430 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4434 /*-----------------------------------------------------------------*/
4435 /* genDiv - generates code for division */
4436 /*-----------------------------------------------------------------*/
4440 operand *left = IC_LEFT (ic);
4441 operand *right = IC_RIGHT (ic);
4442 operand *result = IC_RESULT (ic);
4444 D(emitcode ("; genDiv",""));
4446 /* assign the amsops */
4447 aopOp (left, ic, FALSE);
4448 aopOp (right, ic, FALSE);
4449 aopOp (result, ic, TRUE);
4451 /* special cases first */
4453 if (AOP_TYPE (left) == AOP_CRY &&
4454 AOP_TYPE (right) == AOP_CRY)
4456 genDivbits (left, right, result);
4460 /* if both are of size == 1 */
4461 if (AOP_SIZE (left) == 1 &&
4462 AOP_SIZE (right) == 1)
4464 genDivOneByte (left, right, result);
4468 /* should have been converted to function call */
4471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (result, NULL, ic, TRUE);
4476 /*-----------------------------------------------------------------*/
4477 /* genModbits :- modulus of bits */
4478 /*-----------------------------------------------------------------*/
4480 genModbits (operand * left,
4487 D(emitcode ("; genModbits",""));
4489 /* the result must be bit */
4490 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4491 l = aopGet (AOP (left), 0, FALSE, FALSE);
4495 emitcode ("div", "ab");
4496 emitcode ("mov", "a,b");
4497 emitcode ("rrc", "a");
4498 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4501 /*-----------------------------------------------------------------*/
4502 /* genModOneByte : 8 bit modulus */
4503 /*-----------------------------------------------------------------*/
4505 genModOneByte (operand * left,
4509 bool lUnsigned, rUnsigned;
4510 bool runtimeSign, compiletimeSign;
4514 D(emitcode ("; genModOneByte",""));
4516 size = AOP_SIZE (result) - 1;
4518 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4519 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4521 /* signed or unsigned */
4522 if (lUnsigned && rUnsigned)
4524 /* unsigned is easy */
4525 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4526 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4527 emitcode ("div", "ab");
4528 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4530 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4534 /* signed is a little bit more difficult */
4536 /* now sign adjust for both left & right */
4538 /* modulus: sign of the right operand has no influence on the result! */
4539 if (AOP_TYPE(right) == AOP_LIT)
4541 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4543 if (!rUnsigned && val < 0)
4544 emitcode ("mov", "b,#0x%02x", -val);
4546 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4548 else /* not literal */
4551 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4554 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4555 lbl = newiTempLabel (NULL);
4556 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4557 emitcode ("cpl", "a"); /* 2's complement */
4558 emitcode ("inc", "a");
4559 emitcode ("", "%05d$:", (lbl->key + 100));
4560 emitcode ("mov", "b,a");
4564 /* let's see what's needed: */
4565 /* apply negative sign during runtime */
4566 runtimeSign = FALSE;
4567 /* negative sign from literals */
4568 compiletimeSign = FALSE;
4570 /* sign adjust left side */
4571 if (AOP_TYPE(left) == AOP_LIT)
4573 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4575 if (!lUnsigned && val < 0)
4577 compiletimeSign = TRUE; /* set sign flag */
4578 emitcode ("mov", "a,#0x%02x", -val);
4581 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4583 else /* ! literal */
4585 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4590 emitcode ("clr", "F0"); /* clear sign flag */
4592 lbl = newiTempLabel (NULL);
4593 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4594 emitcode ("setb", "F0"); /* set sign flag */
4595 emitcode ("cpl", "a"); /* 2's complement */
4596 emitcode ("inc", "a");
4597 emitcode ("", "%05d$:", (lbl->key + 100));
4601 /* now the modulus */
4602 emitcode ("div", "ab");
4604 if (runtimeSign || compiletimeSign)
4606 emitcode ("mov", "a,b");
4607 lbl = newiTempLabel (NULL);
4609 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4610 emitcode ("cpl", "a"); /* 2's complement */
4611 emitcode ("inc", "a");
4612 emitcode ("", "%05d$:", (lbl->key + 100));
4614 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4617 /* msb is 0x00 or 0xff depending on the sign */
4620 emitcode ("mov", "c,F0");
4621 emitcode ("subb", "a,acc");
4623 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4625 else /* compiletimeSign */
4627 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4632 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4634 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4638 /*-----------------------------------------------------------------*/
4639 /* genMod - generates code for division */
4640 /*-----------------------------------------------------------------*/
4644 operand *left = IC_LEFT (ic);
4645 operand *right = IC_RIGHT (ic);
4646 operand *result = IC_RESULT (ic);
4648 D(emitcode ("; genMod",""));
4650 /* assign the amsops */
4651 aopOp (left, ic, FALSE);
4652 aopOp (right, ic, FALSE);
4653 aopOp (result, ic, TRUE);
4655 /* special cases first */
4657 if (AOP_TYPE (left) == AOP_CRY &&
4658 AOP_TYPE (right) == AOP_CRY)
4660 genModbits (left, right, result);
4664 /* if both are of size == 1 */
4665 if (AOP_SIZE (left) == 1 &&
4666 AOP_SIZE (right) == 1)
4668 genModOneByte (left, right, result);
4672 /* should have been converted to function call */
4676 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4677 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4678 freeAsmop (result, NULL, ic, TRUE);
4681 /*-----------------------------------------------------------------*/
4682 /* genIfxJump :- will create a jump depending on the ifx */
4683 /*-----------------------------------------------------------------*/
4685 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4688 symbol *tlbl = newiTempLabel (NULL);
4691 D(emitcode ("; genIfxJump",""));
4693 /* if true label then we jump if condition
4697 jlbl = IC_TRUE (ic);
4698 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4699 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4703 /* false label is present */
4704 jlbl = IC_FALSE (ic);
4705 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4706 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4708 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4709 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4711 emitcode (inst, "%05d$", tlbl->key + 100);
4712 freeForBranchAsmop (result);
4713 freeForBranchAsmop (right);
4714 freeForBranchAsmop (left);
4715 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4716 emitcode ("", "%05d$:", tlbl->key + 100);
4718 /* mark the icode as generated */
4722 /*-----------------------------------------------------------------*/
4723 /* genCmp :- greater or less than comparison */
4724 /*-----------------------------------------------------------------*/
4726 genCmp (operand * left, operand * right,
4727 operand * result, iCode * ifx, int sign, iCode *ic)
4729 int size, offset = 0;
4730 unsigned long lit = 0L;
4733 D(emitcode ("; genCmp",""));
4735 /* if left & right are bit variables */
4736 if (AOP_TYPE (left) == AOP_CRY &&
4737 AOP_TYPE (right) == AOP_CRY)
4739 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4740 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4744 /* subtract right from left if at the
4745 end the carry flag is set then we know that
4746 left is greater than right */
4747 size = max (AOP_SIZE (left), AOP_SIZE (right));
4749 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4750 if ((size == 1) && !sign &&
4751 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4753 symbol *lbl = newiTempLabel (NULL);
4754 emitcode ("cjne", "%s,%s,%05d$",
4755 aopGet (AOP (left), offset, FALSE, FALSE),
4756 aopGet (AOP (right), offset, FALSE, FALSE),
4758 emitcode ("", "%05d$:", lbl->key + 100);
4762 if (AOP_TYPE (right) == AOP_LIT)
4764 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4765 /* optimize if(x < 0) or if(x >= 0) */
4774 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4775 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4777 genIfxJump (ifx, "acc.7", left, right, result);
4778 freeAsmop (right, NULL, ic, TRUE);
4779 freeAsmop (left, NULL, ic, TRUE);
4784 emitcode ("rlc", "a");
4792 rightInB = aopGetUsesAcc(AOP (right), offset);
4794 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4795 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4796 if (sign && size == 0)
4798 emitcode ("xrl", "a,#0x80");
4799 if (AOP_TYPE (right) == AOP_LIT)
4801 unsigned long lit = (unsigned long)
4802 floatFromVal (AOP (right)->aopu.aop_lit);
4803 emitcode ("subb", "a,#0x%02x",
4804 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4809 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4810 emitcode ("xrl", "b,#0x80");
4811 emitcode ("subb", "a,b");
4817 emitcode ("subb", "a,b");
4819 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4835 /* if the result is used in the next
4836 ifx conditional branch then generate
4837 code a little differently */
4839 genIfxJump (ifx, "c", NULL, NULL, result);
4842 /* leave the result in acc */
4846 /*-----------------------------------------------------------------*/
4847 /* genCmpGt :- greater than comparison */
4848 /*-----------------------------------------------------------------*/
4850 genCmpGt (iCode * ic, iCode * ifx)
4852 operand *left, *right, *result;
4853 sym_link *letype, *retype;
4856 D(emitcode ("; genCmpGt",""));
4858 left = IC_LEFT (ic);
4859 right = IC_RIGHT (ic);
4860 result = IC_RESULT (ic);
4862 letype = getSpec (operandType (left));
4863 retype = getSpec (operandType (right));
4864 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4865 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4866 /* assign the amsops */
4867 aopOp (left, ic, FALSE);
4868 aopOp (right, ic, FALSE);
4869 aopOp (result, ic, TRUE);
4871 genCmp (right, left, result, ifx, sign,ic);
4873 freeAsmop (result, NULL, ic, TRUE);
4876 /*-----------------------------------------------------------------*/
4877 /* genCmpLt - less than comparisons */
4878 /*-----------------------------------------------------------------*/
4880 genCmpLt (iCode * ic, iCode * ifx)
4882 operand *left, *right, *result;
4883 sym_link *letype, *retype;
4886 D(emitcode ("; genCmpLt",""));
4888 left = IC_LEFT (ic);
4889 right = IC_RIGHT (ic);
4890 result = IC_RESULT (ic);
4892 letype = getSpec (operandType (left));
4893 retype = getSpec (operandType (right));
4894 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4895 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4896 /* assign the amsops */
4897 aopOp (left, ic, FALSE);
4898 aopOp (right, ic, FALSE);
4899 aopOp (result, ic, TRUE);
4901 genCmp (left, right, result, ifx, sign,ic);
4903 freeAsmop (result, NULL, ic, TRUE);
4906 /*-----------------------------------------------------------------*/
4907 /* gencjneshort - compare and jump if not equal */
4908 /*-----------------------------------------------------------------*/
4910 gencjneshort (operand * left, operand * right, symbol * lbl)
4912 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4914 unsigned long lit = 0L;
4916 /* if the left side is a literal or
4917 if the right is in a pointer register and left
4919 if ((AOP_TYPE (left) == AOP_LIT) ||
4920 (AOP_TYPE (left) == AOP_IMMD) ||
4921 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4928 if (AOP_TYPE (right) == AOP_LIT)
4929 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4931 /* if the right side is a literal then anything goes */
4932 if (AOP_TYPE (right) == AOP_LIT &&
4933 AOP_TYPE (left) != AOP_DIR &&
4934 AOP_TYPE (left) != AOP_IMMD)
4938 emitcode ("cjne", "%s,%s,%05d$",
4939 aopGet (AOP (left), offset, FALSE, FALSE),
4940 aopGet (AOP (right), offset, FALSE, FALSE),
4946 /* if the right side is in a register or in direct space or
4947 if the left is a pointer register & right is not */
4948 else if (AOP_TYPE (right) == AOP_REG ||
4949 AOP_TYPE (right) == AOP_DIR ||
4950 AOP_TYPE (right) == AOP_LIT ||
4951 AOP_TYPE (right) == AOP_IMMD ||
4952 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4953 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4957 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4958 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4959 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4960 emitcode ("jnz", "%05d$", lbl->key + 100);
4962 emitcode ("cjne", "a,%s,%05d$",
4963 aopGet (AOP (right), offset, FALSE, TRUE),
4970 /* right is a pointer reg need both a & b */
4973 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4974 if (strcmp (l, "b"))
4975 emitcode ("mov", "b,%s", l);
4976 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4977 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4983 /*-----------------------------------------------------------------*/
4984 /* gencjne - compare and jump if not equal */
4985 /*-----------------------------------------------------------------*/
4987 gencjne (operand * left, operand * right, symbol * lbl)
4989 symbol *tlbl = newiTempLabel (NULL);
4991 gencjneshort (left, right, lbl);
4993 emitcode ("mov", "a,%s", one);
4994 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4995 emitcode ("", "%05d$:", lbl->key + 100);
4996 emitcode ("clr", "a");
4997 emitcode ("", "%05d$:", tlbl->key + 100);
5000 /*-----------------------------------------------------------------*/
5001 /* genCmpEq - generates code for equal to */
5002 /*-----------------------------------------------------------------*/
5004 genCmpEq (iCode * ic, iCode * ifx)
5006 operand *left, *right, *result;
5008 D(emitcode ("; genCmpEq",""));
5010 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5011 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5012 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5014 /* if literal, literal on the right or
5015 if the right is in a pointer register and left
5017 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5018 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5020 operand *t = IC_RIGHT (ic);
5021 IC_RIGHT (ic) = IC_LEFT (ic);
5025 if (ifx && !AOP_SIZE (result))
5028 /* if they are both bit variables */
5029 if (AOP_TYPE (left) == AOP_CRY &&
5030 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5032 if (AOP_TYPE (right) == AOP_LIT)
5034 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5037 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5038 emitcode ("cpl", "c");
5042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5046 emitcode ("clr", "c");
5048 /* AOP_TYPE(right) == AOP_CRY */
5052 symbol *lbl = newiTempLabel (NULL);
5053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5054 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5055 emitcode ("cpl", "c");
5056 emitcode ("", "%05d$:", (lbl->key + 100));
5058 /* if true label then we jump if condition
5060 tlbl = newiTempLabel (NULL);
5063 emitcode ("jnc", "%05d$", tlbl->key + 100);
5064 freeForBranchAsmop (result);
5065 freeForBranchAsmop (right);
5066 freeForBranchAsmop (left);
5067 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5071 emitcode ("jc", "%05d$", tlbl->key + 100);
5072 freeForBranchAsmop (result);
5073 freeForBranchAsmop (right);
5074 freeForBranchAsmop (left);
5075 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5077 emitcode ("", "%05d$:", tlbl->key + 100);
5081 tlbl = newiTempLabel (NULL);
5082 gencjneshort (left, right, tlbl);
5085 freeForBranchAsmop (result);
5086 freeForBranchAsmop (right);
5087 freeForBranchAsmop (left);
5088 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5089 emitcode ("", "%05d$:", tlbl->key + 100);
5093 symbol *lbl = newiTempLabel (NULL);
5094 emitcode ("sjmp", "%05d$", lbl->key + 100);
5095 emitcode ("", "%05d$:", tlbl->key + 100);
5096 freeForBranchAsmop (result);
5097 freeForBranchAsmop (right);
5098 freeForBranchAsmop (left);
5099 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5100 emitcode ("", "%05d$:", lbl->key + 100);
5103 /* mark the icode as generated */
5108 /* if they are both bit variables */
5109 if (AOP_TYPE (left) == AOP_CRY &&
5110 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5112 if (AOP_TYPE (right) == AOP_LIT)
5114 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5117 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5118 emitcode ("cpl", "c");
5122 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5126 emitcode ("clr", "c");
5128 /* AOP_TYPE(right) == AOP_CRY */
5132 symbol *lbl = newiTempLabel (NULL);
5133 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5134 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5135 emitcode ("cpl", "c");
5136 emitcode ("", "%05d$:", (lbl->key + 100));
5139 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5146 genIfxJump (ifx, "c", left, right, result);
5149 /* if the result is used in an arithmetic operation
5150 then put the result in place */
5155 gencjne (left, right, newiTempLabel (NULL));
5156 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5158 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5163 genIfxJump (ifx, "a", left, right, result);
5166 /* if the result is used in an arithmetic operation
5167 then put the result in place */
5168 if (AOP_TYPE (result) != AOP_CRY)
5170 /* leave the result in acc */
5174 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5175 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176 freeAsmop (result, NULL, ic, TRUE);
5179 /*-----------------------------------------------------------------*/
5180 /* ifxForOp - returns the icode containing the ifx for operand */
5181 /*-----------------------------------------------------------------*/
5183 ifxForOp (operand * op, iCode * ic)
5185 /* if true symbol then needs to be assigned */
5186 if (IS_TRUE_SYMOP (op))
5189 /* if this has register type condition and
5190 the next instruction is ifx with the same operand
5191 and live to of the operand is upto the ifx only then */
5193 ic->next->op == IFX &&
5194 IC_COND (ic->next)->key == op->key &&
5195 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5201 /*-----------------------------------------------------------------*/
5202 /* hasInc - operand is incremented before any other use */
5203 /*-----------------------------------------------------------------*/
5205 hasInc (operand *op, iCode *ic,int osize)
5207 sym_link *type = operandType(op);
5208 sym_link *retype = getSpec (type);
5209 iCode *lic = ic->next;
5212 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5213 if (!IS_SYMOP(op)) return NULL;
5215 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5216 if (IS_AGGREGATE(type->next)) return NULL;
5217 if (osize != (isize = getSize(type->next))) return NULL;
5220 /* if operand of the form op = op + <sizeof *op> */
5221 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5222 isOperandEqual(IC_RESULT(lic),op) &&
5223 isOperandLiteral(IC_RIGHT(lic)) &&
5224 operandLitValue(IC_RIGHT(lic)) == isize) {
5227 /* if the operand used or deffed */
5228 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5231 /* if GOTO or IFX */
5232 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5238 /*-----------------------------------------------------------------*/
5239 /* genAndOp - for && operation */
5240 /*-----------------------------------------------------------------*/
5242 genAndOp (iCode * ic)
5244 operand *left, *right, *result;
5247 D(emitcode ("; genAndOp",""));
5249 /* note here that && operations that are in an
5250 if statement are taken away by backPatchLabels
5251 only those used in arthmetic operations remain */
5252 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5253 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5254 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5256 /* if both are bit variables */
5257 if (AOP_TYPE (left) == AOP_CRY &&
5258 AOP_TYPE (right) == AOP_CRY)
5260 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5261 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5266 tlbl = newiTempLabel (NULL);
5268 emitcode ("jz", "%05d$", tlbl->key + 100);
5270 emitcode ("", "%05d$:", tlbl->key + 100);
5274 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5275 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5276 freeAsmop (result, NULL, ic, TRUE);
5280 /*-----------------------------------------------------------------*/
5281 /* genOrOp - for || operation */
5282 /*-----------------------------------------------------------------*/
5284 genOrOp (iCode * ic)
5286 operand *left, *right, *result;
5289 D(emitcode ("; genOrOp",""));
5291 /* note here that || operations that are in an
5292 if statement are taken away by backPatchLabels
5293 only those used in arthmetic operations remain */
5294 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5295 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5296 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5298 /* if both are bit variables */
5299 if (AOP_TYPE (left) == AOP_CRY &&
5300 AOP_TYPE (right) == AOP_CRY)
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5303 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5308 tlbl = newiTempLabel (NULL);
5310 emitcode ("jnz", "%05d$", tlbl->key + 100);
5312 emitcode ("", "%05d$:", tlbl->key + 100);
5316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5317 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318 freeAsmop (result, NULL, ic, TRUE);
5321 /*-----------------------------------------------------------------*/
5322 /* isLiteralBit - test if lit == 2^n */
5323 /*-----------------------------------------------------------------*/
5325 isLiteralBit (unsigned long lit)
5327 unsigned long pw[32] =
5328 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5329 0x100L, 0x200L, 0x400L, 0x800L,
5330 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5331 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5332 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5333 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5334 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5337 for (idx = 0; idx < 32; idx++)
5343 /*-----------------------------------------------------------------*/
5344 /* continueIfTrue - */
5345 /*-----------------------------------------------------------------*/
5347 continueIfTrue (iCode * ic)
5350 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5354 /*-----------------------------------------------------------------*/
5356 /*-----------------------------------------------------------------*/
5358 jumpIfTrue (iCode * ic)
5361 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5365 /*-----------------------------------------------------------------*/
5366 /* jmpTrueOrFalse - */
5367 /*-----------------------------------------------------------------*/
5369 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5371 // ugly but optimized by peephole
5374 symbol *nlbl = newiTempLabel (NULL);
5375 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5376 emitcode ("", "%05d$:", tlbl->key + 100);
5377 freeForBranchAsmop (result);
5378 freeForBranchAsmop (right);
5379 freeForBranchAsmop (left);
5380 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5381 emitcode ("", "%05d$:", nlbl->key + 100);
5385 freeForBranchAsmop (result);
5386 freeForBranchAsmop (right);
5387 freeForBranchAsmop (left);
5388 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5389 emitcode ("", "%05d$:", tlbl->key + 100);
5394 /*-----------------------------------------------------------------*/
5395 /* genAnd - code for and */
5396 /*-----------------------------------------------------------------*/
5398 genAnd (iCode * ic, iCode * ifx)
5400 operand *left, *right, *result;
5401 int size, offset = 0;
5402 unsigned long lit = 0L;
5406 D(emitcode ("; genAnd",""));
5408 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5409 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5410 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5413 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5415 AOP_TYPE (left), AOP_TYPE (right));
5416 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5418 AOP_SIZE (left), AOP_SIZE (right));
5421 /* if left is a literal & right is not then exchange them */
5422 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5423 AOP_NEEDSACC (left))
5425 operand *tmp = right;
5430 /* if result = right then exchange left and right */
5431 if (sameRegs (AOP (result), AOP (right)))
5433 operand *tmp = right;
5438 /* if right is bit then exchange them */
5439 if (AOP_TYPE (right) == AOP_CRY &&
5440 AOP_TYPE (left) != AOP_CRY)
5442 operand *tmp = right;
5446 if (AOP_TYPE (right) == AOP_LIT)
5447 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449 size = AOP_SIZE (result);
5452 // result = bit & yy;
5453 if (AOP_TYPE (left) == AOP_CRY)
5455 // c = bit & literal;
5456 if (AOP_TYPE (right) == AOP_LIT)
5460 if (size && sameRegs (AOP (result), AOP (left)))
5463 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5468 if (size && (AOP_TYPE (result) == AOP_CRY))
5470 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5473 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5478 emitcode ("clr", "c");
5483 if (AOP_TYPE (right) == AOP_CRY)
5486 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5487 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5492 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5494 emitcode ("rrc", "a");
5495 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5503 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5504 genIfxJump (ifx, "c", left, right, result);
5508 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5509 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5510 if ((AOP_TYPE (right) == AOP_LIT) &&
5511 (AOP_TYPE (result) == AOP_CRY) &&
5512 (AOP_TYPE (left) != AOP_CRY))
5514 int posbit = isLiteralBit (lit);
5519 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5522 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5528 SNPRINTF (buffer, sizeof(buffer),
5529 "acc.%d", posbit & 0x07);
5530 genIfxJump (ifx, buffer, left, right, result);
5533 {// what is this case? just found it in ds390/gen.c
5534 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5541 symbol *tlbl = newiTempLabel (NULL);
5542 int sizel = AOP_SIZE (left);
5544 emitcode ("setb", "c");
5547 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5549 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5551 if ((posbit = isLiteralBit (bytelit)) != 0)
5552 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5555 if (bytelit != 0x0FFL)
5556 emitcode ("anl", "a,%s",
5557 aopGet (AOP (right), offset, FALSE, TRUE));
5558 emitcode ("jnz", "%05d$", tlbl->key + 100);
5563 // bit = left & literal
5566 emitcode ("clr", "c");
5567 emitcode ("", "%05d$:", tlbl->key + 100);
5569 // if(left & literal)
5573 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5575 emitcode ("", "%05d$:", tlbl->key + 100);
5583 /* if left is same as result */
5584 if (sameRegs (AOP (result), AOP (left)))
5586 for (; size--; offset++)
5588 if (AOP_TYPE (right) == AOP_LIT)
5590 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5591 if (bytelit == 0x0FF)
5593 /* dummy read of volatile operand */
5594 if (isOperandVolatile (left, FALSE))
5595 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5599 else if (bytelit == 0)
5601 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5603 else if (IS_AOP_PREG (result))
5605 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5606 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5607 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5610 emitcode ("anl", "%s,%s",
5611 aopGet (AOP (left), offset, FALSE, TRUE),
5612 aopGet (AOP (right), offset, FALSE, FALSE));
5616 if (AOP_TYPE (left) == AOP_ACC)
5617 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5620 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5621 if (IS_AOP_PREG (result))
5623 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5624 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5627 emitcode ("anl", "%s,a",
5628 aopGet (AOP (left), offset, FALSE, TRUE));
5635 // left & result in different registers
5636 if (AOP_TYPE (result) == AOP_CRY)
5639 // if(size), result in bit
5640 // if(!size && ifx), conditional oper: if(left & right)
5641 symbol *tlbl = newiTempLabel (NULL);
5642 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5644 emitcode ("setb", "c");
5647 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5648 emitcode ("anl", "a,%s",
5649 aopGet (AOP (right), offset, FALSE, FALSE));
5651 if (AOP_TYPE(left)==AOP_ACC) {
5652 emitcode("mov", "b,a");
5653 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5654 emitcode("anl", "a,b");
5656 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5657 emitcode ("anl", "a,%s",
5658 aopGet (AOP (left), offset, FALSE, FALSE));
5661 emitcode ("jnz", "%05d$", tlbl->key + 100);
5667 emitcode ("", "%05d$:", tlbl->key + 100);
5671 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5673 emitcode ("", "%05d$:", tlbl->key + 100);
5677 for (; (size--); offset++)
5680 // result = left & right
5681 if (AOP_TYPE (right) == AOP_LIT)
5683 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5684 if (bytelit == 0x0FF)
5686 aopPut (AOP (result),
5687 aopGet (AOP (left), offset, FALSE, FALSE),
5689 isOperandVolatile (result, FALSE));
5692 else if (bytelit == 0)
5694 /* dummy read of volatile operand */
5695 if (isOperandVolatile (left, FALSE))
5696 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5697 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5701 // faster than result <- left, anl result,right
5702 // and better if result is SFR
5703 if (AOP_TYPE (left) == AOP_ACC)
5704 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5707 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5708 emitcode ("anl", "a,%s",
5709 aopGet (AOP (left), offset, FALSE, FALSE));
5711 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5717 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5718 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5719 freeAsmop (result, NULL, ic, TRUE);
5722 /*-----------------------------------------------------------------*/
5723 /* genOr - code for or */
5724 /*-----------------------------------------------------------------*/
5726 genOr (iCode * ic, iCode * ifx)
5728 operand *left, *right, *result;
5729 int size, offset = 0;
5730 unsigned long lit = 0L;
5733 D(emitcode ("; genOr",""));
5735 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5736 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5737 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5740 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5742 AOP_TYPE (left), AOP_TYPE (right));
5743 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5745 AOP_SIZE (left), AOP_SIZE (right));
5748 /* if left is a literal & right is not then exchange them */
5749 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5750 AOP_NEEDSACC (left))
5752 operand *tmp = right;
5757 /* if result = right then exchange them */
5758 if (sameRegs (AOP (result), AOP (right)))
5760 operand *tmp = right;
5765 /* if right is bit then exchange them */
5766 if (AOP_TYPE (right) == AOP_CRY &&
5767 AOP_TYPE (left) != AOP_CRY)
5769 operand *tmp = right;
5773 if (AOP_TYPE (right) == AOP_LIT)
5774 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776 size = AOP_SIZE (result);
5780 if (AOP_TYPE (left) == AOP_CRY)
5782 if (AOP_TYPE (right) == AOP_LIT)
5784 // c = bit | literal;
5787 // lit != 0 => result = 1
5788 if (AOP_TYPE (result) == AOP_CRY)
5791 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5793 continueIfTrue (ifx);
5796 emitcode ("setb", "c");
5800 // lit == 0 => result = left
5801 if (size && sameRegs (AOP (result), AOP (left)))
5803 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5808 if (AOP_TYPE (right) == AOP_CRY)
5811 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5812 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5817 symbol *tlbl = newiTempLabel (NULL);
5818 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5819 emitcode ("setb", "c");
5820 emitcode ("jb", "%s,%05d$",
5821 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5823 emitcode ("jnz", "%05d$", tlbl->key + 100);
5824 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5826 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5832 emitcode ("", "%05d$:", tlbl->key + 100);
5841 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5842 genIfxJump (ifx, "c", left, right, result);
5846 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5847 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5848 if ((AOP_TYPE (right) == AOP_LIT) &&
5849 (AOP_TYPE (result) == AOP_CRY) &&
5850 (AOP_TYPE (left) != AOP_CRY))
5856 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5858 continueIfTrue (ifx);
5863 // lit = 0, result = boolean(left)
5865 emitcode ("setb", "c");
5869 symbol *tlbl = newiTempLabel (NULL);
5870 emitcode ("jnz", "%05d$", tlbl->key + 100);
5872 emitcode ("", "%05d$:", tlbl->key + 100);
5876 genIfxJump (ifx, "a", left, right, result);
5884 /* if left is same as result */
5885 if (sameRegs (AOP (result), AOP (left)))
5887 for (; size--; offset++)
5889 if (AOP_TYPE (right) == AOP_LIT)
5891 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5894 /* dummy read of volatile operand */
5895 if (isOperandVolatile (left, FALSE))
5896 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5900 else if (bytelit == 0x0FF)
5902 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
5904 else if (IS_AOP_PREG (left))
5906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5907 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5908 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5912 emitcode ("orl", "%s,%s",
5913 aopGet (AOP (left), offset, FALSE, TRUE),
5914 aopGet (AOP (right), offset, FALSE, FALSE));
5919 if (AOP_TYPE (left) == AOP_ACC)
5920 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5923 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5924 if (IS_AOP_PREG (left))
5926 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5927 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5931 emitcode ("orl", "%s,a",
5932 aopGet (AOP (left), offset, FALSE, TRUE));
5940 // left & result in different registers
5941 if (AOP_TYPE (result) == AOP_CRY)
5944 // if(size), result in bit
5945 // if(!size && ifx), conditional oper: if(left | right)
5946 symbol *tlbl = newiTempLabel (NULL);
5947 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5949 emitcode ("setb", "c");
5952 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5953 emitcode ("orl", "a,%s",
5954 aopGet (AOP (right), offset, FALSE, FALSE));
5956 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5957 emitcode ("orl", "a,%s",
5958 aopGet (AOP (left), offset, FALSE, FALSE));
5960 emitcode ("jnz", "%05d$", tlbl->key + 100);
5966 emitcode ("", "%05d$:", tlbl->key + 100);
5970 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5972 emitcode ("", "%05d$:", tlbl->key + 100);
5976 for (; (size--); offset++)
5979 // result = left | right
5980 if (AOP_TYPE (right) == AOP_LIT)
5982 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5985 aopPut (AOP (result),
5986 aopGet (AOP (left), offset, FALSE, FALSE),
5988 isOperandVolatile (result, FALSE));
5991 else if (bytelit == 0x0FF)
5993 /* dummy read of volatile operand */
5994 if (isOperandVolatile (left, FALSE))
5995 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5996 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6000 // faster than result <- left, anl result,right
6001 // and better if result is SFR
6002 if (AOP_TYPE (left) == AOP_ACC)
6003 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6006 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6007 emitcode ("orl", "a,%s",
6008 aopGet (AOP (left), offset, FALSE, FALSE));
6010 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6016 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018 freeAsmop (result, NULL, ic, TRUE);
6021 /*-----------------------------------------------------------------*/
6022 /* genXor - code for xclusive or */
6023 /*-----------------------------------------------------------------*/
6025 genXor (iCode * ic, iCode * ifx)
6027 operand *left, *right, *result;
6028 int size, offset = 0;
6029 unsigned long lit = 0L;
6032 D(emitcode ("; genXor",""));
6034 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6035 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6036 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6039 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6041 AOP_TYPE (left), AOP_TYPE (right));
6042 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6044 AOP_SIZE (left), AOP_SIZE (right));
6047 /* if left is a literal & right is not ||
6048 if left needs acc & right does not */
6049 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6050 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6052 operand *tmp = right;
6057 /* if result = right then exchange them */
6058 if (sameRegs (AOP (result), AOP (right)))
6060 operand *tmp = right;
6065 /* if right is bit then exchange them */
6066 if (AOP_TYPE (right) == AOP_CRY &&
6067 AOP_TYPE (left) != AOP_CRY)
6069 operand *tmp = right;
6073 if (AOP_TYPE (right) == AOP_LIT)
6074 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6076 size = AOP_SIZE (result);
6080 if (AOP_TYPE (left) == AOP_CRY)
6082 if (AOP_TYPE (right) == AOP_LIT)
6084 // c = bit & literal;
6087 // lit>>1 != 0 => result = 1
6088 if (AOP_TYPE (result) == AOP_CRY)
6091 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6093 continueIfTrue (ifx);
6096 emitcode ("setb", "c");
6103 // lit == 0, result = left
6104 if (size && sameRegs (AOP (result), AOP (left)))
6106 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6110 // lit == 1, result = not(left)
6111 if (size && sameRegs (AOP (result), AOP (left)))
6113 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6119 emitcode ("cpl", "c");
6128 symbol *tlbl = newiTempLabel (NULL);
6129 if (AOP_TYPE (right) == AOP_CRY)
6132 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6136 int sizer = AOP_SIZE (right);
6138 // if val>>1 != 0, result = 1
6139 emitcode ("setb", "c");
6142 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6144 // test the msb of the lsb
6145 emitcode ("anl", "a,#0xfe");
6146 emitcode ("jnz", "%05d$", tlbl->key + 100);
6150 emitcode ("rrc", "a");
6152 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6153 emitcode ("cpl", "c");
6154 emitcode ("", "%05d$:", (tlbl->key + 100));
6161 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6162 genIfxJump (ifx, "c", left, right, result);
6166 /* if left is same as result */
6167 if (sameRegs (AOP (result), AOP (left)))
6169 for (; size--; offset++)
6171 if (AOP_TYPE (right) == AOP_LIT)
6173 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6176 /* dummy read of volatile operand */
6177 if (isOperandVolatile (left, FALSE))
6178 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6182 else if (IS_AOP_PREG (left))
6184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6185 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6186 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6190 emitcode ("xrl", "%s,%s",
6191 aopGet (AOP (left), offset, FALSE, TRUE),
6192 aopGet (AOP (right), offset, FALSE, FALSE));
6197 if (AOP_TYPE (left) == AOP_ACC)
6198 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6201 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6202 if (IS_AOP_PREG (left))
6204 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6205 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6208 emitcode ("xrl", "%s,a",
6209 aopGet (AOP (left), offset, FALSE, TRUE));
6216 // left & result in different registers
6217 if (AOP_TYPE (result) == AOP_CRY)
6220 // if(size), result in bit
6221 // if(!size && ifx), conditional oper: if(left ^ right)
6222 symbol *tlbl = newiTempLabel (NULL);
6223 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6225 emitcode ("setb", "c");
6228 if ((AOP_TYPE (right) == AOP_LIT) &&
6229 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6231 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6235 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6236 emitcode ("xrl", "a,%s",
6237 aopGet (AOP (right), offset, FALSE, FALSE));
6239 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6240 emitcode ("xrl", "a,%s",
6241 aopGet (AOP (left), offset, FALSE, FALSE));
6244 emitcode ("jnz", "%05d$", tlbl->key + 100);
6250 emitcode ("", "%05d$:", tlbl->key + 100);
6254 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6258 for (; (size--); offset++)
6261 // result = left & right
6262 if (AOP_TYPE (right) == AOP_LIT)
6264 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6267 aopPut (AOP (result),
6268 aopGet (AOP (left), offset, FALSE, FALSE),
6270 isOperandVolatile (result, FALSE));
6274 // faster than result <- left, anl result,right
6275 // and better if result is SFR
6276 if (AOP_TYPE (left) == AOP_ACC)
6277 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6280 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6281 emitcode ("xrl", "a,%s",
6282 aopGet (AOP (left), offset, FALSE, TRUE));
6284 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6290 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6292 freeAsmop (result, NULL, ic, TRUE);
6295 /*-----------------------------------------------------------------*/
6296 /* genInline - write the inline code out */
6297 /*-----------------------------------------------------------------*/
6299 genInline (iCode * ic)
6301 char *buffer, *bp, *bp1;
6303 D(emitcode ("; genInline",""));
6305 _G.inLine += (!options.asmpeep);
6307 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6308 strcpy (buffer, IC_INLINE (ic));
6310 /* emit each line as a code */
6321 /* Add \n for labels, not dirs such as c:\mydir */
6322 if ( (*bp == ':') && (isspace(bp[1])) )
6336 /* emitcode("",buffer); */
6337 _G.inLine -= (!options.asmpeep);
6340 /*-----------------------------------------------------------------*/
6341 /* genRRC - rotate right with carry */
6342 /*-----------------------------------------------------------------*/
6346 operand *left, *result;
6347 int size, offset = 0;
6350 D(emitcode ("; genRRC",""));
6352 /* rotate right with carry */
6353 left = IC_LEFT (ic);
6354 result = IC_RESULT (ic);
6355 aopOp (left, ic, FALSE);
6356 aopOp (result, ic, FALSE);
6358 /* move it to the result */
6359 size = AOP_SIZE (result);
6361 if (size == 1) { /* special case for 1 byte */
6362 l = aopGet (AOP (left), offset, FALSE, FALSE);
6364 emitcode ("rr", "a");
6370 l = aopGet (AOP (left), offset, FALSE, FALSE);
6372 emitcode ("rrc", "a");
6373 if (AOP_SIZE (result) > 1)
6374 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6376 /* now we need to put the carry into the
6377 highest order byte of the result */
6378 if (AOP_SIZE (result) > 1)
6380 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6383 emitcode ("mov", "acc.7,c");
6385 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6386 freeAsmop (left, NULL, ic, TRUE);
6387 freeAsmop (result, NULL, ic, TRUE);
6390 /*-----------------------------------------------------------------*/
6391 /* genRLC - generate code for rotate left with carry */
6392 /*-----------------------------------------------------------------*/
6396 operand *left, *result;
6397 int size, offset = 0;
6400 D(emitcode ("; genRLC",""));
6402 /* rotate right with carry */
6403 left = IC_LEFT (ic);
6404 result = IC_RESULT (ic);
6405 aopOp (left, ic, FALSE);
6406 aopOp (result, ic, FALSE);
6408 /* move it to the result */
6409 size = AOP_SIZE (result);
6413 l = aopGet (AOP (left), offset, FALSE, FALSE);
6415 if (size == 0) { /* special case for 1 byte */
6419 emitcode ("add", "a,acc");
6420 if (AOP_SIZE (result) > 1)
6421 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6424 l = aopGet (AOP (left), offset, FALSE, FALSE);
6426 emitcode ("rlc", "a");
6427 if (AOP_SIZE (result) > 1)
6428 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6431 /* now we need to put the carry into the
6432 highest order byte of the result */
6433 if (AOP_SIZE (result) > 1)
6435 l = aopGet (AOP (result), 0, FALSE, FALSE);
6438 emitcode ("mov", "acc.0,c");
6440 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6441 freeAsmop (left, NULL, ic, TRUE);
6442 freeAsmop (result, NULL, ic, TRUE);
6445 /*-----------------------------------------------------------------*/
6446 /* genGetHbit - generates code get highest order bit */
6447 /*-----------------------------------------------------------------*/
6449 genGetHbit (iCode * ic)
6451 operand *left, *result;
6453 D(emitcode ("; genGetHbit",""));
6455 left = IC_LEFT (ic);
6456 result = IC_RESULT (ic);
6457 aopOp (left, ic, FALSE);
6458 aopOp (result, ic, FALSE);
6460 /* get the highest order byte into a */
6461 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6462 if (AOP_TYPE (result) == AOP_CRY)
6464 emitcode ("rlc", "a");
6469 emitcode ("rl", "a");
6470 emitcode ("anl", "a,#0x01");
6475 freeAsmop (left, NULL, ic, TRUE);
6476 freeAsmop (result, NULL, ic, TRUE);
6479 /*-----------------------------------------------------------------*/
6480 /* genSwap - generates code to swap nibbles or bytes */
6481 /*-----------------------------------------------------------------*/
6483 genSwap (iCode * ic)
6485 operand *left, *result;
6487 D(emitcode ("; genSwap",""));
6489 left = IC_LEFT (ic);
6490 result = IC_RESULT (ic);
6491 aopOp (left, ic, FALSE);
6492 aopOp (result, ic, FALSE);
6494 switch (AOP_SIZE (left))
6496 case 1: /* swap nibbles in byte */
6497 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6498 emitcode ("swap", "a");
6499 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6501 case 2: /* swap bytes in word */
6502 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6504 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6505 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6506 0, isOperandVolatile (result, FALSE));
6507 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6509 else if (operandsEqu (left, result))
6512 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6513 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6515 emitcode ("mov", "b,a");
6518 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6519 0, isOperandVolatile (result, FALSE));
6520 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6524 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6525 0, isOperandVolatile (result, FALSE));
6526 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6527 1, isOperandVolatile (result, FALSE));
6531 wassertl(FALSE, "unsupported SWAP operand size");
6534 freeAsmop (left, NULL, ic, TRUE);
6535 freeAsmop (result, NULL, ic, TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* AccRol - rotate left accumulator by known count */
6541 /*-----------------------------------------------------------------*/
6543 AccRol (int shCount)
6545 shCount &= 0x0007; // shCount : 0..7
6552 emitcode ("rl", "a");
6555 emitcode ("rl", "a");
6556 emitcode ("rl", "a");
6559 emitcode ("swap", "a");
6560 emitcode ("rr", "a");
6563 emitcode ("swap", "a");
6566 emitcode ("swap", "a");
6567 emitcode ("rl", "a");
6570 emitcode ("rr", "a");
6571 emitcode ("rr", "a");
6574 emitcode ("rr", "a");
6579 /*-----------------------------------------------------------------*/
6580 /* AccLsh - left shift accumulator by known count */
6581 /*-----------------------------------------------------------------*/
6583 AccLsh (int shCount)
6588 emitcode ("add", "a,acc");
6589 else if (shCount == 2)
6591 emitcode ("add", "a,acc");
6592 emitcode ("add", "a,acc");
6596 /* rotate left accumulator */
6598 /* and kill the lower order bits */
6599 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6604 /*-----------------------------------------------------------------*/
6605 /* AccRsh - right shift accumulator by known count */
6606 /*-----------------------------------------------------------------*/
6608 AccRsh (int shCount)
6615 emitcode ("rrc", "a");
6619 /* rotate right accumulator */
6620 AccRol (8 - shCount);
6621 /* and kill the higher order bits */
6622 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6627 /*-----------------------------------------------------------------*/
6628 /* AccSRsh - signed right shift accumulator by known count */
6629 /*-----------------------------------------------------------------*/
6631 AccSRsh (int shCount)
6638 emitcode ("mov", "c,acc.7");
6639 emitcode ("rrc", "a");
6641 else if (shCount == 2)
6643 emitcode ("mov", "c,acc.7");
6644 emitcode ("rrc", "a");
6645 emitcode ("mov", "c,acc.7");
6646 emitcode ("rrc", "a");
6650 tlbl = newiTempLabel (NULL);
6651 /* rotate right accumulator */
6652 AccRol (8 - shCount);
6653 /* and kill the higher order bits */
6654 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6655 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6656 emitcode ("orl", "a,#0x%02x",
6657 (unsigned char) ~SRMask[shCount]);
6658 emitcode ("", "%05d$:", tlbl->key + 100);
6663 /*-----------------------------------------------------------------*/
6664 /* shiftR1Left2Result - shift right one byte from left to result */
6665 /*-----------------------------------------------------------------*/
6667 shiftR1Left2Result (operand * left, int offl,
6668 operand * result, int offr,
6669 int shCount, int sign)
6671 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6672 /* shift right accumulator */
6677 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6680 /*-----------------------------------------------------------------*/
6681 /* shiftL1Left2Result - shift left one byte from left to result */
6682 /*-----------------------------------------------------------------*/
6684 shiftL1Left2Result (operand * left, int offl,
6685 operand * result, int offr, int shCount)
6688 l = aopGet (AOP (left), offl, FALSE, FALSE);
6690 /* shift left accumulator */
6692 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6695 /*-----------------------------------------------------------------*/
6696 /* movLeft2Result - move byte from left to result */
6697 /*-----------------------------------------------------------------*/
6699 movLeft2Result (operand * left, int offl,
6700 operand * result, int offr, int sign)
6703 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6705 l = aopGet (AOP (left), offl, FALSE, FALSE);
6707 if (*l == '@' && (IS_AOP_PREG (result)))
6709 emitcode ("mov", "a,%s", l);
6710 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6715 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6718 /* MSB sign in acc.7 ! */
6719 if (getDataSize (left) == offl + 1)
6721 emitcode ("mov", "a,%s", l);
6722 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6729 /*-----------------------------------------------------------------*/
6730 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6731 /*-----------------------------------------------------------------*/
6735 emitcode ("rrc", "a");
6736 emitcode ("xch", "a,%s", x);
6737 emitcode ("rrc", "a");
6738 emitcode ("xch", "a,%s", x);
6741 /*-----------------------------------------------------------------*/
6742 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6743 /*-----------------------------------------------------------------*/
6747 emitcode ("xch", "a,%s", x);
6748 emitcode ("rlc", "a");
6749 emitcode ("xch", "a,%s", x);
6750 emitcode ("rlc", "a");
6753 /*-----------------------------------------------------------------*/
6754 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6755 /*-----------------------------------------------------------------*/
6759 emitcode ("xch", "a,%s", x);
6760 emitcode ("add", "a,acc");
6761 emitcode ("xch", "a,%s", x);
6762 emitcode ("rlc", "a");
6765 /*-----------------------------------------------------------------*/
6766 /* AccAXLsh - left shift a:x by known count (0..7) */
6767 /*-----------------------------------------------------------------*/
6769 AccAXLsh (char *x, int shCount)
6784 case 5: // AAAAABBB:CCCCCDDD
6786 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6788 emitcode ("anl", "a,#0x%02x",
6789 SLMask[shCount]); // BBB00000:CCCCCDDD
6791 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6793 AccRol (shCount); // DDDCCCCC:BBB00000
6795 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6797 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6799 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6801 emitcode ("anl", "a,#0x%02x",
6802 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6804 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6806 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6809 case 6: // AAAAAABB:CCCCCCDD
6810 emitcode ("anl", "a,#0x%02x",
6811 SRMask[shCount]); // 000000BB:CCCCCCDD
6812 emitcode ("mov", "c,acc.0"); // c = B
6813 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6815 AccAXRrl1 (x); // BCCCCCCD:D000000B
6816 AccAXRrl1 (x); // BBCCCCCC:DD000000
6818 emitcode("rrc","a");
6819 emitcode("xch","a,%s", x);
6820 emitcode("rrc","a");
6821 emitcode("mov","c,acc.0"); //<< get correct bit
6822 emitcode("xch","a,%s", x);
6824 emitcode("rrc","a");
6825 emitcode("xch","a,%s", x);
6826 emitcode("rrc","a");
6827 emitcode("xch","a,%s", x);
6830 case 7: // a:x <<= 7
6832 emitcode ("anl", "a,#0x%02x",
6833 SRMask[shCount]); // 0000000B:CCCCCCCD
6835 emitcode ("mov", "c,acc.0"); // c = B
6837 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6839 AccAXRrl1 (x); // BCCCCCCC:D0000000
6847 /*-----------------------------------------------------------------*/
6848 /* AccAXRsh - right shift a:x known count (0..7) */
6849 /*-----------------------------------------------------------------*/
6851 AccAXRsh (char *x, int shCount)
6859 AccAXRrl1 (x); // 0->a:x
6864 AccAXRrl1 (x); // 0->a:x
6867 AccAXRrl1 (x); // 0->a:x
6872 case 5: // AAAAABBB:CCCCCDDD = a:x
6874 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6876 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6878 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6880 emitcode ("anl", "a,#0x%02x",
6881 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6883 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6885 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6887 emitcode ("anl", "a,#0x%02x",
6888 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6890 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6892 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6894 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6897 case 6: // AABBBBBB:CCDDDDDD
6899 emitcode ("mov", "c,acc.7");
6900 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6902 emitcode ("mov", "c,acc.7");
6903 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6905 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6907 emitcode ("anl", "a,#0x%02x",
6908 SRMask[shCount]); // 000000AA:BBBBBBCC
6911 case 7: // ABBBBBBB:CDDDDDDD
6913 emitcode ("mov", "c,acc.7"); // c = A
6915 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6917 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6919 emitcode ("anl", "a,#0x%02x",
6920 SRMask[shCount]); // 0000000A:BBBBBBBC
6928 /*-----------------------------------------------------------------*/
6929 /* AccAXRshS - right shift signed a:x known count (0..7) */
6930 /*-----------------------------------------------------------------*/
6932 AccAXRshS (char *x, int shCount)
6940 emitcode ("mov", "c,acc.7");
6941 AccAXRrl1 (x); // s->a:x
6945 emitcode ("mov", "c,acc.7");
6946 AccAXRrl1 (x); // s->a:x
6948 emitcode ("mov", "c,acc.7");
6949 AccAXRrl1 (x); // s->a:x
6954 case 5: // AAAAABBB:CCCCCDDD = a:x
6956 tlbl = newiTempLabel (NULL);
6957 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6959 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6961 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6963 emitcode ("anl", "a,#0x%02x",
6964 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6966 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6968 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6970 emitcode ("anl", "a,#0x%02x",
6971 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6973 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6975 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6977 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6979 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6980 emitcode ("orl", "a,#0x%02x",
6981 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6983 emitcode ("", "%05d$:", tlbl->key + 100);
6984 break; // SSSSAAAA:BBBCCCCC
6986 case 6: // AABBBBBB:CCDDDDDD
6988 tlbl = newiTempLabel (NULL);
6989 emitcode ("mov", "c,acc.7");
6990 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6992 emitcode ("mov", "c,acc.7");
6993 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6995 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6997 emitcode ("anl", "a,#0x%02x",
6998 SRMask[shCount]); // 000000AA:BBBBBBCC
7000 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7001 emitcode ("orl", "a,#0x%02x",
7002 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7004 emitcode ("", "%05d$:", tlbl->key + 100);
7006 case 7: // ABBBBBBB:CDDDDDDD
7008 tlbl = newiTempLabel (NULL);
7009 emitcode ("mov", "c,acc.7"); // c = A
7011 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7013 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7015 emitcode ("anl", "a,#0x%02x",
7016 SRMask[shCount]); // 0000000A:BBBBBBBC
7018 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7019 emitcode ("orl", "a,#0x%02x",
7020 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7022 emitcode ("", "%05d$:", tlbl->key + 100);
7029 /*-----------------------------------------------------------------*/
7030 /* shiftL2Left2Result - shift left two bytes from left to result */
7031 /*-----------------------------------------------------------------*/
7033 shiftL2Left2Result (operand * left, int offl,
7034 operand * result, int offr, int shCount)
7036 if (sameRegs (AOP (result), AOP (left)) &&
7037 ((offl + MSB16) == offr))
7039 /* don't crash result[offr] */
7040 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7041 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7045 movLeft2Result (left, offl, result, offr, 0);
7046 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7048 /* ax << shCount (x = lsb(result)) */
7049 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7050 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7054 /*-----------------------------------------------------------------*/
7055 /* shiftR2Left2Result - shift right two bytes from left to result */
7056 /*-----------------------------------------------------------------*/
7058 shiftR2Left2Result (operand * left, int offl,
7059 operand * result, int offr,
7060 int shCount, int sign)
7062 if (sameRegs (AOP (result), AOP (left)) &&
7063 ((offl + MSB16) == offr))
7065 /* don't crash result[offr] */
7066 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7067 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7071 movLeft2Result (left, offl, result, offr, 0);
7072 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7074 /* a:x >> shCount (x = lsb(result)) */
7076 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7078 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7079 if (getDataSize (result) > 1)
7080 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7083 /*-----------------------------------------------------------------*/
7084 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7085 /*-----------------------------------------------------------------*/
7087 shiftLLeftOrResult (operand * left, int offl,
7088 operand * result, int offr, int shCount)
7090 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7091 /* shift left accumulator */
7093 /* or with result */
7094 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7095 /* back to result */
7096 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7099 /*-----------------------------------------------------------------*/
7100 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7101 /*-----------------------------------------------------------------*/
7103 shiftRLeftOrResult (operand * left, int offl,
7104 operand * result, int offr, int shCount)
7106 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7107 /* shift right accumulator */
7109 /* or with result */
7110 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7111 /* back to result */
7112 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7115 /*-----------------------------------------------------------------*/
7116 /* genlshOne - left shift a one byte quantity by known count */
7117 /*-----------------------------------------------------------------*/
7119 genlshOne (operand * result, operand * left, int shCount)
7121 D(emitcode ("; genlshOne",""));
7123 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7126 /*-----------------------------------------------------------------*/
7127 /* genlshTwo - left shift two bytes by known amount != 0 */
7128 /*-----------------------------------------------------------------*/
7130 genlshTwo (operand * result, operand * left, int shCount)
7134 D(emitcode ("; genlshTwo",""));
7136 size = getDataSize (result);
7138 /* if shCount >= 8 */
7146 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7148 movLeft2Result (left, LSB, result, MSB16, 0);
7150 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7153 /* 1 <= shCount <= 7 */
7157 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7159 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7163 /*-----------------------------------------------------------------*/
7164 /* shiftLLong - shift left one long from left to result */
7165 /* offl = LSB or MSB16 */
7166 /*-----------------------------------------------------------------*/
7168 shiftLLong (operand * left, operand * result, int offr)
7171 int size = AOP_SIZE (result);
7173 if (size >= LSB + offr)
7175 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7177 emitcode ("add", "a,acc");
7178 if (sameRegs (AOP (left), AOP (result)) &&
7179 size >= MSB16 + offr && offr != LSB)
7180 emitcode ("xch", "a,%s",
7181 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7183 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7186 if (size >= MSB16 + offr)
7188 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7190 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7193 emitcode ("rlc", "a");
7194 if (sameRegs (AOP (left), AOP (result)) &&
7195 size >= MSB24 + offr && offr != LSB)
7196 emitcode ("xch", "a,%s",
7197 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7199 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7202 if (size >= MSB24 + offr)
7204 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7206 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7209 emitcode ("rlc", "a");
7210 if (sameRegs (AOP (left), AOP (result)) &&
7211 size >= MSB32 + offr && offr != LSB)
7212 emitcode ("xch", "a,%s",
7213 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7215 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7218 if (size > MSB32 + offr)
7220 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7222 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7225 emitcode ("rlc", "a");
7226 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7229 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7232 /*-----------------------------------------------------------------*/
7233 /* genlshFour - shift four byte by a known amount != 0 */
7234 /*-----------------------------------------------------------------*/
7236 genlshFour (operand * result, operand * left, int shCount)
7240 D(emitcode ("; genlshFour",""));
7242 size = AOP_SIZE (result);
7244 /* if shifting more that 3 bytes */
7249 /* lowest order of left goes to the highest
7250 order of the destination */
7251 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7253 movLeft2Result (left, LSB, result, MSB32, 0);
7254 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7255 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7256 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7260 /* more than two bytes */
7261 else if (shCount >= 16)
7263 /* lower order two bytes goes to higher order two bytes */
7265 /* if some more remaining */
7267 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7270 movLeft2Result (left, MSB16, result, MSB32, 0);
7271 movLeft2Result (left, LSB, result, MSB24, 0);
7273 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7274 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7278 /* if more than 1 byte */
7279 else if (shCount >= 8)
7281 /* lower order three bytes goes to higher order three bytes */
7286 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7288 movLeft2Result (left, LSB, result, MSB16, 0);
7294 movLeft2Result (left, MSB24, result, MSB32, 0);
7295 movLeft2Result (left, MSB16, result, MSB24, 0);
7296 movLeft2Result (left, LSB, result, MSB16, 0);
7297 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7299 else if (shCount == 1)
7300 shiftLLong (left, result, MSB16);
7303 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7304 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7305 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7306 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7311 /* 1 <= shCount <= 7 */
7312 else if (shCount <= 2)
7314 shiftLLong (left, result, LSB);
7316 shiftLLong (result, result, LSB);
7318 /* 3 <= shCount <= 7, optimize */
7321 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7322 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7323 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7327 /*-----------------------------------------------------------------*/
7328 /* genLeftShiftLiteral - left shifting by known count */
7329 /*-----------------------------------------------------------------*/
7331 genLeftShiftLiteral (operand * left,
7336 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7339 D(emitcode ("; genLeftShiftLiteral",""));
7341 freeAsmop (right, NULL, ic, TRUE);
7343 aopOp (left, ic, FALSE);
7344 aopOp (result, ic, FALSE);
7346 size = getSize (operandType (result));
7349 emitcode ("; shift left ", "result %d, left %d", size,
7353 /* I suppose that the left size >= result size */
7358 movLeft2Result (left, size, result, size, 0);
7362 else if (shCount >= (size * 8))
7364 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7370 genlshOne (result, left, shCount);
7374 genlshTwo (result, left, shCount);
7378 genlshFour (result, left, shCount);
7381 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7382 "*** ack! mystery literal shift!\n");
7386 freeAsmop (left, NULL, ic, TRUE);
7387 freeAsmop (result, NULL, ic, TRUE);
7390 /*-----------------------------------------------------------------*/
7391 /* genLeftShift - generates code for left shifting */
7392 /*-----------------------------------------------------------------*/
7394 genLeftShift (iCode * ic)
7396 operand *left, *right, *result;
7399 symbol *tlbl, *tlbl1;
7401 D(emitcode ("; genLeftShift",""));
7403 right = IC_RIGHT (ic);
7404 left = IC_LEFT (ic);
7405 result = IC_RESULT (ic);
7407 aopOp (right, ic, FALSE);
7409 /* if the shift count is known then do it
7410 as efficiently as possible */
7411 if (AOP_TYPE (right) == AOP_LIT)
7413 genLeftShiftLiteral (left, right, result, ic);
7417 /* shift count is unknown then we have to form
7418 a loop get the loop count in B : Note: we take
7419 only the lower order byte since shifting
7420 more that 32 bits make no sense anyway, ( the
7421 largest size of an object can be only 32 bits ) */
7423 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7424 emitcode ("inc", "b");
7425 freeAsmop (right, NULL, ic, TRUE);
7426 aopOp (left, ic, FALSE);
7427 aopOp (result, ic, FALSE);
7429 /* now move the left to the result if they are not the
7431 if (!sameRegs (AOP (left), AOP (result)) &&
7432 AOP_SIZE (result) > 1)
7435 size = AOP_SIZE (result);
7439 l = aopGet (AOP (left), offset, FALSE, TRUE);
7440 if (*l == '@' && (IS_AOP_PREG (result)))
7443 emitcode ("mov", "a,%s", l);
7444 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7447 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7452 tlbl = newiTempLabel (NULL);
7453 size = AOP_SIZE (result);
7455 tlbl1 = newiTempLabel (NULL);
7457 /* if it is only one byte then */
7460 symbol *tlbl1 = newiTempLabel (NULL);
7462 l = aopGet (AOP (left), 0, FALSE, FALSE);
7464 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7465 emitcode ("", "%05d$:", tlbl->key + 100);
7466 emitcode ("add", "a,acc");
7467 emitcode ("", "%05d$:", tlbl1->key + 100);
7468 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7469 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7473 reAdjustPreg (AOP (result));
7475 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7476 emitcode ("", "%05d$:", tlbl->key + 100);
7477 l = aopGet (AOP (result), offset, FALSE, FALSE);
7479 emitcode ("add", "a,acc");
7480 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7483 l = aopGet (AOP (result), offset, FALSE, FALSE);
7485 emitcode ("rlc", "a");
7486 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7488 reAdjustPreg (AOP (result));
7490 emitcode ("", "%05d$:", tlbl1->key + 100);
7491 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7493 freeAsmop (left, NULL, ic, TRUE);
7494 freeAsmop (result, NULL, ic, TRUE);
7497 /*-----------------------------------------------------------------*/
7498 /* genrshOne - right shift a one byte quantity by known count */
7499 /*-----------------------------------------------------------------*/
7501 genrshOne (operand * result, operand * left,
7502 int shCount, int sign)
7504 D(emitcode ("; genrshOne",""));
7506 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7509 /*-----------------------------------------------------------------*/
7510 /* genrshTwo - right shift two bytes by known amount != 0 */
7511 /*-----------------------------------------------------------------*/
7513 genrshTwo (operand * result, operand * left,
7514 int shCount, int sign)
7516 D(emitcode ("; genrshTwo",""));
7518 /* if shCount >= 8 */
7523 shiftR1Left2Result (left, MSB16, result, LSB,
7526 movLeft2Result (left, MSB16, result, LSB, sign);
7527 addSign (result, MSB16, sign);
7530 /* 1 <= shCount <= 7 */
7532 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7535 /*-----------------------------------------------------------------*/
7536 /* shiftRLong - shift right one long from left to result */
7537 /* offl = LSB or MSB16 */
7538 /*-----------------------------------------------------------------*/
7540 shiftRLong (operand * left, int offl,
7541 operand * result, int sign)
7543 int isSameRegs=sameRegs(AOP(left),AOP(result));
7545 if (isSameRegs && offl>1) {
7546 // we are in big trouble, but this shouldn't happen
7547 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7550 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7555 emitcode ("rlc", "a");
7556 emitcode ("subb", "a,acc");
7558 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7560 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7561 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7564 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7569 emitcode ("clr", "c");
7571 emitcode ("mov", "c,acc.7");
7574 emitcode ("rrc", "a");
7576 if (isSameRegs && offl==MSB16) {
7577 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7579 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7580 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7583 emitcode ("rrc", "a");
7584 if (isSameRegs && offl==1) {
7585 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7587 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7588 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7590 emitcode ("rrc", "a");
7591 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7595 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7596 emitcode ("rrc", "a");
7597 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7601 /*-----------------------------------------------------------------*/
7602 /* genrshFour - shift four byte by a known amount != 0 */
7603 /*-----------------------------------------------------------------*/
7605 genrshFour (operand * result, operand * left,
7606 int shCount, int sign)
7608 D(emitcode ("; genrshFour",""));
7610 /* if shifting more that 3 bytes */
7615 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7617 movLeft2Result (left, MSB32, result, LSB, sign);
7618 addSign (result, MSB16, sign);
7620 else if (shCount >= 16)
7624 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7627 movLeft2Result (left, MSB24, result, LSB, 0);
7628 movLeft2Result (left, MSB32, result, MSB16, sign);
7630 addSign (result, MSB24, sign);
7632 else if (shCount >= 8)
7636 shiftRLong (left, MSB16, result, sign);
7637 else if (shCount == 0)
7639 movLeft2Result (left, MSB16, result, LSB, 0);
7640 movLeft2Result (left, MSB24, result, MSB16, 0);
7641 movLeft2Result (left, MSB32, result, MSB24, sign);
7642 addSign (result, MSB32, sign);
7646 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7647 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7648 /* the last shift is signed */
7649 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7650 addSign (result, MSB32, sign);
7654 { /* 1 <= shCount <= 7 */
7657 shiftRLong (left, LSB, result, sign);
7659 shiftRLong (result, LSB, result, sign);
7663 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7664 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7665 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7670 /*-----------------------------------------------------------------*/
7671 /* genRightShiftLiteral - right shifting by known count */
7672 /*-----------------------------------------------------------------*/
7674 genRightShiftLiteral (operand * left,
7680 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7683 D(emitcode ("; genRightShiftLiteral",""));
7685 freeAsmop (right, NULL, ic, TRUE);
7687 aopOp (left, ic, FALSE);
7688 aopOp (result, ic, FALSE);
7691 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7695 size = getDataSize (left);
7696 /* test the LEFT size !!! */
7698 /* I suppose that the left size >= result size */
7701 size = getDataSize (result);
7703 movLeft2Result (left, size, result, size, 0);
7706 else if (shCount >= (size * 8))
7709 /* get sign in acc.7 */
7710 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7712 addSign (result, LSB, sign);
7719 genrshOne (result, left, shCount, sign);
7723 genrshTwo (result, left, shCount, sign);
7727 genrshFour (result, left, shCount, sign);
7733 freeAsmop (left, NULL, ic, TRUE);
7734 freeAsmop (result, NULL, ic, TRUE);
7737 /*-----------------------------------------------------------------*/
7738 /* genSignedRightShift - right shift of signed number */
7739 /*-----------------------------------------------------------------*/
7741 genSignedRightShift (iCode * ic)
7743 operand *right, *left, *result;
7746 symbol *tlbl, *tlbl1;
7748 D(emitcode ("; genSignedRightShift",""));
7750 /* we do it the hard way put the shift count in b
7751 and loop thru preserving the sign */
7753 right = IC_RIGHT (ic);
7754 left = IC_LEFT (ic);
7755 result = IC_RESULT (ic);
7757 aopOp (right, ic, FALSE);
7760 if (AOP_TYPE (right) == AOP_LIT)
7762 genRightShiftLiteral (left, right, result, ic, 1);
7765 /* shift count is unknown then we have to form
7766 a loop get the loop count in B : Note: we take
7767 only the lower order byte since shifting
7768 more that 32 bits make no sense anyway, ( the
7769 largest size of an object can be only 32 bits ) */
7771 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7772 emitcode ("inc", "b");
7773 freeAsmop (right, NULL, ic, TRUE);
7774 aopOp (left, ic, FALSE);
7775 aopOp (result, ic, FALSE);
7777 /* now move the left to the result if they are not the
7779 if (!sameRegs (AOP (left), AOP (result)) &&
7780 AOP_SIZE (result) > 1)
7783 size = AOP_SIZE (result);
7787 l = aopGet (AOP (left), offset, FALSE, TRUE);
7788 if (*l == '@' && IS_AOP_PREG (result))
7791 emitcode ("mov", "a,%s", l);
7792 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7795 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7800 /* mov the highest order bit to OVR */
7801 tlbl = newiTempLabel (NULL);
7802 tlbl1 = newiTempLabel (NULL);
7804 size = AOP_SIZE (result);
7806 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7807 emitcode ("rlc", "a");
7808 emitcode ("mov", "ov,c");
7809 /* if it is only one byte then */
7812 l = aopGet (AOP (left), 0, FALSE, FALSE);
7814 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7815 emitcode ("", "%05d$:", tlbl->key + 100);
7816 emitcode ("mov", "c,ov");
7817 emitcode ("rrc", "a");
7818 emitcode ("", "%05d$:", tlbl1->key + 100);
7819 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7820 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7824 reAdjustPreg (AOP (result));
7825 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7826 emitcode ("", "%05d$:", tlbl->key + 100);
7827 emitcode ("mov", "c,ov");
7830 l = aopGet (AOP (result), offset, FALSE, FALSE);
7832 emitcode ("rrc", "a");
7833 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7835 reAdjustPreg (AOP (result));
7836 emitcode ("", "%05d$:", tlbl1->key + 100);
7837 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7840 freeAsmop (left, NULL, ic, TRUE);
7841 freeAsmop (result, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genRightShift - generate code for right shifting */
7846 /*-----------------------------------------------------------------*/
7848 genRightShift (iCode * ic)
7850 operand *right, *left, *result;
7854 symbol *tlbl, *tlbl1;
7856 D(emitcode ("; genRightShift",""));
7858 /* if signed then we do it the hard way preserve the
7859 sign bit moving it inwards */
7860 letype = getSpec (operandType (IC_LEFT (ic)));
7862 if (!SPEC_USIGN (letype))
7864 genSignedRightShift (ic);
7868 /* signed & unsigned types are treated the same : i.e. the
7869 signed is NOT propagated inwards : quoting from the
7870 ANSI - standard : "for E1 >> E2, is equivalent to division
7871 by 2**E2 if unsigned or if it has a non-negative value,
7872 otherwise the result is implementation defined ", MY definition
7873 is that the sign does not get propagated */
7875 right = IC_RIGHT (ic);
7876 left = IC_LEFT (ic);
7877 result = IC_RESULT (ic);
7879 aopOp (right, ic, FALSE);
7881 /* if the shift count is known then do it
7882 as efficiently as possible */
7883 if (AOP_TYPE (right) == AOP_LIT)
7885 genRightShiftLiteral (left, right, result, ic, 0);
7889 /* shift count is unknown then we have to form
7890 a loop get the loop count in B : Note: we take
7891 only the lower order byte since shifting
7892 more that 32 bits make no sense anyway, ( the
7893 largest size of an object can be only 32 bits ) */
7895 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7896 emitcode ("inc", "b");
7897 freeAsmop (right, NULL, ic, TRUE);
7898 aopOp (left, ic, FALSE);
7899 aopOp (result, ic, FALSE);
7901 /* now move the left to the result if they are not the
7903 if (!sameRegs (AOP (left), AOP (result)) &&
7904 AOP_SIZE (result) > 1)
7907 size = AOP_SIZE (result);
7911 l = aopGet (AOP (left), offset, FALSE, TRUE);
7912 if (*l == '@' && IS_AOP_PREG (result))
7915 emitcode ("mov", "a,%s", l);
7916 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7919 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7924 tlbl = newiTempLabel (NULL);
7925 tlbl1 = newiTempLabel (NULL);
7926 size = AOP_SIZE (result);
7929 /* if it is only one byte then */
7932 l = aopGet (AOP (left), 0, FALSE, FALSE);
7934 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7935 emitcode ("", "%05d$:", tlbl->key + 100);
7937 emitcode ("rrc", "a");
7938 emitcode ("", "%05d$:", tlbl1->key + 100);
7939 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7940 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7944 reAdjustPreg (AOP (result));
7945 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7946 emitcode ("", "%05d$:", tlbl->key + 100);
7950 l = aopGet (AOP (result), offset, FALSE, FALSE);
7952 emitcode ("rrc", "a");
7953 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7955 reAdjustPreg (AOP (result));
7957 emitcode ("", "%05d$:", tlbl1->key + 100);
7958 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7961 freeAsmop (left, NULL, ic, TRUE);
7962 freeAsmop (result, NULL, ic, TRUE);
7965 /*-----------------------------------------------------------------*/
7966 /* emitPtrByteGet - emits code to get a byte into A through a */
7967 /* pointer register (R0, R1, or DPTR). The */
7968 /* original value of A can be preserved in B. */
7969 /*-----------------------------------------------------------------*/
7971 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7978 emitcode ("mov", "b,a");
7979 emitcode ("mov", "a,@%s", rname);
7984 emitcode ("mov", "b,a");
7985 emitcode ("movx", "a,@%s", rname);
7990 emitcode ("mov", "b,a");
7991 emitcode ("movx", "a,@dptr");
7996 emitcode ("mov", "b,a");
7997 emitcode ("clr", "a");
7998 emitcode ("movc", "a,@a+dptr");
8004 emitcode ("push", "b");
8005 emitcode ("push", "acc");
8007 emitcode ("lcall", "__gptrget");
8009 emitcode ("pop", "b");
8014 /*-----------------------------------------------------------------*/
8015 /* emitPtrByteSet - emits code to set a byte from src through a */
8016 /* pointer register (R0, R1, or DPTR). */
8017 /*-----------------------------------------------------------------*/
8019 emitPtrByteSet (char *rname, int p_type, char *src)
8028 emitcode ("mov", "@%s,a", rname);
8031 emitcode ("mov", "@%s,%s", rname, src);
8036 emitcode ("movx", "@%s,a", rname);
8041 emitcode ("movx", "@dptr,a");
8046 emitcode ("lcall", "__gptrput");
8051 /*-----------------------------------------------------------------*/
8052 /* genUnpackBits - generates code for unpacking bits */
8053 /*-----------------------------------------------------------------*/
8055 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8057 int offset = 0; /* result byte offset */
8058 int rsize; /* result size */
8059 int rlen = 0; /* remaining bitfield length */
8060 sym_link *etype; /* bitfield type information */
8061 int blen; /* bitfield length */
8062 int bstr; /* bitfield starting bit within byte */
8065 D(emitcode ("; genUnpackBits",""));
8067 etype = getSpec (operandType (result));
8068 rsize = getSize (operandType (result));
8069 blen = SPEC_BLEN (etype);
8070 bstr = SPEC_BSTR (etype);
8072 if (ifx && blen <= 8)
8074 emitPtrByteGet (rname, ptype, FALSE);
8077 SNPRINTF (buffer, sizeof(buffer),
8079 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8084 emitcode ("anl", "a,#0x%02x",
8085 (((unsigned char) -1) >> (8 - blen)) << bstr);
8086 genIfxJump (ifx, "a", NULL, NULL, NULL);
8092 /* If the bitfield length is less than a byte */
8095 emitPtrByteGet (rname, ptype, FALSE);
8097 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8098 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8102 /* Bit field did not fit in a byte. Copy all
8103 but the partial byte at the end. */
8104 for (rlen=blen;rlen>=8;rlen-=8)
8106 emitPtrByteGet (rname, ptype, FALSE);
8107 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8109 emitcode ("inc", "%s", rname);
8112 /* Handle the partial byte at the end */
8115 emitPtrByteGet (rname, ptype, FALSE);
8116 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8117 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8125 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8130 /*-----------------------------------------------------------------*/
8131 /* genDataPointerGet - generates code when ptr offset is known */
8132 /*-----------------------------------------------------------------*/
8134 genDataPointerGet (operand * left,
8140 int size, offset = 0;
8142 D(emitcode ("; genDataPointerGet",""));
8144 aopOp (result, ic, TRUE);
8146 /* get the string representation of the name */
8147 l = aopGet (AOP (left), 0, FALSE, TRUE);
8148 size = AOP_SIZE (result);
8152 sprintf (buffer, "(%s + %d)", l + 1, offset);
8154 sprintf (buffer, "%s", l + 1);
8155 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8158 freeAsmop (left, NULL, ic, TRUE);
8159 freeAsmop (result, NULL, ic, TRUE);
8162 /*-----------------------------------------------------------------*/
8163 /* genNearPointerGet - emitcode for near pointer fetch */
8164 /*-----------------------------------------------------------------*/
8166 genNearPointerGet (operand * left,
8175 sym_link *rtype, *retype;
8176 sym_link *ltype = operandType (left);
8179 D(emitcode ("; genNearPointerGet",""));
8181 rtype = operandType (result);
8182 retype = getSpec (rtype);
8184 aopOp (left, ic, FALSE);
8186 /* if left is rematerialisable and
8187 result is not bitfield variable type and
8188 the left is pointer to data space i.e
8189 lower 128 bytes of space */
8190 if (AOP_TYPE (left) == AOP_IMMD &&
8191 !IS_BITFIELD (retype) &&
8192 DCL_TYPE (ltype) == POINTER)
8194 genDataPointerGet (left, result, ic);
8198 /* if the value is already in a pointer register
8199 then don't need anything more */
8200 if (!AOP_INPREG (AOP (left)))
8202 if (IS_AOP_PREG (left))
8204 // Aha, it is a pointer, just in disguise.
8205 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8208 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8209 __FILE__, __LINE__);
8214 emitcode ("mov", "a%s,%s", rname + 1, rname);
8215 rname++; // skip the '@'.
8220 /* otherwise get a free pointer register */
8222 preg = getFreePtr (ic, &aop, FALSE);
8223 emitcode ("mov", "%s,%s",
8225 aopGet (AOP (left), 0, FALSE, TRUE));
8230 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8232 //aopOp (result, ic, FALSE);
8233 aopOp (result, ic, result?TRUE:FALSE);
8235 /* if bitfield then unpack the bits */
8236 if (IS_BITFIELD (retype))
8237 genUnpackBits (result, rname, POINTER, ifx);
8240 /* we have can just get the values */
8241 int size = AOP_SIZE (result);
8246 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8249 emitcode ("mov", "a,@%s", rname);
8251 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8255 sprintf (buffer, "@%s", rname);
8256 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8260 emitcode ("inc", "%s", rname);
8264 /* now some housekeeping stuff */
8265 if (aop) /* we had to allocate for this iCode */
8267 if (pi) { /* post increment present */
8268 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8270 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8274 /* we did not allocate which means left
8275 already in a pointer register, then
8276 if size > 0 && this could be used again
8277 we have to point it back to where it
8279 if ((AOP_SIZE (result) > 1 &&
8280 !OP_SYMBOL (left)->remat &&
8281 (OP_SYMBOL (left)->liveTo > ic->seq ||
8285 int size = AOP_SIZE (result) - 1;
8287 emitcode ("dec", "%s", rname);
8291 if (ifx && !ifx->generated)
8293 genIfxJump (ifx, "a", left, NULL, result);
8297 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8298 freeAsmop (left, NULL, ic, TRUE);
8299 if (pi) pi->generated = 1;
8302 /*-----------------------------------------------------------------*/
8303 /* genPagedPointerGet - emitcode for paged pointer fetch */
8304 /*-----------------------------------------------------------------*/
8306 genPagedPointerGet (operand * left,
8315 sym_link *rtype, *retype;
8317 D(emitcode ("; genPagedPointerGet",""));
8319 rtype = operandType (result);
8320 retype = getSpec (rtype);
8322 aopOp (left, ic, FALSE);
8324 /* if the value is already in a pointer register
8325 then don't need anything more */
8326 if (!AOP_INPREG (AOP (left)))
8328 /* otherwise get a free pointer register */
8330 preg = getFreePtr (ic, &aop, FALSE);
8331 emitcode ("mov", "%s,%s",
8333 aopGet (AOP (left), 0, FALSE, TRUE));
8337 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8339 aopOp (result, ic, FALSE);
8341 /* if bitfield then unpack the bits */
8342 if (IS_BITFIELD (retype))
8343 genUnpackBits (result, rname, PPOINTER, ifx);
8346 /* we have can just get the values */
8347 int size = AOP_SIZE (result);
8353 emitcode ("movx", "a,@%s", rname);
8355 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8360 emitcode ("inc", "%s", rname);
8364 /* now some housekeeping stuff */
8365 if (aop) /* we had to allocate for this iCode */
8367 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8368 freeAsmop (NULL, aop, ic, TRUE);
8372 /* we did not allocate which means left
8373 already in a pointer register, then
8374 if size > 0 && this could be used again
8375 we have to point it back to where it
8377 if ((AOP_SIZE (result) > 1 &&
8378 !OP_SYMBOL (left)->remat &&
8379 (OP_SYMBOL (left)->liveTo > ic->seq ||
8383 int size = AOP_SIZE (result) - 1;
8385 emitcode ("dec", "%s", rname);
8389 if (ifx && !ifx->generated)
8391 genIfxJump (ifx, "a", left, NULL, result);
8395 freeAsmop (left, NULL, ic, TRUE);
8396 freeAsmop (result, NULL, ic, TRUE);
8397 if (pi) pi->generated = 1;
8401 /*--------------------------------------------------------------------*/
8402 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8403 /*--------------------------------------------------------------------*/
8405 loadDptrFromOperand (operand *op, bool loadBToo)
8407 if (AOP_TYPE (op) != AOP_STR)
8409 /* if this is remateriazable */
8410 if (AOP_TYPE (op) == AOP_IMMD)
8412 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8415 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8416 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8419 wassertl(FALSE, "need pointerCode");
8420 emitcode ("", "; mov b,???");
8421 /* genPointerGet and genPointerSet originally did different
8422 ** things for this case. Both seem wrong.
8423 ** from genPointerGet:
8424 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8425 ** from genPointerSet:
8426 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8431 else if (AOP_TYPE (op) == AOP_DPTR)
8435 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8436 emitcode ("push", "acc");
8437 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8438 emitcode ("push", "acc");
8439 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8440 emitcode ("pop", "dph");
8441 emitcode ("pop", "dpl");
8445 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8446 emitcode ("push", "acc");
8447 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8448 emitcode ("pop", "dpl");
8452 { /* we need to get it byte by byte */
8453 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8454 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8456 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8461 /*-----------------------------------------------------------------*/
8462 /* genFarPointerGet - gget value from far space */
8463 /*-----------------------------------------------------------------*/
8465 genFarPointerGet (operand * left,
8466 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8469 sym_link *retype = getSpec (operandType (result));
8471 D(emitcode ("; genFarPointerGet",""));
8473 aopOp (left, ic, FALSE);
8474 loadDptrFromOperand (left, FALSE);
8476 /* so dptr now contains the address */
8477 aopOp (result, ic, FALSE);
8479 /* if bit then unpack */
8480 if (IS_BITFIELD (retype))
8481 genUnpackBits (result, "dptr", FPOINTER, ifx);
8484 size = AOP_SIZE (result);
8489 emitcode ("movx", "a,@dptr");
8491 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8493 emitcode ("inc", "dptr");
8498 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8500 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8501 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8505 if (ifx && !ifx->generated)
8507 genIfxJump (ifx, "a", left, NULL, result);
8510 freeAsmop (left, NULL, ic, TRUE);
8511 freeAsmop (result, NULL, ic, TRUE);
8514 /*-----------------------------------------------------------------*/
8515 /* genCodePointerGet - gget value from code space */
8516 /*-----------------------------------------------------------------*/
8518 genCodePointerGet (operand * left,
8519 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8522 sym_link *retype = getSpec (operandType (result));
8524 D(emitcode ("; genCodePointerGet",""));
8526 aopOp (left, ic, FALSE);
8527 loadDptrFromOperand (left, FALSE);
8529 /* so dptr now contains the address */
8530 aopOp (result, ic, FALSE);
8532 /* if bit then unpack */
8533 if (IS_BITFIELD (retype))
8534 genUnpackBits (result, "dptr", CPOINTER, ifx);
8537 size = AOP_SIZE (result);
8544 emitcode ("clr", "a");
8545 emitcode ("movc", "a,@a+dptr");
8547 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8548 emitcode ("inc", "dptr");
8552 emitcode ("mov", "a,#0x%02x", offset);
8553 emitcode ("movc", "a,@a+dptr");
8555 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8560 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8562 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8563 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8567 if (ifx && !ifx->generated)
8569 genIfxJump (ifx, "a", left, NULL, result);
8572 freeAsmop (left, NULL, ic, TRUE);
8573 freeAsmop (result, NULL, ic, TRUE);
8576 /*-----------------------------------------------------------------*/
8577 /* genGenPointerGet - gget value from generic pointer space */
8578 /*-----------------------------------------------------------------*/
8580 genGenPointerGet (operand * left,
8581 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8584 sym_link *retype = getSpec (operandType (result));
8586 D(emitcode ("; genGenPointerGet",""));
8588 aopOp (left, ic, FALSE);
8589 loadDptrFromOperand (left, TRUE);
8591 /* so dptr know contains the address */
8592 aopOp (result, ic, FALSE);
8594 /* if bit then unpack */
8595 if (IS_BITFIELD (retype))
8596 genUnpackBits (result, "dptr", GPOINTER, ifx);
8599 size = AOP_SIZE (result);
8604 emitcode ("lcall", "__gptrget");
8606 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8608 emitcode ("inc", "dptr");
8612 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8614 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8615 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8619 if (ifx && !ifx->generated)
8621 genIfxJump (ifx, "a", left, NULL, result);
8625 freeAsmop (left, NULL, ic, TRUE);
8626 freeAsmop (result, NULL, ic, TRUE);
8629 /*-----------------------------------------------------------------*/
8630 /* genPointerGet - generate code for pointer get */
8631 /*-----------------------------------------------------------------*/
8633 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8635 operand *left, *result;
8636 sym_link *type, *etype;
8639 D(emitcode ("; genPointerGet",""));
8641 left = IC_LEFT (ic);
8642 result = IC_RESULT (ic);
8644 if (getSize (operandType (result))>1)
8647 /* depending on the type of pointer we need to
8648 move it to the correct pointer register */
8649 type = operandType (left);
8650 etype = getSpec (type);
8651 /* if left is of type of pointer then it is simple */
8652 if (IS_PTR (type) && !IS_FUNC (type->next))
8653 p_type = DCL_TYPE (type);
8656 /* we have to go by the storage class */
8657 p_type = PTR_TYPE (SPEC_OCLS (etype));
8660 /* special case when cast remat */
8661 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8662 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8663 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8664 type = operandType (left);
8665 p_type = DCL_TYPE (type);
8667 /* now that we have the pointer type we assign
8668 the pointer values */
8674 genNearPointerGet (left, result, ic, pi, ifx);
8678 genPagedPointerGet (left, result, ic, pi, ifx);
8682 genFarPointerGet (left, result, ic, pi, ifx);
8686 genCodePointerGet (left, result, ic, pi, ifx);
8690 genGenPointerGet (left, result, ic, pi, ifx);
8698 /*-----------------------------------------------------------------*/
8699 /* genPackBits - generates code for packed bit storage */
8700 /*-----------------------------------------------------------------*/
8702 genPackBits (sym_link * etype,
8704 char *rname, int p_type)
8706 int offset = 0; /* source byte offset */
8707 int rlen = 0; /* remaining bitfield length */
8708 int blen; /* bitfield length */
8709 int bstr; /* bitfield starting bit within byte */
8710 int litval; /* source literal value (if AOP_LIT) */
8711 unsigned char mask; /* bitmask within current byte */
8713 D(emitcode ("; genPackBits",""));
8715 blen = SPEC_BLEN (etype);
8716 bstr = SPEC_BSTR (etype);
8718 /* If the bitfield length is less than a byte */
8721 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8722 (unsigned char) (0xFF >> (8 - bstr)));
8724 if (AOP_TYPE (right) == AOP_LIT)
8726 /* Case with a bitfield length <8 and literal source
8728 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8730 litval &= (~mask) & 0xff;
8731 emitPtrByteGet (rname, p_type, FALSE);
8732 if ((mask|litval)!=0xff)
8733 emitcode ("anl","a,#0x%02x", mask);
8735 emitcode ("orl","a,#0x%02x", litval);
8739 if ((blen==1) && (p_type!=GPOINTER))
8741 /* Case with a bitfield length == 1 and no generic pointer
8743 if (AOP_TYPE (right) == AOP_CRY)
8744 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8747 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8748 emitcode ("rrc","a");
8750 emitPtrByteGet (rname, p_type, FALSE);
8751 emitcode ("mov","acc.%d,c",bstr);
8755 /* Case with a bitfield length < 8 and arbitrary source
8757 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8758 /* shift and mask source value */
8760 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8762 /* transfer A to B and get next byte */
8763 emitPtrByteGet (rname, p_type, TRUE);
8765 emitcode ("anl", "a,#0x%02x", mask);
8766 emitcode ("orl", "a,b");
8767 if (p_type == GPOINTER)
8768 emitcode ("pop", "b");
8772 emitPtrByteSet (rname, p_type, "a");
8776 /* Bit length is greater than 7 bits. In this case, copy */
8777 /* all except the partial byte at the end */
8778 for (rlen=blen;rlen>=8;rlen-=8)
8780 emitPtrByteSet (rname, p_type,
8781 aopGet (AOP (right), offset++, FALSE, TRUE) );
8783 emitcode ("inc", "%s", rname);
8786 /* If there was a partial byte at the end */
8789 mask = (((unsigned char) -1 << rlen) & 0xff);
8791 if (AOP_TYPE (right) == AOP_LIT)
8793 /* Case with partial byte and literal source
8795 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8796 litval >>= (blen-rlen);
8797 litval &= (~mask) & 0xff;
8798 emitPtrByteGet (rname, p_type, FALSE);
8799 if ((mask|litval)!=0xff)
8800 emitcode ("anl","a,#0x%02x", mask);
8802 emitcode ("orl","a,#0x%02x", litval);
8806 /* Case with partial byte and arbitrary source
8808 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8809 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8811 /* transfer A to B and get next byte */
8812 emitPtrByteGet (rname, p_type, TRUE);
8814 emitcode ("anl", "a,#0x%02x", mask);
8815 emitcode ("orl", "a,b");
8816 if (p_type == GPOINTER)
8817 emitcode ("pop", "b");
8819 emitPtrByteSet (rname, p_type, "a");
8825 /*-----------------------------------------------------------------*/
8826 /* genDataPointerSet - remat pointer to data space */
8827 /*-----------------------------------------------------------------*/
8829 genDataPointerSet (operand * right,
8833 int size, offset = 0;
8834 char *l, buffer[256];
8836 D(emitcode ("; genDataPointerSet",""));
8838 aopOp (right, ic, FALSE);
8840 l = aopGet (AOP (result), 0, FALSE, TRUE);
8841 size = AOP_SIZE (right);
8845 sprintf (buffer, "(%s + %d)", l + 1, offset);
8847 sprintf (buffer, "%s", l + 1);
8848 emitcode ("mov", "%s,%s", buffer,
8849 aopGet (AOP (right), offset++, FALSE, FALSE));
8852 freeAsmop (right, NULL, ic, TRUE);
8853 freeAsmop (result, NULL, ic, TRUE);
8856 /*-----------------------------------------------------------------*/
8857 /* genNearPointerSet - emitcode for near pointer put */
8858 /*-----------------------------------------------------------------*/
8860 genNearPointerSet (operand * right,
8868 sym_link *retype, *letype;
8869 sym_link *ptype = operandType (result);
8871 D(emitcode ("; genNearPointerSet",""));
8873 retype = getSpec (operandType (right));
8874 letype = getSpec (ptype);
8875 aopOp (result, ic, FALSE);
8877 /* if the result is rematerializable &
8878 in data space & not a bit variable */
8879 if (AOP_TYPE (result) == AOP_IMMD &&
8880 DCL_TYPE (ptype) == POINTER &&
8881 !IS_BITVAR (retype) &&
8882 !IS_BITVAR (letype))
8884 genDataPointerSet (right, result, ic);
8888 /* if the value is already in a pointer register
8889 then don't need anything more */
8890 if (!AOP_INPREG (AOP (result)))
8893 //AOP_TYPE (result) == AOP_STK
8897 // Aha, it is a pointer, just in disguise.
8898 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8901 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8902 __FILE__, __LINE__);
8907 emitcode ("mov", "a%s,%s", rname + 1, rname);
8908 rname++; // skip the '@'.
8913 /* otherwise get a free pointer register */
8915 preg = getFreePtr (ic, &aop, FALSE);
8916 emitcode ("mov", "%s,%s",
8918 aopGet (AOP (result), 0, FALSE, TRUE));
8924 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8927 aopOp (right, ic, FALSE);
8929 /* if bitfield then unpack the bits */
8930 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8931 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8934 /* we have can just get the values */
8935 int size = AOP_SIZE (right);
8940 l = aopGet (AOP (right), offset, FALSE, TRUE);
8944 emitcode ("mov", "@%s,a", rname);
8947 emitcode ("mov", "@%s,%s", rname, l);
8949 emitcode ("inc", "%s", rname);
8954 /* now some housekeeping stuff */
8955 if (aop) /* we had to allocate for this iCode */
8958 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8959 freeAsmop (NULL, aop, ic, TRUE);
8963 /* we did not allocate which means left
8964 already in a pointer register, then
8965 if size > 0 && this could be used again
8966 we have to point it back to where it
8968 if ((AOP_SIZE (right) > 1 &&
8969 !OP_SYMBOL (result)->remat &&
8970 (OP_SYMBOL (result)->liveTo > ic->seq ||
8974 int size = AOP_SIZE (right) - 1;
8976 emitcode ("dec", "%s", rname);
8981 if (pi) pi->generated = 1;
8982 freeAsmop (result, NULL, ic, TRUE);
8983 freeAsmop (right, NULL, ic, TRUE);
8986 /*-----------------------------------------------------------------*/
8987 /* genPagedPointerSet - emitcode for Paged pointer put */
8988 /*-----------------------------------------------------------------*/
8990 genPagedPointerSet (operand * right,
8998 sym_link *retype, *letype;
9000 D(emitcode ("; genPagedPointerSet",""));
9002 retype = getSpec (operandType (right));
9003 letype = getSpec (operandType (result));
9005 aopOp (result, ic, FALSE);
9007 /* if the value is already in a pointer register
9008 then don't need anything more */
9009 if (!AOP_INPREG (AOP (result)))
9011 /* otherwise get a free pointer register */
9013 preg = getFreePtr (ic, &aop, FALSE);
9014 emitcode ("mov", "%s,%s",
9016 aopGet (AOP (result), 0, FALSE, TRUE));
9020 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9022 aopOp (right, ic, FALSE);
9024 /* if bitfield then unpack the bits */
9025 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9026 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9029 /* we have can just get the values */
9030 int size = AOP_SIZE (right);
9035 l = aopGet (AOP (right), offset, FALSE, TRUE);
9038 emitcode ("movx", "@%s,a", rname);
9041 emitcode ("inc", "%s", rname);
9047 /* now some housekeeping stuff */
9048 if (aop) /* we had to allocate for this iCode */
9051 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9052 freeAsmop (NULL, aop, ic, TRUE);
9056 /* we did not allocate which means left
9057 already in a pointer register, then
9058 if size > 0 && this could be used again
9059 we have to point it back to where it
9061 if (AOP_SIZE (right) > 1 &&
9062 !OP_SYMBOL (result)->remat &&
9063 (OP_SYMBOL (result)->liveTo > ic->seq ||
9066 int size = AOP_SIZE (right) - 1;
9068 emitcode ("dec", "%s", rname);
9073 if (pi) pi->generated = 1;
9074 freeAsmop (result, NULL, ic, TRUE);
9075 freeAsmop (right, NULL, ic, TRUE);
9080 /*-----------------------------------------------------------------*/
9081 /* genFarPointerSet - set value from far space */
9082 /*-----------------------------------------------------------------*/
9084 genFarPointerSet (operand * right,
9085 operand * result, iCode * ic, iCode * pi)
9088 sym_link *retype = getSpec (operandType (right));
9089 sym_link *letype = getSpec (operandType (result));
9091 D(emitcode ("; genFarPointerSet",""));
9093 aopOp (result, ic, FALSE);
9094 loadDptrFromOperand (result, FALSE);
9096 /* so dptr know contains the address */
9097 aopOp (right, ic, FALSE);
9099 /* if bit then unpack */
9100 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9101 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9104 size = AOP_SIZE (right);
9109 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9111 emitcode ("movx", "@dptr,a");
9113 emitcode ("inc", "dptr");
9116 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9117 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9118 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9121 freeAsmop (result, NULL, ic, TRUE);
9122 freeAsmop (right, NULL, ic, TRUE);
9125 /*-----------------------------------------------------------------*/
9126 /* genGenPointerSet - set value from generic pointer space */
9127 /*-----------------------------------------------------------------*/
9129 genGenPointerSet (operand * right,
9130 operand * result, iCode * ic, iCode * pi)
9133 sym_link *retype = getSpec (operandType (right));
9134 sym_link *letype = getSpec (operandType (result));
9136 D(emitcode ("; genGenPointerSet",""));
9138 aopOp (result, ic, FALSE);
9139 loadDptrFromOperand (result, TRUE);
9141 /* so dptr know contains the address */
9142 aopOp (right, ic, FALSE);
9144 /* if bit then unpack */
9145 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9146 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9149 size = AOP_SIZE (right);
9154 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9156 emitcode ("lcall", "__gptrput");
9158 emitcode ("inc", "dptr");
9162 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9163 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9164 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9167 freeAsmop (result, NULL, ic, TRUE);
9168 freeAsmop (right, NULL, ic, TRUE);
9171 /*-----------------------------------------------------------------*/
9172 /* genPointerSet - stores the value into a pointer location */
9173 /*-----------------------------------------------------------------*/
9175 genPointerSet (iCode * ic, iCode *pi)
9177 operand *right, *result;
9178 sym_link *type, *etype;
9181 D(emitcode ("; genPointerSet",""));
9183 right = IC_RIGHT (ic);
9184 result = IC_RESULT (ic);
9186 /* depending on the type of pointer we need to
9187 move it to the correct pointer register */
9188 type = operandType (result);
9189 etype = getSpec (type);
9190 /* if left is of type of pointer then it is simple */
9191 if (IS_PTR (type) && !IS_FUNC (type->next))
9193 p_type = DCL_TYPE (type);
9197 /* we have to go by the storage class */
9198 p_type = PTR_TYPE (SPEC_OCLS (etype));
9201 /* special case when cast remat */
9202 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9203 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9204 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9205 type = operandType (result);
9206 p_type = DCL_TYPE (type);
9208 /* now that we have the pointer type we assign
9209 the pointer values */
9215 genNearPointerSet (right, result, ic, pi);
9219 genPagedPointerSet (right, result, ic, pi);
9223 genFarPointerSet (right, result, ic, pi);
9227 genGenPointerSet (right, result, ic, pi);
9231 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9232 "genPointerSet: illegal pointer type");
9237 /*-----------------------------------------------------------------*/
9238 /* genIfx - generate code for Ifx statement */
9239 /*-----------------------------------------------------------------*/
9241 genIfx (iCode * ic, iCode * popIc)
9243 operand *cond = IC_COND (ic);
9246 D(emitcode ("; genIfx",""));
9248 aopOp (cond, ic, FALSE);
9250 /* get the value into acc */
9251 if (AOP_TYPE (cond) != AOP_CRY)
9255 /* the result is now in the accumulator */
9256 freeAsmop (cond, NULL, ic, TRUE);
9258 /* if there was something to be popped then do it */
9262 /* if the condition is a bit variable */
9263 if (isbit && IS_ITEMP (cond) &&
9265 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9266 else if (isbit && !IS_ITEMP (cond))
9267 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9269 genIfxJump (ic, "a", NULL, NULL, NULL);
9274 /*-----------------------------------------------------------------*/
9275 /* genAddrOf - generates code for address of */
9276 /*-----------------------------------------------------------------*/
9278 genAddrOf (iCode * ic)
9280 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9283 D(emitcode ("; genAddrOf",""));
9285 aopOp (IC_RESULT (ic), ic, FALSE);
9287 /* if the operand is on the stack then we
9288 need to get the stack offset of this
9292 /* if it has an offset then we need to compute
9296 emitcode ("mov", "a,_bp");
9297 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9298 ((char) (sym->stack - _G.nRegsSaved)) :
9299 ((char) sym->stack)) & 0xff);
9300 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9304 /* we can just move _bp */
9305 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9307 /* fill the result with zero */
9308 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9313 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9319 /* object not on stack then we need the name */
9320 size = AOP_SIZE (IC_RESULT (ic));
9325 char s[SDCC_NAME_MAX];
9327 sprintf (s, "#(%s >> %d)",
9331 sprintf (s, "#%s", sym->rname);
9332 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9340 /*-----------------------------------------------------------------*/
9341 /* genFarFarAssign - assignment when both are in far space */
9342 /*-----------------------------------------------------------------*/
9344 genFarFarAssign (operand * result, operand * right, iCode * ic)
9346 int size = AOP_SIZE (right);
9350 D(emitcode ("; genFarFarAssign",""));
9352 /* first push the right side on to the stack */
9355 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9357 emitcode ("push", "acc");
9360 freeAsmop (right, NULL, ic, FALSE);
9361 /* now assign DPTR to result */
9362 aopOp (result, ic, FALSE);
9363 size = AOP_SIZE (result);
9366 emitcode ("pop", "acc");
9367 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9369 freeAsmop (result, NULL, ic, FALSE);
9373 /*-----------------------------------------------------------------*/
9374 /* genAssign - generate code for assignment */
9375 /*-----------------------------------------------------------------*/
9377 genAssign (iCode * ic)
9379 operand *result, *right;
9381 unsigned long lit = 0L;
9383 D(emitcode("; genAssign",""));
9385 result = IC_RESULT (ic);
9386 right = IC_RIGHT (ic);
9388 /* if they are the same */
9389 if (operandsEqu (result, right) &&
9390 !isOperandVolatile (result, FALSE) &&
9391 !isOperandVolatile (right, FALSE))
9394 aopOp (right, ic, FALSE);
9396 /* special case both in far space */
9397 if (AOP_TYPE (right) == AOP_DPTR &&
9398 IS_TRUE_SYMOP (result) &&
9399 isOperandInFarSpace (result))
9402 genFarFarAssign (result, right, ic);
9406 aopOp (result, ic, TRUE);
9408 /* if they are the same registers */
9409 if (sameRegs (AOP (right), AOP (result)) &&
9410 !isOperandVolatile (result, FALSE) &&
9411 !isOperandVolatile (right, FALSE))
9414 /* if the result is a bit */
9415 if (AOP_TYPE (result) == AOP_CRY)
9418 /* if the right size is a literal then
9419 we know what the value is */
9420 if (AOP_TYPE (right) == AOP_LIT)
9422 if (((int) operandLitValue (right)))
9423 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9425 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9429 /* the right is also a bit variable */
9430 if (AOP_TYPE (right) == AOP_CRY)
9432 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9433 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9439 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9443 /* bit variables done */
9445 size = AOP_SIZE (result);
9447 if (AOP_TYPE (right) == AOP_LIT)
9448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9450 (AOP_TYPE (result) != AOP_REG) &&
9451 (AOP_TYPE (right) == AOP_LIT) &&
9452 !IS_FLOAT (operandType (right)) &&
9455 emitcode ("clr", "a");
9458 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9459 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9461 aopPut (AOP (result),
9462 aopGet (AOP (right), size, FALSE, FALSE),
9464 isOperandVolatile (result, FALSE));
9471 aopPut (AOP (result),
9472 aopGet (AOP (right), offset, FALSE, FALSE),
9474 isOperandVolatile (result, FALSE));
9480 freeAsmop (right, NULL, ic, TRUE);
9481 freeAsmop (result, NULL, ic, TRUE);
9484 /*-----------------------------------------------------------------*/
9485 /* genJumpTab - genrates code for jump table */
9486 /*-----------------------------------------------------------------*/
9488 genJumpTab (iCode * ic)
9490 symbol *jtab,*jtablo,*jtabhi;
9494 D(emitcode ("; genJumpTab",""));
9496 count = elementsInSet( IC_JTLABELS (ic) );
9500 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9501 if the switch argument is in an register.
9502 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9503 aopOp (IC_JTCOND (ic), ic, FALSE);
9504 /* get the condition into accumulator */
9505 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9507 /* multiply by three */
9508 emitcode ("add", "a,acc");
9509 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9510 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9512 jtab = newiTempLabel (NULL);
9513 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9514 emitcode ("jmp", "@a+dptr");
9515 emitcode ("", "%05d$:", jtab->key + 100);
9516 /* now generate the jump labels */
9517 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9518 jtab = setNextItem (IC_JTLABELS (ic)))
9519 emitcode ("ljmp", "%05d$", jtab->key + 100);
9523 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9524 if the switch argument is in an register.
9525 For n>6 this algorithm may be more compact */
9526 jtablo = newiTempLabel (NULL);
9527 jtabhi = newiTempLabel (NULL);
9529 /* get the condition into accumulator.
9530 Using b as temporary storage, if register push/pop is needed */
9531 aopOp (IC_JTCOND (ic), ic, FALSE);
9532 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9533 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9534 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9536 emitcode ("mov", "b,%s", l);
9539 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9543 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9544 emitcode ("movc", "a,@a+pc");
9545 emitcode ("push", "acc");
9548 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9549 emitcode ("movc", "a,@a+pc");
9550 emitcode ("push", "acc");
9554 /* this scales up to n<=255, but needs two more bytes
9556 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9557 emitcode ("movc", "a,@a+dptr");
9558 emitcode ("push", "acc");
9561 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9562 emitcode ("movc", "a,@a+dptr");
9563 emitcode ("push", "acc");
9566 emitcode ("ret", "");
9568 /* now generate jump table, LSB */
9569 emitcode ("", "%05d$:", jtablo->key + 100);
9570 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9571 jtab = setNextItem (IC_JTLABELS (ic)))
9572 emitcode (".db", "%05d$", jtab->key + 100);
9574 /* now generate jump table, MSB */
9575 emitcode ("", "%05d$:", jtabhi->key + 100);
9576 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9577 jtab = setNextItem (IC_JTLABELS (ic)))
9578 emitcode (".db", "%05d$>>8", jtab->key + 100);
9584 /*-----------------------------------------------------------------*/
9585 /* genCast - gen code for casting */
9586 /*-----------------------------------------------------------------*/
9588 genCast (iCode * ic)
9590 operand *result = IC_RESULT (ic);
9591 sym_link *ctype = operandType (IC_LEFT (ic));
9592 sym_link *rtype = operandType (IC_RIGHT (ic));
9593 operand *right = IC_RIGHT (ic);
9596 D(emitcode("; genCast",""));
9598 /* if they are equivalent then do nothing */
9599 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9602 aopOp (right, ic, FALSE);
9603 aopOp (result, ic, FALSE);
9605 /* if the result is a bit (and not a bitfield) */
9606 // if (AOP_TYPE (result) == AOP_CRY)
9607 if (IS_BITVAR (OP_SYMBOL (result)->type)
9608 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9610 /* if the right size is a literal then
9611 we know what the value is */
9612 if (AOP_TYPE (right) == AOP_LIT)
9614 if (((int) operandLitValue (right)))
9615 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9617 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9622 /* the right is also a bit variable */
9623 if (AOP_TYPE (right) == AOP_CRY)
9625 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9626 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9632 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9637 /* if they are the same size : or less */
9638 if (AOP_SIZE (result) <= AOP_SIZE (right))
9641 /* if they are in the same place */
9642 if (sameRegs (AOP (right), AOP (result)))
9645 /* if they in different places then copy */
9646 size = AOP_SIZE (result);
9650 aopPut (AOP (result),
9651 aopGet (AOP (right), offset, FALSE, FALSE),
9653 isOperandVolatile (result, FALSE));
9660 /* if the result is of type pointer */
9665 sym_link *type = operandType (right);
9666 sym_link *etype = getSpec (type);
9668 /* pointer to generic pointer */
9669 if (IS_GENPTR (ctype))
9672 p_type = DCL_TYPE (type);
9675 if (SPEC_SCLS(etype)==S_REGISTER) {
9676 // let's assume it is a generic pointer
9679 /* we have to go by the storage class */
9680 p_type = PTR_TYPE (SPEC_OCLS (etype));
9684 /* the first two bytes are known */
9685 size = GPTRSIZE - 1;
9689 aopPut (AOP (result),
9690 aopGet (AOP (right), offset, FALSE, FALSE),
9692 isOperandVolatile (result, FALSE));
9695 /* the last byte depending on type */
9697 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9702 // pointerTypeToGPByte will have bitched.
9706 sprintf(gpValStr, "#0x%d", gpVal);
9707 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9712 /* just copy the pointers */
9713 size = AOP_SIZE (result);
9717 aopPut (AOP (result),
9718 aopGet (AOP (right), offset, FALSE, FALSE),
9720 isOperandVolatile (result, FALSE));
9726 /* so we now know that the size of destination is greater
9727 than the size of the source */
9728 /* we move to result for the size of source */
9729 size = AOP_SIZE (right);
9733 aopPut (AOP (result),
9734 aopGet (AOP (right), offset, FALSE, FALSE),
9736 isOperandVolatile (result, FALSE));
9740 /* now depending on the sign of the source && destination */
9741 size = AOP_SIZE (result) - AOP_SIZE (right);
9742 /* if unsigned or not an integral type */
9743 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9746 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9750 /* we need to extend the sign :{ */
9751 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9754 emitcode ("rlc", "a");
9755 emitcode ("subb", "a,acc");
9757 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9760 /* we are done hurray !!!! */
9763 freeAsmop (right, NULL, ic, TRUE);
9764 freeAsmop (result, NULL, ic, TRUE);
9768 /*-----------------------------------------------------------------*/
9769 /* genDjnz - generate decrement & jump if not zero instrucion */
9770 /*-----------------------------------------------------------------*/
9772 genDjnz (iCode * ic, iCode * ifx)
9778 D(emitcode ("; genDjnz",""));
9780 /* if the if condition has a false label
9781 then we cannot save */
9785 /* if the minus is not of the form
9787 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9788 !IS_OP_LITERAL (IC_RIGHT (ic)))
9791 if (operandLitValue (IC_RIGHT (ic)) != 1)
9794 /* if the size of this greater than one then no
9796 if (getSize (operandType (IC_RESULT (ic))) > 1)
9799 /* otherwise we can save BIG */
9800 lbl = newiTempLabel (NULL);
9801 lbl1 = newiTempLabel (NULL);
9803 aopOp (IC_RESULT (ic), ic, FALSE);
9805 if (AOP_NEEDSACC(IC_RESULT(ic)))
9807 /* If the result is accessed indirectly via
9808 * the accumulator, we must explicitly write
9809 * it back after the decrement.
9811 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9813 if (strcmp(rByte, "a"))
9815 /* Something is hopelessly wrong */
9816 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9817 __FILE__, __LINE__);
9818 /* We can just give up; the generated code will be inefficient,
9821 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9824 emitcode ("dec", "%s", rByte);
9825 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9826 emitcode ("jnz", "%05d$", lbl->key + 100);
9828 else if (IS_AOP_PREG (IC_RESULT (ic)))
9830 emitcode ("dec", "%s",
9831 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9832 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9833 emitcode ("jnz", "%05d$", lbl->key + 100);
9837 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9840 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9841 emitcode ("", "%05d$:", lbl->key + 100);
9842 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9843 emitcode ("", "%05d$:", lbl1->key + 100);
9845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9850 /*-----------------------------------------------------------------*/
9851 /* genReceive - generate code for a receive iCode */
9852 /*-----------------------------------------------------------------*/
9854 genReceive (iCode * ic)
9856 int size = getSize (operandType (IC_RESULT (ic)));
9858 D(emitcode ("; genReceive",""));
9860 if (ic->argreg == 1) { /* first parameter */
9861 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9862 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9863 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9869 for (offset = 0; offset<size; offset++)
9870 if (!strcmp (fReturn[offset], "a"))
9875 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9877 for (offset = size-1; offset>0; offset--)
9878 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9879 emitcode("mov","a,%s", fReturn[0]);
9881 aopOp (IC_RESULT (ic), ic, FALSE);
9883 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9884 isOperandVolatile (IC_RESULT (ic), FALSE));
9885 for (offset = 1; offset<size; offset++)
9886 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9887 isOperandVolatile (IC_RESULT (ic), FALSE));
9893 if (getTempRegs(tempRegs, size, ic))
9895 for (offset = 0; offset<size; offset++)
9896 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9897 aopOp (IC_RESULT (ic), ic, FALSE);
9898 for (offset = 0; offset<size; offset++)
9899 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9900 isOperandVolatile (IC_RESULT (ic), FALSE));
9905 offset = fReturnSizeMCS51 - size;
9907 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9908 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9911 aopOp (IC_RESULT (ic), ic, FALSE);
9912 size = AOP_SIZE (IC_RESULT (ic));
9915 emitcode ("pop", "acc");
9916 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9921 aopOp (IC_RESULT (ic), ic, FALSE);
9923 assignResultValue (IC_RESULT (ic));
9925 } else { /* second receive onwards */
9927 aopOp (IC_RESULT (ic), ic, FALSE);
9928 rb1off = ic->argreg;
9930 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9938 /*-----------------------------------------------------------------*/
9939 /* genDummyRead - generate code for dummy read of volatiles */
9940 /*-----------------------------------------------------------------*/
9942 genDummyRead (iCode * ic)
9947 D(emitcode("; genDummyRead",""));
9950 if (op && IS_SYMOP (op))
9952 aopOp (op, ic, FALSE);
9954 /* if the result is a bit */
9955 if (AOP_TYPE (op) == AOP_CRY)
9956 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9959 /* bit variables done */
9961 size = AOP_SIZE (op);
9965 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9970 freeAsmop (op, NULL, ic, TRUE);
9974 if (op && IS_SYMOP (op))
9976 aopOp (op, ic, FALSE);
9978 /* if the result is a bit */
9979 if (AOP_TYPE (op) == AOP_CRY)
9980 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9983 /* bit variables done */
9985 size = AOP_SIZE (op);
9989 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9994 freeAsmop (op, NULL, ic, TRUE);
9998 /*-----------------------------------------------------------------*/
9999 /* genCritical - generate code for start of a critical sequence */
10000 /*-----------------------------------------------------------------*/
10002 genCritical (iCode *ic)
10004 symbol *tlbl = newiTempLabel (NULL);
10006 D(emitcode("; genCritical",""));
10008 if (IC_RESULT (ic))
10009 aopOp (IC_RESULT (ic), ic, TRUE);
10011 emitcode ("setb", "c");
10012 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10013 emitcode ("clr", "c");
10014 emitcode ("", "%05d$:", (tlbl->key + 100));
10016 if (IC_RESULT (ic))
10017 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
10019 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10021 if (IC_RESULT (ic))
10022 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10025 /*-----------------------------------------------------------------*/
10026 /* genEndCritical - generate code for end of a critical sequence */
10027 /*-----------------------------------------------------------------*/
10029 genEndCritical (iCode *ic)
10031 D(emitcode("; genEndCritical",""));
10035 aopOp (IC_RIGHT (ic), ic, FALSE);
10036 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10038 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10039 emitcode ("mov", "ea,c");
10043 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10044 emitcode ("rrc", "a");
10045 emitcode ("mov", "ea,c");
10047 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10051 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10052 emitcode ("mov", "ea,c");
10056 /*-----------------------------------------------------------------*/
10057 /* gen51Code - generate code for 8051 based controllers */
10058 /*-----------------------------------------------------------------*/
10060 gen51Code (iCode * lic)
10064 /* int cseq = 0; */
10066 _G.currentFunc = NULL;
10067 lineHead = lineCurr = NULL;
10069 /* print the allocation information */
10070 if (allocInfo && currFunc)
10071 printAllocInfo (currFunc, codeOutFile);
10072 /* if debug information required */
10073 if (options.debug && currFunc)
10075 debugFile->writeFunction (currFunc, lic);
10077 /* stack pointer name */
10078 if (options.useXstack)
10084 for (ic = lic; ic; ic = ic->next)
10086 _G.current_iCode = ic;
10088 if (ic->lineno && cln != ic->lineno)
10092 debugFile->writeCLine(ic);
10094 if (!options.noCcodeInAsm) {
10095 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10096 printCLine(ic->filename, ic->lineno));
10101 if (ic->seqPoint && ic->seqPoint != cseq)
10103 emitcode ("", "; sequence point %d", ic->seqPoint);
10104 cseq = ic->seqPoint;
10107 if (options.iCodeInAsm) {
10108 char regsInUse[80];
10111 for (i=0; i<8; i++) {
10112 sprintf (®sInUse[i],
10113 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10116 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10118 /* if the result is marked as
10119 spilt and rematerializable or code for
10120 this has already been generated then
10122 if (resultRemat (ic) || ic->generated)
10125 /* depending on the operation */
10145 /* IPOP happens only when trying to restore a
10146 spilt live range, if there is an ifx statement
10147 following this pop then the if statement might
10148 be using some of the registers being popped which
10149 would destory the contents of the register so
10150 we need to check for this condition and handle it */
10152 ic->next->op == IFX &&
10153 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10154 genIfx (ic->next, ic);
10172 genEndFunction (ic);
10192 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10209 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10213 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10220 /* note these two are xlated by algebraic equivalence
10221 during parsing SDCC.y */
10222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10223 "got '>=' or '<=' shouldn't have come here");
10227 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10239 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10243 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10247 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10271 genRightShift (ic);
10274 case GET_VALUE_AT_ADDRESS:
10276 hasInc (IC_LEFT (ic), ic,
10277 getSize (operandType (IC_RESULT (ic)))),
10278 ifxForOp (IC_RESULT (ic), ic) );
10282 if (POINTER_SET (ic))
10283 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10309 addSet (&_G.sendSet, ic);
10312 case DUMMY_READ_VOLATILE:
10321 genEndCritical (ic);
10333 _G.current_iCode = NULL;
10335 /* now we are ready to call the
10336 peep hole optimizer */
10337 if (!options.nopeep)
10338 peepHole (&lineHead);
10340 /* now do the actual printing */
10341 printLine (lineHead, codeOutFile);