1 /*-------------------------------------------------------------------------
2 gen.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 REG_WITH_INDEX mcs51_regWithIdx
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74 AOP_TYPE(x) == AOP_R0))
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
77 AOP_TYPE(x) == AOP_DPTR || \
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
81 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86 #define R0INB _G.bu.bs.r0InB
87 #define R1INB _G.bu.bs.r1InB
88 #define OPINB _G.bu.bs.OpInB
89 #define BINUSE _G.bu.BInUse
99 short r0InB : 2;//2 so we can see it overflow
100 short r1InB : 2;//2 so we can see it overflow
101 short OpInB : 2;//2 so we can see it overflow
110 iCode *current_iCode;
115 static char *rb1regs[] = {
116 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (char *inst, const char *fmt,...)
155 char lb[INITIAL_INLINEASM];
164 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
168 SNPRINTF (lb, sizeof(lb), "%s", inst);
171 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
175 tvsprintf (lb, sizeof(lb), fmt, ap);
178 while (isspace ((unsigned char)*lbp))
185 lineCurr = (lineCurr ?
186 connectLine (lineCurr, newLineNode (lb)) :
187 (lineHead = newLineNode (lb)));
190 lineCurr->isInline = _G.inLine;
191 lineCurr->isDebug = _G.debugLine;
192 lineCurr->ic = _G.current_iCode;
193 lineCurr->isComment = (*lbp==';');
198 emitLabel (symbol *tlbl)
200 emitcode ("", "%05d$:", tlbl->key + 100);
201 lineCurr->isLabel = 1;
204 /*-----------------------------------------------------------------*/
205 /* mcs51_emitDebuggerSymbol - associate the current code location */
206 /* with a debugger symbol */
207 /*-----------------------------------------------------------------*/
209 mcs51_emitDebuggerSymbol (char * debugSym)
212 emitcode ("", "%s ==.", debugSym);
216 /*-----------------------------------------------------------------*/
217 /* mova - moves specified value into accumulator */
218 /*-----------------------------------------------------------------*/
222 /* do some early peephole optimization */
223 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
226 emitcode("mov", "a,%s", x);
229 /*-----------------------------------------------------------------*/
230 /* movb - moves specified value into register b */
231 /*-----------------------------------------------------------------*/
235 /* do some early peephole optimization */
236 if (!strncmp(x, "b", 2))
239 emitcode("mov","b,%s", x);
242 /*-----------------------------------------------------------------*/
243 /* movc - moves specified value into the carry */
244 /*-----------------------------------------------------------------*/
248 if (!strcmp (s, zero))
250 else if (!strcmp (s, one))
252 else if (strcmp (s, "c"))
253 {/* it's not in carry already */
255 /* set C, if a >= 1 */
256 emitcode ("add", "a,#0xff");
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerialzes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic)) {
732 sym_link *from_type = operandType(IC_RIGHT(ic));
733 aop->aopu.aop_immd.from_cast_remat = 1;
734 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
735 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
739 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
744 SNPRINTF (buffer, sizeof(buffer),
746 OP_SYMBOL (IC_LEFT (ic))->rname,
747 val >= 0 ? '+' : '-',
752 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
755 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
756 /* set immd2 field if required */
757 if (aop->aopu.aop_immd.from_cast_remat)
759 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
760 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
766 /*-----------------------------------------------------------------*/
767 /* regsInCommon - two operands have some registers in common */
768 /*-----------------------------------------------------------------*/
770 regsInCommon (operand * op1, operand * op2)
775 /* if they have registers in common */
776 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
779 sym1 = OP_SYMBOL (op1);
780 sym2 = OP_SYMBOL (op2);
782 if (sym1->nRegs == 0 || sym2->nRegs == 0)
785 for (i = 0; i < sym1->nRegs; i++)
791 for (j = 0; j < sym2->nRegs; j++)
796 if (sym2->regs[j] == sym1->regs[i])
804 /*-----------------------------------------------------------------*/
805 /* operandsEqu - equivalent */
806 /*-----------------------------------------------------------------*/
808 operandsEqu (operand * op1, operand * op2)
812 /* if they're not symbols */
813 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
816 sym1 = OP_SYMBOL (op1);
817 sym2 = OP_SYMBOL (op2);
819 /* if both are itemps & one is spilt
820 and the other is not then false */
821 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
822 sym1->isspilt != sym2->isspilt)
825 /* if they are the same */
829 /* if they have the same rname */
830 if (sym1->rname[0] && sym2->rname[0] &&
831 strcmp (sym1->rname, sym2->rname) == 0 &&
832 !(IS_PARM (op2) && IS_ITEMP (op1)))
835 /* if left is a tmp & right is not */
836 if (IS_ITEMP (op1) &&
839 (sym1->usl.spillLoc == sym2))
842 if (IS_ITEMP (op2) &&
846 (sym2->usl.spillLoc == sym1))
852 /*-----------------------------------------------------------------*/
853 /* sameByte - two asmops have the same address at given offsets */
854 /*-----------------------------------------------------------------*/
856 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
858 if (aop1 == aop2 && off1 == off2)
861 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
864 if (aop1->type != aop2->type)
867 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
873 /*-----------------------------------------------------------------*/
874 /* sameRegs - two asmops have the same registers */
875 /*-----------------------------------------------------------------*/
877 sameRegs (asmop * aop1, asmop * aop2)
884 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
887 if (aop1->type != aop2->type)
890 if (aop1->size != aop2->size)
893 for (i = 0; i < aop1->size; i++)
894 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand : */
902 /*-----------------------------------------------------------------*/
904 aopOp (operand * op, iCode * ic, bool result)
913 /* if this a literal */
914 if (IS_OP_LITERAL (op))
916 op->aop = aop = newAsmop (AOP_LIT);
917 aop->aopu.aop_lit = op->operand.valOperand;
918 aop->size = getSize (operandType (op));
922 /* if already has a asmop then continue */
925 op->aop->allocated++;
929 /* if the underlying symbol has a aop */
930 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
932 op->aop = OP_SYMBOL (op)->aop;
933 op->aop->allocated++;
937 /* if this is a true symbol */
938 if (IS_TRUE_SYMOP (op))
940 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
944 /* this is a temporary : this has
950 e) can be a return use only */
952 sym = OP_SYMBOL (op);
954 /* if the type is a conditional */
955 if (sym->regType == REG_CND)
957 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
962 /* if it is spilt then two situations
964 b) has a spill location */
965 if (sym->isspilt || sym->nRegs == 0)
968 /* rematerialize it NOW */
971 sym->aop = op->aop = aop = aopForRemat (sym);
972 aop->size = getSize (sym->type);
979 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
980 aop->size = getSize (sym->type);
981 for (i = 0; i < 2; i++)
982 aop->aopu.aop_str[i] = accUse[i];
990 aop = op->aop = sym->aop = newAsmop (AOP_STR);
991 aop->size = getSize (sym->type);
992 for (i = 0; i < fReturnSizeMCS51; i++)
993 aop->aopu.aop_str[i] = fReturn[i];
997 if (sym->usl.spillLoc)
999 asmop *oldAsmOp = NULL;
1001 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1003 /* force a new aop if sizes differ */
1004 oldAsmOp = sym->usl.spillLoc->aop;
1005 sym->usl.spillLoc->aop = NULL;
1007 sym->aop = op->aop = aop =
1008 aopForSym (ic, sym->usl.spillLoc, result);
1009 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1011 /* Don't reuse the new aop, go with the last one */
1012 sym->usl.spillLoc->aop = oldAsmOp;
1014 aop->size = getSize (sym->type);
1018 /* else must be a dummy iTemp */
1019 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020 aop->size = getSize (sym->type);
1024 /* if the type is a bit register */
1025 if (sym->regType == REG_BIT)
1027 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028 aop->size = sym->nRegs;//1???
1029 aop->aopu.aop_reg[0] = sym->regs[0];
1030 aop->aopu.aop_dir = sym->regs[0]->name;
1034 /* must be in a register */
1035 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036 aop->size = sym->nRegs;
1037 for (i = 0; i < sym->nRegs; i++)
1038 aop->aopu.aop_reg[i] = sym->regs[i];
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand */
1043 /*----------------------------------------------------------------*/
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1062 /* depending on the asmop type only three cases need work
1063 AOP_R0, AOP_R1 & AOP_STK */
1069 emitcode ("mov", "r0,b");
1072 else if (_G.r0Pushed)
1076 emitcode ("pop", "ar0");
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1086 emitcode ("mov", "r1,b");
1089 else if (_G.r1Pushed)
1093 emitcode ("pop", "ar1");
1097 bitVectUnSetBit (ic->rUsed, R1_IDX);
1103 int stk = aop->aopu.aop_stk + aop->size - 1;
1104 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 getFreePtr (ic, &aop, FALSE);
1111 emitcode ("mov", "a,_bp");
1112 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1117 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122 emitcode ("pop", "acc");
1123 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1129 freeAsmop (op, NULL, ic, TRUE);
1132 emitcode ("pop", "ar1");
1137 emitcode ("pop", "ar0");
1145 /* all other cases just dealloc */
1151 OP_SYMBOL (op)->aop = NULL;
1152 /* if the symbol has a spill */
1154 SPIL_LOC (op)->aop = NULL;
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /* pop r0 or r1 off stack if pushed */
1162 /*------------------------------------------------------------------*/
1164 freeForBranchAsmop (operand * op)
1176 if (!aop->allocated)
1184 emitcode ("mov", "r0,b");
1186 else if (_G.r0Pushed)
1188 emitcode ("pop", "ar0");
1195 emitcode ("mov", "r1,b");
1197 else if (_G.r1Pushed)
1199 emitcode ("pop", "ar1");
1206 int stk = aop->aopu.aop_stk + aop->size - 1;
1208 emitcode ("mov", "b,r0");
1211 emitcode ("mov", "a,_bp");
1212 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213 emitcode ("mov", "r0,a");
1217 emitcode ("mov", "r0,_bp");
1222 emitcode ("pop", "acc");
1223 emitcode ("mov", "@r0,a");
1226 emitcode ("dec", "r0");
1228 emitcode ("mov", "r0,b");
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1236 /* clobber the accumulator */
1237 /*-----------------------------------------------------------------*/
1239 aopGetUsesAcc (operand * oper, int offset)
1241 asmop * aop = AOP (oper);
1243 if (offset > (aop->size - 1))
1261 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1272 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1278 /* Error case --- will have been caught already */
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop */
1286 /*-------------------------------------------------------------------*/
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1290 asmop * aop = AOP (oper);
1292 /* offset is greater than
1294 if (offset > (aop->size - 1) &&
1295 aop->type != AOP_LIT)
1298 /* depending on type */
1306 /* if we need to increment it */
1307 while (offset > aop->coff)
1309 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1313 while (offset < aop->coff)
1315 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1322 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323 return (dname ? "acc" : "a");
1325 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326 return Safe_strdup(buffer);
1329 if (aop->code && aop->coff==0 && offset>=1) {
1330 emitcode ("mov", "a,#0x%02x", offset);
1331 emitcode ("movc", "a,@a+dptr");
1332 return (dname ? "acc" : "a");
1335 while (offset > aop->coff)
1337 emitcode ("inc", "dptr");
1341 while (offset < aop->coff)
1343 emitcode ("lcall", "__decdptr");
1350 emitcode ("clr", "a");
1351 emitcode ("movc", "a,@a+dptr");
1355 emitcode ("movx", "a,@dptr");
1357 return (dname ? "acc" : "a");
1360 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s",aop->aopu.aop_immd.aop_immd2);
1367 SNPRINTF(buffer, sizeof(buffer),
1368 "#%s", aop->aopu.aop_immd.aop_immd1);
1372 SNPRINTF (buffer, sizeof(buffer),
1374 aop->aopu.aop_immd.aop_immd1,
1379 SNPRINTF (buffer, sizeof(buffer),
1381 aop->aopu.aop_immd.aop_immd1);
1383 return Safe_strdup(buffer);
1386 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1388 SNPRINTF (buffer, sizeof(buffer),
1390 aop->aopu.aop_dir, offset * 8);
1394 SNPRINTF (buffer, sizeof(buffer),
1401 SNPRINTF (buffer, sizeof(buffer),
1406 return Safe_strdup(buffer);
1410 return aop->aopu.aop_reg[offset]->dname;
1412 return aop->aopu.aop_reg[offset]->name;
1415 emitcode ("clr", "a");
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("rlc", "a");
1418 return (dname ? "acc" : "a");
1421 if (!offset && dname)
1423 return aop->aopu.aop_str[offset];
1426 return aopLiteral (aop->aopu.aop_lit, offset);
1430 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1434 return aop->aopu.aop_str[offset];
1438 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439 "aopget got unsupported aop->type");
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1445 /* clobber the accumulator */
1446 /*-----------------------------------------------------------------*/
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1450 asmop * aop = AOP (oper);
1452 if (offset > (aop->size - 1))
1462 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1468 return ((aop->paged) || (*s == '@'));
1472 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1480 /* Error case --- will have been caught already */
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1490 aopPut (operand * result, const char *s, int offset)
1492 bool bvolatile = isOperandVolatile (result, FALSE);
1493 bool accuse = FALSE;
1494 asmop * aop = AOP (result);
1496 if (aop->size && offset > (aop->size - 1))
1498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499 "aopPut got offset > aop->size");
1503 /* will assign value to value */
1504 /* depending on where it is ofcourse */
1508 MOVA (s); /* read s in case it was volatile */
1513 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1515 SNPRINTF (buffer, sizeof(buffer),
1517 aop->aopu.aop_dir, offset * 8);
1521 SNPRINTF (buffer, sizeof(buffer),
1523 aop->aopu.aop_dir, offset);
1527 SNPRINTF (buffer, sizeof(buffer),
1532 if (strcmp (buffer, s) || bvolatile)
1534 emitcode ("mov", "%s,%s", buffer, s);
1536 if (!strcmp (buffer, "acc"))
1543 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1547 strcmp (s, "r0") == 0 ||
1548 strcmp (s, "r1") == 0 ||
1549 strcmp (s, "r2") == 0 ||
1550 strcmp (s, "r3") == 0 ||
1551 strcmp (s, "r4") == 0 ||
1552 strcmp (s, "r5") == 0 ||
1553 strcmp (s, "r6") == 0 ||
1554 strcmp (s, "r7") == 0)
1556 emitcode ("mov", "%s,%s",
1557 aop->aopu.aop_reg[offset]->dname, s);
1561 emitcode ("mov", "%s,%s",
1562 aop->aopu.aop_reg[offset]->name, s);
1570 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571 "aopPut writing to code space");
1575 while (offset > aop->coff)
1578 emitcode ("inc", "dptr");
1581 while (offset < aop->coff)
1584 emitcode ("lcall", "__decdptr");
1589 /* if not in accumulator */
1592 emitcode ("movx", "@dptr,a");
1597 while (offset > aop->coff)
1600 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1602 while (offset < aop->coff)
1605 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1612 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1617 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1619 else if (strcmp (s, "r0") == 0 ||
1620 strcmp (s, "r1") == 0 ||
1621 strcmp (s, "r2") == 0 ||
1622 strcmp (s, "r3") == 0 ||
1623 strcmp (s, "r4") == 0 ||
1624 strcmp (s, "r5") == 0 ||
1625 strcmp (s, "r6") == 0 ||
1626 strcmp (s, "r7") == 0)
1629 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630 emitcode ("mov", "@%s,%s",
1631 aop->aopu.aop_ptr->name, buffer);
1635 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1640 if (strcmp (s, "a") == 0)
1641 emitcode ("push", "acc");
1645 emitcode ("push", "acc");
1647 emitcode ("push", s);
1653 /* if not bit variable */
1654 if (!aop->aopu.aop_dir)
1656 /* inefficient: move carry into A and use jz/jnz */
1657 emitcode ("clr", "a");
1658 emitcode ("rlc", "a");
1664 emitcode ("clr", "%s", aop->aopu.aop_dir);
1666 emitcode ("setb", "%s", aop->aopu.aop_dir);
1667 else if (!strcmp (s, "c"))
1668 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669 else if (strcmp (s, aop->aopu.aop_dir))
1672 /* set C, if a >= 1 */
1673 emitcode ("add", "a,#0xff");
1674 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1681 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1688 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1691 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697 "aopPut got unsupported aop->type");
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand */
1708 /*-----------------------------------------------------------------*/
1710 pointToEnd (asmop * aop)
1716 aop->coff = count = (aop->size - 1);
1722 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1726 emitcode ("inc", "dptr");
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should */
1735 /*-----------------------------------------------------------------*/
1737 reAdjustPreg (asmop * aop)
1739 if ((aop->coff==0) || (aop->size <= 1))
1747 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1752 emitcode ("lcall", "__decdptr");
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is */
1761 /* a generic pointer type. */
1762 /*-----------------------------------------------------------------*/
1764 opIsGptr (operand * op)
1766 sym_link *type = operandType (op);
1768 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size */
1777 /*-----------------------------------------------------------------*/
1779 getDataSize (operand * op)
1782 size = AOP_SIZE (op);
1783 if (size == GPTRSIZE)
1785 sym_link *type = operandType (op);
1786 if (IS_GENPTR (type))
1788 /* generic pointer; arithmetic operations
1789 * should ignore the high byte (pointer type).
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc */
1799 /*-----------------------------------------------------------------*/
1801 outAcc (operand * result)
1804 size = getDataSize (result);
1807 aopPut (result, "a", 0);
1810 /* unsigned or positive */
1813 aopPut (result, zero, offset++);
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C */
1820 /*-----------------------------------------------------------------*/
1822 outBitC (operand * result)
1824 /* if the result is bit */
1825 if (AOP_TYPE (result) == AOP_CRY)
1827 aopPut (result, "c", 0);
1831 emitcode ("clr", "a");
1832 emitcode ("rlc", "a");
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop) */
1839 /*-----------------------------------------------------------------*/
1841 toBoolean (operand * oper)
1843 int size = AOP_SIZE (oper) - 1;
1845 bool AccUsed = FALSE;
1848 while (!AccUsed && size--)
1850 AccUsed |= aopGetUsesAcc(oper, offset++);
1853 size = AOP_SIZE (oper) - 1;
1855 MOVA (aopGet (oper, 0, FALSE, FALSE));
1856 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1859 emitcode("mov", "b,a");
1862 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863 emitcode ("orl", "b,a");
1865 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866 emitcode ("orl", "a,b");
1873 emitcode ("orl", "a,%s",
1874 aopGet (oper, offset++, FALSE, FALSE));
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop */
1882 /*-------------------------------------------------------------------*/
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1888 if (aopGetUsesAcc (oper, offset))
1890 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset, bit16, dname));
1892 emitcode("xch", "a,b");
1893 aopPut (oper, "a", offset);
1894 emitcode("xch", "a,b");
1899 l = aopGet (oper, offset, bit16, dname);
1900 emitcode("xch", "a,%s", l);
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation */
1908 /*-----------------------------------------------------------------*/
1914 D (emitcode (";", "genNot"));
1916 /* assign asmOps to operand & result */
1917 aopOp (IC_LEFT (ic), ic, FALSE);
1918 aopOp (IC_RESULT (ic), ic, TRUE);
1920 /* if in bit space then a special case */
1921 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1923 /* if left==result then cpl bit */
1924 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1926 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1930 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931 emitcode ("cpl", "c");
1932 outBitC (IC_RESULT (ic));
1937 toBoolean (IC_LEFT (ic));
1939 /* set C, if a == 0 */
1940 tlbl = newiTempLabel (NULL);
1941 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1943 outBitC (IC_RESULT (ic));
1946 /* release the aops */
1947 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement */
1954 /*-----------------------------------------------------------------*/
1961 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1963 D(emitcode (";", "genCpl"));
1965 /* assign asmOps to operand & result */
1966 aopOp (IC_LEFT (ic), ic, FALSE);
1967 aopOp (IC_RESULT (ic), ic, TRUE);
1969 /* special case if in bit space */
1970 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1974 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1977 /* promotion rules are responsible for this strange result:
1978 bit -> int -> ~int -> bit
1979 uchar -> int -> ~int -> bit
1981 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1985 tlbl=newiTempLabel(NULL);
1986 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989 IS_AOP_PREG (IC_LEFT (ic)))
1991 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1996 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1999 outBitC (IC_RESULT(ic));
2003 size = AOP_SIZE (IC_RESULT (ic));
2006 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2008 emitcode ("cpl", "a");
2009 aopPut (IC_RESULT (ic), "a", offset++);
2014 /* release the aops */
2015 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2019 /*-----------------------------------------------------------------*/
2020 /* genUminusFloat - unary minus for floating points */
2021 /*-----------------------------------------------------------------*/
2023 genUminusFloat (operand * op, operand * result)
2025 int size, offset = 0;
2028 D (emitcode (";", "genUminusFloat"));
2030 /* for this we just copy and then flip the bit */
2032 size = AOP_SIZE (op) - 1;
2037 aopGet (op, offset, FALSE, FALSE),
2042 l = aopGet (op, offset, FALSE, FALSE);
2045 emitcode ("cpl", "acc.7");
2046 aopPut (result, "a", offset);
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation */
2051 /*-----------------------------------------------------------------*/
2053 genUminus (iCode * ic)
2058 D (emitcode (";", "genUminus"));
2061 aopOp (IC_LEFT (ic), ic, FALSE);
2062 aopOp (IC_RESULT (ic), ic, TRUE);
2064 /* if both in bit space then special
2066 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2070 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071 emitcode ("cpl", "c");
2072 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2076 optype = operandType (IC_LEFT (ic));
2078 /* if float then do float stuff */
2079 if (IS_FLOAT (optype))
2081 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2085 /* otherwise subtract from zero */
2086 size = AOP_SIZE (IC_LEFT (ic));
2090 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091 if (!strcmp (l, "a"))
2095 emitcode ("cpl", "a");
2096 emitcode ("addc", "a,#0");
2102 emitcode ("clr", "a");
2103 emitcode ("subb", "a,%s", l);
2105 aopPut (IC_RESULT (ic), "a", offset++);
2108 /* if any remaining bytes in the result */
2109 /* we just need to propagate the sign */
2110 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2112 emitcode ("rlc", "a");
2113 emitcode ("subb", "a,acc");
2115 aopPut (IC_RESULT (ic), "a", offset++);
2119 /* release the aops */
2120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers */
2126 /*-----------------------------------------------------------------*/
2128 saveRegisters (iCode * lic)
2135 for (ic = lic; ic; ic = ic->next)
2136 if (ic->op == CALL || ic->op == PCALL)
2141 fprintf (stderr, "found parameter push with no function call\n");
2145 /* if the registers have been saved already or don't need to be then
2149 if (IS_SYMOP(IC_LEFT(ic)) &&
2150 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2154 /* save the registers in use at this time but skip the
2155 ones for the result */
2156 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157 mcs51_rUmaskForOp (IC_RESULT(ic)));
2160 if (options.useXstack)
2162 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163 int nBits = bitVectnBitsOn (rsavebits);
2164 int count = bitVectnBitsOn (rsave);
2168 count = count - nBits + 1;
2169 /* remove all but the first bits as they are pushed all at once */
2170 rsave = bitVectCplAnd (rsave, rsavebits);
2171 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2176 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177 if (reg->type == REG_BIT)
2179 emitcode ("mov", "a,%s", reg->base);
2183 emitcode ("mov", "a,%s", reg->name);
2185 emitcode ("mov", "r0,%s", spname);
2186 emitcode ("inc", "%s", spname);// allocate before use
2187 emitcode ("movx", "@r0,a");
2188 if (bitVectBitValue (rsave, R0_IDX))
2189 emitcode ("mov", "r0,a");
2191 else if (count != 0)
2193 if (bitVectBitValue (rsave, R0_IDX))
2195 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2197 emitcode ("mov", "r0,%s", spname);
2199 emitcode ("add", "a,#%d", count);
2200 emitcode ("mov", "%s,a", spname);
2201 for (i = 0; i < mcs51_nRegs; i++)
2203 if (bitVectBitValue (rsave, i))
2205 regs * reg = REG_WITH_INDEX (i);
2208 emitcode ("pop", "acc");
2209 emitcode ("push", "acc");
2211 else if (reg->type == REG_BIT)
2213 emitcode ("mov", "a,%s", reg->base);
2217 emitcode ("mov", "a,%s", reg->name);
2219 emitcode ("movx", "@r0,a");
2222 emitcode ("inc", "r0");
2226 if (bitVectBitValue (rsave, R0_IDX))
2228 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2234 bool bits_pushed = FALSE;
2235 for (i = 0; i < mcs51_nRegs; i++)
2237 if (bitVectBitValue (rsave, i))
2239 bits_pushed = pushReg (i, bits_pushed);
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers */
2247 /*-----------------------------------------------------------------*/
2249 unsaveRegisters (iCode * ic)
2254 /* restore the registers in use at this time but skip the
2255 ones for the result */
2256 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257 mcs51_rUmaskForOp (IC_RESULT(ic)));
2259 if (options.useXstack)
2261 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262 int nBits = bitVectnBitsOn (rsavebits);
2263 int count = bitVectnBitsOn (rsave);
2267 count = count - nBits + 1;
2268 /* remove all but the first bits as they are popped all at once */
2269 rsave = bitVectCplAnd (rsave, rsavebits);
2270 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2275 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276 emitcode ("mov", "r0,%s", spname);
2277 emitcode ("dec", "r0");
2278 emitcode ("movx", "a,@r0");
2279 if (reg->type == REG_BIT)
2281 emitcode ("mov", "%s,a", reg->base);
2285 emitcode ("mov", "%s,a", reg->name);
2287 emitcode ("dec", "%s", spname);
2289 else if (count != 0)
2291 emitcode ("mov", "r0,%s", spname);
2292 for (i = mcs51_nRegs; i >= 0; i--)
2294 if (bitVectBitValue (rsave, i))
2296 regs * reg = REG_WITH_INDEX (i);
2297 emitcode ("dec", "r0");
2298 emitcode ("movx", "a,@r0");
2301 emitcode ("push", "acc");
2303 else if (reg->type == REG_BIT)
2305 emitcode ("mov", "%s,a", reg->base);
2309 emitcode ("mov", "%s,a", reg->name);
2313 emitcode ("mov", "%s,r0", spname);
2314 if (bitVectBitValue (rsave, R0_IDX))
2316 emitcode ("pop", "ar0");
2322 bool bits_popped = FALSE;
2323 for (i = mcs51_nRegs; i >= 0; i--)
2325 if (bitVectBitValue (rsave, i))
2327 bits_popped = popReg (i, bits_popped);
2334 /*-----------------------------------------------------------------*/
2336 /*-----------------------------------------------------------------*/
2338 pushSide (operand * oper, int size)
2343 char *l = aopGet (oper, offset++, FALSE, TRUE);
2344 if (AOP_TYPE (oper) != AOP_REG &&
2345 AOP_TYPE (oper) != AOP_DIR &&
2349 emitcode ("push", "acc");
2353 emitcode ("push", "%s", l);
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards */
2360 /*-----------------------------------------------------------------*/
2362 assignResultValue (operand * oper, operand * func)
2365 int size = AOP_SIZE (oper);
2366 bool accuse = FALSE;
2367 bool pushedA = FALSE;
2369 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2375 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2377 emitcode ("push", "acc");
2382 if ((offset == 3) && pushedA)
2383 emitcode ("pop", "acc");
2384 accuse |= aopPut (oper, fReturn[offset], offset);
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack */
2393 /*-----------------------------------------------------------------*/
2395 genXpush (iCode * ic)
2397 asmop *aop = newAsmop (0);
2399 int size, offset = 0;
2401 D (emitcode (";", "genXpush"));
2403 aopOp (IC_LEFT (ic), ic, FALSE);
2404 r = getFreePtr (ic, &aop, FALSE);
2406 size = AOP_SIZE (IC_LEFT (ic));
2410 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411 emitcode ("mov", "%s,%s", r->name, spname);
2412 emitcode ("inc", "%s", spname); // allocate space first
2413 emitcode ("movx", "@%s,a", r->name);
2417 // allocate space first
2418 emitcode ("mov", "%s,%s", r->name, spname);
2420 emitcode ("add", "a,#%d", size);
2421 emitcode ("mov", "%s,a", spname);
2425 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426 emitcode ("movx", "@%s,a", r->name);
2427 emitcode ("inc", "%s", r->name);
2431 freeAsmop (NULL, aop, ic, TRUE);
2432 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2439 genIpush (iCode * ic)
2441 int size, offset = 0;
2445 D (emitcode (";", "genIpush"));
2447 /* if this is not a parm push : ie. it is spill push
2448 and spill push is always done on the local stack */
2452 /* and the item is spilt then do nothing */
2453 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2456 aopOp (IC_LEFT (ic), ic, FALSE);
2457 size = AOP_SIZE (IC_LEFT (ic));
2458 /* push it on the stack */
2461 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2467 emitcode ("push", "%s", l);
2472 /* this is a parameter push: in this case we call
2473 the routine to find the call and save those
2474 registers that need to be saved */
2477 /* if use external stack then call the external
2478 stack pushing routine */
2479 if (options.useXstack)
2485 /* then do the push */
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2488 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489 size = AOP_SIZE (IC_LEFT (ic));
2493 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2497 if (strcmp (l, prev) || *l == '@')
2499 emitcode ("push", "acc");
2503 emitcode ("push", "%s", l);
2508 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling */
2513 /*-----------------------------------------------------------------*/
2515 genIpop (iCode * ic)
2519 D (emitcode (";", "genIpop"));
2521 /* if the temp was not pushed then */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2527 offset = (size - 1);
2530 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2534 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack */
2539 /*-----------------------------------------------------------------*/
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2544 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2548 if (options.useXstack)
2552 /* Assume r0 is available for use. */
2553 r = REG_WITH_INDEX (R0_IDX);;
2558 r = getFreePtr (ic, &aop, FALSE);
2560 // allocate space first
2561 emitcode ("mov", "%s,%s", r->name, spname);
2563 emitcode ("add", "a,#%d", count);
2564 emitcode ("mov", "%s,a", spname);
2567 for (i = 0; i < 8; i++)
2569 if (options.useXstack)
2571 emitcode ("mov", "a,(%s+%d)",
2572 regs8051[i].base, 8 * bank + regs8051[i].offset);
2573 emitcode ("movx", "@%s,a", r->name);
2575 emitcode ("inc", "%s", r->name);
2578 emitcode ("push", "(%s+%d)",
2579 regs8051[i].base, 8 * bank + regs8051[i].offset);
2582 if (mcs51_nRegs > 8)
2584 if (options.useXstack)
2586 emitcode ("mov", "a,bits");
2587 emitcode ("movx", "@%s,a", r->name);
2589 emitcode ("inc", "%s", r->name);
2593 emitcode ("push", "bits");
2600 if (options.useXstack)
2602 emitcode ("mov", "a,psw");
2603 emitcode ("movx", "@%s,a", r->name);
2607 emitcode ("push", "psw");
2610 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2615 freeAsmop (NULL, aop, ic, TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack */
2626 /*-----------------------------------------------------------------*/
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2634 if (options.useXstack)
2638 /* Assume r0 is available for use. */
2639 r = REG_WITH_INDEX (R0_IDX);;
2644 r = getFreePtr (ic, &aop, FALSE);
2646 emitcode ("mov", "%s,%s", r->name, spname);
2651 if (options.useXstack)
2653 emitcode ("dec", "%s", r->name);
2654 emitcode ("movx", "a,@%s", r->name);
2655 emitcode ("mov", "psw,a");
2659 emitcode ("pop", "psw");
2663 if (mcs51_nRegs > 8)
2665 if (options.useXstack)
2667 emitcode ("dec", "%s", r->name);
2668 emitcode ("movx", "a,@%s", r->name);
2669 emitcode ("mov", "bits,a");
2673 emitcode ("pop", "bits");
2677 for (i = 7; i >= 0; i--)
2679 if (options.useXstack)
2681 emitcode ("dec", "%s", r->name);
2682 emitcode ("movx", "a,@%s", r->name);
2683 emitcode ("mov", "(%s+%d),a",
2684 regs8051[i].base, 8 * bank + regs8051[i].offset);
2688 emitcode ("pop", "(%s+%d)",
2689 regs8051[i].base, 8 * bank + regs8051[i].offset);
2693 if (options.useXstack)
2695 emitcode ("mov", "%s,%s", spname, r->name);
2700 freeAsmop (NULL, aop, ic, TRUE);
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2712 /* first we do all bit parameters */
2713 for (sic = setFirstItem (sendSet); sic;
2714 sic = setNextItem (sendSet))
2716 if (sic->argreg > 12)
2718 int bit = sic->argreg-13;
2720 aopOp (IC_LEFT (sic), sic, FALSE);
2722 /* if left is a literal then
2723 we know what the value is */
2724 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2726 if (((int) operandLitValue (IC_LEFT (sic))))
2727 emitcode ("setb", "b[%d]", bit);
2729 emitcode ("clr", "b[%d]", bit);
2731 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2733 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734 if (strcmp (l, "c"))
2735 emitcode ("mov", "c,%s", l);
2736 emitcode ("mov", "b[%d],c", bit);
2741 toBoolean (IC_LEFT (sic));
2742 /* set C, if a >= 1 */
2743 emitcode ("add", "a,#0xff");
2744 emitcode ("mov", "b[%d],c", bit);
2749 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2755 saveRegisters (setFirstItem (sendSet));
2756 emitcode ("mov", "bits,b");
2759 /* then we do all other parameters */
2760 for (sic = setFirstItem (sendSet); sic;
2761 sic = setNextItem (sendSet))
2763 if (sic->argreg <= 12)
2765 int size, offset = 0;
2766 aopOp (IC_LEFT (sic), sic, FALSE);
2767 size = AOP_SIZE (IC_LEFT (sic));
2769 if (sic->argreg == 1)
2773 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774 if (strcmp (l, fReturn[offset]))
2776 emitcode ("mov", "%s,%s", fReturn[offset], l);
2785 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2790 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank */
2797 /*-----------------------------------------------------------------*/
2799 selectRegBank (short bank, bool keepFlags)
2801 /* if f.e. result is in carry */
2804 emitcode ("anl", "psw,#0xE7");
2806 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2810 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement */
2816 /*-----------------------------------------------------------------*/
2818 genCall (iCode * ic)
2822 // bool restoreBank = FALSE;
2823 bool swapBanks = FALSE;
2824 bool accuse = FALSE;
2825 bool accPushed = FALSE;
2826 bool resultInF0 = FALSE;
2827 bool assignResultGenerated = FALSE;
2829 D (emitcode (";", "genCall"));
2831 dtype = operandType (IC_LEFT (ic));
2832 etype = getSpec(dtype);
2833 /* if send set is not empty then assign */
2836 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837 genSend(reverseSet(_G.sendSet));
2839 genSend(_G.sendSet);
2844 /* if we are calling a not _naked function that is not using
2845 the same register bank then we need to save the
2846 destination registers on the stack */
2847 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849 !IFFUNC_ISISR (dtype))
2854 /* if caller saves & we have not saved then */
2860 emitcode ("mov", "psw,#0x%02x",
2861 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2865 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2867 if (IFFUNC_CALLEESAVES(dtype))
2869 werror (E_BANKED_WITH_CALLEESAVES);
2873 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874 OP_SYMBOL (IC_LEFT (ic))->rname :
2875 OP_SYMBOL (IC_LEFT (ic))->name);
2877 emitcode ("mov", "r0,#%s", l);
2878 emitcode ("mov", "r1,#(%s >> 8)", l);
2879 emitcode ("mov", "r2,#(%s >> 16)", l);
2880 emitcode ("lcall", "__sdcc_banked_call");
2885 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886 OP_SYMBOL (IC_LEFT (ic))->rname :
2887 OP_SYMBOL (IC_LEFT (ic))->name));
2892 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2895 /* if we need assign a result value */
2896 if ((IS_ITEMP (IC_RESULT (ic)) &&
2897 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901 IS_TRUE_SYMOP (IC_RESULT (ic)))
2905 aopOp (IC_RESULT (ic), ic, FALSE);
2908 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909 assignResultGenerated = TRUE;
2911 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2914 /* adjust the stack for parameters if required */
2918 if (ic->parmBytes > 3)
2922 emitcode ("push", "acc");
2925 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927 !assignResultGenerated)
2929 emitcode ("mov", "F0,c");
2933 emitcode ("mov", "a,%s", spname);
2934 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935 emitcode ("mov", "%s,a", spname);
2937 /* unsaveRegisters from xstack needs acc, but */
2938 /* unsaveRegisters from stack needs this popped */
2939 if (accPushed && !options.useXstack)
2941 emitcode ("pop", "acc");
2946 for (i = 0; i < ic->parmBytes; i++)
2947 emitcode ("dec", "%s", spname);
2950 /* if we had saved some registers then unsave them */
2951 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2953 if (accuse && !accPushed && options.useXstack)
2955 /* xstack needs acc, but doesn't touch normal stack */
2956 emitcode ("push", "acc");
2959 unsaveRegisters (ic);
2962 // /* if register bank was saved then pop them */
2964 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2966 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2969 emitcode ("mov", "c,F0");
2971 aopOp (IC_RESULT (ic), ic, FALSE);
2972 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2977 emitcode ("pop", "acc");
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement */
2982 /*-----------------------------------------------------------------*/
2984 genPcall (iCode * ic)
2988 symbol *rlbl = newiTempLabel (NULL);
2989 // bool restoreBank=FALSE;
2990 bool swapBanks = FALSE;
2991 bool resultInF0 = FALSE;
2993 D (emitcode (";", "genPcall"));
2995 dtype = operandType (IC_LEFT (ic))->next;
2996 etype = getSpec(dtype);
2997 /* if caller saves & we have not saved then */
3001 /* if we are calling a not _naked function that is not using
3002 the same register bank then we need to save the
3003 destination registers on the stack */
3004 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006 !IFFUNC_ISISR (dtype))
3008 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 // restoreBank=TRUE;
3011 // need caution message to user here
3014 if (IS_LITERAL(etype))
3016 /* if send set is not empty then assign */
3019 genSend(reverseSet(_G.sendSet));
3025 emitcode ("mov", "psw,#0x%02x",
3026 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3029 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3031 if (IFFUNC_CALLEESAVES(dtype))
3033 werror (E_BANKED_WITH_CALLEESAVES);
3037 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3039 emitcode ("mov", "r0,#%s", l);
3040 emitcode ("mov", "r1,#(%s >> 8)", l);
3041 emitcode ("mov", "r2,#(%s >> 16)", l);
3042 emitcode ("lcall", "__sdcc_banked_call");
3047 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3052 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3054 if (IFFUNC_CALLEESAVES(dtype))
3056 werror (E_BANKED_WITH_CALLEESAVES);
3060 aopOp (IC_LEFT (ic), ic, FALSE);
3064 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3070 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3078 /* if send set is not empty then assign */
3081 genSend(reverseSet(_G.sendSet));
3087 emitcode ("mov", "psw,#0x%02x",
3088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3092 emitcode ("lcall", "__sdcc_banked_call");
3097 /* push the return address on to the stack */
3098 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099 emitcode ("push", "acc");
3100 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101 emitcode ("push", "acc");
3103 /* now push the calling address */
3104 aopOp (IC_LEFT (ic), ic, FALSE);
3106 pushSide (IC_LEFT (ic), FPTRSIZE);
3108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3110 /* if send set is not empty the assign */
3113 genSend(reverseSet(_G.sendSet));
3119 emitcode ("mov", "psw,#0x%02x",
3120 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3124 emitcode ("ret", "");
3130 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3133 /* if we need assign a result value */
3134 if ((IS_ITEMP (IC_RESULT (ic)) &&
3135 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138 IS_TRUE_SYMOP (IC_RESULT (ic)))
3142 aopOp (IC_RESULT (ic), ic, FALSE);
3145 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3147 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3150 /* adjust the stack for parameters if required */
3154 if (ic->parmBytes > 3)
3156 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3159 emitcode ("mov", "F0,c");
3163 emitcode ("mov", "a,%s", spname);
3164 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165 emitcode ("mov", "%s,a", spname);
3168 for (i = 0; i < ic->parmBytes; i++)
3169 emitcode ("dec", "%s", spname);
3172 // /* if register bank was saved then unsave them */
3174 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3176 /* if we had saved some registers then unsave them */
3177 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178 unsaveRegisters (ic);
3180 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3183 emitcode ("mov", "c,F0");
3185 aopOp (IC_RESULT (ic), ic, FALSE);
3186 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result is rematerializable */
3193 /*-----------------------------------------------------------------*/
3195 resultRemat (iCode * ic)
3197 if (SKIP_IC (ic) || ic->op == IFX)
3200 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3202 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203 if (sym->remat && !POINTER_SET (ic))
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3213 #define STRCASECMP strcasecmp
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list */
3218 /*-----------------------------------------------------------------*/
3220 regsCmp(void *p1, void *p2)
3222 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3226 inExcludeList (char *s)
3228 const char *p = setFirstItem(options.excludeRegsSet);
3230 if (p == NULL || STRCASECMP(p, "none") == 0)
3234 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry */
3239 /*-----------------------------------------------------------------*/
3241 genFunction (iCode * ic)
3243 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3245 bool switchedPSW = FALSE;
3246 int calleesaves_saved_register = -1;
3247 int stackAdjust = sym->stack;
3248 int accIsFree = sym->recvSize < 4;
3249 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3253 /* create the function header */
3254 emitcode (";", "-----------------------------------------");
3255 emitcode (";", " function %s", sym->name);
3256 emitcode (";", "-----------------------------------------");
3258 emitcode ("", "%s:", sym->rname);
3259 lineCurr->isLabel = 1;
3260 ftype = operandType (IC_LEFT (ic));
3261 _G.currentFunc = sym;
3263 if (IFFUNC_ISNAKED(ftype))
3265 emitcode(";", "naked function: no prologue.");
3269 /* here we need to generate the equates for the
3270 register bank if required */
3271 if (FUNC_REGBANK (ftype) != rbank)
3275 rbank = FUNC_REGBANK (ftype);
3276 for (i = 0; i < mcs51_nRegs; i++)
3278 if (regs8051[i].type != REG_BIT)
3280 if (strcmp (regs8051[i].base, "0") == 0)
3281 emitcode ("", "%s = 0x%02x",
3283 8 * rbank + regs8051[i].offset);
3285 emitcode ("", "%s = %s + 0x%02x",
3288 8 * rbank + regs8051[i].offset);
3293 /* if this is an interrupt service routine then
3294 save acc, b, dpl, dph */
3295 if (IFFUNC_ISISR (sym->type))
3297 if (!inExcludeList ("acc"))
3298 emitcode ("push", "acc");
3299 if (!inExcludeList ("b"))
3300 emitcode ("push", "b");
3301 if (!inExcludeList ("dpl"))
3302 emitcode ("push", "dpl");
3303 if (!inExcludeList ("dph"))
3304 emitcode ("push", "dph");
3305 /* if this isr has no bank i.e. is going to
3306 run with bank 0 , then we need to save more
3308 if (!FUNC_REGBANK (sym->type))
3312 /* if this function does not call any other
3313 function then we can be economical and
3314 save only those registers that are used */
3315 if (!IFFUNC_HASFCALL(sym->type))
3317 /* if any registers used */
3320 bool bits_pushed = FALSE;
3321 /* save the registers used */
3322 for (i = 0; i < sym->regsUsed->size; i++)
3324 if (bitVectBitValue (sym->regsUsed, i))
3325 bits_pushed = pushReg (i, bits_pushed);
3331 /* this function has a function call. We cannot
3332 determine register usage so we will have to push the
3334 saveRBank (0, ic, FALSE);
3335 if (options.parms_in_bank1) {
3336 for (i=0; i < 8 ; i++ ) {
3337 emitcode ("push","%s",rb1regs[i]);
3344 /* This ISR uses a non-zero bank.
3346 * We assume that the bank is available for our
3349 * However, if this ISR calls a function which uses some
3350 * other bank, we must save that bank entirely.
3352 unsigned long banksToSave = 0;
3354 if (IFFUNC_HASFCALL(sym->type))
3357 #define MAX_REGISTER_BANKS 4
3362 for (i = ic; i; i = i->next)
3364 if (i->op == ENDFUNCTION)
3366 /* we got to the end OK. */
3374 dtype = operandType (IC_LEFT(i));
3376 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3378 /* Mark this bank for saving. */
3379 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3381 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3385 banksToSave |= (1 << FUNC_REGBANK(dtype));
3388 /* And note that we don't need to do it in
3396 /* This is a mess; we have no idea what
3397 * register bank the called function might
3400 * The only thing I can think of to do is
3401 * throw a warning and hope.
3403 werror(W_FUNCPTR_IN_USING_ISR);
3407 if (banksToSave && options.useXstack)
3409 /* Since we aren't passing it an ic,
3410 * saveRBank will assume r0 is available to abuse.
3412 * So switch to our (trashable) bank now, so
3413 * the caller's R0 isn't trashed.
3415 emitcode ("push", "psw");
3416 emitcode ("mov", "psw,#0x%02x",
3417 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3421 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3423 if (banksToSave & (1 << ix))
3425 saveRBank(ix, NULL, FALSE);
3429 // TODO: this needs a closer look
3430 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3433 /* Set the register bank to the desired value if nothing else */
3434 /* has done so yet. */
3437 emitcode ("push", "psw");
3438 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3443 /* This is a non-ISR function. The caller has already switched register */
3444 /* banks, if necessary, so just handle the callee-saves option. */
3446 /* if callee-save to be used for this function
3447 then save the registers being used in this function */
3448 if (IFFUNC_CALLEESAVES(sym->type))
3452 /* if any registers used */
3455 bool bits_pushed = FALSE;
3456 /* save the registers used */
3457 for (i = 0; i < sym->regsUsed->size; i++)
3459 if (bitVectBitValue (sym->regsUsed, i))
3461 /* remember one saved register for later usage */
3462 if (calleesaves_saved_register < 0)
3463 calleesaves_saved_register = i;
3464 bits_pushed = pushReg (i, bits_pushed);
3474 if (options.useXstack)
3476 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3478 emitcode ("mov", "r0,%s", spname);
3479 emitcode ("inc", "%s", spname);
3480 emitcode ("xch", "a,_bpx");
3481 emitcode ("movx", "@r0,a");
3482 emitcode ("inc", "r0");
3483 emitcode ("mov", "a,r0");
3484 emitcode ("xch", "a,_bpx");
3488 emitcode ("push", "_bp"); /* save the callers stack */
3489 emitcode ("mov", "_bp,sp");
3494 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3496 /* set up the stack */
3497 emitcode ("push", "_bp"); /* save the callers stack */
3498 emitcode ("mov", "_bp,sp");
3503 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3504 /* before setting up the stack frame completely. */
3505 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3507 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3511 if (rsym && rsym->regType == REG_CND)
3513 if (rsym && (rsym->accuse || rsym->ruonly))
3515 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3516 rsym = rsym->usl.spillLoc;
3519 /* If the RECEIVE operand immediately spills to the first entry on the */
3520 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3521 /* rather than the usual @r0/r1 machinations. */
3522 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3526 _G.current_iCode = ric;
3527 D(emitcode ("; genReceive",""));
3528 for (ofs=0; ofs < sym->recvSize; ofs++)
3530 if (!strcmp (fReturn[ofs], "a"))
3531 emitcode ("push", "acc");
3533 emitcode ("push", fReturn[ofs]);
3535 stackAdjust -= sym->recvSize;
3538 assert (stackAdjust>=0);
3541 _G.current_iCode = ic;
3545 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3546 /* to free up the accumulator. */
3547 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3551 _G.current_iCode = ric;
3552 D(emitcode ("; genReceive",""));
3553 for (ofs=0; ofs < sym->recvSize; ofs++)
3555 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3557 _G.current_iCode = ic;
3563 /* adjust the stack for the function */
3566 int i = stackAdjust;
3568 werror (W_STACK_OVERFLOW, sym->name);
3570 if (i > 3 && accIsFree)
3572 emitcode ("mov", "a,sp");
3573 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3574 emitcode ("mov", "sp,a");
3578 /* The accumulator is not free, so we will need another register */
3579 /* to clobber. No need to worry about a possible conflict with */
3580 /* the above early RECEIVE optimizations since they would have */
3581 /* freed the accumulator if they were generated. */
3583 if (IFFUNC_CALLEESAVES(sym->type))
3585 /* if it's a callee-saves function we need a saved register */
3586 if (calleesaves_saved_register >= 0)
3588 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3589 emitcode ("mov", "a,sp");
3590 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3591 emitcode ("mov", "sp,a");
3592 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3595 /* do it the hard way */
3597 emitcode ("inc", "sp");
3601 /* not callee-saves, we can clobber r0 */
3602 emitcode ("mov", "r0,a");
3603 emitcode ("mov", "a,sp");
3604 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3605 emitcode ("mov", "sp,a");
3606 emitcode ("mov", "a,r0");
3611 emitcode ("inc", "sp");
3616 char i = ((char) sym->xstack & 0xff);
3618 if (i > 3 && accIsFree)
3620 emitcode ("mov", "a,_spx");
3621 emitcode ("add", "a,#0x%02x", i & 0xff);
3622 emitcode ("mov", "_spx,a");
3626 emitcode ("push", "acc");
3627 emitcode ("mov", "a,_spx");
3628 emitcode ("add", "a,#0x%02x", i & 0xff);
3629 emitcode ("mov", "_spx,a");
3630 emitcode ("pop", "acc");
3635 emitcode ("inc", "_spx");
3639 /* if critical function then turn interrupts off */
3640 if (IFFUNC_ISCRITICAL (ftype))
3642 symbol *tlbl = newiTempLabel (NULL);
3643 emitcode ("setb", "c");
3644 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3645 emitcode ("clr", "c");
3647 emitcode ("push", "psw"); /* save old ea via c in psw */
3651 /*-----------------------------------------------------------------*/
3652 /* genEndFunction - generates epilogue for functions */
3653 /*-----------------------------------------------------------------*/
3655 genEndFunction (iCode * ic)
3657 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3658 lineNode *lnp = lineCurr;
3660 bitVect *regsUsedPrologue;
3661 bitVect *regsUnneeded;
3664 _G.currentFunc = NULL;
3665 if (IFFUNC_ISNAKED(sym->type))
3667 emitcode(";", "naked function: no epilogue.");
3668 if (options.debug && currFunc)
3669 debugFile->writeEndFunction (currFunc, ic, 0);
3673 if (IFFUNC_ISCRITICAL (sym->type))
3675 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3677 emitcode ("rlc", "a"); /* save c in a */
3678 emitcode ("pop", "psw"); /* restore ea via c in psw */
3679 emitcode ("mov", "ea,c");
3680 emitcode ("rrc", "a"); /* restore c from a */
3684 emitcode ("pop", "psw"); /* restore ea via c in psw */
3685 emitcode ("mov", "ea,c");
3689 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3691 if (options.useXstack)
3695 emitcode ("mov", "sp,_bp");
3696 emitcode ("pop", "_bp");
3698 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3700 emitcode ("xch", "a,_bpx");
3701 emitcode ("mov", "r0,a");
3702 emitcode ("dec", "r0");
3703 emitcode ("movx", "a,@r0");
3704 emitcode ("xch", "a,_bpx");
3705 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3708 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3711 emitcode ("mov", "sp,_bp");
3712 emitcode ("pop", "_bp");
3716 /* restore the register bank */
3717 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3719 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3720 || !options.useXstack)
3722 /* Special case of ISR using non-zero bank with useXstack
3725 emitcode ("pop", "psw");
3729 if (IFFUNC_ISISR (sym->type))
3732 /* now we need to restore the registers */
3733 /* if this isr has no bank i.e. is going to
3734 run with bank 0 , then we need to save more
3736 if (!FUNC_REGBANK (sym->type))
3739 /* if this function does not call any other
3740 function then we can be economical and
3741 save only those registers that are used */
3742 if (!IFFUNC_HASFCALL(sym->type))
3744 /* if any registers used */
3747 bool bits_popped = FALSE;
3748 /* save the registers used */
3749 for (i = sym->regsUsed->size; i >= 0; i--)
3751 if (bitVectBitValue (sym->regsUsed, i))
3752 bits_popped = popReg (i, bits_popped);
3758 if (options.parms_in_bank1) {
3759 for (i = 7 ; i >= 0 ; i-- ) {
3760 emitcode ("pop","%s",rb1regs[i]);
3763 /* this function has a function call cannot
3764 determines register usage so we will have to pop the
3766 unsaveRBank (0, ic, FALSE);
3771 /* This ISR uses a non-zero bank.
3773 * Restore any register banks saved by genFunction
3776 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3779 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3781 if (savedBanks & (1 << ix))
3783 unsaveRBank(ix, NULL, FALSE);
3787 if (options.useXstack)
3789 /* Restore bank AFTER calling unsaveRBank,
3790 * since it can trash r0.
3792 emitcode ("pop", "psw");
3796 if (!inExcludeList ("dph"))
3797 emitcode ("pop", "dph");
3798 if (!inExcludeList ("dpl"))
3799 emitcode ("pop", "dpl");
3800 if (!inExcludeList ("b"))
3801 emitcode ("pop", "b");
3802 if (!inExcludeList ("acc"))
3803 emitcode ("pop", "acc");
3805 /* if debug then send end of function */
3806 if (options.debug && currFunc)
3808 debugFile->writeEndFunction (currFunc, ic, 1);
3811 emitcode ("reti", "");
3815 if (IFFUNC_CALLEESAVES(sym->type))
3819 /* if any registers used */
3822 /* save the registers used */
3823 for (i = sym->regsUsed->size; i >= 0; i--)
3825 if (bitVectBitValue (sym->regsUsed, i) ||
3826 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3827 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3830 else if (mcs51_ptrRegReq)
3832 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3833 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3838 /* if debug then send end of function */
3839 if (options.debug && currFunc)
3841 debugFile->writeEndFunction (currFunc, ic, 1);
3844 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3846 emitcode ("ljmp", "__sdcc_banked_ret");
3850 emitcode ("ret", "");
3854 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3857 /* If this was an interrupt handler using bank 0 that called another */
3858 /* function, then all registers must be saved; nothing to optimized. */
3859 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3860 && !FUNC_REGBANK(sym->type))
3863 /* There are no push/pops to optimize if not callee-saves or ISR */
3864 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3867 /* If there were stack parameters, we cannot optimize without also */
3868 /* fixing all of the stack offsets; this is too dificult to consider. */
3869 if (FUNC_HASSTACKPARM(sym->type))
3872 /* Compute the registers actually used */
3873 regsUsed = newBitVect (mcs51_nRegs);
3874 regsUsedPrologue = newBitVect (mcs51_nRegs);
3877 if (lnp->ic && lnp->ic->op == FUNCTION)
3878 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3880 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3882 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3883 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3890 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3891 && !bitVectBitValue (regsUsed, CND_IDX))
3893 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3894 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3895 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3896 bitVectUnSetBit (regsUsed, CND_IDX);
3899 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3901 /* If this was an interrupt handler that called another function */
3902 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3903 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3905 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3906 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3907 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3908 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3909 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3912 /* Remove the unneeded push/pops */
3913 regsUnneeded = newBitVect (mcs51_nRegs);
3916 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3918 if (!strncmp(lnp->line, "push", 4))
3920 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3921 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3923 connectLine (lnp->prev, lnp->next);
3924 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3927 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3929 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3930 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3932 connectLine (lnp->prev, lnp->next);
3933 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3940 for (idx = 0; idx < regsUnneeded->size; idx++)
3941 if (bitVectBitValue (regsUnneeded, idx))
3942 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3944 freeBitVect (regsUnneeded);
3945 freeBitVect (regsUsed);
3946 freeBitVect (regsUsedPrologue);
3949 /*-----------------------------------------------------------------*/
3950 /* genRet - generate code for return statement */
3951 /*-----------------------------------------------------------------*/
3955 int size, offset = 0, pushed = 0;
3957 D (emitcode (";", "genRet"));
3959 /* if we have no return value then
3960 just generate the "ret" */
3964 /* we have something to return then
3965 move the return value into place */
3966 aopOp (IC_LEFT (ic), ic, FALSE);
3967 size = AOP_SIZE (IC_LEFT (ic));
3969 if (IS_BIT(_G.currentFunc->etype))
3971 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3978 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3981 l = aopGet (IC_LEFT (ic), offset++,
3983 emitcode ("push", "%s", l);
3988 l = aopGet (IC_LEFT (ic), offset,
3990 if (strcmp (fReturn[offset], l))
3991 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3998 if (strcmp (fReturn[pushed], "a"))
3999 emitcode ("pop", fReturn[pushed]);
4001 emitcode ("pop", "acc");
4003 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4006 /* generate a jump to the return label
4007 if the next is not the return statement */
4008 if (!(ic->next && ic->next->op == LABEL &&
4009 IC_LABEL (ic->next) == returnLabel))
4011 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4015 /*-----------------------------------------------------------------*/
4016 /* genLabel - generates a label */
4017 /*-----------------------------------------------------------------*/
4019 genLabel (iCode * ic)
4021 /* special case never generate */
4022 if (IC_LABEL (ic) == entryLabel)
4025 emitLabel (IC_LABEL (ic));
4028 /*-----------------------------------------------------------------*/
4029 /* genGoto - generates a ljmp */
4030 /*-----------------------------------------------------------------*/
4032 genGoto (iCode * ic)
4034 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4037 /*-----------------------------------------------------------------*/
4038 /* findLabelBackwards: walks back through the iCode chain looking */
4039 /* for the given label. Returns number of iCode instructions */
4040 /* between that label and given ic. */
4041 /* Returns zero if label not found. */
4042 /*-----------------------------------------------------------------*/
4044 findLabelBackwards (iCode * ic, int key)
4053 /* If we have any pushes or pops, we cannot predict the distance.
4054 I don't like this at all, this should be dealt with in the
4056 if (ic->op == IPUSH || ic->op == IPOP) {
4060 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4069 /*-----------------------------------------------------------------*/
4070 /* genPlusIncr :- does addition with increment if possible */
4071 /*-----------------------------------------------------------------*/
4073 genPlusIncr (iCode * ic)
4075 unsigned int icount;
4076 unsigned int size = getDataSize (IC_RESULT (ic));
4078 /* will try to generate an increment */
4079 /* if the right side is not a literal
4081 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4084 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4086 D(emitcode (";","genPlusIncr"));
4088 /* if increment >=16 bits in register or direct space */
4089 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4090 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4091 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4092 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4093 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4101 /* If the next instruction is a goto and the goto target
4102 * is < 10 instructions previous to this, we can generate
4103 * jumps straight to that target.
4105 if (ic->next && ic->next->op == GOTO
4106 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4107 && labelRange <= 10)
4109 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4110 tlbl = IC_LABEL (ic->next);
4115 tlbl = newiTempLabel (NULL);
4118 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4119 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4120 IS_AOP_PREG (IC_RESULT (ic)))
4121 emitcode ("cjne", "%s,#0x00,%05d$",
4122 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4126 emitcode ("clr", "a");
4127 emitcode ("cjne", "a,%s,%05d$",
4128 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4132 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4135 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4136 IS_AOP_PREG (IC_RESULT (ic)))
4137 emitcode ("cjne", "%s,#0x00,%05d$",
4138 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4141 emitcode ("cjne", "a,%s,%05d$",
4142 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4145 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4149 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4150 IS_AOP_PREG (IC_RESULT (ic)))
4151 emitcode ("cjne", "%s,#0x00,%05d$",
4152 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4156 emitcode ("cjne", "a,%s,%05d$",
4157 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4160 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4170 /* if result is dptr */
4171 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4172 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4173 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4174 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4176 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4182 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4185 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4186 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4188 emitcode ("inc", "dptr");
4193 /* if the literal value of the right hand side
4194 is greater than 4 then it is not worth it */
4198 /* if the sizes are greater than 1 then we cannot */
4199 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4200 AOP_SIZE (IC_LEFT (ic)) > 1)
4203 /* we can if the aops of the left & result match or
4204 if they are in registers and the registers are the
4206 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4210 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4211 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4212 aopPut (IC_RESULT (ic), "a", 0);
4218 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4227 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4228 emitcode ("inc", "a");
4229 aopPut (IC_RESULT (ic), "a", 0);
4236 /*-----------------------------------------------------------------*/
4237 /* outBitAcc - output a bit in acc */
4238 /*-----------------------------------------------------------------*/
4240 outBitAcc (operand * result)
4242 symbol *tlbl = newiTempLabel (NULL);
4243 /* if the result is a bit */
4244 if (AOP_TYPE (result) == AOP_CRY)
4246 aopPut (result, "a", 0);
4250 emitcode ("jz", "%05d$", tlbl->key + 100);
4251 emitcode ("mov", "a,%s", one);
4257 /*-----------------------------------------------------------------*/
4258 /* genPlusBits - generates code for addition of two bits */
4259 /*-----------------------------------------------------------------*/
4261 genPlusBits (iCode * ic)
4263 D (emitcode (";", "genPlusBits"));
4265 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4267 symbol *lbl = newiTempLabel (NULL);
4268 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4269 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4270 emitcode ("cpl", "c");
4272 outBitC (IC_RESULT (ic));
4276 emitcode ("clr", "a");
4277 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4278 emitcode ("rlc", "a");
4279 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4280 emitcode ("addc", "a,%s", zero);
4281 outAcc (IC_RESULT (ic));
4286 /* This is the original version of this code.
4288 * This is being kept around for reference,
4289 * because I am not entirely sure I got it right...
4292 adjustArithmeticResult (iCode * ic)
4294 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4295 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4296 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4297 aopPut (IC_RESULT (ic),
4298 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4301 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4302 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4303 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4304 aopPut (IC_RESULT (ic),
4305 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4308 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4309 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4310 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4311 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4312 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4315 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4316 aopPut (IC_RESULT (ic), buffer, 2);
4320 /* This is the pure and virtuous version of this code.
4321 * I'm pretty certain it's right, but not enough to toss the old
4325 adjustArithmeticResult (iCode * ic)
4327 if (opIsGptr (IC_RESULT (ic)) &&
4328 opIsGptr (IC_LEFT (ic)) &&
4329 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4331 aopPut (IC_RESULT (ic),
4332 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4336 if (opIsGptr (IC_RESULT (ic)) &&
4337 opIsGptr (IC_RIGHT (ic)) &&
4338 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4340 aopPut (IC_RESULT (ic),
4341 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4345 if (opIsGptr (IC_RESULT (ic)) &&
4346 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4347 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4348 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4349 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4352 SNPRINTF (buffer, sizeof(buffer),
4353 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4354 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4359 /*-----------------------------------------------------------------*/
4360 /* genPlus - generates code for addition */
4361 /*-----------------------------------------------------------------*/
4363 genPlus (iCode * ic)
4365 int size, offset = 0;
4368 bool swappedLR = FALSE;
4369 operand *leftOp, *rightOp;
4372 D (emitcode (";", "genPlus"));
4374 /* special cases :- */
4376 aopOp (IC_LEFT (ic), ic, FALSE);
4377 aopOp (IC_RIGHT (ic), ic, FALSE);
4378 aopOp (IC_RESULT (ic), ic, TRUE);
4380 /* if literal, literal on the right or
4381 if left requires ACC or right is already
4383 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4384 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4385 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4387 operand *t = IC_RIGHT (ic);
4388 IC_RIGHT (ic) = IC_LEFT (ic);
4393 /* if both left & right are in bit
4395 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4396 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4402 /* if left in bit space & right literal */
4403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4404 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4406 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4407 /* if result in bit space */
4408 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4410 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4411 emitcode ("cpl", "c");
4412 outBitC (IC_RESULT (ic));
4416 size = getDataSize (IC_RESULT (ic));
4419 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4420 emitcode ("addc", "a,%s", zero);
4421 aopPut (IC_RESULT (ic), "a", offset++);
4427 /* if I can do an increment instead
4428 of add then GOOD for ME */
4429 if (genPlusIncr (ic) == TRUE)
4432 size = getDataSize (IC_RESULT (ic));
4433 leftOp = IC_LEFT(ic);
4434 rightOp = IC_RIGHT(ic);
4437 /* if this is an add for an array access
4438 at a 256 byte boundary */
4440 && AOP_TYPE (op) == AOP_IMMD
4442 && IS_SPEC (OP_SYM_ETYPE (op))
4443 && SPEC_ABSA (OP_SYM_ETYPE (op))
4444 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4447 D(emitcode ("; genPlus aligned array",""));
4448 aopPut (IC_RESULT (ic),
4449 aopGet (rightOp, 0, FALSE, FALSE),
4452 if( 1 == getDataSize (IC_RIGHT (ic)) )
4454 aopPut (IC_RESULT (ic),
4455 aopGet (leftOp, 1, FALSE, FALSE),
4460 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4461 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4462 aopPut (IC_RESULT (ic), "a", 1);
4467 /* if the lower bytes of a literal are zero skip the addition */
4468 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4470 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4471 (skip_bytes+1 < size))
4476 D(emitcode ("; genPlus shortcut",""));
4481 if( offset >= skip_bytes )
4483 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4486 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4488 emitcode("xch", "a,b");
4489 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490 emitcode (add, "a,b");
4493 else if (aopGetUsesAcc (leftOp, offset))
4495 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4496 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4500 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4501 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4503 aopPut (IC_RESULT (ic), "a", offset);
4504 add = "addc"; /* further adds must propagate carry */
4508 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4509 isOperandVolatile (IC_RESULT (ic), FALSE))
4512 aopPut (IC_RESULT (ic),
4513 aopGet (leftOp, offset, FALSE, FALSE),
4520 adjustArithmeticResult (ic);
4523 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4526 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4527 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4532 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536 /*-----------------------------------------------------------------*/
4537 /* genMinusDec :- does subtraction with decrement if possible */
4538 /*-----------------------------------------------------------------*/
4540 genMinusDec (iCode * ic)
4542 unsigned int icount;
4543 unsigned int size = getDataSize (IC_RESULT (ic));
4545 /* will try to generate an increment */
4546 /* if the right side is not a literal
4548 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4551 /* if the literal value of the right hand side
4552 is greater than 4 then it is not worth it */
4553 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4556 D (emitcode (";", "genMinusDec"));
4558 /* if decrement >=16 bits in register or direct space */
4559 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4560 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4561 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4562 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4570 /* If the next instruction is a goto and the goto target
4571 * is <= 10 instructions previous to this, we can generate
4572 * jumps straight to that target.
4574 if (ic->next && ic->next->op == GOTO
4575 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4576 && labelRange <= 10)
4578 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4579 tlbl = IC_LABEL (ic->next);
4584 tlbl = newiTempLabel (NULL);
4588 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4589 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4590 IS_AOP_PREG (IC_RESULT (ic)))
4591 emitcode ("cjne", "%s,#0xff,%05d$"
4592 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4596 emitcode ("mov", "a,#0xff");
4597 emitcode ("cjne", "a,%s,%05d$"
4598 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4601 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4604 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4605 IS_AOP_PREG (IC_RESULT (ic)))
4606 emitcode ("cjne", "%s,#0xff,%05d$"
4607 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4611 emitcode ("cjne", "a,%s,%05d$"
4612 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4615 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4619 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4620 IS_AOP_PREG (IC_RESULT (ic)))
4621 emitcode ("cjne", "%s,#0xff,%05d$"
4622 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4626 emitcode ("cjne", "a,%s,%05d$"
4627 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4630 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4639 /* if the sizes are greater than 1 then we cannot */
4640 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4641 AOP_SIZE (IC_LEFT (ic)) > 1)
4644 /* we can if the aops of the left & result match or
4645 if they are in registers and the registers are the
4647 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4651 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4653 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4658 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4663 emitcode ("dec", "%s", l);
4666 if (AOP_NEEDSACC (IC_RESULT (ic)))
4667 aopPut (IC_RESULT (ic), "a", 0);
4674 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4675 emitcode ("dec", "a");
4676 aopPut (IC_RESULT (ic), "a", 0);
4683 /*-----------------------------------------------------------------*/
4684 /* addSign - complete with sign */
4685 /*-----------------------------------------------------------------*/
4687 addSign (operand * result, int offset, int sign)
4689 int size = (getDataSize (result) - offset);
4694 emitcode ("rlc", "a");
4695 emitcode ("subb", "a,acc");
4698 aopPut (result, "a", offset++);
4705 aopPut (result, zero, offset++);
4711 /*-----------------------------------------------------------------*/
4712 /* genMinusBits - generates code for subtraction of two bits */
4713 /*-----------------------------------------------------------------*/
4715 genMinusBits (iCode * ic)
4717 symbol *lbl = newiTempLabel (NULL);
4719 D (emitcode (";", "genMinusBits"));
4721 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4723 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4724 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4725 emitcode ("cpl", "c");
4727 outBitC (IC_RESULT (ic));
4731 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4732 emitcode ("subb", "a,acc");
4733 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4734 emitcode ("inc", "a");
4736 aopPut (IC_RESULT (ic), "a", 0);
4737 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4741 /*-----------------------------------------------------------------*/
4742 /* genMinus - generates code for subtraction */
4743 /*-----------------------------------------------------------------*/
4745 genMinus (iCode * ic)
4747 int size, offset = 0;
4749 D (emitcode (";", "genMinus"));
4751 aopOp (IC_LEFT (ic), ic, FALSE);
4752 aopOp (IC_RIGHT (ic), ic, FALSE);
4753 aopOp (IC_RESULT (ic), ic, TRUE);
4755 /* special cases :- */
4756 /* if both left & right are in bit space */
4757 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4758 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4764 /* if I can do an decrement instead
4765 of subtract then GOOD for ME */
4766 if (genMinusDec (ic) == TRUE)
4769 size = getDataSize (IC_RESULT (ic));
4771 /* if literal, add a,#-lit, else normal subb */
4772 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4774 unsigned long lit = 0L;
4775 bool useCarry = FALSE;
4777 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4782 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4784 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4785 if (!offset && !size && lit== (unsigned long) -1)
4787 emitcode ("dec", "a");
4791 /* first add without previous c */
4792 emitcode ("add", "a,#0x%02x",
4793 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4798 emitcode ("addc", "a,#0x%02x",
4799 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4801 aopPut (IC_RESULT (ic), "a", offset++);
4805 /* no need to add zeroes */
4806 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4808 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4817 operand *leftOp, *rightOp;
4819 leftOp = IC_LEFT(ic);
4820 rightOp = IC_RIGHT(ic);
4824 if (aopGetUsesAcc(rightOp, offset)) {
4825 if (aopGetUsesAcc(leftOp, offset)) {
4828 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4830 emitcode ("mov", "b,a");
4833 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4834 emitcode ("subb", "a,b");
4837 /* reverse subtraction with 2's complement */
4839 emitcode( "setb", "c");
4841 emitcode( "cpl", "c");
4842 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4843 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4844 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4845 emitcode("cpl", "a");
4846 if (size) /* skip if last byte */
4847 emitcode( "cpl", "c");
4850 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4853 emitcode ("subb", "a,%s",
4854 aopGet(rightOp, offset, FALSE, TRUE));
4857 aopPut (IC_RESULT (ic), "a", offset++);
4861 adjustArithmeticResult (ic);
4864 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4865 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4870 /*-----------------------------------------------------------------*/
4871 /* genMultbits :- multiplication of bits */
4872 /*-----------------------------------------------------------------*/
4874 genMultbits (operand * left,
4878 D (emitcode (";", "genMultbits"));
4880 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4881 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4885 /*-----------------------------------------------------------------*/
4886 /* genMultOneByte : 8*8=8/16 bit multiplication */
4887 /*-----------------------------------------------------------------*/
4889 genMultOneByte (operand * left,
4894 int size = AOP_SIZE (result);
4895 bool runtimeSign, compiletimeSign;
4896 bool lUnsigned, rUnsigned, pushedB;
4898 D (emitcode (";", "genMultOneByte"));
4900 if (size < 1 || size > 2)
4902 /* this should never happen */
4903 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4904 AOP_SIZE(result), __FILE__, lineno);
4908 /* (if two literals: the value is computed before) */
4909 /* if one literal, literal on the right */
4910 if (AOP_TYPE (left) == AOP_LIT)
4915 /* emitcode (";", "swapped left and right"); */
4917 /* if no literal, unsigned on the right: shorter code */
4918 if ( AOP_TYPE (right) != AOP_LIT
4919 && SPEC_USIGN (getSpec (operandType (left))))
4926 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4927 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4931 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4932 no need to take care about the signedness! */
4933 || (lUnsigned && rUnsigned))
4935 /* just an unsigned 8 * 8 = 8 multiply
4937 /* emitcode (";","unsigned"); */
4938 /* TODO: check for accumulator clash between left & right aops? */
4940 if (AOP_TYPE (right) == AOP_LIT)
4942 /* moving to accumulator first helps peepholes */
4943 MOVA (aopGet (left, 0, FALSE, FALSE));
4944 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4948 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4949 MOVA (aopGet (left, 0, FALSE, FALSE));
4952 emitcode ("mul", "ab");
4953 aopPut (result, "a", 0);
4955 aopPut (result, "b", 1);
4961 /* we have to do a signed multiply */
4962 /* emitcode (";", "signed"); */
4964 /* now sign adjust for both left & right */
4966 /* let's see what's needed: */
4967 /* apply negative sign during runtime */
4968 runtimeSign = FALSE;
4969 /* negative sign from literals */
4970 compiletimeSign = FALSE;
4974 if (AOP_TYPE(left) == AOP_LIT)
4976 /* signed literal */
4977 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4979 compiletimeSign = TRUE;
4982 /* signed but not literal */
4988 if (AOP_TYPE(right) == AOP_LIT)
4990 /* signed literal */
4991 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4993 compiletimeSign ^= TRUE;
4996 /* signed but not literal */
5000 /* initialize F0, which stores the runtime sign */
5003 if (compiletimeSign)
5004 emitcode ("setb", "F0"); /* set sign flag */
5006 emitcode ("clr", "F0"); /* reset sign flag */
5009 /* save the signs of the operands */
5010 if (AOP_TYPE(right) == AOP_LIT)
5012 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5014 if (!rUnsigned && val < 0)
5015 emitcode ("mov", "b,#0x%02x", -val);
5017 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5019 else /* ! literal */
5021 if (rUnsigned) /* emitcode (";", "signed"); */
5022 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5025 MOVA (aopGet (right, 0, FALSE, FALSE));
5026 lbl = newiTempLabel (NULL);
5027 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5028 emitcode ("cpl", "F0"); /* complement sign flag */
5029 emitcode ("cpl", "a"); /* 2's complement */
5030 emitcode ("inc", "a");
5032 emitcode ("mov", "b,a");
5036 if (AOP_TYPE(left) == AOP_LIT)
5038 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5040 if (!lUnsigned && val < 0)
5041 emitcode ("mov", "a,#0x%02x", -val);
5043 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5045 else /* ! literal */
5047 MOVA (aopGet (left, 0, FALSE, FALSE));
5051 lbl = newiTempLabel (NULL);
5052 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5053 emitcode ("cpl", "F0"); /* complement sign flag */
5054 emitcode ("cpl", "a"); /* 2's complement */
5055 emitcode ("inc", "a");
5060 /* now the multiplication */
5061 emitcode ("mul", "ab");
5062 if (runtimeSign || compiletimeSign)
5064 lbl = newiTempLabel (NULL);
5066 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5067 emitcode ("cpl", "a"); /* lsb 2's complement */
5069 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5072 emitcode ("add", "a,#1"); /* this sets carry flag */
5073 emitcode ("xch", "a,b");
5074 emitcode ("cpl", "a"); /* msb 2's complement */
5075 emitcode ("addc", "a,#0");
5076 emitcode ("xch", "a,b");
5080 aopPut (result, "a", 0);
5082 aopPut (result, "b", 1);
5087 /*-----------------------------------------------------------------*/
5088 /* genMult - generates code for multiplication */
5089 /*-----------------------------------------------------------------*/
5091 genMult (iCode * ic)
5093 operand *left = IC_LEFT (ic);
5094 operand *right = IC_RIGHT (ic);
5095 operand *result = IC_RESULT (ic);
5097 D (emitcode (";", "genMult"));
5099 /* assign the asmops */
5100 aopOp (left, ic, FALSE);
5101 aopOp (right, ic, FALSE);
5102 aopOp (result, ic, TRUE);
5104 /* special cases first */
5106 if (AOP_TYPE (left) == AOP_CRY &&
5107 AOP_TYPE (right) == AOP_CRY)
5109 genMultbits (left, right, result);
5113 /* if both are of size == 1 */
5114 #if 0 // one of them can be a sloc shared with the result
5115 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5117 if (getSize(operandType(left)) == 1 &&
5118 getSize(operandType(right)) == 1)
5121 genMultOneByte (left, right, result);
5125 /* should have been converted to function call */
5126 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5127 getSize(OP_SYMBOL(right)->type));
5131 freeAsmop (result, NULL, ic, TRUE);
5132 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 /*-----------------------------------------------------------------*/
5137 /* genDivbits :- division of bits */
5138 /*-----------------------------------------------------------------*/
5140 genDivbits (operand * left,
5147 D(emitcode ("; genDivbits",""));
5151 /* the result must be bit */
5152 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5153 l = aopGet (left, 0, FALSE, FALSE);
5157 emitcode ("div", "ab");
5158 emitcode ("rrc", "a");
5162 aopPut (result, "c", 0);
5165 /*-----------------------------------------------------------------*/
5166 /* genDivOneByte : 8 bit division */
5167 /*-----------------------------------------------------------------*/
5169 genDivOneByte (operand * left,
5173 bool lUnsigned, rUnsigned, pushedB;
5174 bool runtimeSign, compiletimeSign;
5175 bool accuse = FALSE;
5176 bool pushedA = FALSE;
5180 D(emitcode ("; genDivOneByte",""));
5182 /* Why is it necessary that genDivOneByte() can return an int result?
5185 volatile unsigned char uc;
5186 volatile signed char sc1, sc2;
5199 In all cases a one byte result would overflow, the following cast to int
5200 would return the wrong result.
5202 Two possible solution:
5203 a) cast operands to int, if ((unsigned) / (signed)) or
5204 ((signed) / (signed))
5205 b) return an 16 bit signed int; this is what we're doing here!
5208 size = AOP_SIZE (result) - 1;
5210 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5211 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5215 /* signed or unsigned */
5216 if (lUnsigned && rUnsigned)
5218 /* unsigned is easy */
5219 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5220 MOVA (aopGet (left, 0, FALSE, FALSE));
5221 emitcode ("div", "ab");
5222 aopPut (result, "a", 0);
5224 aopPut (result, zero, offset++);
5230 /* signed is a little bit more difficult */
5232 /* now sign adjust for both left & right */
5234 /* let's see what's needed: */
5235 /* apply negative sign during runtime */
5236 runtimeSign = FALSE;
5237 /* negative sign from literals */
5238 compiletimeSign = FALSE;
5242 if (AOP_TYPE(left) == AOP_LIT)
5244 /* signed literal */
5245 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5247 compiletimeSign = TRUE;
5250 /* signed but not literal */
5256 if (AOP_TYPE(right) == AOP_LIT)
5258 /* signed literal */
5259 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5261 compiletimeSign ^= TRUE;
5264 /* signed but not literal */
5268 /* initialize F0, which stores the runtime sign */
5271 if (compiletimeSign)
5272 emitcode ("setb", "F0"); /* set sign flag */
5274 emitcode ("clr", "F0"); /* reset sign flag */
5277 /* save the signs of the operands */
5278 if (AOP_TYPE(right) == AOP_LIT)
5280 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5282 if (!rUnsigned && val < 0)
5283 emitcode ("mov", "b,#0x%02x", -val);
5285 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5287 else /* ! literal */
5290 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5293 MOVA (aopGet (right, 0, FALSE, FALSE));
5294 lbl = newiTempLabel (NULL);
5295 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5296 emitcode ("cpl", "F0"); /* complement sign flag */
5297 emitcode ("cpl", "a"); /* 2's complement */
5298 emitcode ("inc", "a");
5300 emitcode ("mov", "b,a");
5304 if (AOP_TYPE(left) == AOP_LIT)
5306 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5308 if (!lUnsigned && val < 0)
5309 emitcode ("mov", "a,#0x%02x", -val);
5311 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5313 else /* ! literal */
5315 MOVA (aopGet (left, 0, FALSE, FALSE));
5319 lbl = newiTempLabel (NULL);
5320 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5321 emitcode ("cpl", "F0"); /* complement sign flag */
5322 emitcode ("cpl", "a"); /* 2's complement */
5323 emitcode ("inc", "a");
5328 /* now the division */
5329 emitcode ("div", "ab");
5331 if (runtimeSign || compiletimeSign)
5333 lbl = newiTempLabel (NULL);
5335 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5336 emitcode ("cpl", "a"); /* lsb 2's complement */
5337 emitcode ("inc", "a");
5340 accuse = aopPut (result, "a", 0);
5343 /* msb is 0x00 or 0xff depending on the sign */
5348 emitcode ("push", "acc");
5351 emitcode ("mov", "c,F0");
5352 emitcode ("subb", "a,acc");
5354 aopPut (result, "a", offset++);
5356 else /* compiletimeSign */
5358 if (aopPutUsesAcc (result, "#0xFF", offset))
5360 emitcode ("push", "acc");
5364 aopPut (result, "#0xff", offset++);
5370 aopPut (result, "a", 0);
5372 aopPut (result, zero, offset++);
5376 emitcode ("pop", "acc");
5380 /*-----------------------------------------------------------------*/
5381 /* genDiv - generates code for division */
5382 /*-----------------------------------------------------------------*/
5386 operand *left = IC_LEFT (ic);
5387 operand *right = IC_RIGHT (ic);
5388 operand *result = IC_RESULT (ic);
5390 D (emitcode (";", "genDiv"));
5392 /* assign the amsops */
5393 aopOp (left, ic, FALSE);
5394 aopOp (right, ic, FALSE);
5395 aopOp (result, ic, TRUE);
5397 /* special cases first */
5399 if (AOP_TYPE (left) == AOP_CRY &&
5400 AOP_TYPE (right) == AOP_CRY)
5402 genDivbits (left, right, result);
5406 /* if both are of size == 1 */
5407 if (AOP_SIZE (left) == 1 &&
5408 AOP_SIZE (right) == 1)
5410 genDivOneByte (left, right, result);
5414 /* should have been converted to function call */
5417 freeAsmop (result, NULL, ic, TRUE);
5418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 /*-----------------------------------------------------------------*/
5423 /* genModbits :- modulus of bits */
5424 /*-----------------------------------------------------------------*/
5426 genModbits (operand * left,
5433 D (emitcode (";", "genModbits"));
5437 /* the result must be bit */
5438 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5439 l = aopGet (left, 0, FALSE, FALSE);
5443 emitcode ("div", "ab");
5444 emitcode ("mov", "a,b");
5445 emitcode ("rrc", "a");
5449 aopPut (result, "c", 0);
5452 /*-----------------------------------------------------------------*/
5453 /* genModOneByte : 8 bit modulus */
5454 /*-----------------------------------------------------------------*/
5456 genModOneByte (operand * left,
5460 bool lUnsigned, rUnsigned, pushedB;
5461 bool runtimeSign, compiletimeSign;
5465 D (emitcode (";", "genModOneByte"));
5467 size = AOP_SIZE (result) - 1;
5469 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5470 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5472 /* if right is a literal, check it for 2^n */
5473 if (AOP_TYPE(right) == AOP_LIT)
5475 unsigned char val = abs((int) operandLitValue(right));
5476 symbol *lbl2 = NULL;
5480 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5489 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5490 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5491 /* because iCode should have been changed to genAnd */
5492 /* see file "SDCCopt.c", function "convertToFcall()" */
5494 MOVA (aopGet (left, 0, FALSE, FALSE));
5495 emitcode ("mov", "c,acc.7");
5496 emitcode ("anl", "a,#0x%02x", val - 1);
5497 lbl = newiTempLabel (NULL);
5498 emitcode ("jz", "%05d$", (lbl->key + 100));
5499 emitcode ("jnc", "%05d$", (lbl->key + 100));
5500 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5506 aopPut (result, "a", 0);
5508 aopPut (result, "#0xff", offs2++);
5509 lbl2 = newiTempLabel (NULL);
5510 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5513 aopPut (result, "a", 0);
5515 aopPut (result, zero, offset++);
5529 /* signed or unsigned */
5530 if (lUnsigned && rUnsigned)
5532 /* unsigned is easy */
5533 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5534 MOVA (aopGet (left, 0, FALSE, FALSE));
5535 emitcode ("div", "ab");
5536 aopPut (result, "b", 0);
5538 aopPut (result, zero, offset++);
5544 /* signed is a little bit more difficult */
5546 /* now sign adjust for both left & right */
5548 /* modulus: sign of the right operand has no influence on the result! */
5549 if (AOP_TYPE(right) == AOP_LIT)
5551 signed char val = (char) operandLitValue(right);
5553 if (!rUnsigned && val < 0)
5554 emitcode ("mov", "b,#0x%02x", -val);
5556 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5558 else /* not literal */
5561 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5564 MOVA (aopGet (right, 0, FALSE, FALSE));
5565 lbl = newiTempLabel (NULL);
5566 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5567 emitcode ("cpl", "a"); /* 2's complement */
5568 emitcode ("inc", "a");
5570 emitcode ("mov", "b,a");
5574 /* let's see what's needed: */
5575 /* apply negative sign during runtime */
5576 runtimeSign = FALSE;
5577 /* negative sign from literals */
5578 compiletimeSign = FALSE;
5580 /* sign adjust left side */
5581 if (AOP_TYPE(left) == AOP_LIT)
5583 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5585 if (!lUnsigned && val < 0)
5587 compiletimeSign = TRUE; /* set sign flag */
5588 emitcode ("mov", "a,#0x%02x", -val);
5591 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5593 else /* ! literal */
5595 MOVA (aopGet (left, 0, FALSE, FALSE));
5600 emitcode ("clr", "F0"); /* clear sign flag */
5602 lbl = newiTempLabel (NULL);
5603 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5604 emitcode ("setb", "F0"); /* set sign flag */
5605 emitcode ("cpl", "a"); /* 2's complement */
5606 emitcode ("inc", "a");
5611 /* now the modulus */
5612 emitcode ("div", "ab");
5614 if (runtimeSign || compiletimeSign)
5616 emitcode ("mov", "a,b");
5617 lbl = newiTempLabel (NULL);
5619 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5620 emitcode ("cpl", "a"); /* 2's complement */
5621 emitcode ("inc", "a");
5624 aopPut (result, "a", 0);
5627 /* msb is 0x00 or 0xff depending on the sign */
5630 emitcode ("mov", "c,F0");
5631 emitcode ("subb", "a,acc");
5633 aopPut (result, "a", offset++);
5635 else /* compiletimeSign */
5637 aopPut (result, "#0xff", offset++);
5642 aopPut (result, "b", 0);
5644 aopPut (result, zero, offset++);
5650 /*-----------------------------------------------------------------*/
5651 /* genMod - generates code for division */
5652 /*-----------------------------------------------------------------*/
5656 operand *left = IC_LEFT (ic);
5657 operand *right = IC_RIGHT (ic);
5658 operand *result = IC_RESULT (ic);
5660 D (emitcode (";", "genMod"));
5662 /* assign the asmops */
5663 aopOp (left, ic, FALSE);
5664 aopOp (right, ic, FALSE);
5665 aopOp (result, ic, TRUE);
5667 /* special cases first */
5669 if (AOP_TYPE (left) == AOP_CRY &&
5670 AOP_TYPE (right) == AOP_CRY)
5672 genModbits (left, right, result);
5676 /* if both are of size == 1 */
5677 if (AOP_SIZE (left) == 1 &&
5678 AOP_SIZE (right) == 1)
5680 genModOneByte (left, right, result);
5684 /* should have been converted to function call */
5688 freeAsmop (result, NULL, ic, TRUE);
5689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5690 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5693 /*-----------------------------------------------------------------*/
5694 /* genIfxJump :- will create a jump depending on the ifx */
5695 /*-----------------------------------------------------------------*/
5697 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5700 symbol *tlbl = newiTempLabel (NULL);
5703 D (emitcode (";", "genIfxJump"));
5705 /* if true label then we jump if condition
5709 jlbl = IC_TRUE (ic);
5710 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5711 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5715 /* false label is present */
5716 jlbl = IC_FALSE (ic);
5717 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5718 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5720 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5721 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5723 emitcode (inst, "%05d$", tlbl->key + 100);
5724 freeForBranchAsmop (result);
5725 freeForBranchAsmop (right);
5726 freeForBranchAsmop (left);
5727 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5730 /* mark the icode as generated */
5734 /*-----------------------------------------------------------------*/
5735 /* genCmp :- greater or less than comparison */
5736 /*-----------------------------------------------------------------*/
5738 genCmp (operand * left, operand * right,
5739 operand * result, iCode * ifx, int sign, iCode *ic)
5741 int size, offset = 0;
5742 unsigned long lit = 0L;
5745 D (emitcode (";", "genCmp"));
5747 /* if left & right are bit variables */
5748 if (AOP_TYPE (left) == AOP_CRY &&
5749 AOP_TYPE (right) == AOP_CRY)
5751 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5752 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5756 /* subtract right from left if at the
5757 end the carry flag is set then we know that
5758 left is greater than right */
5759 size = max (AOP_SIZE (left), AOP_SIZE (right));
5761 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5762 if ((size == 1) && !sign &&
5763 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5765 symbol *lbl = newiTempLabel (NULL);
5766 emitcode ("cjne", "%s,%s,%05d$",
5767 aopGet (left, offset, FALSE, FALSE),
5768 aopGet (right, offset, FALSE, FALSE),
5774 if (AOP_TYPE (right) == AOP_LIT)
5776 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5777 /* optimize if(x < 0) or if(x >= 0) */
5786 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5787 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5789 genIfxJump (ifx, "acc.7", left, right, result);
5790 freeAsmop (right, NULL, ic, TRUE);
5791 freeAsmop (left, NULL, ic, TRUE);
5797 emitcode ("rlc", "a");
5804 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5805 while (size && (bytelit == 0))
5808 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5814 MOVA (aopGet (left, offset, FALSE, FALSE));
5815 if (sign && size == 0)
5817 emitcode ("xrl", "a,#0x80");
5818 emitcode ("subb", "a,#0x%02x",
5819 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5823 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5833 bool pushedB = FALSE;
5834 rightInB = aopGetUsesAcc(right, offset);
5838 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5840 MOVA (aopGet (left, offset, FALSE, FALSE));
5841 if (sign && size == 0)
5843 emitcode ("xrl", "a,#0x80");
5848 MOVB (aopGet (right, offset, FALSE, FALSE));
5850 emitcode ("xrl", "b,#0x80");
5851 emitcode ("subb", "a,b");
5856 emitcode ("subb", "a,b");
5858 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5868 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5876 /* if the result is used in the next
5877 ifx conditional branch then generate
5878 code a little differently */
5881 genIfxJump (ifx, "c", NULL, NULL, result);
5887 /* leave the result in acc */
5891 /*-----------------------------------------------------------------*/
5892 /* genCmpGt :- greater than comparison */
5893 /*-----------------------------------------------------------------*/
5895 genCmpGt (iCode * ic, iCode * ifx)
5897 operand *left, *right, *result;
5898 sym_link *letype, *retype;
5901 D (emitcode (";", "genCmpGt"));
5903 left = IC_LEFT (ic);
5904 right = IC_RIGHT (ic);
5905 result = IC_RESULT (ic);
5907 letype = getSpec (operandType (left));
5908 retype = getSpec (operandType (right));
5909 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5910 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5911 /* assign the amsops */
5912 aopOp (result, ic, TRUE);
5913 aopOp (left, ic, FALSE);
5914 aopOp (right, ic, FALSE);
5916 genCmp (right, left, result, ifx, sign, ic);
5918 freeAsmop (result, NULL, ic, TRUE);
5921 /*-----------------------------------------------------------------*/
5922 /* genCmpLt - less than comparisons */
5923 /*-----------------------------------------------------------------*/
5925 genCmpLt (iCode * ic, iCode * ifx)
5927 operand *left, *right, *result;
5928 sym_link *letype, *retype;
5931 D (emitcode (";", "genCmpLt"));
5933 left = IC_LEFT (ic);
5934 right = IC_RIGHT (ic);
5935 result = IC_RESULT (ic);
5937 letype = getSpec (operandType (left));
5938 retype = getSpec (operandType (right));
5939 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5940 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5941 /* assign the amsops */
5942 aopOp (result, ic, TRUE);
5943 aopOp (left, ic, FALSE);
5944 aopOp (right, ic, FALSE);
5946 genCmp (left, right, result, ifx, sign, ic);
5948 freeAsmop (result, NULL, ic, TRUE);
5951 /*-----------------------------------------------------------------*/
5952 /* gencjneshort - compare and jump if not equal */
5953 /*-----------------------------------------------------------------*/
5955 gencjneshort (operand * left, operand * right, symbol * lbl)
5957 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5959 unsigned long lit = 0L;
5961 D (emitcode (";", "gencjneshort"));
5963 /* if the left side is a literal or
5964 if the right is in a pointer register and left
5966 if ((AOP_TYPE (left) == AOP_LIT) ||
5967 (AOP_TYPE (left) == AOP_IMMD) ||
5968 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5975 if (AOP_TYPE (right) == AOP_LIT)
5976 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5978 /* if the right side is a literal then anything goes */
5979 if (AOP_TYPE (right) == AOP_LIT &&
5980 AOP_TYPE (left) != AOP_DIR &&
5981 AOP_TYPE (left) != AOP_IMMD)
5985 emitcode ("cjne", "%s,%s,%05d$",
5986 aopGet (left, offset, FALSE, FALSE),
5987 aopGet (right, offset, FALSE, FALSE),
5993 /* if the right side is in a register or in direct space or
5994 if the left is a pointer register & right is not */
5995 else if (AOP_TYPE (right) == AOP_REG ||
5996 AOP_TYPE (right) == AOP_DIR ||
5997 AOP_TYPE (right) == AOP_LIT ||
5998 AOP_TYPE (right) == AOP_IMMD ||
5999 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6000 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6004 MOVA (aopGet (left, offset, FALSE, FALSE));
6005 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6006 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6007 emitcode ("jnz", "%05d$", lbl->key + 100);
6009 emitcode ("cjne", "a,%s,%05d$",
6010 aopGet (right, offset, FALSE, TRUE),
6017 /* right is a pointer reg need both a & b */
6020 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6021 wassertl(!BINUSE, "B was in use");
6022 MOVB (aopGet (left, offset, FALSE, FALSE));
6023 MOVA (aopGet (right, offset, FALSE, FALSE));
6024 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6030 /*-----------------------------------------------------------------*/
6031 /* gencjne - compare and jump if not equal */
6032 /*-----------------------------------------------------------------*/
6034 gencjne (operand * left, operand * right, symbol * lbl)
6036 symbol *tlbl = newiTempLabel (NULL);
6038 D (emitcode (";", "gencjne"));
6040 gencjneshort (left, right, lbl);
6042 emitcode ("mov", "a,%s", one);
6043 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6045 emitcode ("clr", "a");
6049 /*-----------------------------------------------------------------*/
6050 /* genCmpEq - generates code for equal to */
6051 /*-----------------------------------------------------------------*/
6053 genCmpEq (iCode * ic, iCode * ifx)
6055 bool swappedLR = FALSE;
6056 operand *left, *right, *result;
6058 D (emitcode (";", "genCmpEq"));
6060 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6061 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6062 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6064 /* if literal, literal on the right or
6065 if the right is in a pointer register and left
6067 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6068 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6070 operand *t = IC_RIGHT (ic);
6071 IC_RIGHT (ic) = IC_LEFT (ic);
6076 if (ifx && !AOP_SIZE (result))
6079 /* if they are both bit variables */
6080 if (AOP_TYPE (left) == AOP_CRY &&
6081 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6083 if (AOP_TYPE (right) == AOP_LIT)
6085 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6088 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6089 emitcode ("cpl", "c");
6093 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6097 emitcode ("clr", "c");
6099 /* AOP_TYPE(right) == AOP_CRY */
6103 symbol *lbl = newiTempLabel (NULL);
6104 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6105 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6106 emitcode ("cpl", "c");
6109 /* if true label then we jump if condition
6111 tlbl = newiTempLabel (NULL);
6114 emitcode ("jnc", "%05d$", tlbl->key + 100);
6115 freeForBranchAsmop (result);
6116 freeForBranchAsmop (right);
6117 freeForBranchAsmop (left);
6118 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6122 emitcode ("jc", "%05d$", tlbl->key + 100);
6123 freeForBranchAsmop (result);
6124 freeForBranchAsmop (right);
6125 freeForBranchAsmop (left);
6126 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6132 tlbl = newiTempLabel (NULL);
6133 gencjneshort (left, right, tlbl);
6136 freeForBranchAsmop (result);
6137 freeForBranchAsmop (right);
6138 freeForBranchAsmop (left);
6139 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6144 symbol *lbl = newiTempLabel (NULL);
6145 emitcode ("sjmp", "%05d$", lbl->key + 100);
6147 freeForBranchAsmop (result);
6148 freeForBranchAsmop (right);
6149 freeForBranchAsmop (left);
6150 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6154 /* mark the icode as generated */
6159 /* if they are both bit variables */
6160 if (AOP_TYPE (left) == AOP_CRY &&
6161 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6163 if (AOP_TYPE (right) == AOP_LIT)
6165 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6168 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6169 emitcode ("cpl", "c");
6173 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6177 emitcode ("clr", "c");
6179 /* AOP_TYPE(right) == AOP_CRY */
6183 symbol *lbl = newiTempLabel (NULL);
6184 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6185 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6186 emitcode ("cpl", "c");
6190 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6197 genIfxJump (ifx, "c", left, right, result);
6200 /* if the result is used in an arithmetic operation
6201 then put the result in place */
6206 gencjne (left, right, newiTempLabel (NULL));
6207 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6209 aopPut (result, "a", 0);
6214 genIfxJump (ifx, "a", left, right, result);
6217 /* if the result is used in an arithmetic operation
6218 then put the result in place */
6219 if (AOP_TYPE (result) != AOP_CRY)
6221 /* leave the result in acc */
6225 freeAsmop (result, NULL, ic, TRUE);
6228 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6229 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6238 /*-----------------------------------------------------------------*/
6239 /* ifxForOp - returns the icode containing the ifx for operand */
6240 /*-----------------------------------------------------------------*/
6242 ifxForOp (operand * op, iCode * ic)
6244 /* if true symbol then needs to be assigned */
6245 if (IS_TRUE_SYMOP (op))
6248 /* if this has register type condition and
6249 the next instruction is ifx with the same operand
6250 and live to of the operand is upto the ifx only then */
6252 ic->next->op == IFX &&
6253 IC_COND (ic->next)->key == op->key &&
6254 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6260 /*-----------------------------------------------------------------*/
6261 /* hasInc - operand is incremented before any other use */
6262 /*-----------------------------------------------------------------*/
6264 hasInc (operand *op, iCode *ic, int osize)
6266 sym_link *type = operandType(op);
6267 sym_link *retype = getSpec (type);
6268 iCode *lic = ic->next;
6271 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6272 if (!IS_SYMOP(op)) return NULL;
6274 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6275 if (IS_AGGREGATE(type->next)) return NULL;
6276 if (osize != (isize = getSize(type->next))) return NULL;
6279 /* if operand of the form op = op + <sizeof *op> */
6280 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6281 isOperandEqual(IC_RESULT(lic),op) &&
6282 isOperandLiteral(IC_RIGHT(lic)) &&
6283 operandLitValue(IC_RIGHT(lic)) == isize) {
6286 /* if the operand used or deffed */
6287 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6290 /* if GOTO or IFX */
6291 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6297 /*-----------------------------------------------------------------*/
6298 /* genAndOp - for && operation */
6299 /*-----------------------------------------------------------------*/
6301 genAndOp (iCode * ic)
6303 operand *left, *right, *result;
6306 D (emitcode (";", "genAndOp"));
6308 /* note here that && operations that are in an
6309 if statement are taken away by backPatchLabels
6310 only those used in arthmetic operations remain */
6311 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6312 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6313 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6315 /* if both are bit variables */
6316 if (AOP_TYPE (left) == AOP_CRY &&
6317 AOP_TYPE (right) == AOP_CRY)
6319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6320 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6325 tlbl = newiTempLabel (NULL);
6327 emitcode ("jz", "%05d$", tlbl->key + 100);
6333 freeAsmop (result, NULL, ic, TRUE);
6334 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6335 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339 /*-----------------------------------------------------------------*/
6340 /* genOrOp - for || operation */
6341 /*-----------------------------------------------------------------*/
6343 genOrOp (iCode * ic)
6345 operand *left, *right, *result;
6348 D (emitcode (";", "genOrOp"));
6350 /* note here that || operations that are in an
6351 if statement are taken away by backPatchLabels
6352 only those used in arthmetic operations remain */
6353 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6354 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6355 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6357 /* if both are bit variables */
6358 if (AOP_TYPE (left) == AOP_CRY &&
6359 AOP_TYPE (right) == AOP_CRY)
6361 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6362 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6367 tlbl = newiTempLabel (NULL);
6369 emitcode ("jnz", "%05d$", tlbl->key + 100);
6375 freeAsmop (result, NULL, ic, TRUE);
6376 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6377 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6380 /*-----------------------------------------------------------------*/
6381 /* isLiteralBit - test if lit == 2^n */
6382 /*-----------------------------------------------------------------*/
6384 isLiteralBit (unsigned long lit)
6386 unsigned long pw[32] =
6387 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6388 0x100L, 0x200L, 0x400L, 0x800L,
6389 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6390 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6391 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6392 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6393 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6396 for (idx = 0; idx < 32; idx++)
6402 /*-----------------------------------------------------------------*/
6403 /* continueIfTrue - */
6404 /*-----------------------------------------------------------------*/
6406 continueIfTrue (iCode * ic)
6409 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6413 /*-----------------------------------------------------------------*/
6415 /*-----------------------------------------------------------------*/
6417 jumpIfTrue (iCode * ic)
6420 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6424 /*-----------------------------------------------------------------*/
6425 /* jmpTrueOrFalse - */
6426 /*-----------------------------------------------------------------*/
6428 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6430 // ugly but optimized by peephole
6433 symbol *nlbl = newiTempLabel (NULL);
6434 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6436 freeForBranchAsmop (result);
6437 freeForBranchAsmop (right);
6438 freeForBranchAsmop (left);
6439 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6444 freeForBranchAsmop (result);
6445 freeForBranchAsmop (right);
6446 freeForBranchAsmop (left);
6447 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6453 /*-----------------------------------------------------------------*/
6454 /* genAnd - code for and */
6455 /*-----------------------------------------------------------------*/
6457 genAnd (iCode * ic, iCode * ifx)
6459 operand *left, *right, *result;
6460 int size, offset = 0;
6461 unsigned long lit = 0L;
6465 D (emitcode (";", "genAnd"));
6467 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6468 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6469 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6472 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6474 AOP_TYPE (left), AOP_TYPE (right));
6475 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6477 AOP_SIZE (left), AOP_SIZE (right));
6480 /* if left is a literal & right is not then exchange them */
6481 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6482 AOP_NEEDSACC (left))
6484 operand *tmp = right;
6489 /* if result = right then exchange left and right */
6490 if (sameRegs (AOP (result), AOP (right)))
6492 operand *tmp = right;
6497 /* if right is bit then exchange them */
6498 if (AOP_TYPE (right) == AOP_CRY &&
6499 AOP_TYPE (left) != AOP_CRY)
6501 operand *tmp = right;
6505 if (AOP_TYPE (right) == AOP_LIT)
6506 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6508 size = AOP_SIZE (result);
6511 // result = bit & yy;
6512 if (AOP_TYPE (left) == AOP_CRY)
6514 // c = bit & literal;
6515 if (AOP_TYPE (right) == AOP_LIT)
6519 if (size && sameRegs (AOP (result), AOP (left)))
6522 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6527 if (size && (AOP_TYPE (result) == AOP_CRY))
6529 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6532 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6537 emitcode ("clr", "c");
6542 if (AOP_TYPE (right) == AOP_CRY)
6545 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6546 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6551 MOVA (aopGet (right, 0, FALSE, FALSE));
6553 emitcode ("rrc", "a");
6554 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6562 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6563 genIfxJump (ifx, "c", left, right, result);
6567 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6568 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6569 if ((AOP_TYPE (right) == AOP_LIT) &&
6570 (AOP_TYPE (result) == AOP_CRY) &&
6571 (AOP_TYPE (left) != AOP_CRY))
6573 int posbit = isLiteralBit (lit);
6578 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6582 switch (posbit & 0x07)
6584 case 0: emitcode ("rrc", "a");
6586 case 7: emitcode ("rlc", "a");
6588 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6597 SNPRINTF (buffer, sizeof(buffer),
6598 "acc.%d", posbit & 0x07);
6599 genIfxJump (ifx, buffer, left, right, result);
6602 {// what is this case? just found it in ds390/gen.c
6603 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6610 symbol *tlbl = newiTempLabel (NULL);
6611 int sizel = AOP_SIZE (left);
6613 emitcode ("setb", "c");
6616 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6618 MOVA (aopGet (left, offset, FALSE, FALSE));
6620 if ((posbit = isLiteralBit (bytelit)) != 0)
6621 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6624 if (bytelit != 0x0FFL)
6625 emitcode ("anl", "a,%s",
6626 aopGet (right, offset, FALSE, TRUE));
6627 emitcode ("jnz", "%05d$", tlbl->key + 100);
6632 // bit = left & literal
6635 emitcode ("clr", "c");
6638 // if(left & literal)
6642 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6652 /* if left is same as result */
6653 if (sameRegs (AOP (result), AOP (left)))
6655 for (; size--; offset++)
6657 if (AOP_TYPE (right) == AOP_LIT)
6659 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6660 if (bytelit == 0x0FF)
6662 /* dummy read of volatile operand */
6663 if (isOperandVolatile (left, FALSE))
6664 MOVA (aopGet (left, offset, FALSE, FALSE));
6668 else if (bytelit == 0)
6670 aopPut (result, zero, offset);
6672 else if (IS_AOP_PREG (result))
6674 MOVA (aopGet (left, offset, FALSE, TRUE));
6675 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6676 aopPut (result, "a", offset);
6679 emitcode ("anl", "%s,%s",
6680 aopGet (left, offset, FALSE, TRUE),
6681 aopGet (right, offset, FALSE, FALSE));
6685 if (AOP_TYPE (left) == AOP_ACC)
6688 emitcode("mov", "a,b");
6689 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6691 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6693 MOVB (aopGet (left, offset, FALSE, FALSE));
6694 MOVA (aopGet (right, offset, FALSE, FALSE));
6695 emitcode ("anl", "a,b");
6696 aopPut (result, "a", offset);
6698 else if (aopGetUsesAcc (left, offset))
6700 MOVA (aopGet (left, offset, FALSE, FALSE));
6701 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6702 aopPut (result, "a", offset);
6706 MOVA (aopGet (right, offset, FALSE, FALSE));
6707 if (IS_AOP_PREG (result))
6709 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6710 aopPut (result, "a", offset);
6713 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6720 // left & result in different registers
6721 if (AOP_TYPE (result) == AOP_CRY)
6724 // if(size), result in bit
6725 // if(!size && ifx), conditional oper: if(left & right)
6726 symbol *tlbl = newiTempLabel (NULL);
6727 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6729 emitcode ("setb", "c");
6732 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6733 && AOP_TYPE(left)==AOP_ACC)
6736 emitcode("mov", "a,b");
6737 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6739 else if (AOP_TYPE(left)==AOP_ACC)
6743 bool pushedB = pushB ();
6744 emitcode("mov", "b,a");
6745 MOVA (aopGet (right, offset, FALSE, FALSE));
6746 emitcode("anl", "a,b");
6751 MOVA (aopGet (right, offset, FALSE, FALSE));
6752 emitcode("anl", "a,b");
6755 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6757 MOVB (aopGet (left, offset, FALSE, FALSE));
6758 MOVA (aopGet (right, offset, FALSE, FALSE));
6759 emitcode ("anl", "a,b");
6761 else if (aopGetUsesAcc (left, offset))
6763 MOVA (aopGet (left, offset, FALSE, FALSE));
6764 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6768 MOVA (aopGet (right, offset, FALSE, FALSE));
6769 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6772 emitcode ("jnz", "%05d$", tlbl->key + 100);
6782 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6788 for (; (size--); offset++)
6791 // result = left & right
6792 if (AOP_TYPE (right) == AOP_LIT)
6794 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6795 if (bytelit == 0x0FF)
6798 aopGet (left, offset, FALSE, FALSE),
6802 else if (bytelit == 0)
6804 /* dummy read of volatile operand */
6805 if (isOperandVolatile (left, FALSE))
6806 MOVA (aopGet (left, offset, FALSE, FALSE));
6807 aopPut (result, zero, offset);
6810 else if (AOP_TYPE (left) == AOP_ACC)
6814 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6815 aopPut (result, "a", offset);
6820 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6821 aopPut (result, "b", offset);
6826 // faster than result <- left, anl result,right
6827 // and better if result is SFR
6828 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6829 && AOP_TYPE(left)==AOP_ACC)
6832 emitcode("mov", "a,b");
6833 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6835 else if (AOP_TYPE(left)==AOP_ACC)
6839 bool pushedB = pushB ();
6840 emitcode("mov", "b,a");
6841 MOVA (aopGet (right, offset, FALSE, FALSE));
6842 emitcode("anl", "a,b");
6847 MOVA (aopGet (right, offset, FALSE, FALSE));
6848 emitcode("anl", "a,b");
6851 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6853 MOVB (aopGet (left, offset, FALSE, FALSE));
6854 MOVA (aopGet (right, offset, FALSE, FALSE));
6855 emitcode ("anl", "a,b");
6857 else if (aopGetUsesAcc (left, offset))
6859 MOVA (aopGet (left, offset, FALSE, FALSE));
6860 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6864 MOVA (aopGet (right, offset, FALSE, FALSE));
6865 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6867 aopPut (result, "a", offset);
6873 freeAsmop (result, NULL, ic, TRUE);
6874 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6875 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6878 /*-----------------------------------------------------------------*/
6879 /* genOr - code for or */
6880 /*-----------------------------------------------------------------*/
6882 genOr (iCode * ic, iCode * ifx)
6884 operand *left, *right, *result;
6885 int size, offset = 0;
6886 unsigned long lit = 0L;
6889 D (emitcode (";", "genOr"));
6891 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6892 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6893 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6896 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6898 AOP_TYPE (left), AOP_TYPE (right));
6899 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6901 AOP_SIZE (left), AOP_SIZE (right));
6904 /* if left is a literal & right is not then exchange them */
6905 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6906 AOP_NEEDSACC (left))
6908 operand *tmp = right;
6913 /* if result = right then exchange them */
6914 if (sameRegs (AOP (result), AOP (right)))
6916 operand *tmp = right;
6921 /* if right is bit then exchange them */
6922 if (AOP_TYPE (right) == AOP_CRY &&
6923 AOP_TYPE (left) != AOP_CRY)
6925 operand *tmp = right;
6929 if (AOP_TYPE (right) == AOP_LIT)
6930 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6932 size = AOP_SIZE (result);
6936 if (AOP_TYPE (left) == AOP_CRY)
6938 if (AOP_TYPE (right) == AOP_LIT)
6940 // c = bit | literal;
6943 // lit != 0 => result = 1
6944 if (AOP_TYPE (result) == AOP_CRY)
6947 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6949 continueIfTrue (ifx);
6952 emitcode ("setb", "c");
6956 // lit == 0 => result = left
6957 if (size && sameRegs (AOP (result), AOP (left)))
6959 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964 if (AOP_TYPE (right) == AOP_CRY)
6967 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6968 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6973 symbol *tlbl = newiTempLabel (NULL);
6974 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6975 emitcode ("setb", "c");
6976 emitcode ("jb", "%s,%05d$",
6977 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6979 emitcode ("jnz", "%05d$", tlbl->key + 100);
6980 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6982 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6997 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6998 genIfxJump (ifx, "c", left, right, result);
7002 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7003 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7004 if ((AOP_TYPE (right) == AOP_LIT) &&
7005 (AOP_TYPE (result) == AOP_CRY) &&
7006 (AOP_TYPE (left) != AOP_CRY))
7012 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7014 continueIfTrue (ifx);
7019 // lit = 0, result = boolean(left)
7021 emitcode ("setb", "c");
7025 symbol *tlbl = newiTempLabel (NULL);
7026 emitcode ("jnz", "%05d$", tlbl->key + 100);
7032 genIfxJump (ifx, "a", left, right, result);
7040 /* if left is same as result */
7041 if (sameRegs (AOP (result), AOP (left)))
7043 for (; size--; offset++)
7045 if (AOP_TYPE (right) == AOP_LIT)
7047 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7050 /* dummy read of volatile operand */
7051 if (isOperandVolatile (left, FALSE))
7052 MOVA (aopGet (left, offset, FALSE, FALSE));
7056 else if (bytelit == 0x0FF)
7058 aopPut (result, "#0xFF", offset);
7060 else if (IS_AOP_PREG (left))
7062 MOVA (aopGet (left, offset, FALSE, TRUE));
7063 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7064 aopPut (result, "a", offset);
7068 emitcode ("orl", "%s,%s",
7069 aopGet (left, offset, FALSE, TRUE),
7070 aopGet (right, offset, FALSE, FALSE));
7075 if (AOP_TYPE (left) == AOP_ACC)
7078 emitcode("mov", "a,b");
7079 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7081 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7083 MOVB (aopGet (left, offset, FALSE, FALSE));
7084 MOVA (aopGet (right, offset, FALSE, FALSE));
7085 emitcode ("orl", "a,b");
7086 aopPut (result, "a", offset);
7088 else if (aopGetUsesAcc (left, offset))
7090 MOVA (aopGet (left, offset, FALSE, FALSE));
7091 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7092 aopPut (result, "a", offset);
7096 MOVA (aopGet (right, offset, FALSE, FALSE));
7097 if (IS_AOP_PREG (left))
7099 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7100 aopPut (result, "a", offset);
7104 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7112 // left & result in different registers
7113 if (AOP_TYPE (result) == AOP_CRY)
7116 // if(size), result in bit
7117 // if(!size && ifx), conditional oper: if(left | right)
7118 symbol *tlbl = newiTempLabel (NULL);
7119 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7121 emitcode ("setb", "c");
7124 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7125 && AOP_TYPE(left)==AOP_ACC)
7128 emitcode("mov", "a,b");
7129 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7131 else if (AOP_TYPE(left)==AOP_ACC)
7135 bool pushedB = pushB ();
7136 emitcode("mov", "b,a");
7137 MOVA (aopGet (right, offset, FALSE, FALSE));
7138 emitcode("orl", "a,b");
7143 MOVA (aopGet (right, offset, FALSE, FALSE));
7144 emitcode("orl", "a,b");
7147 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7149 MOVB (aopGet (left, offset, FALSE, FALSE));
7150 MOVA (aopGet (right, offset, FALSE, FALSE));
7151 emitcode ("orl", "a,b");
7153 else if (aopGetUsesAcc (left, offset))
7155 MOVA (aopGet (left, offset, FALSE, FALSE));
7156 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7160 MOVA (aopGet (right, offset, FALSE, FALSE));
7161 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7164 emitcode ("jnz", "%05d$", tlbl->key + 100);
7174 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7180 for (; (size--); offset++)
7183 // result = left | right
7184 if (AOP_TYPE (right) == AOP_LIT)
7186 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7190 aopGet (left, offset, FALSE, FALSE),
7194 else if (bytelit == 0x0FF)
7196 /* dummy read of volatile operand */
7197 if (isOperandVolatile (left, FALSE))
7198 MOVA (aopGet (left, offset, FALSE, FALSE));
7199 aopPut (result, "#0xFF", offset);
7203 // faster than result <- left, orl result,right
7204 // and better if result is SFR
7205 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7206 && AOP_TYPE(left)==AOP_ACC)
7209 emitcode("mov", "a,b");
7210 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7212 else if (AOP_TYPE(left)==AOP_ACC)
7216 bool pushedB = pushB ();
7217 emitcode("mov", "b,a");
7218 MOVA (aopGet (right, offset, FALSE, FALSE));
7219 emitcode("orl", "a,b");
7224 MOVA (aopGet (right, offset, FALSE, FALSE));
7225 emitcode("orl", "a,b");
7228 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7230 MOVB (aopGet (left, offset, FALSE, FALSE));
7231 MOVA (aopGet (right, offset, FALSE, FALSE));
7232 emitcode ("orl", "a,b");
7234 else if (aopGetUsesAcc (left, offset))
7236 MOVA (aopGet (left, offset, FALSE, FALSE));
7237 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7241 MOVA (aopGet (right, offset, FALSE, FALSE));
7242 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7244 aopPut (result, "a", offset);
7250 freeAsmop (result, NULL, ic, TRUE);
7251 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7252 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7255 /*-----------------------------------------------------------------*/
7256 /* genXor - code for xclusive or */
7257 /*-----------------------------------------------------------------*/
7259 genXor (iCode * ic, iCode * ifx)
7261 operand *left, *right, *result;
7262 int size, offset = 0;
7263 unsigned long lit = 0L;
7266 D (emitcode (";", "genXor"));
7268 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7269 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7270 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7273 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7275 AOP_TYPE (left), AOP_TYPE (right));
7276 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7278 AOP_SIZE (left), AOP_SIZE (right));
7281 /* if left is a literal & right is not ||
7282 if left needs acc & right does not */
7283 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7284 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7286 operand *tmp = right;
7291 /* if result = right then exchange them */
7292 if (sameRegs (AOP (result), AOP (right)))
7294 operand *tmp = right;
7299 /* if right is bit then exchange them */
7300 if (AOP_TYPE (right) == AOP_CRY &&
7301 AOP_TYPE (left) != AOP_CRY)
7303 operand *tmp = right;
7307 if (AOP_TYPE (right) == AOP_LIT)
7308 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7310 size = AOP_SIZE (result);
7314 if (AOP_TYPE (left) == AOP_CRY)
7316 if (AOP_TYPE (right) == AOP_LIT)
7318 // c = bit & literal;
7321 // lit>>1 != 0 => result = 1
7322 if (AOP_TYPE (result) == AOP_CRY)
7325 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7327 continueIfTrue (ifx);
7330 emitcode ("setb", "c");
7337 // lit == 0, result = left
7338 if (size && sameRegs (AOP (result), AOP (left)))
7340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7344 // lit == 1, result = not(left)
7345 if (size && sameRegs (AOP (result), AOP (left)))
7347 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7352 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7353 emitcode ("cpl", "c");
7361 symbol *tlbl = newiTempLabel (NULL);
7362 if (AOP_TYPE (right) == AOP_CRY)
7365 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7369 int sizer = AOP_SIZE (right);
7371 // if val>>1 != 0, result = 1
7372 emitcode ("setb", "c");
7375 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7377 // test the msb of the lsb
7378 emitcode ("anl", "a,#0xfe");
7379 emitcode ("jnz", "%05d$", tlbl->key + 100);
7383 emitcode ("rrc", "a");
7385 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7386 emitcode ("cpl", "c");
7394 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7395 genIfxJump (ifx, "c", left, right, result);
7399 /* if left is same as result */
7400 if (sameRegs (AOP (result), AOP (left)))
7402 for (; size--; offset++)
7404 if (AOP_TYPE (right) == AOP_LIT)
7406 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7409 /* dummy read of volatile operand */
7410 if (isOperandVolatile (left, FALSE))
7411 MOVA (aopGet (left, offset, FALSE, FALSE));
7415 else if (IS_AOP_PREG (left))
7417 MOVA (aopGet (left, offset, FALSE, TRUE));
7418 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7419 aopPut (result, "a", offset);
7423 emitcode ("xrl", "%s,%s",
7424 aopGet (left, offset, FALSE, TRUE),
7425 aopGet (right, offset, FALSE, FALSE));
7430 if (AOP_TYPE (left) == AOP_ACC)
7433 emitcode("mov", "a,b");
7434 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7436 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7438 MOVB (aopGet (left, offset, FALSE, FALSE));
7439 MOVA (aopGet (right, offset, FALSE, FALSE));
7440 emitcode ("xrl", "a,b");
7441 aopPut (result, "a", offset);
7443 else if (aopGetUsesAcc (left, offset))
7445 MOVA (aopGet (left, offset, FALSE, FALSE));
7446 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7447 aopPut (result, "a", offset);
7451 MOVA (aopGet (right, offset, FALSE, FALSE));
7452 if (IS_AOP_PREG (left))
7454 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7455 aopPut (result, "a", offset);
7458 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7465 // left & result in different registers
7466 if (AOP_TYPE (result) == AOP_CRY)
7469 // if(size), result in bit
7470 // if(!size && ifx), conditional oper: if(left ^ right)
7471 symbol *tlbl = newiTempLabel (NULL);
7472 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7475 emitcode ("setb", "c");
7478 if ((AOP_TYPE (right) == AOP_LIT) &&
7479 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7481 MOVA (aopGet (left, offset, FALSE, FALSE));
7483 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7484 && AOP_TYPE(left)==AOP_ACC)
7487 emitcode("mov", "a,b");
7488 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7490 else if (AOP_TYPE(left)==AOP_ACC)
7494 bool pushedB = pushB ();
7495 emitcode("mov", "b,a");
7496 MOVA (aopGet (right, offset, FALSE, FALSE));
7497 emitcode("xrl", "a,b");
7502 MOVA (aopGet (right, offset, FALSE, FALSE));
7503 emitcode("xrl", "a,b");
7506 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7508 MOVB (aopGet (left, offset, FALSE, FALSE));
7509 MOVA (aopGet (right, offset, FALSE, FALSE));
7510 emitcode ("xrl", "a,b");
7512 else if (aopGetUsesAcc (left, offset))
7514 MOVA (aopGet (left, offset, FALSE, FALSE));
7515 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7519 MOVA (aopGet (right, offset, FALSE, FALSE));
7520 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7523 emitcode ("jnz", "%05d$", tlbl->key + 100);
7533 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7537 for (; (size--); offset++)
7540 // result = left ^ right
7541 if (AOP_TYPE (right) == AOP_LIT)
7543 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7547 aopGet (left, offset, FALSE, FALSE),
7552 // faster than result <- left, xrl result,right
7553 // and better if result is SFR
7554 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7555 && AOP_TYPE(left)==AOP_ACC)
7558 emitcode("mov", "a,b");
7559 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7561 else if (AOP_TYPE(left)==AOP_ACC)
7565 bool pushedB = pushB ();
7566 emitcode("mov", "b,a");
7567 MOVA (aopGet (right, offset, FALSE, FALSE));
7568 emitcode("xrl", "a,b");
7573 MOVA (aopGet (right, offset, FALSE, FALSE));
7574 emitcode("xrl", "a,b");
7577 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7579 MOVB (aopGet (left, offset, FALSE, FALSE));
7580 MOVA (aopGet (right, offset, FALSE, FALSE));
7581 emitcode ("xrl", "a,b");
7583 else if (aopGetUsesAcc (left, offset))
7585 MOVA (aopGet (left, offset, FALSE, FALSE));
7586 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7590 MOVA (aopGet (right, offset, FALSE, FALSE));
7591 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7593 aopPut (result, "a", offset);
7599 freeAsmop (result, NULL, ic, TRUE);
7600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7601 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7604 /*-----------------------------------------------------------------*/
7605 /* genInline - write the inline code out */
7606 /*-----------------------------------------------------------------*/
7608 genInline (iCode * ic)
7610 char *buffer, *bp, *bp1;
7612 D (emitcode (";", "genInline"));
7614 _G.inLine += (!options.asmpeep);
7616 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7618 /* emit each line as a code */
7629 /* Add \n for labels, not dirs such as c:\mydir */
7630 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7644 /* emitcode("",buffer); */
7645 _G.inLine -= (!options.asmpeep);
7648 /*-----------------------------------------------------------------*/
7649 /* genRRC - rotate right with carry */
7650 /*-----------------------------------------------------------------*/
7654 operand *left, *result;
7658 D (emitcode (";", "genRRC"));
7660 /* rotate right with carry */
7661 left = IC_LEFT (ic);
7662 result = IC_RESULT (ic);
7663 aopOp (left, ic, FALSE);
7664 aopOp (result, ic, FALSE);
7666 /* move it to the result */
7667 size = AOP_SIZE (result);
7669 if (size == 1) { /* special case for 1 byte */
7670 l = aopGet (left, offset, FALSE, FALSE);
7672 emitcode ("rr", "a");
7675 /* no need to clear carry, bit7 will be written later */
7678 l = aopGet (left, offset, FALSE, FALSE);
7680 emitcode ("rrc", "a");
7681 if (AOP_SIZE (result) > 1)
7682 aopPut (result, "a", offset--);
7684 /* now we need to put the carry into the
7685 highest order byte of the result */
7686 if (AOP_SIZE (result) > 1)
7688 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7691 emitcode ("mov", "acc.7,c");
7693 aopPut (result, "a", AOP_SIZE (result) - 1);
7694 freeAsmop (result, NULL, ic, TRUE);
7695 freeAsmop (left, NULL, ic, TRUE);
7698 /*-----------------------------------------------------------------*/
7699 /* genRLC - generate code for rotate left with carry */
7700 /*-----------------------------------------------------------------*/
7704 operand *left, *result;
7708 D (emitcode (";", "genRLC"));
7710 /* rotate right with carry */
7711 left = IC_LEFT (ic);
7712 result = IC_RESULT (ic);
7713 aopOp (left, ic, FALSE);
7714 aopOp (result, ic, FALSE);
7716 /* move it to the result */
7717 size = AOP_SIZE (result);
7721 l = aopGet (left, offset, FALSE, FALSE);
7723 if (size == 0) { /* special case for 1 byte */
7727 emitcode("rlc","a"); /* bit0 will be written later */
7728 if (AOP_SIZE (result) > 1)
7730 aopPut (result, "a", offset++);
7735 l = aopGet (left, offset, FALSE, FALSE);
7737 emitcode ("rlc", "a");
7738 if (AOP_SIZE (result) > 1)
7739 aopPut (result, "a", offset++);
7742 /* now we need to put the carry into the
7743 highest order byte of the result */
7744 if (AOP_SIZE (result) > 1)
7746 l = aopGet (result, 0, FALSE, FALSE);
7749 emitcode ("mov", "acc.0,c");
7751 aopPut (result, "a", 0);
7752 freeAsmop (result, NULL, ic, TRUE);
7753 freeAsmop (left, NULL, ic, TRUE);
7756 /*-----------------------------------------------------------------*/
7757 /* genGetHbit - generates code get highest order bit */
7758 /*-----------------------------------------------------------------*/
7760 genGetHbit (iCode * ic)
7762 operand *left, *result;
7764 D (emitcode (";", "genGetHbit"));
7766 left = IC_LEFT (ic);
7767 result = IC_RESULT (ic);
7768 aopOp (left, ic, FALSE);
7769 aopOp (result, ic, FALSE);
7771 /* get the highest order byte into a */
7772 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7773 if (AOP_TYPE (result) == AOP_CRY)
7775 emitcode ("rlc", "a");
7780 emitcode ("rl", "a");
7781 emitcode ("anl", "a,#0x01");
7785 freeAsmop (result, NULL, ic, TRUE);
7786 freeAsmop (left, NULL, ic, TRUE);
7789 /*-----------------------------------------------------------------*/
7790 /* genGetAbit - generates code get a single bit */
7791 /*-----------------------------------------------------------------*/
7793 genGetAbit (iCode * ic)
7795 operand *left, *right, *result;
7798 D (emitcode (";", "genGetAbit"));
7800 left = IC_LEFT (ic);
7801 right = IC_RIGHT (ic);
7802 result = IC_RESULT (ic);
7803 aopOp (left, ic, FALSE);
7804 aopOp (right, ic, FALSE);
7805 aopOp (result, ic, FALSE);
7807 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7809 /* get the needed byte into a */
7810 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7812 if (AOP_TYPE (result) == AOP_CRY)
7815 emitcode ("rlc", "a");
7816 else if ((shCount) == 0)
7817 emitcode ("rrc", "a");
7819 emitcode ("mov", "c,acc[%d]", shCount);
7827 emitcode ("rr", "a");
7830 emitcode ("rr", "a");
7833 emitcode ("anl", "a,#0x01");
7837 emitcode ("mov", "c,acc[%d]", shCount);
7838 emitcode ("clr", "a");
7839 emitcode ("rlc", "a");
7842 emitcode ("swap", "a");
7843 emitcode ("anl", "a,#0x01");
7846 emitcode ("rl", "a");
7849 emitcode ("rl", "a");
7850 emitcode ("anl", "a,#0x01");
7856 freeAsmop (result, NULL, ic, TRUE);
7857 freeAsmop (right, NULL, ic, TRUE);
7858 freeAsmop (left, NULL, ic, TRUE);
7861 /*-----------------------------------------------------------------*/
7862 /* genGetByte - generates code get a single byte */
7863 /*-----------------------------------------------------------------*/
7865 genGetByte (iCode * ic)
7867 operand *left, *right, *result;
7870 D (emitcode (";", "genGetByte"));
7872 left = IC_LEFT (ic);
7873 right = IC_RIGHT (ic);
7874 result = IC_RESULT (ic);
7875 aopOp (left, ic, FALSE);
7876 aopOp (right, ic, FALSE);
7877 aopOp (result, ic, FALSE);
7879 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7881 aopGet (left, offset, FALSE, FALSE),
7884 freeAsmop (result, NULL, ic, TRUE);
7885 freeAsmop (right, NULL, ic, TRUE);
7886 freeAsmop (left, NULL, ic, TRUE);
7889 /*-----------------------------------------------------------------*/
7890 /* genGetWord - generates code get two bytes */
7891 /*-----------------------------------------------------------------*/
7893 genGetWord (iCode * ic)
7895 operand *left, *right, *result;
7898 D (emitcode (";", "genGetWord"));
7900 left = IC_LEFT (ic);
7901 right = IC_RIGHT (ic);
7902 result = IC_RESULT (ic);
7903 aopOp (left, ic, FALSE);
7904 aopOp (right, ic, FALSE);
7905 aopOp (result, ic, FALSE);
7907 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7909 aopGet (left, offset, FALSE, FALSE),
7912 aopGet (left, offset+1, FALSE, FALSE),
7915 freeAsmop (result, NULL, ic, TRUE);
7916 freeAsmop (right, NULL, ic, TRUE);
7917 freeAsmop (left, NULL, ic, TRUE);
7920 /*-----------------------------------------------------------------*/
7921 /* genSwap - generates code to swap nibbles or bytes */
7922 /*-----------------------------------------------------------------*/
7924 genSwap (iCode * ic)
7926 operand *left, *result;
7928 D(emitcode ("; genSwap",""));
7930 left = IC_LEFT (ic);
7931 result = IC_RESULT (ic);
7932 aopOp (left, ic, FALSE);
7933 aopOp (result, ic, FALSE);
7935 switch (AOP_SIZE (left))
7937 case 1: /* swap nibbles in byte */
7938 MOVA (aopGet (left, 0, FALSE, FALSE));
7939 emitcode ("swap", "a");
7940 aopPut (result, "a", 0);
7942 case 2: /* swap bytes in word */
7943 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7945 MOVA (aopGet (left, 0, FALSE, FALSE));
7946 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7947 aopPut (result, "a", 1);
7949 else if (operandsEqu (left, result))
7952 bool pushedB = FALSE, leftInB = FALSE;
7954 MOVA (aopGet (left, 0, FALSE, FALSE));
7955 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7958 emitcode ("mov", "b,a");
7962 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7963 aopPut (result, reg, 1);
7970 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7971 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7975 wassertl(FALSE, "unsupported SWAP operand size");
7978 freeAsmop (result, NULL, ic, TRUE);
7979 freeAsmop (left, NULL, ic, TRUE);
7982 /*-----------------------------------------------------------------*/
7983 /* AccRol - rotate left accumulator by known count */
7984 /*-----------------------------------------------------------------*/
7986 AccRol (int shCount)
7988 shCount &= 0x0007; // shCount : 0..7
7995 emitcode ("rl", "a");
7998 emitcode ("rl", "a");
7999 emitcode ("rl", "a");
8002 emitcode ("swap", "a");
8003 emitcode ("rr", "a");
8006 emitcode ("swap", "a");
8009 emitcode ("swap", "a");
8010 emitcode ("rl", "a");
8013 emitcode ("rr", "a");
8014 emitcode ("rr", "a");
8017 emitcode ("rr", "a");
8022 /*-----------------------------------------------------------------*/
8023 /* AccLsh - left shift accumulator by known count */
8024 /*-----------------------------------------------------------------*/
8026 AccLsh (int shCount)
8031 emitcode ("add", "a,acc");
8032 else if (shCount == 2)
8034 emitcode ("add", "a,acc");
8035 emitcode ("add", "a,acc");
8039 /* rotate left accumulator */
8041 /* and kill the lower order bits */
8042 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8047 /*-----------------------------------------------------------------*/
8048 /* AccRsh - right shift accumulator by known count */
8049 /*-----------------------------------------------------------------*/
8051 AccRsh (int shCount)
8058 emitcode ("rrc", "a");
8062 /* rotate right accumulator */
8063 AccRol (8 - shCount);
8064 /* and kill the higher order bits */
8065 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8070 /*-----------------------------------------------------------------*/
8071 /* AccSRsh - signed right shift accumulator by known count */
8072 /*-----------------------------------------------------------------*/
8074 AccSRsh (int shCount)
8081 emitcode ("mov", "c,acc.7");
8082 emitcode ("rrc", "a");
8084 else if (shCount == 2)
8086 emitcode ("mov", "c,acc.7");
8087 emitcode ("rrc", "a");
8088 emitcode ("mov", "c,acc.7");
8089 emitcode ("rrc", "a");
8093 tlbl = newiTempLabel (NULL);
8094 /* rotate right accumulator */
8095 AccRol (8 - shCount);
8096 /* and kill the higher order bits */
8097 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8098 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8099 emitcode ("orl", "a,#0x%02x",
8100 (unsigned char) ~SRMask[shCount]);
8106 /*-----------------------------------------------------------------*/
8107 /* shiftR1Left2Result - shift right one byte from left to result */
8108 /*-----------------------------------------------------------------*/
8110 shiftR1Left2Result (operand * left, int offl,
8111 operand * result, int offr,
8112 int shCount, int sign)
8114 MOVA (aopGet (left, offl, FALSE, FALSE));
8115 /* shift right accumulator */
8120 aopPut (result, "a", offr);
8123 /*-----------------------------------------------------------------*/
8124 /* shiftL1Left2Result - shift left one byte from left to result */
8125 /*-----------------------------------------------------------------*/
8127 shiftL1Left2Result (operand * left, int offl,
8128 operand * result, int offr, int shCount)
8131 l = aopGet (left, offl, FALSE, FALSE);
8133 /* shift left accumulator */
8135 aopPut (result, "a", offr);
8138 /*-----------------------------------------------------------------*/
8139 /* movLeft2Result - move byte from left to result */
8140 /*-----------------------------------------------------------------*/
8142 movLeft2Result (operand * left, int offl,
8143 operand * result, int offr, int sign)
8146 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8148 l = aopGet (left, offl, FALSE, FALSE);
8150 if (*l == '@' && (IS_AOP_PREG (result)))
8152 emitcode ("mov", "a,%s", l);
8153 aopPut (result, "a", offr);
8159 aopPut (result, l, offr);
8163 /* MSB sign in acc.7 ! */
8164 if (getDataSize (left) == offl + 1)
8167 aopPut (result, "a", offr);
8174 /*-----------------------------------------------------------------*/
8175 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8176 /*-----------------------------------------------------------------*/
8180 emitcode ("rrc", "a");
8181 emitcode ("xch", "a,%s", x);
8182 emitcode ("rrc", "a");
8183 emitcode ("xch", "a,%s", x);
8186 /*-----------------------------------------------------------------*/
8187 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8188 /*-----------------------------------------------------------------*/
8192 emitcode ("xch", "a,%s", x);
8193 emitcode ("rlc", "a");
8194 emitcode ("xch", "a,%s", x);
8195 emitcode ("rlc", "a");
8198 /*-----------------------------------------------------------------*/
8199 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8200 /*-----------------------------------------------------------------*/
8204 emitcode ("xch", "a,%s", x);
8205 emitcode ("add", "a,acc");
8206 emitcode ("xch", "a,%s", x);
8207 emitcode ("rlc", "a");
8210 /*-----------------------------------------------------------------*/
8211 /* AccAXLsh - left shift a:x by known count (0..7) */
8212 /*-----------------------------------------------------------------*/
8214 AccAXLsh (char *x, int shCount)
8229 case 5: // AAAAABBB:CCCCCDDD
8231 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8233 emitcode ("anl", "a,#0x%02x",
8234 SLMask[shCount]); // BBB00000:CCCCCDDD
8236 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8238 AccRol (shCount); // DDDCCCCC:BBB00000
8240 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8242 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8244 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8246 emitcode ("anl", "a,#0x%02x",
8247 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8249 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8251 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8254 case 6: // AAAAAABB:CCCCCCDD
8255 emitcode ("anl", "a,#0x%02x",
8256 SRMask[shCount]); // 000000BB:CCCCCCDD
8257 emitcode ("mov", "c,acc.0"); // c = B
8258 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8260 AccAXRrl1 (x); // BCCCCCCD:D000000B
8261 AccAXRrl1 (x); // BBCCCCCC:DD000000
8263 emitcode("rrc","a");
8264 emitcode("xch","a,%s", x);
8265 emitcode("rrc","a");
8266 emitcode("mov","c,acc.0"); //<< get correct bit
8267 emitcode("xch","a,%s", x);
8269 emitcode("rrc","a");
8270 emitcode("xch","a,%s", x);
8271 emitcode("rrc","a");
8272 emitcode("xch","a,%s", x);
8275 case 7: // a:x <<= 7
8277 emitcode ("anl", "a,#0x%02x",
8278 SRMask[shCount]); // 0000000B:CCCCCCCD
8280 emitcode ("mov", "c,acc.0"); // c = B
8282 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8284 AccAXRrl1 (x); // BCCCCCCC:D0000000
8292 /*-----------------------------------------------------------------*/
8293 /* AccAXRsh - right shift a:x known count (0..7) */
8294 /*-----------------------------------------------------------------*/
8296 AccAXRsh (char *x, int shCount)
8304 AccAXRrl1 (x); // 0->a:x
8309 AccAXRrl1 (x); // 0->a:x
8312 AccAXRrl1 (x); // 0->a:x
8317 case 5: // AAAAABBB:CCCCCDDD = a:x
8319 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8321 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8323 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8325 emitcode ("anl", "a,#0x%02x",
8326 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8328 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8330 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8332 emitcode ("anl", "a,#0x%02x",
8333 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8335 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8337 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8339 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8342 case 6: // AABBBBBB:CCDDDDDD
8344 emitcode ("mov", "c,acc.7");
8345 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8347 emitcode ("mov", "c,acc.7");
8348 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8350 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8352 emitcode ("anl", "a,#0x%02x",
8353 SRMask[shCount]); // 000000AA:BBBBBBCC
8356 case 7: // ABBBBBBB:CDDDDDDD
8358 emitcode ("mov", "c,acc.7"); // c = A
8360 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8362 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8364 emitcode ("anl", "a,#0x%02x",
8365 SRMask[shCount]); // 0000000A:BBBBBBBC
8373 /*-----------------------------------------------------------------*/
8374 /* AccAXRshS - right shift signed a:x known count (0..7) */
8375 /*-----------------------------------------------------------------*/
8377 AccAXRshS (char *x, int shCount)
8385 emitcode ("mov", "c,acc.7");
8386 AccAXRrl1 (x); // s->a:x
8390 emitcode ("mov", "c,acc.7");
8391 AccAXRrl1 (x); // s->a:x
8393 emitcode ("mov", "c,acc.7");
8394 AccAXRrl1 (x); // s->a:x
8399 case 5: // AAAAABBB:CCCCCDDD = a:x
8401 tlbl = newiTempLabel (NULL);
8402 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8404 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8406 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8408 emitcode ("anl", "a,#0x%02x",
8409 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8411 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8413 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8415 emitcode ("anl", "a,#0x%02x",
8416 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8418 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8420 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8422 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8424 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8425 emitcode ("orl", "a,#0x%02x",
8426 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8429 break; // SSSSAAAA:BBBCCCCC
8431 case 6: // AABBBBBB:CCDDDDDD
8433 tlbl = newiTempLabel (NULL);
8434 emitcode ("mov", "c,acc.7");
8435 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8437 emitcode ("mov", "c,acc.7");
8438 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8440 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8442 emitcode ("anl", "a,#0x%02x",
8443 SRMask[shCount]); // 000000AA:BBBBBBCC
8445 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8446 emitcode ("orl", "a,#0x%02x",
8447 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8451 case 7: // ABBBBBBB:CDDDDDDD
8453 tlbl = newiTempLabel (NULL);
8454 emitcode ("mov", "c,acc.7"); // c = A
8456 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8458 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8460 emitcode ("anl", "a,#0x%02x",
8461 SRMask[shCount]); // 0000000A:BBBBBBBC
8463 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8464 emitcode ("orl", "a,#0x%02x",
8465 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8474 /*-----------------------------------------------------------------*/
8475 /* shiftL2Left2Result - shift left two bytes from left to result */
8476 /*-----------------------------------------------------------------*/
8478 shiftL2Left2Result (operand * left, int offl,
8479 operand * result, int offr, int shCount)
8482 bool pushedB = FALSE;
8485 if (sameRegs (AOP (result), AOP (left)) &&
8486 ((offl + MSB16) == offr))
8488 /* don't crash result[offr] */
8489 MOVA (aopGet (left, offl, FALSE, FALSE));
8490 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8491 usedB = !strncmp(x, "b", 1);
8493 else if (aopGetUsesAcc (result, offr))
8495 movLeft2Result (left, offl, result, offr, 0);
8498 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8499 MOVA (aopGet (result, offr, FALSE, FALSE));
8500 emitcode ("xch", "a,b");
8505 movLeft2Result (left, offl, result, offr, 0);
8506 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8507 x = aopGet (result, offr, FALSE, FALSE);
8509 /* ax << shCount (x = lsb(result)) */
8510 AccAXLsh (x, shCount);
8513 emitcode ("xch", "a,b");
8514 aopPut (result, "a", offr);
8515 aopPut (result, "b", offr + MSB16);
8520 aopPut (result, "a", offr + MSB16);
8525 /*-----------------------------------------------------------------*/
8526 /* shiftR2Left2Result - shift right two bytes from left to result */
8527 /*-----------------------------------------------------------------*/
8529 shiftR2Left2Result (operand * left, int offl,
8530 operand * result, int offr,
8531 int shCount, int sign)
8534 bool pushedB = FALSE;
8537 if (sameRegs (AOP (result), AOP (left)) &&
8538 ((offl + MSB16) == offr))
8540 /* don't crash result[offr] */
8541 MOVA (aopGet (left, offl, FALSE, FALSE));
8542 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8543 usedB = !strncmp(x, "b", 1);
8545 else if (aopGetUsesAcc (result, offr))
8547 movLeft2Result (left, offl, result, offr, 0);
8550 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8551 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8556 movLeft2Result (left, offl, result, offr, 0);
8557 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8558 x = aopGet (result, offr, FALSE, FALSE);
8560 /* a:x >> shCount (x = lsb(result)) */
8562 AccAXRshS (x, shCount);
8564 AccAXRsh (x, shCount);
8567 emitcode ("xch", "a,b");
8568 aopPut (result, "a", offr);
8569 emitcode ("xch", "a,b");
8572 if (getDataSize (result) > 1)
8573 aopPut (result, "a", offr + MSB16);
8576 /*-----------------------------------------------------------------*/
8577 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8578 /*-----------------------------------------------------------------*/
8580 shiftLLeftOrResult (operand * left, int offl,
8581 operand * result, int offr, int shCount)
8583 MOVA (aopGet (left, offl, FALSE, FALSE));
8584 /* shift left accumulator */
8586 /* or with result */
8587 if (aopGetUsesAcc (result, offr))
8589 emitcode ("xch", "a,b");
8590 MOVA (aopGet (result, offr, FALSE, FALSE));
8591 emitcode ("orl", "a,b");
8595 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8597 /* back to result */
8598 aopPut (result, "a", offr);
8601 /*-----------------------------------------------------------------*/
8602 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8603 /*-----------------------------------------------------------------*/
8605 shiftRLeftOrResult (operand * left, int offl,
8606 operand * result, int offr, int shCount)
8608 MOVA (aopGet (left, offl, FALSE, FALSE));
8609 /* shift right accumulator */
8611 /* or with result */
8612 if (aopGetUsesAcc(result, offr))
8614 emitcode ("xch", "a,b");
8615 MOVA (aopGet (result, offr, FALSE, FALSE));
8616 emitcode ("orl", "a,b");
8620 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8622 /* back to result */
8623 aopPut (result, "a", offr);
8626 /*-----------------------------------------------------------------*/
8627 /* genlshOne - left shift a one byte quantity by known count */
8628 /*-----------------------------------------------------------------*/
8630 genlshOne (operand * result, operand * left, int shCount)
8632 D (emitcode (";", "genlshOne"));
8634 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8637 /*-----------------------------------------------------------------*/
8638 /* genlshTwo - left shift two bytes by known amount != 0 */
8639 /*-----------------------------------------------------------------*/
8641 genlshTwo (operand * result, operand * left, int shCount)
8645 D (emitcode (";", "genlshTwo"));
8647 size = getDataSize (result);
8649 /* if shCount >= 8 */
8657 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8659 movLeft2Result (left, LSB, result, MSB16, 0);
8661 aopPut (result, zero, LSB);
8664 /* 1 <= shCount <= 7 */
8668 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8670 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8674 /*-----------------------------------------------------------------*/
8675 /* shiftLLong - shift left one long from left to result */
8676 /* offl = LSB or MSB16 */
8677 /*-----------------------------------------------------------------*/
8679 shiftLLong (operand * left, operand * result, int offr)
8682 int size = AOP_SIZE (result);
8684 if (size >= LSB + offr)
8686 l = aopGet (left, LSB, FALSE, FALSE);
8688 emitcode ("add", "a,acc");
8689 if (sameRegs (AOP (left), AOP (result)) &&
8690 size >= MSB16 + offr && offr != LSB)
8691 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8693 aopPut (result, "a", LSB + offr);
8696 if (size >= MSB16 + offr)
8698 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8700 l = aopGet (left, MSB16, FALSE, FALSE);
8703 emitcode ("rlc", "a");
8704 if (sameRegs (AOP (left), AOP (result)) &&
8705 size >= MSB24 + offr && offr != LSB)
8706 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8708 aopPut (result, "a", MSB16 + offr);
8711 if (size >= MSB24 + offr)
8713 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8715 l = aopGet (left, MSB24, FALSE, FALSE);
8718 emitcode ("rlc", "a");
8719 if (sameRegs (AOP (left), AOP (result)) &&
8720 size >= MSB32 + offr && offr != LSB)
8721 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8723 aopPut (result, "a", MSB24 + offr);
8726 if (size > MSB32 + offr)
8728 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8730 l = aopGet (left, MSB32, FALSE, FALSE);
8733 emitcode ("rlc", "a");
8734 aopPut (result, "a", MSB32 + offr);
8737 aopPut (result, zero, LSB);
8740 /*-----------------------------------------------------------------*/
8741 /* genlshFour - shift four byte by a known amount != 0 */
8742 /*-----------------------------------------------------------------*/
8744 genlshFour (operand * result, operand * left, int shCount)
8748 D (emitcode (";", "genlshFour"));
8750 size = AOP_SIZE (result);
8752 /* if shifting more that 3 bytes */
8757 /* lowest order of left goes to the highest
8758 order of the destination */
8759 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8761 movLeft2Result (left, LSB, result, MSB32, 0);
8762 aopPut (result, zero, LSB);
8763 aopPut (result, zero, MSB16);
8764 aopPut (result, zero, MSB24);
8768 /* more than two bytes */
8769 else if (shCount >= 16)
8771 /* lower order two bytes goes to higher order two bytes */
8773 /* if some more remaining */
8775 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8778 movLeft2Result (left, MSB16, result, MSB32, 0);
8779 movLeft2Result (left, LSB, result, MSB24, 0);
8781 aopPut (result, zero, MSB16);
8782 aopPut (result, zero, LSB);
8786 /* if more than 1 byte */
8787 else if (shCount >= 8)
8789 /* lower order three bytes goes to higher order three bytes */
8794 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8796 movLeft2Result (left, LSB, result, MSB16, 0);
8802 movLeft2Result (left, MSB24, result, MSB32, 0);
8803 movLeft2Result (left, MSB16, result, MSB24, 0);
8804 movLeft2Result (left, LSB, result, MSB16, 0);
8805 aopPut (result, zero, LSB);
8807 else if (shCount == 1)
8808 shiftLLong (left, result, MSB16);
8811 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8812 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8813 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8814 aopPut (result, zero, LSB);
8819 /* 1 <= shCount <= 7 */
8820 else if (shCount <= 2)
8822 shiftLLong (left, result, LSB);
8824 shiftLLong (result, result, LSB);
8826 /* 3 <= shCount <= 7, optimize */
8829 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8830 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8831 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8835 /*-----------------------------------------------------------------*/
8836 /* genLeftShiftLiteral - left shifting by known count */
8837 /*-----------------------------------------------------------------*/
8839 genLeftShiftLiteral (operand * left,
8844 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8847 D (emitcode (";", "genLeftShiftLiteral"));
8849 freeAsmop (right, NULL, ic, TRUE);
8851 aopOp (left, ic, FALSE);
8852 aopOp (result, ic, FALSE);
8854 size = getSize (operandType (result));
8857 emitcode ("; shift left ", "result %d, left %d", size,
8861 /* I suppose that the left size >= result size */
8866 movLeft2Result (left, size, result, size, 0);
8869 else if (shCount >= (size * 8))
8873 aopPut (result, zero, size);
8881 genlshOne (result, left, shCount);
8885 genlshTwo (result, left, shCount);
8889 genlshFour (result, left, shCount);
8892 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8893 "*** ack! mystery literal shift!\n");
8897 freeAsmop (result, NULL, ic, TRUE);
8898 freeAsmop (left, NULL, ic, TRUE);
8901 /*-----------------------------------------------------------------*/
8902 /* genLeftShift - generates code for left shifting */
8903 /*-----------------------------------------------------------------*/
8905 genLeftShift (iCode * ic)
8907 operand *left, *right, *result;
8910 symbol *tlbl, *tlbl1;
8913 D (emitcode (";", "genLeftShift"));
8915 right = IC_RIGHT (ic);
8916 left = IC_LEFT (ic);
8917 result = IC_RESULT (ic);
8919 aopOp (right, ic, FALSE);
8921 /* if the shift count is known then do it
8922 as efficiently as possible */
8923 if (AOP_TYPE (right) == AOP_LIT)
8925 genLeftShiftLiteral (left, right, result, ic);
8929 /* shift count is unknown then we have to form
8930 a loop get the loop count in B : Note: we take
8931 only the lower order byte since shifting
8932 more that 32 bits make no sense anyway, ( the
8933 largest size of an object can be only 32 bits ) */
8936 MOVB (aopGet (right, 0, FALSE, FALSE));
8937 emitcode ("inc", "b");
8938 freeAsmop (right, NULL, ic, TRUE);
8939 aopOp (left, ic, FALSE);
8940 aopOp (result, ic, FALSE);
8942 /* now move the left to the result if they are not the same */
8943 if (!sameRegs (AOP (left), AOP (result)) &&
8944 AOP_SIZE (result) > 1)
8947 size = AOP_SIZE (result);
8951 l = aopGet (left, offset, FALSE, TRUE);
8952 if (*l == '@' && (IS_AOP_PREG (result)))
8955 emitcode ("mov", "a,%s", l);
8956 aopPut (result, "a", offset);
8959 aopPut (result, l, offset);
8964 tlbl = newiTempLabel (NULL);
8965 size = AOP_SIZE (result);
8967 tlbl1 = newiTempLabel (NULL);
8969 /* if it is only one byte then */
8972 symbol *tlbl1 = newiTempLabel (NULL);
8974 l = aopGet (left, 0, FALSE, FALSE);
8976 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8978 emitcode ("add", "a,acc");
8980 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8982 aopPut (result, "a", 0);
8986 reAdjustPreg (AOP (result));
8988 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8990 l = aopGet (result, offset, FALSE, FALSE);
8992 emitcode ("add", "a,acc");
8993 aopPut (result, "a", offset++);
8996 l = aopGet (result, offset, FALSE, FALSE);
8998 emitcode ("rlc", "a");
8999 aopPut (result, "a", offset++);
9001 reAdjustPreg (AOP (result));
9004 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9007 freeAsmop (result, NULL, ic, TRUE);
9008 freeAsmop (left, NULL, ic, TRUE);
9011 /*-----------------------------------------------------------------*/
9012 /* genrshOne - right shift a one byte quantity by known count */
9013 /*-----------------------------------------------------------------*/
9015 genrshOne (operand * result, operand * left,
9016 int shCount, int sign)
9018 D (emitcode (";", "genrshOne"));
9020 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9023 /*-----------------------------------------------------------------*/
9024 /* genrshTwo - right shift two bytes by known amount != 0 */
9025 /*-----------------------------------------------------------------*/
9027 genrshTwo (operand * result, operand * left,
9028 int shCount, int sign)
9030 D (emitcode (";", "genrshTwo"));
9032 /* if shCount >= 8 */
9037 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9039 movLeft2Result (left, MSB16, result, LSB, sign);
9040 addSign (result, MSB16, sign);
9043 /* 1 <= shCount <= 7 */
9045 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9048 /*-----------------------------------------------------------------*/
9049 /* shiftRLong - shift right one long from left to result */
9050 /* offl = LSB or MSB16 */
9051 /*-----------------------------------------------------------------*/
9053 shiftRLong (operand * left, int offl,
9054 operand * result, int sign)
9056 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9058 if (overlapping && offl>1)
9060 // we are in big trouble, but this shouldn't happen
9061 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9064 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9071 emitcode ("rlc", "a");
9072 emitcode ("subb", "a,acc");
9073 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9075 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9079 aopPut (result, "a", MSB32);
9080 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9085 if (aopPutUsesAcc (result, zero, MSB32))
9087 emitcode("xch", "a,b");
9088 aopPut (result, zero, MSB32);
9089 emitcode("xch", "a,b");
9093 aopPut (result, zero, MSB32);
9100 emitcode ("clr", "c");
9104 emitcode ("mov", "c,acc.7");
9107 emitcode ("rrc", "a");
9109 if (overlapping && offl==MSB16 &&
9110 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9112 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9116 aopPut (result, "a", MSB32 - offl);
9117 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9120 emitcode ("rrc", "a");
9121 if (overlapping && offl==MSB16 &&
9122 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9124 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9128 aopPut (result, "a", MSB24 - offl);
9129 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9132 emitcode ("rrc", "a");
9135 aopPut (result, "a", MSB16 - offl);
9140 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9142 xch_a_aopGet (left, LSB, FALSE, FALSE);
9146 aopPut (result, "a", MSB16 - offl);
9147 MOVA (aopGet (left, LSB, FALSE, FALSE));
9149 emitcode ("rrc", "a");
9150 aopPut (result, "a", LSB);
9154 /*-----------------------------------------------------------------*/
9155 /* genrshFour - shift four byte by a known amount != 0 */
9156 /*-----------------------------------------------------------------*/
9158 genrshFour (operand * result, operand * left,
9159 int shCount, int sign)
9161 D (emitcode (";", "genrshFour"));
9163 /* if shifting more that 3 bytes */
9168 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9170 movLeft2Result (left, MSB32, result, LSB, sign);
9171 addSign (result, MSB16, sign);
9173 else if (shCount >= 16)
9177 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9180 movLeft2Result (left, MSB24, result, LSB, 0);
9181 movLeft2Result (left, MSB32, result, MSB16, sign);
9183 addSign (result, MSB24, sign);
9185 else if (shCount >= 8)
9190 shiftRLong (left, MSB16, result, sign);
9192 else if (shCount == 0)
9194 movLeft2Result (left, MSB16, result, LSB, 0);
9195 movLeft2Result (left, MSB24, result, MSB16, 0);
9196 movLeft2Result (left, MSB32, result, MSB24, sign);
9197 addSign (result, MSB32, sign);
9201 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9202 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9203 /* the last shift is signed */
9204 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9205 addSign (result, MSB32, sign);
9210 /* 1 <= shCount <= 7 */
9213 shiftRLong (left, LSB, result, sign);
9215 shiftRLong (result, LSB, result, sign);
9219 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9220 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9221 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9226 /*-----------------------------------------------------------------*/
9227 /* genRightShiftLiteral - right shifting by known count */
9228 /*-----------------------------------------------------------------*/
9230 genRightShiftLiteral (operand * left,
9236 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9239 D (emitcode (";", "genRightShiftLiteral"));
9241 freeAsmop (right, NULL, ic, TRUE);
9243 aopOp (left, ic, FALSE);
9244 aopOp (result, ic, FALSE);
9247 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9251 size = getDataSize (left);
9252 /* test the LEFT size !!! */
9254 /* I suppose that the left size >= result size */
9257 size = getDataSize (result);
9259 movLeft2Result (left, size, result, size, 0);
9262 else if (shCount >= (size * 8))
9266 /* get sign in acc.7 */
9267 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9269 addSign (result, LSB, sign);
9276 genrshOne (result, left, shCount, sign);
9280 genrshTwo (result, left, shCount, sign);
9284 genrshFour (result, left, shCount, sign);
9290 freeAsmop (result, NULL, ic, TRUE);
9291 freeAsmop (left, NULL, ic, TRUE);
9294 /*-----------------------------------------------------------------*/
9295 /* genSignedRightShift - right shift of signed number */
9296 /*-----------------------------------------------------------------*/
9298 genSignedRightShift (iCode * ic)
9300 operand *right, *left, *result;
9303 symbol *tlbl, *tlbl1;
9306 D (emitcode (";", "genSignedRightShift"));
9308 /* we do it the hard way put the shift count in b
9309 and loop thru preserving the sign */
9311 right = IC_RIGHT (ic);
9312 left = IC_LEFT (ic);
9313 result = IC_RESULT (ic);
9315 aopOp (right, ic, FALSE);
9318 if (AOP_TYPE (right) == AOP_LIT)
9320 genRightShiftLiteral (left, right, result, ic, 1);
9323 /* shift count is unknown then we have to form
9324 a loop get the loop count in B : Note: we take
9325 only the lower order byte since shifting
9326 more that 32 bits make no sense anyway, ( the
9327 largest size of an object can be only 32 bits ) */
9330 MOVB (aopGet (right, 0, FALSE, FALSE));
9331 emitcode ("inc", "b");
9332 freeAsmop (right, NULL, ic, TRUE);
9333 aopOp (left, ic, FALSE);
9334 aopOp (result, ic, FALSE);
9336 /* now move the left to the result if they are not the
9338 if (!sameRegs (AOP (left), AOP (result)) &&
9339 AOP_SIZE (result) > 1)
9342 size = AOP_SIZE (result);
9346 l = aopGet (left, offset, FALSE, TRUE);
9347 if (*l == '@' && IS_AOP_PREG (result))
9350 emitcode ("mov", "a,%s", l);
9351 aopPut (result, "a", offset);
9354 aopPut (result, l, offset);
9359 /* mov the highest order bit to OVR */
9360 tlbl = newiTempLabel (NULL);
9361 tlbl1 = newiTempLabel (NULL);
9363 size = AOP_SIZE (result);
9365 MOVA (aopGet (left, offset, FALSE, FALSE));
9366 emitcode ("rlc", "a");
9367 emitcode ("mov", "ov,c");
9368 /* if it is only one byte then */
9371 l = aopGet (left, 0, FALSE, FALSE);
9373 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9375 emitcode ("mov", "c,ov");
9376 emitcode ("rrc", "a");
9378 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9380 aopPut (result, "a", 0);
9384 reAdjustPreg (AOP (result));
9385 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9387 emitcode ("mov", "c,ov");
9390 l = aopGet (result, offset, FALSE, FALSE);
9392 emitcode ("rrc", "a");
9393 aopPut (result, "a", offset--);
9395 reAdjustPreg (AOP (result));
9397 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9401 freeAsmop (result, NULL, ic, TRUE);
9402 freeAsmop (left, NULL, ic, TRUE);
9405 /*-----------------------------------------------------------------*/
9406 /* genRightShift - generate code for right shifting */
9407 /*-----------------------------------------------------------------*/
9409 genRightShift (iCode * ic)
9411 operand *right, *left, *result;
9415 symbol *tlbl, *tlbl1;
9418 D (emitcode (";", "genRightShift"));
9420 /* if signed then we do it the hard way preserve the
9421 sign bit moving it inwards */
9422 letype = getSpec (operandType (IC_LEFT (ic)));
9424 if (!SPEC_USIGN (letype))
9426 genSignedRightShift (ic);
9430 /* signed & unsigned types are treated the same : i.e. the
9431 signed is NOT propagated inwards : quoting from the
9432 ANSI - standard : "for E1 >> E2, is equivalent to division
9433 by 2**E2 if unsigned or if it has a non-negative value,
9434 otherwise the result is implementation defined ", MY definition
9435 is that the sign does not get propagated */
9437 right = IC_RIGHT (ic);
9438 left = IC_LEFT (ic);
9439 result = IC_RESULT (ic);
9441 aopOp (right, ic, FALSE);
9443 /* if the shift count is known then do it
9444 as efficiently as possible */
9445 if (AOP_TYPE (right) == AOP_LIT)
9447 genRightShiftLiteral (left, right, result, ic, 0);
9451 /* shift count is unknown then we have to form
9452 a loop get the loop count in B : Note: we take
9453 only the lower order byte since shifting
9454 more that 32 bits make no sense anyway, ( the
9455 largest size of an object can be only 32 bits ) */
9458 MOVB (aopGet (right, 0, FALSE, FALSE));
9459 emitcode ("inc", "b");
9460 freeAsmop (right, NULL, ic, TRUE);
9461 aopOp (left, ic, FALSE);
9462 aopOp (result, ic, FALSE);
9464 /* now move the left to the result if they are not the
9466 if (!sameRegs (AOP (left), AOP (result)) &&
9467 AOP_SIZE (result) > 1)
9469 size = AOP_SIZE (result);
9473 l = aopGet (left, offset, FALSE, TRUE);
9474 if (*l == '@' && IS_AOP_PREG (result))
9477 emitcode ("mov", "a,%s", l);
9478 aopPut (result, "a", offset);
9481 aopPut (result, l, offset);
9486 tlbl = newiTempLabel (NULL);
9487 tlbl1 = newiTempLabel (NULL);
9488 size = AOP_SIZE (result);
9491 /* if it is only one byte then */
9494 l = aopGet (left, 0, FALSE, FALSE);
9496 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9499 emitcode ("rrc", "a");
9501 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9503 aopPut (result, "a", 0);
9507 reAdjustPreg (AOP (result));
9508 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9513 l = aopGet (result, offset, FALSE, FALSE);
9515 emitcode ("rrc", "a");
9516 aopPut (result, "a", offset--);
9518 reAdjustPreg (AOP (result));
9521 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9525 freeAsmop (result, NULL, ic, TRUE);
9526 freeAsmop (left, NULL, ic, TRUE);
9529 /*-----------------------------------------------------------------*/
9530 /* emitPtrByteGet - emits code to get a byte into A through a */
9531 /* pointer register (R0, R1, or DPTR). The */
9532 /* original value of A can be preserved in B. */
9533 /*-----------------------------------------------------------------*/
9535 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9542 emitcode ("mov", "b,a");
9543 emitcode ("mov", "a,@%s", rname);
9548 emitcode ("mov", "b,a");
9549 emitcode ("movx", "a,@%s", rname);
9554 emitcode ("mov", "b,a");
9555 emitcode ("movx", "a,@dptr");
9560 emitcode ("mov", "b,a");
9561 emitcode ("clr", "a");
9562 emitcode ("movc", "a,@a+dptr");
9568 emitcode ("push", "b");
9569 emitcode ("push", "acc");
9571 emitcode ("lcall", "__gptrget");
9573 emitcode ("pop", "b");
9578 /*-----------------------------------------------------------------*/
9579 /* emitPtrByteSet - emits code to set a byte from src through a */
9580 /* pointer register (R0, R1, or DPTR). */
9581 /*-----------------------------------------------------------------*/
9583 emitPtrByteSet (char *rname, int p_type, char *src)
9592 emitcode ("mov", "@%s,a", rname);
9595 emitcode ("mov", "@%s,%s", rname, src);
9600 emitcode ("movx", "@%s,a", rname);
9605 emitcode ("movx", "@dptr,a");
9610 emitcode ("lcall", "__gptrput");
9615 /*-----------------------------------------------------------------*/
9616 /* genUnpackBits - generates code for unpacking bits */
9617 /*-----------------------------------------------------------------*/
9619 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9621 int offset = 0; /* result byte offset */
9622 int rsize; /* result size */
9623 int rlen = 0; /* remaining bitfield length */
9624 sym_link *etype; /* bitfield type information */
9625 int blen; /* bitfield length */
9626 int bstr; /* bitfield starting bit within byte */
9629 D(emitcode ("; genUnpackBits",""));
9631 etype = getSpec (operandType (result));
9632 rsize = getSize (operandType (result));
9633 blen = SPEC_BLEN (etype);
9634 bstr = SPEC_BSTR (etype);
9636 if (ifx && blen <= 8)
9638 emitPtrByteGet (rname, ptype, FALSE);
9641 SNPRINTF (buffer, sizeof(buffer),
9643 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9648 emitcode ("anl", "a,#0x%02x",
9649 (((unsigned char) -1) >> (8 - blen)) << bstr);
9650 genIfxJump (ifx, "a", NULL, NULL, NULL);
9656 /* If the bitfield length is less than a byte */
9659 emitPtrByteGet (rname, ptype, FALSE);
9661 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9662 if (!SPEC_USIGN (etype))
9664 /* signed bitfield */
9665 symbol *tlbl = newiTempLabel (NULL);
9667 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9668 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9671 aopPut (result, "a", offset++);
9675 /* Bit field did not fit in a byte. Copy all
9676 but the partial byte at the end. */
9677 for (rlen=blen;rlen>=8;rlen-=8)
9679 emitPtrByteGet (rname, ptype, FALSE);
9680 aopPut (result, "a", offset++);
9682 emitcode ("inc", "%s", rname);
9685 /* Handle the partial byte at the end */
9688 emitPtrByteGet (rname, ptype, FALSE);
9689 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9690 if (!SPEC_USIGN (etype))
9692 /* signed bitfield */
9693 symbol *tlbl = newiTempLabel (NULL);
9695 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9696 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9699 aopPut (result, "a", offset++);
9707 if (SPEC_USIGN (etype))
9711 /* signed bitfield: sign extension with 0x00 or 0xff */
9712 emitcode ("rlc", "a");
9713 emitcode ("subb", "a,acc");
9719 aopPut (result, source, offset++);
9724 /*-----------------------------------------------------------------*/
9725 /* genDataPointerGet - generates code when ptr offset is known */
9726 /*-----------------------------------------------------------------*/
9728 genDataPointerGet (operand * left,
9734 int size, offset = 0;
9736 D (emitcode (";", "genDataPointerGet"));
9738 aopOp (result, ic, TRUE);
9740 /* get the string representation of the name */
9741 l = aopGet (left, 0, FALSE, TRUE);
9743 size = AOP_SIZE (result);
9748 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9752 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9754 aopPut (result, buffer, offset++);
9757 freeAsmop (result, NULL, ic, TRUE);
9758 freeAsmop (left, NULL, ic, TRUE);
9761 /*-----------------------------------------------------------------*/
9762 /* genNearPointerGet - emitcode for near pointer fetch */
9763 /*-----------------------------------------------------------------*/
9765 genNearPointerGet (operand * left,
9774 sym_link *rtype, *retype;
9775 sym_link *ltype = operandType (left);
9778 D (emitcode (";", "genNearPointerGet"));
9780 rtype = operandType (result);
9781 retype = getSpec (rtype);
9783 aopOp (left, ic, FALSE);
9785 /* if left is rematerialisable and
9786 result is not bitfield variable type and
9787 the left is pointer to data space i.e
9788 lower 128 bytes of space */
9789 if (AOP_TYPE (left) == AOP_IMMD &&
9790 !IS_BITFIELD (retype) &&
9791 DCL_TYPE (ltype) == POINTER)
9793 genDataPointerGet (left, result, ic);
9797 /* if the value is already in a pointer register
9798 then don't need anything more */
9799 if (!AOP_INPREG (AOP (left)))
9801 if (IS_AOP_PREG (left))
9803 // Aha, it is a pointer, just in disguise.
9804 rname = aopGet (left, 0, FALSE, FALSE);
9807 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9808 __FILE__, __LINE__);
9813 emitcode ("mov", "a%s,%s", rname + 1, rname);
9814 rname++; // skip the '@'.
9819 /* otherwise get a free pointer register */
9821 preg = getFreePtr (ic, &aop, FALSE);
9822 emitcode ("mov", "%s,%s",
9824 aopGet (left, 0, FALSE, TRUE));
9829 rname = aopGet (left, 0, FALSE, FALSE);
9831 //aopOp (result, ic, FALSE);
9832 aopOp (result, ic, result?TRUE:FALSE);
9834 /* if bitfield then unpack the bits */
9835 if (IS_BITFIELD (retype))
9836 genUnpackBits (result, rname, POINTER, ifx);
9839 /* we have can just get the values */
9840 int size = AOP_SIZE (result);
9845 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9848 emitcode ("mov", "a,@%s", rname);
9850 aopPut (result, "a", offset);
9854 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9855 aopPut (result, buffer, offset);
9859 emitcode ("inc", "%s", rname);
9863 /* now some housekeeping stuff */
9864 if (aop) /* we had to allocate for this iCode */
9866 if (pi) { /* post increment present */
9867 aopPut (left, rname, 0);
9869 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9873 /* we did not allocate which means left
9874 already in a pointer register, then
9875 if size > 0 && this could be used again
9876 we have to point it back to where it
9878 if ((AOP_SIZE (result) > 1 &&
9879 !OP_SYMBOL (left)->remat &&
9880 (OP_SYMBOL (left)->liveTo > ic->seq ||
9884 int size = AOP_SIZE (result) - 1;
9886 emitcode ("dec", "%s", rname);
9890 if (ifx && !ifx->generated)
9892 genIfxJump (ifx, "a", left, NULL, result);
9896 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9897 freeAsmop (left, NULL, ic, TRUE);
9898 if (pi) pi->generated = 1;
9901 /*-----------------------------------------------------------------*/
9902 /* genPagedPointerGet - emitcode for paged pointer fetch */
9903 /*-----------------------------------------------------------------*/
9905 genPagedPointerGet (operand * left,
9914 sym_link *rtype, *retype;
9916 D (emitcode (";", "genPagedPointerGet"));
9918 rtype = operandType (result);
9919 retype = getSpec (rtype);
9921 aopOp (left, ic, FALSE);
9923 /* if the value is already in a pointer register
9924 then don't need anything more */
9925 if (!AOP_INPREG (AOP (left)))
9927 /* otherwise get a free pointer register */
9929 preg = getFreePtr (ic, &aop, FALSE);
9930 emitcode ("mov", "%s,%s",
9932 aopGet (left, 0, FALSE, TRUE));
9936 rname = aopGet (left, 0, FALSE, FALSE);
9938 aopOp (result, ic, FALSE);
9940 /* if bitfield then unpack the bits */
9941 if (IS_BITFIELD (retype))
9942 genUnpackBits (result, rname, PPOINTER, ifx);
9945 /* we have can just get the values */
9946 int size = AOP_SIZE (result);
9952 emitcode ("movx", "a,@%s", rname);
9954 aopPut (result, "a", offset);
9959 emitcode ("inc", "%s", rname);
9963 /* now some housekeeping stuff */
9964 if (aop) /* we had to allocate for this iCode */
9967 aopPut (left, rname, 0);
9968 freeAsmop (NULL, aop, ic, TRUE);
9972 /* we did not allocate which means left
9973 already in a pointer register, then
9974 if size > 0 && this could be used again
9975 we have to point it back to where it
9977 if ((AOP_SIZE (result) > 1 &&
9978 !OP_SYMBOL (left)->remat &&
9979 (OP_SYMBOL (left)->liveTo > ic->seq ||
9983 int size = AOP_SIZE (result) - 1;
9985 emitcode ("dec", "%s", rname);
9989 if (ifx && !ifx->generated)
9991 genIfxJump (ifx, "a", left, NULL, result);
9995 freeAsmop (result, NULL, ic, TRUE);
9996 freeAsmop (left, NULL, ic, TRUE);
9997 if (pi) pi->generated = 1;
10000 /*--------------------------------------------------------------------*/
10001 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10002 /*--------------------------------------------------------------------*/
10004 loadDptrFromOperand (operand *op, bool loadBToo)
10006 if (AOP_TYPE (op) != AOP_STR)
10008 /* if this is rematerializable */
10009 if (AOP_TYPE (op) == AOP_IMMD)
10011 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10014 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10015 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10018 wassertl(FALSE, "need pointerCode");
10019 emitcode ("", "; mov b,???");
10020 /* genPointerGet and genPointerSet originally did different
10021 ** things for this case. Both seem wrong.
10022 ** from genPointerGet:
10023 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10024 ** from genPointerSet:
10025 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10030 else if (AOP_TYPE (op) == AOP_DPTR)
10034 MOVA (aopGet (op, 0, FALSE, FALSE));
10035 emitcode ("push", "acc");
10036 MOVA (aopGet (op, 1, FALSE, FALSE));
10037 emitcode ("push", "acc");
10038 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10039 emitcode ("pop", "dph");
10040 emitcode ("pop", "dpl");
10044 MOVA (aopGet (op, 0, FALSE, FALSE));
10045 emitcode ("push", "acc");
10046 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10047 emitcode ("pop", "dpl");
10051 { /* we need to get it byte by byte */
10052 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10053 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10055 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerGet - get value from far space */
10062 /*-----------------------------------------------------------------*/
10064 genFarPointerGet (operand * left,
10065 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10068 sym_link *retype = getSpec (operandType (result));
10070 D (emitcode (";", "genFarPointerGet"));
10072 aopOp (left, ic, FALSE);
10073 loadDptrFromOperand (left, FALSE);
10075 /* so dptr now contains the address */
10076 aopOp (result, ic, FALSE);
10078 /* if bit then unpack */
10079 if (IS_BITFIELD (retype))
10080 genUnpackBits (result, "dptr", FPOINTER, ifx);
10083 size = AOP_SIZE (result);
10088 emitcode ("movx", "a,@dptr");
10090 aopPut (result, "a", offset++);
10092 emitcode ("inc", "dptr");
10096 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10098 aopPut (left, "dpl", 0);
10099 aopPut (left, "dph", 1);
10103 if (ifx && !ifx->generated)
10105 genIfxJump (ifx, "a", left, NULL, result);
10108 freeAsmop (result, NULL, ic, TRUE);
10109 freeAsmop (left, NULL, ic, TRUE);
10112 /*-----------------------------------------------------------------*/
10113 /* genCodePointerGet - get value from code space */
10114 /*-----------------------------------------------------------------*/
10116 genCodePointerGet (operand * left,
10117 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10120 sym_link *retype = getSpec (operandType (result));
10122 D (emitcode (";", "genCodePointerGet"));
10124 aopOp (left, ic, FALSE);
10125 loadDptrFromOperand (left, FALSE);
10127 /* so dptr now contains the address */
10128 aopOp (result, ic, FALSE);
10130 /* if bit then unpack */
10131 if (IS_BITFIELD (retype))
10132 genUnpackBits (result, "dptr", CPOINTER, ifx);
10135 size = AOP_SIZE (result);
10140 emitcode ("clr", "a");
10141 emitcode ("movc", "a,@a+dptr");
10143 aopPut (result, "a", offset++);
10145 emitcode ("inc", "dptr");
10149 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10151 aopPut (left, "dpl", 0);
10152 aopPut (left, "dph", 1);
10156 if (ifx && !ifx->generated)
10158 genIfxJump (ifx, "a", left, NULL, result);
10161 freeAsmop (result, NULL, ic, TRUE);
10162 freeAsmop (left, NULL, ic, TRUE);
10165 /*-----------------------------------------------------------------*/
10166 /* genGenPointerGet - get value from generic pointer space */
10167 /*-----------------------------------------------------------------*/
10169 genGenPointerGet (operand * left,
10170 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10173 sym_link *retype = getSpec (operandType (result));
10175 D (emitcode (";", "genGenPointerGet"));
10177 aopOp (left, ic, FALSE);
10178 loadDptrFromOperand (left, TRUE);
10180 /* so dptr now contains the address */
10181 aopOp (result, ic, FALSE);
10183 /* if bit then unpack */
10184 if (IS_BITFIELD (retype))
10186 genUnpackBits (result, "dptr", GPOINTER, ifx);
10190 size = AOP_SIZE (result);
10195 emitcode ("lcall", "__gptrget");
10197 aopPut (result, "a", offset++);
10199 emitcode ("inc", "dptr");
10203 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10205 aopPut (left, "dpl", 0);
10206 aopPut (left, "dph", 1);
10210 if (ifx && !ifx->generated)
10212 genIfxJump (ifx, "a", left, NULL, result);
10215 freeAsmop (result, NULL, ic, TRUE);
10216 freeAsmop (left, NULL, ic, TRUE);
10219 /*-----------------------------------------------------------------*/
10220 /* genPointerGet - generate code for pointer get */
10221 /*-----------------------------------------------------------------*/
10223 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10225 operand *left, *result;
10226 sym_link *type, *etype;
10229 D (emitcode (";", "genPointerGet"));
10231 left = IC_LEFT (ic);
10232 result = IC_RESULT (ic);
10234 if (getSize (operandType (result))>1)
10237 /* depending on the type of pointer we need to
10238 move it to the correct pointer register */
10239 type = operandType (left);
10240 etype = getSpec (type);
10241 /* if left is of type of pointer then it is simple */
10242 if (IS_PTR (type) && !IS_FUNC (type->next))
10243 p_type = DCL_TYPE (type);
10246 /* we have to go by the storage class */
10247 p_type = PTR_TYPE (SPEC_OCLS (etype));
10250 /* special case when cast remat */
10251 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10252 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10254 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10255 type = operandType (left);
10256 p_type = DCL_TYPE (type);
10258 /* now that we have the pointer type we assign
10259 the pointer values */
10265 genNearPointerGet (left, result, ic, pi, ifx);
10269 genPagedPointerGet (left, result, ic, pi, ifx);
10273 genFarPointerGet (left, result, ic, pi, ifx);
10277 genCodePointerGet (left, result, ic, pi, ifx);
10281 genGenPointerGet (left, result, ic, pi, ifx);
10287 /*-----------------------------------------------------------------*/
10288 /* genPackBits - generates code for packed bit storage */
10289 /*-----------------------------------------------------------------*/
10291 genPackBits (sym_link * etype,
10293 char *rname, int p_type)
10295 int offset = 0; /* source byte offset */
10296 int rlen = 0; /* remaining bitfield length */
10297 int blen; /* bitfield length */
10298 int bstr; /* bitfield starting bit within byte */
10299 int litval; /* source literal value (if AOP_LIT) */
10300 unsigned char mask; /* bitmask within current byte */
10302 D(emitcode ("; genPackBits",""));
10304 blen = SPEC_BLEN (etype);
10305 bstr = SPEC_BSTR (etype);
10307 /* If the bitfield length is less than a byte */
10310 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10311 (unsigned char) (0xFF >> (8 - bstr)));
10313 if (AOP_TYPE (right) == AOP_LIT)
10315 /* Case with a bitfield length <8 and literal source
10317 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10319 litval &= (~mask) & 0xff;
10320 emitPtrByteGet (rname, p_type, FALSE);
10321 if ((mask|litval)!=0xff)
10322 emitcode ("anl","a,#0x%02x", mask);
10324 emitcode ("orl","a,#0x%02x", litval);
10328 if ((blen==1) && (p_type!=GPOINTER))
10330 /* Case with a bitfield length == 1 and no generic pointer
10332 if (AOP_TYPE (right) == AOP_CRY)
10333 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10336 MOVA (aopGet (right, 0, FALSE, FALSE));
10337 emitcode ("rrc","a");
10339 emitPtrByteGet (rname, p_type, FALSE);
10340 emitcode ("mov","acc.%d,c",bstr);
10345 /* Case with a bitfield length < 8 and arbitrary source
10347 MOVA (aopGet (right, 0, FALSE, FALSE));
10348 /* shift and mask source value */
10350 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10352 pushedB = pushB ();
10353 /* transfer A to B and get next byte */
10354 emitPtrByteGet (rname, p_type, TRUE);
10356 emitcode ("anl", "a,#0x%02x", mask);
10357 emitcode ("orl", "a,b");
10358 if (p_type == GPOINTER)
10359 emitcode ("pop", "b");
10365 emitPtrByteSet (rname, p_type, "a");
10369 /* Bit length is greater than 7 bits. In this case, copy */
10370 /* all except the partial byte at the end */
10371 for (rlen=blen;rlen>=8;rlen-=8)
10373 emitPtrByteSet (rname, p_type,
10374 aopGet (right, offset++, FALSE, TRUE) );
10376 emitcode ("inc", "%s", rname);
10379 /* If there was a partial byte at the end */
10382 mask = (((unsigned char) -1 << rlen) & 0xff);
10384 if (AOP_TYPE (right) == AOP_LIT)
10386 /* Case with partial byte and literal source
10388 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389 litval >>= (blen-rlen);
10390 litval &= (~mask) & 0xff;
10391 emitPtrByteGet (rname, p_type, FALSE);
10392 if ((mask|litval)!=0xff)
10393 emitcode ("anl","a,#0x%02x", mask);
10395 emitcode ("orl","a,#0x%02x", litval);
10400 /* Case with partial byte and arbitrary source
10402 MOVA (aopGet (right, offset++, FALSE, FALSE));
10403 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10405 pushedB = pushB ();
10406 /* transfer A to B and get next byte */
10407 emitPtrByteGet (rname, p_type, TRUE);
10409 emitcode ("anl", "a,#0x%02x", mask);
10410 emitcode ("orl", "a,b");
10411 if (p_type == GPOINTER)
10412 emitcode ("pop", "b");
10416 emitPtrByteSet (rname, p_type, "a");
10421 /*-----------------------------------------------------------------*/
10422 /* genDataPointerSet - remat pointer to data space */
10423 /*-----------------------------------------------------------------*/
10425 genDataPointerSet (operand * right,
10429 int size, offset = 0;
10430 char *l, buffer[256];
10432 D (emitcode (";", "genDataPointerSet"));
10434 aopOp (right, ic, FALSE);
10436 l = aopGet (result, 0, FALSE, TRUE);
10438 size = AOP_SIZE (right);
10442 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10444 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10445 emitcode ("mov", "%s,%s", buffer,
10446 aopGet (right, offset++, FALSE, FALSE));
10449 freeAsmop (result, NULL, ic, TRUE);
10450 freeAsmop (right, NULL, ic, TRUE);
10453 /*-----------------------------------------------------------------*/
10454 /* genNearPointerSet - emitcode for near pointer put */
10455 /*-----------------------------------------------------------------*/
10457 genNearPointerSet (operand * right,
10465 sym_link *retype, *letype;
10466 sym_link *ptype = operandType (result);
10468 D (emitcode (";", "genNearPointerSet"));
10470 retype = getSpec (operandType (right));
10471 letype = getSpec (ptype);
10473 aopOp (result, ic, FALSE);
10475 /* if the result is rematerializable &
10476 in data space & not a bit variable */
10477 if (AOP_TYPE (result) == AOP_IMMD &&
10478 DCL_TYPE (ptype) == POINTER &&
10479 !IS_BITVAR (retype) &&
10480 !IS_BITVAR (letype))
10482 genDataPointerSet (right, result, ic);
10486 /* if the value is already in a pointer register
10487 then don't need anything more */
10488 if (!AOP_INPREG (AOP (result)))
10491 //AOP_TYPE (result) == AOP_STK
10492 IS_AOP_PREG(result)
10495 // Aha, it is a pointer, just in disguise.
10496 rname = aopGet (result, 0, FALSE, FALSE);
10499 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10500 __FILE__, __LINE__);
10505 emitcode ("mov", "a%s,%s", rname + 1, rname);
10506 rname++; // skip the '@'.
10511 /* otherwise get a free pointer register */
10512 aop = newAsmop (0);
10513 preg = getFreePtr (ic, &aop, FALSE);
10514 emitcode ("mov", "%s,%s",
10516 aopGet (result, 0, FALSE, TRUE));
10517 rname = preg->name;
10522 rname = aopGet (result, 0, FALSE, FALSE);
10525 aopOp (right, ic, FALSE);
10527 /* if bitfield then unpack the bits */
10528 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10529 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10532 /* we can just get the values */
10533 int size = AOP_SIZE (right);
10538 l = aopGet (right, offset, FALSE, TRUE);
10539 if ((*l == '@') || (strcmp (l, "acc") == 0))
10542 emitcode ("mov", "@%s,a", rname);
10545 emitcode ("mov", "@%s,%s", rname, l);
10547 emitcode ("inc", "%s", rname);
10552 /* now some housekeeping stuff */
10553 if (aop) /* we had to allocate for this iCode */
10556 aopPut (result, rname, 0);
10557 freeAsmop (NULL, aop, ic, TRUE);
10561 /* we did not allocate which means left
10562 already in a pointer register, then
10563 if size > 0 && this could be used again
10564 we have to point it back to where it
10566 if ((AOP_SIZE (right) > 1 &&
10567 !OP_SYMBOL (result)->remat &&
10568 (OP_SYMBOL (result)->liveTo > ic->seq ||
10572 int size = AOP_SIZE (right) - 1;
10574 emitcode ("dec", "%s", rname);
10579 if (pi) pi->generated = 1;
10580 freeAsmop (result, NULL, ic, TRUE);
10581 freeAsmop (right, NULL, ic, TRUE);
10584 /*-----------------------------------------------------------------*/
10585 /* genPagedPointerSet - emitcode for Paged pointer put */
10586 /*-----------------------------------------------------------------*/
10588 genPagedPointerSet (operand * right,
10596 sym_link *retype, *letype;
10598 D (emitcode (";", "genPagedPointerSet"));
10600 retype = getSpec (operandType (right));
10601 letype = getSpec (operandType (result));
10603 aopOp (result, ic, FALSE);
10605 /* if the value is already in a pointer register
10606 then don't need anything more */
10607 if (!AOP_INPREG (AOP (result)))
10609 /* otherwise get a free pointer register */
10610 aop = newAsmop (0);
10611 preg = getFreePtr (ic, &aop, FALSE);
10612 emitcode ("mov", "%s,%s",
10614 aopGet (result, 0, FALSE, TRUE));
10615 rname = preg->name;
10618 rname = aopGet (result, 0, FALSE, FALSE);
10620 aopOp (right, ic, FALSE);
10622 /* if bitfield then unpack the bits */
10623 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10624 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10627 /* we have can just get the values */
10628 int size = AOP_SIZE (right);
10633 l = aopGet (right, offset, FALSE, TRUE);
10635 emitcode ("movx", "@%s,a", rname);
10638 emitcode ("inc", "%s", rname);
10644 /* now some housekeeping stuff */
10645 if (aop) /* we had to allocate for this iCode */
10648 aopPut (result, rname, 0);
10649 freeAsmop (NULL, aop, ic, TRUE);
10653 /* we did not allocate which means left
10654 already in a pointer register, then
10655 if size > 0 && this could be used again
10656 we have to point it back to where it
10658 if (AOP_SIZE (right) > 1 &&
10659 !OP_SYMBOL (result)->remat &&
10660 (OP_SYMBOL (result)->liveTo > ic->seq ||
10663 int size = AOP_SIZE (right) - 1;
10665 emitcode ("dec", "%s", rname);
10670 if (pi) pi->generated = 1;
10671 freeAsmop (result, NULL, ic, TRUE);
10672 freeAsmop (right, NULL, ic, TRUE);
10675 /*-----------------------------------------------------------------*/
10676 /* genFarPointerSet - set value from far space */
10677 /*-----------------------------------------------------------------*/
10679 genFarPointerSet (operand * right,
10680 operand * result, iCode * ic, iCode * pi)
10683 sym_link *retype = getSpec (operandType (right));
10684 sym_link *letype = getSpec (operandType (result));
10686 D(emitcode ("; genFarPointerSet",""));
10688 aopOp (result, ic, FALSE);
10689 loadDptrFromOperand (result, FALSE);
10691 /* so dptr now contains the address */
10692 aopOp (right, ic, FALSE);
10694 /* if bit then unpack */
10695 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10696 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10699 size = AOP_SIZE (right);
10704 char *l = aopGet (right, offset++, FALSE, FALSE);
10706 emitcode ("movx", "@dptr,a");
10708 emitcode ("inc", "dptr");
10711 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10712 aopPut (result, "dpl", 0);
10713 aopPut (result, "dph", 1);
10716 freeAsmop (result, NULL, ic, TRUE);
10717 freeAsmop (right, NULL, ic, TRUE);
10720 /*-----------------------------------------------------------------*/
10721 /* genGenPointerSet - set value from generic pointer space */
10722 /*-----------------------------------------------------------------*/
10724 genGenPointerSet (operand * right,
10725 operand * result, iCode * ic, iCode * pi)
10728 sym_link *retype = getSpec (operandType (right));
10729 sym_link *letype = getSpec (operandType (result));
10731 D (emitcode (";", "genGenPointerSet"));
10733 aopOp (result, ic, FALSE);
10734 loadDptrFromOperand (result, TRUE);
10736 /* so dptr now contains the address */
10737 aopOp (right, ic, FALSE);
10739 /* if bit then unpack */
10740 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10742 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10746 size = AOP_SIZE (right);
10751 char *l = aopGet (right, offset++, FALSE, FALSE);
10753 emitcode ("lcall", "__gptrput");
10755 emitcode ("inc", "dptr");
10759 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10760 aopPut (result, "dpl", 0);
10761 aopPut (result, "dph", 1);
10764 freeAsmop (result, NULL, ic, TRUE);
10765 freeAsmop (right, NULL, ic, TRUE);
10768 /*-----------------------------------------------------------------*/
10769 /* genPointerSet - stores the value into a pointer location */
10770 /*-----------------------------------------------------------------*/
10772 genPointerSet (iCode * ic, iCode *pi)
10774 operand *right, *result;
10775 sym_link *type, *etype;
10778 D (emitcode (";", "genPointerSet"));
10780 right = IC_RIGHT (ic);
10781 result = IC_RESULT (ic);
10783 /* depending on the type of pointer we need to
10784 move it to the correct pointer register */
10785 type = operandType (result);
10786 etype = getSpec (type);
10787 /* if left is of type of pointer then it is simple */
10788 if (IS_PTR (type) && !IS_FUNC (type->next))
10790 p_type = DCL_TYPE (type);
10794 /* we have to go by the storage class */
10795 p_type = PTR_TYPE (SPEC_OCLS (etype));
10798 /* special case when cast remat */
10799 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10800 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10801 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10802 type = operandType (result);
10803 p_type = DCL_TYPE (type);
10806 /* now that we have the pointer type we assign
10807 the pointer values */
10813 genNearPointerSet (right, result, ic, pi);
10817 genPagedPointerSet (right, result, ic, pi);
10821 genFarPointerSet (right, result, ic, pi);
10825 genGenPointerSet (right, result, ic, pi);
10829 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10830 "genPointerSet: illegal pointer type");
10834 /*-----------------------------------------------------------------*/
10835 /* genIfx - generate code for Ifx statement */
10836 /*-----------------------------------------------------------------*/
10838 genIfx (iCode * ic, iCode * popIc)
10840 operand *cond = IC_COND (ic);
10844 D (emitcode (";", "genIfx"));
10846 aopOp (cond, ic, FALSE);
10848 /* get the value into acc */
10849 if (AOP_TYPE (cond) != AOP_CRY)
10856 if (AOP(cond)->aopu.aop_dir)
10857 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10860 /* the result is now in the accumulator or a directly addressable bit */
10861 freeAsmop (cond, NULL, ic, TRUE);
10863 /* if there was something to be popped then do it */
10867 /* if the condition is a bit variable */
10869 genIfxJump(ic, dup, NULL, NULL, NULL);
10870 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10871 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10872 else if (isbit && !IS_ITEMP (cond))
10873 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10875 genIfxJump (ic, "a", NULL, NULL, NULL);
10880 /*-----------------------------------------------------------------*/
10881 /* genAddrOf - generates code for address of */
10882 /*-----------------------------------------------------------------*/
10884 genAddrOf (iCode * ic)
10886 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10889 D (emitcode (";", "genAddrOf"));
10891 aopOp (IC_RESULT (ic), ic, FALSE);
10893 /* if the operand is on the stack then we
10894 need to get the stack offset of this
10898 /* if it has an offset then we need to compute it */
10901 int stack_offset = ((sym->stack < 0) ?
10902 ((char) (sym->stack - _G.nRegsSaved)) :
10903 ((char) sym->stack)) & 0xff;
10904 if ((abs(stack_offset) == 1) &&
10905 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10906 !isOperandVolatile (IC_RESULT (ic), FALSE))
10908 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10909 if (stack_offset > 0)
10910 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10912 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10916 emitcode ("mov", "a,%s", SYM_BP (sym));
10917 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10918 aopPut (IC_RESULT (ic), "a", 0);
10923 /* we can just move _bp */
10924 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10926 /* fill the result with zero */
10927 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10932 aopPut (IC_RESULT (ic), zero, offset++);
10937 /* object not on stack then we need the name */
10938 size = AOP_SIZE (IC_RESULT (ic));
10943 char s[SDCC_NAME_MAX];
10945 sprintf (s, "#(%s >> %d)",
10949 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10950 aopPut (IC_RESULT (ic), s, offset++);
10954 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10958 /*-----------------------------------------------------------------*/
10959 /* genFarFarAssign - assignment when both are in far space */
10960 /*-----------------------------------------------------------------*/
10962 genFarFarAssign (operand * result, operand * right, iCode * ic)
10964 int size = AOP_SIZE (right);
10968 D (emitcode (";", "genFarFarAssign"));
10970 /* first push the right side on to the stack */
10973 l = aopGet (right, offset++, FALSE, FALSE);
10975 emitcode ("push", "acc");
10978 freeAsmop (right, NULL, ic, FALSE);
10979 /* now assign DPTR to result */
10980 aopOp (result, ic, FALSE);
10981 size = AOP_SIZE (result);
10984 emitcode ("pop", "acc");
10985 aopPut (result, "a", --offset);
10987 freeAsmop (result, NULL, ic, FALSE);
10990 /*-----------------------------------------------------------------*/
10991 /* genAssign - generate code for assignment */
10992 /*-----------------------------------------------------------------*/
10994 genAssign (iCode * ic)
10996 operand *result, *right;
10998 unsigned long lit = 0L;
11000 D (emitcode (";", "genAssign"));
11002 result = IC_RESULT (ic);
11003 right = IC_RIGHT (ic);
11005 /* if they are the same */
11006 if (operandsEqu (result, right) &&
11007 !isOperandVolatile (result, FALSE) &&
11008 !isOperandVolatile (right, FALSE))
11011 aopOp (right, ic, FALSE);
11013 /* special case both in far space */
11014 if (AOP_TYPE (right) == AOP_DPTR &&
11015 IS_TRUE_SYMOP (result) &&
11016 isOperandInFarSpace (result))
11018 genFarFarAssign (result, right, ic);
11022 aopOp (result, ic, TRUE);
11024 /* if they are the same registers */
11025 if (sameRegs (AOP (right), AOP (result)) &&
11026 !isOperandVolatile (result, FALSE) &&
11027 !isOperandVolatile (right, FALSE))
11030 /* if the result is a bit */
11031 if (AOP_TYPE (result) == AOP_CRY)
11033 /* if the right size is a literal then
11034 we know what the value is */
11035 if (AOP_TYPE (right) == AOP_LIT)
11037 if (((int) operandLitValue (right)))
11038 aopPut (result, one, 0);
11040 aopPut (result, zero, 0);
11044 /* the right is also a bit variable */
11045 if (AOP_TYPE (right) == AOP_CRY)
11047 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11048 aopPut (result, "c", 0);
11052 /* we need to or */
11054 aopPut (result, "a", 0);
11058 /* bit variables done */
11060 size = AOP_SIZE (result);
11062 if (AOP_TYPE (right) == AOP_LIT)
11063 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11066 (AOP_TYPE (result) != AOP_REG) &&
11067 (AOP_TYPE (right) == AOP_LIT) &&
11068 !IS_FLOAT (operandType (right)) &&
11071 while ((size) && (lit))
11074 aopGet (right, offset, FALSE, FALSE),
11080 /* And now fill the rest with zeros. */
11083 emitcode ("clr", "a");
11087 aopPut (result, "a", offset);
11096 aopGet (right, offset, FALSE, FALSE),
11103 freeAsmop (result, NULL, ic, TRUE);
11104 freeAsmop (right, NULL, ic, TRUE);
11107 /*-----------------------------------------------------------------*/
11108 /* genJumpTab - generates code for jump table */
11109 /*-----------------------------------------------------------------*/
11111 genJumpTab (iCode * ic)
11113 symbol *jtab,*jtablo,*jtabhi;
11115 unsigned int count;
11117 D (emitcode (";", "genJumpTab"));
11119 count = elementsInSet( IC_JTLABELS (ic) );
11123 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11124 if the switch argument is in a register.
11125 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11126 /* Peephole may not convert ljmp to sjmp or ret
11127 labelIsReturnOnly & labelInRange must check
11128 currPl->ic->op != JUMPTABLE */
11129 aopOp (IC_JTCOND (ic), ic, FALSE);
11130 /* get the condition into accumulator */
11131 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11133 /* multiply by three */
11134 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11136 emitcode ("mov", "b,#3");
11137 emitcode ("mul", "ab");
11141 emitcode ("add", "a,acc");
11142 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11144 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11146 jtab = newiTempLabel (NULL);
11147 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11148 emitcode ("jmp", "@a+dptr");
11150 /* now generate the jump labels */
11151 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11152 jtab = setNextItem (IC_JTLABELS (ic)))
11153 emitcode ("ljmp", "%05d$", jtab->key + 100);
11157 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11158 if the switch argument is in a register.
11159 For n>6 this algorithm may be more compact */
11160 jtablo = newiTempLabel (NULL);
11161 jtabhi = newiTempLabel (NULL);
11163 /* get the condition into accumulator.
11164 Using b as temporary storage, if register push/pop is needed */
11165 aopOp (IC_JTCOND (ic), ic, FALSE);
11166 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11167 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11168 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11170 // (MB) what if B is in use???
11171 wassertl(!BINUSE, "B was in use");
11172 emitcode ("mov", "b,%s", l);
11175 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11179 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11180 emitcode ("movc", "a,@a+pc");
11181 emitcode ("push", "acc");
11184 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11185 emitcode ("movc", "a,@a+pc");
11186 emitcode ("push", "acc");
11190 /* this scales up to n<=255, but needs two more bytes
11191 and changes dptr */
11192 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11193 emitcode ("movc", "a,@a+dptr");
11194 emitcode ("push", "acc");
11197 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11198 emitcode ("movc", "a,@a+dptr");
11199 emitcode ("push", "acc");
11202 emitcode ("ret", "");
11204 /* now generate jump table, LSB */
11205 emitLabel (jtablo);
11206 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11207 jtab = setNextItem (IC_JTLABELS (ic)))
11208 emitcode (".db", "%05d$", jtab->key + 100);
11210 /* now generate jump table, MSB */
11211 emitLabel (jtabhi);
11212 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11213 jtab = setNextItem (IC_JTLABELS (ic)))
11214 emitcode (".db", "%05d$>>8", jtab->key + 100);
11218 /*-----------------------------------------------------------------*/
11219 /* genCast - gen code for casting */
11220 /*-----------------------------------------------------------------*/
11222 genCast (iCode * ic)
11224 operand *result = IC_RESULT (ic);
11225 sym_link *ctype = operandType (IC_LEFT (ic));
11226 sym_link *rtype = operandType (IC_RIGHT (ic));
11227 operand *right = IC_RIGHT (ic);
11230 D (emitcode (";", "genCast"));
11232 /* if they are equivalent then do nothing */
11233 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11236 aopOp (right, ic, FALSE);
11237 aopOp (result, ic, FALSE);
11239 /* if the result is a bit (and not a bitfield) */
11240 if (IS_BIT (OP_SYMBOL (result)->type))
11242 /* if the right size is a literal then
11243 we know what the value is */
11244 if (AOP_TYPE (right) == AOP_LIT)
11246 if (((int) operandLitValue (right)))
11247 aopPut (result, one, 0);
11249 aopPut (result, zero, 0);
11254 /* the right is also a bit variable */
11255 if (AOP_TYPE (right) == AOP_CRY)
11257 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11258 aopPut (result, "c", 0);
11262 /* we need to or */
11264 aopPut (result, "a", 0);
11268 /* if they are the same size : or less */
11269 if (AOP_SIZE (result) <= AOP_SIZE (right))
11272 /* if they are in the same place */
11273 if (sameRegs (AOP (right), AOP (result)))
11276 /* if they in different places then copy */
11277 size = AOP_SIZE (result);
11282 aopGet (right, offset, FALSE, FALSE),
11289 /* if the result is of type pointer */
11290 if (IS_PTR (ctype))
11294 sym_link *type = operandType (right);
11295 sym_link *etype = getSpec (type);
11297 /* pointer to generic pointer */
11298 if (IS_GENPTR (ctype))
11302 p_type = DCL_TYPE (type);
11306 if (SPEC_SCLS(etype)==S_REGISTER) {
11307 // let's assume it is a generic pointer
11310 /* we have to go by the storage class */
11311 p_type = PTR_TYPE (SPEC_OCLS (etype));
11315 /* the first two bytes are known */
11316 size = GPTRSIZE - 1;
11321 aopGet (right, offset, FALSE, FALSE),
11325 /* the last byte depending on type */
11327 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11332 // pointerTypeToGPByte will have bitched.
11336 sprintf(gpValStr, "#0x%x", gpVal);
11337 aopPut (result, gpValStr, GPTRSIZE - 1);
11342 /* just copy the pointers */
11343 size = AOP_SIZE (result);
11348 aopGet (right, offset, FALSE, FALSE),
11355 /* so we now know that the size of destination is greater
11356 than the size of the source */
11357 /* we move to result for the size of source */
11358 size = AOP_SIZE (right);
11363 aopGet (right, offset, FALSE, FALSE),
11368 /* now depending on the sign of the source && destination */
11369 size = AOP_SIZE (result) - AOP_SIZE (right);
11370 /* if unsigned or not an integral type */
11371 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11374 aopPut (result, zero, offset++);
11378 /* we need to extend the sign :{ */
11379 char *l = aopGet (right, AOP_SIZE (right) - 1,
11382 emitcode ("rlc", "a");
11383 emitcode ("subb", "a,acc");
11385 aopPut (result, "a", offset++);
11388 /* we are done hurray !!!! */
11391 freeAsmop (result, NULL, ic, TRUE);
11392 freeAsmop (right, NULL, ic, TRUE);
11395 /*-----------------------------------------------------------------*/
11396 /* genDjnz - generate decrement & jump if not zero instrucion */
11397 /*-----------------------------------------------------------------*/
11399 genDjnz (iCode * ic, iCode * ifx)
11401 symbol *lbl, *lbl1;
11405 /* if the if condition has a false label
11406 then we cannot save */
11407 if (IC_FALSE (ifx))
11410 /* if the minus is not of the form a = a - 1 */
11411 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11412 !IS_OP_LITERAL (IC_RIGHT (ic)))
11415 if (operandLitValue (IC_RIGHT (ic)) != 1)
11418 /* if the size of this greater than one then no
11420 if (getSize (operandType (IC_RESULT (ic))) > 1)
11423 /* otherwise we can save BIG */
11425 D (emitcode (";", "genDjnz"));
11427 lbl = newiTempLabel (NULL);
11428 lbl1 = newiTempLabel (NULL);
11430 aopOp (IC_RESULT (ic), ic, FALSE);
11432 if (AOP_NEEDSACC(IC_RESULT(ic)))
11434 /* If the result is accessed indirectly via
11435 * the accumulator, we must explicitly write
11436 * it back after the decrement.
11438 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11440 if (strcmp(rByte, "a"))
11442 /* Something is hopelessly wrong */
11443 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11444 __FILE__, __LINE__);
11445 /* We can just give up; the generated code will be inefficient,
11446 * but what the hey.
11448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11451 emitcode ("dec", "%s", rByte);
11452 aopPut (IC_RESULT (ic), rByte, 0);
11453 emitcode ("jnz", "%05d$", lbl->key + 100);
11455 else if (IS_AOP_PREG (IC_RESULT (ic)))
11457 emitcode ("dec", "%s",
11458 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11459 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11460 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11461 ifx->generated = 1;
11462 emitcode ("jnz", "%05d$", lbl->key + 100);
11466 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11469 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11471 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11474 if (!ifx->generated)
11475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11476 ifx->generated = 1;
11480 /*-----------------------------------------------------------------*/
11481 /* genReceive - generate code for a receive iCode */
11482 /*-----------------------------------------------------------------*/
11484 genReceive (iCode * ic)
11486 int size = getSize (operandType (IC_RESULT (ic)));
11489 D (emitcode (";", "genReceive"));
11491 if (ic->argreg == 1)
11492 { /* first parameter */
11493 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11494 isOperandInPagedSpace (IC_RESULT (ic))) &&
11495 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11496 IS_TRUE_SYMOP (IC_RESULT (ic))))
11499 int receivingA = 0;
11502 for (offset = 0; offset<size; offset++)
11503 if (!strcmp (fReturn[offset], "a"))
11508 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11510 for (offset = size-1; offset>0; offset--)
11511 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11512 emitcode("mov","a,%s", fReturn[0]);
11514 aopOp (IC_RESULT (ic), ic, FALSE);
11516 aopPut (IC_RESULT (ic), "a", offset);
11517 for (offset = 1; offset<size; offset++)
11518 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11524 if (getTempRegs(tempRegs, size, ic))
11526 for (offset = 0; offset<size; offset++)
11527 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11528 aopOp (IC_RESULT (ic), ic, FALSE);
11529 for (offset = 0; offset<size; offset++)
11530 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11535 offset = fReturnSizeMCS51 - size;
11538 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11539 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11542 aopOp (IC_RESULT (ic), ic, FALSE);
11543 size = AOP_SIZE (IC_RESULT (ic));
11547 emitcode ("pop", "acc");
11548 aopPut (IC_RESULT (ic), "a", offset++);
11554 aopOp (IC_RESULT (ic), ic, FALSE);
11556 assignResultValue (IC_RESULT (ic), NULL);
11559 else if (ic->argreg > 12)
11560 { /* bit parameters */
11561 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11563 aopOp (IC_RESULT (ic), ic, FALSE);
11564 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11565 outBitC(IC_RESULT (ic));
11569 { /* other parameters */
11571 aopOp (IC_RESULT (ic), ic, FALSE);
11572 rb1off = ic->argreg;
11575 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11583 /*-----------------------------------------------------------------*/
11584 /* genDummyRead - generate code for dummy read of volatiles */
11585 /*-----------------------------------------------------------------*/
11587 genDummyRead (iCode * ic)
11592 D (emitcode(";", "genDummyRead"));
11594 op = IC_RIGHT (ic);
11595 if (op && IS_SYMOP (op))
11597 aopOp (op, ic, FALSE);
11599 /* if the result is a bit */
11600 if (AOP_TYPE (op) == AOP_CRY)
11601 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11604 /* bit variables done */
11606 size = AOP_SIZE (op);
11610 MOVA (aopGet (op, offset, FALSE, FALSE));
11615 freeAsmop (op, NULL, ic, TRUE);
11619 if (op && IS_SYMOP (op))
11621 aopOp (op, ic, FALSE);
11623 /* if the result is a bit */
11624 if (AOP_TYPE (op) == AOP_CRY)
11625 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11628 /* bit variables done */
11630 size = AOP_SIZE (op);
11634 MOVA (aopGet (op, offset, FALSE, FALSE));
11639 freeAsmop (op, NULL, ic, TRUE);
11643 /*-----------------------------------------------------------------*/
11644 /* genCritical - generate code for start of a critical sequence */
11645 /*-----------------------------------------------------------------*/
11647 genCritical (iCode *ic)
11649 symbol *tlbl = newiTempLabel (NULL);
11651 D (emitcode(";", "genCritical"));
11653 if (IC_RESULT (ic))
11655 aopOp (IC_RESULT (ic), ic, TRUE);
11656 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11657 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11658 aopPut (IC_RESULT (ic), zero, 0);
11660 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11664 emitcode ("setb", "c");
11665 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11666 emitcode ("clr", "c");
11668 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11672 /*-----------------------------------------------------------------*/
11673 /* genEndCritical - generate code for end of a critical sequence */
11674 /*-----------------------------------------------------------------*/
11676 genEndCritical (iCode *ic)
11678 D(emitcode("; genEndCritical",""));
11682 aopOp (IC_RIGHT (ic), ic, FALSE);
11683 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11685 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11686 emitcode ("mov", "ea,c");
11690 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11691 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11692 emitcode ("rrc", "a");
11693 emitcode ("mov", "ea,c");
11695 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11699 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11700 emitcode ("mov", "ea,c");
11704 /*-----------------------------------------------------------------*/
11705 /* gen51Code - generate code for 8051 based controllers */
11706 /*-----------------------------------------------------------------*/
11708 gen51Code (iCode * lic)
11712 /* int cseq = 0; */
11714 _G.currentFunc = NULL;
11715 lineHead = lineCurr = NULL;
11717 /* print the allocation information */
11718 if (allocInfo && currFunc)
11719 printAllocInfo (currFunc, codeOutFile);
11720 /* if debug information required */
11721 if (options.debug && currFunc)
11723 debugFile->writeFunction (currFunc, lic);
11725 /* stack pointer name */
11726 if (options.useXstack)
11732 for (ic = lic; ic; ic = ic->next)
11734 _G.current_iCode = ic;
11736 if (ic->lineno && cln != ic->lineno)
11740 debugFile->writeCLine (ic);
11742 if (!options.noCcodeInAsm) {
11743 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11744 printCLine(ic->filename, ic->lineno));
11749 if (ic->seqPoint && ic->seqPoint != cseq)
11751 emitcode ("", "; sequence point %d", ic->seqPoint);
11752 cseq = ic->seqPoint;
11755 if (options.iCodeInAsm) {
11756 char regsInUse[80];
11760 for (i=0; i<8; i++) {
11761 sprintf (®sInUse[i],
11762 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11765 strcpy (regsInUse, "--------");
11766 for (i=0; i < 8; i++) {
11767 if (bitVectBitValue (ic->rMask, i))
11769 int offset = regs8051[i].offset;
11770 regsInUse[offset] = offset + '0'; /* show rMask */
11774 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11776 /* if the result is marked as
11777 spilt and rematerializable or code for
11778 this has already been generated then
11780 if (resultRemat (ic) || ic->generated)
11783 /* depending on the operation */
11803 /* IPOP happens only when trying to restore a
11804 spilt live range, if there is an ifx statement
11805 following this pop then the if statement might
11806 be using some of the registers being popped which
11807 would destory the contents of the register so
11808 we need to check for this condition and handle it */
11810 ic->next->op == IFX &&
11811 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11812 genIfx (ic->next, ic);
11830 genEndFunction (ic);
11850 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11867 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11871 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11878 /* note these two are xlated by algebraic equivalence
11879 in decorateType() in SDCCast.c */
11880 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11881 "got '>=' or '<=' shouldn't have come here");
11885 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11897 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11901 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11905 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11941 genRightShift (ic);
11944 case GET_VALUE_AT_ADDRESS:
11946 hasInc (IC_LEFT (ic), ic,
11947 getSize (operandType (IC_RESULT (ic)))),
11948 ifxForOp (IC_RESULT (ic), ic) );
11952 if (POINTER_SET (ic))
11954 hasInc (IC_RESULT (ic), ic,
11955 getSize (operandType (IC_RIGHT (ic)))));
11981 addSet (&_G.sendSet, ic);
11984 case DUMMY_READ_VOLATILE:
11993 genEndCritical (ic);
12005 _G.current_iCode = NULL;
12007 /* now we are ready to call the
12008 peep hole optimizer */
12009 if (!options.nopeep)
12010 peepHole (&lineHead);
12012 /* now do the actual printing */
12013 printLine (lineHead, codeOutFile);