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 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
140 //printf ("%s\n", lb);
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
148 lineCurr->ic = _G.current_iCode;
149 lineCurr->isComment = (*lbp==';');
153 /*-----------------------------------------------------------------*/
154 /* mova - moves specified value into accumulator */
155 /*-----------------------------------------------------------------*/
159 /* do some early peephole optimization */
160 if (!strcmp(x, "a") || !strcmp(x, "acc"))
163 emitcode("mov","a,%s", x);
166 /*-----------------------------------------------------------------*/
167 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
168 /*-----------------------------------------------------------------*/
170 getFreePtr (iCode * ic, asmop ** aopp, bool result)
172 bool r0iu = FALSE, r1iu = FALSE;
173 bool r0ou = FALSE, r1ou = FALSE;
175 /* the logic: if r0 & r1 used in the instruction
176 then we are in trouble otherwise */
178 /* first check if r0 & r1 are used by this
179 instruction, in which case we are in trouble */
180 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
181 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
186 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
187 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
189 /* if no usage of r0 then return it */
192 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
193 (*aopp)->type = AOP_R0;
195 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
198 /* if no usage of r1 then return it */
201 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
202 (*aopp)->type = AOP_R1;
204 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
207 /* now we know they both have usage */
208 /* if r0 not used in this instruction */
211 /* push it if not already pushed */
214 emitcode ("mov", "b,%s",
215 mcs51_regWithIdx (R0_IDX)->dname);
218 else if (!_G.r0Pushed)
220 emitcode ("push", "%s",
221 mcs51_regWithIdx (R0_IDX)->dname);
225 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
226 (*aopp)->type = AOP_R0;
228 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
231 /* if r1 not used then */
235 /* push it if not already pushed */
238 emitcode ("mov", "b,%s",
239 mcs51_regWithIdx (R1_IDX)->dname);
242 else if (!_G.r1Pushed)
244 emitcode ("push", "%s",
245 mcs51_regWithIdx (R1_IDX)->dname);
249 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
254 /* I said end of world, but not quite end of world yet */
256 /* we can push it on the stack */
257 (*aopp)->type = AOP_STK;
260 /* in the case that result AND left AND right needs a pointer reg
261 we can safely use the result's */
262 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
263 (*aopp)->type = AOP_R0;
264 return mcs51_regWithIdx (R0_IDX);
266 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
267 (*aopp)->type = AOP_R1;
268 return mcs51_regWithIdx (R1_IDX);
272 /* now this is REALLY the end of the world */
273 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
274 "getFreePtr should never reach here");
279 /*-----------------------------------------------------------------*/
280 /* getTempRegs - initialize an array of pointers to GPR registers */
281 /* that are not in use. Returns 1 if the requested */
282 /* number of registers were available, 0 otherwise. */
283 /*-----------------------------------------------------------------*/
285 getTempRegs(regs **tempRegs, int size, iCode *ic)
292 ic = _G.current_iCode;
298 freeRegs = newBitVect(8);
299 bitVectSetBit (freeRegs, R2_IDX);
300 bitVectSetBit (freeRegs, R3_IDX);
301 bitVectSetBit (freeRegs, R4_IDX);
302 bitVectSetBit (freeRegs, R5_IDX);
303 bitVectSetBit (freeRegs, R6_IDX);
304 bitVectSetBit (freeRegs, R7_IDX);
306 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
308 bitVect * newfreeRegs;
309 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
310 freeBitVect(freeRegs);
311 freeRegs = newfreeRegs;
313 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
316 for (i=0; i<freeRegs->size; i++)
318 if (bitVectBitValue(freeRegs,i))
319 tempRegs[offset++] = mcs51_regWithIdx(i);
322 freeBitVect(freeRegs);
327 freeBitVect(freeRegs);
332 /*-----------------------------------------------------------------*/
333 /* newAsmop - creates a new asmOp */
334 /*-----------------------------------------------------------------*/
336 newAsmop (short type)
340 aop = Safe_calloc (1, sizeof (asmop));
345 /*-----------------------------------------------------------------*/
346 /* pointerCode - returns the code for a pointer type */
347 /*-----------------------------------------------------------------*/
349 pointerCode (sym_link * etype)
352 return PTR_TYPE (SPEC_OCLS (etype));
357 /*-----------------------------------------------------------------*/
358 /* leftRightUseAcc - returns size of accumulator use by operands */
359 /*-----------------------------------------------------------------*/
361 leftRightUseAcc(iCode *ic)
370 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
371 "null iCode pointer");
378 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
381 size = getSize (OP_SYMBOL (op)->type);
386 else if (ic->op == JUMPTABLE)
389 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
392 size = getSize (OP_SYMBOL (op)->type);
400 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
403 size = getSize (OP_SYMBOL (op)->type);
408 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
411 size = getSize (OP_SYMBOL (op)->type);
424 /*-----------------------------------------------------------------*/
425 /* aopForSym - for a true symbol */
426 /*-----------------------------------------------------------------*/
428 aopForSym (iCode * ic, symbol * sym, bool result)
433 wassertl (ic != NULL, "Got a null iCode");
434 wassertl (sym != NULL, "Got a null symbol");
436 space = SPEC_OCLS (sym->etype);
438 /* if already has one */
442 /* assign depending on the storage class */
443 /* if it is on the stack or indirectly addressable */
444 /* space we need to assign either r0 or r1 to it */
445 if (sym->onStack || sym->iaccess)
447 sym->aop = aop = newAsmop (0);
448 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
449 aop->size = getSize (sym->type);
451 /* now assign the address of the variable to
452 the pointer register */
453 if (aop->type != AOP_STK)
458 if (_G.accInUse || leftRightUseAcc (ic))
459 emitcode ("push", "acc");
461 emitcode ("mov", "a,_bp");
462 emitcode ("add", "a,#0x%02x",
464 ((char) (sym->stack - _G.nRegsSaved)) :
465 ((char) sym->stack)) & 0xff);
466 emitcode ("mov", "%s,a",
467 aop->aopu.aop_ptr->name);
469 if (_G.accInUse || leftRightUseAcc (ic))
470 emitcode ("pop", "acc");
473 emitcode ("mov", "%s,#%s",
474 aop->aopu.aop_ptr->name,
476 aop->paged = space->paged;
479 aop->aopu.aop_stk = sym->stack;
483 /* if in bit space */
484 if (IN_BITSPACE (space))
486 sym->aop = aop = newAsmop (AOP_CRY);
487 aop->aopu.aop_dir = sym->rname;
488 aop->size = getSize (sym->type);
491 /* if it is in direct space */
492 if (IN_DIRSPACE (space))
494 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
495 //printTypeChainRaw(sym->type, NULL);
496 //printf("space = %s\n", space ? space->sname : "NULL");
497 sym->aop = aop = newAsmop (AOP_DIR);
498 aop->aopu.aop_dir = sym->rname;
499 aop->size = getSize (sym->type);
503 /* special case for a function */
504 if (IS_FUNC (sym->type))
506 sym->aop = aop = newAsmop (AOP_IMMD);
507 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
508 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
509 aop->size = FPTRSIZE;
513 /* only remaining is far space */
514 /* in which case DPTR gets the address */
515 sym->aop = aop = newAsmop (AOP_DPTR);
516 emitcode ("mov", "dptr,#%s", sym->rname);
517 aop->size = getSize (sym->type);
519 /* if it is in code space */
520 if (IN_CODESPACE (space))
526 /*-----------------------------------------------------------------*/
527 /* aopForRemat - rematerialzes an object */
528 /*-----------------------------------------------------------------*/
530 aopForRemat (symbol * sym)
532 iCode *ic = sym->rematiCode;
533 asmop *aop = newAsmop (AOP_IMMD);
540 val += (int) operandLitValue (IC_RIGHT (ic));
541 else if (ic->op == '-')
542 val -= (int) operandLitValue (IC_RIGHT (ic));
543 else if (IS_CAST_ICODE(ic)) {
544 sym_link *from_type = operandType(IC_RIGHT(ic));
545 aop->aopu.aop_immd.from_cast_remat = 1;
546 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
547 ptr_type = DCL_TYPE(from_type);
548 if (ptr_type == IPOINTER) {
555 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
559 sprintf (buffer, "(%s %c 0x%04x)",
560 OP_SYMBOL (IC_LEFT (ic))->rname,
561 val >= 0 ? '+' : '-',
564 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
566 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
567 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
568 /* set immd2 field if required */
569 if (aop->aopu.aop_immd.from_cast_remat) {
570 sprintf(buffer,"#0x%02x",ptr_type);
571 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
572 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common */
580 /*-----------------------------------------------------------------*/
582 regsInCommon (operand * op1, operand * op2)
587 /* if they have registers in common */
588 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
591 sym1 = OP_SYMBOL (op1);
592 sym2 = OP_SYMBOL (op2);
594 if (sym1->nRegs == 0 || sym2->nRegs == 0)
597 for (i = 0; i < sym1->nRegs; i++)
603 for (j = 0; j < sym2->nRegs; j++)
608 if (sym2->regs[j] == sym1->regs[i])
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent */
618 /*-----------------------------------------------------------------*/
620 operandsEqu (operand * op1, operand * op2)
624 /* if they not symbols */
625 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
628 sym1 = OP_SYMBOL (op1);
629 sym2 = OP_SYMBOL (op2);
631 /* if both are itemps & one is spilt
632 and the other is not then false */
633 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634 sym1->isspilt != sym2->isspilt)
637 /* if they are the same */
641 if (strcmp (sym1->rname, sym2->rname) == 0)
645 /* if left is a tmp & right is not */
646 if (IS_ITEMP (op1) &&
649 (sym1->usl.spillLoc == sym2))
652 if (IS_ITEMP (op2) &&
656 (sym2->usl.spillLoc == sym1))
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers */
664 /*-----------------------------------------------------------------*/
666 sameRegs (asmop * aop1, asmop * aop2)
673 if (aop1->type != AOP_REG ||
674 aop2->type != AOP_REG)
677 if (aop1->size != aop2->size)
680 for (i = 0; i < aop1->size; i++)
681 if (aop1->aopu.aop_reg[i] !=
682 aop2->aopu.aop_reg[i])
688 /*-----------------------------------------------------------------*/
689 /* aopOp - allocates an asmop for an operand : */
690 /*-----------------------------------------------------------------*/
692 aopOp (operand * op, iCode * ic, bool result)
701 /* if this a literal */
702 if (IS_OP_LITERAL (op))
704 op->aop = aop = newAsmop (AOP_LIT);
705 aop->aopu.aop_lit = op->operand.valOperand;
706 aop->size = getSize (operandType (op));
710 /* if already has a asmop then continue */
714 /* if the underlying symbol has a aop */
715 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
717 op->aop = OP_SYMBOL (op)->aop;
721 /* if this is a true symbol */
722 if (IS_TRUE_SYMOP (op))
724 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
728 /* this is a temporary : this has
734 e) can be a return use only */
736 sym = OP_SYMBOL (op);
738 /* if the type is a conditional */
739 if (sym->regType == REG_CND)
741 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
746 /* if it is spilt then two situations
748 b) has a spill location */
749 if (sym->isspilt || sym->nRegs == 0)
752 /* rematerialize it NOW */
755 sym->aop = op->aop = aop =
757 aop->size = getSize (sym->type);
764 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
765 aop->size = getSize (sym->type);
766 for (i = 0; i < 2; i++)
767 aop->aopu.aop_str[i] = accUse[i];
775 aop = op->aop = sym->aop = newAsmop (AOP_STR);
776 aop->size = getSize (sym->type);
777 for (i = 0; i < fReturnSizeMCS51; i++)
778 aop->aopu.aop_str[i] = fReturn[i];
782 if (sym->usl.spillLoc)
784 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
786 /* force a new aop if sizes differ */
787 sym->usl.spillLoc->aop = NULL;
789 sym->aop = op->aop = aop =
790 aopForSym (ic, sym->usl.spillLoc, result);
791 aop->size = getSize (sym->type);
795 /* else must be a dummy iTemp */
796 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
797 aop->size = getSize (sym->type);
801 /* must be in a register */
802 sym->aop = op->aop = aop = newAsmop (AOP_REG);
803 aop->size = sym->nRegs;
804 for (i = 0; i < sym->nRegs; i++)
805 aop->aopu.aop_reg[i] = sym->regs[i];
808 /*-----------------------------------------------------------------*/
809 /* freeAsmop - free up the asmop given to an operand */
810 /*----------------------------------------------------------------*/
812 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
829 /* depending on the asmop type only three cases need work AOP_RO
830 , AOP_R1 && AOP_STK */
836 emitcode ("mov", "r0,b");
839 else if (_G.r0Pushed)
843 emitcode ("pop", "ar0");
847 bitVectUnSetBit (ic->rUsed, R0_IDX);
853 emitcode ("mov", "r1,b");
860 emitcode ("pop", "ar1");
864 bitVectUnSetBit (ic->rUsed, R1_IDX);
870 int stk = aop->aopu.aop_stk + aop->size - 1;
871 bitVectUnSetBit (ic->rUsed, R0_IDX);
872 bitVectUnSetBit (ic->rUsed, R1_IDX);
874 getFreePtr (ic, &aop, FALSE);
878 emitcode ("mov", "a,_bp");
879 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
880 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
884 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
889 emitcode ("pop", "acc");
890 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
893 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
896 freeAsmop (op, NULL, ic, TRUE);
899 emitcode ("pop", "ar1");
905 emitcode ("pop", "ar0");
912 /* all other cases just dealloc */
918 OP_SYMBOL (op)->aop = NULL;
919 /* if the symbol has a spill */
921 SPIL_LOC (op)->aop = NULL;
926 /*------------------------------------------------------------------*/
927 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
928 /* pop r0 or r1 off stack if pushed */
929 /*------------------------------------------------------------------*/
931 freeForBranchAsmop (operand * op)
951 emitcode ("mov", "r0,b");
953 else if (_G.r0Pushed)
955 emitcode ("pop", "ar0");
962 emitcode ("mov", "r1,b");
964 else if (_G.r1Pushed)
966 emitcode ("pop", "ar1");
973 int stk = aop->aopu.aop_stk + aop->size - 1;
975 emitcode ("mov", "b,r0");
978 emitcode ("mov", "a,_bp");
979 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
980 emitcode ("mov", "r0,a");
984 emitcode ("mov", "r0,_bp");
989 emitcode ("pop", "acc");
990 emitcode ("mov", "@r0,a");
993 emitcode ("dec", "r0");
995 emitcode ("mov", "r0,b");
1001 /*-----------------------------------------------------------------*/
1002 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1003 /* clobber the accumulator */
1004 /*-----------------------------------------------------------------*/
1006 aopGetUsesAcc (asmop *aop, int offset)
1008 if (offset > (aop->size - 1))
1026 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1035 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1041 /* Error case --- will have been caught already */
1047 /*-----------------------------------------------------------------*/
1048 /* aopGet - for fetching value of the aop */
1049 /*-----------------------------------------------------------------*/
1051 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1056 /* offset is greater than
1058 if (offset > (aop->size - 1) &&
1059 aop->type != AOP_LIT)
1062 /* depending on type */
1070 /* if we need to increment it */
1071 while (offset > aop->coff)
1073 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1077 while (offset < aop->coff)
1079 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1086 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1087 return (dname ? "acc" : "a");
1089 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1090 rs = Safe_calloc (1, strlen (s) + 1);
1095 if (aop->code && aop->coff==0 && offset>=1) {
1096 emitcode ("mov", "a,#0x%02x", offset);
1097 emitcode ("movc", "a,@a+dptr");
1098 return (dname ? "acc" : "a");
1101 while (offset > aop->coff)
1103 emitcode ("inc", "dptr");
1107 while (offset < aop->coff)
1109 emitcode ("lcall", "__decdptr");
1116 emitcode ("clr", "a");
1117 emitcode ("movc", "a,@a+dptr");
1121 emitcode ("movx", "a,@dptr");
1123 return (dname ? "acc" : "a");
1127 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1128 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1130 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1132 sprintf (s, "#(%s >> %d)",
1133 aop->aopu.aop_immd.aop_immd1,
1137 aop->aopu.aop_immd.aop_immd1);
1138 rs = Safe_calloc (1, strlen (s) + 1);
1144 sprintf (s, "(%s + %d)",
1148 sprintf (s, "%s", aop->aopu.aop_dir);
1149 rs = Safe_calloc (1, strlen (s) + 1);
1155 return aop->aopu.aop_reg[offset]->dname;
1157 return aop->aopu.aop_reg[offset]->name;
1160 emitcode ("clr", "a");
1161 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1162 emitcode ("rlc", "a");
1163 return (dname ? "acc" : "a");
1166 if (!offset && dname)
1168 return aop->aopu.aop_str[offset];
1171 return aopLiteral (aop->aopu.aop_lit, offset);
1175 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1179 return aop->aopu.aop_str[offset];
1183 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1184 "aopget got unsupported aop->type");
1187 /*-----------------------------------------------------------------*/
1188 /* aopPut - puts a string for a aop */
1189 /*-----------------------------------------------------------------*/
1191 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1195 if (aop->size && offset > (aop->size - 1))
1197 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1198 "aopPut got offset > aop->size");
1202 /* will assign value to value */
1203 /* depending on where it is ofcourse */
1207 MOVA (s); /* read s in case it was volatile */
1212 sprintf (d, "(%s + %d)",
1213 aop->aopu.aop_dir, offset);
1215 sprintf (d, "%s", aop->aopu.aop_dir);
1217 if (strcmp (d, s) ||
1219 emitcode ("mov", "%s,%s", d, s);
1224 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1225 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1228 strcmp (s, "r0") == 0 ||
1229 strcmp (s, "r1") == 0 ||
1230 strcmp (s, "r2") == 0 ||
1231 strcmp (s, "r3") == 0 ||
1232 strcmp (s, "r4") == 0 ||
1233 strcmp (s, "r5") == 0 ||
1234 strcmp (s, "r6") == 0 ||
1235 strcmp (s, "r7") == 0)
1236 emitcode ("mov", "%s,%s",
1237 aop->aopu.aop_reg[offset]->dname, s);
1239 emitcode ("mov", "%s,%s",
1240 aop->aopu.aop_reg[offset]->name, s);
1247 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1248 "aopPut writing to code space");
1252 while (offset > aop->coff)
1255 emitcode ("inc", "dptr");
1258 while (offset < aop->coff)
1261 emitcode ("lcall", "__decdptr");
1266 /* if not in accumulater */
1269 emitcode ("movx", "@dptr,a");
1274 while (offset > aop->coff)
1277 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1279 while (offset < aop->coff)
1282 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1289 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1295 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1297 else if (strcmp (s, "r0") == 0 ||
1298 strcmp (s, "r1") == 0 ||
1299 strcmp (s, "r2") == 0 ||
1300 strcmp (s, "r3") == 0 ||
1301 strcmp (s, "r4") == 0 ||
1302 strcmp (s, "r5") == 0 ||
1303 strcmp (s, "r6") == 0 ||
1304 strcmp (s, "r7") == 0)
1307 sprintf (buffer, "a%s", s);
1308 emitcode ("mov", "@%s,%s",
1309 aop->aopu.aop_ptr->name, buffer);
1312 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1317 if (strcmp (s, "a") == 0)
1318 emitcode ("push", "acc");
1322 emitcode ("push", "acc");
1324 emitcode ("push", s);
1330 /* if bit variable */
1331 if (!aop->aopu.aop_dir)
1333 emitcode ("clr", "a");
1334 emitcode ("rlc", "a");
1339 emitcode ("clr", "%s", aop->aopu.aop_dir);
1341 emitcode ("setb", "%s", aop->aopu.aop_dir);
1342 else if (!strcmp (s, "c"))
1343 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1346 if (strcmp (s, "a"))
1351 /* set C, if a >= 1 */
1352 emitcode ("add", "a,#0xff");
1353 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1361 if (strcmp (aop->aopu.aop_str[offset], s) ||
1363 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1368 if (!offset && (strcmp (s, "acc") == 0) &&
1372 if (strcmp (aop->aopu.aop_str[offset], s) &&
1374 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1378 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1379 "aopPut got unsupported aop->type");
1387 /*-----------------------------------------------------------------*/
1388 /* pointToEnd :- points to the last byte of the operand */
1389 /*-----------------------------------------------------------------*/
1391 pointToEnd (asmop * aop)
1397 aop->coff = count = (aop->size - 1);
1403 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1407 emitcode ("inc", "dptr");
1414 /*-----------------------------------------------------------------*/
1415 /* reAdjustPreg - points a register back to where it should */
1416 /*-----------------------------------------------------------------*/
1418 reAdjustPreg (asmop * aop)
1420 if ((aop->coff==0) || aop->size <= 1)
1428 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1433 emitcode ("lcall", "__decdptr");
1440 #define AOP(op) op->aop
1441 #define AOP_TYPE(op) AOP(op)->type
1442 #define AOP_SIZE(op) AOP(op)->size
1443 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1444 AOP_TYPE(x) == AOP_R0))
1446 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1447 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1449 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1450 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1451 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1454 /*-----------------------------------------------------------------*/
1455 /* opIsGptr: returns non-zero if the passed operand is */
1456 /* a generic pointer type. */
1457 /*-----------------------------------------------------------------*/
1459 opIsGptr (operand * op)
1461 sym_link *type = operandType (op);
1463 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1470 /*-----------------------------------------------------------------*/
1471 /* getDataSize - get the operand data size */
1472 /*-----------------------------------------------------------------*/
1474 getDataSize (operand * op)
1477 size = AOP_SIZE (op);
1478 if (size == GPTRSIZE)
1480 sym_link *type = operandType (op);
1481 if (IS_GENPTR (type))
1483 /* generic pointer; arithmetic operations
1484 * should ignore the high byte (pointer type).
1492 /*-----------------------------------------------------------------*/
1493 /* outAcc - output Acc */
1494 /*-----------------------------------------------------------------*/
1496 outAcc (operand * result)
1499 size = getDataSize (result);
1502 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1505 /* unsigned or positive */
1508 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1513 /*-----------------------------------------------------------------*/
1514 /* outBitC - output a bit C */
1515 /*-----------------------------------------------------------------*/
1517 outBitC (operand * result)
1519 /* if the result is bit */
1520 if (AOP_TYPE (result) == AOP_CRY)
1521 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1524 emitcode ("clr", "a");
1525 emitcode ("rlc", "a");
1530 /*-----------------------------------------------------------------*/
1531 /* toBoolean - emit code for orl a,operator(sizeop) */
1532 /*-----------------------------------------------------------------*/
1534 toBoolean (operand * oper)
1536 int size = AOP_SIZE (oper) - 1;
1538 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1540 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1544 /*-----------------------------------------------------------------*/
1545 /* genNot - generate code for ! operation */
1546 /*-----------------------------------------------------------------*/
1552 D(emitcode ("; genNot",""));
1554 /* assign asmOps to operand & result */
1555 aopOp (IC_LEFT (ic), ic, FALSE);
1556 aopOp (IC_RESULT (ic), ic, TRUE);
1558 /* if in bit space then a special case */
1559 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1561 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1562 emitcode ("cpl", "c");
1563 outBitC (IC_RESULT (ic));
1567 toBoolean (IC_LEFT (ic));
1569 tlbl = newiTempLabel (NULL);
1570 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1571 emitcode ("", "%05d$:", tlbl->key + 100);
1572 outBitC (IC_RESULT (ic));
1575 /* release the aops */
1576 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1577 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1581 /*-----------------------------------------------------------------*/
1582 /* genCpl - generate code for complement */
1583 /*-----------------------------------------------------------------*/
1591 D(emitcode ("; genCpl",""));
1593 /* assign asmOps to operand & result */
1594 aopOp (IC_LEFT (ic), ic, FALSE);
1595 aopOp (IC_RESULT (ic), ic, TRUE);
1597 /* special case if in bit space */
1598 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1600 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1602 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1603 emitcode ("cpl", "c");
1604 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1608 tlbl=newiTempLabel(NULL);
1609 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1610 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1611 IS_AOP_PREG (IC_LEFT (ic)))
1613 emitcode ("cjne", "%s,#0x01,%05d$",
1614 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1619 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1621 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1623 emitcode ("", "%05d$:", tlbl->key + 100);
1624 outBitC (IC_RESULT(ic));
1628 size = AOP_SIZE (IC_RESULT (ic));
1631 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1633 emitcode ("cpl", "a");
1634 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1639 /* release the aops */
1640 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1641 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1644 /*-----------------------------------------------------------------*/
1645 /* genUminusFloat - unary minus for floating points */
1646 /*-----------------------------------------------------------------*/
1648 genUminusFloat (operand * op, operand * result)
1650 int size, offset = 0;
1653 D(emitcode ("; genUminusFloat",""));
1655 /* for this we just copy and then flip the bit */
1657 size = AOP_SIZE (op) - 1;
1661 aopPut (AOP (result),
1662 aopGet (AOP (op), offset, FALSE, FALSE),
1664 isOperandVolatile (result, FALSE));
1668 l = aopGet (AOP (op), offset, FALSE, FALSE);
1672 emitcode ("cpl", "acc.7");
1673 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1676 /*-----------------------------------------------------------------*/
1677 /* genUminus - unary minus code generation */
1678 /*-----------------------------------------------------------------*/
1680 genUminus (iCode * ic)
1683 sym_link *optype, *rtype;
1686 D(emitcode ("; genUminus",""));
1689 aopOp (IC_LEFT (ic), ic, FALSE);
1690 aopOp (IC_RESULT (ic), ic, TRUE);
1692 /* if both in bit space then special
1694 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1695 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1698 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1699 emitcode ("cpl", "c");
1700 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1704 optype = operandType (IC_LEFT (ic));
1705 rtype = operandType (IC_RESULT (ic));
1707 /* if float then do float stuff */
1708 if (IS_FLOAT (optype))
1710 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1714 /* otherwise subtract from zero */
1715 size = AOP_SIZE (IC_LEFT (ic));
1720 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1721 if (!strcmp (l, "a"))
1725 emitcode ("cpl", "a");
1726 emitcode ("addc", "a,#0");
1732 emitcode ("clr", "a");
1733 emitcode ("subb", "a,%s", l);
1735 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1738 /* if any remaining bytes in the result */
1739 /* we just need to propagate the sign */
1740 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1742 emitcode ("rlc", "a");
1743 emitcode ("subb", "a,acc");
1745 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1749 /* release the aops */
1750 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1751 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1754 /*-----------------------------------------------------------------*/
1755 /* saveRegisters - will look for a call and save the registers */
1756 /*-----------------------------------------------------------------*/
1758 saveRegisters (iCode * lic)
1765 for (ic = lic; ic; ic = ic->next)
1766 if (ic->op == CALL || ic->op == PCALL)
1771 fprintf (stderr, "found parameter push with no function call\n");
1775 /* if the registers have been saved already or don't need to be then
1779 if (IS_SYMOP(IC_LEFT(ic)) &&
1780 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1781 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1784 /* safe the registers in use at this time but skip the
1785 ones for the result */
1786 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1787 mcs51_rUmaskForOp (IC_RESULT(ic)));
1790 if (options.useXstack)
1792 if (bitVectBitValue (rsave, R0_IDX))
1793 emitcode ("mov", "b,r0");
1794 emitcode ("mov", "r0,%s", spname);
1795 for (i = 0; i < mcs51_nRegs; i++)
1797 if (bitVectBitValue (rsave, i))
1800 emitcode ("mov", "a,b");
1802 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1803 emitcode ("movx", "@r0,a");
1804 emitcode ("inc", "r0");
1807 emitcode ("mov", "%s,r0", spname);
1808 if (bitVectBitValue (rsave, R0_IDX))
1809 emitcode ("mov", "r0,b");
1812 for (i = 0; i < mcs51_nRegs; i++)
1814 if (bitVectBitValue (rsave, i))
1815 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1819 /*-----------------------------------------------------------------*/
1820 /* unsaveRegisters - pop the pushed registers */
1821 /*-----------------------------------------------------------------*/
1823 unsaveRegisters (iCode * ic)
1828 /* restore the registers in use at this time but skip the
1829 ones for the result */
1830 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1831 mcs51_rUmaskForOp (IC_RESULT(ic)));
1833 if (options.useXstack)
1835 emitcode ("mov", "r0,%s", spname);
1836 for (i = mcs51_nRegs; i >= 0; i--)
1838 if (bitVectBitValue (rsave, i))
1840 emitcode ("dec", "r0");
1841 emitcode ("movx", "a,@r0");
1843 emitcode ("mov", "b,a");
1845 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1849 emitcode ("mov", "%s,r0", spname);
1850 if (bitVectBitValue (rsave, R0_IDX))
1851 emitcode ("mov", "r0,b");
1854 for (i = mcs51_nRegs; i >= 0; i--)
1856 if (bitVectBitValue (rsave, i))
1857 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1863 /*-----------------------------------------------------------------*/
1865 /*-----------------------------------------------------------------*/
1867 pushSide (operand * oper, int size)
1872 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1873 if (AOP_TYPE (oper) != AOP_REG &&
1874 AOP_TYPE (oper) != AOP_DIR &&
1878 emitcode ("push", "acc");
1881 emitcode ("push", "%s", l);
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue - */
1887 /*-----------------------------------------------------------------*/
1889 assignResultValue (operand * oper)
1892 int size = AOP_SIZE (oper);
1895 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1901 /*-----------------------------------------------------------------*/
1902 /* genXpush - pushes onto the external stack */
1903 /*-----------------------------------------------------------------*/
1905 genXpush (iCode * ic)
1907 asmop *aop = newAsmop (0);
1909 int size, offset = 0;
1911 D(emitcode ("; genXpush",""));
1913 aopOp (IC_LEFT (ic), ic, FALSE);
1914 r = getFreePtr (ic, &aop, FALSE);
1917 emitcode ("mov", "%s,_spx", r->name);
1919 size = AOP_SIZE (IC_LEFT (ic));
1923 char *l = aopGet (AOP (IC_LEFT (ic)),
1924 offset++, FALSE, FALSE);
1926 emitcode ("movx", "@%s,a", r->name);
1927 emitcode ("inc", "%s", r->name);
1932 emitcode ("mov", "_spx,%s", r->name);
1934 freeAsmop (NULL, aop, ic, TRUE);
1935 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1938 /*-----------------------------------------------------------------*/
1939 /* genIpush - genrate code for pushing this gets a little complex */
1940 /*-----------------------------------------------------------------*/
1942 genIpush (iCode * ic)
1944 int size, offset = 0;
1947 D(emitcode ("; genIpush",""));
1949 /* if this is not a parm push : ie. it is spill push
1950 and spill push is always done on the local stack */
1954 /* and the item is spilt then do nothing */
1955 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1958 aopOp (IC_LEFT (ic), ic, FALSE);
1959 size = AOP_SIZE (IC_LEFT (ic));
1960 /* push it on the stack */
1963 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1969 emitcode ("push", "%s", l);
1974 /* this is a paramter push: in this case we call
1975 the routine to find the call and save those
1976 registers that need to be saved */
1979 /* if use external stack then call the external
1980 stack pushing routine */
1981 if (options.useXstack)
1987 /* then do the push */
1988 aopOp (IC_LEFT (ic), ic, FALSE);
1991 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1992 size = AOP_SIZE (IC_LEFT (ic));
1996 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1997 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1998 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2002 emitcode ("push", "acc");
2005 emitcode ("push", "%s", l);
2008 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2011 /*-----------------------------------------------------------------*/
2012 /* genIpop - recover the registers: can happen only for spilling */
2013 /*-----------------------------------------------------------------*/
2015 genIpop (iCode * ic)
2019 D(emitcode ("; genIpop",""));
2021 /* if the temp was not pushed then */
2022 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2025 aopOp (IC_LEFT (ic), ic, FALSE);
2026 size = AOP_SIZE (IC_LEFT (ic));
2027 offset = (size - 1);
2029 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2032 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2035 /*-----------------------------------------------------------------*/
2036 /* unsaveRBank - restores the resgister bank from stack */
2037 /*-----------------------------------------------------------------*/
2039 unsaveRBank (int bank, iCode * ic, bool popPsw)
2045 if (options.useXstack)
2049 /* Assume r0 is available for use. */
2050 r = mcs51_regWithIdx (R0_IDX);;
2055 r = getFreePtr (ic, &aop, FALSE);
2057 emitcode ("mov", "%s,_spx", r->name);
2062 if (options.useXstack)
2064 emitcode ("movx", "a,@%s", r->name);
2065 emitcode ("mov", "psw,a");
2066 emitcode ("dec", "%s", r->name);
2070 emitcode ("pop", "psw");
2074 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2076 if (options.useXstack)
2078 emitcode ("movx", "a,@%s", r->name);
2079 emitcode ("mov", "(%s+%d),a",
2080 regs8051[i].base, 8 * bank + regs8051[i].offset);
2081 emitcode ("dec", "%s", r->name);
2085 emitcode ("pop", "(%s+%d)",
2086 regs8051[i].base, 8 * bank + regs8051[i].offset);
2089 if (options.useXstack)
2091 emitcode ("mov", "_spx,%s", r->name);
2096 freeAsmop (NULL, aop, ic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* saveRBank - saves an entire register bank on the stack */
2102 /*-----------------------------------------------------------------*/
2104 saveRBank (int bank, iCode * ic, bool pushPsw)
2110 if (options.useXstack)
2114 /* Assume r0 is available for use. */
2115 r = mcs51_regWithIdx (R0_IDX);;
2120 r = getFreePtr (ic, &aop, FALSE);
2122 emitcode ("mov", "%s,_spx", r->name);
2125 for (i = 0; i < mcs51_nRegs; i++)
2127 if (options.useXstack)
2129 emitcode ("inc", "%s", r->name);
2130 emitcode ("mov", "a,(%s+%d)",
2131 regs8051[i].base, 8 * bank + regs8051[i].offset);
2132 emitcode ("movx", "@%s,a", r->name);
2135 emitcode ("push", "(%s+%d)",
2136 regs8051[i].base, 8 * bank + regs8051[i].offset);
2141 if (options.useXstack)
2143 emitcode ("mov", "a,psw");
2144 emitcode ("movx", "@%s,a", r->name);
2145 emitcode ("inc", "%s", r->name);
2146 emitcode ("mov", "_spx,%s", r->name);
2151 emitcode ("push", "psw");
2154 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2159 freeAsmop (NULL, aop, ic, TRUE);
2168 /*-----------------------------------------------------------------*/
2169 /* genSend - gen code for SEND */
2170 /*-----------------------------------------------------------------*/
2171 static void genSend(set *sendSet)
2176 for (sic = setFirstItem (_G.sendSet); sic;
2177 sic = setNextItem (_G.sendSet)) {
2178 int size, offset = 0;
2179 aopOp (IC_LEFT (sic), sic, FALSE);
2180 size = AOP_SIZE (IC_LEFT (sic));
2182 if (sic->argreg == 1) {
2184 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2186 if (strcmp (l, fReturn[offset]))
2187 emitcode ("mov", "%s,%s", fReturn[offset], l);
2193 emitcode ("mov","b1_%d,%s",rb1_count++,
2194 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2197 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2201 /*-----------------------------------------------------------------*/
2202 /* genCall - generates a call statement */
2203 /*-----------------------------------------------------------------*/
2205 genCall (iCode * ic)
2208 // bool restoreBank = FALSE;
2209 bool swapBanks = FALSE;
2211 D(emitcode("; genCall",""));
2213 dtype = operandType (IC_LEFT (ic));
2214 /* if send set is not empty the assign */
2217 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2218 genSend(reverseSet(_G.sendSet));
2220 genSend(_G.sendSet);
2226 /* if we are calling a not _naked function that is not using
2227 the same register bank then we need to save the
2228 destination registers on the stack */
2229 dtype = operandType (IC_LEFT (ic));
2230 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2231 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2232 !IFFUNC_ISISR (dtype))
2237 /* if caller saves & we have not saved then */
2243 emitcode ("mov", "psw,#0x%02x",
2244 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2248 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2249 OP_SYMBOL (IC_LEFT (ic))->rname :
2250 OP_SYMBOL (IC_LEFT (ic))->name));
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2258 /* if we need assign a result value */
2259 if ((IS_ITEMP (IC_RESULT (ic)) &&
2260 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2261 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2262 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2263 IS_TRUE_SYMOP (IC_RESULT (ic)))
2267 aopOp (IC_RESULT (ic), ic, FALSE);
2270 assignResultValue (IC_RESULT (ic));
2272 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2275 /* adjust the stack for parameters if
2280 if (ic->parmBytes > 3)
2282 emitcode ("mov", "a,%s", spname);
2283 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2284 emitcode ("mov", "%s,a", spname);
2287 for (i = 0; i < ic->parmBytes; i++)
2288 emitcode ("dec", "%s", spname);
2291 /* if we hade saved some registers then unsave them */
2292 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2293 unsaveRegisters (ic);
2295 // /* if register bank was saved then pop them */
2297 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2300 /*-----------------------------------------------------------------*/
2301 /* -10l - generates a call by pointer statement */
2302 /*-----------------------------------------------------------------*/
2304 genPcall (iCode * ic)
2307 symbol *rlbl = newiTempLabel (NULL);
2308 // bool restoreBank=FALSE;
2309 bool swapBanks = FALSE;
2311 D(emitcode("; genPCall",""));
2313 /* if caller saves & we have not saved then */
2317 /* if we are calling a not _naked function that is not using
2318 the same register bank then we need to save the
2319 destination registers on the stack */
2320 dtype = operandType (IC_LEFT (ic))->next;
2321 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2322 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2323 !IFFUNC_ISISR (dtype))
2325 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2326 // restoreBank=TRUE;
2328 // need caution message to user here
2331 /* push the return address on to the stack */
2332 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2333 emitcode ("push", "acc");
2334 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2335 emitcode ("push", "acc");
2337 /* now push the calling address */
2338 aopOp (IC_LEFT (ic), ic, FALSE);
2340 pushSide (IC_LEFT (ic), FPTRSIZE);
2342 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2344 /* if send set is not empty the assign */
2347 genSend(reverseSet(_G.sendSet));
2353 emitcode ("mov", "psw,#0x%02x",
2354 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2358 emitcode ("ret", "");
2359 emitcode ("", "%05d$:", (rlbl->key + 100));
2364 emitcode ("mov", "psw,#0x%02x",
2365 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2368 /* if we need assign a result value */
2369 if ((IS_ITEMP (IC_RESULT (ic)) &&
2370 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2371 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2372 IS_TRUE_SYMOP (IC_RESULT (ic)))
2376 aopOp (IC_RESULT (ic), ic, FALSE);
2379 assignResultValue (IC_RESULT (ic));
2381 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2384 /* adjust the stack for parameters if
2389 if (ic->parmBytes > 3)
2391 emitcode ("mov", "a,%s", spname);
2392 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2393 emitcode ("mov", "%s,a", spname);
2396 for (i = 0; i < ic->parmBytes; i++)
2397 emitcode ("dec", "%s", spname);
2401 // /* if register bank was saved then unsave them */
2403 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2405 /* if we hade saved some registers then
2407 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2408 unsaveRegisters (ic);
2411 /*-----------------------------------------------------------------*/
2412 /* resultRemat - result is rematerializable */
2413 /*-----------------------------------------------------------------*/
2415 resultRemat (iCode * ic)
2417 if (SKIP_IC (ic) || ic->op == IFX)
2420 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2422 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2423 if (sym->remat && !POINTER_SET (ic))
2430 #if defined(__BORLANDC__) || defined(_MSC_VER)
2431 #define STRCASECMP stricmp
2433 #define STRCASECMP strcasecmp
2436 /*-----------------------------------------------------------------*/
2437 /* inExcludeList - return 1 if the string is in exclude Reg list */
2438 /*-----------------------------------------------------------------*/
2440 regsCmp(void *p1, void *p2)
2442 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2446 inExcludeList (char *s)
2448 const char *p = setFirstItem(options.excludeRegsSet);
2450 if (p == NULL || STRCASECMP(p, "none") == 0)
2454 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2457 /*-----------------------------------------------------------------*/
2458 /* genFunction - generated code for function entry */
2459 /*-----------------------------------------------------------------*/
2461 genFunction (iCode * ic)
2463 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2465 bool switchedPSW = FALSE;
2466 int calleesaves_saved_register = -1;
2467 int stackAdjust = sym->stack;
2468 int accIsFree = sym->recvSize < 4;
2469 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2472 /* create the function header */
2473 emitcode (";", "-----------------------------------------");
2474 emitcode (";", " function %s", sym->name);
2475 emitcode (";", "-----------------------------------------");
2477 emitcode ("", "%s:", sym->rname);
2478 ftype = operandType (IC_LEFT (ic));
2479 _G.currentFunc = sym;
2481 if (IFFUNC_ISNAKED(ftype))
2483 emitcode(";", "naked function: no prologue.");
2487 /* here we need to generate the equates for the
2488 register bank if required */
2489 if (FUNC_REGBANK (ftype) != rbank)
2493 rbank = FUNC_REGBANK (ftype);
2494 for (i = 0; i < mcs51_nRegs; i++)
2496 if (strcmp (regs8051[i].base, "0") == 0)
2497 emitcode ("", "%s = 0x%02x",
2499 8 * rbank + regs8051[i].offset);
2501 emitcode ("", "%s = %s + 0x%02x",
2504 8 * rbank + regs8051[i].offset);
2508 /* if this is an interrupt service routine then
2509 save acc, b, dpl, dph */
2510 if (IFFUNC_ISISR (sym->type))
2513 if (!inExcludeList ("acc"))
2514 emitcode ("push", "acc");
2515 if (!inExcludeList ("b"))
2516 emitcode ("push", "b");
2517 if (!inExcludeList ("dpl"))
2518 emitcode ("push", "dpl");
2519 if (!inExcludeList ("dph"))
2520 emitcode ("push", "dph");
2521 /* if this isr has no bank i.e. is going to
2522 run with bank 0 , then we need to save more
2524 if (!FUNC_REGBANK (sym->type))
2527 /* if this function does not call any other
2528 function then we can be economical and
2529 save only those registers that are used */
2530 if (!IFFUNC_HASFCALL(sym->type))
2534 /* if any registers used */
2537 /* save the registers used */
2538 for (i = 0; i < sym->regsUsed->size; i++)
2540 if (bitVectBitValue (sym->regsUsed, i))
2541 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2548 /* this function has a function call. We cannot
2549 determines register usage so we will have to push the
2551 saveRBank (0, ic, FALSE);
2552 if (options.parms_in_bank1) {
2554 for (i=0; i < 8 ; i++ ) {
2555 emitcode ("push","%s",rb1regs[i]);
2562 /* This ISR uses a non-zero bank.
2564 * We assume that the bank is available for our
2567 * However, if this ISR calls a function which uses some
2568 * other bank, we must save that bank entirely.
2570 unsigned long banksToSave = 0;
2572 if (IFFUNC_HASFCALL(sym->type))
2575 #define MAX_REGISTER_BANKS 4
2580 for (i = ic; i; i = i->next)
2582 if (i->op == ENDFUNCTION)
2584 /* we got to the end OK. */
2592 dtype = operandType (IC_LEFT(i));
2594 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2596 /* Mark this bank for saving. */
2597 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2599 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2603 banksToSave |= (1 << FUNC_REGBANK(dtype));
2606 /* And note that we don't need to do it in
2614 /* This is a mess; we have no idea what
2615 * register bank the called function might
2618 * The only thing I can think of to do is
2619 * throw a warning and hope.
2621 werror(W_FUNCPTR_IN_USING_ISR);
2625 if (banksToSave && options.useXstack)
2627 /* Since we aren't passing it an ic,
2628 * saveRBank will assume r0 is available to abuse.
2630 * So switch to our (trashable) bank now, so
2631 * the caller's R0 isn't trashed.
2633 emitcode ("push", "psw");
2634 emitcode ("mov", "psw,#0x%02x",
2635 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2639 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2641 if (banksToSave & (1 << ix))
2643 saveRBank(ix, NULL, FALSE);
2647 // TODO: this needs a closer look
2648 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2651 /* Set the register bank to the desired value if nothing else */
2652 /* has done so yet. */
2655 emitcode ("push", "psw");
2656 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2661 /* This is a non-ISR function. The caller has already switched register */
2662 /* banks, if necessary, so just handle the callee-saves option. */
2664 /* if callee-save to be used for this function
2665 then save the registers being used in this function */
2666 if (IFFUNC_CALLEESAVES(sym->type))
2670 /* if any registers used */
2673 /* save the registers used */
2674 for (i = 0; i < sym->regsUsed->size; i++)
2676 if (bitVectBitValue (sym->regsUsed, i))
2678 /* remember one saved register for later usage */
2679 if (calleesaves_saved_register < 0)
2680 calleesaves_saved_register = i;
2681 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2690 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2693 if (options.useXstack)
2696 emitcode ("push", "acc");
2697 emitcode ("mov", "r0,%s", spname);
2698 emitcode ("mov", "a,_bp");
2699 emitcode ("movx", "@r0,a");
2700 emitcode ("inc", "%s", spname);
2702 emitcode ("pop", "acc");
2706 /* set up the stack */
2707 emitcode ("push", "_bp"); /* save the callers stack */
2709 emitcode ("mov", "_bp,%s", spname);
2712 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2713 /* before setting up the stack frame completely. */
2714 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2716 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2720 if (rsym && rsym->regType == REG_CND)
2722 if (rsym && (rsym->accuse || rsym->ruonly))
2724 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2725 rsym = rsym->usl.spillLoc;
2728 /* If the RECEIVE operand immediately spills to the first entry on the */
2729 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2730 /* rather than the usual @r0/r1 machinations. */
2731 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2735 _G.current_iCode = ric;
2736 D(emitcode ("; genReceive",""));
2737 for (ofs=0; ofs < sym->recvSize; ofs++)
2739 if (!strcmp (fReturn[ofs], "a"))
2740 emitcode ("push", "acc");
2742 emitcode ("push", fReturn[ofs]);
2744 stackAdjust -= sym->recvSize;
2747 assert (stackAdjust>=0);
2750 _G.current_iCode = ic;
2754 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2755 /* to free up the accumulator. */
2756 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2760 _G.current_iCode = ric;
2761 D(emitcode ("; genReceive",""));
2762 for (ofs=0; ofs < sym->recvSize; ofs++)
2764 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2766 _G.current_iCode = ic;
2772 /* adjust the stack for the function */
2776 int i = stackAdjust;
2778 werror (W_STACK_OVERFLOW, sym->name);
2780 if (i > 3 && accIsFree)
2783 emitcode ("mov", "a,sp");
2784 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2785 emitcode ("mov", "sp,a");
2790 /* The accumulator is not free, so we will need another register */
2791 /* to clobber. No need to worry about a possible conflict with */
2792 /* the above early RECEIVE optimizations since they would have */
2793 /* freed the accumulator if they were generated. */
2795 if (IFFUNC_CALLEESAVES(sym->type))
2797 /* if it's a callee-saves function we need a saved register */
2798 if (calleesaves_saved_register >= 0)
2800 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2801 emitcode ("mov", "a,sp");
2802 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2803 emitcode ("mov", "sp,a");
2804 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2807 /* do it the hard way */
2809 emitcode ("inc", "sp");
2813 /* not callee-saves, we can clobber r0 */
2814 emitcode ("mov", "r0,a");
2815 emitcode ("mov", "a,sp");
2816 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2817 emitcode ("mov", "sp,a");
2818 emitcode ("mov", "a,r0");
2823 emitcode ("inc", "sp");
2830 emitcode ("push", "acc");
2831 emitcode ("mov", "a,_spx");
2832 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2833 emitcode ("mov", "_spx,a");
2835 emitcode ("pop", "acc");
2838 /* if critical function then turn interrupts off */
2839 if (IFFUNC_ISCRITICAL (ftype))
2841 symbol *tlbl = newiTempLabel (NULL);
2842 emitcode ("setb", "c");
2843 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2844 emitcode ("clr", "c");
2845 emitcode ("", "%05d$:", (tlbl->key + 100));
2846 emitcode ("push", "psw"); /* save old ea via c in psw */
2850 /*-----------------------------------------------------------------*/
2851 /* genEndFunction - generates epilogue for functions */
2852 /*-----------------------------------------------------------------*/
2854 genEndFunction (iCode * ic)
2856 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2857 lineNode *lnp = lineCurr;
2859 bitVect *regsUsedPrologue;
2860 bitVect *regsUnneeded;
2863 _G.currentFunc = NULL;
2864 if (IFFUNC_ISNAKED(sym->type))
2866 emitcode(";", "naked function: no epilogue.");
2870 if (IFFUNC_ISCRITICAL (sym->type))
2872 emitcode ("pop", "psw"); /* restore ea via c in psw */
2873 emitcode ("mov", "ea,c");
2876 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2878 emitcode ("mov", "%s,_bp", spname);
2881 /* if use external stack but some variables were
2882 added to the local stack then decrement the
2884 if (options.useXstack && sym->stack)
2886 emitcode ("mov", "a,sp");
2887 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2888 emitcode ("mov", "sp,a");
2892 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2894 if (options.useXstack)
2896 emitcode ("mov", "r0,%s", spname);
2897 emitcode ("movx", "a,@r0");
2898 emitcode ("mov", "_bp,a");
2899 emitcode ("dec", "%s", spname);
2903 emitcode ("pop", "_bp");
2907 /* restore the register bank */
2908 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2910 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2911 || !options.useXstack)
2913 /* Special case of ISR using non-zero bank with useXstack
2916 emitcode ("pop", "psw");
2920 if (IFFUNC_ISISR (sym->type))
2923 /* now we need to restore the registers */
2924 /* if this isr has no bank i.e. is going to
2925 run with bank 0 , then we need to save more
2927 if (!FUNC_REGBANK (sym->type))
2929 /* if this function does not call any other
2930 function then we can be economical and
2931 save only those registers that are used */
2932 if (!IFFUNC_HASFCALL(sym->type))
2936 /* if any registers used */
2939 /* save the registers used */
2940 for (i = sym->regsUsed->size; i >= 0; i--)
2942 if (bitVectBitValue (sym->regsUsed, i))
2943 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2949 if (options.parms_in_bank1) {
2951 for (i = 7 ; i >= 0 ; i-- ) {
2952 emitcode ("pop","%s",rb1regs[i]);
2955 /* this function has a function call cannot
2956 determines register usage so we will have to pop the
2958 unsaveRBank (0, ic, FALSE);
2963 /* This ISR uses a non-zero bank.
2965 * Restore any register banks saved by genFunction
2968 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2971 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2973 if (savedBanks & (1 << ix))
2975 unsaveRBank(ix, NULL, FALSE);
2979 if (options.useXstack)
2981 /* Restore bank AFTER calling unsaveRBank,
2982 * since it can trash r0.
2984 emitcode ("pop", "psw");
2988 if (!inExcludeList ("dph"))
2989 emitcode ("pop", "dph");
2990 if (!inExcludeList ("dpl"))
2991 emitcode ("pop", "dpl");
2992 if (!inExcludeList ("b"))
2993 emitcode ("pop", "b");
2994 if (!inExcludeList ("acc"))
2995 emitcode ("pop", "acc");
2997 /* if debug then send end of function */
2998 if (options.debug && currFunc)
3001 emitcode ("", "C$%s$%d$%d$%d ==.",
3002 FileBaseName (ic->filename), currFunc->lastLine,
3003 ic->level, ic->block);
3004 if (IS_STATIC (currFunc->etype))
3005 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3007 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3011 emitcode ("reti", "");
3015 if (IFFUNC_CALLEESAVES(sym->type))
3019 /* if any registers used */
3022 /* save the registers used */
3023 for (i = sym->regsUsed->size; i >= 0; i--)
3025 if (bitVectBitValue (sym->regsUsed, i) ||
3026 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3027 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3030 else if (mcs51_ptrRegReq)
3032 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3033 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3038 /* if debug then send end of function */
3039 if (options.debug && currFunc)
3042 emitcode ("", "C$%s$%d$%d$%d ==.",
3043 FileBaseName (ic->filename), currFunc->lastLine,
3044 ic->level, ic->block);
3045 if (IS_STATIC (currFunc->etype))
3046 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3048 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3052 emitcode ("ret", "");
3055 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3058 /* If this was an interrupt handler using bank 0 that called another */
3059 /* function, then all registers must be saved; nothing to optimized. */
3060 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3061 && !FUNC_REGBANK(sym->type))
3064 /* There are no push/pops to optimize if not callee-saves or ISR */
3065 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3068 /* If there were stack parameters, we cannot optimize without also */
3069 /* fixing all of the stack offsets; this is too dificult to consider. */
3070 if (FUNC_HASSTACKPARM(sym->type))
3073 /* Compute the registers actually used */
3074 regsUsed = newBitVect (mcs51_nRegs);
3075 regsUsedPrologue = newBitVect (mcs51_nRegs);
3078 if (lnp->ic && lnp->ic->op == FUNCTION)
3079 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3081 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3083 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3084 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3091 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3092 && !bitVectBitValue (regsUsed, CND_IDX))
3094 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3095 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3097 bitVectUnSetBit (regsUsed, CND_IDX);
3100 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3102 /* If this was an interrupt handler that called another function */
3103 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3104 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3106 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3107 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3108 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3109 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3110 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3113 /* Remove the unneeded push/pops */
3114 regsUnneeded = newBitVect (mcs51_nRegs);
3117 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3119 if (!strncmp(lnp->line, "push", 4))
3121 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3122 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3124 connectLine (lnp->prev, lnp->next);
3125 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3128 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3130 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3131 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3133 connectLine (lnp->prev, lnp->next);
3134 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3141 for (idx = 0; idx < regsUnneeded->size; idx++)
3142 if (bitVectBitValue (regsUnneeded, idx))
3143 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3145 freeBitVect (regsUnneeded);
3146 freeBitVect (regsUsed);
3147 freeBitVect (regsUsedPrologue);
3150 /*-----------------------------------------------------------------*/
3151 /* genRet - generate code for return statement */
3152 /*-----------------------------------------------------------------*/
3156 int size, offset = 0, pushed = 0;
3158 D(emitcode ("; genRet",""));
3160 /* if we have no return value then
3161 just generate the "ret" */
3165 /* we have something to return then
3166 move the return value into place */
3167 aopOp (IC_LEFT (ic), ic, FALSE);
3168 size = AOP_SIZE (IC_LEFT (ic));
3173 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3176 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3178 emitcode ("push", "%s", l);
3183 l = aopGet (AOP (IC_LEFT (ic)), offset,
3185 if (strcmp (fReturn[offset], l))
3186 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3195 if (strcmp (fReturn[pushed], "a"))
3196 emitcode ("pop", fReturn[pushed]);
3198 emitcode ("pop", "acc");
3201 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3204 /* generate a jump to the return label
3205 if the next is not the return statement */
3206 if (!(ic->next && ic->next->op == LABEL &&
3207 IC_LABEL (ic->next) == returnLabel))
3209 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3213 /*-----------------------------------------------------------------*/
3214 /* genLabel - generates a label */
3215 /*-----------------------------------------------------------------*/
3217 genLabel (iCode * ic)
3219 /* special case never generate */
3220 if (IC_LABEL (ic) == entryLabel)
3223 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3226 /*-----------------------------------------------------------------*/
3227 /* genGoto - generates a ljmp */
3228 /*-----------------------------------------------------------------*/
3230 genGoto (iCode * ic)
3232 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3235 /*-----------------------------------------------------------------*/
3236 /* findLabelBackwards: walks back through the iCode chain looking */
3237 /* for the given label. Returns number of iCode instructions */
3238 /* between that label and given ic. */
3239 /* Returns zero if label not found. */
3240 /*-----------------------------------------------------------------*/
3242 findLabelBackwards (iCode * ic, int key)
3251 /* If we have any pushes or pops, we cannot predict the distance.
3252 I don't like this at all, this should be dealt with in the
3254 if (ic->op == IPUSH || ic->op == IPOP) {
3258 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3267 /*-----------------------------------------------------------------*/
3268 /* genPlusIncr :- does addition with increment if possible */
3269 /*-----------------------------------------------------------------*/
3271 genPlusIncr (iCode * ic)
3273 unsigned int icount;
3274 unsigned int size = getDataSize (IC_RESULT (ic));
3276 /* will try to generate an increment */
3277 /* if the right side is not a literal
3279 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3282 /* if the literal value of the right hand side
3283 is greater than 4 then it is not worth it */
3284 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3287 D(emitcode ("; genPlusIncr",""));
3289 /* if increment >=16 bits in register or direct space */
3290 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3291 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3299 /* If the next instruction is a goto and the goto target
3300 * is < 10 instructions previous to this, we can generate
3301 * jumps straight to that target.
3303 if (ic->next && ic->next->op == GOTO
3304 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3305 && labelRange <= 10)
3307 emitcode (";", "tail increment optimized");
3308 tlbl = IC_LABEL (ic->next);
3313 tlbl = newiTempLabel (NULL);
3316 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3317 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3318 IS_AOP_PREG (IC_RESULT (ic)))
3319 emitcode ("cjne", "%s,#0x00,%05d$",
3320 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3324 emitcode ("clr", "a");
3325 emitcode ("cjne", "a,%s,%05d$",
3326 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3330 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3333 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3334 IS_AOP_PREG (IC_RESULT (ic)))
3335 emitcode ("cjne", "%s,#0x00,%05d$",
3336 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3339 emitcode ("cjne", "a,%s,%05d$",
3340 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3343 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3347 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3348 IS_AOP_PREG (IC_RESULT (ic)))
3349 emitcode ("cjne", "%s,#0x00,%05d$",
3350 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3354 emitcode ("cjne", "a,%s,%05d$",
3355 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3358 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3363 emitcode ("", "%05d$:", tlbl->key + 100);
3368 /* if the sizes are greater than 1 then we cannot */
3369 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3370 AOP_SIZE (IC_LEFT (ic)) > 1)
3373 /* we can if the aops of the left & result match or
3374 if they are in registers and the registers are the
3376 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3381 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3382 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3383 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3389 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3398 /*-----------------------------------------------------------------*/
3399 /* outBitAcc - output a bit in acc */
3400 /*-----------------------------------------------------------------*/
3402 outBitAcc (operand * result)
3404 symbol *tlbl = newiTempLabel (NULL);
3405 /* if the result is a bit */
3406 if (AOP_TYPE (result) == AOP_CRY)
3408 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3412 emitcode ("jz", "%05d$", tlbl->key + 100);
3413 emitcode ("mov", "a,%s", one);
3414 emitcode ("", "%05d$:", tlbl->key + 100);
3419 /*-----------------------------------------------------------------*/
3420 /* genPlusBits - generates code for addition of two bits */
3421 /*-----------------------------------------------------------------*/
3423 genPlusBits (iCode * ic)
3425 D(emitcode ("; genPlusBits",""));
3427 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3429 symbol *lbl = newiTempLabel (NULL);
3430 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3431 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3432 emitcode ("cpl", "c");
3433 emitcode ("", "%05d$:", (lbl->key + 100));
3434 outBitC (IC_RESULT (ic));
3438 emitcode ("clr", "a");
3439 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3440 emitcode ("rlc", "a");
3441 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3442 emitcode ("addc", "a,#0x00");
3443 outAcc (IC_RESULT (ic));
3448 /* This is the original version of this code.
3450 * This is being kept around for reference,
3451 * because I am not entirely sure I got it right...
3454 adjustArithmeticResult (iCode * ic)
3456 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3457 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3458 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3459 aopPut (AOP (IC_RESULT (ic)),
3460 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3462 isOperandVolatile (IC_RESULT (ic), FALSE));
3464 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3465 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3466 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3467 aopPut (AOP (IC_RESULT (ic)),
3468 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3470 isOperandVolatile (IC_RESULT (ic), FALSE));
3472 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3473 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3474 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3475 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3476 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3479 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3480 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3484 /* This is the pure and virtuous version of this code.
3485 * I'm pretty certain it's right, but not enough to toss the old
3489 adjustArithmeticResult (iCode * ic)
3491 if (opIsGptr (IC_RESULT (ic)) &&
3492 opIsGptr (IC_LEFT (ic)) &&
3493 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3495 aopPut (AOP (IC_RESULT (ic)),
3496 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3498 isOperandVolatile (IC_RESULT (ic), FALSE));
3501 if (opIsGptr (IC_RESULT (ic)) &&
3502 opIsGptr (IC_RIGHT (ic)) &&
3503 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3505 aopPut (AOP (IC_RESULT (ic)),
3506 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3508 isOperandVolatile (IC_RESULT (ic), FALSE));
3511 if (opIsGptr (IC_RESULT (ic)) &&
3512 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3513 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3514 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3515 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3518 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3519 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3524 /*-----------------------------------------------------------------*/
3525 /* genPlus - generates code for addition */
3526 /*-----------------------------------------------------------------*/
3528 genPlus (iCode * ic)
3530 int size, offset = 0;
3533 asmop *leftOp, *rightOp;
3536 /* special cases :- */
3538 D(emitcode ("; genPlus",""));
3540 aopOp (IC_LEFT (ic), ic, FALSE);
3541 aopOp (IC_RIGHT (ic), ic, FALSE);
3542 aopOp (IC_RESULT (ic), ic, TRUE);
3544 /* if literal, literal on the right or
3545 if left requires ACC or right is already
3547 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3548 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3549 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3551 operand *t = IC_RIGHT (ic);
3552 IC_RIGHT (ic) = IC_LEFT (ic);
3556 /* if both left & right are in bit
3558 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3559 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3565 /* if left in bit space & right literal */
3566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3567 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3569 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3570 /* if result in bit space */
3571 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3573 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3574 emitcode ("cpl", "c");
3575 outBitC (IC_RESULT (ic));
3579 size = getDataSize (IC_RESULT (ic));
3582 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3583 emitcode ("addc", "a,#00");
3584 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3590 /* if I can do an increment instead
3591 of add then GOOD for ME */
3592 if (genPlusIncr (ic) == TRUE)
3595 size = getDataSize (IC_RESULT (ic));
3596 leftOp = AOP(IC_LEFT(ic));
3597 rightOp = AOP(IC_RIGHT(ic));
3600 /* if this is an add for an array access
3601 at a 256 byte boundary */
3603 && AOP_TYPE (op) == AOP_IMMD
3605 && IS_SPEC (OP_SYM_ETYPE (op))
3606 && SPEC_ABSA (OP_SYM_ETYPE (op))
3607 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3610 D(emitcode ("; genPlus aligned array",""));
3611 aopPut (AOP (IC_RESULT (ic)),
3612 aopGet (rightOp, 0, FALSE, FALSE),
3614 isOperandVolatile (IC_RESULT (ic), FALSE));
3616 if( 1 == getDataSize (IC_RIGHT (ic)) )
3618 aopPut (AOP (IC_RESULT (ic)),
3619 aopGet (leftOp, 1, FALSE, FALSE),
3621 isOperandVolatile (IC_RESULT (ic), FALSE));
3625 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3626 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3627 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3632 /* if the lower bytes of a literal are zero skip the addition */
3633 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3635 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3636 (skip_bytes+1 < size))
3641 D(emitcode ("; genPlus shortcut",""));
3646 if( offset >= skip_bytes )
3648 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3650 emitcode("mov", "b,a");
3651 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3652 emitcode("xch", "a,b");
3653 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3654 emitcode (add, "a,b");
3656 else if (aopGetUsesAcc (leftOp, offset))
3658 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3659 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3663 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3664 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3666 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3667 add = "addc"; /* further adds must propagate carry */
3671 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3672 isOperandVolatile (IC_RESULT (ic), FALSE))
3675 aopPut (AOP (IC_RESULT (ic)),
3676 aopGet (leftOp, offset, FALSE, FALSE),
3678 isOperandVolatile (IC_RESULT (ic), FALSE));
3684 adjustArithmeticResult (ic);
3687 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3688 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3689 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3692 /*-----------------------------------------------------------------*/
3693 /* genMinusDec :- does subtraction with deccrement if possible */
3694 /*-----------------------------------------------------------------*/
3696 genMinusDec (iCode * ic)
3698 unsigned int icount;
3699 unsigned int size = getDataSize (IC_RESULT (ic));
3701 /* will try to generate an increment */
3702 /* if the right side is not a literal
3704 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3707 /* if the literal value of the right hand side
3708 is greater than 4 then it is not worth it */
3709 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3712 D(emitcode ("; genMinusDec",""));
3714 /* if decrement >=16 bits in register or direct space */
3715 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3716 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3724 /* If the next instruction is a goto and the goto target
3725 * is <= 10 instructions previous to this, we can generate
3726 * jumps straight to that target.
3728 if (ic->next && ic->next->op == GOTO
3729 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3730 && labelRange <= 10)
3732 emitcode (";", "tail decrement optimized");
3733 tlbl = IC_LABEL (ic->next);
3738 tlbl = newiTempLabel (NULL);
3742 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3743 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3744 IS_AOP_PREG (IC_RESULT (ic)))
3745 emitcode ("cjne", "%s,#0xff,%05d$"
3746 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3750 emitcode ("mov", "a,#0xff");
3751 emitcode ("cjne", "a,%s,%05d$"
3752 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3755 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3758 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3759 IS_AOP_PREG (IC_RESULT (ic)))
3760 emitcode ("cjne", "%s,#0xff,%05d$"
3761 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3765 emitcode ("cjne", "a,%s,%05d$"
3766 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3769 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3773 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3774 IS_AOP_PREG (IC_RESULT (ic)))
3775 emitcode ("cjne", "%s,#0xff,%05d$"
3776 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3780 emitcode ("cjne", "a,%s,%05d$"
3781 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3784 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3788 emitcode ("", "%05d$:", tlbl->key + 100);
3793 /* if the sizes are greater than 1 then we cannot */
3794 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3795 AOP_SIZE (IC_LEFT (ic)) > 1)
3798 /* we can if the aops of the left & result match or
3799 if they are in registers and the registers are the
3801 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3805 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3813 /*-----------------------------------------------------------------*/
3814 /* addSign - complete with sign */
3815 /*-----------------------------------------------------------------*/
3817 addSign (operand * result, int offset, int sign)
3819 int size = (getDataSize (result) - offset);
3824 emitcode ("rlc", "a");
3825 emitcode ("subb", "a,acc");
3827 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3831 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3835 /*-----------------------------------------------------------------*/
3836 /* genMinusBits - generates code for subtraction of two bits */
3837 /*-----------------------------------------------------------------*/
3839 genMinusBits (iCode * ic)
3841 symbol *lbl = newiTempLabel (NULL);
3843 D(emitcode ("; genMinusBits",""));
3845 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3847 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3848 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3849 emitcode ("cpl", "c");
3850 emitcode ("", "%05d$:", (lbl->key + 100));
3851 outBitC (IC_RESULT (ic));
3855 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3856 emitcode ("subb", "a,acc");
3857 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3858 emitcode ("inc", "a");
3859 emitcode ("", "%05d$:", (lbl->key + 100));
3860 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3861 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3865 /*-----------------------------------------------------------------*/
3866 /* genMinus - generates code for subtraction */
3867 /*-----------------------------------------------------------------*/
3869 genMinus (iCode * ic)
3871 int size, offset = 0;
3873 D(emitcode ("; genMinus",""));
3875 aopOp (IC_LEFT (ic), ic, FALSE);
3876 aopOp (IC_RIGHT (ic), ic, FALSE);
3877 aopOp (IC_RESULT (ic), ic, TRUE);
3879 /* special cases :- */
3880 /* if both left & right are in bit space */
3881 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3882 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3888 /* if I can do an decrement instead
3889 of subtract then GOOD for ME */
3890 if (genMinusDec (ic) == TRUE)
3893 size = getDataSize (IC_RESULT (ic));
3895 /* if literal, add a,#-lit, else normal subb */
3896 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3898 unsigned long lit = 0L;
3900 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3905 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3906 /* first add without previous c */
3908 if (!size && lit== (unsigned long) -1) {
3909 emitcode ("dec", "a");
3911 emitcode ("add", "a,#0x%02x",
3912 (unsigned int) (lit & 0x0FFL));
3915 emitcode ("addc", "a,#0x%02x",
3916 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3918 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3923 asmop *leftOp, *rightOp;
3925 leftOp = AOP(IC_LEFT(ic));
3926 rightOp = AOP(IC_RIGHT(ic));
3930 if (aopGetUsesAcc(rightOp, offset)) {
3931 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3932 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3934 emitcode( "setb", "c");
3936 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3937 emitcode("cpl", "a");
3939 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3942 emitcode ("subb", "a,%s",
3943 aopGet(rightOp, offset, FALSE, TRUE));
3946 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3951 adjustArithmeticResult (ic);
3954 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3955 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3956 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3960 /*-----------------------------------------------------------------*/
3961 /* genMultbits :- multiplication of bits */
3962 /*-----------------------------------------------------------------*/
3964 genMultbits (operand * left,
3968 D(emitcode ("; genMultbits",""));
3970 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3971 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3975 /*-----------------------------------------------------------------*/
3976 /* genMultOneByte : 8*8=8/16 bit multiplication */
3977 /*-----------------------------------------------------------------*/
3979 genMultOneByte (operand * left,
3984 int size = AOP_SIZE (result);
3985 bool runtimeSign, compiletimeSign;
3986 bool lUnsigned, rUnsigned;
3988 D(emitcode ("; genMultOneByte",""));
3990 if (size < 1 || size > 2)
3992 /* this should never happen */
3993 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3994 AOP_SIZE(result), __FILE__, lineno);
3998 /* (if two literals: the value is computed before) */
3999 /* if one literal, literal on the right */
4000 if (AOP_TYPE (left) == AOP_LIT)
4005 /* emitcode (";", "swapped left and right"); */
4007 /* if no literal, unsigned on the right: shorter code */
4008 if ( AOP_TYPE (right) != AOP_LIT
4009 && SPEC_USIGN (getSpec (operandType (left))))
4016 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4017 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4019 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4020 no need to take care about the signedness! */
4021 || (lUnsigned && rUnsigned))
4023 /* just an unsigned 8 * 8 = 8 multiply
4025 /* emitcode (";","unsigned"); */
4026 /* TODO: check for accumulator clash between left & right aops? */
4028 if (AOP_TYPE (right) == AOP_LIT)
4030 /* moving to accumulator first helps peepholes */
4031 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4032 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4036 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4037 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4040 emitcode ("mul", "ab");
4041 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4043 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4047 /* we have to do a signed multiply */
4048 /* emitcode (";", "signed"); */
4050 /* now sign adjust for both left & right */
4052 /* let's see what's needed: */
4053 /* apply negative sign during runtime */
4054 runtimeSign = FALSE;
4055 /* negative sign from literals */
4056 compiletimeSign = FALSE;
4060 if (AOP_TYPE(left) == AOP_LIT)
4062 /* signed literal */
4063 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4065 compiletimeSign = TRUE;
4068 /* signed but not literal */
4074 if (AOP_TYPE(right) == AOP_LIT)
4076 /* signed literal */
4077 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4079 compiletimeSign ^= TRUE;
4082 /* signed but not literal */
4086 /* initialize F0, which stores the runtime sign */
4089 if (compiletimeSign)
4090 emitcode ("setb", "F0"); /* set sign flag */
4092 emitcode ("clr", "F0"); /* reset sign flag */
4095 /* save the signs of the operands */
4096 if (AOP_TYPE(right) == AOP_LIT)
4098 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4100 if (!rUnsigned && val < 0)
4101 emitcode ("mov", "b,#0x%02x", -val);
4103 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4105 else /* ! literal */
4107 if (rUnsigned) /* emitcode (";", "signed"); */
4109 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4112 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4113 lbl = newiTempLabel (NULL);
4114 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4115 emitcode ("cpl", "F0"); /* complement sign flag */
4116 emitcode ("cpl", "a"); /* 2's complement */
4117 emitcode ("inc", "a");
4118 emitcode ("", "%05d$:", (lbl->key + 100));
4119 emitcode ("mov", "b,a");
4123 if (AOP_TYPE(left) == AOP_LIT)
4125 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4127 if (!lUnsigned && val < 0)
4128 emitcode ("mov", "a,#0x%02x", -val);
4130 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4132 else /* ! literal */
4134 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4138 lbl = newiTempLabel (NULL);
4139 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4140 emitcode ("cpl", "F0"); /* complement sign flag */
4141 emitcode ("cpl", "a"); /* 2's complement */
4142 emitcode ("inc", "a");
4143 emitcode ("", "%05d$:", (lbl->key + 100));
4147 /* now the multiplication */
4148 emitcode ("mul", "ab");
4149 if (runtimeSign || compiletimeSign)
4151 lbl = newiTempLabel (NULL);
4153 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4154 emitcode ("cpl", "a"); /* lsb 2's complement */
4156 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4159 emitcode ("add", "a,#1"); /* this sets carry flag */
4160 emitcode ("xch", "a,b");
4161 emitcode ("cpl", "a"); /* msb 2's complement */
4162 emitcode ("addc", "a,#0");
4163 emitcode ("xch", "a,b");
4165 emitcode ("", "%05d$:", (lbl->key + 100));
4167 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4169 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4172 /*-----------------------------------------------------------------*/
4173 /* genMult - generates code for multiplication */
4174 /*-----------------------------------------------------------------*/
4176 genMult (iCode * ic)
4178 operand *left = IC_LEFT (ic);
4179 operand *right = IC_RIGHT (ic);
4180 operand *result = IC_RESULT (ic);
4182 D(emitcode ("; genMult",""));
4184 /* assign the amsops */
4185 aopOp (left, ic, FALSE);
4186 aopOp (right, ic, FALSE);
4187 aopOp (result, ic, TRUE);
4189 /* special cases first */
4191 if (AOP_TYPE (left) == AOP_CRY &&
4192 AOP_TYPE (right) == AOP_CRY)
4194 genMultbits (left, right, result);
4198 /* if both are of size == 1 */
4199 #if 0 // one of them can be a sloc shared with the result
4200 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4202 if (getSize(operandType(left)) == 1 &&
4203 getSize(operandType(right)) == 1)
4206 genMultOneByte (left, right, result);
4210 /* should have been converted to function call */
4211 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4212 getSize(OP_SYMBOL(right)->type));
4216 freeAsmop (result, NULL, ic, TRUE);
4217 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4221 /*-----------------------------------------------------------------*/
4222 /* genDivbits :- division of bits */
4223 /*-----------------------------------------------------------------*/
4225 genDivbits (operand * left,
4232 D(emitcode ("; genDivbits",""));
4234 /* the result must be bit */
4235 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4236 l = aopGet (AOP (left), 0, FALSE, FALSE);
4240 emitcode ("div", "ab");
4241 emitcode ("rrc", "a");
4242 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4245 /*-----------------------------------------------------------------*/
4246 /* genDivOneByte : 8 bit division */
4247 /*-----------------------------------------------------------------*/
4249 genDivOneByte (operand * left,
4253 bool lUnsigned, rUnsigned;
4254 bool runtimeSign, compiletimeSign;
4258 D(emitcode ("; genDivOneByte",""));
4260 /* Why is it necessary that genDivOneByte() can return an int result?
4263 volatile unsigned char uc;
4264 volatile signed char sc1, sc2;
4277 In all cases a one byte result would overflow, the following cast to int
4278 would return the wrong result.
4280 Two possible solution:
4281 a) cast operands to int, if ((unsigned) / (signed)) or
4282 ((signed) / (signed))
4283 b) return an 16 bit signed int; this is what we're doing here!
4286 size = AOP_SIZE (result) - 1;
4288 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4289 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4291 /* signed or unsigned */
4292 if (lUnsigned && rUnsigned)
4294 /* unsigned is easy */
4295 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4296 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4297 emitcode ("div", "ab");
4298 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4300 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4304 /* signed is a little bit more difficult */
4306 /* now sign adjust for both left & right */
4308 /* let's see what's needed: */
4309 /* apply negative sign during runtime */
4310 runtimeSign = FALSE;
4311 /* negative sign from literals */
4312 compiletimeSign = FALSE;
4316 if (AOP_TYPE(left) == AOP_LIT)
4318 /* signed literal */
4319 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4321 compiletimeSign = TRUE;
4324 /* signed but not literal */
4330 if (AOP_TYPE(right) == AOP_LIT)
4332 /* signed literal */
4333 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4335 compiletimeSign ^= TRUE;
4338 /* signed but not literal */
4342 /* initialize F0, which stores the runtime sign */
4345 if (compiletimeSign)
4346 emitcode ("setb", "F0"); /* set sign flag */
4348 emitcode ("clr", "F0"); /* reset sign flag */
4351 /* save the signs of the operands */
4352 if (AOP_TYPE(right) == AOP_LIT)
4354 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4356 if (!rUnsigned && val < 0)
4357 emitcode ("mov", "b,#0x%02x", -val);
4359 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4361 else /* ! literal */
4364 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4367 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4368 lbl = newiTempLabel (NULL);
4369 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4370 emitcode ("cpl", "F0"); /* complement sign flag */
4371 emitcode ("cpl", "a"); /* 2's complement */
4372 emitcode ("inc", "a");
4373 emitcode ("", "%05d$:", (lbl->key + 100));
4374 emitcode ("mov", "b,a");
4378 if (AOP_TYPE(left) == AOP_LIT)
4380 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4382 if (!lUnsigned && val < 0)
4383 emitcode ("mov", "a,#0x%02x", -val);
4385 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4387 else /* ! literal */
4389 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4393 lbl = newiTempLabel (NULL);
4394 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4395 emitcode ("cpl", "F0"); /* complement sign flag */
4396 emitcode ("cpl", "a"); /* 2's complement */
4397 emitcode ("inc", "a");
4398 emitcode ("", "%05d$:", (lbl->key + 100));
4402 /* now the division */
4403 emitcode ("div", "ab");
4405 if (runtimeSign || compiletimeSign)
4407 lbl = newiTempLabel (NULL);
4409 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4410 emitcode ("cpl", "a"); /* lsb 2's complement */
4411 emitcode ("inc", "a");
4412 emitcode ("", "%05d$:", (lbl->key + 100));
4414 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4417 /* msb is 0x00 or 0xff depending on the sign */
4420 emitcode ("mov", "c,F0");
4421 emitcode ("subb", "a,acc");
4423 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4425 else /* compiletimeSign */
4427 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4432 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4434 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4438 /*-----------------------------------------------------------------*/
4439 /* genDiv - generates code for division */
4440 /*-----------------------------------------------------------------*/
4444 operand *left = IC_LEFT (ic);
4445 operand *right = IC_RIGHT (ic);
4446 operand *result = IC_RESULT (ic);
4448 D(emitcode ("; genDiv",""));
4450 /* assign the amsops */
4451 aopOp (left, ic, FALSE);
4452 aopOp (right, ic, FALSE);
4453 aopOp (result, ic, TRUE);
4455 /* special cases first */
4457 if (AOP_TYPE (left) == AOP_CRY &&
4458 AOP_TYPE (right) == AOP_CRY)
4460 genDivbits (left, right, result);
4464 /* if both are of size == 1 */
4465 if (AOP_SIZE (left) == 1 &&
4466 AOP_SIZE (right) == 1)
4468 genDivOneByte (left, right, result);
4472 /* should have been converted to function call */
4475 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4476 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4477 freeAsmop (result, NULL, ic, TRUE);
4480 /*-----------------------------------------------------------------*/
4481 /* genModbits :- modulus of bits */
4482 /*-----------------------------------------------------------------*/
4484 genModbits (operand * left,
4491 D(emitcode ("; genModbits",""));
4493 /* the result must be bit */
4494 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4495 l = aopGet (AOP (left), 0, FALSE, FALSE);
4499 emitcode ("div", "ab");
4500 emitcode ("mov", "a,b");
4501 emitcode ("rrc", "a");
4502 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4505 /*-----------------------------------------------------------------*/
4506 /* genModOneByte : 8 bit modulus */
4507 /*-----------------------------------------------------------------*/
4509 genModOneByte (operand * left,
4513 bool lUnsigned, rUnsigned;
4514 bool runtimeSign, compiletimeSign;
4518 D(emitcode ("; genModOneByte",""));
4520 size = AOP_SIZE (result) - 1;
4522 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4523 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4525 /* signed or unsigned */
4526 if (lUnsigned && rUnsigned)
4528 /* unsigned is easy */
4529 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4530 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4531 emitcode ("div", "ab");
4532 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4534 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4538 /* signed is a little bit more difficult */
4540 /* now sign adjust for both left & right */
4542 /* modulus: sign of the right operand has no influence on the result! */
4543 if (AOP_TYPE(right) == AOP_LIT)
4545 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4547 if (!rUnsigned && val < 0)
4548 emitcode ("mov", "b,#0x%02x", -val);
4550 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4552 else /* not literal */
4555 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4558 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4559 lbl = newiTempLabel (NULL);
4560 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4561 emitcode ("cpl", "a"); /* 2's complement */
4562 emitcode ("inc", "a");
4563 emitcode ("", "%05d$:", (lbl->key + 100));
4564 emitcode ("mov", "b,a");
4568 /* let's see what's needed: */
4569 /* apply negative sign during runtime */
4570 runtimeSign = FALSE;
4571 /* negative sign from literals */
4572 compiletimeSign = FALSE;
4574 /* sign adjust left side */
4575 if (AOP_TYPE(left) == AOP_LIT)
4577 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4579 if (!lUnsigned && val < 0)
4581 compiletimeSign = TRUE; /* set sign flag */
4582 emitcode ("mov", "a,#0x%02x", -val);
4585 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4587 else /* ! literal */
4589 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4594 emitcode ("clr", "F0"); /* clear sign flag */
4596 lbl = newiTempLabel (NULL);
4597 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4598 emitcode ("setb", "F0"); /* set sign flag */
4599 emitcode ("cpl", "a"); /* 2's complement */
4600 emitcode ("inc", "a");
4601 emitcode ("", "%05d$:", (lbl->key + 100));
4605 /* now the modulus */
4606 emitcode ("div", "ab");
4608 if (runtimeSign || compiletimeSign)
4610 emitcode ("mov", "a,b");
4611 lbl = newiTempLabel (NULL);
4613 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4614 emitcode ("cpl", "a"); /* 2's complement */
4615 emitcode ("inc", "a");
4616 emitcode ("", "%05d$:", (lbl->key + 100));
4618 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4621 /* msb is 0x00 or 0xff depending on the sign */
4624 emitcode ("mov", "c,F0");
4625 emitcode ("subb", "a,acc");
4627 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4629 else /* compiletimeSign */
4631 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4636 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4638 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4642 /*-----------------------------------------------------------------*/
4643 /* genMod - generates code for division */
4644 /*-----------------------------------------------------------------*/
4648 operand *left = IC_LEFT (ic);
4649 operand *right = IC_RIGHT (ic);
4650 operand *result = IC_RESULT (ic);
4652 D(emitcode ("; genMod",""));
4654 /* assign the amsops */
4655 aopOp (left, ic, FALSE);
4656 aopOp (right, ic, FALSE);
4657 aopOp (result, ic, TRUE);
4659 /* special cases first */
4661 if (AOP_TYPE (left) == AOP_CRY &&
4662 AOP_TYPE (right) == AOP_CRY)
4664 genModbits (left, right, result);
4668 /* if both are of size == 1 */
4669 if (AOP_SIZE (left) == 1 &&
4670 AOP_SIZE (right) == 1)
4672 genModOneByte (left, right, result);
4676 /* should have been converted to function call */
4680 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4681 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4682 freeAsmop (result, NULL, ic, TRUE);
4685 /*-----------------------------------------------------------------*/
4686 /* genIfxJump :- will create a jump depending on the ifx */
4687 /*-----------------------------------------------------------------*/
4689 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4692 symbol *tlbl = newiTempLabel (NULL);
4695 D(emitcode ("; genIfxJump",""));
4697 /* if true label then we jump if condition
4701 jlbl = IC_TRUE (ic);
4702 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4703 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4707 /* false label is present */
4708 jlbl = IC_FALSE (ic);
4709 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4710 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4712 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4713 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4715 emitcode (inst, "%05d$", tlbl->key + 100);
4716 freeForBranchAsmop (result);
4717 freeForBranchAsmop (right);
4718 freeForBranchAsmop (left);
4719 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4720 emitcode ("", "%05d$:", tlbl->key + 100);
4722 /* mark the icode as generated */
4726 /*-----------------------------------------------------------------*/
4727 /* genCmp :- greater or less than comparison */
4728 /*-----------------------------------------------------------------*/
4730 genCmp (operand * left, operand * right,
4731 operand * result, iCode * ifx, int sign, iCode *ic)
4733 int size, offset = 0;
4734 unsigned long lit = 0L;
4737 D(emitcode ("; genCmp",""));
4739 /* if left & right are bit variables */
4740 if (AOP_TYPE (left) == AOP_CRY &&
4741 AOP_TYPE (right) == AOP_CRY)
4743 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4744 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4748 /* subtract right from left if at the
4749 end the carry flag is set then we know that
4750 left is greater than right */
4751 size = max (AOP_SIZE (left), AOP_SIZE (right));
4753 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4754 if ((size == 1) && !sign &&
4755 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4757 symbol *lbl = newiTempLabel (NULL);
4758 emitcode ("cjne", "%s,%s,%05d$",
4759 aopGet (AOP (left), offset, FALSE, FALSE),
4760 aopGet (AOP (right), offset, FALSE, FALSE),
4762 emitcode ("", "%05d$:", lbl->key + 100);
4766 if (AOP_TYPE (right) == AOP_LIT)
4768 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4769 /* optimize if(x < 0) or if(x >= 0) */
4778 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4779 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4781 genIfxJump (ifx, "acc.7", left, right, result);
4785 emitcode ("rlc", "a");
4793 rightInB = aopGetUsesAcc(AOP (right), offset);
4795 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4796 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4797 if (sign && size == 0)
4799 emitcode ("xrl", "a,#0x80");
4800 if (AOP_TYPE (right) == AOP_LIT)
4802 unsigned long lit = (unsigned long)
4803 floatFromVal (AOP (right)->aopu.aop_lit);
4804 emitcode ("subb", "a,#0x%02x",
4805 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4810 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4811 emitcode ("xrl", "b,#0x80");
4812 emitcode ("subb", "a,b");
4818 emitcode ("subb", "a,b");
4820 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4836 /* if the result is used in the next
4837 ifx conditional branch then generate
4838 code a little differently */
4840 genIfxJump (ifx, "c", NULL, NULL, result);
4843 /* leave the result in acc */
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpGt :- greater than comparison */
4849 /*-----------------------------------------------------------------*/
4851 genCmpGt (iCode * ic, iCode * ifx)
4853 operand *left, *right, *result;
4854 sym_link *letype, *retype;
4857 D(emitcode ("; genCmpGt",""));
4859 left = IC_LEFT (ic);
4860 right = IC_RIGHT (ic);
4861 result = IC_RESULT (ic);
4863 letype = getSpec (operandType (left));
4864 retype = getSpec (operandType (right));
4865 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4866 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4867 /* assign the amsops */
4868 aopOp (left, ic, FALSE);
4869 aopOp (right, ic, FALSE);
4870 aopOp (result, ic, TRUE);
4872 genCmp (right, left, result, ifx, sign,ic);
4874 freeAsmop (result, NULL, ic, TRUE);
4877 /*-----------------------------------------------------------------*/
4878 /* genCmpLt - less than comparisons */
4879 /*-----------------------------------------------------------------*/
4881 genCmpLt (iCode * ic, iCode * ifx)
4883 operand *left, *right, *result;
4884 sym_link *letype, *retype;
4887 D(emitcode ("; genCmpLt",""));
4889 left = IC_LEFT (ic);
4890 right = IC_RIGHT (ic);
4891 result = IC_RESULT (ic);
4893 letype = getSpec (operandType (left));
4894 retype = getSpec (operandType (right));
4895 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4896 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4897 /* assign the amsops */
4898 aopOp (left, ic, FALSE);
4899 aopOp (right, ic, FALSE);
4900 aopOp (result, ic, TRUE);
4902 genCmp (left, right, result, ifx, sign,ic);
4904 freeAsmop (result, NULL, ic, TRUE);
4907 /*-----------------------------------------------------------------*/
4908 /* gencjneshort - compare and jump if not equal */
4909 /*-----------------------------------------------------------------*/
4911 gencjneshort (operand * left, operand * right, symbol * lbl)
4913 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4915 unsigned long lit = 0L;
4917 /* if the left side is a literal or
4918 if the right is in a pointer register and left
4920 if ((AOP_TYPE (left) == AOP_LIT) ||
4921 (AOP_TYPE (left) == AOP_IMMD) ||
4922 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4929 if (AOP_TYPE (right) == AOP_LIT)
4930 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4932 /* if the right side is a literal then anything goes */
4933 if (AOP_TYPE (right) == AOP_LIT &&
4934 AOP_TYPE (left) != AOP_DIR &&
4935 AOP_TYPE (left) != AOP_IMMD)
4939 emitcode ("cjne", "%s,%s,%05d$",
4940 aopGet (AOP (left), offset, FALSE, FALSE),
4941 aopGet (AOP (right), offset, FALSE, FALSE),
4947 /* if the right side is in a register or in direct space or
4948 if the left is a pointer register & right is not */
4949 else if (AOP_TYPE (right) == AOP_REG ||
4950 AOP_TYPE (right) == AOP_DIR ||
4951 AOP_TYPE (right) == AOP_LIT ||
4952 AOP_TYPE (right) == AOP_IMMD ||
4953 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4954 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4959 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4960 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4961 emitcode ("jnz", "%05d$", lbl->key + 100);
4963 emitcode ("cjne", "a,%s,%05d$",
4964 aopGet (AOP (right), offset, FALSE, TRUE),
4971 /* right is a pointer reg need both a & b */
4974 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4975 if (strcmp (l, "b"))
4976 emitcode ("mov", "b,%s", l);
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4984 /*-----------------------------------------------------------------*/
4985 /* gencjne - compare and jump if not equal */
4986 /*-----------------------------------------------------------------*/
4988 gencjne (operand * left, operand * right, symbol * lbl)
4990 symbol *tlbl = newiTempLabel (NULL);
4992 gencjneshort (left, right, lbl);
4994 emitcode ("mov", "a,%s", one);
4995 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4996 emitcode ("", "%05d$:", lbl->key + 100);
4997 emitcode ("clr", "a");
4998 emitcode ("", "%05d$:", tlbl->key + 100);
5001 /*-----------------------------------------------------------------*/
5002 /* genCmpEq - generates code for equal to */
5003 /*-----------------------------------------------------------------*/
5005 genCmpEq (iCode * ic, iCode * ifx)
5007 operand *left, *right, *result;
5009 D(emitcode ("; genCmpEq",""));
5011 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5012 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5013 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5015 /* if literal, literal on the right or
5016 if the right is in a pointer register and left
5018 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5019 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5021 operand *t = IC_RIGHT (ic);
5022 IC_RIGHT (ic) = IC_LEFT (ic);
5026 if (ifx && !AOP_SIZE (result))
5029 /* if they are both bit variables */
5030 if (AOP_TYPE (left) == AOP_CRY &&
5031 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5033 if (AOP_TYPE (right) == AOP_LIT)
5035 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5039 emitcode ("cpl", "c");
5043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5047 emitcode ("clr", "c");
5049 /* AOP_TYPE(right) == AOP_CRY */
5053 symbol *lbl = newiTempLabel (NULL);
5054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5055 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5056 emitcode ("cpl", "c");
5057 emitcode ("", "%05d$:", (lbl->key + 100));
5059 /* if true label then we jump if condition
5061 tlbl = newiTempLabel (NULL);
5064 emitcode ("jnc", "%05d$", tlbl->key + 100);
5065 freeForBranchAsmop (result);
5066 freeForBranchAsmop (right);
5067 freeForBranchAsmop (left);
5068 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5072 emitcode ("jc", "%05d$", tlbl->key + 100);
5073 freeForBranchAsmop (result);
5074 freeForBranchAsmop (right);
5075 freeForBranchAsmop (left);
5076 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5082 tlbl = newiTempLabel (NULL);
5083 gencjneshort (left, right, tlbl);
5086 freeForBranchAsmop (result);
5087 freeForBranchAsmop (right);
5088 freeForBranchAsmop (left);
5089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5090 emitcode ("", "%05d$:", tlbl->key + 100);
5094 symbol *lbl = newiTempLabel (NULL);
5095 emitcode ("sjmp", "%05d$", lbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5097 freeForBranchAsmop (result);
5098 freeForBranchAsmop (right);
5099 freeForBranchAsmop (left);
5100 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5101 emitcode ("", "%05d$:", lbl->key + 100);
5104 /* mark the icode as generated */
5109 /* if they are both bit variables */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119 emitcode ("cpl", "c");
5123 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5127 emitcode ("clr", "c");
5129 /* AOP_TYPE(right) == AOP_CRY */
5133 symbol *lbl = newiTempLabel (NULL);
5134 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5135 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5136 emitcode ("cpl", "c");
5137 emitcode ("", "%05d$:", (lbl->key + 100));
5140 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5147 genIfxJump (ifx, "c", left, right, result);
5150 /* if the result is used in an arithmetic operation
5151 then put the result in place */
5156 gencjne (left, right, newiTempLabel (NULL));
5157 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5159 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5164 genIfxJump (ifx, "a", left, right, result);
5167 /* if the result is used in an arithmetic operation
5168 then put the result in place */
5169 if (AOP_TYPE (result) != AOP_CRY)
5171 /* leave the result in acc */
5175 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177 freeAsmop (result, NULL, ic, TRUE);
5180 /*-----------------------------------------------------------------*/
5181 /* ifxForOp - returns the icode containing the ifx for operand */
5182 /*-----------------------------------------------------------------*/
5184 ifxForOp (operand * op, iCode * ic)
5186 /* if true symbol then needs to be assigned */
5187 if (IS_TRUE_SYMOP (op))
5190 /* if this has register type condition and
5191 the next instruction is ifx with the same operand
5192 and live to of the operand is upto the ifx only then */
5194 ic->next->op == IFX &&
5195 IC_COND (ic->next)->key == op->key &&
5196 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5202 /*-----------------------------------------------------------------*/
5203 /* hasInc - operand is incremented before any other use */
5204 /*-----------------------------------------------------------------*/
5206 hasInc (operand *op, iCode *ic,int osize)
5208 sym_link *type = operandType(op);
5209 sym_link *retype = getSpec (type);
5210 iCode *lic = ic->next;
5213 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5214 if (!IS_SYMOP(op)) return NULL;
5216 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5217 if (IS_AGGREGATE(type->next)) return NULL;
5218 if (osize != (isize = getSize(type->next))) return NULL;
5221 /* if operand of the form op = op + <sizeof *op> */
5222 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5223 isOperandEqual(IC_RESULT(lic),op) &&
5224 isOperandLiteral(IC_RIGHT(lic)) &&
5225 operandLitValue(IC_RIGHT(lic)) == isize) {
5228 /* if the operand used or deffed */
5229 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5232 /* if GOTO or IFX */
5233 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5239 /*-----------------------------------------------------------------*/
5240 /* genAndOp - for && operation */
5241 /*-----------------------------------------------------------------*/
5243 genAndOp (iCode * ic)
5245 operand *left, *right, *result;
5248 D(emitcode ("; genAndOp",""));
5250 /* note here that && operations that are in an
5251 if statement are taken away by backPatchLabels
5252 only those used in arthmetic operations remain */
5253 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5254 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5255 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5257 /* if both are bit variables */
5258 if (AOP_TYPE (left) == AOP_CRY &&
5259 AOP_TYPE (right) == AOP_CRY)
5261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5267 tlbl = newiTempLabel (NULL);
5269 emitcode ("jz", "%05d$", tlbl->key + 100);
5271 emitcode ("", "%05d$:", tlbl->key + 100);
5275 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 freeAsmop (result, NULL, ic, TRUE);
5281 /*-----------------------------------------------------------------*/
5282 /* genOrOp - for || operation */
5283 /*-----------------------------------------------------------------*/
5285 genOrOp (iCode * ic)
5287 operand *left, *right, *result;
5290 D(emitcode ("; genOrOp",""));
5292 /* note here that || operations that are in an
5293 if statement are taken away by backPatchLabels
5294 only those used in arthmetic operations remain */
5295 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5296 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5297 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5299 /* if both are bit variables */
5300 if (AOP_TYPE (left) == AOP_CRY &&
5301 AOP_TYPE (right) == AOP_CRY)
5303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5309 tlbl = newiTempLabel (NULL);
5311 emitcode ("jnz", "%05d$", tlbl->key + 100);
5313 emitcode ("", "%05d$:", tlbl->key + 100);
5317 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5319 freeAsmop (result, NULL, ic, TRUE);
5322 /*-----------------------------------------------------------------*/
5323 /* isLiteralBit - test if lit == 2^n */
5324 /*-----------------------------------------------------------------*/
5326 isLiteralBit (unsigned long lit)
5328 unsigned long pw[32] =
5329 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5330 0x100L, 0x200L, 0x400L, 0x800L,
5331 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5332 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5333 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5334 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5335 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5338 for (idx = 0; idx < 32; idx++)
5344 /*-----------------------------------------------------------------*/
5345 /* continueIfTrue - */
5346 /*-----------------------------------------------------------------*/
5348 continueIfTrue (iCode * ic)
5351 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5355 /*-----------------------------------------------------------------*/
5357 /*-----------------------------------------------------------------*/
5359 jumpIfTrue (iCode * ic)
5362 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5366 /*-----------------------------------------------------------------*/
5367 /* jmpTrueOrFalse - */
5368 /*-----------------------------------------------------------------*/
5370 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5372 // ugly but optimized by peephole
5375 symbol *nlbl = newiTempLabel (NULL);
5376 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5377 emitcode ("", "%05d$:", tlbl->key + 100);
5378 freeForBranchAsmop (result);
5379 freeForBranchAsmop (right);
5380 freeForBranchAsmop (left);
5381 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5382 emitcode ("", "%05d$:", nlbl->key + 100);
5386 freeForBranchAsmop (result);
5387 freeForBranchAsmop (right);
5388 freeForBranchAsmop (left);
5389 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5390 emitcode ("", "%05d$:", tlbl->key + 100);
5395 /*-----------------------------------------------------------------*/
5396 /* genAnd - code for and */
5397 /*-----------------------------------------------------------------*/
5399 genAnd (iCode * ic, iCode * ifx)
5401 operand *left, *right, *result;
5402 int size, offset = 0;
5403 unsigned long lit = 0L;
5407 D(emitcode ("; genAnd",""));
5409 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5410 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5411 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5414 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5416 AOP_TYPE (left), AOP_TYPE (right));
5417 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5419 AOP_SIZE (left), AOP_SIZE (right));
5422 /* if left is a literal & right is not then exchange them */
5423 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5424 AOP_NEEDSACC (left))
5426 operand *tmp = right;
5431 /* if result = right then exchange them */
5432 if (sameRegs (AOP (result), AOP (right)))
5434 operand *tmp = right;
5439 /* if right is bit then exchange them */
5440 if (AOP_TYPE (right) == AOP_CRY &&
5441 AOP_TYPE (left) != AOP_CRY)
5443 operand *tmp = right;
5447 if (AOP_TYPE (right) == AOP_LIT)
5448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5450 size = AOP_SIZE (result);
5453 // result = bit & yy;
5454 if (AOP_TYPE (left) == AOP_CRY)
5456 // c = bit & literal;
5457 if (AOP_TYPE (right) == AOP_LIT)
5461 if (size && sameRegs (AOP (result), AOP (left)))
5464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5469 if (size && (AOP_TYPE (result) == AOP_CRY))
5471 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5474 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5479 emitcode ("clr", "c");
5484 if (AOP_TYPE (right) == AOP_CRY)
5487 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5488 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5493 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5495 emitcode ("rrc", "a");
5496 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5504 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5505 genIfxJump (ifx, "c", left, right, result);
5509 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5510 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5511 if ((AOP_TYPE (right) == AOP_LIT) &&
5512 (AOP_TYPE (result) == AOP_CRY) &&
5513 (AOP_TYPE (left) != AOP_CRY))
5515 int posbit = isLiteralBit (lit);
5520 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5523 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5529 sprintf (buffer, "acc.%d", posbit & 0x07);
5530 genIfxJump (ifx, buffer, left, right, result);
5537 symbol *tlbl = newiTempLabel (NULL);
5538 int sizel = AOP_SIZE (left);
5540 emitcode ("setb", "c");
5543 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5545 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5547 if ((posbit = isLiteralBit (bytelit)) != 0)
5548 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5551 if (bytelit != 0x0FFL)
5552 emitcode ("anl", "a,%s",
5553 aopGet (AOP (right), offset, FALSE, TRUE));
5554 emitcode ("jnz", "%05d$", tlbl->key + 100);
5559 // bit = left & literal
5562 emitcode ("clr", "c");
5563 emitcode ("", "%05d$:", tlbl->key + 100);
5565 // if(left & literal)
5569 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5571 emitcode ("", "%05d$:", tlbl->key + 100);
5579 /* if left is same as result */
5580 if (sameRegs (AOP (result), AOP (left)))
5582 for (; size--; offset++)
5584 if (AOP_TYPE (right) == AOP_LIT)
5586 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5588 else if (bytelit == 0)
5590 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5592 else if (IS_AOP_PREG (result))
5594 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5595 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5596 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5599 emitcode ("anl", "%s,%s",
5600 aopGet (AOP (left), offset, FALSE, TRUE),
5601 aopGet (AOP (right), offset, FALSE, FALSE));
5605 if (AOP_TYPE (left) == AOP_ACC)
5606 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5609 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5610 if (IS_AOP_PREG (result))
5612 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5613 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5617 emitcode ("anl", "%s,a",
5618 aopGet (AOP (left), offset, FALSE, TRUE));
5625 // left & result in different registers
5626 if (AOP_TYPE (result) == AOP_CRY)
5629 // if(size), result in bit
5630 // if(!size && ifx), conditional oper: if(left & right)
5631 symbol *tlbl = newiTempLabel (NULL);
5632 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5634 emitcode ("setb", "c");
5637 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5638 emitcode ("anl", "a,%s",
5639 aopGet (AOP (right), offset, FALSE, FALSE));
5641 if (AOP_TYPE(left)==AOP_ACC) {
5642 emitcode("mov", "b,a");
5643 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5644 emitcode("anl", "a,b");
5646 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5647 emitcode ("anl", "a,%s",
5648 aopGet (AOP (left), offset, FALSE, FALSE));
5651 emitcode ("jnz", "%05d$", tlbl->key + 100);
5657 emitcode ("", "%05d$:", tlbl->key + 100);
5661 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5663 emitcode ("", "%05d$:", tlbl->key + 100);
5667 for (; (size--); offset++)
5670 // result = left & right
5671 if (AOP_TYPE (right) == AOP_LIT)
5673 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5675 aopPut (AOP (result),
5676 aopGet (AOP (left), offset, FALSE, FALSE),
5678 isOperandVolatile (result, FALSE));
5681 else if (bytelit == 0)
5683 /* dummy read of volatile operand */
5684 if (isOperandVolatile (left, FALSE))
5685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5686 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5690 // faster than result <- left, anl result,right
5691 // and better if result is SFR
5692 if (AOP_TYPE (left) == AOP_ACC)
5693 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5696 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5697 emitcode ("anl", "a,%s",
5698 aopGet (AOP (left), offset, FALSE, FALSE));
5700 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 freeAsmop (result, NULL, ic, TRUE);
5711 /*-----------------------------------------------------------------*/
5712 /* genOr - code for or */
5713 /*-----------------------------------------------------------------*/
5715 genOr (iCode * ic, iCode * ifx)
5717 operand *left, *right, *result;
5718 int size, offset = 0;
5719 unsigned long lit = 0L;
5721 D(emitcode ("; genOr",""));
5723 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5724 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5725 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5728 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5730 AOP_TYPE (left), AOP_TYPE (right));
5731 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5733 AOP_SIZE (left), AOP_SIZE (right));
5736 /* if left is a literal & right is not then exchange them */
5737 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5738 AOP_NEEDSACC (left))
5740 operand *tmp = right;
5745 /* if result = right then exchange them */
5746 if (sameRegs (AOP (result), AOP (right)))
5748 operand *tmp = right;
5753 /* if right is bit then exchange them */
5754 if (AOP_TYPE (right) == AOP_CRY &&
5755 AOP_TYPE (left) != AOP_CRY)
5757 operand *tmp = right;
5761 if (AOP_TYPE (right) == AOP_LIT)
5762 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5764 size = AOP_SIZE (result);
5768 if (AOP_TYPE (left) == AOP_CRY)
5770 if (AOP_TYPE (right) == AOP_LIT)
5772 // c = bit | literal;
5775 // lit != 0 => result = 1
5776 if (AOP_TYPE (result) == AOP_CRY)
5779 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5781 continueIfTrue (ifx);
5784 emitcode ("setb", "c");
5788 // lit == 0 => result = left
5789 if (size && sameRegs (AOP (result), AOP (left)))
5791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796 if (AOP_TYPE (right) == AOP_CRY)
5799 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5800 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5805 symbol *tlbl = newiTempLabel (NULL);
5806 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5807 emitcode ("setb", "c");
5808 emitcode ("jb", "%s,%05d$",
5809 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5811 emitcode ("jnz", "%05d$", tlbl->key + 100);
5812 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5814 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5820 emitcode ("", "%05d$:", tlbl->key + 100);
5829 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5830 genIfxJump (ifx, "c", left, right, result);
5834 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5835 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5836 if ((AOP_TYPE (right) == AOP_LIT) &&
5837 (AOP_TYPE (result) == AOP_CRY) &&
5838 (AOP_TYPE (left) != AOP_CRY))
5844 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5846 continueIfTrue (ifx);
5851 // lit = 0, result = boolean(left)
5853 emitcode ("setb", "c");
5857 symbol *tlbl = newiTempLabel (NULL);
5858 emitcode ("jnz", "%05d$", tlbl->key + 100);
5860 emitcode ("", "%05d$:", tlbl->key + 100);
5864 genIfxJump (ifx, "a", left, right, result);
5872 /* if left is same as result */
5873 if (sameRegs (AOP (result), AOP (left)))
5875 for (; size--; offset++)
5877 if (AOP_TYPE (right) == AOP_LIT)
5879 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5881 /* dummy read of volatile operand */
5882 if (isOperandVolatile (left, FALSE))
5883 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5887 else if (IS_AOP_PREG (left))
5889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5890 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5891 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5894 emitcode ("orl", "%s,%s",
5895 aopGet (AOP (left), offset, FALSE, TRUE),
5896 aopGet (AOP (right), offset, FALSE, FALSE));
5900 if (AOP_TYPE (left) == AOP_ACC)
5901 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5905 if (IS_AOP_PREG (left))
5907 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5908 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5911 emitcode ("orl", "%s,a",
5912 aopGet (AOP (left), offset, FALSE, TRUE));
5919 // left & result in different registers
5920 if (AOP_TYPE (result) == AOP_CRY)
5923 // if(size), result in bit
5924 // if(!size && ifx), conditional oper: if(left | right)
5925 symbol *tlbl = newiTempLabel (NULL);
5926 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5928 emitcode ("setb", "c");
5931 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5932 emitcode ("orl", "a,%s",
5933 aopGet (AOP (right), offset, FALSE, FALSE));
5935 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5936 emitcode ("orl", "a,%s",
5937 aopGet (AOP (left), offset, FALSE, FALSE));
5939 emitcode ("jnz", "%05d$", tlbl->key + 100);
5945 emitcode ("", "%05d$:", tlbl->key + 100);
5949 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5951 emitcode ("", "%05d$:", tlbl->key + 100);
5954 for (; (size--); offset++)
5957 // result = left & right
5958 if (AOP_TYPE (right) == AOP_LIT)
5960 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5962 aopPut (AOP (result),
5963 aopGet (AOP (left), offset, FALSE, FALSE),
5965 isOperandVolatile (result, FALSE));
5969 // faster than result <- left, anl result,right
5970 // and better if result is SFR
5971 if (AOP_TYPE (left) == AOP_ACC)
5972 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5976 emitcode ("orl", "a,%s",
5977 aopGet (AOP (left), offset, FALSE, FALSE));
5979 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (result, NULL, ic, TRUE);
5989 /*-----------------------------------------------------------------*/
5990 /* genXor - code for xclusive or */
5991 /*-----------------------------------------------------------------*/
5993 genXor (iCode * ic, iCode * ifx)
5995 operand *left, *right, *result;
5996 int size, offset = 0;
5997 unsigned long lit = 0L;
5999 D(emitcode ("; genXor",""));
6001 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6002 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6003 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6006 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6008 AOP_TYPE (left), AOP_TYPE (right));
6009 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6011 AOP_SIZE (left), AOP_SIZE (right));
6014 /* if left is a literal & right is not ||
6015 if left needs acc & right does not */
6016 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6017 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6019 operand *tmp = right;
6024 /* if result = right then exchange them */
6025 if (sameRegs (AOP (result), AOP (right)))
6027 operand *tmp = right;
6032 /* if right is bit then exchange them */
6033 if (AOP_TYPE (right) == AOP_CRY &&
6034 AOP_TYPE (left) != AOP_CRY)
6036 operand *tmp = right;
6040 if (AOP_TYPE (right) == AOP_LIT)
6041 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6043 size = AOP_SIZE (result);
6047 if (AOP_TYPE (left) == AOP_CRY)
6049 if (AOP_TYPE (right) == AOP_LIT)
6051 // c = bit & literal;
6054 // lit>>1 != 0 => result = 1
6055 if (AOP_TYPE (result) == AOP_CRY)
6058 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6060 continueIfTrue (ifx);
6063 emitcode ("setb", "c");
6070 // lit == 0, result = left
6071 if (size && sameRegs (AOP (result), AOP (left)))
6073 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6077 // lit == 1, result = not(left)
6078 if (size && sameRegs (AOP (result), AOP (left)))
6080 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6085 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6086 emitcode ("cpl", "c");
6095 symbol *tlbl = newiTempLabel (NULL);
6096 if (AOP_TYPE (right) == AOP_CRY)
6099 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6103 int sizer = AOP_SIZE (right);
6105 // if val>>1 != 0, result = 1
6106 emitcode ("setb", "c");
6109 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6111 // test the msb of the lsb
6112 emitcode ("anl", "a,#0xfe");
6113 emitcode ("jnz", "%05d$", tlbl->key + 100);
6117 emitcode ("rrc", "a");
6119 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6120 emitcode ("cpl", "c");
6121 emitcode ("", "%05d$:", (tlbl->key + 100));
6128 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6129 genIfxJump (ifx, "c", left, right, result);
6133 if (sameRegs (AOP (result), AOP (left)))
6135 /* if left is same as result */
6136 for (; size--; offset++)
6138 if (AOP_TYPE (right) == AOP_LIT)
6140 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6142 else if (IS_AOP_PREG (left))
6144 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6145 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6146 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6149 emitcode ("xrl", "%s,%s",
6150 aopGet (AOP (left), offset, FALSE, TRUE),
6151 aopGet (AOP (right), offset, FALSE, FALSE));
6155 if (AOP_TYPE (left) == AOP_ACC)
6156 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6160 if (IS_AOP_PREG (left))
6162 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6163 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6166 emitcode ("xrl", "%s,a",
6167 aopGet (AOP (left), offset, FALSE, TRUE));
6174 // left & result in different registers
6175 if (AOP_TYPE (result) == AOP_CRY)
6178 // if(size), result in bit
6179 // if(!size && ifx), conditional oper: if(left ^ right)
6180 symbol *tlbl = newiTempLabel (NULL);
6181 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6183 emitcode ("setb", "c");
6186 if ((AOP_TYPE (right) == AOP_LIT) &&
6187 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6189 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6193 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6194 emitcode ("xrl", "a,%s",
6195 aopGet (AOP (right), offset, FALSE, FALSE));
6197 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6198 emitcode ("xrl", "a,%s",
6199 aopGet (AOP (left), offset, FALSE, FALSE));
6202 emitcode ("jnz", "%05d$", tlbl->key + 100);
6208 emitcode ("", "%05d$:", tlbl->key + 100);
6212 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6215 for (; (size--); offset++)
6218 // result = left & right
6219 if (AOP_TYPE (right) == AOP_LIT)
6221 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6223 aopPut (AOP (result),
6224 aopGet (AOP (left), offset, FALSE, FALSE),
6226 isOperandVolatile (result, FALSE));
6230 // faster than result <- left, anl result,right
6231 // and better if result is SFR
6232 if (AOP_TYPE (left) == AOP_ACC)
6233 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6236 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6237 emitcode ("xrl", "a,%s",
6238 aopGet (AOP (left), offset, FALSE, TRUE));
6240 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6245 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6246 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6247 freeAsmop (result, NULL, ic, TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genInline - write the inline code out */
6252 /*-----------------------------------------------------------------*/
6254 genInline (iCode * ic)
6256 char *buffer, *bp, *bp1;
6258 D(emitcode ("; genInline",""));
6260 _G.inLine += (!options.asmpeep);
6262 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6263 strcpy (buffer, IC_INLINE (ic));
6265 /* emit each line as a code */
6290 /* emitcode("",buffer); */
6291 _G.inLine -= (!options.asmpeep);
6294 /*-----------------------------------------------------------------*/
6295 /* genRRC - rotate right with carry */
6296 /*-----------------------------------------------------------------*/
6300 operand *left, *result;
6301 int size, offset = 0;
6304 D(emitcode ("; genRRC",""));
6306 /* rotate right with carry */
6307 left = IC_LEFT (ic);
6308 result = IC_RESULT (ic);
6309 aopOp (left, ic, FALSE);
6310 aopOp (result, ic, FALSE);
6312 /* move it to the result */
6313 size = AOP_SIZE (result);
6315 if (size == 1) { /* special case for 1 byte */
6316 l = aopGet (AOP (left), offset, FALSE, FALSE);
6318 emitcode ("rr", "a");
6324 l = aopGet (AOP (left), offset, FALSE, FALSE);
6326 emitcode ("rrc", "a");
6327 if (AOP_SIZE (result) > 1)
6328 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6330 /* now we need to put the carry into the
6331 highest order byte of the result */
6332 if (AOP_SIZE (result) > 1)
6334 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6337 emitcode ("mov", "acc.7,c");
6339 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6340 freeAsmop (left, NULL, ic, TRUE);
6341 freeAsmop (result, NULL, ic, TRUE);
6344 /*-----------------------------------------------------------------*/
6345 /* genRLC - generate code for rotate left with carry */
6346 /*-----------------------------------------------------------------*/
6350 operand *left, *result;
6351 int size, offset = 0;
6354 D(emitcode ("; genRLC",""));
6356 /* rotate right with carry */
6357 left = IC_LEFT (ic);
6358 result = IC_RESULT (ic);
6359 aopOp (left, ic, FALSE);
6360 aopOp (result, ic, FALSE);
6362 /* move it to the result */
6363 size = AOP_SIZE (result);
6367 l = aopGet (AOP (left), offset, FALSE, FALSE);
6369 if (size == 0) { /* special case for 1 byte */
6373 emitcode ("add", "a,acc");
6374 if (AOP_SIZE (result) > 1)
6375 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6378 l = aopGet (AOP (left), offset, FALSE, FALSE);
6380 emitcode ("rlc", "a");
6381 if (AOP_SIZE (result) > 1)
6382 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6385 /* now we need to put the carry into the
6386 highest order byte of the result */
6387 if (AOP_SIZE (result) > 1)
6389 l = aopGet (AOP (result), 0, FALSE, FALSE);
6392 emitcode ("mov", "acc.0,c");
6394 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6395 freeAsmop (left, NULL, ic, TRUE);
6396 freeAsmop (result, NULL, ic, TRUE);
6399 /*-----------------------------------------------------------------*/
6400 /* genGetHbit - generates code get highest order bit */
6401 /*-----------------------------------------------------------------*/
6403 genGetHbit (iCode * ic)
6405 operand *left, *result;
6407 D(emitcode ("; genGetHbit",""));
6409 left = IC_LEFT (ic);
6410 result = IC_RESULT (ic);
6411 aopOp (left, ic, FALSE);
6412 aopOp (result, ic, FALSE);
6414 /* get the highest order byte into a */
6415 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6416 if (AOP_TYPE (result) == AOP_CRY)
6418 emitcode ("rlc", "a");
6423 emitcode ("rl", "a");
6424 emitcode ("anl", "a,#0x01");
6429 freeAsmop (left, NULL, ic, TRUE);
6430 freeAsmop (result, NULL, ic, TRUE);
6433 /*-----------------------------------------------------------------*/
6434 /* genSwap - generates code to swap nibbles or bytes */
6435 /*-----------------------------------------------------------------*/
6437 genSwap (iCode * ic)
6439 operand *left, *result;
6441 D(emitcode ("; genSwap",""));
6443 left = IC_LEFT (ic);
6444 result = IC_RESULT (ic);
6445 aopOp (left, ic, FALSE);
6446 aopOp (result, ic, FALSE);
6448 switch (AOP_SIZE (left))
6450 case 1: /* swap nibbles in byte */
6451 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6452 emitcode ("swap", "a");
6453 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6455 case 2: /* swap bytes in word */
6456 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6458 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6459 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6460 0, isOperandVolatile (result, FALSE));
6461 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6463 else if (operandsEqu (left, result))
6466 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6467 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6469 emitcode ("mov", "b,a");
6472 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6473 0, isOperandVolatile (result, FALSE));
6474 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6478 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6479 0, isOperandVolatile (result, FALSE));
6480 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6481 1, isOperandVolatile (result, FALSE));
6485 wassertl(FALSE, "unsupported SWAP operand size");
6488 freeAsmop (left, NULL, ic, TRUE);
6489 freeAsmop (result, NULL, ic, TRUE);
6493 /*-----------------------------------------------------------------*/
6494 /* AccRol - rotate left accumulator by known count */
6495 /*-----------------------------------------------------------------*/
6497 AccRol (int shCount)
6499 shCount &= 0x0007; // shCount : 0..7
6506 emitcode ("rl", "a");
6509 emitcode ("rl", "a");
6510 emitcode ("rl", "a");
6513 emitcode ("swap", "a");
6514 emitcode ("rr", "a");
6517 emitcode ("swap", "a");
6520 emitcode ("swap", "a");
6521 emitcode ("rl", "a");
6524 emitcode ("rr", "a");
6525 emitcode ("rr", "a");
6528 emitcode ("rr", "a");
6533 /*-----------------------------------------------------------------*/
6534 /* AccLsh - left shift accumulator by known count */
6535 /*-----------------------------------------------------------------*/
6537 AccLsh (int shCount)
6542 emitcode ("add", "a,acc");
6543 else if (shCount == 2)
6545 emitcode ("add", "a,acc");
6546 emitcode ("add", "a,acc");
6550 /* rotate left accumulator */
6552 /* and kill the lower order bits */
6553 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6558 /*-----------------------------------------------------------------*/
6559 /* AccRsh - right shift accumulator by known count */
6560 /*-----------------------------------------------------------------*/
6562 AccRsh (int shCount)
6569 emitcode ("rrc", "a");
6573 /* rotate right accumulator */
6574 AccRol (8 - shCount);
6575 /* and kill the higher order bits */
6576 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6581 /*-----------------------------------------------------------------*/
6582 /* AccSRsh - signed right shift accumulator by known count */
6583 /*-----------------------------------------------------------------*/
6585 AccSRsh (int shCount)
6592 emitcode ("mov", "c,acc.7");
6593 emitcode ("rrc", "a");
6595 else if (shCount == 2)
6597 emitcode ("mov", "c,acc.7");
6598 emitcode ("rrc", "a");
6599 emitcode ("mov", "c,acc.7");
6600 emitcode ("rrc", "a");
6604 tlbl = newiTempLabel (NULL);
6605 /* rotate right accumulator */
6606 AccRol (8 - shCount);
6607 /* and kill the higher order bits */
6608 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6609 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6610 emitcode ("orl", "a,#0x%02x",
6611 (unsigned char) ~SRMask[shCount]);
6612 emitcode ("", "%05d$:", tlbl->key + 100);
6617 /*-----------------------------------------------------------------*/
6618 /* shiftR1Left2Result - shift right one byte from left to result */
6619 /*-----------------------------------------------------------------*/
6621 shiftR1Left2Result (operand * left, int offl,
6622 operand * result, int offr,
6623 int shCount, int sign)
6625 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6626 /* shift right accumulator */
6631 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6634 /*-----------------------------------------------------------------*/
6635 /* shiftL1Left2Result - shift left one byte from left to result */
6636 /*-----------------------------------------------------------------*/
6638 shiftL1Left2Result (operand * left, int offl,
6639 operand * result, int offr, int shCount)
6642 l = aopGet (AOP (left), offl, FALSE, FALSE);
6644 /* shift left accumulator */
6646 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6649 /*-----------------------------------------------------------------*/
6650 /* movLeft2Result - move byte from left to result */
6651 /*-----------------------------------------------------------------*/
6653 movLeft2Result (operand * left, int offl,
6654 operand * result, int offr, int sign)
6657 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6659 l = aopGet (AOP (left), offl, FALSE, FALSE);
6661 if (*l == '@' && (IS_AOP_PREG (result)))
6663 emitcode ("mov", "a,%s", l);
6664 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6669 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6672 /* MSB sign in acc.7 ! */
6673 if (getDataSize (left) == offl + 1)
6675 emitcode ("mov", "a,%s", l);
6676 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6683 /*-----------------------------------------------------------------*/
6684 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6685 /*-----------------------------------------------------------------*/
6689 emitcode ("rrc", "a");
6690 emitcode ("xch", "a,%s", x);
6691 emitcode ("rrc", "a");
6692 emitcode ("xch", "a,%s", x);
6695 /*-----------------------------------------------------------------*/
6696 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6697 /*-----------------------------------------------------------------*/
6701 emitcode ("xch", "a,%s", x);
6702 emitcode ("rlc", "a");
6703 emitcode ("xch", "a,%s", x);
6704 emitcode ("rlc", "a");
6707 /*-----------------------------------------------------------------*/
6708 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6709 /*-----------------------------------------------------------------*/
6713 emitcode ("xch", "a,%s", x);
6714 emitcode ("add", "a,acc");
6715 emitcode ("xch", "a,%s", x);
6716 emitcode ("rlc", "a");
6719 /*-----------------------------------------------------------------*/
6720 /* AccAXLsh - left shift a:x by known count (0..7) */
6721 /*-----------------------------------------------------------------*/
6723 AccAXLsh (char *x, int shCount)
6738 case 5: // AAAAABBB:CCCCCDDD
6740 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6742 emitcode ("anl", "a,#0x%02x",
6743 SLMask[shCount]); // BBB00000:CCCCCDDD
6745 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6747 AccRol (shCount); // DDDCCCCC:BBB00000
6749 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6751 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6753 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6755 emitcode ("anl", "a,#0x%02x",
6756 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6758 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6760 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6763 case 6: // AAAAAABB:CCCCCCDD
6764 emitcode ("anl", "a,#0x%02x",
6765 SRMask[shCount]); // 000000BB:CCCCCCDD
6766 emitcode ("mov", "c,acc.0"); // c = B
6767 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6769 AccAXRrl1 (x); // BCCCCCCD:D000000B
6770 AccAXRrl1 (x); // BBCCCCCC:DD000000
6772 emitcode("rrc","a");
6773 emitcode("xch","a,%s", x);
6774 emitcode("rrc","a");
6775 emitcode("mov","c,acc.0"); //<< get correct bit
6776 emitcode("xch","a,%s", x);
6778 emitcode("rrc","a");
6779 emitcode("xch","a,%s", x);
6780 emitcode("rrc","a");
6781 emitcode("xch","a,%s", x);
6784 case 7: // a:x <<= 7
6786 emitcode ("anl", "a,#0x%02x",
6787 SRMask[shCount]); // 0000000B:CCCCCCCD
6789 emitcode ("mov", "c,acc.0"); // c = B
6791 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6793 AccAXRrl1 (x); // BCCCCCCC:D0000000
6801 /*-----------------------------------------------------------------*/
6802 /* AccAXRsh - right shift a:x known count (0..7) */
6803 /*-----------------------------------------------------------------*/
6805 AccAXRsh (char *x, int shCount)
6813 AccAXRrl1 (x); // 0->a:x
6818 AccAXRrl1 (x); // 0->a:x
6821 AccAXRrl1 (x); // 0->a:x
6826 case 5: // AAAAABBB:CCCCCDDD = a:x
6828 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6830 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6832 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6834 emitcode ("anl", "a,#0x%02x",
6835 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6837 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6839 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6841 emitcode ("anl", "a,#0x%02x",
6842 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6844 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6846 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6848 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6851 case 6: // AABBBBBB:CCDDDDDD
6853 emitcode ("mov", "c,acc.7");
6854 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6856 emitcode ("mov", "c,acc.7");
6857 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6859 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6861 emitcode ("anl", "a,#0x%02x",
6862 SRMask[shCount]); // 000000AA:BBBBBBCC
6865 case 7: // ABBBBBBB:CDDDDDDD
6867 emitcode ("mov", "c,acc.7"); // c = A
6869 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6871 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6873 emitcode ("anl", "a,#0x%02x",
6874 SRMask[shCount]); // 0000000A:BBBBBBBC
6882 /*-----------------------------------------------------------------*/
6883 /* AccAXRshS - right shift signed a:x known count (0..7) */
6884 /*-----------------------------------------------------------------*/
6886 AccAXRshS (char *x, int shCount)
6894 emitcode ("mov", "c,acc.7");
6895 AccAXRrl1 (x); // s->a:x
6899 emitcode ("mov", "c,acc.7");
6900 AccAXRrl1 (x); // s->a:x
6902 emitcode ("mov", "c,acc.7");
6903 AccAXRrl1 (x); // s->a:x
6908 case 5: // AAAAABBB:CCCCCDDD = a:x
6910 tlbl = newiTempLabel (NULL);
6911 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6913 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6915 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6917 emitcode ("anl", "a,#0x%02x",
6918 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6920 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6922 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6924 emitcode ("anl", "a,#0x%02x",
6925 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6927 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6929 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6931 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6933 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6934 emitcode ("orl", "a,#0x%02x",
6935 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6937 emitcode ("", "%05d$:", tlbl->key + 100);
6938 break; // SSSSAAAA:BBBCCCCC
6940 case 6: // AABBBBBB:CCDDDDDD
6942 tlbl = newiTempLabel (NULL);
6943 emitcode ("mov", "c,acc.7");
6944 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6946 emitcode ("mov", "c,acc.7");
6947 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6949 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6951 emitcode ("anl", "a,#0x%02x",
6952 SRMask[shCount]); // 000000AA:BBBBBBCC
6954 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6955 emitcode ("orl", "a,#0x%02x",
6956 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6958 emitcode ("", "%05d$:", tlbl->key + 100);
6960 case 7: // ABBBBBBB:CDDDDDDD
6962 tlbl = newiTempLabel (NULL);
6963 emitcode ("mov", "c,acc.7"); // c = A
6965 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6967 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6969 emitcode ("anl", "a,#0x%02x",
6970 SRMask[shCount]); // 0000000A:BBBBBBBC
6972 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6973 emitcode ("orl", "a,#0x%02x",
6974 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6976 emitcode ("", "%05d$:", tlbl->key + 100);
6983 /*-----------------------------------------------------------------*/
6984 /* shiftL2Left2Result - shift left two bytes from left to result */
6985 /*-----------------------------------------------------------------*/
6987 shiftL2Left2Result (operand * left, int offl,
6988 operand * result, int offr, int shCount)
6990 if (sameRegs (AOP (result), AOP (left)) &&
6991 ((offl + MSB16) == offr))
6993 /* don't crash result[offr] */
6994 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6995 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6999 movLeft2Result (left, offl, result, offr, 0);
7000 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7002 /* ax << shCount (x = lsb(result)) */
7003 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7004 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7008 /*-----------------------------------------------------------------*/
7009 /* shiftR2Left2Result - shift right two bytes from left to result */
7010 /*-----------------------------------------------------------------*/
7012 shiftR2Left2Result (operand * left, int offl,
7013 operand * result, int offr,
7014 int shCount, int sign)
7016 if (sameRegs (AOP (result), AOP (left)) &&
7017 ((offl + MSB16) == offr))
7019 /* don't crash result[offr] */
7020 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7021 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7025 movLeft2Result (left, offl, result, offr, 0);
7026 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7028 /* a:x >> shCount (x = lsb(result)) */
7030 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7032 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7033 if (getDataSize (result) > 1)
7034 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7037 /*-----------------------------------------------------------------*/
7038 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7039 /*-----------------------------------------------------------------*/
7041 shiftLLeftOrResult (operand * left, int offl,
7042 operand * result, int offr, int shCount)
7044 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7045 /* shift left accumulator */
7047 /* or with result */
7048 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7049 /* back to result */
7050 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7053 /*-----------------------------------------------------------------*/
7054 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7055 /*-----------------------------------------------------------------*/
7057 shiftRLeftOrResult (operand * left, int offl,
7058 operand * result, int offr, int shCount)
7060 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7061 /* shift right accumulator */
7063 /* or with result */
7064 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7065 /* back to result */
7066 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7069 /*-----------------------------------------------------------------*/
7070 /* genlshOne - left shift a one byte quantity by known count */
7071 /*-----------------------------------------------------------------*/
7073 genlshOne (operand * result, operand * left, int shCount)
7075 D(emitcode ("; genlshOne",""));
7077 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7080 /*-----------------------------------------------------------------*/
7081 /* genlshTwo - left shift two bytes by known amount != 0 */
7082 /*-----------------------------------------------------------------*/
7084 genlshTwo (operand * result, operand * left, int shCount)
7088 D(emitcode ("; genlshTwo",""));
7090 size = getDataSize (result);
7092 /* if shCount >= 8 */
7100 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7102 movLeft2Result (left, LSB, result, MSB16, 0);
7104 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7107 /* 1 <= shCount <= 7 */
7111 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7113 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7117 /*-----------------------------------------------------------------*/
7118 /* shiftLLong - shift left one long from left to result */
7119 /* offl = LSB or MSB16 */
7120 /*-----------------------------------------------------------------*/
7122 shiftLLong (operand * left, operand * result, int offr)
7125 int size = AOP_SIZE (result);
7127 if (size >= LSB + offr)
7129 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7131 emitcode ("add", "a,acc");
7132 if (sameRegs (AOP (left), AOP (result)) &&
7133 size >= MSB16 + offr && offr != LSB)
7134 emitcode ("xch", "a,%s",
7135 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7137 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7140 if (size >= MSB16 + offr)
7142 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7144 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7147 emitcode ("rlc", "a");
7148 if (sameRegs (AOP (left), AOP (result)) &&
7149 size >= MSB24 + offr && offr != LSB)
7150 emitcode ("xch", "a,%s",
7151 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7153 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7156 if (size >= MSB24 + offr)
7158 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7160 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7163 emitcode ("rlc", "a");
7164 if (sameRegs (AOP (left), AOP (result)) &&
7165 size >= MSB32 + offr && offr != LSB)
7166 emitcode ("xch", "a,%s",
7167 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7169 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7172 if (size > MSB32 + offr)
7174 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7176 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7179 emitcode ("rlc", "a");
7180 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7183 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7186 /*-----------------------------------------------------------------*/
7187 /* genlshFour - shift four byte by a known amount != 0 */
7188 /*-----------------------------------------------------------------*/
7190 genlshFour (operand * result, operand * left, int shCount)
7194 D(emitcode ("; genlshFour",""));
7196 size = AOP_SIZE (result);
7198 /* if shifting more that 3 bytes */
7203 /* lowest order of left goes to the highest
7204 order of the destination */
7205 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7207 movLeft2Result (left, LSB, result, MSB32, 0);
7208 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7209 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7210 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7214 /* more than two bytes */
7215 else if (shCount >= 16)
7217 /* lower order two bytes goes to higher order two bytes */
7219 /* if some more remaining */
7221 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7224 movLeft2Result (left, MSB16, result, MSB32, 0);
7225 movLeft2Result (left, LSB, result, MSB24, 0);
7227 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7228 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7232 /* if more than 1 byte */
7233 else if (shCount >= 8)
7235 /* lower order three bytes goes to higher order three bytes */
7240 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7242 movLeft2Result (left, LSB, result, MSB16, 0);
7248 movLeft2Result (left, MSB24, result, MSB32, 0);
7249 movLeft2Result (left, MSB16, result, MSB24, 0);
7250 movLeft2Result (left, LSB, result, MSB16, 0);
7251 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7253 else if (shCount == 1)
7254 shiftLLong (left, result, MSB16);
7257 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7258 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7259 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7260 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7265 /* 1 <= shCount <= 7 */
7266 else if (shCount <= 2)
7268 shiftLLong (left, result, LSB);
7270 shiftLLong (result, result, LSB);
7272 /* 3 <= shCount <= 7, optimize */
7275 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7276 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7277 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7281 /*-----------------------------------------------------------------*/
7282 /* genLeftShiftLiteral - left shifting by known count */
7283 /*-----------------------------------------------------------------*/
7285 genLeftShiftLiteral (operand * left,
7290 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7293 D(emitcode ("; genLeftShiftLiteral",""));
7295 freeAsmop (right, NULL, ic, TRUE);
7297 aopOp (left, ic, FALSE);
7298 aopOp (result, ic, FALSE);
7300 size = getSize (operandType (result));
7303 emitcode ("; shift left ", "result %d, left %d", size,
7307 /* I suppose that the left size >= result size */
7312 movLeft2Result (left, size, result, size, 0);
7316 else if (shCount >= (size * 8))
7318 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7324 genlshOne (result, left, shCount);
7328 genlshTwo (result, left, shCount);
7332 genlshFour (result, left, shCount);
7335 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7336 "*** ack! mystery literal shift!\n");
7340 freeAsmop (left, NULL, ic, TRUE);
7341 freeAsmop (result, NULL, ic, TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genLeftShift - generates code for left shifting */
7346 /*-----------------------------------------------------------------*/
7348 genLeftShift (iCode * ic)
7350 operand *left, *right, *result;
7353 symbol *tlbl, *tlbl1;
7355 D(emitcode ("; genLeftShift",""));
7357 right = IC_RIGHT (ic);
7358 left = IC_LEFT (ic);
7359 result = IC_RESULT (ic);
7361 aopOp (right, ic, FALSE);
7363 /* if the shift count is known then do it
7364 as efficiently as possible */
7365 if (AOP_TYPE (right) == AOP_LIT)
7367 genLeftShiftLiteral (left, right, result, ic);
7371 /* shift count is unknown then we have to form
7372 a loop get the loop count in B : Note: we take
7373 only the lower order byte since shifting
7374 more that 32 bits make no sense anyway, ( the
7375 largest size of an object can be only 32 bits ) */
7377 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7378 emitcode ("inc", "b");
7379 freeAsmop (right, NULL, ic, TRUE);
7380 aopOp (left, ic, FALSE);
7381 aopOp (result, ic, FALSE);
7383 /* now move the left to the result if they are not the
7385 if (!sameRegs (AOP (left), AOP (result)) &&
7386 AOP_SIZE (result) > 1)
7389 size = AOP_SIZE (result);
7393 l = aopGet (AOP (left), offset, FALSE, TRUE);
7394 if (*l == '@' && (IS_AOP_PREG (result)))
7397 emitcode ("mov", "a,%s", l);
7398 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7401 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7406 tlbl = newiTempLabel (NULL);
7407 size = AOP_SIZE (result);
7409 tlbl1 = newiTempLabel (NULL);
7411 /* if it is only one byte then */
7414 symbol *tlbl1 = newiTempLabel (NULL);
7416 l = aopGet (AOP (left), 0, FALSE, FALSE);
7418 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7419 emitcode ("", "%05d$:", tlbl->key + 100);
7420 emitcode ("add", "a,acc");
7421 emitcode ("", "%05d$:", tlbl1->key + 100);
7422 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7423 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7427 reAdjustPreg (AOP (result));
7429 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7430 emitcode ("", "%05d$:", tlbl->key + 100);
7431 l = aopGet (AOP (result), offset, FALSE, FALSE);
7433 emitcode ("add", "a,acc");
7434 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7437 l = aopGet (AOP (result), offset, FALSE, FALSE);
7439 emitcode ("rlc", "a");
7440 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7442 reAdjustPreg (AOP (result));
7444 emitcode ("", "%05d$:", tlbl1->key + 100);
7445 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7447 freeAsmop (left, NULL, ic, TRUE);
7448 freeAsmop (result, NULL, ic, TRUE);
7451 /*-----------------------------------------------------------------*/
7452 /* genrshOne - right shift a one byte quantity by known count */
7453 /*-----------------------------------------------------------------*/
7455 genrshOne (operand * result, operand * left,
7456 int shCount, int sign)
7458 D(emitcode ("; genrshOne",""));
7460 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7463 /*-----------------------------------------------------------------*/
7464 /* genrshTwo - right shift two bytes by known amount != 0 */
7465 /*-----------------------------------------------------------------*/
7467 genrshTwo (operand * result, operand * left,
7468 int shCount, int sign)
7470 D(emitcode ("; genrshTwo",""));
7472 /* if shCount >= 8 */
7477 shiftR1Left2Result (left, MSB16, result, LSB,
7480 movLeft2Result (left, MSB16, result, LSB, sign);
7481 addSign (result, MSB16, sign);
7484 /* 1 <= shCount <= 7 */
7486 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7489 /*-----------------------------------------------------------------*/
7490 /* shiftRLong - shift right one long from left to result */
7491 /* offl = LSB or MSB16 */
7492 /*-----------------------------------------------------------------*/
7494 shiftRLong (operand * left, int offl,
7495 operand * result, int sign)
7497 int isSameRegs=sameRegs(AOP(left),AOP(result));
7499 if (isSameRegs && offl>1) {
7500 // we are in big trouble, but this shouldn't happen
7501 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7504 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7509 emitcode ("rlc", "a");
7510 emitcode ("subb", "a,acc");
7512 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7514 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7515 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7518 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7523 emitcode ("clr", "c");
7525 emitcode ("mov", "c,acc.7");
7528 emitcode ("rrc", "a");
7530 if (isSameRegs && offl==MSB16) {
7531 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7533 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7534 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7537 emitcode ("rrc", "a");
7538 if (isSameRegs && offl==1) {
7539 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7541 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7542 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7544 emitcode ("rrc", "a");
7545 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7549 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7550 emitcode ("rrc", "a");
7551 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7555 /*-----------------------------------------------------------------*/
7556 /* genrshFour - shift four byte by a known amount != 0 */
7557 /*-----------------------------------------------------------------*/
7559 genrshFour (operand * result, operand * left,
7560 int shCount, int sign)
7562 D(emitcode ("; genrshFour",""));
7564 /* if shifting more that 3 bytes */
7569 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7571 movLeft2Result (left, MSB32, result, LSB, sign);
7572 addSign (result, MSB16, sign);
7574 else if (shCount >= 16)
7578 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7581 movLeft2Result (left, MSB24, result, LSB, 0);
7582 movLeft2Result (left, MSB32, result, MSB16, sign);
7584 addSign (result, MSB24, sign);
7586 else if (shCount >= 8)
7590 shiftRLong (left, MSB16, result, sign);
7591 else if (shCount == 0)
7593 movLeft2Result (left, MSB16, result, LSB, 0);
7594 movLeft2Result (left, MSB24, result, MSB16, 0);
7595 movLeft2Result (left, MSB32, result, MSB24, sign);
7596 addSign (result, MSB32, sign);
7600 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7601 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7602 /* the last shift is signed */
7603 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7604 addSign (result, MSB32, sign);
7608 { /* 1 <= shCount <= 7 */
7611 shiftRLong (left, LSB, result, sign);
7613 shiftRLong (result, LSB, result, sign);
7617 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7618 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7619 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7624 /*-----------------------------------------------------------------*/
7625 /* genRightShiftLiteral - right shifting by known count */
7626 /*-----------------------------------------------------------------*/
7628 genRightShiftLiteral (operand * left,
7634 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7637 D(emitcode ("; genRightShiftLiteral",""));
7639 freeAsmop (right, NULL, ic, TRUE);
7641 aopOp (left, ic, FALSE);
7642 aopOp (result, ic, FALSE);
7645 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7649 size = getDataSize (left);
7650 /* test the LEFT size !!! */
7652 /* I suppose that the left size >= result size */
7655 size = getDataSize (result);
7657 movLeft2Result (left, size, result, size, 0);
7660 else if (shCount >= (size * 8))
7663 /* get sign in acc.7 */
7664 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7666 addSign (result, LSB, sign);
7673 genrshOne (result, left, shCount, sign);
7677 genrshTwo (result, left, shCount, sign);
7681 genrshFour (result, left, shCount, sign);
7687 freeAsmop (left, NULL, ic, TRUE);
7688 freeAsmop (result, NULL, ic, TRUE);
7691 /*-----------------------------------------------------------------*/
7692 /* genSignedRightShift - right shift of signed number */
7693 /*-----------------------------------------------------------------*/
7695 genSignedRightShift (iCode * ic)
7697 operand *right, *left, *result;
7700 symbol *tlbl, *tlbl1;
7702 D(emitcode ("; genSignedRightShift",""));
7704 /* we do it the hard way put the shift count in b
7705 and loop thru preserving the sign */
7707 right = IC_RIGHT (ic);
7708 left = IC_LEFT (ic);
7709 result = IC_RESULT (ic);
7711 aopOp (right, ic, FALSE);
7714 if (AOP_TYPE (right) == AOP_LIT)
7716 genRightShiftLiteral (left, right, result, ic, 1);
7719 /* shift count is unknown then we have to form
7720 a loop get the loop count in B : Note: we take
7721 only the lower order byte since shifting
7722 more that 32 bits make no sense anyway, ( the
7723 largest size of an object can be only 32 bits ) */
7725 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7726 emitcode ("inc", "b");
7727 freeAsmop (right, NULL, ic, TRUE);
7728 aopOp (left, ic, FALSE);
7729 aopOp (result, ic, FALSE);
7731 /* now move the left to the result if they are not the
7733 if (!sameRegs (AOP (left), AOP (result)) &&
7734 AOP_SIZE (result) > 1)
7737 size = AOP_SIZE (result);
7741 l = aopGet (AOP (left), offset, FALSE, TRUE);
7742 if (*l == '@' && IS_AOP_PREG (result))
7745 emitcode ("mov", "a,%s", l);
7746 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7749 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7754 /* mov the highest order bit to OVR */
7755 tlbl = newiTempLabel (NULL);
7756 tlbl1 = newiTempLabel (NULL);
7758 size = AOP_SIZE (result);
7760 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7761 emitcode ("rlc", "a");
7762 emitcode ("mov", "ov,c");
7763 /* if it is only one byte then */
7766 l = aopGet (AOP (left), 0, FALSE, FALSE);
7768 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7769 emitcode ("", "%05d$:", tlbl->key + 100);
7770 emitcode ("mov", "c,ov");
7771 emitcode ("rrc", "a");
7772 emitcode ("", "%05d$:", tlbl1->key + 100);
7773 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7774 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7778 reAdjustPreg (AOP (result));
7779 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7780 emitcode ("", "%05d$:", tlbl->key + 100);
7781 emitcode ("mov", "c,ov");
7784 l = aopGet (AOP (result), offset, FALSE, FALSE);
7786 emitcode ("rrc", "a");
7787 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7789 reAdjustPreg (AOP (result));
7790 emitcode ("", "%05d$:", tlbl1->key + 100);
7791 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7794 freeAsmop (left, NULL, ic, TRUE);
7795 freeAsmop (result, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genRightShift - generate code for right shifting */
7800 /*-----------------------------------------------------------------*/
7802 genRightShift (iCode * ic)
7804 operand *right, *left, *result;
7808 symbol *tlbl, *tlbl1;
7810 D(emitcode ("; genRightShift",""));
7812 /* if signed then we do it the hard way preserve the
7813 sign bit moving it inwards */
7814 letype = getSpec (operandType (IC_LEFT (ic)));
7816 if (!SPEC_USIGN (letype))
7818 genSignedRightShift (ic);
7822 /* signed & unsigned types are treated the same : i.e. the
7823 signed is NOT propagated inwards : quoting from the
7824 ANSI - standard : "for E1 >> E2, is equivalent to division
7825 by 2**E2 if unsigned or if it has a non-negative value,
7826 otherwise the result is implementation defined ", MY definition
7827 is that the sign does not get propagated */
7829 right = IC_RIGHT (ic);
7830 left = IC_LEFT (ic);
7831 result = IC_RESULT (ic);
7833 aopOp (right, ic, FALSE);
7835 /* if the shift count is known then do it
7836 as efficiently as possible */
7837 if (AOP_TYPE (right) == AOP_LIT)
7839 genRightShiftLiteral (left, right, result, ic, 0);
7843 /* shift count is unknown then we have to form
7844 a loop get the loop count in B : Note: we take
7845 only the lower order byte since shifting
7846 more that 32 bits make no sense anyway, ( the
7847 largest size of an object can be only 32 bits ) */
7849 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7850 emitcode ("inc", "b");
7851 freeAsmop (right, NULL, ic, TRUE);
7852 aopOp (left, ic, FALSE);
7853 aopOp (result, ic, FALSE);
7855 /* now move the left to the result if they are not the
7857 if (!sameRegs (AOP (left), AOP (result)) &&
7858 AOP_SIZE (result) > 1)
7861 size = AOP_SIZE (result);
7865 l = aopGet (AOP (left), offset, FALSE, TRUE);
7866 if (*l == '@' && IS_AOP_PREG (result))
7869 emitcode ("mov", "a,%s", l);
7870 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7873 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7878 tlbl = newiTempLabel (NULL);
7879 tlbl1 = newiTempLabel (NULL);
7880 size = AOP_SIZE (result);
7883 /* if it is only one byte then */
7886 l = aopGet (AOP (left), 0, FALSE, FALSE);
7888 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7889 emitcode ("", "%05d$:", tlbl->key + 100);
7891 emitcode ("rrc", "a");
7892 emitcode ("", "%05d$:", tlbl1->key + 100);
7893 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7894 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7898 reAdjustPreg (AOP (result));
7899 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7900 emitcode ("", "%05d$:", tlbl->key + 100);
7904 l = aopGet (AOP (result), offset, FALSE, FALSE);
7906 emitcode ("rrc", "a");
7907 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7909 reAdjustPreg (AOP (result));
7911 emitcode ("", "%05d$:", tlbl1->key + 100);
7912 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7915 freeAsmop (left, NULL, ic, TRUE);
7916 freeAsmop (result, NULL, ic, TRUE);
7919 /*-----------------------------------------------------------------*/
7920 /* emitPtrByteGet - emits code to get a byte into A through a */
7921 /* pointer register (R0, R1, or DPTR). The */
7922 /* original value of A can be preserved in B. */
7923 /*-----------------------------------------------------------------*/
7925 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7932 emitcode ("mov", "b,a");
7933 emitcode ("mov", "a,@%s", rname);
7938 emitcode ("mov", "b,a");
7939 emitcode ("movx", "a,@%s", rname);
7944 emitcode ("mov", "b,a");
7945 emitcode ("movx", "a,@dptr");
7950 emitcode ("mov", "b,a");
7951 emitcode ("clr", "a");
7952 emitcode ("movc", "a,@a+dptr");
7958 emitcode ("push", "b");
7959 emitcode ("push", "acc");
7961 emitcode ("lcall", "__gptrget");
7963 emitcode ("pop", "b");
7968 /*-----------------------------------------------------------------*/
7969 /* emitPtrByteSet - emits code to set a byte from src through a */
7970 /* pointer register (R0, R1, or DPTR). */
7971 /*-----------------------------------------------------------------*/
7973 emitPtrByteSet (char *rname, int p_type, char *src)
7982 emitcode ("mov", "@%s,a", rname);
7985 emitcode ("mov", "@%s,%s", rname, src);
7990 emitcode ("movx", "@%s,a", rname);
7995 emitcode ("movx", "@dptr,a");
8000 emitcode ("lcall", "__gptrput");
8005 /*-----------------------------------------------------------------*/
8006 /* genUnpackBits - generates code for unpacking bits */
8007 /*-----------------------------------------------------------------*/
8009 genUnpackBits (operand * result, char *rname, int ptype)
8011 int offset = 0; /* result byte offset */
8012 int rsize; /* result size */
8013 int rlen = 0; /* remaining bitfield length */
8014 sym_link *etype; /* bitfield type information */
8015 int blen; /* bitfield length */
8016 int bstr; /* bitfield starting bit within byte */
8018 D(emitcode ("; genUnpackBits",""));
8020 etype = getSpec (operandType (result));
8021 rsize = getSize (operandType (result));
8022 blen = SPEC_BLEN (etype);
8023 bstr = SPEC_BSTR (etype);
8025 /* If the bitfield length is less than a byte */
8028 emitPtrByteGet (rname, ptype, FALSE);
8030 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8031 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8035 /* Bit field did not fit in a byte. Copy all
8036 but the partial byte at the end. */
8037 for (rlen=blen;rlen>=8;rlen-=8)
8039 emitPtrByteGet (rname, ptype, FALSE);
8040 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8042 emitcode ("inc", "%s", rname);
8045 /* Handle the partial byte at the end */
8048 emitPtrByteGet (rname, ptype, FALSE);
8049 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8050 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8058 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8063 /*-----------------------------------------------------------------*/
8064 /* genDataPointerGet - generates code when ptr offset is known */
8065 /*-----------------------------------------------------------------*/
8067 genDataPointerGet (operand * left,
8073 int size, offset = 0;
8075 D(emitcode ("; genDataPointerGet",""));
8077 aopOp (result, ic, TRUE);
8079 /* get the string representation of the name */
8080 l = aopGet (AOP (left), 0, FALSE, TRUE);
8081 size = AOP_SIZE (result);
8085 sprintf (buffer, "(%s + %d)", l + 1, offset);
8087 sprintf (buffer, "%s", l + 1);
8088 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8091 freeAsmop (left, NULL, ic, TRUE);
8092 freeAsmop (result, NULL, ic, TRUE);
8095 /*-----------------------------------------------------------------*/
8096 /* genNearPointerGet - emitcode for near pointer fetch */
8097 /*-----------------------------------------------------------------*/
8099 genNearPointerGet (operand * left,
8107 sym_link *rtype, *retype;
8108 sym_link *ltype = operandType (left);
8111 D(emitcode ("; genNearPointerGet",""));
8113 rtype = operandType (result);
8114 retype = getSpec (rtype);
8116 aopOp (left, ic, FALSE);
8118 /* if left is rematerialisable and
8119 result is not bitfield variable type and
8120 the left is pointer to data space i.e
8121 lower 128 bytes of space */
8122 if (AOP_TYPE (left) == AOP_IMMD &&
8123 !IS_BITFIELD (retype) &&
8124 DCL_TYPE (ltype) == POINTER)
8126 genDataPointerGet (left, result, ic);
8130 /* if the value is already in a pointer register
8131 then don't need anything more */
8132 if (!AOP_INPREG (AOP (left)))
8134 if (IS_AOP_PREG (left))
8136 // Aha, it is a pointer, just in disguise.
8137 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8140 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8141 __FILE__, __LINE__);
8146 emitcode ("mov", "a%s,%s", rname + 1, rname);
8147 rname++; // skip the '@'.
8152 /* otherwise get a free pointer register */
8154 preg = getFreePtr (ic, &aop, FALSE);
8155 emitcode ("mov", "%s,%s",
8157 aopGet (AOP (left), 0, FALSE, TRUE));
8162 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8164 //aopOp (result, ic, FALSE);
8165 aopOp (result, ic, result?TRUE:FALSE);
8167 /* if bitfield then unpack the bits */
8168 if (IS_BITFIELD (retype))
8169 genUnpackBits (result, rname, POINTER);
8172 /* we have can just get the values */
8173 int size = AOP_SIZE (result);
8178 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8181 emitcode ("mov", "a,@%s", rname);
8182 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8186 sprintf (buffer, "@%s", rname);
8187 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8191 emitcode ("inc", "%s", rname);
8195 /* now some housekeeping stuff */
8196 if (aop) /* we had to allocate for this iCode */
8198 if (pi) { /* post increment present */
8199 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8201 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8205 /* we did not allocate which means left
8206 already in a pointer register, then
8207 if size > 0 && this could be used again
8208 we have to point it back to where it
8210 if ((AOP_SIZE (result) > 1 &&
8211 !OP_SYMBOL (left)->remat &&
8212 (OP_SYMBOL (left)->liveTo > ic->seq ||
8216 int size = AOP_SIZE (result) - 1;
8218 emitcode ("dec", "%s", rname);
8223 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8224 freeAsmop (left, NULL, ic, TRUE);
8225 if (pi) pi->generated = 1;
8228 /*-----------------------------------------------------------------*/
8229 /* genPagedPointerGet - emitcode for paged pointer fetch */
8230 /*-----------------------------------------------------------------*/
8232 genPagedPointerGet (operand * left,
8240 sym_link *rtype, *retype;
8242 D(emitcode ("; genPagedPointerGet",""));
8244 rtype = operandType (result);
8245 retype = getSpec (rtype);
8247 aopOp (left, ic, FALSE);
8249 /* if the value is already in a pointer register
8250 then don't need anything more */
8251 if (!AOP_INPREG (AOP (left)))
8253 /* otherwise get a free pointer register */
8255 preg = getFreePtr (ic, &aop, FALSE);
8256 emitcode ("mov", "%s,%s",
8258 aopGet (AOP (left), 0, FALSE, TRUE));
8262 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8264 aopOp (result, ic, FALSE);
8266 /* if bitfield then unpack the bits */
8267 if (IS_BITFIELD (retype))
8268 genUnpackBits (result, rname, PPOINTER);
8271 /* we have can just get the values */
8272 int size = AOP_SIZE (result);
8278 emitcode ("movx", "a,@%s", rname);
8279 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8284 emitcode ("inc", "%s", rname);
8288 /* now some housekeeping stuff */
8289 if (aop) /* we had to allocate for this iCode */
8291 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8292 freeAsmop (NULL, aop, ic, TRUE);
8296 /* we did not allocate which means left
8297 already in a pointer register, then
8298 if size > 0 && this could be used again
8299 we have to point it back to where it
8301 if ((AOP_SIZE (result) > 1 &&
8302 !OP_SYMBOL (left)->remat &&
8303 (OP_SYMBOL (left)->liveTo > ic->seq ||
8307 int size = AOP_SIZE (result) - 1;
8309 emitcode ("dec", "%s", rname);
8314 freeAsmop (left, NULL, ic, TRUE);
8315 freeAsmop (result, NULL, ic, TRUE);
8316 if (pi) pi->generated = 1;
8320 /*--------------------------------------------------------------------*/
8321 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8322 /*--------------------------------------------------------------------*/
8324 loadDptrFromOperand (operand *op, bool loadBToo)
8326 if (AOP_TYPE (op) != AOP_STR)
8328 /* if this is remateriazable */
8329 if (AOP_TYPE (op) == AOP_IMMD)
8331 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8334 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8335 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8338 wassertl(FALSE, "need pointerCode");
8339 emitcode ("", "; mov b,???");
8340 /* genPointerGet and genPointerSet originally did different
8341 ** things for this case. Both seem wrong.
8342 ** from genPointerGet:
8343 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8344 ** from genPointerSet:
8345 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8350 else if (AOP_TYPE (op) == AOP_DPTR)
8354 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8355 emitcode ("push", "acc");
8356 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8357 emitcode ("push", "acc");
8358 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8359 emitcode ("pop", "dph");
8360 emitcode ("pop", "dpl");
8364 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8365 emitcode ("push", "acc");
8366 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8367 emitcode ("pop", "dpl");
8371 { /* we need to get it byte by byte */
8372 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8373 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8375 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8380 /*-----------------------------------------------------------------*/
8381 /* genFarPointerGet - gget value from far space */
8382 /*-----------------------------------------------------------------*/
8384 genFarPointerGet (operand * left,
8385 operand * result, iCode * ic, iCode * pi)
8388 sym_link *retype = getSpec (operandType (result));
8390 D(emitcode ("; genFarPointerGet",""));
8392 aopOp (left, ic, FALSE);
8393 loadDptrFromOperand (left, FALSE);
8395 /* so dptr now contains the address */
8396 aopOp (result, ic, FALSE);
8398 /* if bit then unpack */
8399 if (IS_BITFIELD (retype))
8400 genUnpackBits (result, "dptr", FPOINTER);
8403 size = AOP_SIZE (result);
8408 emitcode ("movx", "a,@dptr");
8409 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8411 emitcode ("inc", "dptr");
8415 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8416 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8417 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8420 freeAsmop (left, NULL, ic, TRUE);
8421 freeAsmop (result, NULL, ic, TRUE);
8424 /*-----------------------------------------------------------------*/
8425 /* genCodePointerGet - gget value from code space */
8426 /*-----------------------------------------------------------------*/
8428 genCodePointerGet (operand * left,
8429 operand * result, iCode * ic, iCode *pi)
8432 sym_link *retype = getSpec (operandType (result));
8434 D(emitcode ("; genCodePointerGet",""));
8436 aopOp (left, ic, FALSE);
8437 loadDptrFromOperand (left, FALSE);
8439 /* so dptr now contains the address */
8440 aopOp (result, ic, FALSE);
8442 /* if bit then unpack */
8443 if (IS_BITFIELD (retype))
8444 genUnpackBits (result, "dptr", CPOINTER);
8447 size = AOP_SIZE (result);
8454 emitcode ("clr", "a");
8455 emitcode ("movc", "a,@a+dptr");
8456 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8457 emitcode ("inc", "dptr");
8461 emitcode ("mov", "a,#0x%02x", offset);
8462 emitcode ("movc", "a,@a+dptr");
8463 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8468 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8469 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8470 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8473 freeAsmop (left, NULL, ic, TRUE);
8474 freeAsmop (result, NULL, ic, TRUE);
8477 /*-----------------------------------------------------------------*/
8478 /* genGenPointerGet - gget value from generic pointer space */
8479 /*-----------------------------------------------------------------*/
8481 genGenPointerGet (operand * left,
8482 operand * result, iCode * ic, iCode *pi)
8485 sym_link *retype = getSpec (operandType (result));
8487 D(emitcode ("; genGenPointerGet",""));
8489 aopOp (left, ic, FALSE);
8490 loadDptrFromOperand (left, TRUE);
8492 /* so dptr know contains the address */
8493 aopOp (result, ic, FALSE);
8495 /* if bit then unpack */
8496 if (IS_BITFIELD (retype))
8497 genUnpackBits (result, "dptr", GPOINTER);
8500 size = AOP_SIZE (result);
8505 emitcode ("lcall", "__gptrget");
8506 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8508 emitcode ("inc", "dptr");
8512 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8513 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8514 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8517 freeAsmop (left, NULL, ic, TRUE);
8518 freeAsmop (result, NULL, ic, TRUE);
8521 /*-----------------------------------------------------------------*/
8522 /* genPointerGet - generate code for pointer get */
8523 /*-----------------------------------------------------------------*/
8525 genPointerGet (iCode * ic, iCode *pi)
8527 operand *left, *result;
8528 sym_link *type, *etype;
8531 D(emitcode ("; genPointerGet",""));
8533 left = IC_LEFT (ic);
8534 result = IC_RESULT (ic);
8536 /* depending on the type of pointer we need to
8537 move it to the correct pointer register */
8538 type = operandType (left);
8539 etype = getSpec (type);
8540 /* if left is of type of pointer then it is simple */
8541 if (IS_PTR (type) && !IS_FUNC (type->next))
8542 p_type = DCL_TYPE (type);
8545 /* we have to go by the storage class */
8546 p_type = PTR_TYPE (SPEC_OCLS (etype));
8549 /* special case when cast remat */
8550 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8551 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8552 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8553 type = operandType (left);
8554 p_type = DCL_TYPE (type);
8556 /* now that we have the pointer type we assign
8557 the pointer values */
8563 genNearPointerGet (left, result, ic, pi);
8567 genPagedPointerGet (left, result, ic, pi);
8571 genFarPointerGet (left, result, ic, pi);
8575 genCodePointerGet (left, result, ic, pi);
8579 genGenPointerGet (left, result, ic, pi);
8587 /*-----------------------------------------------------------------*/
8588 /* genPackBits - generates code for packed bit storage */
8589 /*-----------------------------------------------------------------*/
8591 genPackBits (sym_link * etype,
8593 char *rname, int p_type)
8595 int offset = 0; /* source byte offset */
8596 int rlen = 0; /* remaining bitfield length */
8597 int blen; /* bitfield length */
8598 int bstr; /* bitfield starting bit within byte */
8599 int litval; /* source literal value (if AOP_LIT) */
8600 unsigned char mask; /* bitmask within current byte */
8602 D(emitcode ("; genPackBits",""));
8604 blen = SPEC_BLEN (etype);
8605 bstr = SPEC_BSTR (etype);
8607 /* If the bitfield length is less than a byte */
8610 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8611 (unsigned char) (0xFF >> (8 - bstr)));
8613 if (AOP_TYPE (right) == AOP_LIT)
8615 /* Case with a bitfield length <8 and literal source
8617 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8619 litval &= (~mask) & 0xff;
8620 emitPtrByteGet (rname, p_type, FALSE);
8621 if ((mask|litval)!=0xff)
8622 emitcode ("anl","a,#0x%02x", mask);
8624 emitcode ("orl","a,#0x%02x", litval);
8628 if ((blen==1) && (p_type!=GPOINTER))
8630 /* Case with a bitfield length == 1 and no generic pointer
8632 if (AOP_TYPE (right) == AOP_CRY)
8633 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8636 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8637 emitcode ("rrc","a");
8639 emitPtrByteGet (rname, p_type, FALSE);
8640 emitcode ("mov","acc.%d,c",bstr);
8644 /* Case with a bitfield length < 8 and arbitrary source
8646 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8647 /* shift and mask source value */
8649 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8651 /* transfer A to B and get next byte */
8652 emitPtrByteGet (rname, p_type, TRUE);
8654 emitcode ("anl", "a,#0x%02x", mask);
8655 emitcode ("orl", "a,b");
8656 if (p_type == GPOINTER)
8657 emitcode ("pop", "b");
8661 emitPtrByteSet (rname, p_type, "a");
8665 /* Bit length is greater than 7 bits. In this case, copy */
8666 /* all except the partial byte at the end */
8667 for (rlen=blen;rlen>=8;rlen-=8)
8669 emitPtrByteSet (rname, p_type,
8670 aopGet (AOP (right), offset++, FALSE, TRUE) );
8672 emitcode ("inc", "%s", rname);
8675 /* If there was a partial byte at the end */
8678 mask = (((unsigned char) -1 << rlen) & 0xff);
8680 if (AOP_TYPE (right) == AOP_LIT)
8682 /* Case with partial byte and literal source
8684 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8685 litval >>= (blen-rlen);
8686 litval &= (~mask) & 0xff;
8687 emitPtrByteGet (rname, p_type, FALSE);
8688 if ((mask|litval)!=0xff)
8689 emitcode ("anl","a,#0x%02x", mask);
8691 emitcode ("orl","a,#0x%02x", litval);
8695 /* Case with partial byte and arbitrary source
8697 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8698 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8700 /* transfer A to B and get next byte */
8701 emitPtrByteGet (rname, p_type, TRUE);
8703 emitcode ("anl", "a,#0x%02x", mask);
8704 emitcode ("orl", "a,b");
8705 if (p_type == GPOINTER)
8706 emitcode ("pop", "b");
8708 emitPtrByteSet (rname, p_type, "a");
8714 /*-----------------------------------------------------------------*/
8715 /* genDataPointerSet - remat pointer to data space */
8716 /*-----------------------------------------------------------------*/
8718 genDataPointerSet (operand * right,
8722 int size, offset = 0;
8723 char *l, buffer[256];
8725 D(emitcode ("; genDataPointerSet",""));
8727 aopOp (right, ic, FALSE);
8729 l = aopGet (AOP (result), 0, FALSE, TRUE);
8730 size = AOP_SIZE (right);
8734 sprintf (buffer, "(%s + %d)", l + 1, offset);
8736 sprintf (buffer, "%s", l + 1);
8737 emitcode ("mov", "%s,%s", buffer,
8738 aopGet (AOP (right), offset++, FALSE, FALSE));
8741 freeAsmop (right, NULL, ic, TRUE);
8742 freeAsmop (result, NULL, ic, TRUE);
8745 /*-----------------------------------------------------------------*/
8746 /* genNearPointerSet - emitcode for near pointer put */
8747 /*-----------------------------------------------------------------*/
8749 genNearPointerSet (operand * right,
8757 sym_link *retype, *letype;
8758 sym_link *ptype = operandType (result);
8760 D(emitcode ("; genNearPointerSet",""));
8762 retype = getSpec (operandType (right));
8763 letype = getSpec (ptype);
8764 aopOp (result, ic, FALSE);
8766 /* if the result is rematerializable &
8767 in data space & not a bit variable */
8768 if (AOP_TYPE (result) == AOP_IMMD &&
8769 DCL_TYPE (ptype) == POINTER &&
8770 !IS_BITVAR (retype) &&
8771 !IS_BITVAR (letype))
8773 genDataPointerSet (right, result, ic);
8777 /* if the value is already in a pointer register
8778 then don't need anything more */
8779 if (!AOP_INPREG (AOP (result)))
8782 //AOP_TYPE (result) == AOP_STK
8786 // Aha, it is a pointer, just in disguise.
8787 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8790 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8791 __FILE__, __LINE__);
8796 emitcode ("mov", "a%s,%s", rname + 1, rname);
8797 rname++; // skip the '@'.
8802 /* otherwise get a free pointer register */
8804 preg = getFreePtr (ic, &aop, FALSE);
8805 emitcode ("mov", "%s,%s",
8807 aopGet (AOP (result), 0, FALSE, TRUE));
8813 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8816 aopOp (right, ic, FALSE);
8818 /* if bitfield then unpack the bits */
8819 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8820 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8823 /* we have can just get the values */
8824 int size = AOP_SIZE (right);
8829 l = aopGet (AOP (right), offset, FALSE, TRUE);
8833 emitcode ("mov", "@%s,a", rname);
8836 emitcode ("mov", "@%s,%s", rname, l);
8838 emitcode ("inc", "%s", rname);
8843 /* now some housekeeping stuff */
8844 if (aop) /* we had to allocate for this iCode */
8847 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8848 freeAsmop (NULL, aop, ic, TRUE);
8852 /* we did not allocate which means left
8853 already in a pointer register, then
8854 if size > 0 && this could be used again
8855 we have to point it back to where it
8857 if ((AOP_SIZE (right) > 1 &&
8858 !OP_SYMBOL (result)->remat &&
8859 (OP_SYMBOL (result)->liveTo > ic->seq ||
8863 int size = AOP_SIZE (right) - 1;
8865 emitcode ("dec", "%s", rname);
8870 if (pi) pi->generated = 1;
8871 freeAsmop (result, NULL, ic, TRUE);
8872 freeAsmop (right, NULL, ic, TRUE);
8875 /*-----------------------------------------------------------------*/
8876 /* genPagedPointerSet - emitcode for Paged pointer put */
8877 /*-----------------------------------------------------------------*/
8879 genPagedPointerSet (operand * right,
8887 sym_link *retype, *letype;
8889 D(emitcode ("; genPagedPointerSet",""));
8891 retype = getSpec (operandType (right));
8892 letype = getSpec (operandType (result));
8894 aopOp (result, ic, FALSE);
8896 /* if the value is already in a pointer register
8897 then don't need anything more */
8898 if (!AOP_INPREG (AOP (result)))
8900 /* otherwise get a free pointer register */
8902 preg = getFreePtr (ic, &aop, FALSE);
8903 emitcode ("mov", "%s,%s",
8905 aopGet (AOP (result), 0, FALSE, TRUE));
8909 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8911 aopOp (right, ic, FALSE);
8913 /* if bitfield then unpack the bits */
8914 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8915 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8918 /* we have can just get the values */
8919 int size = AOP_SIZE (right);
8924 l = aopGet (AOP (right), offset, FALSE, TRUE);
8927 emitcode ("movx", "@%s,a", rname);
8930 emitcode ("inc", "%s", rname);
8936 /* now some housekeeping stuff */
8937 if (aop) /* we had to allocate for this iCode */
8940 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8941 freeAsmop (NULL, aop, ic, TRUE);
8945 /* we did not allocate which means left
8946 already in a pointer register, then
8947 if size > 0 && this could be used again
8948 we have to point it back to where it
8950 if (AOP_SIZE (right) > 1 &&
8951 !OP_SYMBOL (result)->remat &&
8952 (OP_SYMBOL (result)->liveTo > ic->seq ||
8955 int size = AOP_SIZE (right) - 1;
8957 emitcode ("dec", "%s", rname);
8962 if (pi) pi->generated = 1;
8963 freeAsmop (result, NULL, ic, TRUE);
8964 freeAsmop (right, NULL, ic, TRUE);
8969 /*-----------------------------------------------------------------*/
8970 /* genFarPointerSet - set value from far space */
8971 /*-----------------------------------------------------------------*/
8973 genFarPointerSet (operand * right,
8974 operand * result, iCode * ic, iCode * pi)
8977 sym_link *retype = getSpec (operandType (right));
8978 sym_link *letype = getSpec (operandType (result));
8980 D(emitcode ("; genFarPointerSet",""));
8982 aopOp (result, ic, FALSE);
8983 loadDptrFromOperand (result, FALSE);
8985 /* so dptr know contains the address */
8986 aopOp (right, ic, FALSE);
8988 /* if bit then unpack */
8989 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8990 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8993 size = AOP_SIZE (right);
8998 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9000 emitcode ("movx", "@dptr,a");
9002 emitcode ("inc", "dptr");
9005 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9006 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9007 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9010 freeAsmop (result, NULL, ic, TRUE);
9011 freeAsmop (right, NULL, ic, TRUE);
9014 /*-----------------------------------------------------------------*/
9015 /* genGenPointerSet - set value from generic pointer space */
9016 /*-----------------------------------------------------------------*/
9018 genGenPointerSet (operand * right,
9019 operand * result, iCode * ic, iCode * pi)
9022 sym_link *retype = getSpec (operandType (right));
9023 sym_link *letype = getSpec (operandType (result));
9025 D(emitcode ("; genGenPointerSet",""));
9027 aopOp (result, ic, FALSE);
9028 loadDptrFromOperand (result, TRUE);
9030 /* so dptr know contains the address */
9031 aopOp (right, ic, FALSE);
9033 /* if bit then unpack */
9034 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9035 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9038 size = AOP_SIZE (right);
9043 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9045 emitcode ("lcall", "__gptrput");
9047 emitcode ("inc", "dptr");
9051 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9052 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9053 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9056 freeAsmop (result, NULL, ic, TRUE);
9057 freeAsmop (right, NULL, ic, TRUE);
9060 /*-----------------------------------------------------------------*/
9061 /* genPointerSet - stores the value into a pointer location */
9062 /*-----------------------------------------------------------------*/
9064 genPointerSet (iCode * ic, iCode *pi)
9066 operand *right, *result;
9067 sym_link *type, *etype;
9070 D(emitcode ("; genPointerSet",""));
9072 right = IC_RIGHT (ic);
9073 result = IC_RESULT (ic);
9075 /* depending on the type of pointer we need to
9076 move it to the correct pointer register */
9077 type = operandType (result);
9078 etype = getSpec (type);
9079 /* if left is of type of pointer then it is simple */
9080 if (IS_PTR (type) && !IS_FUNC (type->next))
9082 p_type = DCL_TYPE (type);
9086 /* we have to go by the storage class */
9087 p_type = PTR_TYPE (SPEC_OCLS (etype));
9090 /* special case when cast remat */
9091 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9092 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9093 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9094 type = operandType (result);
9095 p_type = DCL_TYPE (type);
9097 /* now that we have the pointer type we assign
9098 the pointer values */
9104 genNearPointerSet (right, result, ic, pi);
9108 genPagedPointerSet (right, result, ic, pi);
9112 genFarPointerSet (right, result, ic, pi);
9116 genGenPointerSet (right, result, ic, pi);
9120 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9121 "genPointerSet: illegal pointer type");
9126 /*-----------------------------------------------------------------*/
9127 /* genIfx - generate code for Ifx statement */
9128 /*-----------------------------------------------------------------*/
9130 genIfx (iCode * ic, iCode * popIc)
9132 operand *cond = IC_COND (ic);
9135 D(emitcode ("; genIfx",""));
9137 aopOp (cond, ic, FALSE);
9139 /* get the value into acc */
9140 if (AOP_TYPE (cond) != AOP_CRY)
9144 /* the result is now in the accumulator */
9145 freeAsmop (cond, NULL, ic, TRUE);
9147 /* if there was something to be popped then do it */
9151 /* if the condition is a bit variable */
9152 if (isbit && IS_ITEMP (cond) &&
9154 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9155 else if (isbit && !IS_ITEMP (cond))
9156 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9158 genIfxJump (ic, "a", NULL, NULL, NULL);
9163 /*-----------------------------------------------------------------*/
9164 /* genAddrOf - generates code for address of */
9165 /*-----------------------------------------------------------------*/
9167 genAddrOf (iCode * ic)
9169 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9172 D(emitcode ("; genAddrOf",""));
9174 aopOp (IC_RESULT (ic), ic, FALSE);
9176 /* if the operand is on the stack then we
9177 need to get the stack offset of this
9181 /* if it has an offset then we need to compute
9185 emitcode ("mov", "a,_bp");
9186 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9187 ((char) (sym->stack - _G.nRegsSaved)) :
9188 ((char) sym->stack)) & 0xff);
9189 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9193 /* we can just move _bp */
9194 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9196 /* fill the result with zero */
9197 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9202 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9208 /* object not on stack then we need the name */
9209 size = AOP_SIZE (IC_RESULT (ic));
9214 char s[SDCC_NAME_MAX];
9216 sprintf (s, "#(%s >> %d)",
9220 sprintf (s, "#%s", sym->rname);
9221 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9229 /*-----------------------------------------------------------------*/
9230 /* genFarFarAssign - assignment when both are in far space */
9231 /*-----------------------------------------------------------------*/
9233 genFarFarAssign (operand * result, operand * right, iCode * ic)
9235 int size = AOP_SIZE (right);
9239 D(emitcode ("; genFarFarAssign",""));
9241 /* first push the right side on to the stack */
9244 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9246 emitcode ("push", "acc");
9249 freeAsmop (right, NULL, ic, FALSE);
9250 /* now assign DPTR to result */
9251 aopOp (result, ic, FALSE);
9252 size = AOP_SIZE (result);
9255 emitcode ("pop", "acc");
9256 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9258 freeAsmop (result, NULL, ic, FALSE);
9262 /*-----------------------------------------------------------------*/
9263 /* genAssign - generate code for assignment */
9264 /*-----------------------------------------------------------------*/
9266 genAssign (iCode * ic)
9268 operand *result, *right;
9270 unsigned long lit = 0L;
9272 D(emitcode("; genAssign",""));
9274 result = IC_RESULT (ic);
9275 right = IC_RIGHT (ic);
9277 /* if they are the same */
9278 if (operandsEqu (result, right) &&
9279 !isOperandVolatile (result, FALSE) &&
9280 !isOperandVolatile (right, FALSE))
9283 aopOp (right, ic, FALSE);
9285 /* special case both in far space */
9286 if (AOP_TYPE (right) == AOP_DPTR &&
9287 IS_TRUE_SYMOP (result) &&
9288 isOperandInFarSpace (result))
9291 genFarFarAssign (result, right, ic);
9295 aopOp (result, ic, TRUE);
9297 /* if they are the same registers */
9298 if (sameRegs (AOP (right), AOP (result)) &&
9299 !isOperandVolatile (result, FALSE) &&
9300 !isOperandVolatile (right, FALSE))
9303 /* if the result is a bit */
9304 if (AOP_TYPE (result) == AOP_CRY)
9307 /* if the right size is a literal then
9308 we know what the value is */
9309 if (AOP_TYPE (right) == AOP_LIT)
9311 if (((int) operandLitValue (right)))
9312 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9314 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9318 /* the right is also a bit variable */
9319 if (AOP_TYPE (right) == AOP_CRY)
9321 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9322 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9328 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9332 /* bit variables done */
9334 size = AOP_SIZE (result);
9336 if (AOP_TYPE (right) == AOP_LIT)
9337 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9339 (AOP_TYPE (result) != AOP_REG) &&
9340 (AOP_TYPE (right) == AOP_LIT) &&
9341 !IS_FLOAT (operandType (right)) &&
9344 emitcode ("clr", "a");
9347 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9348 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9350 aopPut (AOP (result),
9351 aopGet (AOP (right), size, FALSE, FALSE),
9353 isOperandVolatile (result, FALSE));
9360 aopPut (AOP (result),
9361 aopGet (AOP (right), offset, FALSE, FALSE),
9363 isOperandVolatile (result, FALSE));
9369 freeAsmop (right, NULL, ic, TRUE);
9370 freeAsmop (result, NULL, ic, TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genJumpTab - genrates code for jump table */
9375 /*-----------------------------------------------------------------*/
9377 genJumpTab (iCode * ic)
9382 D(emitcode ("; genJumpTab",""));
9384 aopOp (IC_JTCOND (ic), ic, FALSE);
9385 /* get the condition into accumulator */
9386 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9388 /* multiply by three */
9389 emitcode ("add", "a,acc");
9390 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9391 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9393 jtab = newiTempLabel (NULL);
9394 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9395 emitcode ("jmp", "@a+dptr");
9396 emitcode ("", "%05d$:", jtab->key + 100);
9397 /* now generate the jump labels */
9398 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9399 jtab = setNextItem (IC_JTLABELS (ic)))
9400 emitcode ("ljmp", "%05d$", jtab->key + 100);
9404 /*-----------------------------------------------------------------*/
9405 /* genCast - gen code for casting */
9406 /*-----------------------------------------------------------------*/
9408 genCast (iCode * ic)
9410 operand *result = IC_RESULT (ic);
9411 sym_link *ctype = operandType (IC_LEFT (ic));
9412 sym_link *rtype = operandType (IC_RIGHT (ic));
9413 operand *right = IC_RIGHT (ic);
9416 D(emitcode("; genCast",""));
9418 /* if they are equivalent then do nothing */
9419 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9422 aopOp (right, ic, FALSE);
9423 aopOp (result, ic, FALSE);
9425 /* if the result is a bit (and not a bitfield) */
9426 // if (AOP_TYPE (result) == AOP_CRY)
9427 if (IS_BITVAR (OP_SYMBOL (result)->type)
9428 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9430 /* if the right size is a literal then
9431 we know what the value is */
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 if (((int) operandLitValue (right)))
9435 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9437 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9442 /* the right is also a bit variable */
9443 if (AOP_TYPE (right) == AOP_CRY)
9445 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9446 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9452 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9457 /* if they are the same size : or less */
9458 if (AOP_SIZE (result) <= AOP_SIZE (right))
9461 /* if they are in the same place */
9462 if (sameRegs (AOP (right), AOP (result)))
9465 /* if they in different places then copy */
9466 size = AOP_SIZE (result);
9470 aopPut (AOP (result),
9471 aopGet (AOP (right), offset, FALSE, FALSE),
9473 isOperandVolatile (result, FALSE));
9480 /* if the result is of type pointer */
9485 sym_link *type = operandType (right);
9486 sym_link *etype = getSpec (type);
9488 /* pointer to generic pointer */
9489 if (IS_GENPTR (ctype))
9492 p_type = DCL_TYPE (type);
9495 if (SPEC_SCLS(etype)==S_REGISTER) {
9496 // let's assume it is a generic pointer
9499 /* we have to go by the storage class */
9500 p_type = PTR_TYPE (SPEC_OCLS (etype));
9504 /* the first two bytes are known */
9505 size = GPTRSIZE - 1;
9509 aopPut (AOP (result),
9510 aopGet (AOP (right), offset, FALSE, FALSE),
9512 isOperandVolatile (result, FALSE));
9515 /* the last byte depending on type */
9517 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9522 // pointerTypeToGPByte will have bitched.
9526 sprintf(gpValStr, "#0x%d", gpVal);
9527 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9532 /* just copy the pointers */
9533 size = AOP_SIZE (result);
9537 aopPut (AOP (result),
9538 aopGet (AOP (right), offset, FALSE, FALSE),
9540 isOperandVolatile (result, FALSE));
9546 /* so we now know that the size of destination is greater
9547 than the size of the source */
9548 /* we move to result for the size of source */
9549 size = AOP_SIZE (right);
9553 aopPut (AOP (result),
9554 aopGet (AOP (right), offset, FALSE, FALSE),
9556 isOperandVolatile (result, FALSE));
9560 /* now depending on the sign of the source && destination */
9561 size = AOP_SIZE (result) - AOP_SIZE (right);
9562 /* if unsigned or not an integral type */
9563 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9566 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9570 /* we need to extend the sign :{ */
9571 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9574 emitcode ("rlc", "a");
9575 emitcode ("subb", "a,acc");
9577 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9580 /* we are done hurray !!!! */
9583 freeAsmop (right, NULL, ic, TRUE);
9584 freeAsmop (result, NULL, ic, TRUE);
9588 /*-----------------------------------------------------------------*/
9589 /* genDjnz - generate decrement & jump if not zero instrucion */
9590 /*-----------------------------------------------------------------*/
9592 genDjnz (iCode * ic, iCode * ifx)
9598 D(emitcode ("; genDjnz",""));
9600 /* if the if condition has a false label
9601 then we cannot save */
9605 /* if the minus is not of the form
9607 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9608 !IS_OP_LITERAL (IC_RIGHT (ic)))
9611 if (operandLitValue (IC_RIGHT (ic)) != 1)
9614 /* if the size of this greater than one then no
9616 if (getSize (operandType (IC_RESULT (ic))) > 1)
9619 /* otherwise we can save BIG */
9620 lbl = newiTempLabel (NULL);
9621 lbl1 = newiTempLabel (NULL);
9623 aopOp (IC_RESULT (ic), ic, FALSE);
9625 if (AOP_NEEDSACC(IC_RESULT(ic)))
9627 /* If the result is accessed indirectly via
9628 * the accumulator, we must explicitly write
9629 * it back after the decrement.
9631 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9633 if (strcmp(rByte, "a"))
9635 /* Something is hopelessly wrong */
9636 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9637 __FILE__, __LINE__);
9638 /* We can just give up; the generated code will be inefficient,
9641 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9644 emitcode ("dec", "%s", rByte);
9645 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9646 emitcode ("jnz", "%05d$", lbl->key + 100);
9648 else if (IS_AOP_PREG (IC_RESULT (ic)))
9650 emitcode ("dec", "%s",
9651 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9652 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9653 emitcode ("jnz", "%05d$", lbl->key + 100);
9657 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9660 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9661 emitcode ("", "%05d$:", lbl->key + 100);
9662 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9663 emitcode ("", "%05d$:", lbl1->key + 100);
9665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9670 /*-----------------------------------------------------------------*/
9671 /* genReceive - generate code for a receive iCode */
9672 /*-----------------------------------------------------------------*/
9674 genReceive (iCode * ic)
9676 int size = getSize (operandType (IC_RESULT (ic)));
9678 D(emitcode ("; genReceive",""));
9680 if (ic->argreg == 1) { /* first parameter */
9681 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9682 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9683 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9689 for (offset = 0; offset<size; offset++)
9690 if (!strcmp (fReturn[offset], "a"))
9695 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9697 for (offset = size-1; offset>0; offset--)
9698 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9699 emitcode("mov","a,%s", fReturn[0]);
9701 aopOp (IC_RESULT (ic), ic, FALSE);
9703 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9704 isOperandVolatile (IC_RESULT (ic), FALSE));
9705 for (offset = 1; offset<size; offset++)
9706 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9707 isOperandVolatile (IC_RESULT (ic), FALSE));
9713 if (getTempRegs(tempRegs, size, ic))
9715 for (offset = 0; offset<size; offset++)
9716 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9717 aopOp (IC_RESULT (ic), ic, FALSE);
9718 for (offset = 0; offset<size; offset++)
9719 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9720 isOperandVolatile (IC_RESULT (ic), FALSE));
9725 offset = fReturnSizeMCS51 - size;
9727 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9728 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9731 aopOp (IC_RESULT (ic), ic, FALSE);
9732 size = AOP_SIZE (IC_RESULT (ic));
9735 emitcode ("pop", "acc");
9736 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9741 aopOp (IC_RESULT (ic), ic, FALSE);
9743 assignResultValue (IC_RESULT (ic));
9745 } else { /* second receive onwards */
9747 aopOp (IC_RESULT (ic), ic, FALSE);
9748 rb1off = ic->argreg;
9750 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9755 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9758 /*-----------------------------------------------------------------*/
9759 /* genDummyRead - generate code for dummy read of volatiles */
9760 /*-----------------------------------------------------------------*/
9762 genDummyRead (iCode * ic)
9767 D(emitcode("; genDummyRead",""));
9770 if (op && IS_SYMOP (op))
9772 aopOp (op, ic, FALSE);
9774 /* if the result is a bit */
9775 if (AOP_TYPE (op) == AOP_CRY)
9776 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9779 /* bit variables done */
9781 size = AOP_SIZE (op);
9785 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9790 freeAsmop (op, NULL, ic, TRUE);
9794 if (op && IS_SYMOP (op))
9796 aopOp (op, ic, FALSE);
9798 /* if the result is a bit */
9799 if (AOP_TYPE (op) == AOP_CRY)
9800 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9803 /* bit variables done */
9805 size = AOP_SIZE (op);
9809 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9814 freeAsmop (op, NULL, ic, TRUE);
9818 /*-----------------------------------------------------------------*/
9819 /* genCritical - generate code for start of a critical sequence */
9820 /*-----------------------------------------------------------------*/
9822 genCritical (iCode *ic)
9824 symbol *tlbl = newiTempLabel (NULL);
9826 D(emitcode("; genCritical",""));
9829 aopOp (IC_RESULT (ic), ic, TRUE);
9831 emitcode ("setb", "c");
9832 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9833 emitcode ("clr", "c");
9834 emitcode ("", "%05d$:", (tlbl->key + 100));
9837 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9839 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9845 /*-----------------------------------------------------------------*/
9846 /* genEndCritical - generate code for end of a critical sequence */
9847 /*-----------------------------------------------------------------*/
9849 genEndCritical (iCode *ic)
9851 D(emitcode("; genEndCritical",""));
9855 aopOp (IC_RIGHT (ic), ic, FALSE);
9856 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9858 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9859 emitcode ("mov", "ea,c");
9863 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9864 emitcode ("rrc", "a");
9865 emitcode ("mov", "ea,c");
9867 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9871 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9872 emitcode ("mov", "ea,c");
9876 /*-----------------------------------------------------------------*/
9877 /* gen51Code - generate code for 8051 based controllers */
9878 /*-----------------------------------------------------------------*/
9880 gen51Code (iCode * lic)
9886 _G.currentFunc = NULL;
9887 lineHead = lineCurr = NULL;
9889 /* print the allocation information */
9890 if (allocInfo && currFunc)
9891 printAllocInfo (currFunc, codeOutFile);
9892 /* if debug information required */
9893 if (options.debug && currFunc)
9895 debugFile->writeFunction(currFunc);
9897 if (IS_STATIC (currFunc->etype))
9898 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9900 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9903 /* stack pointer name */
9904 if (options.useXstack)
9910 for (ic = lic; ic; ic = ic->next)
9912 _G.current_iCode = ic;
9914 if (ic->lineno && cln != ic->lineno)
9919 emitcode ("", "C$%s$%d$%d$%d ==.",
9920 FileBaseName (ic->filename), ic->lineno,
9921 ic->level, ic->block);
9924 if (!options.noCcodeInAsm) {
9925 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9926 printCLine(ic->filename, ic->lineno));
9931 if (ic->seqPoint && ic->seqPoint != cseq)
9933 emitcode ("", "; sequence point %d", ic->seqPoint);
9934 cseq = ic->seqPoint;
9937 if (options.iCodeInAsm) {
9941 for (i=0; i<8; i++) {
9942 sprintf (®sInUse[i],
9943 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9946 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9948 /* if the result is marked as
9949 spilt and rematerializable or code for
9950 this has already been generated then
9952 if (resultRemat (ic) || ic->generated)
9955 /* depending on the operation */
9975 /* IPOP happens only when trying to restore a
9976 spilt live range, if there is an ifx statement
9977 following this pop then the if statement might
9978 be using some of the registers being popped which
9979 would destory the contents of the register so
9980 we need to check for this condition and handle it */
9982 ic->next->op == IFX &&
9983 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9984 genIfx (ic->next, ic);
10002 genEndFunction (ic);
10022 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10039 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10043 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10050 /* note these two are xlated by algebraic equivalence
10051 during parsing SDCC.y */
10052 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10053 "got '>=' or '<=' shouldn't have come here");
10057 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10069 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10073 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10077 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10101 genRightShift (ic);
10104 case GET_VALUE_AT_ADDRESS:
10105 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10109 if (POINTER_SET (ic))
10110 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10136 addSet (&_G.sendSet, ic);
10139 case DUMMY_READ_VOLATILE:
10148 genEndCritical (ic);
10160 _G.current_iCode = NULL;
10162 /* now we are ready to call the
10163 peep hole optimizer */
10164 if (!options.nopeep)
10165 peepHole (&lineHead);
10167 /* now do the actual printing */
10168 printLine (lineHead, codeOutFile);