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);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72 AOP_TYPE(x) == AOP_R0))
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
75 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
78 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
82 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
84 #define R0INB _G.bu.bs.r0InB
85 #define R1INB _G.bu.bs.r1InB
86 #define OPINB _G.bu.bs.OpInB
87 #define BINUSE _G.bu.BInUse
97 short r0InB : 2;//2 so we can see it overflow
98 short r1InB : 2;//2 so we can see it overflow
99 short OpInB : 2;//2 so we can see it overflow
108 iCode *current_iCode;
113 static char *rb1regs[] = {
114 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
117 extern int mcs51_ptrRegReq;
118 extern int mcs51_nRegs;
119 extern FILE *codeOutFile;
120 static void saveRBank (int, iCode *, bool);
122 #define RESULTONSTACK(x) \
123 (IC_RESULT(x) && IC_RESULT(x)->aop && \
124 IC_RESULT(x)->aop->type == AOP_STK )
126 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
127 #define CLRC emitcode("clr","c")
128 #define SETC emitcode("setb","c")
130 static lineNode *lineHead = NULL;
131 static lineNode *lineCurr = NULL;
133 static unsigned char SLMask[] =
134 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
135 0xE0, 0xC0, 0x80, 0x00};
136 static unsigned char SRMask[] =
137 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
138 0x07, 0x03, 0x01, 0x00};
145 /*-----------------------------------------------------------------*/
146 /* emitcode - writes the code into a file : for now it is simple */
147 /*-----------------------------------------------------------------*/
149 emitcode (char *inst, const char *fmt,...)
152 char lb[INITIAL_INLINEASM];
160 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
162 SNPRINTF (lb, sizeof(lb), "%s", inst);
163 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
166 tvsprintf (lb, sizeof(lb), fmt, ap);
168 while (isspace (*lbp))
172 lineCurr = (lineCurr ?
173 connectLine (lineCurr, newLineNode (lb)) :
174 (lineHead = newLineNode (lb)));
175 lineCurr->isInline = _G.inLine;
176 lineCurr->isDebug = _G.debugLine;
177 lineCurr->ic = _G.current_iCode;
178 lineCurr->isComment = (*lbp==';');
182 /*-----------------------------------------------------------------*/
183 /* mcs51_emitDebuggerSymbol - associate the current code location */
184 /* with a debugger symbol */
185 /*-----------------------------------------------------------------*/
187 mcs51_emitDebuggerSymbol (char * debugSym)
190 emitcode ("", "%s ==.", debugSym);
194 /*-----------------------------------------------------------------*/
195 /* mova - moves specified value into accumulator */
196 /*-----------------------------------------------------------------*/
200 /* do some early peephole optimization */
201 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
204 emitcode("mov","a,%s", x);
207 /*-----------------------------------------------------------------*/
208 /* pushB - saves register B if necessary */
209 /*-----------------------------------------------------------------*/
213 bool pushedB = FALSE;
217 emitcode ("push", "b");
218 // printf("B was in use !\n");
228 /*-----------------------------------------------------------------*/
229 /* popB - restores value of register B if necessary */
230 /*-----------------------------------------------------------------*/
236 emitcode ("pop", "b");
244 /*-----------------------------------------------------------------*/
245 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
246 /*-----------------------------------------------------------------*/
248 getFreePtr (iCode * ic, asmop ** aopp, bool result)
253 /* the logic: if r0 & r1 used in the instruction
254 then we are in trouble otherwise */
256 /* first check if r0 & r1 are used by this
257 instruction, in which case we are in trouble */
258 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
259 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
264 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
265 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
267 /* if no usage of r0 then return it */
270 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
271 (*aopp)->type = AOP_R0;
273 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
276 /* if no usage of r1 then return it */
279 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
280 (*aopp)->type = AOP_R1;
282 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
285 /* now we know they both have usage */
286 /* if r0 not used in this instruction */
289 /* push it if not already pushed */
292 emitcode ("mov", "b,%s",
293 mcs51_regWithIdx (R0_IDX)->dname);
296 else if (!_G.r0Pushed)
298 emitcode ("push", "%s",
299 mcs51_regWithIdx (R0_IDX)->dname);
303 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
304 (*aopp)->type = AOP_R0;
306 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
309 /* if r1 not used then */
313 /* push it if not already pushed */
316 emitcode ("mov", "b,%s",
317 mcs51_regWithIdx (R1_IDX)->dname);
320 else if (!_G.r1Pushed)
322 emitcode ("push", "%s",
323 mcs51_regWithIdx (R1_IDX)->dname);
327 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
328 (*aopp)->type = AOP_R1;
329 return mcs51_regWithIdx (R1_IDX);
332 /* I said end of world, but not quite end of world yet */
334 /* we can push it on the stack */
335 (*aopp)->type = AOP_STK;
338 /* in the case that result AND left AND right needs a pointer reg
339 we can safely use the result's */
340 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
341 (*aopp)->type = AOP_R0;
342 return mcs51_regWithIdx (R0_IDX);
344 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
345 (*aopp)->type = AOP_R1;
346 return mcs51_regWithIdx (R1_IDX);
350 /* now this is REALLY the end of the world */
351 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
352 "getFreePtr should never reach here");
357 /*-----------------------------------------------------------------*/
358 /* getTempRegs - initialize an array of pointers to GPR registers */
359 /* that are not in use. Returns 1 if the requested */
360 /* number of registers were available, 0 otherwise. */
361 /*-----------------------------------------------------------------*/
363 getTempRegs(regs **tempRegs, int size, iCode *ic)
370 ic = _G.current_iCode;
376 freeRegs = newBitVect(8);
377 bitVectSetBit (freeRegs, R2_IDX);
378 bitVectSetBit (freeRegs, R3_IDX);
379 bitVectSetBit (freeRegs, R4_IDX);
380 bitVectSetBit (freeRegs, R5_IDX);
381 bitVectSetBit (freeRegs, R6_IDX);
382 bitVectSetBit (freeRegs, R7_IDX);
384 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
386 bitVect * newfreeRegs;
387 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
388 freeBitVect(freeRegs);
389 freeRegs = newfreeRegs;
391 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
394 for (i=0; i<freeRegs->size; i++)
396 if (bitVectBitValue(freeRegs,i))
397 tempRegs[offset++] = mcs51_regWithIdx(i);
400 freeBitVect(freeRegs);
405 freeBitVect(freeRegs);
410 /*-----------------------------------------------------------------*/
411 /* newAsmop - creates a new asmOp */
412 /*-----------------------------------------------------------------*/
414 newAsmop (short type)
418 aop = Safe_calloc (1, sizeof (asmop));
423 /*-----------------------------------------------------------------*/
424 /* pointerCode - returns the code for a pointer type */
425 /*-----------------------------------------------------------------*/
427 pointerCode (sym_link * etype)
430 return PTR_TYPE (SPEC_OCLS (etype));
434 /*-----------------------------------------------------------------*/
435 /* leftRightUseAcc - returns size of accumulator use by operands */
436 /*-----------------------------------------------------------------*/
438 leftRightUseAcc(iCode *ic)
447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
448 "null iCode pointer");
455 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
458 size = getSize (OP_SYMBOL (op)->type);
463 else if (ic->op == JUMPTABLE)
466 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
469 size = getSize (OP_SYMBOL (op)->type);
477 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
480 size = getSize (OP_SYMBOL (op)->type);
485 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488 size = getSize (OP_SYMBOL (op)->type);
500 /*-----------------------------------------------------------------*/
501 /* aopForSym - for a true symbol */
502 /*-----------------------------------------------------------------*/
504 aopForSym (iCode * ic, symbol * sym, bool result)
509 wassertl (ic != NULL, "Got a null iCode");
510 wassertl (sym != NULL, "Got a null symbol");
512 space = SPEC_OCLS (sym->etype);
514 /* if already has one */
518 /* assign depending on the storage class */
519 /* if it is on the stack or indirectly addressable */
520 /* space we need to assign either r0 or r1 to it */
521 if (sym->onStack || sym->iaccess)
523 sym->aop = aop = newAsmop (0);
524 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
525 aop->size = getSize (sym->type);
527 /* now assign the address of the variable to
528 the pointer register */
529 if (aop->type != AOP_STK)
534 char offset = ((sym->stack < 0) ?
535 ((char) (sym->stack - _G.nRegsSaved)) :
536 ((char) sym->stack)) & 0xff;
538 if ((offset >= -3) && (offset <= 3))
540 emitcode ("mov", "%s,%s",
541 aop->aopu.aop_ptr->name, SYM_BP (sym));
544 emitcode ("dec", aop->aopu.aop_ptr->name);
549 emitcode ("inc", aop->aopu.aop_ptr->name);
555 if (_G.accInUse || leftRightUseAcc (ic))
556 emitcode ("push", "acc");
557 emitcode ("mov", "a,%s", SYM_BP (sym));
558 emitcode ("add", "a,#0x%02x", offset);
559 emitcode ("mov", "%s,a",
560 aop->aopu.aop_ptr->name);
561 if (_G.accInUse || leftRightUseAcc (ic))
562 emitcode ("pop", "acc");
566 emitcode ("mov", "%s,#%s",
567 aop->aopu.aop_ptr->name,
569 aop->paged = space->paged;
572 aop->aopu.aop_stk = sym->stack;
576 /* if in bit space */
577 if (IN_BITSPACE (space))
579 sym->aop = aop = newAsmop (AOP_CRY);
580 aop->aopu.aop_dir = sym->rname;
581 aop->size = getSize (sym->type);
584 /* if it is in direct space */
585 if (IN_DIRSPACE (space))
587 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
588 //printTypeChainRaw(sym->type, NULL);
589 //printf("space = %s\n", space ? space->sname : "NULL");
590 sym->aop = aop = newAsmop (AOP_DIR);
591 aop->aopu.aop_dir = sym->rname;
592 aop->size = getSize (sym->type);
596 /* special case for a function */
597 if (IS_FUNC (sym->type))
599 sym->aop = aop = newAsmop (AOP_IMMD);
600 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
601 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
602 aop->size = getSize (sym->type);
606 /* only remaining is far space */
607 /* in which case DPTR gets the address */
608 sym->aop = aop = newAsmop (AOP_DPTR);
609 emitcode ("mov", "dptr,#%s", sym->rname);
610 aop->size = getSize (sym->type);
612 /* if it is in code space */
613 if (IN_CODESPACE (space))
619 /*-----------------------------------------------------------------*/
620 /* aopForRemat - rematerialzes an object */
621 /*-----------------------------------------------------------------*/
623 aopForRemat (symbol * sym)
625 iCode *ic = sym->rematiCode;
626 asmop *aop = newAsmop (AOP_IMMD);
633 val += (int) operandLitValue (IC_RIGHT (ic));
634 else if (ic->op == '-')
635 val -= (int) operandLitValue (IC_RIGHT (ic));
636 else if (IS_CAST_ICODE(ic)) {
637 sym_link *from_type = operandType(IC_RIGHT(ic));
638 aop->aopu.aop_immd.from_cast_remat = 1;
639 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
640 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
644 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
648 sprintf (buffer, "(%s %c 0x%04x)",
649 OP_SYMBOL (IC_LEFT (ic))->rname,
650 val >= 0 ? '+' : '-',
653 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
655 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
656 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
657 /* set immd2 field if required */
658 if (aop->aopu.aop_immd.from_cast_remat) {
659 sprintf(buffer,"#0x%02x",ptr_type);
660 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
661 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
667 /*-----------------------------------------------------------------*/
668 /* regsInCommon - two operands have some registers in common */
669 /*-----------------------------------------------------------------*/
671 regsInCommon (operand * op1, operand * op2)
676 /* if they have registers in common */
677 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
680 sym1 = OP_SYMBOL (op1);
681 sym2 = OP_SYMBOL (op2);
683 if (sym1->nRegs == 0 || sym2->nRegs == 0)
686 for (i = 0; i < sym1->nRegs; i++)
692 for (j = 0; j < sym2->nRegs; j++)
697 if (sym2->regs[j] == sym1->regs[i])
705 /*-----------------------------------------------------------------*/
706 /* operandsEqu - equivalent */
707 /*-----------------------------------------------------------------*/
709 operandsEqu (operand * op1, operand * op2)
713 /* if they're not symbols */
714 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
717 sym1 = OP_SYMBOL (op1);
718 sym2 = OP_SYMBOL (op2);
720 /* if both are itemps & one is spilt
721 and the other is not then false */
722 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
723 sym1->isspilt != sym2->isspilt)
726 /* if they are the same */
730 /* if they have the same rname */
731 if (sym1->rname[0] && sym2->rname[0] &&
732 strcmp (sym1->rname, sym2->rname) == 0 &&
733 !(IS_PARM (op2) && IS_ITEMP (op1)))
736 /* if left is a tmp & right is not */
737 if (IS_ITEMP (op1) &&
740 (sym1->usl.spillLoc == sym2))
743 if (IS_ITEMP (op2) &&
747 (sym2->usl.spillLoc == sym1))
753 /*-----------------------------------------------------------------*/
754 /* sameRegs - two asmops have the same registers */
755 /*-----------------------------------------------------------------*/
757 sameRegs (asmop * aop1, asmop * aop2)
764 if (aop1->type != AOP_REG ||
765 aop2->type != AOP_REG)
768 if (aop1->size != aop2->size)
771 for (i = 0; i < aop1->size; i++)
772 if (aop1->aopu.aop_reg[i] !=
773 aop2->aopu.aop_reg[i])
779 /*-----------------------------------------------------------------*/
780 /* aopOp - allocates an asmop for an operand : */
781 /*-----------------------------------------------------------------*/
783 aopOp (operand * op, iCode * ic, bool result)
792 /* if this a literal */
793 if (IS_OP_LITERAL (op))
795 op->aop = aop = newAsmop (AOP_LIT);
796 aop->aopu.aop_lit = op->operand.valOperand;
797 aop->size = getSize (operandType (op));
801 /* if already has a asmop then continue */
805 /* if the underlying symbol has a aop */
806 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
808 op->aop = OP_SYMBOL (op)->aop;
812 /* if this is a true symbol */
813 if (IS_TRUE_SYMOP (op))
815 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
819 /* this is a temporary : this has
825 e) can be a return use only */
827 sym = OP_SYMBOL (op);
829 /* if the type is a conditional */
830 if (sym->regType == REG_CND)
832 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
837 /* if it is spilt then two situations
839 b) has a spill location */
840 if (sym->isspilt || sym->nRegs == 0)
843 /* rematerialize it NOW */
846 sym->aop = op->aop = aop =
848 aop->size = getSize (sym->type);
855 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
856 aop->size = getSize (sym->type);
857 for (i = 0; i < 2; i++)
858 aop->aopu.aop_str[i] = accUse[i];
866 aop = op->aop = sym->aop = newAsmop (AOP_STR);
867 aop->size = getSize (sym->type);
868 for (i = 0; i < fReturnSizeMCS51; i++)
869 aop->aopu.aop_str[i] = fReturn[i];
873 if (sym->usl.spillLoc)
875 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
877 /* force a new aop if sizes differ */
878 sym->usl.spillLoc->aop = NULL;
880 sym->aop = op->aop = aop =
881 aopForSym (ic, sym->usl.spillLoc, result);
882 aop->size = getSize (sym->type);
886 /* else must be a dummy iTemp */
887 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
888 aop->size = getSize (sym->type);
892 /* must be in a register */
893 sym->aop = op->aop = aop = newAsmop (AOP_REG);
894 aop->size = sym->nRegs;
895 for (i = 0; i < sym->nRegs; i++)
896 aop->aopu.aop_reg[i] = sym->regs[i];
899 /*-----------------------------------------------------------------*/
900 /* freeAsmop - free up the asmop given to an operand */
901 /*----------------------------------------------------------------*/
903 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
920 /* depending on the asmop type only three cases need work AOP_RO
921 , AOP_R1 && AOP_STK */
927 emitcode ("mov", "r0,b");
930 else if (_G.r0Pushed)
934 emitcode ("pop", "ar0");
938 bitVectUnSetBit (ic->rUsed, R0_IDX);
944 emitcode ("mov", "r1,b");
951 emitcode ("pop", "ar1");
955 bitVectUnSetBit (ic->rUsed, R1_IDX);
961 int stk = aop->aopu.aop_stk + aop->size - 1;
962 bitVectUnSetBit (ic->rUsed, R0_IDX);
963 bitVectUnSetBit (ic->rUsed, R1_IDX);
965 getFreePtr (ic, &aop, FALSE);
969 emitcode ("mov", "a,_bp");
970 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
971 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
975 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
980 emitcode ("pop", "acc");
981 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
984 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 freeAsmop (op, NULL, ic, TRUE);
990 emitcode ("pop", "ar1");
996 emitcode ("pop", "ar0");
1003 /* all other cases just dealloc */
1009 OP_SYMBOL (op)->aop = NULL;
1010 /* if the symbol has a spill */
1012 SPIL_LOC (op)->aop = NULL;
1017 /*------------------------------------------------------------------*/
1018 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1019 /* pop r0 or r1 off stack if pushed */
1020 /*------------------------------------------------------------------*/
1022 freeForBranchAsmop (operand * op)
1042 emitcode ("mov", "r0,b");
1044 else if (_G.r0Pushed)
1046 emitcode ("pop", "ar0");
1053 emitcode ("mov", "r1,b");
1055 else if (_G.r1Pushed)
1057 emitcode ("pop", "ar1");
1064 int stk = aop->aopu.aop_stk + aop->size - 1;
1066 emitcode ("mov", "b,r0");
1069 emitcode ("mov", "a,_bp");
1070 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1071 emitcode ("mov", "r0,a");
1075 emitcode ("mov", "r0,_bp");
1080 emitcode ("pop", "acc");
1081 emitcode ("mov", "@r0,a");
1084 emitcode ("dec", "r0");
1086 emitcode ("mov", "r0,b");
1092 /*-----------------------------------------------------------------*/
1093 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1094 /* clobber the accumulator */
1095 /*-----------------------------------------------------------------*/
1097 aopGetUsesAcc (operand * oper, int offset)
1099 asmop * aop = AOP (oper);
1101 if (offset > (aop->size - 1))
1119 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1130 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1136 /* Error case --- will have been caught already */
1142 /*-----------------------------------------------------------------*/
1143 /* aopGet - for fetching value of the aop */
1144 /*-----------------------------------------------------------------*/
1146 aopGet (operand * oper, int offset, bool bit16, bool dname)
1150 asmop * aop = AOP (oper);
1152 /* offset is greater than
1154 if (offset > (aop->size - 1) &&
1155 aop->type != AOP_LIT)
1158 /* depending on type */
1166 /* if we need to increment it */
1167 while (offset > aop->coff)
1169 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1173 while (offset < aop->coff)
1175 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1182 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1183 return (dname ? "acc" : "a");
1185 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1186 rs = Safe_calloc (1, strlen (s) + 1);
1191 if (aop->code && aop->coff==0 && offset>=1) {
1192 emitcode ("mov", "a,#0x%02x", offset);
1193 emitcode ("movc", "a,@a+dptr");
1194 return (dname ? "acc" : "a");
1197 while (offset > aop->coff)
1199 emitcode ("inc", "dptr");
1203 while (offset < aop->coff)
1205 emitcode ("lcall", "__decdptr");
1212 emitcode ("clr", "a");
1213 emitcode ("movc", "a,@a+dptr");
1217 emitcode ("movx", "a,@dptr");
1219 return (dname ? "acc" : "a");
1223 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1224 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1226 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1228 sprintf (s, "#(%s >> %d)",
1229 aop->aopu.aop_immd.aop_immd1,
1233 aop->aopu.aop_immd.aop_immd1);
1234 rs = Safe_calloc (1, strlen (s) + 1);
1239 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1240 sprintf (s, "(%s >> %d)",
1241 aop->aopu.aop_dir, offset * 8);
1243 sprintf (s, "(%s + %d)",
1247 sprintf (s, "%s", aop->aopu.aop_dir);
1248 rs = Safe_calloc (1, strlen (s) + 1);
1254 return aop->aopu.aop_reg[offset]->dname;
1256 return aop->aopu.aop_reg[offset]->name;
1259 emitcode ("clr", "a");
1260 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1261 emitcode ("rlc", "a");
1262 return (dname ? "acc" : "a");
1265 if (!offset && dname)
1267 return aop->aopu.aop_str[offset];
1270 return aopLiteral (aop->aopu.aop_lit, offset);
1274 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1278 return aop->aopu.aop_str[offset];
1282 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1283 "aopget got unsupported aop->type");
1286 /*-----------------------------------------------------------------*/
1287 /* aopPut - puts a string for a aop and indicates if acc is in use */
1288 /*-----------------------------------------------------------------*/
1290 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1293 bool accuse = FALSE;
1294 asmop * aop = AOP (result);
1296 if (aop->size && offset > (aop->size - 1))
1298 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1299 "aopPut got offset > aop->size");
1303 /* will assign value to value */
1304 /* depending on where it is ofcourse */
1308 MOVA (s); /* read s in case it was volatile */
1313 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1314 sprintf (d, "(%s >> %d)",
1315 aop->aopu.aop_dir, offset * 8);
1317 sprintf (d, "(%s + %d)",
1318 aop->aopu.aop_dir, offset);
1320 sprintf (d, "%s", aop->aopu.aop_dir);
1322 if (strcmp (d, s) ||
1324 emitcode ("mov", "%s,%s", d, s);
1325 if (!strcmp (d, "acc"))
1331 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1332 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1335 strcmp (s, "r0") == 0 ||
1336 strcmp (s, "r1") == 0 ||
1337 strcmp (s, "r2") == 0 ||
1338 strcmp (s, "r3") == 0 ||
1339 strcmp (s, "r4") == 0 ||
1340 strcmp (s, "r5") == 0 ||
1341 strcmp (s, "r6") == 0 ||
1342 strcmp (s, "r7") == 0)
1343 emitcode ("mov", "%s,%s",
1344 aop->aopu.aop_reg[offset]->dname, s);
1346 emitcode ("mov", "%s,%s",
1347 aop->aopu.aop_reg[offset]->name, s);
1354 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1355 "aopPut writing to code space");
1359 while (offset > aop->coff)
1362 emitcode ("inc", "dptr");
1365 while (offset < aop->coff)
1368 emitcode ("lcall", "__decdptr");
1373 /* if not in accumulator */
1376 emitcode ("movx", "@dptr,a");
1381 while (offset > aop->coff)
1384 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1386 while (offset < aop->coff)
1389 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1396 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1402 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1404 else if (strcmp (s, "r0") == 0 ||
1405 strcmp (s, "r1") == 0 ||
1406 strcmp (s, "r2") == 0 ||
1407 strcmp (s, "r3") == 0 ||
1408 strcmp (s, "r4") == 0 ||
1409 strcmp (s, "r5") == 0 ||
1410 strcmp (s, "r6") == 0 ||
1411 strcmp (s, "r7") == 0)
1414 sprintf (buffer, "a%s", s);
1415 emitcode ("mov", "@%s,%s",
1416 aop->aopu.aop_ptr->name, buffer);
1419 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1424 if (strcmp (s, "a") == 0)
1425 emitcode ("push", "acc");
1429 emitcode ("push", "acc");
1431 emitcode ("push", s);
1437 /* if not bit variable */
1438 if (!aop->aopu.aop_dir)
1440 /* inefficient: move carry into A and use jz/jnz */
1441 emitcode ("clr", "a");
1442 emitcode ("rlc", "a");
1448 emitcode ("clr", "%s", aop->aopu.aop_dir);
1450 emitcode ("setb", "%s", aop->aopu.aop_dir);
1451 else if (!strcmp (s, "c"))
1452 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1456 /* set C, if a >= 1 */
1457 emitcode ("add", "a,#0xff");
1458 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1465 if (strcmp (aop->aopu.aop_str[offset], s) ||
1467 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1473 if (!offset && (strcmp (s, "acc") == 0) &&
1477 if (strcmp (aop->aopu.aop_str[offset], s) &&
1479 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1483 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1484 "aopPut got unsupported aop->type");
1493 /*-----------------------------------------------------------------*/
1494 /* pointToEnd :- points to the last byte of the operand */
1495 /*-----------------------------------------------------------------*/
1497 pointToEnd (asmop * aop)
1503 aop->coff = count = (aop->size - 1);
1509 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1513 emitcode ("inc", "dptr");
1520 /*-----------------------------------------------------------------*/
1521 /* reAdjustPreg - points a register back to where it should */
1522 /*-----------------------------------------------------------------*/
1524 reAdjustPreg (asmop * aop)
1526 if ((aop->coff==0) || aop->size <= 1)
1534 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1539 emitcode ("lcall", "__decdptr");
1546 /*-----------------------------------------------------------------*/
1547 /* opIsGptr: returns non-zero if the passed operand is */
1548 /* a generic pointer type. */
1549 /*-----------------------------------------------------------------*/
1551 opIsGptr (operand * op)
1553 sym_link *type = operandType (op);
1555 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1562 /*-----------------------------------------------------------------*/
1563 /* getDataSize - get the operand data size */
1564 /*-----------------------------------------------------------------*/
1566 getDataSize (operand * op)
1569 size = AOP_SIZE (op);
1570 if (size == GPTRSIZE)
1572 sym_link *type = operandType (op);
1573 if (IS_GENPTR (type))
1575 /* generic pointer; arithmetic operations
1576 * should ignore the high byte (pointer type).
1584 /*-----------------------------------------------------------------*/
1585 /* outAcc - output Acc */
1586 /*-----------------------------------------------------------------*/
1588 outAcc (operand * result)
1591 size = getDataSize (result);
1594 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1597 /* unsigned or positive */
1600 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1605 /*-----------------------------------------------------------------*/
1606 /* outBitC - output a bit C */
1607 /*-----------------------------------------------------------------*/
1609 outBitC (operand * result)
1611 /* if the result is bit */
1612 if (AOP_TYPE (result) == AOP_CRY)
1613 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1616 emitcode ("clr", "a");
1617 emitcode ("rlc", "a");
1622 /*-----------------------------------------------------------------*/
1623 /* toBoolean - emit code for orl a,operator(sizeop) */
1624 /*-----------------------------------------------------------------*/
1626 toBoolean (operand * oper)
1628 int size = AOP_SIZE (oper) - 1;
1630 bool AccUsed = FALSE;
1633 while (!AccUsed && size--)
1635 AccUsed |= aopGetUsesAcc(oper, offset++);
1638 size = AOP_SIZE (oper) - 1;
1640 MOVA (aopGet (oper, 0, FALSE, FALSE));
1641 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1644 emitcode("mov", "b,a");
1647 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1648 emitcode ("orl", "b,a");
1650 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1651 emitcode ("orl", "a,b");
1658 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1664 /*-----------------------------------------------------------------*/
1665 /* genNot - generate code for ! operation */
1666 /*-----------------------------------------------------------------*/
1672 D(emitcode ("; genNot",""));
1674 /* assign asmOps to operand & result */
1675 aopOp (IC_LEFT (ic), ic, FALSE);
1676 aopOp (IC_RESULT (ic), ic, TRUE);
1678 /* if in bit space then a special case */
1679 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1681 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1682 emitcode ("cpl", "c");
1683 outBitC (IC_RESULT (ic));
1687 toBoolean (IC_LEFT (ic));
1689 tlbl = newiTempLabel (NULL);
1690 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1691 emitcode ("", "%05d$:", tlbl->key + 100);
1692 outBitC (IC_RESULT (ic));
1695 /* release the aops */
1696 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1701 /*-----------------------------------------------------------------*/
1702 /* genCpl - generate code for complement */
1703 /*-----------------------------------------------------------------*/
1710 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1712 D(emitcode (";", "genCpl"));
1714 /* assign asmOps to operand & result */
1715 aopOp (IC_LEFT (ic), ic, FALSE);
1716 aopOp (IC_RESULT (ic), ic, TRUE);
1718 /* special case if in bit space */
1719 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1723 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1724 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1726 /* promotion rules are responsible for this strange result:
1727 bit -> int -> ~int -> bit
1728 uchar -> int -> ~int -> bit
1730 werror(W_COMPLEMENT);
1731 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1735 tlbl=newiTempLabel(NULL);
1736 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1737 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1738 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1739 IS_AOP_PREG (IC_LEFT (ic)))
1741 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1746 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1748 emitcode ("", "%05d$:", tlbl->key + 100);
1749 outBitC (IC_RESULT(ic));
1753 size = AOP_SIZE (IC_RESULT (ic));
1756 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1758 emitcode ("cpl", "a");
1759 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1764 /* release the aops */
1765 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1766 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1769 /*-----------------------------------------------------------------*/
1770 /* genUminusFloat - unary minus for floating points */
1771 /*-----------------------------------------------------------------*/
1773 genUminusFloat (operand * op, operand * result)
1775 int size, offset = 0;
1778 D(emitcode ("; genUminusFloat",""));
1780 /* for this we just copy and then flip the bit */
1782 size = AOP_SIZE (op) - 1;
1787 aopGet (op, offset, FALSE, FALSE),
1789 isOperandVolatile (result, FALSE));
1793 l = aopGet (op, offset, FALSE, FALSE);
1797 emitcode ("cpl", "acc.7");
1798 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1801 /*-----------------------------------------------------------------*/
1802 /* genUminus - unary minus code generation */
1803 /*-----------------------------------------------------------------*/
1805 genUminus (iCode * ic)
1808 sym_link *optype, *rtype;
1811 D(emitcode ("; genUminus",""));
1814 aopOp (IC_LEFT (ic), ic, FALSE);
1815 aopOp (IC_RESULT (ic), ic, TRUE);
1817 /* if both in bit space then special
1819 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1820 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1823 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1824 emitcode ("cpl", "c");
1825 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1829 optype = operandType (IC_LEFT (ic));
1830 rtype = operandType (IC_RESULT (ic));
1832 /* if float then do float stuff */
1833 if (IS_FLOAT (optype))
1835 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1839 /* otherwise subtract from zero */
1840 size = AOP_SIZE (IC_LEFT (ic));
1845 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1846 if (!strcmp (l, "a"))
1850 emitcode ("cpl", "a");
1851 emitcode ("addc", "a,#0");
1857 emitcode ("clr", "a");
1858 emitcode ("subb", "a,%s", l);
1860 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1863 /* if any remaining bytes in the result */
1864 /* we just need to propagate the sign */
1865 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1867 emitcode ("rlc", "a");
1868 emitcode ("subb", "a,acc");
1870 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1874 /* release the aops */
1875 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1876 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1879 /*-----------------------------------------------------------------*/
1880 /* saveRegisters - will look for a call and save the registers */
1881 /*-----------------------------------------------------------------*/
1883 saveRegisters (iCode * lic)
1890 for (ic = lic; ic; ic = ic->next)
1891 if (ic->op == CALL || ic->op == PCALL)
1896 fprintf (stderr, "found parameter push with no function call\n");
1900 /* if the registers have been saved already or don't need to be then
1904 if (IS_SYMOP(IC_LEFT(ic)) &&
1905 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1906 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1909 /* save the registers in use at this time but skip the
1910 ones for the result */
1911 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1912 mcs51_rUmaskForOp (IC_RESULT(ic)));
1915 if (options.useXstack)
1917 int count = bitVectnBitsOn (rsave);
1921 i = bitVectFirstBit (rsave);
1922 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1923 emitcode ("mov", "r0,%s", spname);
1924 emitcode ("inc", "%s", spname);// allocate before use
1925 emitcode ("movx", "@r0,a");
1926 if (bitVectBitValue (rsave, R0_IDX))
1927 emitcode ("mov", "r0,a");
1929 else if (count != 0)
1931 if (bitVectBitValue (rsave, R0_IDX))
1933 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1935 emitcode ("mov", "r0,%s", spname);
1937 emitcode ("add", "a,#%d", count);
1938 emitcode ("mov", "%s,a", spname);
1939 for (i = 0; i < mcs51_nRegs; i++)
1941 if (bitVectBitValue (rsave, i))
1945 emitcode ("pop", "acc");
1946 emitcode ("push", "acc");
1950 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1952 emitcode ("movx", "@r0,a");
1955 emitcode ("inc", "r0");
1959 if (bitVectBitValue (rsave, R0_IDX))
1961 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1966 for (i = 0; i < mcs51_nRegs; i++)
1968 if (bitVectBitValue (rsave, i))
1969 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1973 /*-----------------------------------------------------------------*/
1974 /* unsaveRegisters - pop the pushed registers */
1975 /*-----------------------------------------------------------------*/
1977 unsaveRegisters (iCode * ic)
1982 /* restore the registers in use at this time but skip the
1983 ones for the result */
1984 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1985 mcs51_rUmaskForOp (IC_RESULT(ic)));
1987 if (options.useXstack)
1989 int count = bitVectnBitsOn (rsave);
1993 emitcode ("mov", "r0,%s", spname);
1994 emitcode ("dec", "r0");
1995 emitcode ("movx", "a,@r0");
1996 i = bitVectFirstBit (rsave);
1997 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1998 emitcode ("dec", "%s", spname);
2000 else if (count != 0)
2002 emitcode ("mov", "r0,%s", spname);
2003 for (i = mcs51_nRegs; i >= 0; i--)
2005 if (bitVectBitValue (rsave, i))
2007 emitcode ("dec", "r0");
2008 emitcode ("movx", "a,@r0");
2010 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
2012 emitcode ("push", "acc");
2015 emitcode ("mov", "%s,r0", spname);
2016 if (bitVectBitValue (rsave, R0_IDX))
2018 emitcode ("pop", "ar0");
2023 for (i = mcs51_nRegs; i >= 0; i--)
2025 if (bitVectBitValue (rsave, i))
2026 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2031 /*-----------------------------------------------------------------*/
2033 /*-----------------------------------------------------------------*/
2035 pushSide (operand * oper, int size)
2040 char *l = aopGet (oper, offset++, FALSE, TRUE);
2041 if (AOP_TYPE (oper) != AOP_REG &&
2042 AOP_TYPE (oper) != AOP_DIR &&
2046 emitcode ("push", "acc");
2050 emitcode ("push", "%s", l);
2055 /*-----------------------------------------------------------------*/
2056 /* assignResultValue - also indicates if acc is in use afterwards */
2057 /*-----------------------------------------------------------------*/
2059 assignResultValue (operand * oper)
2062 int size = AOP_SIZE (oper);
2063 bool accuse = FALSE;
2067 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2074 /*-----------------------------------------------------------------*/
2075 /* genXpush - pushes onto the external stack */
2076 /*-----------------------------------------------------------------*/
2078 genXpush (iCode * ic)
2080 asmop *aop = newAsmop (0);
2082 int size, offset = 0;
2084 D(emitcode ("; genXpush",""));
2086 aopOp (IC_LEFT (ic), ic, FALSE);
2087 r = getFreePtr (ic, &aop, FALSE);
2089 size = AOP_SIZE (IC_LEFT (ic));
2093 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2094 emitcode ("mov", "%s,%s", r->name, spname);
2095 emitcode ("inc", "%s", spname); // allocate space first
2096 emitcode ("movx", "@%s,a", r->name);
2100 // allocate space first
2101 emitcode ("mov", "%s,%s", r->name, spname);
2103 emitcode ("add", "a,#%d", size);
2104 emitcode ("mov", "%s,a", spname);
2108 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2109 emitcode ("movx", "@%s,a", r->name);
2110 emitcode ("inc", "%s", r->name);
2114 freeAsmop (NULL, aop, ic, TRUE);
2115 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2118 /*-----------------------------------------------------------------*/
2119 /* genIpush - generate code for pushing this gets a little complex */
2120 /*-----------------------------------------------------------------*/
2122 genIpush (iCode * ic)
2124 int size, offset = 0;
2127 D(emitcode ("; genIpush",""));
2129 /* if this is not a parm push : ie. it is spill push
2130 and spill push is always done on the local stack */
2134 /* and the item is spilt then do nothing */
2135 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2138 aopOp (IC_LEFT (ic), ic, FALSE);
2139 size = AOP_SIZE (IC_LEFT (ic));
2140 /* push it on the stack */
2143 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2149 emitcode ("push", "%s", l);
2154 /* this is a paramter push: in this case we call
2155 the routine to find the call and save those
2156 registers that need to be saved */
2159 /* if use external stack then call the external
2160 stack pushing routine */
2161 if (options.useXstack)
2167 /* then do the push */
2168 aopOp (IC_LEFT (ic), ic, FALSE);
2170 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2171 size = AOP_SIZE (IC_LEFT (ic));
2175 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2176 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2177 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2181 emitcode ("push", "acc");
2184 emitcode ("push", "%s", l);
2187 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2190 /*-----------------------------------------------------------------*/
2191 /* genIpop - recover the registers: can happen only for spilling */
2192 /*-----------------------------------------------------------------*/
2194 genIpop (iCode * ic)
2198 D(emitcode ("; genIpop",""));
2200 /* if the temp was not pushed then */
2201 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2204 aopOp (IC_LEFT (ic), ic, FALSE);
2205 size = AOP_SIZE (IC_LEFT (ic));
2206 offset = (size - 1);
2208 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2211 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2214 /*-----------------------------------------------------------------*/
2215 /* saveRBank - saves an entire register bank on the stack */
2216 /*-----------------------------------------------------------------*/
2218 saveRBank (int bank, iCode * ic, bool pushPsw)
2221 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2225 if (options.useXstack)
2229 /* Assume r0 is available for use. */
2230 r = mcs51_regWithIdx (R0_IDX);;
2235 r = getFreePtr (ic, &aop, FALSE);
2237 // allocate space first
2238 emitcode ("mov", "%s,%s", r->name, spname);
2240 emitcode ("add", "a,#%d", count);
2241 emitcode ("mov", "%s,a", spname);
2244 for (i = 0; i < mcs51_nRegs; i++)
2246 if (options.useXstack)
2248 emitcode ("mov", "a,(%s+%d)",
2249 regs8051[i].base, 8 * bank + regs8051[i].offset);
2250 emitcode ("movx", "@%s,a", r->name);
2252 emitcode ("inc", "%s", r->name);
2255 emitcode ("push", "(%s+%d)",
2256 regs8051[i].base, 8 * bank + regs8051[i].offset);
2261 if (options.useXstack)
2263 emitcode ("mov", "a,psw");
2264 emitcode ("movx", "@%s,a", r->name);
2269 emitcode ("push", "psw");
2272 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2277 freeAsmop (NULL, aop, ic, TRUE);
2286 /*-----------------------------------------------------------------*/
2287 /* unsaveRBank - restores the register bank from stack */
2288 /*-----------------------------------------------------------------*/
2290 unsaveRBank (int bank, iCode * ic, bool popPsw)
2296 if (options.useXstack)
2300 /* Assume r0 is available for use. */
2301 r = mcs51_regWithIdx (R0_IDX);;
2306 r = getFreePtr (ic, &aop, FALSE);
2308 emitcode ("mov", "%s,%s", r->name, spname);
2313 if (options.useXstack)
2315 emitcode ("dec", "%s", r->name);
2316 emitcode ("movx", "a,@%s", r->name);
2317 emitcode ("mov", "psw,a");
2321 emitcode ("pop", "psw");
2325 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2327 if (options.useXstack)
2329 emitcode ("dec", "%s", r->name);
2330 emitcode ("movx", "a,@%s", r->name);
2331 emitcode ("mov", "(%s+%d),a",
2332 regs8051[i].base, 8 * bank + regs8051[i].offset);
2336 emitcode ("pop", "(%s+%d)",
2337 regs8051[i].base, 8 * bank + regs8051[i].offset);
2341 if (options.useXstack)
2343 emitcode ("mov", "%s,%s", spname, r->name);
2348 freeAsmop (NULL, aop, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genSend - gen code for SEND */
2354 /*-----------------------------------------------------------------*/
2355 static void genSend(set *sendSet)
2360 for (sic = setFirstItem (sendSet); sic;
2361 sic = setNextItem (sendSet)) {
2362 int size, offset = 0;
2363 aopOp (IC_LEFT (sic), sic, FALSE);
2364 size = AOP_SIZE (IC_LEFT (sic));
2366 if (sic->argreg == 1) {
2368 char *l = aopGet (IC_LEFT (sic), offset,
2370 if (strcmp (l, fReturn[offset]))
2371 emitcode ("mov", "%s,%s", fReturn[offset], l);
2377 emitcode ("mov","b1_%d,%s",rb1_count++,
2378 aopGet (IC_LEFT (sic), offset++,FALSE, FALSE));
2381 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2385 /*-----------------------------------------------------------------*/
2386 /* genCall - generates a call statement */
2387 /*-----------------------------------------------------------------*/
2389 genCall (iCode * ic)
2392 // bool restoreBank = FALSE;
2393 bool swapBanks = FALSE;
2394 bool accuse = FALSE;
2395 bool accPushed = FALSE;
2397 D(emitcode("; genCall",""));
2399 dtype = operandType (IC_LEFT (ic));
2400 /* if send set is not empty then assign */
2403 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2404 genSend(reverseSet(_G.sendSet));
2406 genSend(_G.sendSet);
2412 /* if we are calling a not _naked function that is not using
2413 the same register bank then we need to save the
2414 destination registers on the stack */
2415 dtype = operandType (IC_LEFT (ic));
2416 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2417 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2418 !IFFUNC_ISISR (dtype))
2423 /* if caller saves & we have not saved then */
2429 emitcode ("mov", "psw,#0x%02x",
2430 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2434 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2436 if (IFFUNC_CALLEESAVES(dtype))
2438 werror (E_BANKED_WITH_CALLEESAVES);
2442 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2443 OP_SYMBOL (IC_LEFT (ic))->rname :
2444 OP_SYMBOL (IC_LEFT (ic))->name);
2446 emitcode ("mov", "r0,#%s", l);
2447 emitcode ("mov", "r1,#(%s >> 8)", l);
2448 emitcode ("mov", "r2,#(%s >> 16)", l);
2449 emitcode ("lcall", "__sdcc_banked_call");
2454 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2455 OP_SYMBOL (IC_LEFT (ic))->rname :
2456 OP_SYMBOL (IC_LEFT (ic))->name));
2461 emitcode ("mov", "psw,#0x%02x",
2462 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2465 /* if we need assign a result value */
2466 if ((IS_ITEMP (IC_RESULT (ic)) &&
2467 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2468 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2469 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2470 IS_TRUE_SYMOP (IC_RESULT (ic)))
2474 aopOp (IC_RESULT (ic), ic, FALSE);
2477 accuse = assignResultValue (IC_RESULT (ic));
2479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2482 /* adjust the stack for parameters if required */
2486 if (ic->parmBytes > 3)
2490 emitcode ("push", "acc");
2494 emitcode ("mov", "a,%s", spname);
2495 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2496 emitcode ("mov", "%s,a", spname);
2498 /* unsaveRegisters from xstack needs acc, but */
2499 /* unsaveRegisters from stack needs this popped */
2500 if (accPushed && !options.useXstack)
2502 emitcode ("pop", "acc");
2507 for (i = 0; i < ic->parmBytes; i++)
2508 emitcode ("dec", "%s", spname);
2511 /* if we hade saved some registers then unsave them */
2512 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2514 if (accuse && !accPushed && options.useXstack)
2516 /* xstack needs acc, but doesn't touch normal stack */
2517 emitcode ("push", "acc");
2520 unsaveRegisters (ic);
2523 // /* if register bank was saved then pop them */
2525 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2528 emitcode ("pop", "acc");
2531 /*-----------------------------------------------------------------*/
2532 /* -10l - generates a call by pointer statement */
2533 /*-----------------------------------------------------------------*/
2535 genPcall (iCode * ic)
2539 symbol *rlbl = newiTempLabel (NULL);
2540 // bool restoreBank=FALSE;
2541 bool swapBanks = FALSE;
2543 D(emitcode("; genPCall",""));
2545 /* if caller saves & we have not saved then */
2549 /* if we are calling a not _naked function that is not using
2550 the same register bank then we need to save the
2551 destination registers on the stack */
2552 dtype = operandType (IC_LEFT (ic))->next;
2553 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2554 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2555 !IFFUNC_ISISR (dtype))
2557 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2558 // restoreBank=TRUE;
2560 // need caution message to user here
2563 etype = getSpec(dtype);
2564 if (IS_LITERAL(etype))
2566 /* if send set is not empty then assign */
2569 genSend(reverseSet(_G.sendSet));
2575 emitcode ("mov", "psw,#0x%02x",
2576 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2579 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2581 if (IFFUNC_CALLEESAVES(dtype))
2583 werror (E_BANKED_WITH_CALLEESAVES);
2587 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2589 emitcode ("mov", "r0,#%s", l);
2590 emitcode ("mov", "r1,#(%s >> 8)", l);
2591 emitcode ("mov", "r2,#(%s >> 16)", l);
2592 emitcode ("lcall", "__sdcc_banked_call");
2597 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2602 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2604 if (IFFUNC_CALLEESAVES(dtype))
2606 werror (E_BANKED_WITH_CALLEESAVES);
2610 aopOp (IC_LEFT (ic), ic, FALSE);
2614 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2615 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2616 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2620 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2621 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2622 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2623 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2626 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2628 /* if send set is not empty then assign */
2631 genSend(reverseSet(_G.sendSet));
2637 emitcode ("mov", "psw,#0x%02x",
2638 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2642 emitcode ("lcall", "__sdcc_banked_call");
2647 /* push the return address on to the stack */
2648 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2649 emitcode ("push", "acc");
2650 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2651 emitcode ("push", "acc");
2653 /* now push the calling address */
2654 aopOp (IC_LEFT (ic), ic, FALSE);
2656 pushSide (IC_LEFT (ic), FPTRSIZE);
2658 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2660 /* if send set is not empty the assign */
2663 genSend(reverseSet(_G.sendSet));
2669 emitcode ("mov", "psw,#0x%02x",
2670 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2674 emitcode ("ret", "");
2675 emitcode ("", "%05d$:", (rlbl->key + 100));
2680 emitcode ("mov", "psw,#0x%02x",
2681 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2684 /* if we need assign a result value */
2685 if ((IS_ITEMP (IC_RESULT (ic)) &&
2686 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2687 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2688 IS_TRUE_SYMOP (IC_RESULT (ic)))
2692 aopOp (IC_RESULT (ic), ic, FALSE);
2695 assignResultValue (IC_RESULT (ic));
2697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2700 /* adjust the stack for parameters if
2705 if (ic->parmBytes > 3)
2707 emitcode ("mov", "a,%s", spname);
2708 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2709 emitcode ("mov", "%s,a", spname);
2712 for (i = 0; i < ic->parmBytes; i++)
2713 emitcode ("dec", "%s", spname);
2717 // /* if register bank was saved then unsave them */
2719 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2721 /* if we hade saved some registers then
2723 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2724 unsaveRegisters (ic);
2727 /*-----------------------------------------------------------------*/
2728 /* resultRemat - result is rematerializable */
2729 /*-----------------------------------------------------------------*/
2731 resultRemat (iCode * ic)
2733 if (SKIP_IC (ic) || ic->op == IFX)
2736 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2738 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2739 if (sym->remat && !POINTER_SET (ic))
2746 #if defined(__BORLANDC__) || defined(_MSC_VER)
2747 #define STRCASECMP stricmp
2749 #define STRCASECMP strcasecmp
2752 /*-----------------------------------------------------------------*/
2753 /* inExcludeList - return 1 if the string is in exclude Reg list */
2754 /*-----------------------------------------------------------------*/
2756 regsCmp(void *p1, void *p2)
2758 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2762 inExcludeList (char *s)
2764 const char *p = setFirstItem(options.excludeRegsSet);
2766 if (p == NULL || STRCASECMP(p, "none") == 0)
2770 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2773 /*-----------------------------------------------------------------*/
2774 /* genFunction - generated code for function entry */
2775 /*-----------------------------------------------------------------*/
2777 genFunction (iCode * ic)
2779 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2781 bool switchedPSW = FALSE;
2782 int calleesaves_saved_register = -1;
2783 int stackAdjust = sym->stack;
2784 int accIsFree = sym->recvSize < 4;
2785 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2786 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2789 /* create the function header */
2790 emitcode (";", "-----------------------------------------");
2791 emitcode (";", " function %s", sym->name);
2792 emitcode (";", "-----------------------------------------");
2794 emitcode ("", "%s:", sym->rname);
2795 ftype = operandType (IC_LEFT (ic));
2796 _G.currentFunc = sym;
2798 if (IFFUNC_ISNAKED(ftype))
2800 emitcode(";", "naked function: no prologue.");
2804 /* here we need to generate the equates for the
2805 register bank if required */
2806 if (FUNC_REGBANK (ftype) != rbank)
2810 rbank = FUNC_REGBANK (ftype);
2811 for (i = 0; i < mcs51_nRegs; i++)
2813 if (strcmp (regs8051[i].base, "0") == 0)
2814 emitcode ("", "%s = 0x%02x",
2816 8 * rbank + regs8051[i].offset);
2818 emitcode ("", "%s = %s + 0x%02x",
2821 8 * rbank + regs8051[i].offset);
2825 /* if this is an interrupt service routine then
2826 save acc, b, dpl, dph */
2827 if (IFFUNC_ISISR (sym->type))
2830 if (!inExcludeList ("acc"))
2831 emitcode ("push", "acc");
2832 if (!inExcludeList ("b"))
2833 emitcode ("push", "b");
2834 if (!inExcludeList ("dpl"))
2835 emitcode ("push", "dpl");
2836 if (!inExcludeList ("dph"))
2837 emitcode ("push", "dph");
2838 /* if this isr has no bank i.e. is going to
2839 run with bank 0 , then we need to save more
2841 if (!FUNC_REGBANK (sym->type))
2844 /* if this function does not call any other
2845 function then we can be economical and
2846 save only those registers that are used */
2847 if (!IFFUNC_HASFCALL(sym->type))
2851 /* if any registers used */
2854 /* save the registers used */
2855 for (i = 0; i < sym->regsUsed->size; i++)
2857 if (bitVectBitValue (sym->regsUsed, i))
2858 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2865 /* this function has a function call. We cannot
2866 determines register usage so we will have to push the
2868 saveRBank (0, ic, FALSE);
2869 if (options.parms_in_bank1) {
2871 for (i=0; i < 8 ; i++ ) {
2872 emitcode ("push","%s",rb1regs[i]);
2879 /* This ISR uses a non-zero bank.
2881 * We assume that the bank is available for our
2884 * However, if this ISR calls a function which uses some
2885 * other bank, we must save that bank entirely.
2887 unsigned long banksToSave = 0;
2889 if (IFFUNC_HASFCALL(sym->type))
2892 #define MAX_REGISTER_BANKS 4
2897 for (i = ic; i; i = i->next)
2899 if (i->op == ENDFUNCTION)
2901 /* we got to the end OK. */
2909 dtype = operandType (IC_LEFT(i));
2911 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2913 /* Mark this bank for saving. */
2914 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2916 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2920 banksToSave |= (1 << FUNC_REGBANK(dtype));
2923 /* And note that we don't need to do it in
2931 /* This is a mess; we have no idea what
2932 * register bank the called function might
2935 * The only thing I can think of to do is
2936 * throw a warning and hope.
2938 werror(W_FUNCPTR_IN_USING_ISR);
2942 if (banksToSave && options.useXstack)
2944 /* Since we aren't passing it an ic,
2945 * saveRBank will assume r0 is available to abuse.
2947 * So switch to our (trashable) bank now, so
2948 * the caller's R0 isn't trashed.
2950 emitcode ("push", "psw");
2951 emitcode ("mov", "psw,#0x%02x",
2952 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2956 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2958 if (banksToSave & (1 << ix))
2960 saveRBank(ix, NULL, FALSE);
2964 // TODO: this needs a closer look
2965 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2968 /* Set the register bank to the desired value if nothing else */
2969 /* has done so yet. */
2972 emitcode ("push", "psw");
2973 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2978 /* This is a non-ISR function. The caller has already switched register */
2979 /* banks, if necessary, so just handle the callee-saves option. */
2981 /* if callee-save to be used for this function
2982 then save the registers being used in this function */
2983 if (IFFUNC_CALLEESAVES(sym->type))
2987 /* if any registers used */
2990 /* save the registers used */
2991 for (i = 0; i < sym->regsUsed->size; i++)
2993 if (bitVectBitValue (sym->regsUsed, i))
2995 /* remember one saved register for later usage */
2996 if (calleesaves_saved_register < 0)
2997 calleesaves_saved_register = i;
2998 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
3009 if (options.useXstack)
3011 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3013 emitcode ("mov", "r0,%s", spname);
3014 emitcode ("inc", "%s", spname);
3015 emitcode ("xch", "a,_bpx");
3016 emitcode ("movx", "@r0,a");
3017 emitcode ("inc", "r0");
3018 emitcode ("mov", "a,r0");
3019 emitcode ("xch", "a,_bpx");
3023 emitcode ("push", "_bp"); /* save the callers stack */
3024 emitcode ("mov", "_bp,sp");
3029 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3031 /* set up the stack */
3032 emitcode ("push", "_bp"); /* save the callers stack */
3033 emitcode ("mov", "_bp,sp");
3038 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3039 /* before setting up the stack frame completely. */
3040 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3042 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3046 if (rsym && rsym->regType == REG_CND)
3048 if (rsym && (rsym->accuse || rsym->ruonly))
3050 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3051 rsym = rsym->usl.spillLoc;
3054 /* If the RECEIVE operand immediately spills to the first entry on the */
3055 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3056 /* rather than the usual @r0/r1 machinations. */
3057 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3061 _G.current_iCode = ric;
3062 D(emitcode ("; genReceive",""));
3063 for (ofs=0; ofs < sym->recvSize; ofs++)
3065 if (!strcmp (fReturn[ofs], "a"))
3066 emitcode ("push", "acc");
3068 emitcode ("push", fReturn[ofs]);
3070 stackAdjust -= sym->recvSize;
3073 assert (stackAdjust>=0);
3076 _G.current_iCode = ic;
3080 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3081 /* to free up the accumulator. */
3082 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3086 _G.current_iCode = ric;
3087 D(emitcode ("; genReceive",""));
3088 for (ofs=0; ofs < sym->recvSize; ofs++)
3090 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3092 _G.current_iCode = ic;
3098 /* adjust the stack for the function */
3101 int i = stackAdjust;
3103 werror (W_STACK_OVERFLOW, sym->name);
3105 if (i > 3 && accIsFree)
3107 emitcode ("mov", "a,sp");
3108 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3109 emitcode ("mov", "sp,a");
3113 /* The accumulator is not free, so we will need another register */
3114 /* to clobber. No need to worry about a possible conflict with */
3115 /* the above early RECEIVE optimizations since they would have */
3116 /* freed the accumulator if they were generated. */
3118 if (IFFUNC_CALLEESAVES(sym->type))
3120 /* if it's a callee-saves function we need a saved register */
3121 if (calleesaves_saved_register >= 0)
3123 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3124 emitcode ("mov", "a,sp");
3125 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3126 emitcode ("mov", "sp,a");
3127 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3130 /* do it the hard way */
3132 emitcode ("inc", "sp");
3136 /* not callee-saves, we can clobber r0 */
3137 emitcode ("mov", "r0,a");
3138 emitcode ("mov", "a,sp");
3139 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3140 emitcode ("mov", "sp,a");
3141 emitcode ("mov", "a,r0");
3146 emitcode ("inc", "sp");
3151 char i = ((char) sym->xstack & 0xff);
3153 if (i > 3 && accIsFree)
3155 emitcode ("mov", "a,_spx");
3156 emitcode ("add", "a,#0x%02x", i);
3157 emitcode ("mov", "_spx,a");
3161 emitcode ("push", "acc");
3162 emitcode ("mov", "a,_spx");
3163 emitcode ("add", "a,#0x%02x", i);
3164 emitcode ("mov", "_spx,a");
3165 emitcode ("pop", "acc");
3170 emitcode ("inc", "_spx");
3174 /* if critical function then turn interrupts off */
3175 if (IFFUNC_ISCRITICAL (ftype))
3177 symbol *tlbl = newiTempLabel (NULL);
3178 emitcode ("setb", "c");
3179 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3180 emitcode ("clr", "c");
3181 emitcode ("", "%05d$:", (tlbl->key + 100));
3182 emitcode ("push", "psw"); /* save old ea via c in psw */
3186 /*-----------------------------------------------------------------*/
3187 /* genEndFunction - generates epilogue for functions */
3188 /*-----------------------------------------------------------------*/
3190 genEndFunction (iCode * ic)
3192 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3193 lineNode *lnp = lineCurr;
3195 bitVect *regsUsedPrologue;
3196 bitVect *regsUnneeded;
3199 _G.currentFunc = NULL;
3200 if (IFFUNC_ISNAKED(sym->type))
3202 emitcode(";", "naked function: no epilogue.");
3203 if (options.debug && currFunc)
3204 debugFile->writeEndFunction (currFunc, ic, 0);
3208 if (IFFUNC_ISCRITICAL (sym->type))
3210 emitcode ("pop", "psw"); /* restore ea via c in psw */
3211 emitcode ("mov", "ea,c");
3214 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3216 if (options.useXstack)
3220 emitcode ("mov", "sp,_bp");
3221 emitcode ("pop", "_bp");
3223 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3225 emitcode ("xch", "a,_bpx");
3226 emitcode ("mov", "r0,a");
3227 emitcode ("dec", "r0");
3228 emitcode ("movx", "a,@r0");
3229 emitcode ("xch", "a,_bpx");
3230 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3233 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3235 emitcode ("mov", "sp,_bp");
3236 emitcode ("pop", "_bp");
3240 /* restore the register bank */
3241 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3243 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3244 || !options.useXstack)
3246 /* Special case of ISR using non-zero bank with useXstack
3249 emitcode ("pop", "psw");
3253 if (IFFUNC_ISISR (sym->type))
3256 /* now we need to restore the registers */
3257 /* if this isr has no bank i.e. is going to
3258 run with bank 0 , then we need to save more
3260 if (!FUNC_REGBANK (sym->type))
3262 /* if this function does not call any other
3263 function then we can be economical and
3264 save only those registers that are used */
3265 if (!IFFUNC_HASFCALL(sym->type))
3269 /* if any registers used */
3272 /* save the registers used */
3273 for (i = sym->regsUsed->size; i >= 0; i--)
3275 if (bitVectBitValue (sym->regsUsed, i))
3276 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3282 if (options.parms_in_bank1) {
3284 for (i = 7 ; i >= 0 ; i-- ) {
3285 emitcode ("pop","%s",rb1regs[i]);
3288 /* this function has a function call cannot
3289 determines register usage so we will have to pop the
3291 unsaveRBank (0, ic, FALSE);
3296 /* This ISR uses a non-zero bank.
3298 * Restore any register banks saved by genFunction
3301 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3304 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3306 if (savedBanks & (1 << ix))
3308 unsaveRBank(ix, NULL, FALSE);
3312 if (options.useXstack)
3314 /* Restore bank AFTER calling unsaveRBank,
3315 * since it can trash r0.
3317 emitcode ("pop", "psw");
3321 if (!inExcludeList ("dph"))
3322 emitcode ("pop", "dph");
3323 if (!inExcludeList ("dpl"))
3324 emitcode ("pop", "dpl");
3325 if (!inExcludeList ("b"))
3326 emitcode ("pop", "b");
3327 if (!inExcludeList ("acc"))
3328 emitcode ("pop", "acc");
3330 /* if debug then send end of function */
3331 if (options.debug && currFunc)
3333 debugFile->writeEndFunction (currFunc, ic, 1);
3336 emitcode ("reti", "");
3340 if (IFFUNC_CALLEESAVES(sym->type))
3344 /* if any registers used */
3347 /* save the registers used */
3348 for (i = sym->regsUsed->size; i >= 0; i--)
3350 if (bitVectBitValue (sym->regsUsed, i) ||
3351 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3352 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3355 else if (mcs51_ptrRegReq)
3357 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3358 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3363 /* if debug then send end of function */
3364 if (options.debug && currFunc)
3366 debugFile->writeEndFunction (currFunc, ic, 1);
3369 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3371 emitcode ("ljmp", "__sdcc_banked_ret");
3375 emitcode ("ret", "");
3379 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3382 /* If this was an interrupt handler using bank 0 that called another */
3383 /* function, then all registers must be saved; nothing to optimized. */
3384 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3385 && !FUNC_REGBANK(sym->type))
3388 /* There are no push/pops to optimize if not callee-saves or ISR */
3389 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3392 /* If there were stack parameters, we cannot optimize without also */
3393 /* fixing all of the stack offsets; this is too dificult to consider. */
3394 if (FUNC_HASSTACKPARM(sym->type))
3397 /* Compute the registers actually used */
3398 regsUsed = newBitVect (mcs51_nRegs);
3399 regsUsedPrologue = newBitVect (mcs51_nRegs);
3402 if (lnp->ic && lnp->ic->op == FUNCTION)
3403 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3405 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3407 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3408 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3415 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3416 && !bitVectBitValue (regsUsed, CND_IDX))
3418 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3419 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3420 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3421 bitVectUnSetBit (regsUsed, CND_IDX);
3424 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3426 /* If this was an interrupt handler that called another function */
3427 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3428 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3430 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3431 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3432 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3433 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3434 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3437 /* Remove the unneeded push/pops */
3438 regsUnneeded = newBitVect (mcs51_nRegs);
3441 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3443 if (!strncmp(lnp->line, "push", 4))
3445 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3446 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3448 connectLine (lnp->prev, lnp->next);
3449 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3452 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3454 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3455 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3457 connectLine (lnp->prev, lnp->next);
3458 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3465 for (idx = 0; idx < regsUnneeded->size; idx++)
3466 if (bitVectBitValue (regsUnneeded, idx))
3467 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3469 freeBitVect (regsUnneeded);
3470 freeBitVect (regsUsed);
3471 freeBitVect (regsUsedPrologue);
3474 /*-----------------------------------------------------------------*/
3475 /* genRet - generate code for return statement */
3476 /*-----------------------------------------------------------------*/
3480 int size, offset = 0, pushed = 0;
3482 D(emitcode ("; genRet",""));
3484 /* if we have no return value then
3485 just generate the "ret" */
3489 /* we have something to return then
3490 move the return value into place */
3491 aopOp (IC_LEFT (ic), ic, FALSE);
3492 size = AOP_SIZE (IC_LEFT (ic));
3497 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3500 l = aopGet (IC_LEFT (ic), offset++,
3502 emitcode ("push", "%s", l);
3507 l = aopGet (IC_LEFT (ic), offset,
3509 if (strcmp (fReturn[offset], l))
3510 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3519 if (strcmp (fReturn[pushed], "a"))
3520 emitcode ("pop", fReturn[pushed]);
3522 emitcode ("pop", "acc");
3525 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3528 /* generate a jump to the return label
3529 if the next is not the return statement */
3530 if (!(ic->next && ic->next->op == LABEL &&
3531 IC_LABEL (ic->next) == returnLabel))
3533 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3537 /*-----------------------------------------------------------------*/
3538 /* genLabel - generates a label */
3539 /*-----------------------------------------------------------------*/
3541 genLabel (iCode * ic)
3543 /* special case never generate */
3544 if (IC_LABEL (ic) == entryLabel)
3547 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp */
3552 /*-----------------------------------------------------------------*/
3554 genGoto (iCode * ic)
3556 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3559 /*-----------------------------------------------------------------*/
3560 /* findLabelBackwards: walks back through the iCode chain looking */
3561 /* for the given label. Returns number of iCode instructions */
3562 /* between that label and given ic. */
3563 /* Returns zero if label not found. */
3564 /*-----------------------------------------------------------------*/
3566 findLabelBackwards (iCode * ic, int key)
3575 /* If we have any pushes or pops, we cannot predict the distance.
3576 I don't like this at all, this should be dealt with in the
3578 if (ic->op == IPUSH || ic->op == IPOP) {
3582 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3591 /*-----------------------------------------------------------------*/
3592 /* genPlusIncr :- does addition with increment if possible */
3593 /*-----------------------------------------------------------------*/
3595 genPlusIncr (iCode * ic)
3597 unsigned int icount;
3598 unsigned int size = getDataSize (IC_RESULT (ic));
3600 /* will try to generate an increment */
3601 /* if the right side is not a literal
3603 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3606 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3608 D(emitcode ("; genPlusIncr",""));
3610 /* if increment >=16 bits in register or direct space */
3611 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3612 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3613 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3621 /* If the next instruction is a goto and the goto target
3622 * is < 10 instructions previous to this, we can generate
3623 * jumps straight to that target.
3625 if (ic->next && ic->next->op == GOTO
3626 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3627 && labelRange <= 10)
3629 emitcode (";", "tail increment optimized");
3630 tlbl = IC_LABEL (ic->next);
3635 tlbl = newiTempLabel (NULL);
3638 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3639 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3640 IS_AOP_PREG (IC_RESULT (ic)))
3641 emitcode ("cjne", "%s,#0x00,%05d$",
3642 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3646 emitcode ("clr", "a");
3647 emitcode ("cjne", "a,%s,%05d$",
3648 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3652 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3655 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656 IS_AOP_PREG (IC_RESULT (ic)))
3657 emitcode ("cjne", "%s,#0x00,%05d$",
3658 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3661 emitcode ("cjne", "a,%s,%05d$",
3662 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3665 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3669 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3670 IS_AOP_PREG (IC_RESULT (ic)))
3671 emitcode ("cjne", "%s,#0x00,%05d$",
3672 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3676 emitcode ("cjne", "a,%s,%05d$",
3677 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3680 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3685 emitcode ("", "%05d$:", tlbl->key + 100);
3690 /* if result is dptr */
3691 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3692 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3693 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3694 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3696 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3702 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3705 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3706 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3708 emitcode ("inc", "dptr");
3713 /* if the literal value of the right hand side
3714 is greater than 4 then it is not worth it */
3718 /* if the sizes are greater than 1 then we cannot */
3719 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3720 AOP_SIZE (IC_LEFT (ic)) > 1)
3723 /* we can if the aops of the left & result match or
3724 if they are in registers and the registers are the
3726 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3731 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3732 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3733 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3739 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3748 /*-----------------------------------------------------------------*/
3749 /* outBitAcc - output a bit in acc */
3750 /*-----------------------------------------------------------------*/
3752 outBitAcc (operand * result)
3754 symbol *tlbl = newiTempLabel (NULL);
3755 /* if the result is a bit */
3756 if (AOP_TYPE (result) == AOP_CRY)
3758 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
3762 emitcode ("jz", "%05d$", tlbl->key + 100);
3763 emitcode ("mov", "a,%s", one);
3764 emitcode ("", "%05d$:", tlbl->key + 100);
3769 /*-----------------------------------------------------------------*/
3770 /* genPlusBits - generates code for addition of two bits */
3771 /*-----------------------------------------------------------------*/
3773 genPlusBits (iCode * ic)
3775 D(emitcode ("; genPlusBits",""));
3777 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3779 symbol *lbl = newiTempLabel (NULL);
3780 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3781 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3782 emitcode ("cpl", "c");
3783 emitcode ("", "%05d$:", (lbl->key + 100));
3784 outBitC (IC_RESULT (ic));
3788 emitcode ("clr", "a");
3789 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3790 emitcode ("rlc", "a");
3791 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3792 emitcode ("addc", "a,#0x00");
3793 outAcc (IC_RESULT (ic));
3798 /* This is the original version of this code.
3800 * This is being kept around for reference,
3801 * because I am not entirely sure I got it right...
3804 adjustArithmeticResult (iCode * ic)
3806 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3807 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3808 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3809 aopPut (IC_RESULT (ic),
3810 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
3812 isOperandVolatile (IC_RESULT (ic), FALSE));
3814 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3815 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3816 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3817 aopPut (IC_RESULT (ic),
3818 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
3820 isOperandVolatile (IC_RESULT (ic), FALSE));
3822 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3823 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3824 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3825 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3826 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3829 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3830 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3834 /* This is the pure and virtuous version of this code.
3835 * I'm pretty certain it's right, but not enough to toss the old
3839 adjustArithmeticResult (iCode * ic)
3841 if (opIsGptr (IC_RESULT (ic)) &&
3842 opIsGptr (IC_LEFT (ic)) &&
3843 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3845 aopPut (IC_RESULT (ic),
3846 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
3848 isOperandVolatile (IC_RESULT (ic), FALSE));
3851 if (opIsGptr (IC_RESULT (ic)) &&
3852 opIsGptr (IC_RIGHT (ic)) &&
3853 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3855 aopPut (IC_RESULT (ic),
3856 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
3858 isOperandVolatile (IC_RESULT (ic), FALSE));
3861 if (opIsGptr (IC_RESULT (ic)) &&
3862 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3863 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3864 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3865 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3868 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3869 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3874 /*-----------------------------------------------------------------*/
3875 /* genPlus - generates code for addition */
3876 /*-----------------------------------------------------------------*/
3878 genPlus (iCode * ic)
3880 int size, offset = 0;
3883 operand *leftOp, *rightOp;
3886 /* special cases :- */
3888 D(emitcode ("; genPlus",""));
3890 aopOp (IC_LEFT (ic), ic, FALSE);
3891 aopOp (IC_RIGHT (ic), ic, FALSE);
3892 aopOp (IC_RESULT (ic), ic, TRUE);
3894 /* if literal, literal on the right or
3895 if left requires ACC or right is already
3897 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3898 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3899 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3901 operand *t = IC_RIGHT (ic);
3902 IC_RIGHT (ic) = IC_LEFT (ic);
3906 /* if both left & right are in bit
3908 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3909 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3915 /* if left in bit space & right literal */
3916 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3917 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3919 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3920 /* if result in bit space */
3921 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3923 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3924 emitcode ("cpl", "c");
3925 outBitC (IC_RESULT (ic));
3929 size = getDataSize (IC_RESULT (ic));
3932 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
3933 emitcode ("addc", "a,#00");
3934 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3940 /* if I can do an increment instead
3941 of add then GOOD for ME */
3942 if (genPlusIncr (ic) == TRUE)
3945 size = getDataSize (IC_RESULT (ic));
3946 leftOp = IC_LEFT(ic);
3947 rightOp = IC_RIGHT(ic);
3950 /* if this is an add for an array access
3951 at a 256 byte boundary */
3953 && AOP_TYPE (op) == AOP_IMMD
3955 && IS_SPEC (OP_SYM_ETYPE (op))
3956 && SPEC_ABSA (OP_SYM_ETYPE (op))
3957 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3960 D(emitcode ("; genPlus aligned array",""));
3961 aopPut (IC_RESULT (ic),
3962 aopGet (rightOp, 0, FALSE, FALSE),
3964 isOperandVolatile (IC_RESULT (ic), FALSE));
3966 if( 1 == getDataSize (IC_RIGHT (ic)) )
3968 aopPut (IC_RESULT (ic),
3969 aopGet (leftOp, 1, FALSE, FALSE),
3971 isOperandVolatile (IC_RESULT (ic), FALSE));
3975 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
3976 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3977 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3982 /* if the lower bytes of a literal are zero skip the addition */
3983 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3985 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3986 (skip_bytes+1 < size))
3991 D(emitcode ("; genPlus shortcut",""));
3996 if( offset >= skip_bytes )
3998 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4001 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4003 emitcode("xch", "a,b");
4004 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4005 emitcode (add, "a,b");
4008 else if (aopGetUsesAcc (leftOp, offset))
4010 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4011 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4015 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4016 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4018 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4019 add = "addc"; /* further adds must propagate carry */
4023 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4024 isOperandVolatile (IC_RESULT (ic), FALSE))
4027 aopPut (IC_RESULT (ic),
4028 aopGet (leftOp, offset, FALSE, FALSE),
4030 isOperandVolatile (IC_RESULT (ic), FALSE));
4036 adjustArithmeticResult (ic);
4039 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4040 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4041 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4044 /*-----------------------------------------------------------------*/
4045 /* genMinusDec :- does subtraction with deccrement if possible */
4046 /*-----------------------------------------------------------------*/
4048 genMinusDec (iCode * ic)
4050 unsigned int icount;
4051 unsigned int size = getDataSize (IC_RESULT (ic));
4053 /* will try to generate an increment */
4054 /* if the right side is not a literal
4056 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4059 /* if the literal value of the right hand side
4060 is greater than 4 then it is not worth it */
4061 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4064 D(emitcode ("; genMinusDec",""));
4066 /* if decrement >=16 bits in register or direct space */
4067 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4068 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4076 /* If the next instruction is a goto and the goto target
4077 * is <= 10 instructions previous to this, we can generate
4078 * jumps straight to that target.
4080 if (ic->next && ic->next->op == GOTO
4081 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4082 && labelRange <= 10)
4084 emitcode (";", "tail decrement optimized");
4085 tlbl = IC_LABEL (ic->next);
4090 tlbl = newiTempLabel (NULL);
4094 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4095 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4096 IS_AOP_PREG (IC_RESULT (ic)))
4097 emitcode ("cjne", "%s,#0xff,%05d$"
4098 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4102 emitcode ("mov", "a,#0xff");
4103 emitcode ("cjne", "a,%s,%05d$"
4104 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4107 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4110 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4111 IS_AOP_PREG (IC_RESULT (ic)))
4112 emitcode ("cjne", "%s,#0xff,%05d$"
4113 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4117 emitcode ("cjne", "a,%s,%05d$"
4118 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4121 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4125 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4126 IS_AOP_PREG (IC_RESULT (ic)))
4127 emitcode ("cjne", "%s,#0xff,%05d$"
4128 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4132 emitcode ("cjne", "a,%s,%05d$"
4133 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4136 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4140 emitcode ("", "%05d$:", tlbl->key + 100);
4145 /* if the sizes are greater than 1 then we cannot */
4146 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4147 AOP_SIZE (IC_LEFT (ic)) > 1)
4150 /* we can if the aops of the left & result match or
4151 if they are in registers and the registers are the
4153 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4157 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4165 /*-----------------------------------------------------------------*/
4166 /* addSign - complete with sign */
4167 /*-----------------------------------------------------------------*/
4169 addSign (operand * result, int offset, int sign)
4171 int size = (getDataSize (result) - offset);
4176 emitcode ("rlc", "a");
4177 emitcode ("subb", "a,acc");
4179 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4183 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4187 /*-----------------------------------------------------------------*/
4188 /* genMinusBits - generates code for subtraction of two bits */
4189 /*-----------------------------------------------------------------*/
4191 genMinusBits (iCode * ic)
4193 symbol *lbl = newiTempLabel (NULL);
4195 D(emitcode ("; genMinusBits",""));
4197 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4199 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4200 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4201 emitcode ("cpl", "c");
4202 emitcode ("", "%05d$:", (lbl->key + 100));
4203 outBitC (IC_RESULT (ic));
4207 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4208 emitcode ("subb", "a,acc");
4209 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4210 emitcode ("inc", "a");
4211 emitcode ("", "%05d$:", (lbl->key + 100));
4212 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4213 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4217 /*-----------------------------------------------------------------*/
4218 /* genMinus - generates code for subtraction */
4219 /*-----------------------------------------------------------------*/
4221 genMinus (iCode * ic)
4223 int size, offset = 0;
4225 D(emitcode ("; genMinus",""));
4227 aopOp (IC_LEFT (ic), ic, FALSE);
4228 aopOp (IC_RIGHT (ic), ic, FALSE);
4229 aopOp (IC_RESULT (ic), ic, TRUE);
4231 /* special cases :- */
4232 /* if both left & right are in bit space */
4233 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4234 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4240 /* if I can do an decrement instead
4241 of subtract then GOOD for ME */
4242 if (genMinusDec (ic) == TRUE)
4245 size = getDataSize (IC_RESULT (ic));
4247 /* if literal, add a,#-lit, else normal subb */
4248 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4250 unsigned long lit = 0L;
4251 bool useCarry = FALSE;
4253 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4258 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4259 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4260 if (!offset && !size && lit== (unsigned long) -1) {
4261 emitcode ("dec", "a");
4262 } else if (!useCarry) {
4263 /* first add without previous c */
4264 emitcode ("add", "a,#0x%02x",
4265 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4268 emitcode ("addc", "a,#0x%02x",
4269 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4271 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4273 /* no need to add zeroes */
4280 operand *leftOp, *rightOp;
4282 leftOp = IC_LEFT(ic);
4283 rightOp = IC_RIGHT(ic);
4287 if (aopGetUsesAcc(rightOp, offset)) {
4288 if (aopGetUsesAcc(leftOp, offset)) {
4291 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4293 emitcode ("mov", "b,a");
4296 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4297 emitcode ("subb", "a,b");
4300 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4301 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4303 emitcode( "setb", "c");
4305 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4306 emitcode("cpl", "a");
4309 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4312 emitcode ("subb", "a,%s",
4313 aopGet(rightOp, offset, FALSE, TRUE));
4316 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4321 adjustArithmeticResult (ic);
4324 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4330 /*-----------------------------------------------------------------*/
4331 /* genMultbits :- multiplication of bits */
4332 /*-----------------------------------------------------------------*/
4334 genMultbits (operand * left,
4338 D(emitcode ("; genMultbits",""));
4340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4341 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4345 /*-----------------------------------------------------------------*/
4346 /* genMultOneByte : 8*8=8/16 bit multiplication */
4347 /*-----------------------------------------------------------------*/
4349 genMultOneByte (operand * left,
4354 int size = AOP_SIZE (result);
4355 bool runtimeSign, compiletimeSign;
4356 bool lUnsigned, rUnsigned, pushedB;
4358 D(emitcode ("; genMultOneByte",""));
4360 if (size < 1 || size > 2)
4362 /* this should never happen */
4363 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4364 AOP_SIZE(result), __FILE__, lineno);
4368 /* (if two literals: the value is computed before) */
4369 /* if one literal, literal on the right */
4370 if (AOP_TYPE (left) == AOP_LIT)
4375 /* emitcode (";", "swapped left and right"); */
4377 /* if no literal, unsigned on the right: shorter code */
4378 if ( AOP_TYPE (right) != AOP_LIT
4379 && SPEC_USIGN (getSpec (operandType (left))))
4386 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4387 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4391 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4392 no need to take care about the signedness! */
4393 || (lUnsigned && rUnsigned))
4395 /* just an unsigned 8 * 8 = 8 multiply
4397 /* emitcode (";","unsigned"); */
4398 /* TODO: check for accumulator clash between left & right aops? */
4400 if (AOP_TYPE (right) == AOP_LIT)
4402 /* moving to accumulator first helps peepholes */
4403 MOVA (aopGet (left, 0, FALSE, FALSE));
4404 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4408 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4409 MOVA (aopGet (left, 0, FALSE, FALSE));
4412 emitcode ("mul", "ab");
4413 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4415 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4421 /* we have to do a signed multiply */
4422 /* emitcode (";", "signed"); */
4424 /* now sign adjust for both left & right */
4426 /* let's see what's needed: */
4427 /* apply negative sign during runtime */
4428 runtimeSign = FALSE;
4429 /* negative sign from literals */
4430 compiletimeSign = FALSE;
4434 if (AOP_TYPE(left) == AOP_LIT)
4436 /* signed literal */
4437 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4439 compiletimeSign = TRUE;
4442 /* signed but not literal */
4448 if (AOP_TYPE(right) == AOP_LIT)
4450 /* signed literal */
4451 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4453 compiletimeSign ^= TRUE;
4456 /* signed but not literal */
4460 /* initialize F0, which stores the runtime sign */
4463 if (compiletimeSign)
4464 emitcode ("setb", "F0"); /* set sign flag */
4466 emitcode ("clr", "F0"); /* reset sign flag */
4469 /* save the signs of the operands */
4470 if (AOP_TYPE(right) == AOP_LIT)
4472 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4474 if (!rUnsigned && val < 0)
4475 emitcode ("mov", "b,#0x%02x", -val);
4477 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4479 else /* ! literal */
4481 if (rUnsigned) /* emitcode (";", "signed"); */
4483 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4486 MOVA (aopGet (right, 0, FALSE, FALSE));
4487 lbl = newiTempLabel (NULL);
4488 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4489 emitcode ("cpl", "F0"); /* complement sign flag */
4490 emitcode ("cpl", "a"); /* 2's complement */
4491 emitcode ("inc", "a");
4492 emitcode ("", "%05d$:", (lbl->key + 100));
4493 emitcode ("mov", "b,a");
4497 if (AOP_TYPE(left) == AOP_LIT)
4499 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4501 if (!lUnsigned && val < 0)
4502 emitcode ("mov", "a,#0x%02x", -val);
4504 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4506 else /* ! literal */
4508 MOVA (aopGet (left, 0, FALSE, FALSE));
4512 lbl = newiTempLabel (NULL);
4513 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4514 emitcode ("cpl", "F0"); /* complement sign flag */
4515 emitcode ("cpl", "a"); /* 2's complement */
4516 emitcode ("inc", "a");
4517 emitcode ("", "%05d$:", (lbl->key + 100));
4521 /* now the multiplication */
4522 emitcode ("mul", "ab");
4523 if (runtimeSign || compiletimeSign)
4525 lbl = newiTempLabel (NULL);
4527 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4528 emitcode ("cpl", "a"); /* lsb 2's complement */
4530 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4533 emitcode ("add", "a,#1"); /* this sets carry flag */
4534 emitcode ("xch", "a,b");
4535 emitcode ("cpl", "a"); /* msb 2's complement */
4536 emitcode ("addc", "a,#0");
4537 emitcode ("xch", "a,b");
4539 emitcode ("", "%05d$:", (lbl->key + 100));
4541 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4543 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4548 /*-----------------------------------------------------------------*/
4549 /* genMult - generates code for multiplication */
4550 /*-----------------------------------------------------------------*/
4552 genMult (iCode * ic)
4554 operand *left = IC_LEFT (ic);
4555 operand *right = IC_RIGHT (ic);
4556 operand *result = IC_RESULT (ic);
4558 D(emitcode ("; genMult",""));
4560 /* assign the amsops */
4561 aopOp (left, ic, FALSE);
4562 aopOp (right, ic, FALSE);
4563 aopOp (result, ic, TRUE);
4565 /* special cases first */
4567 if (AOP_TYPE (left) == AOP_CRY &&
4568 AOP_TYPE (right) == AOP_CRY)
4570 genMultbits (left, right, result);
4574 /* if both are of size == 1 */
4575 #if 0 // one of them can be a sloc shared with the result
4576 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4578 if (getSize(operandType(left)) == 1 &&
4579 getSize(operandType(right)) == 1)
4582 genMultOneByte (left, right, result);
4586 /* should have been converted to function call */
4587 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4588 getSize(OP_SYMBOL(right)->type));
4592 freeAsmop (result, NULL, ic, TRUE);
4593 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4594 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597 /*-----------------------------------------------------------------*/
4598 /* genDivbits :- division of bits */
4599 /*-----------------------------------------------------------------*/
4601 genDivbits (operand * left,
4608 D(emitcode ("; genDivbits",""));
4612 /* the result must be bit */
4613 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4614 l = aopGet (left, 0, FALSE, FALSE);
4618 emitcode ("div", "ab");
4619 emitcode ("rrc", "a");
4623 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4626 /*-----------------------------------------------------------------*/
4627 /* genDivOneByte : 8 bit division */
4628 /*-----------------------------------------------------------------*/
4630 genDivOneByte (operand * left,
4634 bool lUnsigned, rUnsigned, pushedB;
4635 bool runtimeSign, compiletimeSign;
4639 D(emitcode ("; genDivOneByte",""));
4641 /* Why is it necessary that genDivOneByte() can return an int result?
4644 volatile unsigned char uc;
4645 volatile signed char sc1, sc2;
4658 In all cases a one byte result would overflow, the following cast to int
4659 would return the wrong result.
4661 Two possible solution:
4662 a) cast operands to int, if ((unsigned) / (signed)) or
4663 ((signed) / (signed))
4664 b) return an 16 bit signed int; this is what we're doing here!
4667 size = AOP_SIZE (result) - 1;
4669 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4670 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4674 /* signed or unsigned */
4675 if (lUnsigned && rUnsigned)
4677 /* unsigned is easy */
4678 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4679 MOVA (aopGet (left, 0, FALSE, FALSE));
4680 emitcode ("div", "ab");
4681 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4683 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4689 /* signed is a little bit more difficult */
4691 /* now sign adjust for both left & right */
4693 /* let's see what's needed: */
4694 /* apply negative sign during runtime */
4695 runtimeSign = FALSE;
4696 /* negative sign from literals */
4697 compiletimeSign = FALSE;
4701 if (AOP_TYPE(left) == AOP_LIT)
4703 /* signed literal */
4704 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4706 compiletimeSign = TRUE;
4709 /* signed but not literal */
4715 if (AOP_TYPE(right) == AOP_LIT)
4717 /* signed literal */
4718 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4720 compiletimeSign ^= TRUE;
4723 /* signed but not literal */
4727 /* initialize F0, which stores the runtime sign */
4730 if (compiletimeSign)
4731 emitcode ("setb", "F0"); /* set sign flag */
4733 emitcode ("clr", "F0"); /* reset sign flag */
4736 /* save the signs of the operands */
4737 if (AOP_TYPE(right) == AOP_LIT)
4739 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4741 if (!rUnsigned && val < 0)
4742 emitcode ("mov", "b,#0x%02x", -val);
4744 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4746 else /* ! literal */
4749 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4752 MOVA (aopGet (right, 0, FALSE, FALSE));
4753 lbl = newiTempLabel (NULL);
4754 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4755 emitcode ("cpl", "F0"); /* complement sign flag */
4756 emitcode ("cpl", "a"); /* 2's complement */
4757 emitcode ("inc", "a");
4758 emitcode ("", "%05d$:", (lbl->key + 100));
4759 emitcode ("mov", "b,a");
4763 if (AOP_TYPE(left) == AOP_LIT)
4765 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4767 if (!lUnsigned && val < 0)
4768 emitcode ("mov", "a,#0x%02x", -val);
4770 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4772 else /* ! literal */
4774 MOVA (aopGet (left, 0, FALSE, FALSE));
4778 lbl = newiTempLabel (NULL);
4779 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4780 emitcode ("cpl", "F0"); /* complement sign flag */
4781 emitcode ("cpl", "a"); /* 2's complement */
4782 emitcode ("inc", "a");
4783 emitcode ("", "%05d$:", (lbl->key + 100));
4787 /* now the division */
4788 emitcode ("div", "ab");
4790 if (runtimeSign || compiletimeSign)
4792 lbl = newiTempLabel (NULL);
4794 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4795 emitcode ("cpl", "a"); /* lsb 2's complement */
4796 emitcode ("inc", "a");
4797 emitcode ("", "%05d$:", (lbl->key + 100));
4799 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4802 /* msb is 0x00 or 0xff depending on the sign */
4805 emitcode ("mov", "c,F0");
4806 emitcode ("subb", "a,acc");
4808 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4810 else /* compiletimeSign */
4812 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4817 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4819 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4825 /*-----------------------------------------------------------------*/
4826 /* genDiv - generates code for division */
4827 /*-----------------------------------------------------------------*/
4831 operand *left = IC_LEFT (ic);
4832 operand *right = IC_RIGHT (ic);
4833 operand *result = IC_RESULT (ic);
4835 D(emitcode ("; genDiv",""));
4837 /* assign the amsops */
4838 aopOp (left, ic, FALSE);
4839 aopOp (right, ic, FALSE);
4840 aopOp (result, ic, TRUE);
4842 /* special cases first */
4844 if (AOP_TYPE (left) == AOP_CRY &&
4845 AOP_TYPE (right) == AOP_CRY)
4847 genDivbits (left, right, result);
4851 /* if both are of size == 1 */
4852 if (AOP_SIZE (left) == 1 &&
4853 AOP_SIZE (right) == 1)
4855 genDivOneByte (left, right, result);
4859 /* should have been converted to function call */
4862 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864 freeAsmop (result, NULL, ic, TRUE);
4867 /*-----------------------------------------------------------------*/
4868 /* genModbits :- modulus of bits */
4869 /*-----------------------------------------------------------------*/
4871 genModbits (operand * left,
4878 D(emitcode ("; genModbits",""));
4882 /* the result must be bit */
4883 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4884 l = aopGet (left, 0, FALSE, FALSE);
4888 emitcode ("div", "ab");
4889 emitcode ("mov", "a,b");
4890 emitcode ("rrc", "a");
4894 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4897 /*-----------------------------------------------------------------*/
4898 /* genModOneByte : 8 bit modulus */
4899 /*-----------------------------------------------------------------*/
4901 genModOneByte (operand * left,
4905 bool lUnsigned, rUnsigned, pushedB;
4906 bool runtimeSign, compiletimeSign;
4910 D(emitcode ("; genModOneByte",""));
4912 size = AOP_SIZE (result) - 1;
4914 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4915 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4917 /* if right is a literal, check it for 2^n */
4918 if (AOP_TYPE(right) == AOP_LIT)
4920 unsigned char val = abs((int) operandLitValue(right));
4921 symbol *lbl2 = NULL;
4925 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4934 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4935 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4936 /* because iCode should have been changed to genAnd */
4937 /* see file "SDCCopt.c", function "convertToFcall()" */
4939 MOVA (aopGet (left, 0, FALSE, FALSE));
4940 emitcode ("mov", "c,acc.7");
4941 emitcode ("anl", "a,#0x%02x", val - 1);
4942 lbl = newiTempLabel (NULL);
4943 emitcode ("jz", "%05d$", (lbl->key + 100));
4944 emitcode ("jnc", "%05d$", (lbl->key + 100));
4945 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4951 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4953 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
4954 lbl2 = newiTempLabel (NULL);
4955 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4957 emitcode ("", "%05d$:", (lbl->key + 100));
4958 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4960 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4963 emitcode ("", "%05d$:", (lbl2->key + 100));
4974 /* signed or unsigned */
4975 if (lUnsigned && rUnsigned)
4977 /* unsigned is easy */
4978 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4979 MOVA (aopGet (left, 0, FALSE, FALSE));
4980 emitcode ("div", "ab");
4981 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4983 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4989 /* signed is a little bit more difficult */
4991 /* now sign adjust for both left & right */
4993 /* modulus: sign of the right operand has no influence on the result! */
4994 if (AOP_TYPE(right) == AOP_LIT)
4996 signed char val = (char) operandLitValue(right);
4998 if (!rUnsigned && val < 0)
4999 emitcode ("mov", "b,#0x%02x", -val);
5001 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5003 else /* not literal */
5006 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5009 MOVA (aopGet (right, 0, FALSE, FALSE));
5010 lbl = newiTempLabel (NULL);
5011 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5012 emitcode ("cpl", "a"); /* 2's complement */
5013 emitcode ("inc", "a");
5014 emitcode ("", "%05d$:", (lbl->key + 100));
5015 emitcode ("mov", "b,a");
5019 /* let's see what's needed: */
5020 /* apply negative sign during runtime */
5021 runtimeSign = FALSE;
5022 /* negative sign from literals */
5023 compiletimeSign = FALSE;
5025 /* sign adjust left side */
5026 if (AOP_TYPE(left) == AOP_LIT)
5028 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5030 if (!lUnsigned && val < 0)
5032 compiletimeSign = TRUE; /* set sign flag */
5033 emitcode ("mov", "a,#0x%02x", -val);
5036 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5038 else /* ! literal */
5040 MOVA (aopGet (left, 0, FALSE, FALSE));
5045 emitcode ("clr", "F0"); /* clear sign flag */
5047 lbl = newiTempLabel (NULL);
5048 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5049 emitcode ("setb", "F0"); /* set sign flag */
5050 emitcode ("cpl", "a"); /* 2's complement */
5051 emitcode ("inc", "a");
5052 emitcode ("", "%05d$:", (lbl->key + 100));
5056 /* now the modulus */
5057 emitcode ("div", "ab");
5059 if (runtimeSign || compiletimeSign)
5061 emitcode ("mov", "a,b");
5062 lbl = newiTempLabel (NULL);
5064 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5065 emitcode ("cpl", "a"); /* 2's complement */
5066 emitcode ("inc", "a");
5067 emitcode ("", "%05d$:", (lbl->key + 100));
5069 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5072 /* msb is 0x00 or 0xff depending on the sign */
5075 emitcode ("mov", "c,F0");
5076 emitcode ("subb", "a,acc");
5078 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5080 else /* compiletimeSign */
5082 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5087 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5089 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5095 /*-----------------------------------------------------------------*/
5096 /* genMod - generates code for division */
5097 /*-----------------------------------------------------------------*/
5101 operand *left = IC_LEFT (ic);
5102 operand *right = IC_RIGHT (ic);
5103 operand *result = IC_RESULT (ic);
5105 D(emitcode ("; genMod",""));
5107 /* assign the asmops */
5108 aopOp (left, ic, FALSE);
5109 aopOp (right, ic, FALSE);
5110 aopOp (result, ic, TRUE);
5112 /* special cases first */
5114 if (AOP_TYPE (left) == AOP_CRY &&
5115 AOP_TYPE (right) == AOP_CRY)
5117 genModbits (left, right, result);
5121 /* if both are of size == 1 */
5122 if (AOP_SIZE (left) == 1 &&
5123 AOP_SIZE (right) == 1)
5125 genModOneByte (left, right, result);
5129 /* should have been converted to function call */
5133 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (result, NULL, ic, TRUE);
5138 /*-----------------------------------------------------------------*/
5139 /* genIfxJump :- will create a jump depending on the ifx */
5140 /*-----------------------------------------------------------------*/
5142 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5145 symbol *tlbl = newiTempLabel (NULL);
5148 D(emitcode ("; genIfxJump",""));
5150 /* if true label then we jump if condition
5154 jlbl = IC_TRUE (ic);
5155 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5156 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5160 /* false label is present */
5161 jlbl = IC_FALSE (ic);
5162 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5163 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5165 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5166 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5168 emitcode (inst, "%05d$", tlbl->key + 100);
5169 freeForBranchAsmop (result);
5170 freeForBranchAsmop (right);
5171 freeForBranchAsmop (left);
5172 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5173 emitcode ("", "%05d$:", tlbl->key + 100);
5175 /* mark the icode as generated */
5179 /*-----------------------------------------------------------------*/
5180 /* genCmp :- greater or less than comparison */
5181 /*-----------------------------------------------------------------*/
5183 genCmp (operand * left, operand * right,
5184 operand * result, iCode * ifx, int sign, iCode *ic)
5186 int size, offset = 0;
5187 unsigned long lit = 0L;
5190 D(emitcode ("; genCmp",""));
5192 /* if left & right are bit variables */
5193 if (AOP_TYPE (left) == AOP_CRY &&
5194 AOP_TYPE (right) == AOP_CRY)
5196 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5197 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5201 /* subtract right from left if at the
5202 end the carry flag is set then we know that
5203 left is greater than right */
5204 size = max (AOP_SIZE (left), AOP_SIZE (right));
5206 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5207 if ((size == 1) && !sign &&
5208 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5210 symbol *lbl = newiTempLabel (NULL);
5211 emitcode ("cjne", "%s,%s,%05d$",
5212 aopGet (left, offset, FALSE, FALSE),
5213 aopGet (right, offset, FALSE, FALSE),
5215 emitcode ("", "%05d$:", lbl->key + 100);
5219 if (AOP_TYPE (right) == AOP_LIT)
5221 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5222 /* optimize if(x < 0) or if(x >= 0) */
5231 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5232 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5234 genIfxJump (ifx, "acc.7", left, right, result);
5235 freeAsmop (right, NULL, ic, TRUE);
5236 freeAsmop (left, NULL, ic, TRUE);
5241 emitcode ("rlc", "a");
5249 bool pushedB = FALSE;
5250 rightInB = aopGetUsesAcc(right, offset);
5254 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5256 MOVA (aopGet (left, offset, FALSE, FALSE));
5257 if (sign && size == 0)
5259 emitcode ("xrl", "a,#0x80");
5260 if (AOP_TYPE (right) == AOP_LIT)
5262 unsigned long lit = (unsigned long)
5263 floatFromVal (AOP (right)->aopu.aop_lit);
5264 emitcode ("subb", "a,#0x%02x",
5265 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5273 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5275 emitcode ("xrl", "b,#0x80");
5276 emitcode ("subb", "a,b");
5282 emitcode ("subb", "a,b");
5284 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5294 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5295 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5296 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5302 /* if the result is used in the next
5303 ifx conditional branch then generate
5304 code a little differently */
5306 genIfxJump (ifx, "c", NULL, NULL, result);
5309 /* leave the result in acc */
5313 /*-----------------------------------------------------------------*/
5314 /* genCmpGt :- greater than comparison */
5315 /*-----------------------------------------------------------------*/
5317 genCmpGt (iCode * ic, iCode * ifx)
5319 operand *left, *right, *result;
5320 sym_link *letype, *retype;
5323 D(emitcode ("; genCmpGt",""));
5325 left = IC_LEFT (ic);
5326 right = IC_RIGHT (ic);
5327 result = IC_RESULT (ic);
5329 letype = getSpec (operandType (left));
5330 retype = getSpec (operandType (right));
5331 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5332 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5333 /* assign the amsops */
5334 aopOp (left, ic, FALSE);
5335 aopOp (right, ic, FALSE);
5336 aopOp (result, ic, TRUE);
5338 genCmp (right, left, result, ifx, sign, ic);
5340 freeAsmop (result, NULL, ic, TRUE);
5343 /*-----------------------------------------------------------------*/
5344 /* genCmpLt - less than comparisons */
5345 /*-----------------------------------------------------------------*/
5347 genCmpLt (iCode * ic, iCode * ifx)
5349 operand *left, *right, *result;
5350 sym_link *letype, *retype;
5353 D(emitcode ("; genCmpLt",""));
5355 left = IC_LEFT (ic);
5356 right = IC_RIGHT (ic);
5357 result = IC_RESULT (ic);
5359 letype = getSpec (operandType (left));
5360 retype = getSpec (operandType (right));
5361 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5362 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5363 /* assign the amsops */
5364 aopOp (left, ic, FALSE);
5365 aopOp (right, ic, FALSE);
5366 aopOp (result, ic, TRUE);
5368 genCmp (left, right, result, ifx, sign,ic);
5370 freeAsmop (result, NULL, ic, TRUE);
5373 /*-----------------------------------------------------------------*/
5374 /* gencjneshort - compare and jump if not equal */
5375 /*-----------------------------------------------------------------*/
5377 gencjneshort (operand * left, operand * right, symbol * lbl)
5379 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5381 unsigned long lit = 0L;
5383 /* if the left side is a literal or
5384 if the right is in a pointer register and left
5386 if ((AOP_TYPE (left) == AOP_LIT) ||
5387 (AOP_TYPE (left) == AOP_IMMD) ||
5388 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5395 if (AOP_TYPE (right) == AOP_LIT)
5396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5398 /* if the right side is a literal then anything goes */
5399 if (AOP_TYPE (right) == AOP_LIT &&
5400 AOP_TYPE (left) != AOP_DIR &&
5401 AOP_TYPE (left) != AOP_IMMD)
5405 emitcode ("cjne", "%s,%s,%05d$",
5406 aopGet (left, offset, FALSE, FALSE),
5407 aopGet (right, offset, FALSE, FALSE),
5413 /* if the right side is in a register or in direct space or
5414 if the left is a pointer register & right is not */
5415 else if (AOP_TYPE (right) == AOP_REG ||
5416 AOP_TYPE (right) == AOP_DIR ||
5417 AOP_TYPE (right) == AOP_LIT ||
5418 AOP_TYPE (right) == AOP_IMMD ||
5419 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5420 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5424 MOVA (aopGet (left, offset, FALSE, FALSE));
5425 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5426 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5427 emitcode ("jnz", "%05d$", lbl->key + 100);
5429 emitcode ("cjne", "a,%s,%05d$",
5430 aopGet (right, offset, FALSE, TRUE),
5437 /* right is a pointer reg need both a & b */
5441 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5442 wassertl(!BINUSE, "B was in use");
5443 l = aopGet (left, offset, FALSE, FALSE);
5444 if (strcmp (l, "b"))
5445 emitcode ("mov", "b,%s", l);
5446 MOVA (aopGet (right, offset, FALSE, FALSE));
5447 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5453 /*-----------------------------------------------------------------*/
5454 /* gencjne - compare and jump if not equal */
5455 /*-----------------------------------------------------------------*/
5457 gencjne (operand * left, operand * right, symbol * lbl)
5459 symbol *tlbl = newiTempLabel (NULL);
5461 gencjneshort (left, right, lbl);
5463 emitcode ("mov", "a,%s", one);
5464 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5465 emitcode ("", "%05d$:", lbl->key + 100);
5466 emitcode ("clr", "a");
5467 emitcode ("", "%05d$:", tlbl->key + 100);
5470 /*-----------------------------------------------------------------*/
5471 /* genCmpEq - generates code for equal to */
5472 /*-----------------------------------------------------------------*/
5474 genCmpEq (iCode * ic, iCode * ifx)
5476 operand *left, *right, *result;
5478 D(emitcode ("; genCmpEq",""));
5480 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5481 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5482 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5484 /* if literal, literal on the right or
5485 if the right is in a pointer register and left
5487 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5488 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5490 operand *t = IC_RIGHT (ic);
5491 IC_RIGHT (ic) = IC_LEFT (ic);
5495 if (ifx && !AOP_SIZE (result))
5498 /* if they are both bit variables */
5499 if (AOP_TYPE (left) == AOP_CRY &&
5500 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5502 if (AOP_TYPE (right) == AOP_LIT)
5504 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5508 emitcode ("cpl", "c");
5512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5516 emitcode ("clr", "c");
5518 /* AOP_TYPE(right) == AOP_CRY */
5522 symbol *lbl = newiTempLabel (NULL);
5523 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5524 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5525 emitcode ("cpl", "c");
5526 emitcode ("", "%05d$:", (lbl->key + 100));
5528 /* if true label then we jump if condition
5530 tlbl = newiTempLabel (NULL);
5533 emitcode ("jnc", "%05d$", tlbl->key + 100);
5534 freeForBranchAsmop (result);
5535 freeForBranchAsmop (right);
5536 freeForBranchAsmop (left);
5537 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5541 emitcode ("jc", "%05d$", tlbl->key + 100);
5542 freeForBranchAsmop (result);
5543 freeForBranchAsmop (right);
5544 freeForBranchAsmop (left);
5545 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5547 emitcode ("", "%05d$:", tlbl->key + 100);
5551 tlbl = newiTempLabel (NULL);
5552 gencjneshort (left, right, tlbl);
5555 freeForBranchAsmop (result);
5556 freeForBranchAsmop (right);
5557 freeForBranchAsmop (left);
5558 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5559 emitcode ("", "%05d$:", tlbl->key + 100);
5563 symbol *lbl = newiTempLabel (NULL);
5564 emitcode ("sjmp", "%05d$", lbl->key + 100);
5565 emitcode ("", "%05d$:", tlbl->key + 100);
5566 freeForBranchAsmop (result);
5567 freeForBranchAsmop (right);
5568 freeForBranchAsmop (left);
5569 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5570 emitcode ("", "%05d$:", lbl->key + 100);
5573 /* mark the icode as generated */
5578 /* if they are both bit variables */
5579 if (AOP_TYPE (left) == AOP_CRY &&
5580 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5582 if (AOP_TYPE (right) == AOP_LIT)
5584 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5588 emitcode ("cpl", "c");
5592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5596 emitcode ("clr", "c");
5598 /* AOP_TYPE(right) == AOP_CRY */
5602 symbol *lbl = newiTempLabel (NULL);
5603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5604 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5605 emitcode ("cpl", "c");
5606 emitcode ("", "%05d$:", (lbl->key + 100));
5609 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5616 genIfxJump (ifx, "c", left, right, result);
5619 /* if the result is used in an arithmetic operation
5620 then put the result in place */
5625 gencjne (left, right, newiTempLabel (NULL));
5626 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5628 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5633 genIfxJump (ifx, "a", left, right, result);
5636 /* if the result is used in an arithmetic operation
5637 then put the result in place */
5638 if (AOP_TYPE (result) != AOP_CRY)
5640 /* leave the result in acc */
5644 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5645 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5646 freeAsmop (result, NULL, ic, TRUE);
5649 /*-----------------------------------------------------------------*/
5650 /* ifxForOp - returns the icode containing the ifx for operand */
5651 /*-----------------------------------------------------------------*/
5653 ifxForOp (operand * op, iCode * ic)
5655 /* if true symbol then needs to be assigned */
5656 if (IS_TRUE_SYMOP (op))
5659 /* if this has register type condition and
5660 the next instruction is ifx with the same operand
5661 and live to of the operand is upto the ifx only then */
5663 ic->next->op == IFX &&
5664 IC_COND (ic->next)->key == op->key &&
5665 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5671 /*-----------------------------------------------------------------*/
5672 /* hasInc - operand is incremented before any other use */
5673 /*-----------------------------------------------------------------*/
5675 hasInc (operand *op, iCode *ic,int osize)
5677 sym_link *type = operandType(op);
5678 sym_link *retype = getSpec (type);
5679 iCode *lic = ic->next;
5682 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5683 if (!IS_SYMOP(op)) return NULL;
5685 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5686 if (IS_AGGREGATE(type->next)) return NULL;
5687 if (osize != (isize = getSize(type->next))) return NULL;
5690 /* if operand of the form op = op + <sizeof *op> */
5691 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5692 isOperandEqual(IC_RESULT(lic),op) &&
5693 isOperandLiteral(IC_RIGHT(lic)) &&
5694 operandLitValue(IC_RIGHT(lic)) == isize) {
5697 /* if the operand used or deffed */
5698 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5701 /* if GOTO or IFX */
5702 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5708 /*-----------------------------------------------------------------*/
5709 /* genAndOp - for && operation */
5710 /*-----------------------------------------------------------------*/
5712 genAndOp (iCode * ic)
5714 operand *left, *right, *result;
5717 D(emitcode ("; genAndOp",""));
5719 /* note here that && operations that are in an
5720 if statement are taken away by backPatchLabels
5721 only those used in arthmetic operations remain */
5722 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5723 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5724 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5726 /* if both are bit variables */
5727 if (AOP_TYPE (left) == AOP_CRY &&
5728 AOP_TYPE (right) == AOP_CRY)
5730 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5731 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5736 tlbl = newiTempLabel (NULL);
5738 emitcode ("jz", "%05d$", tlbl->key + 100);
5740 emitcode ("", "%05d$:", tlbl->key + 100);
5744 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5745 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5746 freeAsmop (result, NULL, ic, TRUE);
5750 /*-----------------------------------------------------------------*/
5751 /* genOrOp - for || operation */
5752 /*-----------------------------------------------------------------*/
5754 genOrOp (iCode * ic)
5756 operand *left, *right, *result;
5759 D(emitcode ("; genOrOp",""));
5761 /* note here that || operations that are in an
5762 if statement are taken away by backPatchLabels
5763 only those used in arthmetic operations remain */
5764 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5765 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5766 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5768 /* if both are bit variables */
5769 if (AOP_TYPE (left) == AOP_CRY &&
5770 AOP_TYPE (right) == AOP_CRY)
5772 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5773 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5778 tlbl = newiTempLabel (NULL);
5780 emitcode ("jnz", "%05d$", tlbl->key + 100);
5782 emitcode ("", "%05d$:", tlbl->key + 100);
5786 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5787 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5788 freeAsmop (result, NULL, ic, TRUE);
5791 /*-----------------------------------------------------------------*/
5792 /* isLiteralBit - test if lit == 2^n */
5793 /*-----------------------------------------------------------------*/
5795 isLiteralBit (unsigned long lit)
5797 unsigned long pw[32] =
5798 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5799 0x100L, 0x200L, 0x400L, 0x800L,
5800 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5801 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5802 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5803 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5804 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5807 for (idx = 0; idx < 32; idx++)
5813 /*-----------------------------------------------------------------*/
5814 /* continueIfTrue - */
5815 /*-----------------------------------------------------------------*/
5817 continueIfTrue (iCode * ic)
5820 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5824 /*-----------------------------------------------------------------*/
5826 /*-----------------------------------------------------------------*/
5828 jumpIfTrue (iCode * ic)
5831 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5835 /*-----------------------------------------------------------------*/
5836 /* jmpTrueOrFalse - */
5837 /*-----------------------------------------------------------------*/
5839 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5841 // ugly but optimized by peephole
5844 symbol *nlbl = newiTempLabel (NULL);
5845 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5846 emitcode ("", "%05d$:", tlbl->key + 100);
5847 freeForBranchAsmop (result);
5848 freeForBranchAsmop (right);
5849 freeForBranchAsmop (left);
5850 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5851 emitcode ("", "%05d$:", nlbl->key + 100);
5855 freeForBranchAsmop (result);
5856 freeForBranchAsmop (right);
5857 freeForBranchAsmop (left);
5858 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5859 emitcode ("", "%05d$:", tlbl->key + 100);
5864 /*-----------------------------------------------------------------*/
5865 /* genAnd - code for and */
5866 /*-----------------------------------------------------------------*/
5868 genAnd (iCode * ic, iCode * ifx)
5870 operand *left, *right, *result;
5871 int size, offset = 0;
5872 unsigned long lit = 0L;
5876 D(emitcode ("; genAnd",""));
5878 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5879 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5880 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5883 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5885 AOP_TYPE (left), AOP_TYPE (right));
5886 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5888 AOP_SIZE (left), AOP_SIZE (right));
5891 /* if left is a literal & right is not then exchange them */
5892 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5893 AOP_NEEDSACC (left))
5895 operand *tmp = right;
5900 /* if result = right then exchange left and right */
5901 if (sameRegs (AOP (result), AOP (right)))
5903 operand *tmp = right;
5908 /* if right is bit then exchange them */
5909 if (AOP_TYPE (right) == AOP_CRY &&
5910 AOP_TYPE (left) != AOP_CRY)
5912 operand *tmp = right;
5916 if (AOP_TYPE (right) == AOP_LIT)
5917 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5919 size = AOP_SIZE (result);
5922 // result = bit & yy;
5923 if (AOP_TYPE (left) == AOP_CRY)
5925 // c = bit & literal;
5926 if (AOP_TYPE (right) == AOP_LIT)
5930 if (size && sameRegs (AOP (result), AOP (left)))
5933 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5938 if (size && (AOP_TYPE (result) == AOP_CRY))
5940 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5943 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5948 emitcode ("clr", "c");
5953 if (AOP_TYPE (right) == AOP_CRY)
5956 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5957 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5962 MOVA (aopGet (right, 0, FALSE, FALSE));
5964 emitcode ("rrc", "a");
5965 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5973 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5974 genIfxJump (ifx, "c", left, right, result);
5978 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5979 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5980 if ((AOP_TYPE (right) == AOP_LIT) &&
5981 (AOP_TYPE (result) == AOP_CRY) &&
5982 (AOP_TYPE (left) != AOP_CRY))
5984 int posbit = isLiteralBit (lit);
5989 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
5993 switch (posbit & 0x07)
5995 case 0: emitcode ("rrc", "a");
5997 case 7: emitcode ("rlc", "a");
5999 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6008 SNPRINTF (buffer, sizeof(buffer),
6009 "acc.%d", posbit & 0x07);
6010 genIfxJump (ifx, buffer, left, right, result);
6013 {// what is this case? just found it in ds390/gen.c
6014 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6021 symbol *tlbl = newiTempLabel (NULL);
6022 int sizel = AOP_SIZE (left);
6024 emitcode ("setb", "c");
6027 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6029 MOVA (aopGet (left, offset, FALSE, FALSE));
6031 if ((posbit = isLiteralBit (bytelit)) != 0)
6032 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6035 if (bytelit != 0x0FFL)
6036 emitcode ("anl", "a,%s",
6037 aopGet (right, offset, FALSE, TRUE));
6038 emitcode ("jnz", "%05d$", tlbl->key + 100);
6043 // bit = left & literal
6046 emitcode ("clr", "c");
6047 emitcode ("", "%05d$:", tlbl->key + 100);
6049 // if(left & literal)
6053 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6055 emitcode ("", "%05d$:", tlbl->key + 100);
6063 /* if left is same as result */
6064 if (sameRegs (AOP (result), AOP (left)))
6066 for (; size--; offset++)
6068 if (AOP_TYPE (right) == AOP_LIT)
6070 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6071 if (bytelit == 0x0FF)
6073 /* dummy read of volatile operand */
6074 if (isOperandVolatile (left, FALSE))
6075 MOVA (aopGet (left, offset, FALSE, FALSE));
6079 else if (bytelit == 0)
6081 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6083 else if (IS_AOP_PREG (result))
6085 MOVA (aopGet (left, offset, FALSE, TRUE));
6086 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6087 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6090 emitcode ("anl", "%s,%s",
6091 aopGet (left, offset, FALSE, TRUE),
6092 aopGet (right, offset, FALSE, FALSE));
6096 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6098 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6102 MOVA (aopGet (right, offset, FALSE, FALSE));
6103 if (IS_AOP_PREG (result))
6105 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6106 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6109 emitcode ("anl", "%s,a",
6110 aopGet (left, offset, FALSE, TRUE));
6117 // left & result in different registers
6118 if (AOP_TYPE (result) == AOP_CRY)
6121 // if(size), result in bit
6122 // if(!size && ifx), conditional oper: if(left & right)
6123 symbol *tlbl = newiTempLabel (NULL);
6124 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6126 emitcode ("setb", "c");
6129 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6130 && AOP_TYPE(left)==AOP_ACC)
6133 emitcode("mov", "a,b");
6134 emitcode ("anl", "a,%s",
6135 aopGet (right, offset, FALSE, FALSE));
6137 if (AOP_TYPE(left)==AOP_ACC)
6141 bool pushedB = pushB ();
6142 emitcode("mov", "b,a");
6143 MOVA (aopGet (right, offset, FALSE, FALSE));
6144 emitcode("anl", "a,b");
6149 MOVA (aopGet (right, offset, FALSE, FALSE));
6150 emitcode("anl", "a,b");
6153 MOVA (aopGet (right, offset, FALSE, FALSE));
6154 emitcode ("anl", "a,%s",
6155 aopGet (left, offset, FALSE, FALSE));
6158 emitcode ("jnz", "%05d$", tlbl->key + 100);
6164 emitcode ("", "%05d$:", tlbl->key + 100);
6168 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6170 emitcode ("", "%05d$:", tlbl->key + 100);
6174 for (; (size--); offset++)
6177 // result = left & right
6178 if (AOP_TYPE (right) == AOP_LIT)
6180 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6181 if (bytelit == 0x0FF)
6184 aopGet (left, offset, FALSE, FALSE),
6186 isOperandVolatile (result, FALSE));
6189 else if (bytelit == 0)
6191 /* dummy read of volatile operand */
6192 if (isOperandVolatile (left, FALSE))
6193 MOVA (aopGet (left, offset, FALSE, FALSE));
6194 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6197 else if (AOP_TYPE (left) == AOP_ACC)
6201 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6202 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6207 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6208 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6213 // faster than result <- left, anl result,right
6214 // and better if result is SFR
6215 if (AOP_TYPE (left) == AOP_ACC)
6218 emitcode("mov", "a,b");
6219 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6223 MOVA (aopGet (right, offset, FALSE, FALSE));
6224 emitcode ("anl", "a,%s",
6225 aopGet (left, offset, FALSE, FALSE));
6227 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6233 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6235 freeAsmop (result, NULL, ic, TRUE);
6238 /*-----------------------------------------------------------------*/
6239 /* genOr - code for or */
6240 /*-----------------------------------------------------------------*/
6242 genOr (iCode * ic, iCode * ifx)
6244 operand *left, *right, *result;
6245 int size, offset = 0;
6246 unsigned long lit = 0L;
6249 D(emitcode ("; genOr",""));
6251 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6252 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6253 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6256 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6258 AOP_TYPE (left), AOP_TYPE (right));
6259 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6261 AOP_SIZE (left), AOP_SIZE (right));
6264 /* if left is a literal & right is not then exchange them */
6265 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6266 AOP_NEEDSACC (left))
6268 operand *tmp = right;
6273 /* if result = right then exchange them */
6274 if (sameRegs (AOP (result), AOP (right)))
6276 operand *tmp = right;
6281 /* if right is bit then exchange them */
6282 if (AOP_TYPE (right) == AOP_CRY &&
6283 AOP_TYPE (left) != AOP_CRY)
6285 operand *tmp = right;
6289 if (AOP_TYPE (right) == AOP_LIT)
6290 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6292 size = AOP_SIZE (result);
6296 if (AOP_TYPE (left) == AOP_CRY)
6298 if (AOP_TYPE (right) == AOP_LIT)
6300 // c = bit | literal;
6303 // lit != 0 => result = 1
6304 if (AOP_TYPE (result) == AOP_CRY)
6307 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6309 continueIfTrue (ifx);
6312 emitcode ("setb", "c");
6316 // lit == 0 => result = left
6317 if (size && sameRegs (AOP (result), AOP (left)))
6319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6324 if (AOP_TYPE (right) == AOP_CRY)
6327 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6328 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6333 symbol *tlbl = newiTempLabel (NULL);
6334 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6335 emitcode ("setb", "c");
6336 emitcode ("jb", "%s,%05d$",
6337 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6339 emitcode ("jnz", "%05d$", tlbl->key + 100);
6340 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6342 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6348 emitcode ("", "%05d$:", tlbl->key + 100);
6357 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6358 genIfxJump (ifx, "c", left, right, result);
6362 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6363 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6364 if ((AOP_TYPE (right) == AOP_LIT) &&
6365 (AOP_TYPE (result) == AOP_CRY) &&
6366 (AOP_TYPE (left) != AOP_CRY))
6372 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6374 continueIfTrue (ifx);
6379 // lit = 0, result = boolean(left)
6381 emitcode ("setb", "c");
6385 symbol *tlbl = newiTempLabel (NULL);
6386 emitcode ("jnz", "%05d$", tlbl->key + 100);
6388 emitcode ("", "%05d$:", tlbl->key + 100);
6392 genIfxJump (ifx, "a", left, right, result);
6400 /* if left is same as result */
6401 if (sameRegs (AOP (result), AOP (left)))
6403 for (; size--; offset++)
6405 if (AOP_TYPE (right) == AOP_LIT)
6407 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6410 /* dummy read of volatile operand */
6411 if (isOperandVolatile (left, FALSE))
6412 MOVA (aopGet (left, offset, FALSE, FALSE));
6416 else if (bytelit == 0x0FF)
6418 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6420 else if (IS_AOP_PREG (left))
6422 MOVA (aopGet (left, offset, FALSE, TRUE));
6423 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6424 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6428 emitcode ("orl", "%s,%s",
6429 aopGet (left, offset, FALSE, TRUE),
6430 aopGet (right, offset, FALSE, FALSE));
6435 if (AOP_TYPE (left) == AOP_ACC)
6438 emitcode("mov", "a,b");
6439 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6443 MOVA (aopGet (right, offset, FALSE, FALSE));
6444 if (IS_AOP_PREG (left))
6446 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6447 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6451 emitcode ("orl", "%s,a",
6452 aopGet (left, offset, FALSE, TRUE));
6460 // left & result in different registers
6461 if (AOP_TYPE (result) == AOP_CRY)
6464 // if(size), result in bit
6465 // if(!size && ifx), conditional oper: if(left | right)
6466 symbol *tlbl = newiTempLabel (NULL);
6467 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6469 emitcode ("setb", "c");
6472 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6474 emitcode("mov", "a,b");
6475 emitcode ("orl", "a,%s",
6476 aopGet (right, offset, FALSE, FALSE));
6478 MOVA (aopGet (right, offset, FALSE, FALSE));
6479 emitcode ("orl", "a,%s",
6480 aopGet (left, offset, FALSE, FALSE));
6482 emitcode ("jnz", "%05d$", tlbl->key + 100);
6488 emitcode ("", "%05d$:", tlbl->key + 100);
6492 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6494 emitcode ("", "%05d$:", tlbl->key + 100);
6498 for (; (size--); offset++)
6501 // result = left | right
6502 if (AOP_TYPE (right) == AOP_LIT)
6504 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6508 aopGet (left, offset, FALSE, FALSE),
6510 isOperandVolatile (result, FALSE));
6513 else if (bytelit == 0x0FF)
6515 /* dummy read of volatile operand */
6516 if (isOperandVolatile (left, FALSE))
6517 MOVA (aopGet (left, offset, FALSE, FALSE));
6518 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6522 // faster than result <- left, anl result,right
6523 // and better if result is SFR
6524 if (AOP_TYPE (left) == AOP_ACC)
6527 emitcode("mov", "a,b");
6528 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6532 MOVA (aopGet (right, offset, FALSE, FALSE));
6533 emitcode ("orl", "a,%s",
6534 aopGet (left, offset, FALSE, FALSE));
6536 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6542 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6543 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6544 freeAsmop (result, NULL, ic, TRUE);
6547 /*-----------------------------------------------------------------*/
6548 /* genXor - code for xclusive or */
6549 /*-----------------------------------------------------------------*/
6551 genXor (iCode * ic, iCode * ifx)
6553 operand *left, *right, *result;
6554 int size, offset = 0;
6555 unsigned long lit = 0L;
6558 D(emitcode ("; genXor",""));
6560 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6561 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6562 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6565 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6567 AOP_TYPE (left), AOP_TYPE (right));
6568 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6570 AOP_SIZE (left), AOP_SIZE (right));
6573 /* if left is a literal & right is not ||
6574 if left needs acc & right does not */
6575 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6576 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6578 operand *tmp = right;
6583 /* if result = right then exchange them */
6584 if (sameRegs (AOP (result), AOP (right)))
6586 operand *tmp = right;
6591 /* if right is bit then exchange them */
6592 if (AOP_TYPE (right) == AOP_CRY &&
6593 AOP_TYPE (left) != AOP_CRY)
6595 operand *tmp = right;
6599 if (AOP_TYPE (right) == AOP_LIT)
6600 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6602 size = AOP_SIZE (result);
6606 if (AOP_TYPE (left) == AOP_CRY)
6608 if (AOP_TYPE (right) == AOP_LIT)
6610 // c = bit & literal;
6613 // lit>>1 != 0 => result = 1
6614 if (AOP_TYPE (result) == AOP_CRY)
6617 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6619 continueIfTrue (ifx);
6622 emitcode ("setb", "c");
6629 // lit == 0, result = left
6630 if (size && sameRegs (AOP (result), AOP (left)))
6632 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6636 // lit == 1, result = not(left)
6637 if (size && sameRegs (AOP (result), AOP (left)))
6639 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6644 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6645 emitcode ("cpl", "c");
6654 symbol *tlbl = newiTempLabel (NULL);
6655 if (AOP_TYPE (right) == AOP_CRY)
6658 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6662 int sizer = AOP_SIZE (right);
6664 // if val>>1 != 0, result = 1
6665 emitcode ("setb", "c");
6668 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6670 // test the msb of the lsb
6671 emitcode ("anl", "a,#0xfe");
6672 emitcode ("jnz", "%05d$", tlbl->key + 100);
6676 emitcode ("rrc", "a");
6678 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6679 emitcode ("cpl", "c");
6680 emitcode ("", "%05d$:", (tlbl->key + 100));
6687 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6688 genIfxJump (ifx, "c", left, right, result);
6692 /* if left is same as result */
6693 if (sameRegs (AOP (result), AOP (left)))
6695 for (; size--; offset++)
6697 if (AOP_TYPE (right) == AOP_LIT)
6699 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6702 /* dummy read of volatile operand */
6703 if (isOperandVolatile (left, FALSE))
6704 MOVA (aopGet (left, offset, FALSE, FALSE));
6708 else if (IS_AOP_PREG (left))
6710 MOVA (aopGet (left, offset, FALSE, TRUE));
6711 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6712 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6716 emitcode ("xrl", "%s,%s",
6717 aopGet (left, offset, FALSE, TRUE),
6718 aopGet (right, offset, FALSE, FALSE));
6723 if (AOP_TYPE (left) == AOP_ACC)
6726 emitcode("mov", "a,b");
6727 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6731 MOVA (aopGet (right, offset, FALSE, FALSE));
6732 if (IS_AOP_PREG (left))
6734 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6735 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6738 emitcode ("xrl", "%s,a",
6739 aopGet (left, offset, FALSE, TRUE));
6746 // left & result in different registers
6747 if (AOP_TYPE (result) == AOP_CRY)
6750 // if(size), result in bit
6751 // if(!size && ifx), conditional oper: if(left ^ right)
6752 symbol *tlbl = newiTempLabel (NULL);
6753 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6755 emitcode ("setb", "c");
6758 if ((AOP_TYPE (right) == AOP_LIT) &&
6759 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6761 MOVA (aopGet (left, offset, FALSE, FALSE));
6765 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6767 emitcode("mov", "a,b");
6768 emitcode ("xrl", "a,%s",
6769 aopGet (right, offset, FALSE, FALSE));
6771 MOVA (aopGet (right, offset, FALSE, FALSE));
6772 emitcode ("xrl", "a,%s",
6773 aopGet (left, offset, FALSE, FALSE));
6776 emitcode ("jnz", "%05d$", tlbl->key + 100);
6782 emitcode ("", "%05d$:", tlbl->key + 100);
6786 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6790 for (; (size--); offset++)
6793 // result = left & right
6794 if (AOP_TYPE (right) == AOP_LIT)
6796 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6800 aopGet (left, offset, FALSE, FALSE),
6802 isOperandVolatile (result, FALSE));
6806 // faster than result <- left, anl result,right
6807 // and better if result is SFR
6808 if (AOP_TYPE (left) == AOP_ACC)
6811 emitcode("mov", "a,b");
6812 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6816 MOVA (aopGet (right, offset, FALSE, FALSE));
6817 emitcode ("xrl", "a,%s",
6818 aopGet (left, offset, FALSE, TRUE));
6820 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (result, NULL, ic, TRUE);
6831 /*-----------------------------------------------------------------*/
6832 /* genInline - write the inline code out */
6833 /*-----------------------------------------------------------------*/
6835 genInline (iCode * ic)
6837 char *buffer, *bp, *bp1;
6839 D(emitcode ("; genInline",""));
6841 _G.inLine += (!options.asmpeep);
6843 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6844 strcpy (buffer, IC_INLINE (ic));
6846 /* emit each line as a code */
6857 /* Add \n for labels, not dirs such as c:\mydir */
6858 if ( (*bp == ':') && (isspace(bp[1])) )
6872 /* emitcode("",buffer); */
6873 _G.inLine -= (!options.asmpeep);
6876 /*-----------------------------------------------------------------*/
6877 /* genRRC - rotate right with carry */
6878 /*-----------------------------------------------------------------*/
6882 operand *left, *result;
6883 int size, offset = 0;
6886 D(emitcode ("; genRRC",""));
6888 /* rotate right with carry */
6889 left = IC_LEFT (ic);
6890 result = IC_RESULT (ic);
6891 aopOp (left, ic, FALSE);
6892 aopOp (result, ic, FALSE);
6894 /* move it to the result */
6895 size = AOP_SIZE (result);
6897 if (size == 1) { /* special case for 1 byte */
6898 l = aopGet (left, offset, FALSE, FALSE);
6900 emitcode ("rr", "a");
6903 /* no need to clear carry, bit7 will be written later */
6906 l = aopGet (left, offset, FALSE, FALSE);
6908 emitcode ("rrc", "a");
6909 if (AOP_SIZE (result) > 1)
6910 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
6912 /* now we need to put the carry into the
6913 highest order byte of the result */
6914 if (AOP_SIZE (result) > 1)
6916 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
6919 emitcode ("mov", "acc.7,c");
6921 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6922 freeAsmop (left, NULL, ic, TRUE);
6923 freeAsmop (result, NULL, ic, TRUE);
6926 /*-----------------------------------------------------------------*/
6927 /* genRLC - generate code for rotate left with carry */
6928 /*-----------------------------------------------------------------*/
6932 operand *left, *result;
6933 int size, offset = 0;
6936 D(emitcode ("; genRLC",""));
6938 /* rotate right with carry */
6939 left = IC_LEFT (ic);
6940 result = IC_RESULT (ic);
6941 aopOp (left, ic, FALSE);
6942 aopOp (result, ic, FALSE);
6944 /* move it to the result */
6945 size = AOP_SIZE (result);
6949 l = aopGet (left, offset, FALSE, FALSE);
6951 if (size == 0) { /* special case for 1 byte */
6955 emitcode("rlc","a"); /* bit0 will be written later */
6956 if (AOP_SIZE (result) > 1)
6957 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6960 l = aopGet (left, offset, FALSE, FALSE);
6962 emitcode ("rlc", "a");
6963 if (AOP_SIZE (result) > 1)
6964 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6967 /* now we need to put the carry into the
6968 highest order byte of the result */
6969 if (AOP_SIZE (result) > 1)
6971 l = aopGet (result, 0, FALSE, FALSE);
6974 emitcode ("mov", "acc.0,c");
6976 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6977 freeAsmop (left, NULL, ic, TRUE);
6978 freeAsmop (result, NULL, ic, TRUE);
6981 /*-----------------------------------------------------------------*/
6982 /* genGetHbit - generates code get highest order bit */
6983 /*-----------------------------------------------------------------*/
6985 genGetHbit (iCode * ic)
6987 operand *left, *result;
6989 D(emitcode ("; genGetHbit",""));
6991 left = IC_LEFT (ic);
6992 result = IC_RESULT (ic);
6993 aopOp (left, ic, FALSE);
6994 aopOp (result, ic, FALSE);
6996 /* get the highest order byte into a */
6997 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
6998 if (AOP_TYPE (result) == AOP_CRY)
7000 emitcode ("rlc", "a");
7005 emitcode ("rl", "a");
7006 emitcode ("anl", "a,#0x01");
7011 freeAsmop (left, NULL, ic, TRUE);
7012 freeAsmop (result, NULL, ic, TRUE);
7015 /*-----------------------------------------------------------------*/
7016 /* genSwap - generates code to swap nibbles or bytes */
7017 /*-----------------------------------------------------------------*/
7019 genSwap (iCode * ic)
7021 operand *left, *result;
7023 D(emitcode ("; genSwap",""));
7025 left = IC_LEFT (ic);
7026 result = IC_RESULT (ic);
7027 aopOp (left, ic, FALSE);
7028 aopOp (result, ic, FALSE);
7030 switch (AOP_SIZE (left))
7032 case 1: /* swap nibbles in byte */
7033 MOVA (aopGet (left, 0, FALSE, FALSE));
7034 emitcode ("swap", "a");
7035 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7037 case 2: /* swap bytes in word */
7038 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7040 MOVA (aopGet (left, 0, FALSE, FALSE));
7041 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7042 0, isOperandVolatile (result, FALSE));
7043 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7045 else if (operandsEqu (left, result))
7048 bool pushedB = FALSE, leftInB = FALSE;
7050 MOVA (aopGet (left, 0, FALSE, FALSE));
7051 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7054 emitcode ("mov", "b,a");
7058 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7059 0, isOperandVolatile (result, FALSE));
7060 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7067 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7068 0, isOperandVolatile (result, FALSE));
7069 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7070 1, isOperandVolatile (result, FALSE));
7074 wassertl(FALSE, "unsupported SWAP operand size");
7077 freeAsmop (left, NULL, ic, TRUE);
7078 freeAsmop (result, NULL, ic, TRUE);
7082 /*-----------------------------------------------------------------*/
7083 /* AccRol - rotate left accumulator by known count */
7084 /*-----------------------------------------------------------------*/
7086 AccRol (int shCount)
7088 shCount &= 0x0007; // shCount : 0..7
7095 emitcode ("rl", "a");
7098 emitcode ("rl", "a");
7099 emitcode ("rl", "a");
7102 emitcode ("swap", "a");
7103 emitcode ("rr", "a");
7106 emitcode ("swap", "a");
7109 emitcode ("swap", "a");
7110 emitcode ("rl", "a");
7113 emitcode ("rr", "a");
7114 emitcode ("rr", "a");
7117 emitcode ("rr", "a");
7122 /*-----------------------------------------------------------------*/
7123 /* AccLsh - left shift accumulator by known count */
7124 /*-----------------------------------------------------------------*/
7126 AccLsh (int shCount)
7131 emitcode ("add", "a,acc");
7132 else if (shCount == 2)
7134 emitcode ("add", "a,acc");
7135 emitcode ("add", "a,acc");
7139 /* rotate left accumulator */
7141 /* and kill the lower order bits */
7142 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7147 /*-----------------------------------------------------------------*/
7148 /* AccRsh - right shift accumulator by known count */
7149 /*-----------------------------------------------------------------*/
7151 AccRsh (int shCount)
7158 emitcode ("rrc", "a");
7162 /* rotate right accumulator */
7163 AccRol (8 - shCount);
7164 /* and kill the higher order bits */
7165 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7170 /*-----------------------------------------------------------------*/
7171 /* AccSRsh - signed right shift accumulator by known count */
7172 /*-----------------------------------------------------------------*/
7174 AccSRsh (int shCount)
7181 emitcode ("mov", "c,acc.7");
7182 emitcode ("rrc", "a");
7184 else if (shCount == 2)
7186 emitcode ("mov", "c,acc.7");
7187 emitcode ("rrc", "a");
7188 emitcode ("mov", "c,acc.7");
7189 emitcode ("rrc", "a");
7193 tlbl = newiTempLabel (NULL);
7194 /* rotate right accumulator */
7195 AccRol (8 - shCount);
7196 /* and kill the higher order bits */
7197 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7198 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7199 emitcode ("orl", "a,#0x%02x",
7200 (unsigned char) ~SRMask[shCount]);
7201 emitcode ("", "%05d$:", tlbl->key + 100);
7206 /*-----------------------------------------------------------------*/
7207 /* shiftR1Left2Result - shift right one byte from left to result */
7208 /*-----------------------------------------------------------------*/
7210 shiftR1Left2Result (operand * left, int offl,
7211 operand * result, int offr,
7212 int shCount, int sign)
7214 MOVA (aopGet (left, offl, FALSE, FALSE));
7215 /* shift right accumulator */
7220 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7223 /*-----------------------------------------------------------------*/
7224 /* shiftL1Left2Result - shift left one byte from left to result */
7225 /*-----------------------------------------------------------------*/
7227 shiftL1Left2Result (operand * left, int offl,
7228 operand * result, int offr, int shCount)
7231 l = aopGet (left, offl, FALSE, FALSE);
7233 /* shift left accumulator */
7235 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7238 /*-----------------------------------------------------------------*/
7239 /* movLeft2Result - move byte from left to result */
7240 /*-----------------------------------------------------------------*/
7242 movLeft2Result (operand * left, int offl,
7243 operand * result, int offr, int sign)
7246 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7248 l = aopGet (left, offl, FALSE, FALSE);
7250 if (*l == '@' && (IS_AOP_PREG (result)))
7252 emitcode ("mov", "a,%s", l);
7253 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7258 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7261 /* MSB sign in acc.7 ! */
7262 if (getDataSize (left) == offl + 1)
7264 emitcode ("mov", "a,%s", l);
7265 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7272 /*-----------------------------------------------------------------*/
7273 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7274 /*-----------------------------------------------------------------*/
7278 emitcode ("rrc", "a");
7279 emitcode ("xch", "a,%s", x);
7280 emitcode ("rrc", "a");
7281 emitcode ("xch", "a,%s", x);
7284 /*-----------------------------------------------------------------*/
7285 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7286 /*-----------------------------------------------------------------*/
7290 emitcode ("xch", "a,%s", x);
7291 emitcode ("rlc", "a");
7292 emitcode ("xch", "a,%s", x);
7293 emitcode ("rlc", "a");
7296 /*-----------------------------------------------------------------*/
7297 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7298 /*-----------------------------------------------------------------*/
7302 emitcode ("xch", "a,%s", x);
7303 emitcode ("add", "a,acc");
7304 emitcode ("xch", "a,%s", x);
7305 emitcode ("rlc", "a");
7308 /*-----------------------------------------------------------------*/
7309 /* AccAXLsh - left shift a:x by known count (0..7) */
7310 /*-----------------------------------------------------------------*/
7312 AccAXLsh (char *x, int shCount)
7327 case 5: // AAAAABBB:CCCCCDDD
7329 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7331 emitcode ("anl", "a,#0x%02x",
7332 SLMask[shCount]); // BBB00000:CCCCCDDD
7334 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7336 AccRol (shCount); // DDDCCCCC:BBB00000
7338 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7340 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7342 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7344 emitcode ("anl", "a,#0x%02x",
7345 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7347 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7349 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7352 case 6: // AAAAAABB:CCCCCCDD
7353 emitcode ("anl", "a,#0x%02x",
7354 SRMask[shCount]); // 000000BB:CCCCCCDD
7355 emitcode ("mov", "c,acc.0"); // c = B
7356 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7358 AccAXRrl1 (x); // BCCCCCCD:D000000B
7359 AccAXRrl1 (x); // BBCCCCCC:DD000000
7361 emitcode("rrc","a");
7362 emitcode("xch","a,%s", x);
7363 emitcode("rrc","a");
7364 emitcode("mov","c,acc.0"); //<< get correct bit
7365 emitcode("xch","a,%s", x);
7367 emitcode("rrc","a");
7368 emitcode("xch","a,%s", x);
7369 emitcode("rrc","a");
7370 emitcode("xch","a,%s", x);
7373 case 7: // a:x <<= 7
7375 emitcode ("anl", "a,#0x%02x",
7376 SRMask[shCount]); // 0000000B:CCCCCCCD
7378 emitcode ("mov", "c,acc.0"); // c = B
7380 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7382 AccAXRrl1 (x); // BCCCCCCC:D0000000
7390 /*-----------------------------------------------------------------*/
7391 /* AccAXRsh - right shift a:x known count (0..7) */
7392 /*-----------------------------------------------------------------*/
7394 AccAXRsh (char *x, int shCount)
7402 AccAXRrl1 (x); // 0->a:x
7407 AccAXRrl1 (x); // 0->a:x
7410 AccAXRrl1 (x); // 0->a:x
7415 case 5: // AAAAABBB:CCCCCDDD = a:x
7417 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7419 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7421 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7423 emitcode ("anl", "a,#0x%02x",
7424 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7426 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7428 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7430 emitcode ("anl", "a,#0x%02x",
7431 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7433 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7435 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7437 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7440 case 6: // AABBBBBB:CCDDDDDD
7442 emitcode ("mov", "c,acc.7");
7443 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7445 emitcode ("mov", "c,acc.7");
7446 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7448 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7450 emitcode ("anl", "a,#0x%02x",
7451 SRMask[shCount]); // 000000AA:BBBBBBCC
7454 case 7: // ABBBBBBB:CDDDDDDD
7456 emitcode ("mov", "c,acc.7"); // c = A
7458 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7460 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7462 emitcode ("anl", "a,#0x%02x",
7463 SRMask[shCount]); // 0000000A:BBBBBBBC
7471 /*-----------------------------------------------------------------*/
7472 /* AccAXRshS - right shift signed a:x known count (0..7) */
7473 /*-----------------------------------------------------------------*/
7475 AccAXRshS (char *x, int shCount)
7483 emitcode ("mov", "c,acc.7");
7484 AccAXRrl1 (x); // s->a:x
7488 emitcode ("mov", "c,acc.7");
7489 AccAXRrl1 (x); // s->a:x
7491 emitcode ("mov", "c,acc.7");
7492 AccAXRrl1 (x); // s->a:x
7497 case 5: // AAAAABBB:CCCCCDDD = a:x
7499 tlbl = newiTempLabel (NULL);
7500 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7502 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7504 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7506 emitcode ("anl", "a,#0x%02x",
7507 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7509 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7511 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7513 emitcode ("anl", "a,#0x%02x",
7514 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7516 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7518 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7520 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7522 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7523 emitcode ("orl", "a,#0x%02x",
7524 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7526 emitcode ("", "%05d$:", tlbl->key + 100);
7527 break; // SSSSAAAA:BBBCCCCC
7529 case 6: // AABBBBBB:CCDDDDDD
7531 tlbl = newiTempLabel (NULL);
7532 emitcode ("mov", "c,acc.7");
7533 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7535 emitcode ("mov", "c,acc.7");
7536 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7538 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7540 emitcode ("anl", "a,#0x%02x",
7541 SRMask[shCount]); // 000000AA:BBBBBBCC
7543 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7544 emitcode ("orl", "a,#0x%02x",
7545 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7547 emitcode ("", "%05d$:", tlbl->key + 100);
7549 case 7: // ABBBBBBB:CDDDDDDD
7551 tlbl = newiTempLabel (NULL);
7552 emitcode ("mov", "c,acc.7"); // c = A
7554 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7556 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7558 emitcode ("anl", "a,#0x%02x",
7559 SRMask[shCount]); // 0000000A:BBBBBBBC
7561 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7562 emitcode ("orl", "a,#0x%02x",
7563 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7565 emitcode ("", "%05d$:", tlbl->key + 100);
7572 /*-----------------------------------------------------------------*/
7573 /* shiftL2Left2Result - shift left two bytes from left to result */
7574 /*-----------------------------------------------------------------*/
7576 shiftL2Left2Result (operand * left, int offl,
7577 operand * result, int offr, int shCount)
7579 if (sameRegs (AOP (result), AOP (left)) &&
7580 ((offl + MSB16) == offr))
7582 /* don't crash result[offr] */
7583 MOVA (aopGet (left, offl, FALSE, FALSE));
7584 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7588 movLeft2Result (left, offl, result, offr, 0);
7589 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7591 /* ax << shCount (x = lsb(result)) */
7592 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7593 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7597 /*-----------------------------------------------------------------*/
7598 /* shiftR2Left2Result - shift right two bytes from left to result */
7599 /*-----------------------------------------------------------------*/
7601 shiftR2Left2Result (operand * left, int offl,
7602 operand * result, int offr,
7603 int shCount, int sign)
7605 if (sameRegs (AOP (result), AOP (left)) &&
7606 ((offl + MSB16) == offr))
7608 /* don't crash result[offr] */
7609 MOVA (aopGet (left, offl, FALSE, FALSE));
7610 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7614 movLeft2Result (left, offl, result, offr, 0);
7615 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7617 /* a:x >> shCount (x = lsb(result)) */
7619 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7621 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7622 if (getDataSize (result) > 1)
7623 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7626 /*-----------------------------------------------------------------*/
7627 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7628 /*-----------------------------------------------------------------*/
7630 shiftLLeftOrResult (operand * left, int offl,
7631 operand * result, int offr, int shCount)
7633 MOVA (aopGet (left, offl, FALSE, FALSE));
7634 /* shift left accumulator */
7636 /* or with result */
7637 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7638 /* back to result */
7639 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7642 /*-----------------------------------------------------------------*/
7643 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7644 /*-----------------------------------------------------------------*/
7646 shiftRLeftOrResult (operand * left, int offl,
7647 operand * result, int offr, int shCount)
7649 MOVA (aopGet (left, offl, FALSE, FALSE));
7650 /* shift right accumulator */
7652 /* or with result */
7653 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7654 /* back to result */
7655 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7658 /*-----------------------------------------------------------------*/
7659 /* genlshOne - left shift a one byte quantity by known count */
7660 /*-----------------------------------------------------------------*/
7662 genlshOne (operand * result, operand * left, int shCount)
7664 D(emitcode ("; genlshOne",""));
7666 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7669 /*-----------------------------------------------------------------*/
7670 /* genlshTwo - left shift two bytes by known amount != 0 */
7671 /*-----------------------------------------------------------------*/
7673 genlshTwo (operand * result, operand * left, int shCount)
7677 D(emitcode ("; genlshTwo",""));
7679 size = getDataSize (result);
7681 /* if shCount >= 8 */
7689 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7691 movLeft2Result (left, LSB, result, MSB16, 0);
7693 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7696 /* 1 <= shCount <= 7 */
7700 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7702 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7706 /*-----------------------------------------------------------------*/
7707 /* shiftLLong - shift left one long from left to result */
7708 /* offl = LSB or MSB16 */
7709 /*-----------------------------------------------------------------*/
7711 shiftLLong (operand * left, operand * result, int offr)
7714 int size = AOP_SIZE (result);
7716 if (size >= LSB + offr)
7718 l = aopGet (left, LSB, FALSE, FALSE);
7720 emitcode ("add", "a,acc");
7721 if (sameRegs (AOP (left), AOP (result)) &&
7722 size >= MSB16 + offr && offr != LSB)
7723 emitcode ("xch", "a,%s",
7724 aopGet (left, LSB + offr, FALSE, FALSE));
7726 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7729 if (size >= MSB16 + offr)
7731 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7733 l = aopGet (left, MSB16, FALSE, FALSE);
7736 emitcode ("rlc", "a");
7737 if (sameRegs (AOP (left), AOP (result)) &&
7738 size >= MSB24 + offr && offr != LSB)
7739 emitcode ("xch", "a,%s",
7740 aopGet (left, MSB16 + offr, FALSE, FALSE));
7742 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7745 if (size >= MSB24 + offr)
7747 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7749 l = aopGet (left, MSB24, FALSE, FALSE);
7752 emitcode ("rlc", "a");
7753 if (sameRegs (AOP (left), AOP (result)) &&
7754 size >= MSB32 + offr && offr != LSB)
7755 emitcode ("xch", "a,%s",
7756 aopGet (left, MSB24 + offr, FALSE, FALSE));
7758 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7761 if (size > MSB32 + offr)
7763 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7765 l = aopGet (left, MSB32, FALSE, FALSE);
7768 emitcode ("rlc", "a");
7769 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7772 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7775 /*-----------------------------------------------------------------*/
7776 /* genlshFour - shift four byte by a known amount != 0 */
7777 /*-----------------------------------------------------------------*/
7779 genlshFour (operand * result, operand * left, int shCount)
7783 D(emitcode ("; genlshFour",""));
7785 size = AOP_SIZE (result);
7787 /* if shifting more that 3 bytes */
7792 /* lowest order of left goes to the highest
7793 order of the destination */
7794 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7796 movLeft2Result (left, LSB, result, MSB32, 0);
7797 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7798 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7799 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
7803 /* more than two bytes */
7804 else if (shCount >= 16)
7806 /* lower order two bytes goes to higher order two bytes */
7808 /* if some more remaining */
7810 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7813 movLeft2Result (left, MSB16, result, MSB32, 0);
7814 movLeft2Result (left, LSB, result, MSB24, 0);
7816 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7817 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7821 /* if more than 1 byte */
7822 else if (shCount >= 8)
7824 /* lower order three bytes goes to higher order three bytes */
7829 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7831 movLeft2Result (left, LSB, result, MSB16, 0);
7837 movLeft2Result (left, MSB24, result, MSB32, 0);
7838 movLeft2Result (left, MSB16, result, MSB24, 0);
7839 movLeft2Result (left, LSB, result, MSB16, 0);
7840 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7842 else if (shCount == 1)
7843 shiftLLong (left, result, MSB16);
7846 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7847 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7848 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7849 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7854 /* 1 <= shCount <= 7 */
7855 else if (shCount <= 2)
7857 shiftLLong (left, result, LSB);
7859 shiftLLong (result, result, LSB);
7861 /* 3 <= shCount <= 7, optimize */
7864 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7865 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7866 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7870 /*-----------------------------------------------------------------*/
7871 /* genLeftShiftLiteral - left shifting by known count */
7872 /*-----------------------------------------------------------------*/
7874 genLeftShiftLiteral (operand * left,
7879 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7882 D(emitcode ("; genLeftShiftLiteral",""));
7884 freeAsmop (right, NULL, ic, TRUE);
7886 aopOp (left, ic, FALSE);
7887 aopOp (result, ic, FALSE);
7889 size = getSize (operandType (result));
7892 emitcode ("; shift left ", "result %d, left %d", size,
7896 /* I suppose that the left size >= result size */
7901 movLeft2Result (left, size, result, size, 0);
7905 else if (shCount >= (size * 8))
7907 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
7913 genlshOne (result, left, shCount);
7917 genlshTwo (result, left, shCount);
7921 genlshFour (result, left, shCount);
7924 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7925 "*** ack! mystery literal shift!\n");
7929 freeAsmop (left, NULL, ic, TRUE);
7930 freeAsmop (result, NULL, ic, TRUE);
7933 /*-----------------------------------------------------------------*/
7934 /* genLeftShift - generates code for left shifting */
7935 /*-----------------------------------------------------------------*/
7937 genLeftShift (iCode * ic)
7939 operand *left, *right, *result;
7942 symbol *tlbl, *tlbl1;
7945 D(emitcode ("; genLeftShift",""));
7947 right = IC_RIGHT (ic);
7948 left = IC_LEFT (ic);
7949 result = IC_RESULT (ic);
7951 aopOp (right, ic, FALSE);
7953 /* if the shift count is known then do it
7954 as efficiently as possible */
7955 if (AOP_TYPE (right) == AOP_LIT)
7957 genLeftShiftLiteral (left, right, result, ic);
7961 /* shift count is unknown then we have to form
7962 a loop get the loop count in B : Note: we take
7963 only the lower order byte since shifting
7964 more that 32 bits make no sense anyway, ( the
7965 largest size of an object can be only 32 bits ) */
7968 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
7969 emitcode ("inc", "b");
7970 freeAsmop (right, NULL, ic, TRUE);
7971 aopOp (left, ic, FALSE);
7972 aopOp (result, ic, FALSE);
7974 /* now move the left to the result if they are not the same */
7975 if (!sameRegs (AOP (left), AOP (result)) &&
7976 AOP_SIZE (result) > 1)
7979 size = AOP_SIZE (result);
7983 l = aopGet (left, offset, FALSE, TRUE);
7984 if (*l == '@' && (IS_AOP_PREG (result)))
7987 emitcode ("mov", "a,%s", l);
7988 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7991 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
7996 tlbl = newiTempLabel (NULL);
7997 size = AOP_SIZE (result);
7999 tlbl1 = newiTempLabel (NULL);
8001 /* if it is only one byte then */
8004 symbol *tlbl1 = newiTempLabel (NULL);
8006 l = aopGet (left, 0, FALSE, FALSE);
8008 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8009 emitcode ("", "%05d$:", tlbl->key + 100);
8010 emitcode ("add", "a,acc");
8011 emitcode ("", "%05d$:", tlbl1->key + 100);
8012 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8014 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8018 reAdjustPreg (AOP (result));
8020 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8021 emitcode ("", "%05d$:", tlbl->key + 100);
8022 l = aopGet (result, offset, FALSE, FALSE);
8024 emitcode ("add", "a,acc");
8025 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8028 l = aopGet (result, offset, FALSE, FALSE);
8030 emitcode ("rlc", "a");
8031 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8033 reAdjustPreg (AOP (result));
8035 emitcode ("", "%05d$:", tlbl1->key + 100);
8036 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8039 freeAsmop (left, NULL, ic, TRUE);
8040 freeAsmop (result, NULL, ic, TRUE);
8043 /*-----------------------------------------------------------------*/
8044 /* genrshOne - right shift a one byte quantity by known count */
8045 /*-----------------------------------------------------------------*/
8047 genrshOne (operand * result, operand * left,
8048 int shCount, int sign)
8050 D(emitcode ("; genrshOne",""));
8052 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8055 /*-----------------------------------------------------------------*/
8056 /* genrshTwo - right shift two bytes by known amount != 0 */
8057 /*-----------------------------------------------------------------*/
8059 genrshTwo (operand * result, operand * left,
8060 int shCount, int sign)
8062 D(emitcode ("; genrshTwo",""));
8064 /* if shCount >= 8 */
8069 shiftR1Left2Result (left, MSB16, result, LSB,
8072 movLeft2Result (left, MSB16, result, LSB, sign);
8073 addSign (result, MSB16, sign);
8076 /* 1 <= shCount <= 7 */
8078 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8081 /*-----------------------------------------------------------------*/
8082 /* shiftRLong - shift right one long from left to result */
8083 /* offl = LSB or MSB16 */
8084 /*-----------------------------------------------------------------*/
8086 shiftRLong (operand * left, int offl,
8087 operand * result, int sign)
8089 int isSameRegs=sameRegs(AOP(left),AOP(result));
8091 if (isSameRegs && offl>1) {
8092 // we are in big trouble, but this shouldn't happen
8093 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8096 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8101 emitcode ("rlc", "a");
8102 emitcode ("subb", "a,acc");
8104 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8106 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8107 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8110 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8115 emitcode ("clr", "c");
8117 emitcode ("mov", "c,acc.7");
8120 emitcode ("rrc", "a");
8122 if (isSameRegs && offl==MSB16) {
8123 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8125 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8126 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8129 emitcode ("rrc", "a");
8130 if (isSameRegs && offl==1) {
8131 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8133 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8134 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8136 emitcode ("rrc", "a");
8137 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8141 MOVA (aopGet (left, LSB, FALSE, FALSE));
8142 emitcode ("rrc", "a");
8143 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8147 /*-----------------------------------------------------------------*/
8148 /* genrshFour - shift four byte by a known amount != 0 */
8149 /*-----------------------------------------------------------------*/
8151 genrshFour (operand * result, operand * left,
8152 int shCount, int sign)
8154 D(emitcode ("; genrshFour",""));
8156 /* if shifting more that 3 bytes */
8161 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8163 movLeft2Result (left, MSB32, result, LSB, sign);
8164 addSign (result, MSB16, sign);
8166 else if (shCount >= 16)
8170 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8173 movLeft2Result (left, MSB24, result, LSB, 0);
8174 movLeft2Result (left, MSB32, result, MSB16, sign);
8176 addSign (result, MSB24, sign);
8178 else if (shCount >= 8)
8182 shiftRLong (left, MSB16, result, sign);
8183 else if (shCount == 0)
8185 movLeft2Result (left, MSB16, result, LSB, 0);
8186 movLeft2Result (left, MSB24, result, MSB16, 0);
8187 movLeft2Result (left, MSB32, result, MSB24, sign);
8188 addSign (result, MSB32, sign);
8192 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8193 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8194 /* the last shift is signed */
8195 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8196 addSign (result, MSB32, sign);
8200 { /* 1 <= shCount <= 7 */
8203 shiftRLong (left, LSB, result, sign);
8205 shiftRLong (result, LSB, result, sign);
8209 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8210 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8211 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8216 /*-----------------------------------------------------------------*/
8217 /* genRightShiftLiteral - right shifting by known count */
8218 /*-----------------------------------------------------------------*/
8220 genRightShiftLiteral (operand * left,
8226 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8229 D(emitcode ("; genRightShiftLiteral",""));
8231 freeAsmop (right, NULL, ic, TRUE);
8233 aopOp (left, ic, FALSE);
8234 aopOp (result, ic, FALSE);
8237 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8241 size = getDataSize (left);
8242 /* test the LEFT size !!! */
8244 /* I suppose that the left size >= result size */
8247 size = getDataSize (result);
8249 movLeft2Result (left, size, result, size, 0);
8252 else if (shCount >= (size * 8))
8255 /* get sign in acc.7 */
8256 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8258 addSign (result, LSB, sign);
8265 genrshOne (result, left, shCount, sign);
8269 genrshTwo (result, left, shCount, sign);
8273 genrshFour (result, left, shCount, sign);
8279 freeAsmop (left, NULL, ic, TRUE);
8280 freeAsmop (result, NULL, ic, TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genSignedRightShift - right shift of signed number */
8285 /*-----------------------------------------------------------------*/
8287 genSignedRightShift (iCode * ic)
8289 operand *right, *left, *result;
8292 symbol *tlbl, *tlbl1;
8295 D(emitcode ("; genSignedRightShift",""));
8297 /* we do it the hard way put the shift count in b
8298 and loop thru preserving the sign */
8300 right = IC_RIGHT (ic);
8301 left = IC_LEFT (ic);
8302 result = IC_RESULT (ic);
8304 aopOp (right, ic, FALSE);
8307 if (AOP_TYPE (right) == AOP_LIT)
8309 genRightShiftLiteral (left, right, result, ic, 1);
8312 /* shift count is unknown then we have to form
8313 a loop get the loop count in B : Note: we take
8314 only the lower order byte since shifting
8315 more that 32 bits make no sense anyway, ( the
8316 largest size of an object can be only 32 bits ) */
8319 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8320 emitcode ("inc", "b");
8321 freeAsmop (right, NULL, ic, TRUE);
8322 aopOp (left, ic, FALSE);
8323 aopOp (result, ic, FALSE);
8325 /* now move the left to the result if they are not the
8327 if (!sameRegs (AOP (left), AOP (result)) &&
8328 AOP_SIZE (result) > 1)
8331 size = AOP_SIZE (result);
8335 l = aopGet (left, offset, FALSE, TRUE);
8336 if (*l == '@' && IS_AOP_PREG (result))
8339 emitcode ("mov", "a,%s", l);
8340 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8343 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8348 /* mov the highest order bit to OVR */
8349 tlbl = newiTempLabel (NULL);
8350 tlbl1 = newiTempLabel (NULL);
8352 size = AOP_SIZE (result);
8354 MOVA (aopGet (left, offset, FALSE, FALSE));
8355 emitcode ("rlc", "a");
8356 emitcode ("mov", "ov,c");
8357 /* if it is only one byte then */
8360 l = aopGet (left, 0, FALSE, FALSE);
8362 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8363 emitcode ("", "%05d$:", tlbl->key + 100);
8364 emitcode ("mov", "c,ov");
8365 emitcode ("rrc", "a");
8366 emitcode ("", "%05d$:", tlbl1->key + 100);
8367 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8369 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8373 reAdjustPreg (AOP (result));
8374 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8375 emitcode ("", "%05d$:", tlbl->key + 100);
8376 emitcode ("mov", "c,ov");
8379 l = aopGet (result, offset, FALSE, FALSE);
8381 emitcode ("rrc", "a");
8382 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8384 reAdjustPreg (AOP (result));
8385 emitcode ("", "%05d$:", tlbl1->key + 100);
8386 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8390 freeAsmop (left, NULL, ic, TRUE);
8391 freeAsmop (result, NULL, ic, TRUE);
8394 /*-----------------------------------------------------------------*/
8395 /* genRightShift - generate code for right shifting */
8396 /*-----------------------------------------------------------------*/
8398 genRightShift (iCode * ic)
8400 operand *right, *left, *result;
8404 symbol *tlbl, *tlbl1;
8407 D(emitcode ("; genRightShift",""));
8409 /* if signed then we do it the hard way preserve the
8410 sign bit moving it inwards */
8411 letype = getSpec (operandType (IC_LEFT (ic)));
8413 if (!SPEC_USIGN (letype))
8415 genSignedRightShift (ic);
8419 /* signed & unsigned types are treated the same : i.e. the
8420 signed is NOT propagated inwards : quoting from the
8421 ANSI - standard : "for E1 >> E2, is equivalent to division
8422 by 2**E2 if unsigned or if it has a non-negative value,
8423 otherwise the result is implementation defined ", MY definition
8424 is that the sign does not get propagated */
8426 right = IC_RIGHT (ic);
8427 left = IC_LEFT (ic);
8428 result = IC_RESULT (ic);
8430 aopOp (right, ic, FALSE);
8432 /* if the shift count is known then do it
8433 as efficiently as possible */
8434 if (AOP_TYPE (right) == AOP_LIT)
8436 genRightShiftLiteral (left, right, result, ic, 0);
8440 /* shift count is unknown then we have to form
8441 a loop get the loop count in B : Note: we take
8442 only the lower order byte since shifting
8443 more that 32 bits make no sense anyway, ( the
8444 largest size of an object can be only 32 bits ) */
8447 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8448 emitcode ("inc", "b");
8449 freeAsmop (right, NULL, ic, TRUE);
8450 aopOp (left, ic, FALSE);
8451 aopOp (result, ic, FALSE);
8453 /* now move the left to the result if they are not the
8455 if (!sameRegs (AOP (left), AOP (result)) &&
8456 AOP_SIZE (result) > 1)
8459 size = AOP_SIZE (result);
8463 l = aopGet (left, offset, FALSE, TRUE);
8464 if (*l == '@' && IS_AOP_PREG (result))
8467 emitcode ("mov", "a,%s", l);
8468 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8471 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8476 tlbl = newiTempLabel (NULL);
8477 tlbl1 = newiTempLabel (NULL);
8478 size = AOP_SIZE (result);
8481 /* if it is only one byte then */
8484 l = aopGet (left, 0, FALSE, FALSE);
8486 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8487 emitcode ("", "%05d$:", tlbl->key + 100);
8489 emitcode ("rrc", "a");
8490 emitcode ("", "%05d$:", tlbl1->key + 100);
8491 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8493 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8497 reAdjustPreg (AOP (result));
8498 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8499 emitcode ("", "%05d$:", tlbl->key + 100);
8503 l = aopGet (result, offset, FALSE, FALSE);
8505 emitcode ("rrc", "a");
8506 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8508 reAdjustPreg (AOP (result));
8510 emitcode ("", "%05d$:", tlbl1->key + 100);
8511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8515 freeAsmop (left, NULL, ic, TRUE);
8516 freeAsmop (result, NULL, ic, TRUE);
8519 /*-----------------------------------------------------------------*/
8520 /* emitPtrByteGet - emits code to get a byte into A through a */
8521 /* pointer register (R0, R1, or DPTR). The */
8522 /* original value of A can be preserved in B. */
8523 /*-----------------------------------------------------------------*/
8525 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8532 emitcode ("mov", "b,a");
8533 emitcode ("mov", "a,@%s", rname);
8538 emitcode ("mov", "b,a");
8539 emitcode ("movx", "a,@%s", rname);
8544 emitcode ("mov", "b,a");
8545 emitcode ("movx", "a,@dptr");
8550 emitcode ("mov", "b,a");
8551 emitcode ("clr", "a");
8552 emitcode ("movc", "a,@a+dptr");
8558 emitcode ("push", "b");
8559 emitcode ("push", "acc");
8561 emitcode ("lcall", "__gptrget");
8563 emitcode ("pop", "b");
8568 /*-----------------------------------------------------------------*/
8569 /* emitPtrByteSet - emits code to set a byte from src through a */
8570 /* pointer register (R0, R1, or DPTR). */
8571 /*-----------------------------------------------------------------*/
8573 emitPtrByteSet (char *rname, int p_type, char *src)
8582 emitcode ("mov", "@%s,a", rname);
8585 emitcode ("mov", "@%s,%s", rname, src);
8590 emitcode ("movx", "@%s,a", rname);
8595 emitcode ("movx", "@dptr,a");
8600 emitcode ("lcall", "__gptrput");
8605 /*-----------------------------------------------------------------*/
8606 /* genUnpackBits - generates code for unpacking bits */
8607 /*-----------------------------------------------------------------*/
8609 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8611 int offset = 0; /* result byte offset */
8612 int rsize; /* result size */
8613 int rlen = 0; /* remaining bitfield length */
8614 sym_link *etype; /* bitfield type information */
8615 int blen; /* bitfield length */
8616 int bstr; /* bitfield starting bit within byte */
8619 D(emitcode ("; genUnpackBits",""));
8621 etype = getSpec (operandType (result));
8622 rsize = getSize (operandType (result));
8623 blen = SPEC_BLEN (etype);
8624 bstr = SPEC_BSTR (etype);
8626 if (ifx && blen <= 8)
8628 emitPtrByteGet (rname, ptype, FALSE);
8631 SNPRINTF (buffer, sizeof(buffer),
8633 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8638 emitcode ("anl", "a,#0x%02x",
8639 (((unsigned char) -1) >> (8 - blen)) << bstr);
8640 genIfxJump (ifx, "a", NULL, NULL, NULL);
8646 /* If the bitfield length is less than a byte */
8649 emitPtrByteGet (rname, ptype, FALSE);
8651 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8652 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8656 /* Bit field did not fit in a byte. Copy all
8657 but the partial byte at the end. */
8658 for (rlen=blen;rlen>=8;rlen-=8)
8660 emitPtrByteGet (rname, ptype, FALSE);
8661 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8663 emitcode ("inc", "%s", rname);
8666 /* Handle the partial byte at the end */
8669 emitPtrByteGet (rname, ptype, FALSE);
8670 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8671 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8679 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8684 /*-----------------------------------------------------------------*/
8685 /* genDataPointerGet - generates code when ptr offset is known */
8686 /*-----------------------------------------------------------------*/
8688 genDataPointerGet (operand * left,
8694 int size, offset = 0;
8696 D(emitcode ("; genDataPointerGet",""));
8698 aopOp (result, ic, TRUE);
8700 /* get the string representation of the name */
8701 l = aopGet (left, 0, FALSE, TRUE);
8702 size = AOP_SIZE (result);
8706 sprintf (buffer, "(%s + %d)", l + 1, offset);
8708 sprintf (buffer, "%s", l + 1);
8709 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8712 freeAsmop (left, NULL, ic, TRUE);
8713 freeAsmop (result, NULL, ic, TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* genNearPointerGet - emitcode for near pointer fetch */
8718 /*-----------------------------------------------------------------*/
8720 genNearPointerGet (operand * left,
8729 sym_link *rtype, *retype;
8730 sym_link *ltype = operandType (left);
8733 D(emitcode ("; genNearPointerGet",""));
8735 rtype = operandType (result);
8736 retype = getSpec (rtype);
8738 aopOp (left, ic, FALSE);
8740 /* if left is rematerialisable and
8741 result is not bitfield variable type and
8742 the left is pointer to data space i.e
8743 lower 128 bytes of space */
8744 if (AOP_TYPE (left) == AOP_IMMD &&
8745 !IS_BITFIELD (retype) &&
8746 DCL_TYPE (ltype) == POINTER)
8748 genDataPointerGet (left, result, ic);
8752 /* if the value is already in a pointer register
8753 then don't need anything more */
8754 if (!AOP_INPREG (AOP (left)))
8756 if (IS_AOP_PREG (left))
8758 // Aha, it is a pointer, just in disguise.
8759 rname = aopGet (left, 0, FALSE, FALSE);
8762 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8763 __FILE__, __LINE__);
8768 emitcode ("mov", "a%s,%s", rname + 1, rname);
8769 rname++; // skip the '@'.
8774 /* otherwise get a free pointer register */
8776 preg = getFreePtr (ic, &aop, FALSE);
8777 emitcode ("mov", "%s,%s",
8779 aopGet (left, 0, FALSE, TRUE));
8784 rname = aopGet (left, 0, FALSE, FALSE);
8786 //aopOp (result, ic, FALSE);
8787 aopOp (result, ic, result?TRUE:FALSE);
8789 /* if bitfield then unpack the bits */
8790 if (IS_BITFIELD (retype))
8791 genUnpackBits (result, rname, POINTER, ifx);
8794 /* we have can just get the values */
8795 int size = AOP_SIZE (result);
8800 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8803 emitcode ("mov", "a,@%s", rname);
8805 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8809 sprintf (buffer, "@%s", rname);
8810 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
8814 emitcode ("inc", "%s", rname);
8818 /* now some housekeeping stuff */
8819 if (aop) /* we had to allocate for this iCode */
8821 if (pi) { /* post increment present */
8822 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8824 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8828 /* we did not allocate which means left
8829 already in a pointer register, then
8830 if size > 0 && this could be used again
8831 we have to point it back to where it
8833 if ((AOP_SIZE (result) > 1 &&
8834 !OP_SYMBOL (left)->remat &&
8835 (OP_SYMBOL (left)->liveTo > ic->seq ||
8839 int size = AOP_SIZE (result) - 1;
8841 emitcode ("dec", "%s", rname);
8845 if (ifx && !ifx->generated)
8847 genIfxJump (ifx, "a", left, NULL, result);
8851 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8852 freeAsmop (left, NULL, ic, TRUE);
8853 if (pi) pi->generated = 1;
8856 /*-----------------------------------------------------------------*/
8857 /* genPagedPointerGet - emitcode for paged pointer fetch */
8858 /*-----------------------------------------------------------------*/
8860 genPagedPointerGet (operand * left,
8869 sym_link *rtype, *retype;
8871 D(emitcode ("; genPagedPointerGet",""));
8873 rtype = operandType (result);
8874 retype = getSpec (rtype);
8876 aopOp (left, ic, FALSE);
8878 /* if the value is already in a pointer register
8879 then don't need anything more */
8880 if (!AOP_INPREG (AOP (left)))
8882 /* otherwise get a free pointer register */
8884 preg = getFreePtr (ic, &aop, FALSE);
8885 emitcode ("mov", "%s,%s",
8887 aopGet (left, 0, FALSE, TRUE));
8891 rname = aopGet (left, 0, FALSE, FALSE);
8893 aopOp (result, ic, FALSE);
8895 /* if bitfield then unpack the bits */
8896 if (IS_BITFIELD (retype))
8897 genUnpackBits (result, rname, PPOINTER, ifx);
8900 /* we have can just get the values */
8901 int size = AOP_SIZE (result);
8907 emitcode ("movx", "a,@%s", rname);
8909 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8914 emitcode ("inc", "%s", rname);
8918 /* now some housekeeping stuff */
8919 if (aop) /* we had to allocate for this iCode */
8921 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8922 freeAsmop (NULL, aop, ic, TRUE);
8926 /* we did not allocate which means left
8927 already in a pointer register, then
8928 if size > 0 && this could be used again
8929 we have to point it back to where it
8931 if ((AOP_SIZE (result) > 1 &&
8932 !OP_SYMBOL (left)->remat &&
8933 (OP_SYMBOL (left)->liveTo > ic->seq ||
8937 int size = AOP_SIZE (result) - 1;
8939 emitcode ("dec", "%s", rname);
8943 if (ifx && !ifx->generated)
8945 genIfxJump (ifx, "a", left, NULL, result);
8949 freeAsmop (left, NULL, ic, TRUE);
8950 freeAsmop (result, NULL, ic, TRUE);
8951 if (pi) pi->generated = 1;
8955 /*--------------------------------------------------------------------*/
8956 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8957 /*--------------------------------------------------------------------*/
8959 loadDptrFromOperand (operand *op, bool loadBToo)
8961 if (AOP_TYPE (op) != AOP_STR)
8963 /* if this is rematerializable */
8964 if (AOP_TYPE (op) == AOP_IMMD)
8966 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
8969 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8970 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
8973 wassertl(FALSE, "need pointerCode");
8974 emitcode ("", "; mov b,???");
8975 /* genPointerGet and genPointerSet originally did different
8976 ** things for this case. Both seem wrong.
8977 ** from genPointerGet:
8978 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8979 ** from genPointerSet:
8980 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
8985 else if (AOP_TYPE (op) == AOP_DPTR)
8989 MOVA (aopGet (op, 0, FALSE, FALSE));
8990 emitcode ("push", "acc");
8991 MOVA (aopGet (op, 1, FALSE, FALSE));
8992 emitcode ("push", "acc");
8993 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8994 emitcode ("pop", "dph");
8995 emitcode ("pop", "dpl");
8999 MOVA (aopGet (op, 0, FALSE, FALSE));
9000 emitcode ("push", "acc");
9001 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9002 emitcode ("pop", "dpl");
9006 { /* we need to get it byte by byte */
9007 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9008 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9010 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9015 /*-----------------------------------------------------------------*/
9016 /* genFarPointerGet - gget value from far space */
9017 /*-----------------------------------------------------------------*/
9019 genFarPointerGet (operand * left,
9020 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9023 sym_link *retype = getSpec (operandType (result));
9025 D(emitcode ("; genFarPointerGet",""));
9027 aopOp (left, ic, FALSE);
9028 loadDptrFromOperand (left, FALSE);
9030 /* so dptr now contains the address */
9031 aopOp (result, ic, FALSE);
9033 /* if bit then unpack */
9034 if (IS_BITFIELD (retype))
9035 genUnpackBits (result, "dptr", FPOINTER, ifx);
9038 size = AOP_SIZE (result);
9043 emitcode ("movx", "a,@dptr");
9045 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9047 emitcode ("inc", "dptr");
9051 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9053 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9054 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9058 if (ifx && !ifx->generated)
9060 genIfxJump (ifx, "a", left, NULL, result);
9063 freeAsmop (left, NULL, ic, TRUE);
9064 freeAsmop (result, NULL, ic, TRUE);
9067 /*-----------------------------------------------------------------*/
9068 /* genCodePointerGet - gget value from code space */
9069 /*-----------------------------------------------------------------*/
9071 genCodePointerGet (operand * left,
9072 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9075 sym_link *retype = getSpec (operandType (result));
9077 D(emitcode ("; genCodePointerGet",""));
9079 aopOp (left, ic, FALSE);
9080 loadDptrFromOperand (left, FALSE);
9082 /* so dptr now contains the address */
9083 aopOp (result, ic, FALSE);
9085 /* if bit then unpack */
9086 if (IS_BITFIELD (retype))
9087 genUnpackBits (result, "dptr", CPOINTER, ifx);
9090 size = AOP_SIZE (result);
9097 emitcode ("clr", "a");
9098 emitcode ("movc", "a,@a+dptr");
9100 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9101 emitcode ("inc", "dptr");
9105 emitcode ("mov", "a,#0x%02x", offset);
9106 emitcode ("movc", "a,@a+dptr");
9108 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9113 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9115 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9116 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9120 if (ifx && !ifx->generated)
9122 genIfxJump (ifx, "a", left, NULL, result);
9125 freeAsmop (left, NULL, ic, TRUE);
9126 freeAsmop (result, NULL, ic, TRUE);
9129 /*-----------------------------------------------------------------*/
9130 /* genGenPointerGet - gget value from generic pointer space */
9131 /*-----------------------------------------------------------------*/
9133 genGenPointerGet (operand * left,
9134 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9137 sym_link *retype = getSpec (operandType (result));
9139 D(emitcode ("; genGenPointerGet",""));
9141 aopOp (left, ic, FALSE);
9142 loadDptrFromOperand (left, TRUE);
9144 /* so dptr know contains the address */
9145 aopOp (result, ic, FALSE);
9147 /* if bit then unpack */
9148 if (IS_BITFIELD (retype))
9149 genUnpackBits (result, "dptr", GPOINTER, ifx);
9152 size = AOP_SIZE (result);
9157 emitcode ("lcall", "__gptrget");
9159 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9161 emitcode ("inc", "dptr");
9165 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9167 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9168 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9172 if (ifx && !ifx->generated)
9174 genIfxJump (ifx, "a", left, NULL, result);
9178 freeAsmop (left, NULL, ic, TRUE);
9179 freeAsmop (result, NULL, ic, TRUE);
9182 /*-----------------------------------------------------------------*/
9183 /* genPointerGet - generate code for pointer get */
9184 /*-----------------------------------------------------------------*/
9186 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9188 operand *left, *result;
9189 sym_link *type, *etype;
9192 D(emitcode ("; genPointerGet",""));
9194 left = IC_LEFT (ic);
9195 result = IC_RESULT (ic);
9197 if (getSize (operandType (result))>1)
9200 /* depending on the type of pointer we need to
9201 move it to the correct pointer register */
9202 type = operandType (left);
9203 etype = getSpec (type);
9204 /* if left is of type of pointer then it is simple */
9205 if (IS_PTR (type) && !IS_FUNC (type->next))
9206 p_type = DCL_TYPE (type);
9209 /* we have to go by the storage class */
9210 p_type = PTR_TYPE (SPEC_OCLS (etype));
9213 /* special case when cast remat */
9214 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9215 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9216 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9217 type = operandType (left);
9218 p_type = DCL_TYPE (type);
9220 /* now that we have the pointer type we assign
9221 the pointer values */
9227 genNearPointerGet (left, result, ic, pi, ifx);
9231 genPagedPointerGet (left, result, ic, pi, ifx);
9235 genFarPointerGet (left, result, ic, pi, ifx);
9239 genCodePointerGet (left, result, ic, pi, ifx);
9243 genGenPointerGet (left, result, ic, pi, ifx);
9251 /*-----------------------------------------------------------------*/
9252 /* genPackBits - generates code for packed bit storage */
9253 /*-----------------------------------------------------------------*/
9255 genPackBits (sym_link * etype,
9257 char *rname, int p_type)
9259 int offset = 0; /* source byte offset */
9260 int rlen = 0; /* remaining bitfield length */
9261 int blen; /* bitfield length */
9262 int bstr; /* bitfield starting bit within byte */
9263 int litval; /* source literal value (if AOP_LIT) */
9264 unsigned char mask; /* bitmask within current byte */
9266 D(emitcode ("; genPackBits",""));
9268 blen = SPEC_BLEN (etype);
9269 bstr = SPEC_BSTR (etype);
9271 /* If the bitfield length is less than a byte */
9274 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9275 (unsigned char) (0xFF >> (8 - bstr)));
9277 if (AOP_TYPE (right) == AOP_LIT)
9279 /* Case with a bitfield length <8 and literal source
9281 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9283 litval &= (~mask) & 0xff;
9284 emitPtrByteGet (rname, p_type, FALSE);
9285 if ((mask|litval)!=0xff)
9286 emitcode ("anl","a,#0x%02x", mask);
9288 emitcode ("orl","a,#0x%02x", litval);
9292 if ((blen==1) && (p_type!=GPOINTER))
9294 /* Case with a bitfield length == 1 and no generic pointer
9296 if (AOP_TYPE (right) == AOP_CRY)
9297 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9300 MOVA (aopGet (right, 0, FALSE, FALSE));
9301 emitcode ("rrc","a");
9303 emitPtrByteGet (rname, p_type, FALSE);
9304 emitcode ("mov","acc.%d,c",bstr);
9309 /* Case with a bitfield length < 8 and arbitrary source
9311 MOVA (aopGet (right, 0, FALSE, FALSE));
9312 /* shift and mask source value */
9314 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9317 /* transfer A to B and get next byte */
9318 emitPtrByteGet (rname, p_type, TRUE);
9320 emitcode ("anl", "a,#0x%02x", mask);
9321 emitcode ("orl", "a,b");
9322 if (p_type == GPOINTER)
9323 emitcode ("pop", "b");
9329 emitPtrByteSet (rname, p_type, "a");
9333 /* Bit length is greater than 7 bits. In this case, copy */
9334 /* all except the partial byte at the end */
9335 for (rlen=blen;rlen>=8;rlen-=8)
9337 emitPtrByteSet (rname, p_type,
9338 aopGet (right, offset++, FALSE, TRUE) );
9340 emitcode ("inc", "%s", rname);
9343 /* If there was a partial byte at the end */
9346 mask = (((unsigned char) -1 << rlen) & 0xff);
9348 if (AOP_TYPE (right) == AOP_LIT)
9350 /* Case with partial byte and literal source
9352 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9353 litval >>= (blen-rlen);
9354 litval &= (~mask) & 0xff;
9355 emitPtrByteGet (rname, p_type, FALSE);
9356 if ((mask|litval)!=0xff)
9357 emitcode ("anl","a,#0x%02x", mask);
9359 emitcode ("orl","a,#0x%02x", litval);
9364 /* Case with partial byte and arbitrary source
9366 MOVA (aopGet (right, offset++, FALSE, FALSE));
9367 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9370 /* transfer A to B and get next byte */
9371 emitPtrByteGet (rname, p_type, TRUE);
9373 emitcode ("anl", "a,#0x%02x", mask);
9374 emitcode ("orl", "a,b");
9375 if (p_type == GPOINTER)
9376 emitcode ("pop", "b");
9380 emitPtrByteSet (rname, p_type, "a");
9386 /*-----------------------------------------------------------------*/
9387 /* genDataPointerSet - remat pointer to data space */
9388 /*-----------------------------------------------------------------*/
9390 genDataPointerSet (operand * right,
9394 int size, offset = 0;
9395 char *l, buffer[256];
9397 D(emitcode ("; genDataPointerSet",""));
9399 aopOp (right, ic, FALSE);
9401 l = aopGet (result, 0, FALSE, TRUE);
9402 size = AOP_SIZE (right);
9406 sprintf (buffer, "(%s + %d)", l + 1, offset);
9408 sprintf (buffer, "%s", l + 1);
9409 emitcode ("mov", "%s,%s", buffer,
9410 aopGet (right, offset++, FALSE, FALSE));
9413 freeAsmop (right, NULL, ic, TRUE);
9414 freeAsmop (result, NULL, ic, TRUE);
9417 /*-----------------------------------------------------------------*/
9418 /* genNearPointerSet - emitcode for near pointer put */
9419 /*-----------------------------------------------------------------*/
9421 genNearPointerSet (operand * right,
9429 sym_link *retype, *letype;
9430 sym_link *ptype = operandType (result);
9432 D(emitcode ("; genNearPointerSet",""));
9434 retype = getSpec (operandType (right));
9435 letype = getSpec (ptype);
9436 aopOp (result, ic, FALSE);
9438 /* if the result is rematerializable &
9439 in data space & not a bit variable */
9440 if (AOP_TYPE (result) == AOP_IMMD &&
9441 DCL_TYPE (ptype) == POINTER &&
9442 !IS_BITVAR (retype) &&
9443 !IS_BITVAR (letype))
9445 genDataPointerSet (right, result, ic);
9449 /* if the value is already in a pointer register
9450 then don't need anything more */
9451 if (!AOP_INPREG (AOP (result)))
9454 //AOP_TYPE (result) == AOP_STK
9458 // Aha, it is a pointer, just in disguise.
9459 rname = aopGet (result, 0, FALSE, FALSE);
9462 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9463 __FILE__, __LINE__);
9468 emitcode ("mov", "a%s,%s", rname + 1, rname);
9469 rname++; // skip the '@'.
9474 /* otherwise get a free pointer register */
9476 preg = getFreePtr (ic, &aop, FALSE);
9477 emitcode ("mov", "%s,%s",
9479 aopGet (result, 0, FALSE, TRUE));
9485 rname = aopGet (result, 0, FALSE, FALSE);
9488 aopOp (right, ic, FALSE);
9490 /* if bitfield then unpack the bits */
9491 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9492 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9495 /* we have can just get the values */
9496 int size = AOP_SIZE (right);
9501 l = aopGet (right, offset, FALSE, TRUE);
9505 emitcode ("mov", "@%s,a", rname);
9508 emitcode ("mov", "@%s,%s", rname, l);
9510 emitcode ("inc", "%s", rname);
9515 /* now some housekeeping stuff */
9516 if (aop) /* we had to allocate for this iCode */
9519 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9520 freeAsmop (NULL, aop, ic, TRUE);
9524 /* we did not allocate which means left
9525 already in a pointer register, then
9526 if size > 0 && this could be used again
9527 we have to point it back to where it
9529 if ((AOP_SIZE (right) > 1 &&
9530 !OP_SYMBOL (result)->remat &&
9531 (OP_SYMBOL (result)->liveTo > ic->seq ||
9535 int size = AOP_SIZE (right) - 1;
9537 emitcode ("dec", "%s", rname);
9542 if (pi) pi->generated = 1;
9543 freeAsmop (result, NULL, ic, TRUE);
9544 freeAsmop (right, NULL, ic, TRUE);
9547 /*-----------------------------------------------------------------*/
9548 /* genPagedPointerSet - emitcode for Paged pointer put */
9549 /*-----------------------------------------------------------------*/
9551 genPagedPointerSet (operand * right,
9559 sym_link *retype, *letype;
9561 D(emitcode ("; genPagedPointerSet",""));
9563 retype = getSpec (operandType (right));
9564 letype = getSpec (operandType (result));
9566 aopOp (result, ic, FALSE);
9568 /* if the value is already in a pointer register
9569 then don't need anything more */
9570 if (!AOP_INPREG (AOP (result)))
9572 /* otherwise get a free pointer register */
9574 preg = getFreePtr (ic, &aop, FALSE);
9575 emitcode ("mov", "%s,%s",
9577 aopGet (result, 0, FALSE, TRUE));
9581 rname = aopGet (result, 0, FALSE, FALSE);
9583 aopOp (right, ic, FALSE);
9585 /* if bitfield then unpack the bits */
9586 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9587 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9590 /* we have can just get the values */
9591 int size = AOP_SIZE (right);
9596 l = aopGet (right, offset, FALSE, TRUE);
9599 emitcode ("movx", "@%s,a", rname);
9602 emitcode ("inc", "%s", rname);
9608 /* now some housekeeping stuff */
9609 if (aop) /* we had to allocate for this iCode */
9612 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9613 freeAsmop (NULL, aop, ic, TRUE);
9617 /* we did not allocate which means left
9618 already in a pointer register, then
9619 if size > 0 && this could be used again
9620 we have to point it back to where it
9622 if (AOP_SIZE (right) > 1 &&
9623 !OP_SYMBOL (result)->remat &&
9624 (OP_SYMBOL (result)->liveTo > ic->seq ||
9627 int size = AOP_SIZE (right) - 1;
9629 emitcode ("dec", "%s", rname);
9634 if (pi) pi->generated = 1;
9635 freeAsmop (result, NULL, ic, TRUE);
9636 freeAsmop (right, NULL, ic, TRUE);
9641 /*-----------------------------------------------------------------*/
9642 /* genFarPointerSet - set value from far space */
9643 /*-----------------------------------------------------------------*/
9645 genFarPointerSet (operand * right,
9646 operand * result, iCode * ic, iCode * pi)
9649 sym_link *retype = getSpec (operandType (right));
9650 sym_link *letype = getSpec (operandType (result));
9652 D(emitcode ("; genFarPointerSet",""));
9654 aopOp (result, ic, FALSE);
9655 loadDptrFromOperand (result, FALSE);
9657 /* so dptr know contains the address */
9658 aopOp (right, ic, FALSE);
9660 /* if bit then unpack */
9661 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9662 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9665 size = AOP_SIZE (right);
9670 char *l = aopGet (right, offset++, FALSE, FALSE);
9672 emitcode ("movx", "@dptr,a");
9674 emitcode ("inc", "dptr");
9677 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9678 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9679 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9682 freeAsmop (result, NULL, ic, TRUE);
9683 freeAsmop (right, NULL, ic, TRUE);
9686 /*-----------------------------------------------------------------*/
9687 /* genGenPointerSet - set value from generic pointer space */
9688 /*-----------------------------------------------------------------*/
9690 genGenPointerSet (operand * right,
9691 operand * result, iCode * ic, iCode * pi)
9694 sym_link *retype = getSpec (operandType (right));
9695 sym_link *letype = getSpec (operandType (result));
9697 D(emitcode ("; genGenPointerSet",""));
9699 aopOp (result, ic, FALSE);
9700 loadDptrFromOperand (result, TRUE);
9702 /* so dptr know contains the address */
9703 aopOp (right, ic, FALSE);
9705 /* if bit then unpack */
9706 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9707 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9710 size = AOP_SIZE (right);
9715 char *l = aopGet (right, offset++, FALSE, FALSE);
9717 emitcode ("lcall", "__gptrput");
9719 emitcode ("inc", "dptr");
9723 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9724 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9725 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9728 freeAsmop (result, NULL, ic, TRUE);
9729 freeAsmop (right, NULL, ic, TRUE);
9732 /*-----------------------------------------------------------------*/
9733 /* genPointerSet - stores the value into a pointer location */
9734 /*-----------------------------------------------------------------*/
9736 genPointerSet (iCode * ic, iCode *pi)
9738 operand *right, *result;
9739 sym_link *type, *etype;
9742 D(emitcode ("; genPointerSet",""));
9744 right = IC_RIGHT (ic);
9745 result = IC_RESULT (ic);
9747 /* depending on the type of pointer we need to
9748 move it to the correct pointer register */
9749 type = operandType (result);
9750 etype = getSpec (type);
9751 /* if left is of type of pointer then it is simple */
9752 if (IS_PTR (type) && !IS_FUNC (type->next))
9754 p_type = DCL_TYPE (type);
9758 /* we have to go by the storage class */
9759 p_type = PTR_TYPE (SPEC_OCLS (etype));
9762 /* special case when cast remat */
9763 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9764 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9765 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9766 type = operandType (result);
9767 p_type = DCL_TYPE (type);
9769 /* now that we have the pointer type we assign
9770 the pointer values */
9776 genNearPointerSet (right, result, ic, pi);
9780 genPagedPointerSet (right, result, ic, pi);
9784 genFarPointerSet (right, result, ic, pi);
9788 genGenPointerSet (right, result, ic, pi);
9792 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9793 "genPointerSet: illegal pointer type");
9798 /*-----------------------------------------------------------------*/
9799 /* genIfx - generate code for Ifx statement */
9800 /*-----------------------------------------------------------------*/
9802 genIfx (iCode * ic, iCode * popIc)
9804 operand *cond = IC_COND (ic);
9807 D(emitcode ("; genIfx",""));
9809 aopOp (cond, ic, FALSE);
9811 /* get the value into acc */
9812 if (AOP_TYPE (cond) != AOP_CRY)
9816 /* the result is now in the accumulator */
9817 freeAsmop (cond, NULL, ic, TRUE);
9819 /* if there was something to be popped then do it */
9823 /* if the condition is a bit variable */
9824 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9825 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9826 else if (isbit && !IS_ITEMP (cond))
9827 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9829 genIfxJump (ic, "a", NULL, NULL, NULL);
9834 /*-----------------------------------------------------------------*/
9835 /* genAddrOf - generates code for address of */
9836 /*-----------------------------------------------------------------*/
9838 genAddrOf (iCode * ic)
9840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9843 D(emitcode ("; genAddrOf",""));
9845 aopOp (IC_RESULT (ic), ic, FALSE);
9847 /* if the operand is on the stack then we
9848 need to get the stack offset of this
9852 /* if it has an offset then we need to compute
9856 emitcode ("mov", "a,%s", SYM_BP (sym));
9857 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9858 ((char) (sym->stack - _G.nRegsSaved)) :
9859 ((char) sym->stack)) & 0xff);
9860 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9864 /* we can just move _bp */
9865 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9867 /* fill the result with zero */
9868 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9873 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9879 /* object not on stack then we need the name */
9880 size = AOP_SIZE (IC_RESULT (ic));
9885 char s[SDCC_NAME_MAX];
9887 sprintf (s, "#(%s >> %d)",
9891 sprintf (s, "#%s", sym->rname);
9892 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9896 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9900 /*-----------------------------------------------------------------*/
9901 /* genFarFarAssign - assignment when both are in far space */
9902 /*-----------------------------------------------------------------*/
9904 genFarFarAssign (operand * result, operand * right, iCode * ic)
9906 int size = AOP_SIZE (right);
9910 D(emitcode ("; genFarFarAssign",""));
9912 /* first push the right side on to the stack */
9915 l = aopGet (right, offset++, FALSE, FALSE);
9917 emitcode ("push", "acc");
9920 freeAsmop (right, NULL, ic, FALSE);
9921 /* now assign DPTR to result */
9922 aopOp (result, ic, FALSE);
9923 size = AOP_SIZE (result);
9926 emitcode ("pop", "acc");
9927 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
9929 freeAsmop (result, NULL, ic, FALSE);
9933 /*-----------------------------------------------------------------*/
9934 /* genAssign - generate code for assignment */
9935 /*-----------------------------------------------------------------*/
9937 genAssign (iCode * ic)
9939 operand *result, *right;
9941 unsigned long lit = 0L;
9943 D(emitcode("; genAssign",""));
9945 result = IC_RESULT (ic);
9946 right = IC_RIGHT (ic);
9948 /* if they are the same */
9949 if (operandsEqu (result, right) &&
9950 !isOperandVolatile (result, FALSE) &&
9951 !isOperandVolatile (right, FALSE))
9954 aopOp (right, ic, FALSE);
9956 /* special case both in far space */
9957 if (AOP_TYPE (right) == AOP_DPTR &&
9958 IS_TRUE_SYMOP (result) &&
9959 isOperandInFarSpace (result))
9962 genFarFarAssign (result, right, ic);
9966 aopOp (result, ic, TRUE);
9968 /* if they are the same registers */
9969 if (sameRegs (AOP (right), AOP (result)) &&
9970 !isOperandVolatile (result, FALSE) &&
9971 !isOperandVolatile (right, FALSE))
9974 /* if the result is a bit */
9975 if (AOP_TYPE (result) == AOP_CRY)
9978 /* if the right size is a literal then
9979 we know what the value is */
9980 if (AOP_TYPE (right) == AOP_LIT)
9982 if (((int) operandLitValue (right)))
9983 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
9985 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
9989 /* the right is also a bit variable */
9990 if (AOP_TYPE (right) == AOP_CRY)
9992 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9993 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
9999 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10003 /* bit variables done */
10005 size = AOP_SIZE (result);
10007 if (AOP_TYPE (right) == AOP_LIT)
10008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10010 (AOP_TYPE (result) != AOP_REG) &&
10011 (AOP_TYPE (right) == AOP_LIT) &&
10012 !IS_FLOAT (operandType (right)) &&
10015 while ((size) && (lit))
10018 aopGet (right, offset, FALSE, FALSE),
10020 isOperandVolatile (result, FALSE));
10025 emitcode ("clr", "a");
10028 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10037 aopGet (right, offset, FALSE, FALSE),
10039 isOperandVolatile (result, FALSE));
10045 freeAsmop (right, NULL, ic, TRUE);
10046 freeAsmop (result, NULL, ic, TRUE);
10049 /*-----------------------------------------------------------------*/
10050 /* genJumpTab - generates code for jump table */
10051 /*-----------------------------------------------------------------*/
10053 genJumpTab (iCode * ic)
10055 symbol *jtab,*jtablo,*jtabhi;
10057 unsigned int count;
10059 D(emitcode ("; genJumpTab",""));
10061 count = elementsInSet( IC_JTLABELS (ic) );
10065 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10066 if the switch argument is in a register.
10067 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10068 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10069 How will multiply by three be updated ???*/
10070 aopOp (IC_JTCOND (ic), ic, FALSE);
10071 /* get the condition into accumulator */
10072 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10074 /* multiply by three */
10075 emitcode ("add", "a,acc");
10076 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10077 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10079 jtab = newiTempLabel (NULL);
10080 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10081 emitcode ("jmp", "@a+dptr");
10082 emitcode ("", "%05d$:", jtab->key + 100);
10083 /* now generate the jump labels */
10084 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10085 jtab = setNextItem (IC_JTLABELS (ic)))
10086 emitcode ("ljmp", "%05d$", jtab->key + 100);
10090 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10091 if the switch argument is in a register.
10092 For n>6 this algorithm may be more compact */
10093 jtablo = newiTempLabel (NULL);
10094 jtabhi = newiTempLabel (NULL);
10096 /* get the condition into accumulator.
10097 Using b as temporary storage, if register push/pop is needed */
10098 aopOp (IC_JTCOND (ic), ic, FALSE);
10099 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10100 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10101 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10103 // (MB) what if B is in use???
10104 wassertl(!BINUSE, "B was in use");
10105 emitcode ("mov", "b,%s", l);
10108 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10112 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10113 emitcode ("movc", "a,@a+pc");
10114 emitcode ("push", "acc");
10117 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10118 emitcode ("movc", "a,@a+pc");
10119 emitcode ("push", "acc");
10123 /* this scales up to n<=255, but needs two more bytes
10124 and changes dptr */
10125 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10126 emitcode ("movc", "a,@a+dptr");
10127 emitcode ("push", "acc");
10130 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10131 emitcode ("movc", "a,@a+dptr");
10132 emitcode ("push", "acc");
10135 emitcode ("ret", "");
10137 /* now generate jump table, LSB */
10138 emitcode ("", "%05d$:", jtablo->key + 100);
10139 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10140 jtab = setNextItem (IC_JTLABELS (ic)))
10141 emitcode (".db", "%05d$", jtab->key + 100);
10143 /* now generate jump table, MSB */
10144 emitcode ("", "%05d$:", jtabhi->key + 100);
10145 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10146 jtab = setNextItem (IC_JTLABELS (ic)))
10147 emitcode (".db", "%05d$>>8", jtab->key + 100);
10151 /*-----------------------------------------------------------------*/
10152 /* genCast - gen code for casting */
10153 /*-----------------------------------------------------------------*/
10155 genCast (iCode * ic)
10157 operand *result = IC_RESULT (ic);
10158 sym_link *ctype = operandType (IC_LEFT (ic));
10159 sym_link *rtype = operandType (IC_RIGHT (ic));
10160 operand *right = IC_RIGHT (ic);
10163 D(emitcode("; genCast",""));
10165 /* if they are equivalent then do nothing */
10166 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10169 aopOp (right, ic, FALSE);
10170 aopOp (result, ic, FALSE);
10172 /* if the result is a bit (and not a bitfield) */
10173 // if (AOP_TYPE (result) == AOP_CRY)
10174 if (IS_BITVAR (OP_SYMBOL (result)->type)
10175 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10177 /* if the right size is a literal then
10178 we know what the value is */
10179 if (AOP_TYPE (right) == AOP_LIT)
10181 if (((int) operandLitValue (right)))
10182 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10184 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10189 /* the right is also a bit variable */
10190 if (AOP_TYPE (right) == AOP_CRY)
10192 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10193 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10197 /* we need to or */
10199 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10204 /* if they are the same size : or less */
10205 if (AOP_SIZE (result) <= AOP_SIZE (right))
10208 /* if they are in the same place */
10209 if (sameRegs (AOP (right), AOP (result)))
10212 /* if they in different places then copy */
10213 size = AOP_SIZE (result);
10218 aopGet (right, offset, FALSE, FALSE),
10220 isOperandVolatile (result, FALSE));
10227 /* if the result is of type pointer */
10228 if (IS_PTR (ctype))
10232 sym_link *type = operandType (right);
10233 sym_link *etype = getSpec (type);
10235 /* pointer to generic pointer */
10236 if (IS_GENPTR (ctype))
10239 p_type = DCL_TYPE (type);
10242 if (SPEC_SCLS(etype)==S_REGISTER) {
10243 // let's assume it is a generic pointer
10246 /* we have to go by the storage class */
10247 p_type = PTR_TYPE (SPEC_OCLS (etype));
10251 /* the first two bytes are known */
10252 size = GPTRSIZE - 1;
10257 aopGet (right, offset, FALSE, FALSE),
10259 isOperandVolatile (result, FALSE));
10262 /* the last byte depending on type */
10264 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10269 // pointerTypeToGPByte will have bitched.
10273 sprintf(gpValStr, "#0x%x", gpVal);
10274 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10279 /* just copy the pointers */
10280 size = AOP_SIZE (result);
10285 aopGet (right, offset, FALSE, FALSE),
10287 isOperandVolatile (result, FALSE));
10293 /* so we now know that the size of destination is greater
10294 than the size of the source */
10295 /* we move to result for the size of source */
10296 size = AOP_SIZE (right);
10301 aopGet (right, offset, FALSE, FALSE),
10303 isOperandVolatile (result, FALSE));
10307 /* now depending on the sign of the source && destination */
10308 size = AOP_SIZE (result) - AOP_SIZE (right);
10309 /* if unsigned or not an integral type */
10310 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10313 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10317 /* we need to extend the sign :{ */
10318 char *l = aopGet (right, AOP_SIZE (right) - 1,
10321 emitcode ("rlc", "a");
10322 emitcode ("subb", "a,acc");
10324 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10327 /* we are done hurray !!!! */
10330 freeAsmop (right, NULL, ic, TRUE);
10331 freeAsmop (result, NULL, ic, TRUE);
10335 /*-----------------------------------------------------------------*/
10336 /* genDjnz - generate decrement & jump if not zero instrucion */
10337 /*-----------------------------------------------------------------*/
10339 genDjnz (iCode * ic, iCode * ifx)
10341 symbol *lbl, *lbl1;
10345 D(emitcode ("; genDjnz",""));
10347 /* if the if condition has a false label
10348 then we cannot save */
10349 if (IC_FALSE (ifx))
10352 /* if the minus is not of the form
10354 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10355 !IS_OP_LITERAL (IC_RIGHT (ic)))
10358 if (operandLitValue (IC_RIGHT (ic)) != 1)
10361 /* if the size of this greater than one then no
10363 if (getSize (operandType (IC_RESULT (ic))) > 1)
10366 /* otherwise we can save BIG */
10367 lbl = newiTempLabel (NULL);
10368 lbl1 = newiTempLabel (NULL);
10370 aopOp (IC_RESULT (ic), ic, FALSE);
10372 if (AOP_NEEDSACC(IC_RESULT(ic)))
10374 /* If the result is accessed indirectly via
10375 * the accumulator, we must explicitly write
10376 * it back after the decrement.
10378 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10380 if (strcmp(rByte, "a"))
10382 /* Something is hopelessly wrong */
10383 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10384 __FILE__, __LINE__);
10385 /* We can just give up; the generated code will be inefficient,
10386 * but what the hey.
10388 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10391 emitcode ("dec", "%s", rByte);
10392 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10393 emitcode ("jnz", "%05d$", lbl->key + 100);
10395 else if (IS_AOP_PREG (IC_RESULT (ic)))
10397 emitcode ("dec", "%s",
10398 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10399 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10400 emitcode ("jnz", "%05d$", lbl->key + 100);
10404 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10407 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10408 emitcode ("", "%05d$:", lbl->key + 100);
10409 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10410 emitcode ("", "%05d$:", lbl1->key + 100);
10412 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10413 ifx->generated = 1;
10417 /*-----------------------------------------------------------------*/
10418 /* genReceive - generate code for a receive iCode */
10419 /*-----------------------------------------------------------------*/
10421 genReceive (iCode * ic)
10423 int size = getSize (operandType (IC_RESULT (ic)));
10425 D(emitcode ("; genReceive",""));
10427 if (ic->argreg == 1) { /* first parameter */
10428 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10429 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10430 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10433 int receivingA = 0;
10436 for (offset = 0; offset<size; offset++)
10437 if (!strcmp (fReturn[offset], "a"))
10442 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10444 for (offset = size-1; offset>0; offset--)
10445 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10446 emitcode("mov","a,%s", fReturn[0]);
10448 aopOp (IC_RESULT (ic), ic, FALSE);
10450 aopPut (IC_RESULT (ic), "a", offset,
10451 isOperandVolatile (IC_RESULT (ic), FALSE));
10452 for (offset = 1; offset<size; offset++)
10453 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10454 isOperandVolatile (IC_RESULT (ic), FALSE));
10460 if (getTempRegs(tempRegs, size, ic))
10462 for (offset = 0; offset<size; offset++)
10463 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10464 aopOp (IC_RESULT (ic), ic, FALSE);
10465 for (offset = 0; offset<size; offset++)
10466 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10467 isOperandVolatile (IC_RESULT (ic), FALSE));
10472 offset = fReturnSizeMCS51 - size;
10474 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10475 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10478 aopOp (IC_RESULT (ic), ic, FALSE);
10479 size = AOP_SIZE (IC_RESULT (ic));
10482 emitcode ("pop", "acc");
10483 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10488 aopOp (IC_RESULT (ic), ic, FALSE);
10490 assignResultValue (IC_RESULT (ic));
10492 } else { /* second receive onwards */
10494 aopOp (IC_RESULT (ic), ic, FALSE);
10495 rb1off = ic->argreg;
10497 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10502 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10505 /*-----------------------------------------------------------------*/
10506 /* genDummyRead - generate code for dummy read of volatiles */
10507 /*-----------------------------------------------------------------*/
10509 genDummyRead (iCode * ic)
10514 D(emitcode("; genDummyRead",""));
10516 op = IC_RIGHT (ic);
10517 if (op && IS_SYMOP (op))
10519 aopOp (op, ic, FALSE);
10521 /* if the result is a bit */
10522 if (AOP_TYPE (op) == AOP_CRY)
10523 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10526 /* bit variables done */
10528 size = AOP_SIZE (op);
10532 MOVA (aopGet (op, offset, FALSE, FALSE));
10537 freeAsmop (op, NULL, ic, TRUE);
10541 if (op && IS_SYMOP (op))
10543 aopOp (op, ic, FALSE);
10545 /* if the result is a bit */
10546 if (AOP_TYPE (op) == AOP_CRY)
10547 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10550 /* bit variables done */
10552 size = AOP_SIZE (op);
10556 MOVA (aopGet (op, offset, FALSE, FALSE));
10561 freeAsmop (op, NULL, ic, TRUE);
10565 /*-----------------------------------------------------------------*/
10566 /* genCritical - generate code for start of a critical sequence */
10567 /*-----------------------------------------------------------------*/
10569 genCritical (iCode *ic)
10571 symbol *tlbl = newiTempLabel (NULL);
10573 D(emitcode("; genCritical",""));
10575 if (IC_RESULT (ic))
10577 aopOp (IC_RESULT (ic), ic, TRUE);
10578 aopPut (IC_RESULT (ic), one, 0, 0);
10579 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10580 aopPut (IC_RESULT (ic), zero, 0, 0);
10581 emitcode ("", "%05d$:", (tlbl->key + 100));
10582 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10586 emitcode ("setb", "c");
10587 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10588 emitcode ("clr", "c");
10589 emitcode ("", "%05d$:", (tlbl->key + 100));
10590 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10594 /*-----------------------------------------------------------------*/
10595 /* genEndCritical - generate code for end of a critical sequence */
10596 /*-----------------------------------------------------------------*/
10598 genEndCritical (iCode *ic)
10600 D(emitcode("; genEndCritical",""));
10604 aopOp (IC_RIGHT (ic), ic, FALSE);
10605 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10607 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10608 emitcode ("mov", "ea,c");
10612 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10613 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10614 emitcode ("rrc", "a");
10615 emitcode ("mov", "ea,c");
10617 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10621 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10622 emitcode ("mov", "ea,c");
10626 /*-----------------------------------------------------------------*/
10627 /* gen51Code - generate code for 8051 based controllers */
10628 /*-----------------------------------------------------------------*/
10630 gen51Code (iCode * lic)
10634 /* int cseq = 0; */
10636 _G.currentFunc = NULL;
10637 lineHead = lineCurr = NULL;
10639 /* print the allocation information */
10640 if (allocInfo && currFunc)
10641 printAllocInfo (currFunc, codeOutFile);
10642 /* if debug information required */
10643 if (options.debug && currFunc)
10645 debugFile->writeFunction (currFunc, lic);
10647 /* stack pointer name */
10648 if (options.useXstack)
10654 for (ic = lic; ic; ic = ic->next)
10656 _G.current_iCode = ic;
10658 if (ic->lineno && cln != ic->lineno)
10662 debugFile->writeCLine (ic);
10664 if (!options.noCcodeInAsm) {
10665 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10666 printCLine(ic->filename, ic->lineno));
10671 if (ic->seqPoint && ic->seqPoint != cseq)
10673 emitcode ("", "; sequence point %d", ic->seqPoint);
10674 cseq = ic->seqPoint;
10677 if (options.iCodeInAsm) {
10678 char regsInUse[80];
10681 for (i=0; i<8; i++) {
10682 sprintf (®sInUse[i],
10683 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10686 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10688 /* if the result is marked as
10689 spilt and rematerializable or code for
10690 this has already been generated then
10692 if (resultRemat (ic) || ic->generated)
10695 /* depending on the operation */
10715 /* IPOP happens only when trying to restore a
10716 spilt live range, if there is an ifx statement
10717 following this pop then the if statement might
10718 be using some of the registers being popped which
10719 would destory the contents of the register so
10720 we need to check for this condition and handle it */
10722 ic->next->op == IFX &&
10723 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10724 genIfx (ic->next, ic);
10742 genEndFunction (ic);
10762 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10779 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10783 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10790 /* note these two are xlated by algebraic equivalence
10791 during parsing SDCC.y */
10792 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10793 "got '>=' or '<=' shouldn't have come here");
10797 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10809 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10813 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10817 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10841 genRightShift (ic);
10844 case GET_VALUE_AT_ADDRESS:
10846 hasInc (IC_LEFT (ic), ic,
10847 getSize (operandType (IC_RESULT (ic)))),
10848 ifxForOp (IC_RESULT (ic), ic) );
10852 if (POINTER_SET (ic))
10853 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10879 addSet (&_G.sendSet, ic);
10882 case DUMMY_READ_VOLATILE:
10891 genEndCritical (ic);
10903 _G.current_iCode = NULL;
10905 /* now we are ready to call the
10906 peep hole optimizer */
10907 if (!options.nopeep)
10908 peepHole (&lineHead);
10910 /* now do the actual printing */
10911 printLine (lineHead, codeOutFile);