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 -------------------------------------------------------------------------*/
31 #define D(x) do if (!options.noGenComments) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
122 static void saveRBank (int, iCode *, bool);
124 #define RESULTONSTACK(x) \
125 (IC_RESULT(x) && IC_RESULT(x)->aop && \
126 IC_RESULT(x)->aop->type == AOP_STK )
128 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
129 #define MOVB(x) movb(x)
131 #define CLRC emitcode("clr","c")
132 #define SETC emitcode("setb","c")
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139 0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142 0x07, 0x03, 0x01, 0x00};
149 /*-----------------------------------------------------------------*/
150 /* emitcode - writes the code into a file : for now it is simple */
151 /*-----------------------------------------------------------------*/
153 emitcode (const char *inst, const char *fmt,...)
157 const char *lbp, *lb;
159 dbuf_init (&dbuf, INITIAL_INLINEASM);
165 dbuf_append_str (&dbuf, inst);
169 dbuf_append_char (&dbuf, '\t');
170 dbuf_tvprintf (&dbuf, fmt, ap);
175 dbuf_tvprintf (&dbuf, fmt, ap);
178 lbp = lb = dbuf_c_str(&dbuf);
180 while (isspace ((unsigned char)*lbp))
189 lineCurr = (lineCurr ?
190 connectLine (lineCurr, newLineNode (lb)) :
191 (lineHead = newLineNode (lb)));
194 lineCurr->isInline = _G.inLine;
195 lineCurr->isDebug = _G.debugLine;
196 lineCurr->ic = _G.current_iCode;
197 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
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 ("mov", "c,%s", aop->aopu.aop_dir);
1416 emitcode ("clr", "a");
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)
1642 emitcode ("push", "acc");
1647 emitcode ("push", "acc");
1649 else if (strcmp (s, "r0") == 0 ||
1650 strcmp (s, "r1") == 0 ||
1651 strcmp (s, "r2") == 0 ||
1652 strcmp (s, "r3") == 0 ||
1653 strcmp (s, "r4") == 0 ||
1654 strcmp (s, "r5") == 0 ||
1655 strcmp (s, "r6") == 0 ||
1656 strcmp (s, "r7") == 0)
1659 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1660 emitcode ("push", buffer);
1664 emitcode ("push", s);
1670 /* if result no bit variable */
1671 if (!aop->aopu.aop_dir)
1673 assert (!strcmp (s, "c"));
1674 /* inefficient: move carry into A and use jz/jnz */
1675 emitcode ("clr", "a");
1676 emitcode ("rlc", "a");
1680 emitcode ("clr", "%s", aop->aopu.aop_dir);
1682 emitcode ("setb", "%s", aop->aopu.aop_dir);
1683 else if (!strcmp (s, "c"))
1684 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1685 else if (strcmp (s, aop->aopu.aop_dir))
1688 /* set C, if a >= 1 */
1689 emitcode ("add", "a,#0xff");
1690 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1696 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1697 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1703 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1706 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1707 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1711 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1712 "aopPut got unsupported aop->type");
1721 /*-----------------------------------------------------------------*/
1722 /* pointToEnd :- points to the last byte of the operand */
1723 /*-----------------------------------------------------------------*/
1725 pointToEnd (asmop * aop)
1731 aop->coff = count = (aop->size - 1);
1737 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1741 emitcode ("inc", "dptr");
1748 /*-----------------------------------------------------------------*/
1749 /* reAdjustPreg - points a register back to where it should */
1750 /*-----------------------------------------------------------------*/
1752 reAdjustPreg (asmop * aop)
1754 if ((aop->coff==0) || (aop->size <= 1))
1762 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1767 emitcode ("lcall", "__decdptr");
1774 /*-----------------------------------------------------------------*/
1775 /* opIsGptr: returns non-zero if the passed operand is */
1776 /* a generic pointer type. */
1777 /*-----------------------------------------------------------------*/
1779 opIsGptr (operand * op)
1781 sym_link *type = operandType (op);
1783 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1790 /*-----------------------------------------------------------------*/
1791 /* getDataSize - get the operand data size */
1792 /*-----------------------------------------------------------------*/
1794 getDataSize (operand * op)
1797 size = AOP_SIZE (op);
1798 if (size == GPTRSIZE)
1800 sym_link *type = operandType (op);
1801 if (IS_GENPTR (type))
1803 /* generic pointer; arithmetic operations
1804 * should ignore the high byte (pointer type).
1812 /*-----------------------------------------------------------------*/
1813 /* outAcc - output Acc */
1814 /*-----------------------------------------------------------------*/
1816 outAcc (operand * result)
1819 size = getDataSize (result);
1822 aopPut (result, "a", 0);
1825 /* unsigned or positive */
1828 aopPut (result, zero, offset++);
1833 /*-----------------------------------------------------------------*/
1834 /* outBitC - output a bit C */
1835 /*-----------------------------------------------------------------*/
1837 outBitC (operand * result)
1839 /* if the result is bit */
1840 if (AOP_TYPE (result) == AOP_CRY)
1842 aopPut (result, "c", 0);
1846 emitcode ("clr", "a");
1847 emitcode ("rlc", "a");
1852 /*-----------------------------------------------------------------*/
1853 /* toBoolean - emit code for orl a,operator(sizeop) */
1854 /*-----------------------------------------------------------------*/
1856 toBoolean (operand * oper)
1858 int size = AOP_SIZE (oper) - 1;
1860 bool AccUsed = FALSE;
1863 while (!AccUsed && size--)
1865 AccUsed |= aopGetUsesAcc(oper, offset++);
1868 size = AOP_SIZE (oper) - 1;
1870 MOVA (aopGet (oper, 0, FALSE, FALSE));
1871 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1874 emitcode("mov", "b,a");
1877 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1878 emitcode ("orl", "b,a");
1880 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1881 emitcode ("orl", "a,b");
1888 emitcode ("orl", "a,%s",
1889 aopGet (oper, offset++, FALSE, FALSE));
1894 /*-----------------------------------------------------------------*/
1895 /* toCarry - make boolean and move into carry */
1896 /*-----------------------------------------------------------------*/
1898 toCarry (operand * oper)
1900 /* if the operand is a literal then
1901 we know what the value is */
1902 if (AOP_TYPE (oper) == AOP_LIT)
1904 if ((int) operandLitValue (oper))
1909 else if (AOP_TYPE (oper) == AOP_CRY)
1911 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1915 /* or the operand into a */
1917 /* set C, if a >= 1 */
1918 emitcode ("add", "a,#0xff");
1922 /*-----------------------------------------------------------------*/
1923 /* assignBit - assign operand to bit operand */
1924 /*-----------------------------------------------------------------*/
1926 assignBit (operand * result, operand * right)
1928 /* if the right side is a literal then
1929 we know what the value is */
1930 if (AOP_TYPE (right) == AOP_LIT)
1932 if ((int) operandLitValue (right))
1933 aopPut (result, one, 0);
1935 aopPut (result, zero, 0);
1940 aopPut (result, "c", 0);
1945 /*-------------------------------------------------------------------*/
1946 /* xch_a_aopGet - for exchanging acc with value of the aop */
1947 /*-------------------------------------------------------------------*/
1949 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1953 if (aopGetUsesAcc (oper, offset))
1955 emitcode("mov", "b,a");
1956 MOVA (aopGet (oper, offset, bit16, dname));
1957 emitcode("xch", "a,b");
1958 aopPut (oper, "a", offset);
1959 emitcode("xch", "a,b");
1964 l = aopGet (oper, offset, bit16, dname);
1965 emitcode("xch", "a,%s", l);
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation */
1973 /*-----------------------------------------------------------------*/
1979 D (emitcode (";", "genNot"));
1981 /* assign asmOps to operand & result */
1982 aopOp (IC_LEFT (ic), ic, FALSE);
1983 aopOp (IC_RESULT (ic), ic, TRUE);
1985 /* if in bit space then a special case */
1986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1988 /* if left==result then cpl bit */
1989 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1991 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1995 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996 emitcode ("cpl", "c");
1997 outBitC (IC_RESULT (ic));
2002 toBoolean (IC_LEFT (ic));
2004 /* set C, if a == 0 */
2005 tlbl = newiTempLabel (NULL);
2006 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2008 outBitC (IC_RESULT (ic));
2011 /* release the aops */
2012 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 /*-----------------------------------------------------------------*/
2018 /* genCpl - generate code for complement */
2019 /*-----------------------------------------------------------------*/
2026 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2028 D(emitcode (";", "genCpl"));
2030 /* assign asmOps to operand & result */
2031 aopOp (IC_LEFT (ic), ic, FALSE);
2032 aopOp (IC_RESULT (ic), ic, TRUE);
2034 /* special case if in bit space */
2035 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2039 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2040 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2042 /* promotion rules are responsible for this strange result:
2043 bit -> int -> ~int -> bit
2044 uchar -> int -> ~int -> bit
2046 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2050 tlbl=newiTempLabel(NULL);
2051 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2052 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2053 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2054 IS_AOP_PREG (IC_LEFT (ic)))
2056 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2061 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2064 outBitC (IC_RESULT(ic));
2068 size = AOP_SIZE (IC_RESULT (ic));
2071 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2073 emitcode ("cpl", "a");
2074 aopPut (IC_RESULT (ic), "a", offset++);
2079 /* release the aops */
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2084 /*-----------------------------------------------------------------*/
2085 /* genUminusFloat - unary minus for floating points */
2086 /*-----------------------------------------------------------------*/
2088 genUminusFloat (operand * op, operand * result)
2090 int size, offset = 0;
2093 D (emitcode (";", "genUminusFloat"));
2095 /* for this we just copy and then flip the bit */
2097 size = AOP_SIZE (op) - 1;
2102 aopGet (op, offset, FALSE, FALSE),
2107 l = aopGet (op, offset, FALSE, FALSE);
2110 emitcode ("cpl", "acc.7");
2111 aopPut (result, "a", offset);
2114 /*-----------------------------------------------------------------*/
2115 /* genUminus - unary minus code generation */
2116 /*-----------------------------------------------------------------*/
2118 genUminus (iCode * ic)
2123 D (emitcode (";", "genUminus"));
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2127 aopOp (IC_RESULT (ic), ic, TRUE);
2129 /* if both in bit space then special
2131 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2132 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2135 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2136 emitcode ("cpl", "c");
2137 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2141 optype = operandType (IC_LEFT (ic));
2143 /* if float then do float stuff */
2144 if (IS_FLOAT (optype))
2146 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2150 /* otherwise subtract from zero */
2151 size = AOP_SIZE (IC_LEFT (ic));
2155 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2156 if (!strcmp (l, "a"))
2160 emitcode ("cpl", "a");
2161 emitcode ("addc", "a,#0");
2167 emitcode ("clr", "a");
2168 emitcode ("subb", "a,%s", l);
2170 aopPut (IC_RESULT (ic), "a", offset++);
2173 /* if any remaining bytes in the result */
2174 /* we just need to propagate the sign */
2175 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2177 emitcode ("rlc", "a");
2178 emitcode ("subb", "a,acc");
2180 aopPut (IC_RESULT (ic), "a", offset++);
2184 /* release the aops */
2185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2189 /*-----------------------------------------------------------------*/
2190 /* saveRegisters - will look for a call and save the registers */
2191 /*-----------------------------------------------------------------*/
2193 saveRegisters (iCode * lic)
2200 for (ic = lic; ic; ic = ic->next)
2201 if (ic->op == CALL || ic->op == PCALL)
2206 fprintf (stderr, "found parameter push with no function call\n");
2210 /* if the registers have been saved already or don't need to be then
2214 if (IS_SYMOP(IC_LEFT(ic)) &&
2215 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2216 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2219 /* save the registers in use at this time but skip the
2220 ones for the result */
2221 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2222 mcs51_rUmaskForOp (IC_RESULT(ic)));
2225 if (options.useXstack)
2227 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2228 int nBits = bitVectnBitsOn (rsavebits);
2229 int count = bitVectnBitsOn (rsave);
2233 count = count - nBits + 1;
2234 /* remove all but the first bits as they are pushed all at once */
2235 rsave = bitVectCplAnd (rsave, rsavebits);
2236 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2241 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2242 if (reg->type == REG_BIT)
2244 emitcode ("mov", "a,%s", reg->base);
2248 emitcode ("mov", "a,%s", reg->name);
2250 emitcode ("mov", "r0,%s", spname);
2251 emitcode ("inc", "%s", spname);// allocate before use
2252 emitcode ("movx", "@r0,a");
2253 if (bitVectBitValue (rsave, R0_IDX))
2254 emitcode ("mov", "r0,a");
2256 else if (count != 0)
2258 if (bitVectBitValue (rsave, R0_IDX))
2260 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2262 emitcode ("mov", "r0,%s", spname);
2264 emitcode ("add", "a,#%d", count);
2265 emitcode ("mov", "%s,a", spname);
2266 for (i = 0; i < mcs51_nRegs; i++)
2268 if (bitVectBitValue (rsave, i))
2270 regs * reg = REG_WITH_INDEX (i);
2273 emitcode ("pop", "acc");
2274 emitcode ("push", "acc");
2276 else if (reg->type == REG_BIT)
2278 emitcode ("mov", "a,%s", reg->base);
2282 emitcode ("mov", "a,%s", reg->name);
2284 emitcode ("movx", "@r0,a");
2287 emitcode ("inc", "r0");
2291 if (bitVectBitValue (rsave, R0_IDX))
2293 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2299 bool bits_pushed = FALSE;
2300 for (i = 0; i < mcs51_nRegs; i++)
2302 if (bitVectBitValue (rsave, i))
2304 bits_pushed = pushReg (i, bits_pushed);
2310 /*-----------------------------------------------------------------*/
2311 /* unsaveRegisters - pop the pushed registers */
2312 /*-----------------------------------------------------------------*/
2314 unsaveRegisters (iCode * ic)
2319 /* restore the registers in use at this time but skip the
2320 ones for the result */
2321 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2322 mcs51_rUmaskForOp (IC_RESULT(ic)));
2324 if (options.useXstack)
2326 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2327 int nBits = bitVectnBitsOn (rsavebits);
2328 int count = bitVectnBitsOn (rsave);
2332 count = count - nBits + 1;
2333 /* remove all but the first bits as they are popped all at once */
2334 rsave = bitVectCplAnd (rsave, rsavebits);
2335 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2340 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2341 emitcode ("mov", "r0,%s", spname);
2342 emitcode ("dec", "r0");
2343 emitcode ("movx", "a,@r0");
2344 if (reg->type == REG_BIT)
2346 emitcode ("mov", "%s,a", reg->base);
2350 emitcode ("mov", "%s,a", reg->name);
2352 emitcode ("dec", "%s", spname);
2354 else if (count != 0)
2356 emitcode ("mov", "r0,%s", spname);
2357 for (i = mcs51_nRegs; i >= 0; i--)
2359 if (bitVectBitValue (rsave, i))
2361 regs * reg = REG_WITH_INDEX (i);
2362 emitcode ("dec", "r0");
2363 emitcode ("movx", "a,@r0");
2366 emitcode ("push", "acc");
2368 else if (reg->type == REG_BIT)
2370 emitcode ("mov", "%s,a", reg->base);
2374 emitcode ("mov", "%s,a", reg->name);
2378 emitcode ("mov", "%s,r0", spname);
2379 if (bitVectBitValue (rsave, R0_IDX))
2381 emitcode ("pop", "ar0");
2387 bool bits_popped = FALSE;
2388 for (i = mcs51_nRegs; i >= 0; i--)
2390 if (bitVectBitValue (rsave, i))
2392 bits_popped = popReg (i, bits_popped);
2399 /*-----------------------------------------------------------------*/
2401 /*-----------------------------------------------------------------*/
2403 pushSide (operand * oper, int size)
2408 char *l = aopGet (oper, offset++, FALSE, TRUE);
2409 if (AOP_TYPE (oper) != AOP_REG &&
2410 AOP_TYPE (oper) != AOP_DIR &&
2414 emitcode ("push", "acc");
2418 emitcode ("push", "%s", l);
2423 /*-----------------------------------------------------------------*/
2424 /* assignResultValue - also indicates if acc is in use afterwards */
2425 /*-----------------------------------------------------------------*/
2427 assignResultValue (operand * oper, operand * func)
2430 int size = AOP_SIZE (oper);
2431 bool accuse = FALSE;
2432 bool pushedA = FALSE;
2434 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2440 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2442 emitcode ("push", "acc");
2447 if ((offset == 3) && pushedA)
2448 emitcode ("pop", "acc");
2449 accuse |= aopPut (oper, fReturn[offset], offset);
2456 /*-----------------------------------------------------------------*/
2457 /* genXpush - pushes onto the external stack */
2458 /*-----------------------------------------------------------------*/
2460 genXpush (iCode * ic)
2462 asmop *aop = newAsmop (0);
2464 int size, offset = 0;
2466 D (emitcode (";", "genXpush"));
2468 aopOp (IC_LEFT (ic), ic, FALSE);
2469 r = getFreePtr (ic, &aop, FALSE);
2471 size = AOP_SIZE (IC_LEFT (ic));
2475 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2476 emitcode ("mov", "%s,%s", r->name, spname);
2477 emitcode ("inc", "%s", spname); // allocate space first
2478 emitcode ("movx", "@%s,a", r->name);
2482 // allocate space first
2483 emitcode ("mov", "%s,%s", r->name, spname);
2485 emitcode ("add", "a,#%d", size);
2486 emitcode ("mov", "%s,a", spname);
2490 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2491 emitcode ("movx", "@%s,a", r->name);
2492 emitcode ("inc", "%s", r->name);
2496 freeAsmop (NULL, aop, ic, TRUE);
2497 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2500 /*-----------------------------------------------------------------*/
2501 /* genIpush - generate code for pushing this gets a little complex */
2502 /*-----------------------------------------------------------------*/
2504 genIpush (iCode * ic)
2506 int size, offset = 0;
2510 D (emitcode (";", "genIpush"));
2512 /* if this is not a parm push : ie. it is spill push
2513 and spill push is always done on the local stack */
2517 /* and the item is spilt then do nothing */
2518 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2521 aopOp (IC_LEFT (ic), ic, FALSE);
2522 size = AOP_SIZE (IC_LEFT (ic));
2523 /* push it on the stack */
2526 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2532 emitcode ("push", "%s", l);
2537 /* this is a parameter push: in this case we call
2538 the routine to find the call and save those
2539 registers that need to be saved */
2542 /* if use external stack then call the external
2543 stack pushing routine */
2544 if (options.useXstack)
2550 /* then do the push */
2551 aopOp (IC_LEFT (ic), ic, FALSE);
2553 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2554 size = AOP_SIZE (IC_LEFT (ic));
2558 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2559 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2560 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2562 if (strcmp (l, prev) || *l == '@')
2564 emitcode ("push", "acc");
2568 emitcode ("push", "%s", l);
2573 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2576 /*-----------------------------------------------------------------*/
2577 /* genIpop - recover the registers: can happen only for spilling */
2578 /*-----------------------------------------------------------------*/
2580 genIpop (iCode * ic)
2584 D (emitcode (";", "genIpop"));
2586 /* if the temp was not pushed then */
2587 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2590 aopOp (IC_LEFT (ic), ic, FALSE);
2591 size = AOP_SIZE (IC_LEFT (ic));
2592 offset = (size - 1);
2595 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2599 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2602 /*-----------------------------------------------------------------*/
2603 /* saveRBank - saves an entire register bank on the stack */
2604 /*-----------------------------------------------------------------*/
2606 saveRBank (int bank, iCode * ic, bool pushPsw)
2609 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2613 if (options.useXstack)
2617 /* Assume r0 is available for use. */
2618 r = REG_WITH_INDEX (R0_IDX);;
2623 r = getFreePtr (ic, &aop, FALSE);
2625 // allocate space first
2626 emitcode ("mov", "%s,%s", r->name, spname);
2628 emitcode ("add", "a,#%d", count);
2629 emitcode ("mov", "%s,a", spname);
2632 for (i = 0; i < 8; i++)
2634 if (options.useXstack)
2636 emitcode ("mov", "a,(%s+%d)",
2637 regs8051[i].base, 8 * bank + regs8051[i].offset);
2638 emitcode ("movx", "@%s,a", r->name);
2640 emitcode ("inc", "%s", r->name);
2643 emitcode ("push", "(%s+%d)",
2644 regs8051[i].base, 8 * bank + regs8051[i].offset);
2647 if (mcs51_nRegs > 8)
2649 if (options.useXstack)
2651 emitcode ("mov", "a,bits");
2652 emitcode ("movx", "@%s,a", r->name);
2654 emitcode ("inc", "%s", r->name);
2658 emitcode ("push", "bits");
2665 if (options.useXstack)
2667 emitcode ("mov", "a,psw");
2668 emitcode ("movx", "@%s,a", r->name);
2672 emitcode ("push", "psw");
2675 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2680 freeAsmop (NULL, aop, ic, TRUE);
2689 /*-----------------------------------------------------------------*/
2690 /* unsaveRBank - restores the register bank from stack */
2691 /*-----------------------------------------------------------------*/
2693 unsaveRBank (int bank, iCode * ic, bool popPsw)
2699 if (options.useXstack)
2703 /* Assume r0 is available for use. */
2704 r = REG_WITH_INDEX (R0_IDX);;
2709 r = getFreePtr (ic, &aop, FALSE);
2711 emitcode ("mov", "%s,%s", r->name, spname);
2716 if (options.useXstack)
2718 emitcode ("dec", "%s", r->name);
2719 emitcode ("movx", "a,@%s", r->name);
2720 emitcode ("mov", "psw,a");
2724 emitcode ("pop", "psw");
2728 if (mcs51_nRegs > 8)
2730 if (options.useXstack)
2732 emitcode ("dec", "%s", r->name);
2733 emitcode ("movx", "a,@%s", r->name);
2734 emitcode ("mov", "bits,a");
2738 emitcode ("pop", "bits");
2742 for (i = 7; i >= 0; i--)
2744 if (options.useXstack)
2746 emitcode ("dec", "%s", r->name);
2747 emitcode ("movx", "a,@%s", r->name);
2748 emitcode ("mov", "(%s+%d),a",
2749 regs8051[i].base, 8 * bank + regs8051[i].offset);
2753 emitcode ("pop", "(%s+%d)",
2754 regs8051[i].base, 8 * bank + regs8051[i].offset);
2758 if (options.useXstack)
2760 emitcode ("mov", "%s,%s", spname, r->name);
2765 freeAsmop (NULL, aop, ic, TRUE);
2769 /*-----------------------------------------------------------------*/
2770 /* genSend - gen code for SEND */
2771 /*-----------------------------------------------------------------*/
2772 static void genSend(set *sendSet)
2777 /* first we do all bit parameters */
2778 for (sic = setFirstItem (sendSet); sic;
2779 sic = setNextItem (sendSet))
2781 if (sic->argreg > 12)
2783 int bit = sic->argreg-13;
2785 aopOp (IC_LEFT (sic), sic, FALSE);
2787 /* if left is a literal then
2788 we know what the value is */
2789 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2791 if (((int) operandLitValue (IC_LEFT (sic))))
2792 emitcode ("setb", "b[%d]", bit);
2794 emitcode ("clr", "b[%d]", bit);
2799 toCarry (IC_LEFT (sic));
2800 emitcode ("mov", "b[%d],c", bit);
2805 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2811 saveRegisters (setFirstItem (sendSet));
2812 emitcode ("mov", "bits,b");
2815 /* then we do all other parameters */
2816 for (sic = setFirstItem (sendSet); sic;
2817 sic = setNextItem (sendSet))
2819 if (sic->argreg <= 12)
2821 int size, offset = 0;
2822 aopOp (IC_LEFT (sic), sic, FALSE);
2823 size = AOP_SIZE (IC_LEFT (sic));
2825 if (sic->argreg == 1)
2829 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2830 if (strcmp (l, fReturn[offset]))
2832 emitcode ("mov", "%s,%s", fReturn[offset], l);
2841 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2842 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2846 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2851 /*-----------------------------------------------------------------*/
2852 /* selectRegBank - emit code to select the register bank */
2853 /*-----------------------------------------------------------------*/
2855 selectRegBank (short bank, bool keepFlags)
2857 /* if f.e. result is in carry */
2860 emitcode ("anl", "psw,#0xE7");
2862 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2866 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2870 /*-----------------------------------------------------------------*/
2871 /* genCall - generates a call statement */
2872 /*-----------------------------------------------------------------*/
2874 genCall (iCode * ic)
2878 // bool restoreBank = FALSE;
2879 bool swapBanks = FALSE;
2880 bool accuse = FALSE;
2881 bool accPushed = FALSE;
2882 bool resultInF0 = FALSE;
2883 bool assignResultGenerated = FALSE;
2885 D (emitcode (";", "genCall"));
2887 dtype = operandType (IC_LEFT (ic));
2888 etype = getSpec(dtype);
2889 /* if send set is not empty then assign */
2892 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2893 genSend(reverseSet(_G.sendSet));
2895 genSend(_G.sendSet);
2900 /* if we are calling a not _naked function that is not using
2901 the same register bank then we need to save the
2902 destination registers on the stack */
2903 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2904 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2905 !IFFUNC_ISISR (dtype))
2910 /* if caller saves & we have not saved then */
2916 emitcode ("mov", "psw,#0x%02x",
2917 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2921 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2923 if (IFFUNC_CALLEESAVES(dtype))
2925 werror (E_BANKED_WITH_CALLEESAVES);
2929 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2930 OP_SYMBOL (IC_LEFT (ic))->rname :
2931 OP_SYMBOL (IC_LEFT (ic))->name);
2933 emitcode ("mov", "r0,#%s", l);
2934 emitcode ("mov", "r1,#(%s >> 8)", l);
2935 emitcode ("mov", "r2,#(%s >> 16)", l);
2936 emitcode ("lcall", "__sdcc_banked_call");
2941 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2942 OP_SYMBOL (IC_LEFT (ic))->rname :
2943 OP_SYMBOL (IC_LEFT (ic))->name));
2948 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2951 /* if we need assign a result value */
2952 if ((IS_ITEMP (IC_RESULT (ic)) &&
2953 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2954 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2955 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2956 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2957 IS_TRUE_SYMOP (IC_RESULT (ic)))
2961 aopOp (IC_RESULT (ic), ic, FALSE);
2964 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2965 assignResultGenerated = TRUE;
2967 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2970 /* adjust the stack for parameters if required */
2974 if (ic->parmBytes > 3)
2978 emitcode ("push", "acc");
2981 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2982 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2983 !assignResultGenerated)
2985 emitcode ("mov", "F0,c");
2989 emitcode ("mov", "a,%s", spname);
2990 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2991 emitcode ("mov", "%s,a", spname);
2993 /* unsaveRegisters from xstack needs acc, but */
2994 /* unsaveRegisters from stack needs this popped */
2995 if (accPushed && !options.useXstack)
2997 emitcode ("pop", "acc");
3002 for (i = 0; i < ic->parmBytes; i++)
3003 emitcode ("dec", "%s", spname);
3006 /* if we had saved some registers then unsave them */
3007 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3009 if (accuse && !accPushed && options.useXstack)
3011 /* xstack needs acc, but doesn't touch normal stack */
3012 emitcode ("push", "acc");
3015 unsaveRegisters (ic);
3018 // /* if register bank was saved then pop them */
3020 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3022 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3025 emitcode ("mov", "c,F0");
3027 aopOp (IC_RESULT (ic), ic, FALSE);
3028 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3029 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3033 emitcode ("pop", "acc");
3036 /*-----------------------------------------------------------------*/
3037 /* genPcall - generates a call by pointer statement */
3038 /*-----------------------------------------------------------------*/
3040 genPcall (iCode * ic)
3044 symbol *rlbl = newiTempLabel (NULL);
3045 // bool restoreBank=FALSE;
3046 bool swapBanks = FALSE;
3047 bool resultInF0 = FALSE;
3049 D (emitcode (";", "genPcall"));
3051 dtype = operandType (IC_LEFT (ic))->next;
3052 etype = getSpec(dtype);
3053 /* if caller saves & we have not saved then */
3057 /* if we are calling a not _naked function that is not using
3058 the same register bank then we need to save the
3059 destination registers on the stack */
3060 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3061 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3062 !IFFUNC_ISISR (dtype))
3064 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3065 // restoreBank=TRUE;
3067 // need caution message to user here
3070 if (IS_LITERAL (etype))
3072 /* if send set is not empty then assign */
3075 genSend(reverseSet(_G.sendSet));
3081 emitcode ("mov", "psw,#0x%02x",
3082 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3085 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3087 if (IFFUNC_CALLEESAVES(dtype))
3089 werror (E_BANKED_WITH_CALLEESAVES);
3093 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3095 emitcode ("mov", "r0,#%s", l);
3096 emitcode ("mov", "r1,#(%s >> 8)", l);
3097 emitcode ("mov", "r2,#(%s >> 16)", l);
3098 emitcode ("lcall", "__sdcc_banked_call");
3103 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3108 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3110 if (IFFUNC_CALLEESAVES(dtype))
3112 werror (E_BANKED_WITH_CALLEESAVES);
3116 aopOp (IC_LEFT (ic), ic, FALSE);
3120 /* what if aopGet needs r0 or r1 ??? */
3121 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3122 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3123 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3127 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3128 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3129 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3130 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3133 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3135 /* if send set is not empty then assign */
3138 genSend(reverseSet(_G.sendSet));
3144 emitcode ("mov", "psw,#0x%02x",
3145 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3149 emitcode ("lcall", "__sdcc_banked_call");
3152 else if (_G.sendSet)
3154 /* push the return address on to the stack */
3155 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3156 emitcode ("push", "acc");
3157 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3158 emitcode ("push", "acc");
3160 /* now push the calling address */
3161 aopOp (IC_LEFT (ic), ic, FALSE);
3163 pushSide (IC_LEFT (ic), FPTRSIZE);
3165 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3167 /* if send set is not empty the assign */
3170 genSend(reverseSet(_G.sendSet));
3176 emitcode ("mov", "psw,#0x%02x",
3177 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3181 emitcode ("ret", "");
3184 else /* the send set is empty */
3187 /* now get the calling address into dptr */
3188 aopOp (IC_LEFT (ic), ic, FALSE);
3190 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3191 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3193 emitcode ("mov", "r0,%s", l);
3194 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3195 emitcode ("mov", "dph,%s", l);
3196 emitcode ("mov", "dpl,r0");
3200 emitcode ("mov", "dpl,%s", l);
3201 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3202 emitcode ("mov", "dph,%s", l);
3205 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3209 emitcode ("mov", "psw,#0x%02x",
3210 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3214 emitcode ("lcall", "__sdcc_call_dptr");
3219 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3222 /* if we need assign a result value */
3223 if ((IS_ITEMP (IC_RESULT (ic)) &&
3224 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3225 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3226 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3227 IS_TRUE_SYMOP (IC_RESULT (ic)))
3231 aopOp (IC_RESULT (ic), ic, FALSE);
3234 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3239 /* adjust the stack for parameters if required */
3243 if (ic->parmBytes > 3)
3245 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3246 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3248 emitcode ("mov", "F0,c");
3252 emitcode ("mov", "a,%s", spname);
3253 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3254 emitcode ("mov", "%s,a", spname);
3257 for (i = 0; i < ic->parmBytes; i++)
3258 emitcode ("dec", "%s", spname);
3261 // /* if register bank was saved then unsave them */
3263 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3265 /* if we had saved some registers then unsave them */
3266 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3267 unsaveRegisters (ic);
3269 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3272 emitcode ("mov", "c,F0");
3274 aopOp (IC_RESULT (ic), ic, FALSE);
3275 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3276 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3280 /*-----------------------------------------------------------------*/
3281 /* resultRemat - result is rematerializable */
3282 /*-----------------------------------------------------------------*/
3284 resultRemat (iCode * ic)
3286 if (SKIP_IC (ic) || ic->op == IFX)
3289 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3291 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3292 if (sym->remat && !POINTER_SET (ic))
3299 /*-----------------------------------------------------------------*/
3300 /* inExcludeList - return 1 if the string is in exclude Reg list */
3301 /*-----------------------------------------------------------------*/
3303 regsCmp(void *p1, void *p2)
3305 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3309 inExcludeList (char *s)
3311 const char *p = setFirstItem(options.excludeRegsSet);
3313 if (p == NULL || STRCASECMP(p, "none") == 0)
3317 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3320 /*-----------------------------------------------------------------*/
3321 /* genFunction - generated code for function entry */
3322 /*-----------------------------------------------------------------*/
3324 genFunction (iCode * ic)
3326 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3328 bool switchedPSW = FALSE;
3329 int calleesaves_saved_register = -1;
3330 int stackAdjust = sym->stack;
3331 int accIsFree = sym->recvSize < 4;
3332 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3333 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3336 /* create the function header */
3337 emitcode (";", "-----------------------------------------");
3338 emitcode (";", " function %s", sym->name);
3339 emitcode (";", "-----------------------------------------");
3341 emitcode ("", "%s:", sym->rname);
3342 lineCurr->isLabel = 1;
3343 ftype = operandType (IC_LEFT (ic));
3344 _G.currentFunc = sym;
3346 if (IFFUNC_ISNAKED(ftype))
3348 emitcode(";", "naked function: no prologue.");
3352 /* here we need to generate the equates for the
3353 register bank if required */
3354 if (FUNC_REGBANK (ftype) != rbank)
3358 rbank = FUNC_REGBANK (ftype);
3359 for (i = 0; i < mcs51_nRegs; i++)
3361 if (regs8051[i].type != REG_BIT)
3363 if (strcmp (regs8051[i].base, "0") == 0)
3364 emitcode ("", "%s = 0x%02x",
3366 8 * rbank + regs8051[i].offset);
3368 emitcode ("", "%s = %s + 0x%02x",
3371 8 * rbank + regs8051[i].offset);
3376 /* if this is an interrupt service routine then
3377 save acc, b, dpl, dph */
3378 if (IFFUNC_ISISR (sym->type))
3380 if (!inExcludeList ("acc"))
3381 emitcode ("push", "acc");
3382 if (!inExcludeList ("b"))
3383 emitcode ("push", "b");
3384 if (!inExcludeList ("dpl"))
3385 emitcode ("push", "dpl");
3386 if (!inExcludeList ("dph"))
3387 emitcode ("push", "dph");
3388 /* if this isr has no bank i.e. is going to
3389 run with bank 0 , then we need to save more
3391 if (!FUNC_REGBANK (sym->type))
3395 /* if this function does not call any other
3396 function then we can be economical and
3397 save only those registers that are used */
3398 if (!IFFUNC_HASFCALL(sym->type))
3400 /* if any registers used */
3403 bool bits_pushed = FALSE;
3404 /* save the registers used */
3405 for (i = 0; i < sym->regsUsed->size; i++)
3407 if (bitVectBitValue (sym->regsUsed, i))
3408 bits_pushed = pushReg (i, bits_pushed);
3414 /* this function has a function call. We cannot
3415 determine register usage so we will have to push the
3417 saveRBank (0, ic, FALSE);
3418 if (options.parms_in_bank1) {
3419 for (i=0; i < 8 ; i++ ) {
3420 emitcode ("push","%s",rb1regs[i]);
3427 /* This ISR uses a non-zero bank.
3429 * We assume that the bank is available for our
3432 * However, if this ISR calls a function which uses some
3433 * other bank, we must save that bank entirely.
3435 unsigned long banksToSave = 0;
3437 if (IFFUNC_HASFCALL(sym->type))
3440 #define MAX_REGISTER_BANKS 4
3445 for (i = ic; i; i = i->next)
3447 if (i->op == ENDFUNCTION)
3449 /* we got to the end OK. */
3457 dtype = operandType (IC_LEFT(i));
3459 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3461 /* Mark this bank for saving. */
3462 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3464 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3468 banksToSave |= (1 << FUNC_REGBANK(dtype));
3471 /* And note that we don't need to do it in
3479 /* This is a mess; we have no idea what
3480 * register bank the called function might
3483 * The only thing I can think of to do is
3484 * throw a warning and hope.
3486 werror(W_FUNCPTR_IN_USING_ISR);
3490 if (banksToSave && options.useXstack)
3492 /* Since we aren't passing it an ic,
3493 * saveRBank will assume r0 is available to abuse.
3495 * So switch to our (trashable) bank now, so
3496 * the caller's R0 isn't trashed.
3498 emitcode ("push", "psw");
3499 emitcode ("mov", "psw,#0x%02x",
3500 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3504 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3506 if (banksToSave & (1 << ix))
3508 saveRBank(ix, NULL, FALSE);
3512 // TODO: this needs a closer look
3513 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3516 /* Set the register bank to the desired value if nothing else */
3517 /* has done so yet. */
3520 emitcode ("push", "psw");
3521 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3526 /* This is a non-ISR function. The caller has already switched register */
3527 /* banks, if necessary, so just handle the callee-saves option. */
3529 /* if callee-save to be used for this function
3530 then save the registers being used in this function */
3531 if (IFFUNC_CALLEESAVES(sym->type))
3535 /* if any registers used */
3538 bool bits_pushed = FALSE;
3539 /* save the registers used */
3540 for (i = 0; i < sym->regsUsed->size; i++)
3542 if (bitVectBitValue (sym->regsUsed, i))
3544 /* remember one saved register for later usage */
3545 if (calleesaves_saved_register < 0)
3546 calleesaves_saved_register = i;
3547 bits_pushed = pushReg (i, bits_pushed);
3557 if (options.useXstack)
3559 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3561 emitcode ("mov", "r0,%s", spname);
3562 emitcode ("inc", "%s", spname);
3563 emitcode ("xch", "a,_bpx");
3564 emitcode ("movx", "@r0,a");
3565 emitcode ("inc", "r0");
3566 emitcode ("mov", "a,r0");
3567 emitcode ("xch", "a,_bpx");
3571 emitcode ("push", "_bp"); /* save the callers stack */
3572 emitcode ("mov", "_bp,sp");
3577 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3579 /* set up the stack */
3580 emitcode ("push", "_bp"); /* save the callers stack */
3581 emitcode ("mov", "_bp,sp");
3586 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3587 /* before setting up the stack frame completely. */
3588 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3590 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3594 if (rsym && rsym->regType == REG_CND)
3596 if (rsym && (rsym->accuse || rsym->ruonly))
3598 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3599 rsym = rsym->usl.spillLoc;
3602 /* If the RECEIVE operand immediately spills to the first entry on the */
3603 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3604 /* rather than the usual @r0/r1 machinations. */
3605 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3609 _G.current_iCode = ric;
3610 D(emitcode ("; genReceive",""));
3611 for (ofs=0; ofs < sym->recvSize; ofs++)
3613 if (!strcmp (fReturn[ofs], "a"))
3614 emitcode ("push", "acc");
3616 emitcode ("push", fReturn[ofs]);
3618 stackAdjust -= sym->recvSize;
3621 assert (stackAdjust>=0);
3624 _G.current_iCode = ic;
3628 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3629 /* to free up the accumulator. */
3630 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3634 _G.current_iCode = ric;
3635 D(emitcode ("; genReceive",""));
3636 for (ofs=0; ofs < sym->recvSize; ofs++)
3638 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3640 _G.current_iCode = ic;
3646 /* adjust the stack for the function */
3649 int i = stackAdjust;
3651 werror (W_STACK_OVERFLOW, sym->name);
3653 if (i > 3 && accIsFree)
3655 emitcode ("mov", "a,sp");
3656 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3657 emitcode ("mov", "sp,a");
3661 /* The accumulator is not free, so we will need another register */
3662 /* to clobber. No need to worry about a possible conflict with */
3663 /* the above early RECEIVE optimizations since they would have */
3664 /* freed the accumulator if they were generated. */
3666 if (IFFUNC_CALLEESAVES(sym->type))
3668 /* if it's a callee-saves function we need a saved register */
3669 if (calleesaves_saved_register >= 0)
3671 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3672 emitcode ("mov", "a,sp");
3673 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3674 emitcode ("mov", "sp,a");
3675 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3678 /* do it the hard way */
3680 emitcode ("inc", "sp");
3684 /* not callee-saves, we can clobber r0 */
3685 emitcode ("mov", "r0,a");
3686 emitcode ("mov", "a,sp");
3687 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3688 emitcode ("mov", "sp,a");
3689 emitcode ("mov", "a,r0");
3694 emitcode ("inc", "sp");
3699 char i = ((char) sym->xstack & 0xff);
3701 if (i > 3 && accIsFree)
3703 emitcode ("mov", "a,_spx");
3704 emitcode ("add", "a,#0x%02x", i & 0xff);
3705 emitcode ("mov", "_spx,a");
3709 emitcode ("push", "acc");
3710 emitcode ("mov", "a,_spx");
3711 emitcode ("add", "a,#0x%02x", i & 0xff);
3712 emitcode ("mov", "_spx,a");
3713 emitcode ("pop", "acc");
3718 emitcode ("inc", "_spx");
3722 /* if critical function then turn interrupts off */
3723 if (IFFUNC_ISCRITICAL (ftype))
3725 symbol *tlbl = newiTempLabel (NULL);
3726 emitcode ("setb", "c");
3727 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3728 emitcode ("clr", "c");
3730 emitcode ("push", "psw"); /* save old ea via c in psw */
3734 /*-----------------------------------------------------------------*/
3735 /* genEndFunction - generates epilogue for functions */
3736 /*-----------------------------------------------------------------*/
3738 genEndFunction (iCode * ic)
3740 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3741 lineNode *lnp = lineCurr;
3743 bitVect *regsUsedPrologue;
3744 bitVect *regsUnneeded;
3747 _G.currentFunc = NULL;
3748 if (IFFUNC_ISNAKED(sym->type))
3750 emitcode(";", "naked function: no epilogue.");
3751 if (options.debug && currFunc)
3752 debugFile->writeEndFunction (currFunc, ic, 0);
3756 if (IFFUNC_ISCRITICAL (sym->type))
3758 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3760 emitcode ("rlc", "a"); /* save c in a */
3761 emitcode ("pop", "psw"); /* restore ea via c in psw */
3762 emitcode ("mov", "ea,c");
3763 emitcode ("rrc", "a"); /* restore c from a */
3767 emitcode ("pop", "psw"); /* restore ea via c in psw */
3768 emitcode ("mov", "ea,c");
3772 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3774 if (options.useXstack)
3778 emitcode ("mov", "sp,_bp");
3779 emitcode ("pop", "_bp");
3781 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3783 emitcode ("xch", "a,_bpx");
3784 emitcode ("mov", "r0,a");
3785 emitcode ("dec", "r0");
3786 emitcode ("movx", "a,@r0");
3787 emitcode ("xch", "a,_bpx");
3788 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3791 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3794 emitcode ("mov", "sp,_bp");
3795 emitcode ("pop", "_bp");
3799 /* restore the register bank */
3800 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3802 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3803 || !options.useXstack)
3805 /* Special case of ISR using non-zero bank with useXstack
3808 emitcode ("pop", "psw");
3812 if (IFFUNC_ISISR (sym->type))
3815 /* now we need to restore the registers */
3816 /* if this isr has no bank i.e. is going to
3817 run with bank 0 , then we need to save more
3819 if (!FUNC_REGBANK (sym->type))
3822 /* if this function does not call any other
3823 function then we can be economical and
3824 save only those registers that are used */
3825 if (!IFFUNC_HASFCALL(sym->type))
3827 /* if any registers used */
3830 bool bits_popped = FALSE;
3831 /* save the registers used */
3832 for (i = sym->regsUsed->size; i >= 0; i--)
3834 if (bitVectBitValue (sym->regsUsed, i))
3835 bits_popped = popReg (i, bits_popped);
3841 if (options.parms_in_bank1) {
3842 for (i = 7 ; i >= 0 ; i-- ) {
3843 emitcode ("pop","%s",rb1regs[i]);
3846 /* this function has a function call cannot
3847 determines register usage so we will have to pop the
3849 unsaveRBank (0, ic, FALSE);
3854 /* This ISR uses a non-zero bank.
3856 * Restore any register banks saved by genFunction
3859 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3862 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3864 if (savedBanks & (1 << ix))
3866 unsaveRBank(ix, NULL, FALSE);
3870 if (options.useXstack)
3872 /* Restore bank AFTER calling unsaveRBank,
3873 * since it can trash r0.
3875 emitcode ("pop", "psw");
3879 if (!inExcludeList ("dph"))
3880 emitcode ("pop", "dph");
3881 if (!inExcludeList ("dpl"))
3882 emitcode ("pop", "dpl");
3883 if (!inExcludeList ("b"))
3884 emitcode ("pop", "b");
3885 if (!inExcludeList ("acc"))
3886 emitcode ("pop", "acc");
3888 /* if debug then send end of function */
3889 if (options.debug && currFunc)
3891 debugFile->writeEndFunction (currFunc, ic, 1);
3894 emitcode ("reti", "");
3898 if (IFFUNC_CALLEESAVES(sym->type))
3902 /* if any registers used */
3905 /* save the registers used */
3906 for (i = sym->regsUsed->size; i >= 0; i--)
3908 if (bitVectBitValue (sym->regsUsed, i) ||
3909 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3910 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3913 else if (mcs51_ptrRegReq)
3915 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3916 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3921 /* if debug then send end of function */
3922 if (options.debug && currFunc)
3924 debugFile->writeEndFunction (currFunc, ic, 1);
3927 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3929 emitcode ("ljmp", "__sdcc_banked_ret");
3933 emitcode ("ret", "");
3937 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3940 /* If this was an interrupt handler using bank 0 that called another */
3941 /* function, then all registers must be saved; nothing to optimized. */
3942 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3943 && !FUNC_REGBANK(sym->type))
3946 /* There are no push/pops to optimize if not callee-saves or ISR */
3947 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3950 /* If there were stack parameters, we cannot optimize without also */
3951 /* fixing all of the stack offsets; this is too dificult to consider. */
3952 if (FUNC_HASSTACKPARM(sym->type))
3955 /* Compute the registers actually used */
3956 regsUsed = newBitVect (mcs51_nRegs);
3957 regsUsedPrologue = newBitVect (mcs51_nRegs);
3960 if (lnp->ic && lnp->ic->op == FUNCTION)
3961 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3963 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3965 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3966 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3973 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3974 && !bitVectBitValue (regsUsed, CND_IDX))
3976 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3977 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3978 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3979 bitVectUnSetBit (regsUsed, CND_IDX);
3982 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3984 /* If this was an interrupt handler that called another function */
3985 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3986 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3988 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3989 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3990 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3991 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3992 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3995 /* Remove the unneeded push/pops */
3996 regsUnneeded = newBitVect (mcs51_nRegs);
3999 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4001 if (!strncmp(lnp->line, "push", 4))
4003 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4004 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4006 connectLine (lnp->prev, lnp->next);
4007 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4010 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4012 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4013 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4015 connectLine (lnp->prev, lnp->next);
4016 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4023 for (idx = 0; idx < regsUnneeded->size; idx++)
4024 if (bitVectBitValue (regsUnneeded, idx))
4025 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4027 freeBitVect (regsUnneeded);
4028 freeBitVect (regsUsed);
4029 freeBitVect (regsUsedPrologue);
4032 /*-----------------------------------------------------------------*/
4033 /* genRet - generate code for return statement */
4034 /*-----------------------------------------------------------------*/
4038 int size, offset = 0, pushed = 0;
4040 D (emitcode (";", "genRet"));
4042 /* if we have no return value then
4043 just generate the "ret" */
4047 /* we have something to return then
4048 move the return value into place */
4049 aopOp (IC_LEFT (ic), ic, FALSE);
4050 size = AOP_SIZE (IC_LEFT (ic));
4052 if (IS_BIT(_G.currentFunc->etype))
4054 toCarry (IC_LEFT (ic));
4061 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4064 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4065 emitcode ("push", "%s", l);
4070 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4071 if (strcmp (fReturn[offset], l))
4072 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4079 if (strcmp (fReturn[pushed], "a"))
4080 emitcode ("pop", fReturn[pushed]);
4082 emitcode ("pop", "acc");
4085 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4088 /* generate a jump to the return label
4089 if the next is not the return statement */
4090 if (!(ic->next && ic->next->op == LABEL &&
4091 IC_LABEL (ic->next) == returnLabel))
4093 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4097 /*-----------------------------------------------------------------*/
4098 /* genLabel - generates a label */
4099 /*-----------------------------------------------------------------*/
4101 genLabel (iCode * ic)
4103 /* special case never generate */
4104 if (IC_LABEL (ic) == entryLabel)
4107 emitLabel (IC_LABEL (ic));
4110 /*-----------------------------------------------------------------*/
4111 /* genGoto - generates a ljmp */
4112 /*-----------------------------------------------------------------*/
4114 genGoto (iCode * ic)
4116 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4119 /*-----------------------------------------------------------------*/
4120 /* findLabelBackwards: walks back through the iCode chain looking */
4121 /* for the given label. Returns number of iCode instructions */
4122 /* between that label and given ic. */
4123 /* Returns zero if label not found. */
4124 /*-----------------------------------------------------------------*/
4126 findLabelBackwards (iCode * ic, int key)
4135 /* If we have any pushes or pops, we cannot predict the distance.
4136 I don't like this at all, this should be dealt with in the
4138 if (ic->op == IPUSH || ic->op == IPOP) {
4142 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4151 /*-----------------------------------------------------------------*/
4152 /* genPlusIncr :- does addition with increment if possible */
4153 /*-----------------------------------------------------------------*/
4155 genPlusIncr (iCode * ic)
4157 unsigned int icount;
4158 unsigned int size = getDataSize (IC_RESULT (ic));
4160 /* will try to generate an increment */
4161 /* if the right side is not a literal
4163 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4166 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4168 D(emitcode (";","genPlusIncr"));
4170 /* if increment >=16 bits in register or direct space */
4171 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4172 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4173 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4174 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4175 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4183 /* If the next instruction is a goto and the goto target
4184 * is < 10 instructions previous to this, we can generate
4185 * jumps straight to that target.
4187 if (ic->next && ic->next->op == GOTO
4188 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4189 && labelRange <= 10)
4191 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4192 tlbl = IC_LABEL (ic->next);
4197 tlbl = newiTempLabel (NULL);
4200 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4201 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4202 IS_AOP_PREG (IC_RESULT (ic)))
4203 emitcode ("cjne", "%s,#0x00,%05d$",
4204 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4208 emitcode ("clr", "a");
4209 emitcode ("cjne", "a,%s,%05d$",
4210 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4214 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4217 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4218 IS_AOP_PREG (IC_RESULT (ic)))
4219 emitcode ("cjne", "%s,#0x00,%05d$",
4220 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4223 emitcode ("cjne", "a,%s,%05d$",
4224 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4227 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4231 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4232 IS_AOP_PREG (IC_RESULT (ic)))
4233 emitcode ("cjne", "%s,#0x00,%05d$",
4234 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4238 emitcode ("cjne", "a,%s,%05d$",
4239 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4242 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4252 /* if result is dptr */
4253 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4254 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4255 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4256 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4258 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4264 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4267 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4268 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4270 emitcode ("inc", "dptr");
4275 /* if the literal value of the right hand side
4276 is greater than 4 then it is not worth it */
4280 /* if the sizes are greater than 1 then we cannot */
4281 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4282 AOP_SIZE (IC_LEFT (ic)) > 1)
4285 /* we can if the aops of the left & result match or
4286 if they are in registers and the registers are the
4288 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4292 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4293 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4294 aopPut (IC_RESULT (ic), "a", 0);
4300 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4309 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4310 emitcode ("inc", "a");
4311 aopPut (IC_RESULT (ic), "a", 0);
4318 /*-----------------------------------------------------------------*/
4319 /* outBitAcc - output a bit in acc */
4320 /*-----------------------------------------------------------------*/
4322 outBitAcc (operand * result)
4324 symbol *tlbl = newiTempLabel (NULL);
4325 /* if the result is a bit */
4326 if (AOP_TYPE (result) == AOP_CRY)
4328 aopPut (result, "a", 0);
4332 emitcode ("jz", "%05d$", tlbl->key + 100);
4333 emitcode ("mov", "a,%s", one);
4339 /*-----------------------------------------------------------------*/
4340 /* genPlusBits - generates code for addition of two bits */
4341 /*-----------------------------------------------------------------*/
4343 genPlusBits (iCode * ic)
4345 D (emitcode (";", "genPlusBits"));
4347 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4348 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4350 symbol *lbl = newiTempLabel (NULL);
4351 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4352 emitcode ("cpl", "c");
4354 outBitC (IC_RESULT (ic));
4358 emitcode ("clr", "a");
4359 emitcode ("rlc", "a");
4360 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4361 emitcode ("addc", "a,%s", zero);
4362 outAcc (IC_RESULT (ic));
4367 /* This is the original version of this code.
4369 * This is being kept around for reference,
4370 * because I am not entirely sure I got it right...
4373 adjustArithmeticResult (iCode * ic)
4375 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4376 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4377 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4378 aopPut (IC_RESULT (ic),
4379 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4382 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4383 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4384 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4385 aopPut (IC_RESULT (ic),
4386 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4389 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4390 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4391 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4392 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4393 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4396 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4397 aopPut (IC_RESULT (ic), buffer, 2);
4401 /* This is the pure and virtuous version of this code.
4402 * I'm pretty certain it's right, but not enough to toss the old
4406 adjustArithmeticResult (iCode * ic)
4408 if (opIsGptr (IC_RESULT (ic)) &&
4409 opIsGptr (IC_LEFT (ic)) &&
4410 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4412 aopPut (IC_RESULT (ic),
4413 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4417 if (opIsGptr (IC_RESULT (ic)) &&
4418 opIsGptr (IC_RIGHT (ic)) &&
4419 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4421 aopPut (IC_RESULT (ic),
4422 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4426 if (opIsGptr (IC_RESULT (ic)) &&
4427 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4428 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4429 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4433 SNPRINTF (buffer, sizeof(buffer),
4434 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4435 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4440 /*-----------------------------------------------------------------*/
4441 /* genPlus - generates code for addition */
4442 /*-----------------------------------------------------------------*/
4444 genPlus (iCode * ic)
4446 int size, offset = 0;
4449 bool swappedLR = FALSE;
4450 operand *leftOp, *rightOp;
4453 D (emitcode (";", "genPlus"));
4455 /* special cases :- */
4457 aopOp (IC_LEFT (ic), ic, FALSE);
4458 aopOp (IC_RIGHT (ic), ic, FALSE);
4459 aopOp (IC_RESULT (ic), ic, TRUE);
4461 /* if literal, literal on the right or
4462 if left requires ACC or right is already
4464 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4465 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4466 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4468 operand *t = IC_RIGHT (ic);
4469 IC_RIGHT (ic) = IC_LEFT (ic);
4474 /* if both left & right are in bit
4476 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4477 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4483 /* if left in bit space & right literal */
4484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4485 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4487 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4488 /* if result in bit space */
4489 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4491 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4492 emitcode ("cpl", "c");
4493 outBitC (IC_RESULT (ic));
4497 size = getDataSize (IC_RESULT (ic));
4500 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4501 emitcode ("addc", "a,%s", zero);
4502 aopPut (IC_RESULT (ic), "a", offset++);
4508 /* if I can do an increment instead
4509 of add then GOOD for ME */
4510 if (genPlusIncr (ic) == TRUE)
4513 size = getDataSize (IC_RESULT (ic));
4514 leftOp = IC_LEFT(ic);
4515 rightOp = IC_RIGHT(ic);
4518 /* if this is an add for an array access
4519 at a 256 byte boundary */
4521 && AOP_TYPE (op) == AOP_IMMD
4523 && IS_SPEC (OP_SYM_ETYPE (op))
4524 && SPEC_ABSA (OP_SYM_ETYPE (op))
4525 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4528 D(emitcode ("; genPlus aligned array",""));
4529 aopPut (IC_RESULT (ic),
4530 aopGet (rightOp, 0, FALSE, FALSE),
4533 if( 1 == getDataSize (IC_RIGHT (ic)) )
4535 aopPut (IC_RESULT (ic),
4536 aopGet (leftOp, 1, FALSE, FALSE),
4541 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4542 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4543 aopPut (IC_RESULT (ic), "a", 1);
4548 /* if the lower bytes of a literal are zero skip the addition */
4549 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4551 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4552 (skip_bytes+1 < size))
4557 D(emitcode ("; genPlus shortcut",""));
4562 if( offset >= skip_bytes )
4564 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4567 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4569 emitcode("xch", "a,b");
4570 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4571 emitcode (add, "a,b");
4574 else if (aopGetUsesAcc (leftOp, offset))
4576 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4577 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4581 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4582 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4584 aopPut (IC_RESULT (ic), "a", offset);
4585 add = "addc"; /* further adds must propagate carry */
4589 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4590 isOperandVolatile (IC_RESULT (ic), FALSE))
4593 aopPut (IC_RESULT (ic),
4594 aopGet (leftOp, offset, FALSE, FALSE),
4601 adjustArithmeticResult (ic);
4604 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4607 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4608 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617 /*-----------------------------------------------------------------*/
4618 /* genMinusDec :- does subtraction with decrement if possible */
4619 /*-----------------------------------------------------------------*/
4621 genMinusDec (iCode * ic)
4623 unsigned int icount;
4624 unsigned int size = getDataSize (IC_RESULT (ic));
4626 /* will try to generate an increment */
4627 /* if the right side is not a literal
4629 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4632 /* if the literal value of the right hand side
4633 is greater than 4 then it is not worth it */
4634 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4637 D (emitcode (";", "genMinusDec"));
4639 /* if decrement >=16 bits in register or direct space */
4640 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4641 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4642 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4643 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4651 /* If the next instruction is a goto and the goto target
4652 * is <= 10 instructions previous to this, we can generate
4653 * jumps straight to that target.
4655 if (ic->next && ic->next->op == GOTO
4656 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4657 && labelRange <= 10)
4659 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4660 tlbl = IC_LABEL (ic->next);
4665 tlbl = newiTempLabel (NULL);
4669 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4670 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4671 IS_AOP_PREG (IC_RESULT (ic)))
4672 emitcode ("cjne", "%s,#0xff,%05d$"
4673 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4677 emitcode ("mov", "a,#0xff");
4678 emitcode ("cjne", "a,%s,%05d$"
4679 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4682 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4685 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4686 IS_AOP_PREG (IC_RESULT (ic)))
4687 emitcode ("cjne", "%s,#0xff,%05d$"
4688 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4692 emitcode ("cjne", "a,%s,%05d$"
4693 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4696 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4700 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4701 IS_AOP_PREG (IC_RESULT (ic)))
4702 emitcode ("cjne", "%s,#0xff,%05d$"
4703 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4707 emitcode ("cjne", "a,%s,%05d$"
4708 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4711 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4720 /* if the sizes are greater than 1 then we cannot */
4721 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4722 AOP_SIZE (IC_LEFT (ic)) > 1)
4725 /* we can if the aops of the left & result match or
4726 if they are in registers and the registers are the
4728 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4732 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4734 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4739 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4744 emitcode ("dec", "%s", l);
4747 if (AOP_NEEDSACC (IC_RESULT (ic)))
4748 aopPut (IC_RESULT (ic), "a", 0);
4755 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4756 emitcode ("dec", "a");
4757 aopPut (IC_RESULT (ic), "a", 0);
4764 /*-----------------------------------------------------------------*/
4765 /* addSign - complete with sign */
4766 /*-----------------------------------------------------------------*/
4768 addSign (operand * result, int offset, int sign)
4770 int size = (getDataSize (result) - offset);
4775 emitcode ("rlc", "a");
4776 emitcode ("subb", "a,acc");
4779 aopPut (result, "a", offset++);
4786 aopPut (result, zero, offset++);
4792 /*-----------------------------------------------------------------*/
4793 /* genMinusBits - generates code for subtraction of two bits */
4794 /*-----------------------------------------------------------------*/
4796 genMinusBits (iCode * ic)
4798 symbol *lbl = newiTempLabel (NULL);
4800 D (emitcode (";", "genMinusBits"));
4802 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4804 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4805 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4806 emitcode ("cpl", "c");
4808 outBitC (IC_RESULT (ic));
4812 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4813 emitcode ("subb", "a,acc");
4814 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4815 emitcode ("inc", "a");
4817 aopPut (IC_RESULT (ic), "a", 0);
4818 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4822 /*-----------------------------------------------------------------*/
4823 /* genMinus - generates code for subtraction */
4824 /*-----------------------------------------------------------------*/
4826 genMinus (iCode * ic)
4828 int size, offset = 0;
4830 D (emitcode (";", "genMinus"));
4832 aopOp (IC_LEFT (ic), ic, FALSE);
4833 aopOp (IC_RIGHT (ic), ic, FALSE);
4834 aopOp (IC_RESULT (ic), ic, TRUE);
4836 /* special cases :- */
4837 /* if both left & right are in bit space */
4838 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4839 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4845 /* if I can do an decrement instead
4846 of subtract then GOOD for ME */
4847 if (genMinusDec (ic) == TRUE)
4850 size = getDataSize (IC_RESULT (ic));
4852 /* if literal, add a,#-lit, else normal subb */
4853 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4855 unsigned long lit = 0L;
4856 bool useCarry = FALSE;
4858 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4863 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4865 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4866 if (!offset && !size && lit== (unsigned long) -1)
4868 emitcode ("dec", "a");
4872 /* first add without previous c */
4873 emitcode ("add", "a,#0x%02x",
4874 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4879 emitcode ("addc", "a,#0x%02x",
4880 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4882 aopPut (IC_RESULT (ic), "a", offset++);
4886 /* no need to add zeroes */
4887 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4889 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4898 operand *leftOp, *rightOp;
4900 leftOp = IC_LEFT(ic);
4901 rightOp = IC_RIGHT(ic);
4905 if (aopGetUsesAcc(rightOp, offset)) {
4906 if (aopGetUsesAcc(leftOp, offset)) {
4909 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4911 emitcode ("mov", "b,a");
4914 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4915 emitcode ("subb", "a,b");
4918 /* reverse subtraction with 2's complement */
4920 emitcode( "setb", "c");
4922 emitcode( "cpl", "c");
4923 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4924 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4925 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4926 emitcode("cpl", "a");
4927 if (size) /* skip if last byte */
4928 emitcode( "cpl", "c");
4931 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4934 emitcode ("subb", "a,%s",
4935 aopGet(rightOp, offset, FALSE, TRUE));
4938 aopPut (IC_RESULT (ic), "a", offset++);
4942 adjustArithmeticResult (ic);
4945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4946 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4951 /*-----------------------------------------------------------------*/
4952 /* genMultbits :- multiplication of bits */
4953 /*-----------------------------------------------------------------*/
4955 genMultbits (operand * left,
4959 D (emitcode (";", "genMultbits"));
4961 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4962 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4966 /*-----------------------------------------------------------------*/
4967 /* genMultOneByte : 8*8=8/16 bit multiplication */
4968 /*-----------------------------------------------------------------*/
4970 genMultOneByte (operand * left,
4975 int size = AOP_SIZE (result);
4976 bool runtimeSign, compiletimeSign;
4977 bool lUnsigned, rUnsigned, pushedB;
4979 D (emitcode (";", "genMultOneByte"));
4981 if (size < 1 || size > 2)
4983 /* this should never happen */
4984 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4985 AOP_SIZE(result), __FILE__, lineno);
4989 /* (if two literals: the value is computed before) */
4990 /* if one literal, literal on the right */
4991 if (AOP_TYPE (left) == AOP_LIT)
4996 /* emitcode (";", "swapped left and right"); */
4998 /* if no literal, unsigned on the right: shorter code */
4999 if ( AOP_TYPE (right) != AOP_LIT
5000 && SPEC_USIGN (getSpec (operandType (left))))
5007 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5008 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5012 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5013 no need to take care about the signedness! */
5014 || (lUnsigned && rUnsigned))
5016 /* just an unsigned 8 * 8 = 8 multiply
5018 /* emitcode (";","unsigned"); */
5019 /* TODO: check for accumulator clash between left & right aops? */
5021 if (AOP_TYPE (right) == AOP_LIT)
5023 /* moving to accumulator first helps peepholes */
5024 MOVA (aopGet (left, 0, FALSE, FALSE));
5025 MOVB (aopGet (right, 0, FALSE, FALSE));
5029 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5030 MOVA (aopGet (left, 0, FALSE, FALSE));
5033 emitcode ("mul", "ab");
5034 aopPut (result, "a", 0);
5036 aopPut (result, "b", 1);
5042 /* we have to do a signed multiply */
5043 /* emitcode (";", "signed"); */
5045 /* now sign adjust for both left & right */
5047 /* let's see what's needed: */
5048 /* apply negative sign during runtime */
5049 runtimeSign = FALSE;
5050 /* negative sign from literals */
5051 compiletimeSign = FALSE;
5055 if (AOP_TYPE(left) == AOP_LIT)
5057 /* signed literal */
5058 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5060 compiletimeSign = TRUE;
5063 /* signed but not literal */
5069 if (AOP_TYPE(right) == AOP_LIT)
5071 /* signed literal */
5072 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5074 compiletimeSign ^= TRUE;
5077 /* signed but not literal */
5081 /* initialize F0, which stores the runtime sign */
5084 if (compiletimeSign)
5085 emitcode ("setb", "F0"); /* set sign flag */
5087 emitcode ("clr", "F0"); /* reset sign flag */
5090 /* save the signs of the operands */
5091 if (AOP_TYPE(right) == AOP_LIT)
5093 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5095 if (!rUnsigned && val < 0)
5096 emitcode ("mov", "b,#0x%02x", -val);
5098 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5100 else /* ! literal */
5102 if (rUnsigned) /* emitcode (";", "signed"); */
5103 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5106 MOVA (aopGet (right, 0, FALSE, FALSE));
5107 lbl = newiTempLabel (NULL);
5108 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5109 emitcode ("cpl", "F0"); /* complement sign flag */
5110 emitcode ("cpl", "a"); /* 2's complement */
5111 emitcode ("inc", "a");
5113 emitcode ("mov", "b,a");
5117 if (AOP_TYPE(left) == AOP_LIT)
5119 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5121 if (!lUnsigned && val < 0)
5122 emitcode ("mov", "a,#0x%02x", -val);
5124 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5126 else /* ! literal */
5128 MOVA (aopGet (left, 0, FALSE, FALSE));
5132 lbl = newiTempLabel (NULL);
5133 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5134 emitcode ("cpl", "F0"); /* complement sign flag */
5135 emitcode ("cpl", "a"); /* 2's complement */
5136 emitcode ("inc", "a");
5141 /* now the multiplication */
5142 emitcode ("mul", "ab");
5143 if (runtimeSign || compiletimeSign)
5145 lbl = newiTempLabel (NULL);
5147 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5148 emitcode ("cpl", "a"); /* lsb 2's complement */
5150 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5153 emitcode ("add", "a,#1"); /* this sets carry flag */
5154 emitcode ("xch", "a,b");
5155 emitcode ("cpl", "a"); /* msb 2's complement */
5156 emitcode ("addc", "a,#0");
5157 emitcode ("xch", "a,b");
5161 aopPut (result, "a", 0);
5163 aopPut (result, "b", 1);
5168 /*-----------------------------------------------------------------*/
5169 /* genMult - generates code for multiplication */
5170 /*-----------------------------------------------------------------*/
5172 genMult (iCode * ic)
5174 operand *left = IC_LEFT (ic);
5175 operand *right = IC_RIGHT (ic);
5176 operand *result = IC_RESULT (ic);
5178 D (emitcode (";", "genMult"));
5180 /* assign the asmops */
5181 aopOp (left, ic, FALSE);
5182 aopOp (right, ic, FALSE);
5183 aopOp (result, ic, TRUE);
5185 /* special cases first */
5187 if (AOP_TYPE (left) == AOP_CRY &&
5188 AOP_TYPE (right) == AOP_CRY)
5190 genMultbits (left, right, result);
5194 /* if both are of size == 1 */
5195 #if 0 // one of them can be a sloc shared with the result
5196 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5198 if (getSize(operandType(left)) == 1 &&
5199 getSize(operandType(right)) == 1)
5202 genMultOneByte (left, right, result);
5206 /* should have been converted to function call */
5207 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5208 getSize(OP_SYMBOL(right)->type));
5212 freeAsmop (result, NULL, ic, TRUE);
5213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5217 /*-----------------------------------------------------------------*/
5218 /* genDivbits :- division of bits */
5219 /*-----------------------------------------------------------------*/
5221 genDivbits (operand * left,
5228 D(emitcode ("; genDivbits",""));
5232 /* the result must be bit */
5233 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5234 l = aopGet (left, 0, FALSE, FALSE);
5238 emitcode ("div", "ab");
5239 emitcode ("rrc", "a");
5243 aopPut (result, "c", 0);
5246 /*-----------------------------------------------------------------*/
5247 /* genDivOneByte : 8 bit division */
5248 /*-----------------------------------------------------------------*/
5250 genDivOneByte (operand * left,
5254 bool lUnsigned, rUnsigned, pushedB;
5255 bool runtimeSign, compiletimeSign;
5256 bool accuse = FALSE;
5257 bool pushedA = FALSE;
5261 D(emitcode ("; genDivOneByte",""));
5263 /* Why is it necessary that genDivOneByte() can return an int result?
5266 volatile unsigned char uc;
5267 volatile signed char sc1, sc2;
5280 In all cases a one byte result would overflow, the following cast to int
5281 would return the wrong result.
5283 Two possible solution:
5284 a) cast operands to int, if ((unsigned) / (signed)) or
5285 ((signed) / (signed))
5286 b) return an 16 bit signed int; this is what we're doing here!
5289 size = AOP_SIZE (result) - 1;
5291 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5292 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5296 /* signed or unsigned */
5297 if (lUnsigned && rUnsigned)
5299 /* unsigned is easy */
5300 MOVB (aopGet (right, 0, FALSE, FALSE));
5301 MOVA (aopGet (left, 0, FALSE, FALSE));
5302 emitcode ("div", "ab");
5303 aopPut (result, "a", 0);
5305 aopPut (result, zero, offset++);
5311 /* signed is a little bit more difficult */
5313 /* now sign adjust for both left & right */
5315 /* let's see what's needed: */
5316 /* apply negative sign during runtime */
5317 runtimeSign = FALSE;
5318 /* negative sign from literals */
5319 compiletimeSign = FALSE;
5323 if (AOP_TYPE(left) == AOP_LIT)
5325 /* signed literal */
5326 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5328 compiletimeSign = TRUE;
5331 /* signed but not literal */
5337 if (AOP_TYPE(right) == AOP_LIT)
5339 /* signed literal */
5340 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5342 compiletimeSign ^= TRUE;
5345 /* signed but not literal */
5349 /* initialize F0, which stores the runtime sign */
5352 if (compiletimeSign)
5353 emitcode ("setb", "F0"); /* set sign flag */
5355 emitcode ("clr", "F0"); /* reset sign flag */
5358 /* save the signs of the operands */
5359 if (AOP_TYPE(right) == AOP_LIT)
5361 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5363 if (!rUnsigned && val < 0)
5364 emitcode ("mov", "b,#0x%02x", -val);
5366 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5368 else /* ! literal */
5371 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5374 MOVA (aopGet (right, 0, FALSE, FALSE));
5375 lbl = newiTempLabel (NULL);
5376 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5377 emitcode ("cpl", "F0"); /* complement sign flag */
5378 emitcode ("cpl", "a"); /* 2's complement */
5379 emitcode ("inc", "a");
5381 emitcode ("mov", "b,a");
5385 if (AOP_TYPE(left) == AOP_LIT)
5387 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5389 if (!lUnsigned && val < 0)
5390 emitcode ("mov", "a,#0x%02x", -val);
5392 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5394 else /* ! literal */
5396 MOVA (aopGet (left, 0, FALSE, FALSE));
5400 lbl = newiTempLabel (NULL);
5401 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5402 emitcode ("cpl", "F0"); /* complement sign flag */
5403 emitcode ("cpl", "a"); /* 2's complement */
5404 emitcode ("inc", "a");
5409 /* now the division */
5410 emitcode ("div", "ab");
5412 if (runtimeSign || compiletimeSign)
5414 lbl = newiTempLabel (NULL);
5416 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5417 emitcode ("cpl", "a"); /* lsb 2's complement */
5418 emitcode ("inc", "a");
5421 accuse = aopPut (result, "a", 0);
5424 /* msb is 0x00 or 0xff depending on the sign */
5429 emitcode ("push", "acc");
5432 emitcode ("mov", "c,F0");
5433 emitcode ("subb", "a,acc");
5435 aopPut (result, "a", offset++);
5437 else /* compiletimeSign */
5439 if (aopPutUsesAcc (result, "#0xFF", offset))
5441 emitcode ("push", "acc");
5445 aopPut (result, "#0xff", offset++);
5451 aopPut (result, "a", 0);
5453 aopPut (result, zero, offset++);
5457 emitcode ("pop", "acc");
5461 /*-----------------------------------------------------------------*/
5462 /* genDiv - generates code for division */
5463 /*-----------------------------------------------------------------*/
5467 operand *left = IC_LEFT (ic);
5468 operand *right = IC_RIGHT (ic);
5469 operand *result = IC_RESULT (ic);
5471 D (emitcode (";", "genDiv"));
5473 /* assign the amsops */
5474 aopOp (left, ic, FALSE);
5475 aopOp (right, ic, FALSE);
5476 aopOp (result, ic, TRUE);
5478 /* special cases first */
5480 if (AOP_TYPE (left) == AOP_CRY &&
5481 AOP_TYPE (right) == AOP_CRY)
5483 genDivbits (left, right, result);
5487 /* if both are of size == 1 */
5488 if (AOP_SIZE (left) == 1 &&
5489 AOP_SIZE (right) == 1)
5491 genDivOneByte (left, right, result);
5495 /* should have been converted to function call */
5498 freeAsmop (result, NULL, ic, TRUE);
5499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 /*-----------------------------------------------------------------*/
5504 /* genModbits :- modulus of bits */
5505 /*-----------------------------------------------------------------*/
5507 genModbits (operand * left,
5514 D (emitcode (";", "genModbits"));
5518 /* the result must be bit */
5519 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5520 l = aopGet (left, 0, FALSE, FALSE);
5524 emitcode ("div", "ab");
5525 emitcode ("mov", "a,b");
5526 emitcode ("rrc", "a");
5530 aopPut (result, "c", 0);
5533 /*-----------------------------------------------------------------*/
5534 /* genModOneByte : 8 bit modulus */
5535 /*-----------------------------------------------------------------*/
5537 genModOneByte (operand * left,
5541 bool lUnsigned, rUnsigned, pushedB;
5542 bool runtimeSign, compiletimeSign;
5546 D (emitcode (";", "genModOneByte"));
5548 size = AOP_SIZE (result) - 1;
5550 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5551 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5553 /* if right is a literal, check it for 2^n */
5554 if (AOP_TYPE(right) == AOP_LIT)
5556 unsigned char val = abs((int) operandLitValue(right));
5557 symbol *lbl2 = NULL;
5561 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5570 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5571 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5572 /* because iCode should have been changed to genAnd */
5573 /* see file "SDCCopt.c", function "convertToFcall()" */
5575 MOVA (aopGet (left, 0, FALSE, FALSE));
5576 emitcode ("mov", "c,acc.7");
5577 emitcode ("anl", "a,#0x%02x", val - 1);
5578 lbl = newiTempLabel (NULL);
5579 emitcode ("jz", "%05d$", (lbl->key + 100));
5580 emitcode ("jnc", "%05d$", (lbl->key + 100));
5581 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5587 aopPut (result, "a", 0);
5589 aopPut (result, "#0xff", offs2++);
5590 lbl2 = newiTempLabel (NULL);
5591 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5594 aopPut (result, "a", 0);
5596 aopPut (result, zero, offset++);
5610 /* signed or unsigned */
5611 if (lUnsigned && rUnsigned)
5613 /* unsigned is easy */
5614 MOVB (aopGet (right, 0, FALSE, FALSE));
5615 MOVA (aopGet (left, 0, FALSE, FALSE));
5616 emitcode ("div", "ab");
5617 aopPut (result, "b", 0);
5619 aopPut (result, zero, offset++);
5625 /* signed is a little bit more difficult */
5627 /* now sign adjust for both left & right */
5629 /* modulus: sign of the right operand has no influence on the result! */
5630 if (AOP_TYPE(right) == AOP_LIT)
5632 signed char val = (char) operandLitValue(right);
5634 if (!rUnsigned && val < 0)
5635 emitcode ("mov", "b,#0x%02x", -val);
5637 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5639 else /* not literal */
5642 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5645 MOVA (aopGet (right, 0, FALSE, FALSE));
5646 lbl = newiTempLabel (NULL);
5647 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5648 emitcode ("cpl", "a"); /* 2's complement */
5649 emitcode ("inc", "a");
5651 emitcode ("mov", "b,a");
5655 /* let's see what's needed: */
5656 /* apply negative sign during runtime */
5657 runtimeSign = FALSE;
5658 /* negative sign from literals */
5659 compiletimeSign = FALSE;
5661 /* sign adjust left side */
5662 if (AOP_TYPE(left) == AOP_LIT)
5664 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5666 if (!lUnsigned && val < 0)
5668 compiletimeSign = TRUE; /* set sign flag */
5669 emitcode ("mov", "a,#0x%02x", -val);
5672 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5674 else /* ! literal */
5676 MOVA (aopGet (left, 0, FALSE, FALSE));
5681 emitcode ("clr", "F0"); /* clear sign flag */
5683 lbl = newiTempLabel (NULL);
5684 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5685 emitcode ("setb", "F0"); /* set sign flag */
5686 emitcode ("cpl", "a"); /* 2's complement */
5687 emitcode ("inc", "a");
5692 /* now the modulus */
5693 emitcode ("div", "ab");
5695 if (runtimeSign || compiletimeSign)
5697 emitcode ("mov", "a,b");
5698 lbl = newiTempLabel (NULL);
5700 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5701 emitcode ("cpl", "a"); /* 2's complement */
5702 emitcode ("inc", "a");
5705 aopPut (result, "a", 0);
5708 /* msb is 0x00 or 0xff depending on the sign */
5711 emitcode ("mov", "c,F0");
5712 emitcode ("subb", "a,acc");
5714 aopPut (result, "a", offset++);
5716 else /* compiletimeSign */
5718 aopPut (result, "#0xff", offset++);
5723 aopPut (result, "b", 0);
5725 aopPut (result, zero, offset++);
5731 /*-----------------------------------------------------------------*/
5732 /* genMod - generates code for division */
5733 /*-----------------------------------------------------------------*/
5737 operand *left = IC_LEFT (ic);
5738 operand *right = IC_RIGHT (ic);
5739 operand *result = IC_RESULT (ic);
5741 D (emitcode (";", "genMod"));
5743 /* assign the asmops */
5744 aopOp (left, ic, FALSE);
5745 aopOp (right, ic, FALSE);
5746 aopOp (result, ic, TRUE);
5748 /* special cases first */
5750 if (AOP_TYPE (left) == AOP_CRY &&
5751 AOP_TYPE (right) == AOP_CRY)
5753 genModbits (left, right, result);
5757 /* if both are of size == 1 */
5758 if (AOP_SIZE (left) == 1 &&
5759 AOP_SIZE (right) == 1)
5761 genModOneByte (left, right, result);
5765 /* should have been converted to function call */
5769 freeAsmop (result, NULL, ic, TRUE);
5770 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774 /*-----------------------------------------------------------------*/
5775 /* genIfxJump :- will create a jump depending on the ifx */
5776 /*-----------------------------------------------------------------*/
5778 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5781 symbol *tlbl = newiTempLabel (NULL);
5784 D (emitcode (";", "genIfxJump"));
5786 /* if true label then we jump if condition
5790 jlbl = IC_TRUE (ic);
5791 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5792 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5796 /* false label is present */
5797 jlbl = IC_FALSE (ic);
5798 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5799 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5801 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5802 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5804 emitcode (inst, "%05d$", tlbl->key + 100);
5805 freeForBranchAsmop (result);
5806 freeForBranchAsmop (right);
5807 freeForBranchAsmop (left);
5808 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5811 /* mark the icode as generated */
5815 /*-----------------------------------------------------------------*/
5816 /* genCmp :- greater or less than comparison */
5817 /*-----------------------------------------------------------------*/
5819 genCmp (operand * left, operand * right,
5820 operand * result, iCode * ifx, int sign, iCode *ic)
5822 int size, offset = 0;
5823 unsigned long lit = 0L;
5826 D (emitcode (";", "genCmp"));
5828 /* if left & right are bit variables */
5829 if (AOP_TYPE (left) == AOP_CRY &&
5830 AOP_TYPE (right) == AOP_CRY)
5832 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5833 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5837 /* subtract right from left if at the
5838 end the carry flag is set then we know that
5839 left is greater than right */
5840 size = max (AOP_SIZE (left), AOP_SIZE (right));
5842 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5843 if ((size == 1) && !sign &&
5844 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5846 symbol *lbl = newiTempLabel (NULL);
5847 emitcode ("cjne", "%s,%s,%05d$",
5848 aopGet (left, offset, FALSE, FALSE),
5849 aopGet (right, offset, FALSE, FALSE),
5855 if (AOP_TYPE (right) == AOP_LIT)
5857 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5858 /* optimize if(x < 0) or if(x >= 0) */
5867 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5868 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5870 genIfxJump (ifx, "acc.7", left, right, result);
5871 freeAsmop (right, NULL, ic, TRUE);
5872 freeAsmop (left, NULL, ic, TRUE);
5878 emitcode ("rlc", "a");
5885 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5886 while (size && (bytelit == 0))
5889 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5895 MOVA (aopGet (left, offset, FALSE, FALSE));
5896 if (sign && size == 0)
5898 emitcode ("xrl", "a,#0x80");
5899 emitcode ("subb", "a,#0x%02x",
5900 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5904 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5914 bool pushedB = FALSE;
5915 rightInB = aopGetUsesAcc(right, offset);
5919 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5921 MOVA (aopGet (left, offset, FALSE, FALSE));
5922 if (sign && size == 0)
5924 emitcode ("xrl", "a,#0x80");
5929 MOVB (aopGet (right, offset, FALSE, FALSE));
5931 emitcode ("xrl", "b,#0x80");
5932 emitcode ("subb", "a,b");
5937 emitcode ("subb", "a,b");
5939 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5949 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5950 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5957 /* if the result is used in the next
5958 ifx conditional branch then generate
5959 code a little differently */
5962 genIfxJump (ifx, "c", NULL, NULL, result);
5968 /* leave the result in acc */
5972 /*-----------------------------------------------------------------*/
5973 /* genCmpGt :- greater than comparison */
5974 /*-----------------------------------------------------------------*/
5976 genCmpGt (iCode * ic, iCode * ifx)
5978 operand *left, *right, *result;
5979 sym_link *letype, *retype;
5982 D (emitcode (";", "genCmpGt"));
5984 left = IC_LEFT (ic);
5985 right = IC_RIGHT (ic);
5986 result = IC_RESULT (ic);
5988 letype = getSpec (operandType (left));
5989 retype = getSpec (operandType (right));
5990 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5991 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5992 /* assign the amsops */
5993 aopOp (result, ic, TRUE);
5994 aopOp (left, ic, FALSE);
5995 aopOp (right, ic, FALSE);
5997 genCmp (right, left, result, ifx, sign, ic);
5999 freeAsmop (result, NULL, ic, TRUE);
6002 /*-----------------------------------------------------------------*/
6003 /* genCmpLt - less than comparisons */
6004 /*-----------------------------------------------------------------*/
6006 genCmpLt (iCode * ic, iCode * ifx)
6008 operand *left, *right, *result;
6009 sym_link *letype, *retype;
6012 D (emitcode (";", "genCmpLt"));
6014 left = IC_LEFT (ic);
6015 right = IC_RIGHT (ic);
6016 result = IC_RESULT (ic);
6018 letype = getSpec (operandType (left));
6019 retype = getSpec (operandType (right));
6020 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6021 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6022 /* assign the amsops */
6023 aopOp (result, ic, TRUE);
6024 aopOp (left, ic, FALSE);
6025 aopOp (right, ic, FALSE);
6027 genCmp (left, right, result, ifx, sign, ic);
6029 freeAsmop (result, NULL, ic, TRUE);
6032 /*-----------------------------------------------------------------*/
6033 /* gencjneshort - compare and jump if not equal */
6034 /*-----------------------------------------------------------------*/
6036 gencjneshort (operand * left, operand * right, symbol * lbl)
6038 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6040 unsigned long lit = 0L;
6042 D (emitcode (";", "gencjneshort"));
6044 /* if the left side is a literal or
6045 if the right is in a pointer register and left
6047 if ((AOP_TYPE (left) == AOP_LIT) ||
6048 (AOP_TYPE (left) == AOP_IMMD) ||
6049 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6056 if (AOP_TYPE (right) == AOP_LIT)
6057 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6059 /* if the right side is a literal then anything goes */
6060 if (AOP_TYPE (right) == AOP_LIT &&
6061 AOP_TYPE (left) != AOP_DIR &&
6062 AOP_TYPE (left) != AOP_IMMD)
6066 emitcode ("cjne", "%s,%s,%05d$",
6067 aopGet (left, offset, FALSE, FALSE),
6068 aopGet (right, offset, FALSE, FALSE),
6074 /* if the right side is in a register or in direct space or
6075 if the left is a pointer register & right is not */
6076 else if (AOP_TYPE (right) == AOP_REG ||
6077 AOP_TYPE (right) == AOP_DIR ||
6078 AOP_TYPE (right) == AOP_LIT ||
6079 AOP_TYPE (right) == AOP_IMMD ||
6080 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6081 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6085 MOVA (aopGet (left, offset, FALSE, FALSE));
6086 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6087 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6088 emitcode ("jnz", "%05d$", lbl->key + 100);
6090 emitcode ("cjne", "a,%s,%05d$",
6091 aopGet (right, offset, FALSE, TRUE),
6098 /* right is a pointer reg need both a & b */
6101 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6102 wassertl(!BINUSE, "B was in use");
6103 MOVB (aopGet (left, offset, FALSE, FALSE));
6104 MOVA (aopGet (right, offset, FALSE, FALSE));
6105 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6111 /*-----------------------------------------------------------------*/
6112 /* gencjne - compare and jump if not equal */
6113 /*-----------------------------------------------------------------*/
6115 gencjne (operand * left, operand * right, symbol * lbl)
6117 symbol *tlbl = newiTempLabel (NULL);
6119 D (emitcode (";", "gencjne"));
6121 gencjneshort (left, right, lbl);
6123 emitcode ("mov", "a,%s", one);
6124 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6126 emitcode ("clr", "a");
6130 /*-----------------------------------------------------------------*/
6131 /* genCmpEq - generates code for equal to */
6132 /*-----------------------------------------------------------------*/
6134 genCmpEq (iCode * ic, iCode * ifx)
6136 bool swappedLR = FALSE;
6137 operand *left, *right, *result;
6139 D (emitcode (";", "genCmpEq"));
6141 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6142 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6143 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6145 /* if literal, literal on the right or
6146 if the right is in a pointer register and left
6148 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6149 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6151 operand *t = IC_RIGHT (ic);
6152 IC_RIGHT (ic) = IC_LEFT (ic);
6157 if (ifx && !AOP_SIZE (result))
6160 /* if they are both bit variables */
6161 if (AOP_TYPE (left) == AOP_CRY &&
6162 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6164 if (AOP_TYPE (right) == AOP_LIT)
6166 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6169 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6170 emitcode ("cpl", "c");
6174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6178 emitcode ("clr", "c");
6180 /* AOP_TYPE(right) == AOP_CRY */
6184 symbol *lbl = newiTempLabel (NULL);
6185 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6186 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6187 emitcode ("cpl", "c");
6190 /* if true label then we jump if condition
6192 tlbl = newiTempLabel (NULL);
6195 emitcode ("jnc", "%05d$", tlbl->key + 100);
6196 freeForBranchAsmop (result);
6197 freeForBranchAsmop (right);
6198 freeForBranchAsmop (left);
6199 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6203 emitcode ("jc", "%05d$", tlbl->key + 100);
6204 freeForBranchAsmop (result);
6205 freeForBranchAsmop (right);
6206 freeForBranchAsmop (left);
6207 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6213 tlbl = newiTempLabel (NULL);
6214 gencjneshort (left, right, tlbl);
6217 freeForBranchAsmop (result);
6218 freeForBranchAsmop (right);
6219 freeForBranchAsmop (left);
6220 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6225 symbol *lbl = newiTempLabel (NULL);
6226 emitcode ("sjmp", "%05d$", lbl->key + 100);
6228 freeForBranchAsmop (result);
6229 freeForBranchAsmop (right);
6230 freeForBranchAsmop (left);
6231 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6235 /* mark the icode as generated */
6240 /* if they are both bit variables */
6241 if (AOP_TYPE (left) == AOP_CRY &&
6242 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6244 if (AOP_TYPE (right) == AOP_LIT)
6246 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6249 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6250 emitcode ("cpl", "c");
6254 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6258 emitcode ("clr", "c");
6260 /* AOP_TYPE(right) == AOP_CRY */
6264 symbol *lbl = newiTempLabel (NULL);
6265 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6266 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6267 emitcode ("cpl", "c");
6271 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6278 genIfxJump (ifx, "c", left, right, result);
6281 /* if the result is used in an arithmetic operation
6282 then put the result in place */
6287 gencjne (left, right, newiTempLabel (NULL));
6288 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6290 aopPut (result, "a", 0);
6295 genIfxJump (ifx, "a", left, right, result);
6298 /* if the result is used in an arithmetic operation
6299 then put the result in place */
6300 if (AOP_TYPE (result) != AOP_CRY)
6302 /* leave the result in acc */
6306 freeAsmop (result, NULL, ic, TRUE);
6309 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319 /*-----------------------------------------------------------------*/
6320 /* ifxForOp - returns the icode containing the ifx for operand */
6321 /*-----------------------------------------------------------------*/
6323 ifxForOp (operand * op, iCode * ic)
6325 /* if true symbol then needs to be assigned */
6326 if (IS_TRUE_SYMOP (op))
6329 /* if this has register type condition and
6330 the next instruction is ifx with the same operand
6331 and live to of the operand is upto the ifx only then */
6333 ic->next->op == IFX &&
6334 IC_COND (ic->next)->key == op->key &&
6335 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6341 /*-----------------------------------------------------------------*/
6342 /* hasInc - operand is incremented before any other use */
6343 /*-----------------------------------------------------------------*/
6345 hasInc (operand *op, iCode *ic, int osize)
6347 sym_link *type = operandType(op);
6348 sym_link *retype = getSpec (type);
6349 iCode *lic = ic->next;
6352 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6353 if (!IS_SYMOP(op)) return NULL;
6355 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6356 if (IS_AGGREGATE(type->next)) return NULL;
6357 if (osize != (isize = getSize(type->next))) return NULL;
6360 /* if operand of the form op = op + <sizeof *op> */
6361 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6362 isOperandEqual(IC_RESULT(lic),op) &&
6363 isOperandLiteral(IC_RIGHT(lic)) &&
6364 operandLitValue(IC_RIGHT(lic)) == isize) {
6367 /* if the operand used or deffed */
6368 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6371 /* if GOTO or IFX */
6372 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6378 /*-----------------------------------------------------------------*/
6379 /* genAndOp - for && operation */
6380 /*-----------------------------------------------------------------*/
6382 genAndOp (iCode * ic)
6384 operand *left, *right, *result;
6387 D (emitcode (";", "genAndOp"));
6389 /* note here that && operations that are in an
6390 if statement are taken away by backPatchLabels
6391 only those used in arthmetic operations remain */
6392 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6393 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6394 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6396 /* if both are bit variables */
6397 if (AOP_TYPE (left) == AOP_CRY &&
6398 AOP_TYPE (right) == AOP_CRY)
6400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6401 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6406 tlbl = newiTempLabel (NULL);
6408 emitcode ("jz", "%05d$", tlbl->key + 100);
6414 freeAsmop (result, NULL, ic, TRUE);
6415 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 /*-----------------------------------------------------------------*/
6421 /* genOrOp - for || operation */
6422 /*-----------------------------------------------------------------*/
6424 genOrOp (iCode * ic)
6426 operand *left, *right, *result;
6429 D (emitcode (";", "genOrOp"));
6431 /* note here that || operations that are in an
6432 if statement are taken away by backPatchLabels
6433 only those used in arthmetic operations remain */
6434 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6435 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6436 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6438 /* if both are bit variables */
6439 if (AOP_TYPE (left) == AOP_CRY &&
6440 AOP_TYPE (right) == AOP_CRY)
6442 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6443 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6448 tlbl = newiTempLabel (NULL);
6450 emitcode ("jnz", "%05d$", tlbl->key + 100);
6456 freeAsmop (result, NULL, ic, TRUE);
6457 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6461 /*-----------------------------------------------------------------*/
6462 /* isLiteralBit - test if lit == 2^n */
6463 /*-----------------------------------------------------------------*/
6465 isLiteralBit (unsigned long lit)
6467 unsigned long pw[32] =
6468 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6469 0x100L, 0x200L, 0x400L, 0x800L,
6470 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6471 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6472 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6473 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6474 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6477 for (idx = 0; idx < 32; idx++)
6483 /*-----------------------------------------------------------------*/
6484 /* continueIfTrue - */
6485 /*-----------------------------------------------------------------*/
6487 continueIfTrue (iCode * ic)
6490 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6494 /*-----------------------------------------------------------------*/
6496 /*-----------------------------------------------------------------*/
6498 jumpIfTrue (iCode * ic)
6501 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6505 /*-----------------------------------------------------------------*/
6506 /* jmpTrueOrFalse - */
6507 /*-----------------------------------------------------------------*/
6509 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6511 // ugly but optimized by peephole
6514 symbol *nlbl = newiTempLabel (NULL);
6515 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6517 freeForBranchAsmop (result);
6518 freeForBranchAsmop (right);
6519 freeForBranchAsmop (left);
6520 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6525 freeForBranchAsmop (result);
6526 freeForBranchAsmop (right);
6527 freeForBranchAsmop (left);
6528 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6534 /*-----------------------------------------------------------------*/
6535 /* genAnd - code for and */
6536 /*-----------------------------------------------------------------*/
6538 genAnd (iCode * ic, iCode * ifx)
6540 operand *left, *right, *result;
6541 int size, offset = 0;
6542 unsigned long lit = 0L;
6546 D (emitcode (";", "genAnd"));
6548 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6549 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6550 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6553 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6555 AOP_TYPE (left), AOP_TYPE (right));
6556 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6558 AOP_SIZE (left), AOP_SIZE (right));
6561 /* if left is a literal & right is not then exchange them */
6562 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6563 AOP_NEEDSACC (left))
6565 operand *tmp = right;
6570 /* if result = right then exchange left and right */
6571 if (sameRegs (AOP (result), AOP (right)))
6573 operand *tmp = right;
6578 /* if right is bit then exchange them */
6579 if (AOP_TYPE (right) == AOP_CRY &&
6580 AOP_TYPE (left) != AOP_CRY)
6582 operand *tmp = right;
6586 if (AOP_TYPE (right) == AOP_LIT)
6587 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6589 size = AOP_SIZE (result);
6592 // result = bit & yy;
6593 if (AOP_TYPE (left) == AOP_CRY)
6595 // c = bit & literal;
6596 if (AOP_TYPE (right) == AOP_LIT)
6600 if (size && sameRegs (AOP (result), AOP (left)))
6603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6608 if (size && (AOP_TYPE (result) == AOP_CRY))
6610 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6613 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6618 emitcode ("clr", "c");
6623 if (AOP_TYPE (right) == AOP_CRY)
6626 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6627 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6632 MOVA (aopGet (right, 0, FALSE, FALSE));
6634 emitcode ("rrc", "a");
6635 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6643 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6644 genIfxJump (ifx, "c", left, right, result);
6648 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6649 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6650 if ((AOP_TYPE (right) == AOP_LIT) &&
6651 (AOP_TYPE (result) == AOP_CRY) &&
6652 (AOP_TYPE (left) != AOP_CRY))
6654 int posbit = isLiteralBit (lit);
6659 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6663 switch (posbit & 0x07)
6665 case 0: emitcode ("rrc", "a");
6667 case 7: emitcode ("rlc", "a");
6669 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6678 SNPRINTF (buffer, sizeof(buffer),
6679 "acc.%d", posbit & 0x07);
6680 genIfxJump (ifx, buffer, left, right, result);
6683 {// what is this case? just found it in ds390/gen.c
6684 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6691 symbol *tlbl = newiTempLabel (NULL);
6692 int sizel = AOP_SIZE (left);
6694 emitcode ("setb", "c");
6697 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6699 MOVA (aopGet (left, offset, FALSE, FALSE));
6701 if ((posbit = isLiteralBit (bytelit)) != 0)
6702 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6705 if (bytelit != 0x0FFL)
6706 emitcode ("anl", "a,%s",
6707 aopGet (right, offset, FALSE, TRUE));
6708 emitcode ("jnz", "%05d$", tlbl->key + 100);
6713 // bit = left & literal
6716 emitcode ("clr", "c");
6719 // if(left & literal)
6723 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6733 /* if left is same as result */
6734 if (sameRegs (AOP (result), AOP (left)))
6736 for (; size--; offset++)
6738 if (AOP_TYPE (right) == AOP_LIT)
6740 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6741 if (bytelit == 0x0FF)
6743 /* dummy read of volatile operand */
6744 if (isOperandVolatile (left, FALSE))
6745 MOVA (aopGet (left, offset, FALSE, FALSE));
6749 else if (bytelit == 0)
6751 aopPut (result, zero, offset);
6753 else if (IS_AOP_PREG (result))
6755 MOVA (aopGet (left, offset, FALSE, TRUE));
6756 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6757 aopPut (result, "a", offset);
6760 emitcode ("anl", "%s,%s",
6761 aopGet (left, offset, FALSE, TRUE),
6762 aopGet (right, offset, FALSE, FALSE));
6766 if (AOP_TYPE (left) == AOP_ACC)
6769 emitcode("mov", "a,b");
6770 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6774 MOVB (aopGet (left, offset, FALSE, FALSE));
6775 MOVA (aopGet (right, offset, FALSE, FALSE));
6776 emitcode ("anl", "a,b");
6777 aopPut (result, "a", offset);
6779 else if (aopGetUsesAcc (left, offset))
6781 MOVA (aopGet (left, offset, FALSE, FALSE));
6782 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6783 aopPut (result, "a", offset);
6787 MOVA (aopGet (right, offset, FALSE, FALSE));
6788 if (IS_AOP_PREG (result))
6790 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6791 aopPut (result, "a", offset);
6794 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6801 // left & result in different registers
6802 if (AOP_TYPE (result) == AOP_CRY)
6805 // if(size), result in bit
6806 // if(!size && ifx), conditional oper: if(left & right)
6807 symbol *tlbl = newiTempLabel (NULL);
6808 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6810 emitcode ("setb", "c");
6813 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6814 && AOP_TYPE(left)==AOP_ACC)
6817 emitcode("mov", "a,b");
6818 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6820 else if (AOP_TYPE(left)==AOP_ACC)
6824 bool pushedB = pushB ();
6825 emitcode("mov", "b,a");
6826 MOVA (aopGet (right, offset, FALSE, FALSE));
6827 emitcode("anl", "a,b");
6832 MOVA (aopGet (right, offset, FALSE, FALSE));
6833 emitcode("anl", "a,b");
6836 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6838 MOVB (aopGet (left, offset, FALSE, FALSE));
6839 MOVA (aopGet (right, offset, FALSE, FALSE));
6840 emitcode ("anl", "a,b");
6842 else if (aopGetUsesAcc (left, offset))
6844 MOVA (aopGet (left, offset, FALSE, FALSE));
6845 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6849 MOVA (aopGet (right, offset, FALSE, FALSE));
6850 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6853 emitcode ("jnz", "%05d$", tlbl->key + 100);
6863 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6869 for (; (size--); offset++)
6872 // result = left & right
6873 if (AOP_TYPE (right) == AOP_LIT)
6875 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6876 if (bytelit == 0x0FF)
6879 aopGet (left, offset, FALSE, FALSE),
6883 else if (bytelit == 0)
6885 /* dummy read of volatile operand */
6886 if (isOperandVolatile (left, FALSE))
6887 MOVA (aopGet (left, offset, FALSE, FALSE));
6888 aopPut (result, zero, offset);
6891 else if (AOP_TYPE (left) == AOP_ACC)
6895 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6896 aopPut (result, "a", offset);
6901 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6902 aopPut (result, "b", offset);
6907 // faster than result <- left, anl result,right
6908 // and better if result is SFR
6909 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6910 && AOP_TYPE(left)==AOP_ACC)
6913 emitcode("mov", "a,b");
6914 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6916 else if (AOP_TYPE(left)==AOP_ACC)
6920 bool pushedB = pushB ();
6921 emitcode("mov", "b,a");
6922 MOVA (aopGet (right, offset, FALSE, FALSE));
6923 emitcode("anl", "a,b");
6928 MOVA (aopGet (right, offset, FALSE, FALSE));
6929 emitcode("anl", "a,b");
6932 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6934 MOVB (aopGet (left, offset, FALSE, FALSE));
6935 MOVA (aopGet (right, offset, FALSE, FALSE));
6936 emitcode ("anl", "a,b");
6938 else if (aopGetUsesAcc (left, offset))
6940 MOVA (aopGet (left, offset, FALSE, FALSE));
6941 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6945 MOVA (aopGet (right, offset, FALSE, FALSE));
6946 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6948 aopPut (result, "a", offset);
6954 freeAsmop (result, NULL, ic, TRUE);
6955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6956 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6959 /*-----------------------------------------------------------------*/
6960 /* genOr - code for or */
6961 /*-----------------------------------------------------------------*/
6963 genOr (iCode * ic, iCode * ifx)
6965 operand *left, *right, *result;
6966 int size, offset = 0;
6967 unsigned long lit = 0L;
6970 D (emitcode (";", "genOr"));
6972 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6973 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6974 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6977 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6979 AOP_TYPE (left), AOP_TYPE (right));
6980 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6982 AOP_SIZE (left), AOP_SIZE (right));
6985 /* if left is a literal & right is not then exchange them */
6986 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6987 AOP_NEEDSACC (left))
6989 operand *tmp = right;
6994 /* if result = right then exchange them */
6995 if (sameRegs (AOP (result), AOP (right)))
6997 operand *tmp = right;
7002 /* if right is bit then exchange them */
7003 if (AOP_TYPE (right) == AOP_CRY &&
7004 AOP_TYPE (left) != AOP_CRY)
7006 operand *tmp = right;
7010 if (AOP_TYPE (right) == AOP_LIT)
7011 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7013 size = AOP_SIZE (result);
7017 if (AOP_TYPE (left) == AOP_CRY)
7019 if (AOP_TYPE (right) == AOP_LIT)
7021 // c = bit | literal;
7024 // lit != 0 => result = 1
7025 if (AOP_TYPE (result) == AOP_CRY)
7028 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7030 continueIfTrue (ifx);
7033 emitcode ("setb", "c");
7037 // lit == 0 => result = left
7038 if (size && sameRegs (AOP (result), AOP (left)))
7040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7045 if (AOP_TYPE (right) == AOP_CRY)
7048 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7049 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7054 symbol *tlbl = newiTempLabel (NULL);
7055 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7056 emitcode ("setb", "c");
7057 emitcode ("jb", "%s,%05d$",
7058 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7060 emitcode ("jnz", "%05d$", tlbl->key + 100);
7061 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7063 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7078 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7079 genIfxJump (ifx, "c", left, right, result);
7083 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7084 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7085 if ((AOP_TYPE (right) == AOP_LIT) &&
7086 (AOP_TYPE (result) == AOP_CRY) &&
7087 (AOP_TYPE (left) != AOP_CRY))
7093 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7095 continueIfTrue (ifx);
7100 // lit = 0, result = boolean(left)
7102 emitcode ("setb", "c");
7106 symbol *tlbl = newiTempLabel (NULL);
7107 emitcode ("jnz", "%05d$", tlbl->key + 100);
7113 genIfxJump (ifx, "a", left, right, result);
7121 /* if left is same as result */
7122 if (sameRegs (AOP (result), AOP (left)))
7124 for (; size--; offset++)
7126 if (AOP_TYPE (right) == AOP_LIT)
7128 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7131 /* dummy read of volatile operand */
7132 if (isOperandVolatile (left, FALSE))
7133 MOVA (aopGet (left, offset, FALSE, FALSE));
7137 else if (bytelit == 0x0FF)
7139 aopPut (result, "#0xFF", offset);
7141 else if (IS_AOP_PREG (left))
7143 MOVA (aopGet (left, offset, FALSE, TRUE));
7144 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7145 aopPut (result, "a", offset);
7149 emitcode ("orl", "%s,%s",
7150 aopGet (left, offset, FALSE, TRUE),
7151 aopGet (right, offset, FALSE, FALSE));
7156 if (AOP_TYPE (left) == AOP_ACC)
7159 emitcode("mov", "a,b");
7160 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7162 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7164 MOVB (aopGet (left, offset, FALSE, FALSE));
7165 MOVA (aopGet (right, offset, FALSE, FALSE));
7166 emitcode ("orl", "a,b");
7167 aopPut (result, "a", offset);
7169 else if (aopGetUsesAcc (left, offset))
7171 MOVA (aopGet (left, offset, FALSE, FALSE));
7172 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7173 aopPut (result, "a", offset);
7177 MOVA (aopGet (right, offset, FALSE, FALSE));
7178 if (IS_AOP_PREG (left))
7180 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7181 aopPut (result, "a", offset);
7185 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7193 // left & result in different registers
7194 if (AOP_TYPE (result) == AOP_CRY)
7197 // if(size), result in bit
7198 // if(!size && ifx), conditional oper: if(left | right)
7199 symbol *tlbl = newiTempLabel (NULL);
7200 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7202 emitcode ("setb", "c");
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));
7245 emitcode ("jnz", "%05d$", tlbl->key + 100);
7255 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7261 for (; (size--); offset++)
7264 // result = left | right
7265 if (AOP_TYPE (right) == AOP_LIT)
7267 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7271 aopGet (left, offset, FALSE, FALSE),
7275 else if (bytelit == 0x0FF)
7277 /* dummy read of volatile operand */
7278 if (isOperandVolatile (left, FALSE))
7279 MOVA (aopGet (left, offset, FALSE, FALSE));
7280 aopPut (result, "#0xFF", offset);
7284 // faster than result <- left, orl result,right
7285 // and better if result is SFR
7286 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7287 && AOP_TYPE(left)==AOP_ACC)
7290 emitcode("mov", "a,b");
7291 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7293 else if (AOP_TYPE(left)==AOP_ACC)
7297 bool pushedB = pushB ();
7298 emitcode("mov", "b,a");
7299 MOVA (aopGet (right, offset, FALSE, FALSE));
7300 emitcode("orl", "a,b");
7305 MOVA (aopGet (right, offset, FALSE, FALSE));
7306 emitcode("orl", "a,b");
7309 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7311 MOVB (aopGet (left, offset, FALSE, FALSE));
7312 MOVA (aopGet (right, offset, FALSE, FALSE));
7313 emitcode ("orl", "a,b");
7315 else if (aopGetUsesAcc (left, offset))
7317 MOVA (aopGet (left, offset, FALSE, FALSE));
7318 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7322 MOVA (aopGet (right, offset, FALSE, FALSE));
7323 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7325 aopPut (result, "a", offset);
7331 freeAsmop (result, NULL, ic, TRUE);
7332 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7333 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7336 /*-----------------------------------------------------------------*/
7337 /* genXor - code for xclusive or */
7338 /*-----------------------------------------------------------------*/
7340 genXor (iCode * ic, iCode * ifx)
7342 operand *left, *right, *result;
7343 int size, offset = 0;
7344 unsigned long lit = 0L;
7347 D (emitcode (";", "genXor"));
7349 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7350 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7351 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7354 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7356 AOP_TYPE (left), AOP_TYPE (right));
7357 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7359 AOP_SIZE (left), AOP_SIZE (right));
7362 /* if left is a literal & right is not ||
7363 if left needs acc & right does not */
7364 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7365 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7367 operand *tmp = right;
7372 /* if result = right then exchange them */
7373 if (sameRegs (AOP (result), AOP (right)))
7375 operand *tmp = right;
7380 /* if right is bit then exchange them */
7381 if (AOP_TYPE (right) == AOP_CRY &&
7382 AOP_TYPE (left) != AOP_CRY)
7384 operand *tmp = right;
7388 if (AOP_TYPE (right) == AOP_LIT)
7389 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7391 size = AOP_SIZE (result);
7395 if (AOP_TYPE (left) == AOP_CRY)
7397 if (AOP_TYPE (right) == AOP_LIT)
7399 // c = bit & literal;
7402 // lit>>1 != 0 => result = 1
7403 if (AOP_TYPE (result) == AOP_CRY)
7406 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7408 continueIfTrue (ifx);
7411 emitcode ("setb", "c");
7418 // lit == 0, result = left
7419 if (size && sameRegs (AOP (result), AOP (left)))
7421 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7425 // lit == 1, result = not(left)
7426 if (size && sameRegs (AOP (result), AOP (left)))
7428 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7433 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7434 emitcode ("cpl", "c");
7442 symbol *tlbl = newiTempLabel (NULL);
7443 if (AOP_TYPE (right) == AOP_CRY)
7446 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7450 int sizer = AOP_SIZE (right);
7452 // if val>>1 != 0, result = 1
7453 emitcode ("setb", "c");
7456 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7458 // test the msb of the lsb
7459 emitcode ("anl", "a,#0xfe");
7460 emitcode ("jnz", "%05d$", tlbl->key + 100);
7464 emitcode ("rrc", "a");
7466 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7467 emitcode ("cpl", "c");
7475 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7476 genIfxJump (ifx, "c", left, right, result);
7480 /* if left is same as result */
7481 if (sameRegs (AOP (result), AOP (left)))
7483 for (; size--; offset++)
7485 if (AOP_TYPE (right) == AOP_LIT)
7487 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7490 /* dummy read of volatile operand */
7491 if (isOperandVolatile (left, FALSE))
7492 MOVA (aopGet (left, offset, FALSE, FALSE));
7496 else if (IS_AOP_PREG (left))
7498 MOVA (aopGet (left, offset, FALSE, TRUE));
7499 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7500 aopPut (result, "a", offset);
7504 emitcode ("xrl", "%s,%s",
7505 aopGet (left, offset, FALSE, TRUE),
7506 aopGet (right, offset, FALSE, FALSE));
7511 if (AOP_TYPE (left) == AOP_ACC)
7514 emitcode("mov", "a,b");
7515 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7517 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7519 MOVB (aopGet (left, offset, FALSE, FALSE));
7520 MOVA (aopGet (right, offset, FALSE, FALSE));
7521 emitcode ("xrl", "a,b");
7522 aopPut (result, "a", offset);
7524 else if (aopGetUsesAcc (left, offset))
7526 MOVA (aopGet (left, offset, FALSE, FALSE));
7527 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7528 aopPut (result, "a", offset);
7532 MOVA (aopGet (right, offset, FALSE, FALSE));
7533 if (IS_AOP_PREG (left))
7535 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7536 aopPut (result, "a", offset);
7539 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7546 // left & result in different registers
7547 if (AOP_TYPE (result) == AOP_CRY)
7550 // if(size), result in bit
7551 // if(!size && ifx), conditional oper: if(left ^ right)
7552 symbol *tlbl = newiTempLabel (NULL);
7553 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7556 emitcode ("setb", "c");
7559 if ((AOP_TYPE (right) == AOP_LIT) &&
7560 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7562 MOVA (aopGet (left, offset, FALSE, FALSE));
7564 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7565 && AOP_TYPE(left)==AOP_ACC)
7568 emitcode("mov", "a,b");
7569 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7571 else if (AOP_TYPE(left)==AOP_ACC)
7575 bool pushedB = pushB ();
7576 emitcode("mov", "b,a");
7577 MOVA (aopGet (right, offset, FALSE, FALSE));
7578 emitcode("xrl", "a,b");
7583 MOVA (aopGet (right, offset, FALSE, FALSE));
7584 emitcode("xrl", "a,b");
7587 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7589 MOVB (aopGet (left, offset, FALSE, FALSE));
7590 MOVA (aopGet (right, offset, FALSE, FALSE));
7591 emitcode ("xrl", "a,b");
7593 else if (aopGetUsesAcc (left, offset))
7595 MOVA (aopGet (left, offset, FALSE, FALSE));
7596 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7600 MOVA (aopGet (right, offset, FALSE, FALSE));
7601 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7604 emitcode ("jnz", "%05d$", tlbl->key + 100);
7614 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7618 for (; (size--); offset++)
7621 // result = left ^ right
7622 if (AOP_TYPE (right) == AOP_LIT)
7624 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7628 aopGet (left, offset, FALSE, FALSE),
7633 // faster than result <- left, xrl result,right
7634 // and better if result is SFR
7635 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7636 && AOP_TYPE(left)==AOP_ACC)
7639 emitcode("mov", "a,b");
7640 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7642 else if (AOP_TYPE(left)==AOP_ACC)
7646 bool pushedB = pushB ();
7647 emitcode("mov", "b,a");
7648 MOVA (aopGet (right, offset, FALSE, FALSE));
7649 emitcode("xrl", "a,b");
7654 MOVA (aopGet (right, offset, FALSE, FALSE));
7655 emitcode("xrl", "a,b");
7658 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7660 MOVB (aopGet (left, offset, FALSE, FALSE));
7661 MOVA (aopGet (right, offset, FALSE, FALSE));
7662 emitcode ("xrl", "a,b");
7664 else if (aopGetUsesAcc (left, offset))
7666 MOVA (aopGet (left, offset, FALSE, FALSE));
7667 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7671 MOVA (aopGet (right, offset, FALSE, FALSE));
7672 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7674 aopPut (result, "a", offset);
7680 freeAsmop (result, NULL, ic, TRUE);
7681 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7682 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7685 /*-----------------------------------------------------------------*/
7686 /* genInline - write the inline code out */
7687 /*-----------------------------------------------------------------*/
7689 genInline (iCode * ic)
7691 char *buffer, *bp, *bp1;
7693 D (emitcode (";", "genInline"));
7695 _G.inLine += (!options.asmpeep);
7697 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7699 /* emit each line as a code */
7710 /* Add \n for labels, not dirs such as c:\mydir */
7711 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7725 /* emitcode("",buffer); */
7726 _G.inLine -= (!options.asmpeep);
7729 /*-----------------------------------------------------------------*/
7730 /* genRRC - rotate right with carry */
7731 /*-----------------------------------------------------------------*/
7735 operand *left, *result;
7739 D (emitcode (";", "genRRC"));
7741 /* rotate right with carry */
7742 left = IC_LEFT (ic);
7743 result = IC_RESULT (ic);
7744 aopOp (left, ic, FALSE);
7745 aopOp (result, ic, FALSE);
7747 /* move it to the result */
7748 size = AOP_SIZE (result);
7750 if (size == 1) { /* special case for 1 byte */
7751 l = aopGet (left, offset, FALSE, FALSE);
7753 emitcode ("rr", "a");
7756 /* no need to clear carry, bit7 will be written later */
7759 l = aopGet (left, offset, FALSE, FALSE);
7761 emitcode ("rrc", "a");
7762 if (AOP_SIZE (result) > 1)
7763 aopPut (result, "a", offset--);
7765 /* now we need to put the carry into the
7766 highest order byte of the result */
7767 if (AOP_SIZE (result) > 1)
7769 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7772 emitcode ("mov", "acc.7,c");
7774 aopPut (result, "a", AOP_SIZE (result) - 1);
7775 freeAsmop (result, NULL, ic, TRUE);
7776 freeAsmop (left, NULL, ic, TRUE);
7779 /*-----------------------------------------------------------------*/
7780 /* genRLC - generate code for rotate left with carry */
7781 /*-----------------------------------------------------------------*/
7785 operand *left, *result;
7789 D (emitcode (";", "genRLC"));
7791 /* rotate right with carry */
7792 left = IC_LEFT (ic);
7793 result = IC_RESULT (ic);
7794 aopOp (left, ic, FALSE);
7795 aopOp (result, ic, FALSE);
7797 /* move it to the result */
7798 size = AOP_SIZE (result);
7802 l = aopGet (left, offset, FALSE, FALSE);
7804 if (size == 0) { /* special case for 1 byte */
7808 emitcode("rlc","a"); /* bit0 will be written later */
7809 if (AOP_SIZE (result) > 1)
7811 aopPut (result, "a", offset++);
7816 l = aopGet (left, offset, FALSE, FALSE);
7818 emitcode ("rlc", "a");
7819 if (AOP_SIZE (result) > 1)
7820 aopPut (result, "a", offset++);
7823 /* now we need to put the carry into the
7824 highest order byte of the result */
7825 if (AOP_SIZE (result) > 1)
7827 l = aopGet (result, 0, FALSE, FALSE);
7830 emitcode ("mov", "acc.0,c");
7832 aopPut (result, "a", 0);
7833 freeAsmop (result, NULL, ic, TRUE);
7834 freeAsmop (left, NULL, ic, TRUE);
7837 /*-----------------------------------------------------------------*/
7838 /* genGetHbit - generates code get highest order bit */
7839 /*-----------------------------------------------------------------*/
7841 genGetHbit (iCode * ic)
7843 operand *left, *result;
7845 D (emitcode (";", "genGetHbit"));
7847 left = IC_LEFT (ic);
7848 result = IC_RESULT (ic);
7849 aopOp (left, ic, FALSE);
7850 aopOp (result, ic, FALSE);
7852 /* get the highest order byte into a */
7853 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7854 if (AOP_TYPE (result) == AOP_CRY)
7856 emitcode ("rlc", "a");
7861 emitcode ("rl", "a");
7862 emitcode ("anl", "a,#0x01");
7866 freeAsmop (result, NULL, ic, TRUE);
7867 freeAsmop (left, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genGetAbit - generates code get a single bit */
7872 /*-----------------------------------------------------------------*/
7874 genGetAbit (iCode * ic)
7876 operand *left, *right, *result;
7879 D (emitcode (";", "genGetAbit"));
7881 left = IC_LEFT (ic);
7882 right = IC_RIGHT (ic);
7883 result = IC_RESULT (ic);
7884 aopOp (left, ic, FALSE);
7885 aopOp (right, ic, FALSE);
7886 aopOp (result, ic, FALSE);
7888 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7890 /* get the needed byte into a */
7891 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7893 if (AOP_TYPE (result) == AOP_CRY)
7896 emitcode ("rlc", "a");
7897 else if ((shCount) == 0)
7898 emitcode ("rrc", "a");
7900 emitcode ("mov", "c,acc[%d]", shCount);
7908 emitcode ("rr", "a");
7911 emitcode ("rr", "a");
7914 emitcode ("anl", "a,#0x01");
7918 emitcode ("mov", "c,acc[%d]", shCount);
7919 emitcode ("clr", "a");
7920 emitcode ("rlc", "a");
7923 emitcode ("swap", "a");
7924 emitcode ("anl", "a,#0x01");
7927 emitcode ("rl", "a");
7930 emitcode ("rl", "a");
7931 emitcode ("anl", "a,#0x01");
7937 freeAsmop (result, NULL, ic, TRUE);
7938 freeAsmop (right, NULL, ic, TRUE);
7939 freeAsmop (left, NULL, ic, TRUE);
7942 /*-----------------------------------------------------------------*/
7943 /* genGetByte - generates code get a single byte */
7944 /*-----------------------------------------------------------------*/
7946 genGetByte (iCode * ic)
7948 operand *left, *right, *result;
7951 D (emitcode (";", "genGetByte"));
7953 left = IC_LEFT (ic);
7954 right = IC_RIGHT (ic);
7955 result = IC_RESULT (ic);
7956 aopOp (left, ic, FALSE);
7957 aopOp (right, ic, FALSE);
7958 aopOp (result, ic, FALSE);
7960 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7962 aopGet (left, offset, FALSE, FALSE),
7965 freeAsmop (result, NULL, ic, TRUE);
7966 freeAsmop (right, NULL, ic, TRUE);
7967 freeAsmop (left, NULL, ic, TRUE);
7970 /*-----------------------------------------------------------------*/
7971 /* genGetWord - generates code get two bytes */
7972 /*-----------------------------------------------------------------*/
7974 genGetWord (iCode * ic)
7976 operand *left, *right, *result;
7979 D (emitcode (";", "genGetWord"));
7981 left = IC_LEFT (ic);
7982 right = IC_RIGHT (ic);
7983 result = IC_RESULT (ic);
7984 aopOp (left, ic, FALSE);
7985 aopOp (right, ic, FALSE);
7986 aopOp (result, ic, FALSE);
7988 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7990 aopGet (left, offset, FALSE, FALSE),
7993 aopGet (left, offset+1, FALSE, FALSE),
7996 freeAsmop (result, NULL, ic, TRUE);
7997 freeAsmop (right, NULL, ic, TRUE);
7998 freeAsmop (left, NULL, ic, TRUE);
8001 /*-----------------------------------------------------------------*/
8002 /* genSwap - generates code to swap nibbles or bytes */
8003 /*-----------------------------------------------------------------*/
8005 genSwap (iCode * ic)
8007 operand *left, *result;
8009 D(emitcode ("; genSwap",""));
8011 left = IC_LEFT (ic);
8012 result = IC_RESULT (ic);
8013 aopOp (left, ic, FALSE);
8014 aopOp (result, ic, FALSE);
8016 switch (AOP_SIZE (left))
8018 case 1: /* swap nibbles in byte */
8019 MOVA (aopGet (left, 0, FALSE, FALSE));
8020 emitcode ("swap", "a");
8021 aopPut (result, "a", 0);
8023 case 2: /* swap bytes in word */
8024 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8026 MOVA (aopGet (left, 0, FALSE, FALSE));
8027 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8028 aopPut (result, "a", 1);
8030 else if (operandsEqu (left, result))
8033 bool pushedB = FALSE, leftInB = FALSE;
8035 MOVA (aopGet (left, 0, FALSE, FALSE));
8036 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8039 emitcode ("mov", "b,a");
8043 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8044 aopPut (result, reg, 1);
8051 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8052 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8056 wassertl(FALSE, "unsupported SWAP operand size");
8059 freeAsmop (result, NULL, ic, TRUE);
8060 freeAsmop (left, NULL, ic, TRUE);
8063 /*-----------------------------------------------------------------*/
8064 /* AccRol - rotate left accumulator by known count */
8065 /*-----------------------------------------------------------------*/
8067 AccRol (int shCount)
8069 shCount &= 0x0007; // shCount : 0..7
8076 emitcode ("rl", "a");
8079 emitcode ("rl", "a");
8080 emitcode ("rl", "a");
8083 emitcode ("swap", "a");
8084 emitcode ("rr", "a");
8087 emitcode ("swap", "a");
8090 emitcode ("swap", "a");
8091 emitcode ("rl", "a");
8094 emitcode ("rr", "a");
8095 emitcode ("rr", "a");
8098 emitcode ("rr", "a");
8103 /*-----------------------------------------------------------------*/
8104 /* AccLsh - left shift accumulator by known count */
8105 /*-----------------------------------------------------------------*/
8107 AccLsh (int shCount)
8112 emitcode ("add", "a,acc");
8113 else if (shCount == 2)
8115 emitcode ("add", "a,acc");
8116 emitcode ("add", "a,acc");
8120 /* rotate left accumulator */
8122 /* and kill the lower order bits */
8123 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8128 /*-----------------------------------------------------------------*/
8129 /* AccRsh - right shift accumulator by known count */
8130 /*-----------------------------------------------------------------*/
8132 AccRsh (int shCount)
8139 emitcode ("rrc", "a");
8143 /* rotate right accumulator */
8144 AccRol (8 - shCount);
8145 /* and kill the higher order bits */
8146 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8151 /*-----------------------------------------------------------------*/
8152 /* AccSRsh - signed right shift accumulator by known count */
8153 /*-----------------------------------------------------------------*/
8155 AccSRsh (int shCount)
8162 emitcode ("mov", "c,acc.7");
8163 emitcode ("rrc", "a");
8165 else if (shCount == 2)
8167 emitcode ("mov", "c,acc.7");
8168 emitcode ("rrc", "a");
8169 emitcode ("mov", "c,acc.7");
8170 emitcode ("rrc", "a");
8174 tlbl = newiTempLabel (NULL);
8175 /* rotate right accumulator */
8176 AccRol (8 - shCount);
8177 /* and kill the higher order bits */
8178 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8179 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8180 emitcode ("orl", "a,#0x%02x",
8181 (unsigned char) ~SRMask[shCount]);
8187 /*-----------------------------------------------------------------*/
8188 /* shiftR1Left2Result - shift right one byte from left to result */
8189 /*-----------------------------------------------------------------*/
8191 shiftR1Left2Result (operand * left, int offl,
8192 operand * result, int offr,
8193 int shCount, int sign)
8195 MOVA (aopGet (left, offl, FALSE, FALSE));
8196 /* shift right accumulator */
8201 aopPut (result, "a", offr);
8204 /*-----------------------------------------------------------------*/
8205 /* shiftL1Left2Result - shift left one byte from left to result */
8206 /*-----------------------------------------------------------------*/
8208 shiftL1Left2Result (operand * left, int offl,
8209 operand * result, int offr, int shCount)
8212 l = aopGet (left, offl, FALSE, FALSE);
8214 /* shift left accumulator */
8216 aopPut (result, "a", offr);
8219 /*-----------------------------------------------------------------*/
8220 /* movLeft2Result - move byte from left to result */
8221 /*-----------------------------------------------------------------*/
8223 movLeft2Result (operand * left, int offl,
8224 operand * result, int offr, int sign)
8227 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8229 l = aopGet (left, offl, FALSE, FALSE);
8231 if (*l == '@' && (IS_AOP_PREG (result)))
8233 emitcode ("mov", "a,%s", l);
8234 aopPut (result, "a", offr);
8240 aopPut (result, l, offr);
8244 /* MSB sign in acc.7 ! */
8245 if (getDataSize (left) == offl + 1)
8248 aopPut (result, "a", offr);
8255 /*-----------------------------------------------------------------*/
8256 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8257 /*-----------------------------------------------------------------*/
8261 emitcode ("rrc", "a");
8262 emitcode ("xch", "a,%s", x);
8263 emitcode ("rrc", "a");
8264 emitcode ("xch", "a,%s", x);
8267 /*-----------------------------------------------------------------*/
8268 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8269 /*-----------------------------------------------------------------*/
8273 emitcode ("xch", "a,%s", x);
8274 emitcode ("rlc", "a");
8275 emitcode ("xch", "a,%s", x);
8276 emitcode ("rlc", "a");
8279 /*-----------------------------------------------------------------*/
8280 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8281 /*-----------------------------------------------------------------*/
8285 emitcode ("xch", "a,%s", x);
8286 emitcode ("add", "a,acc");
8287 emitcode ("xch", "a,%s", x);
8288 emitcode ("rlc", "a");
8291 /*-----------------------------------------------------------------*/
8292 /* AccAXLsh - left shift a:x by known count (0..7) */
8293 /*-----------------------------------------------------------------*/
8295 AccAXLsh (char *x, int shCount)
8310 case 5: // AAAAABBB:CCCCCDDD
8312 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8314 emitcode ("anl", "a,#0x%02x",
8315 SLMask[shCount]); // BBB00000:CCCCCDDD
8317 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8319 AccRol (shCount); // DDDCCCCC:BBB00000
8321 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8323 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8325 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8327 emitcode ("anl", "a,#0x%02x",
8328 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8330 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8332 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8335 case 6: // AAAAAABB:CCCCCCDD
8336 emitcode ("anl", "a,#0x%02x",
8337 SRMask[shCount]); // 000000BB:CCCCCCDD
8338 emitcode ("mov", "c,acc.0"); // c = B
8339 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8341 AccAXRrl1 (x); // BCCCCCCD:D000000B
8342 AccAXRrl1 (x); // BBCCCCCC:DD000000
8344 emitcode("rrc","a");
8345 emitcode("xch","a,%s", x);
8346 emitcode("rrc","a");
8347 emitcode("mov","c,acc.0"); //<< get correct bit
8348 emitcode("xch","a,%s", x);
8350 emitcode("rrc","a");
8351 emitcode("xch","a,%s", x);
8352 emitcode("rrc","a");
8353 emitcode("xch","a,%s", x);
8356 case 7: // a:x <<= 7
8358 emitcode ("anl", "a,#0x%02x",
8359 SRMask[shCount]); // 0000000B:CCCCCCCD
8361 emitcode ("mov", "c,acc.0"); // c = B
8363 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8365 AccAXRrl1 (x); // BCCCCCCC:D0000000
8373 /*-----------------------------------------------------------------*/
8374 /* AccAXRsh - right shift a:x known count (0..7) */
8375 /*-----------------------------------------------------------------*/
8377 AccAXRsh (char *x, int shCount)
8385 AccAXRrl1 (x); // 0->a:x
8390 AccAXRrl1 (x); // 0->a:x
8393 AccAXRrl1 (x); // 0->a:x
8398 case 5: // AAAAABBB:CCCCCDDD = a:x
8400 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8402 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8404 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8406 emitcode ("anl", "a,#0x%02x",
8407 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8409 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8411 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8413 emitcode ("anl", "a,#0x%02x",
8414 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8416 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8418 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8420 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8423 case 6: // AABBBBBB:CCDDDDDD
8425 emitcode ("mov", "c,acc.7");
8426 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8428 emitcode ("mov", "c,acc.7");
8429 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8431 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8433 emitcode ("anl", "a,#0x%02x",
8434 SRMask[shCount]); // 000000AA:BBBBBBCC
8437 case 7: // ABBBBBBB:CDDDDDDD
8439 emitcode ("mov", "c,acc.7"); // c = A
8441 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8443 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8445 emitcode ("anl", "a,#0x%02x",
8446 SRMask[shCount]); // 0000000A:BBBBBBBC
8454 /*-----------------------------------------------------------------*/
8455 /* AccAXRshS - right shift signed a:x known count (0..7) */
8456 /*-----------------------------------------------------------------*/
8458 AccAXRshS (char *x, int shCount)
8466 emitcode ("mov", "c,acc.7");
8467 AccAXRrl1 (x); // s->a:x
8471 emitcode ("mov", "c,acc.7");
8472 AccAXRrl1 (x); // s->a:x
8474 emitcode ("mov", "c,acc.7");
8475 AccAXRrl1 (x); // s->a:x
8480 case 5: // AAAAABBB:CCCCCDDD = a:x
8482 tlbl = newiTempLabel (NULL);
8483 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8485 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8487 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8489 emitcode ("anl", "a,#0x%02x",
8490 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8492 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8494 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8496 emitcode ("anl", "a,#0x%02x",
8497 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8499 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8501 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8503 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8505 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8506 emitcode ("orl", "a,#0x%02x",
8507 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8510 break; // SSSSAAAA:BBBCCCCC
8512 case 6: // AABBBBBB:CCDDDDDD
8514 tlbl = newiTempLabel (NULL);
8515 emitcode ("mov", "c,acc.7");
8516 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8518 emitcode ("mov", "c,acc.7");
8519 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8521 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8523 emitcode ("anl", "a,#0x%02x",
8524 SRMask[shCount]); // 000000AA:BBBBBBCC
8526 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8527 emitcode ("orl", "a,#0x%02x",
8528 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8532 case 7: // ABBBBBBB:CDDDDDDD
8534 tlbl = newiTempLabel (NULL);
8535 emitcode ("mov", "c,acc.7"); // c = A
8537 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8539 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8541 emitcode ("anl", "a,#0x%02x",
8542 SRMask[shCount]); // 0000000A:BBBBBBBC
8544 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8545 emitcode ("orl", "a,#0x%02x",
8546 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8555 /*-----------------------------------------------------------------*/
8556 /* shiftL2Left2Result - shift left two bytes from left to result */
8557 /*-----------------------------------------------------------------*/
8559 shiftL2Left2Result (operand * left, int offl,
8560 operand * result, int offr, int shCount)
8563 bool pushedB = FALSE;
8566 if (sameRegs (AOP (result), AOP (left)) &&
8567 ((offl + MSB16) == offr))
8569 /* don't crash result[offr] */
8570 MOVA (aopGet (left, offl, FALSE, FALSE));
8571 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8572 usedB = !strncmp(x, "b", 1);
8574 else if (aopGetUsesAcc (result, offr))
8576 movLeft2Result (left, offl, result, offr, 0);
8579 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8580 MOVA (aopGet (result, offr, FALSE, FALSE));
8581 emitcode ("xch", "a,b");
8586 movLeft2Result (left, offl, result, offr, 0);
8587 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8588 x = aopGet (result, offr, FALSE, FALSE);
8590 /* ax << shCount (x = lsb(result)) */
8591 AccAXLsh (x, shCount);
8594 emitcode ("xch", "a,b");
8595 aopPut (result, "a", offr);
8596 aopPut (result, "b", offr + MSB16);
8601 aopPut (result, "a", offr + MSB16);
8606 /*-----------------------------------------------------------------*/
8607 /* shiftR2Left2Result - shift right two bytes from left to result */
8608 /*-----------------------------------------------------------------*/
8610 shiftR2Left2Result (operand * left, int offl,
8611 operand * result, int offr,
8612 int shCount, int sign)
8615 bool pushedB = FALSE;
8618 if (sameRegs (AOP (result), AOP (left)) &&
8619 ((offl + MSB16) == offr))
8621 /* don't crash result[offr] */
8622 MOVA (aopGet (left, offl, FALSE, FALSE));
8623 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8624 usedB = !strncmp(x, "b", 1);
8626 else if (aopGetUsesAcc (result, offr))
8628 movLeft2Result (left, offl, result, offr, 0);
8631 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8632 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8637 movLeft2Result (left, offl, result, offr, 0);
8638 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8639 x = aopGet (result, offr, FALSE, FALSE);
8641 /* a:x >> shCount (x = lsb(result)) */
8643 AccAXRshS (x, shCount);
8645 AccAXRsh (x, shCount);
8648 emitcode ("xch", "a,b");
8649 aopPut (result, "a", offr);
8650 emitcode ("xch", "a,b");
8653 if (getDataSize (result) > 1)
8654 aopPut (result, "a", offr + MSB16);
8657 /*-----------------------------------------------------------------*/
8658 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8659 /*-----------------------------------------------------------------*/
8661 shiftLLeftOrResult (operand * left, int offl,
8662 operand * result, int offr, int shCount)
8664 MOVA (aopGet (left, offl, FALSE, FALSE));
8665 /* shift left accumulator */
8667 /* or with result */
8668 if (aopGetUsesAcc (result, offr))
8670 emitcode ("xch", "a,b");
8671 MOVA (aopGet (result, offr, FALSE, FALSE));
8672 emitcode ("orl", "a,b");
8676 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8678 /* back to result */
8679 aopPut (result, "a", offr);
8682 /*-----------------------------------------------------------------*/
8683 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8684 /*-----------------------------------------------------------------*/
8686 shiftRLeftOrResult (operand * left, int offl,
8687 operand * result, int offr, int shCount)
8689 MOVA (aopGet (left, offl, FALSE, FALSE));
8690 /* shift right accumulator */
8692 /* or with result */
8693 if (aopGetUsesAcc(result, offr))
8695 emitcode ("xch", "a,b");
8696 MOVA (aopGet (result, offr, FALSE, FALSE));
8697 emitcode ("orl", "a,b");
8701 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8703 /* back to result */
8704 aopPut (result, "a", offr);
8707 /*-----------------------------------------------------------------*/
8708 /* genlshOne - left shift a one byte quantity by known count */
8709 /*-----------------------------------------------------------------*/
8711 genlshOne (operand * result, operand * left, int shCount)
8713 D (emitcode (";", "genlshOne"));
8715 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8718 /*-----------------------------------------------------------------*/
8719 /* genlshTwo - left shift two bytes by known amount != 0 */
8720 /*-----------------------------------------------------------------*/
8722 genlshTwo (operand * result, operand * left, int shCount)
8726 D (emitcode (";", "genlshTwo"));
8728 size = getDataSize (result);
8730 /* if shCount >= 8 */
8738 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8740 movLeft2Result (left, LSB, result, MSB16, 0);
8742 aopPut (result, zero, LSB);
8745 /* 1 <= shCount <= 7 */
8749 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8751 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8755 /*-----------------------------------------------------------------*/
8756 /* shiftLLong - shift left one long from left to result */
8757 /* offl = LSB or MSB16 */
8758 /*-----------------------------------------------------------------*/
8760 shiftLLong (operand * left, operand * result, int offr)
8763 int size = AOP_SIZE (result);
8765 if (size >= LSB + offr)
8767 l = aopGet (left, LSB, FALSE, FALSE);
8769 emitcode ("add", "a,acc");
8770 if (sameRegs (AOP (left), AOP (result)) &&
8771 size >= MSB16 + offr && offr != LSB)
8772 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8774 aopPut (result, "a", LSB + offr);
8777 if (size >= MSB16 + offr)
8779 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8781 l = aopGet (left, MSB16, FALSE, FALSE);
8784 emitcode ("rlc", "a");
8785 if (sameRegs (AOP (left), AOP (result)) &&
8786 size >= MSB24 + offr && offr != LSB)
8787 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8789 aopPut (result, "a", MSB16 + offr);
8792 if (size >= MSB24 + offr)
8794 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8796 l = aopGet (left, MSB24, FALSE, FALSE);
8799 emitcode ("rlc", "a");
8800 if (sameRegs (AOP (left), AOP (result)) &&
8801 size >= MSB32 + offr && offr != LSB)
8802 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8804 aopPut (result, "a", MSB24 + offr);
8807 if (size > MSB32 + offr)
8809 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8811 l = aopGet (left, MSB32, FALSE, FALSE);
8814 emitcode ("rlc", "a");
8815 aopPut (result, "a", MSB32 + offr);
8818 aopPut (result, zero, LSB);
8821 /*-----------------------------------------------------------------*/
8822 /* genlshFour - shift four byte by a known amount != 0 */
8823 /*-----------------------------------------------------------------*/
8825 genlshFour (operand * result, operand * left, int shCount)
8829 D (emitcode (";", "genlshFour"));
8831 size = AOP_SIZE (result);
8833 /* if shifting more that 3 bytes */
8838 /* lowest order of left goes to the highest
8839 order of the destination */
8840 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8842 movLeft2Result (left, LSB, result, MSB32, 0);
8843 aopPut (result, zero, LSB);
8844 aopPut (result, zero, MSB16);
8845 aopPut (result, zero, MSB24);
8849 /* more than two bytes */
8850 else if (shCount >= 16)
8852 /* lower order two bytes goes to higher order two bytes */
8854 /* if some more remaining */
8856 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8859 movLeft2Result (left, MSB16, result, MSB32, 0);
8860 movLeft2Result (left, LSB, result, MSB24, 0);
8862 aopPut (result, zero, MSB16);
8863 aopPut (result, zero, LSB);
8867 /* if more than 1 byte */
8868 else if (shCount >= 8)
8870 /* lower order three bytes goes to higher order three bytes */
8875 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8877 movLeft2Result (left, LSB, result, MSB16, 0);
8883 movLeft2Result (left, MSB24, result, MSB32, 0);
8884 movLeft2Result (left, MSB16, result, MSB24, 0);
8885 movLeft2Result (left, LSB, result, MSB16, 0);
8886 aopPut (result, zero, LSB);
8888 else if (shCount == 1)
8889 shiftLLong (left, result, MSB16);
8892 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8893 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8894 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8895 aopPut (result, zero, LSB);
8900 /* 1 <= shCount <= 7 */
8901 else if (shCount <= 2)
8903 shiftLLong (left, result, LSB);
8905 shiftLLong (result, result, LSB);
8907 /* 3 <= shCount <= 7, optimize */
8910 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8911 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8912 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8916 /*-----------------------------------------------------------------*/
8917 /* genLeftShiftLiteral - left shifting by known count */
8918 /*-----------------------------------------------------------------*/
8920 genLeftShiftLiteral (operand * left,
8925 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8928 D (emitcode (";", "genLeftShiftLiteral"));
8930 freeAsmop (right, NULL, ic, TRUE);
8932 aopOp (left, ic, FALSE);
8933 aopOp (result, ic, FALSE);
8935 size = getSize (operandType (result));
8938 emitcode ("; shift left ", "result %d, left %d", size,
8942 /* I suppose that the left size >= result size */
8947 movLeft2Result (left, size, result, size, 0);
8950 else if (shCount >= (size * 8))
8954 aopPut (result, zero, size);
8962 genlshOne (result, left, shCount);
8966 genlshTwo (result, left, shCount);
8970 genlshFour (result, left, shCount);
8973 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8974 "*** ack! mystery literal shift!\n");
8978 freeAsmop (result, NULL, ic, TRUE);
8979 freeAsmop (left, NULL, ic, TRUE);
8982 /*-----------------------------------------------------------------*/
8983 /* genLeftShift - generates code for left shifting */
8984 /*-----------------------------------------------------------------*/
8986 genLeftShift (iCode * ic)
8988 operand *left, *right, *result;
8991 symbol *tlbl, *tlbl1;
8994 D (emitcode (";", "genLeftShift"));
8996 right = IC_RIGHT (ic);
8997 left = IC_LEFT (ic);
8998 result = IC_RESULT (ic);
9000 aopOp (right, ic, FALSE);
9002 /* if the shift count is known then do it
9003 as efficiently as possible */
9004 if (AOP_TYPE (right) == AOP_LIT)
9006 genLeftShiftLiteral (left, right, result, ic);
9010 /* shift count is unknown then we have to form
9011 a loop get the loop count in B : Note: we take
9012 only the lower order byte since shifting
9013 more that 32 bits make no sense anyway, ( the
9014 largest size of an object can be only 32 bits ) */
9017 MOVB (aopGet (right, 0, FALSE, FALSE));
9018 emitcode ("inc", "b");
9019 freeAsmop (right, NULL, ic, TRUE);
9020 aopOp (left, ic, FALSE);
9021 aopOp (result, ic, FALSE);
9023 /* now move the left to the result if they are not the same */
9024 if (!sameRegs (AOP (left), AOP (result)) &&
9025 AOP_SIZE (result) > 1)
9028 size = AOP_SIZE (result);
9032 l = aopGet (left, offset, FALSE, TRUE);
9033 if (*l == '@' && (IS_AOP_PREG (result)))
9036 emitcode ("mov", "a,%s", l);
9037 aopPut (result, "a", offset);
9040 aopPut (result, l, offset);
9045 tlbl = newiTempLabel (NULL);
9046 size = AOP_SIZE (result);
9048 tlbl1 = newiTempLabel (NULL);
9050 /* if it is only one byte then */
9053 symbol *tlbl1 = newiTempLabel (NULL);
9055 l = aopGet (left, 0, FALSE, FALSE);
9057 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9059 emitcode ("add", "a,acc");
9061 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9063 aopPut (result, "a", 0);
9067 reAdjustPreg (AOP (result));
9069 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9071 l = aopGet (result, offset, FALSE, FALSE);
9073 emitcode ("add", "a,acc");
9074 aopPut (result, "a", offset++);
9077 l = aopGet (result, offset, FALSE, FALSE);
9079 emitcode ("rlc", "a");
9080 aopPut (result, "a", offset++);
9082 reAdjustPreg (AOP (result));
9085 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9088 freeAsmop (result, NULL, ic, TRUE);
9089 freeAsmop (left, NULL, ic, TRUE);
9092 /*-----------------------------------------------------------------*/
9093 /* genrshOne - right shift a one byte quantity by known count */
9094 /*-----------------------------------------------------------------*/
9096 genrshOne (operand * result, operand * left,
9097 int shCount, int sign)
9099 D (emitcode (";", "genrshOne"));
9101 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9104 /*-----------------------------------------------------------------*/
9105 /* genrshTwo - right shift two bytes by known amount != 0 */
9106 /*-----------------------------------------------------------------*/
9108 genrshTwo (operand * result, operand * left,
9109 int shCount, int sign)
9111 D (emitcode (";", "genrshTwo"));
9113 /* if shCount >= 8 */
9118 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9120 movLeft2Result (left, MSB16, result, LSB, sign);
9121 addSign (result, MSB16, sign);
9124 /* 1 <= shCount <= 7 */
9126 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9129 /*-----------------------------------------------------------------*/
9130 /* shiftRLong - shift right one long from left to result */
9131 /* offl = LSB or MSB16 */
9132 /*-----------------------------------------------------------------*/
9134 shiftRLong (operand * left, int offl,
9135 operand * result, int sign)
9137 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9139 if (overlapping && offl>1)
9141 // we are in big trouble, but this shouldn't happen
9142 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9145 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9152 emitcode ("rlc", "a");
9153 emitcode ("subb", "a,acc");
9154 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9156 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9160 aopPut (result, "a", MSB32);
9161 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9166 if (aopPutUsesAcc (result, zero, MSB32))
9168 emitcode("xch", "a,b");
9169 aopPut (result, zero, MSB32);
9170 emitcode("xch", "a,b");
9174 aopPut (result, zero, MSB32);
9181 emitcode ("clr", "c");
9185 emitcode ("mov", "c,acc.7");
9188 emitcode ("rrc", "a");
9190 if (overlapping && offl==MSB16 &&
9191 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9193 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9197 aopPut (result, "a", MSB32 - offl);
9198 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9201 emitcode ("rrc", "a");
9202 if (overlapping && offl==MSB16 &&
9203 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9205 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9209 aopPut (result, "a", MSB24 - offl);
9210 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9213 emitcode ("rrc", "a");
9216 aopPut (result, "a", MSB16 - offl);
9221 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9223 xch_a_aopGet (left, LSB, FALSE, FALSE);
9227 aopPut (result, "a", MSB16 - offl);
9228 MOVA (aopGet (left, LSB, FALSE, FALSE));
9230 emitcode ("rrc", "a");
9231 aopPut (result, "a", LSB);
9235 /*-----------------------------------------------------------------*/
9236 /* genrshFour - shift four byte by a known amount != 0 */
9237 /*-----------------------------------------------------------------*/
9239 genrshFour (operand * result, operand * left,
9240 int shCount, int sign)
9242 D (emitcode (";", "genrshFour"));
9244 /* if shifting more that 3 bytes */
9249 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9251 movLeft2Result (left, MSB32, result, LSB, sign);
9252 addSign (result, MSB16, sign);
9254 else if (shCount >= 16)
9258 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9261 movLeft2Result (left, MSB24, result, LSB, 0);
9262 movLeft2Result (left, MSB32, result, MSB16, sign);
9264 addSign (result, MSB24, sign);
9266 else if (shCount >= 8)
9271 shiftRLong (left, MSB16, result, sign);
9273 else if (shCount == 0)
9275 movLeft2Result (left, MSB16, result, LSB, 0);
9276 movLeft2Result (left, MSB24, result, MSB16, 0);
9277 movLeft2Result (left, MSB32, result, MSB24, sign);
9278 addSign (result, MSB32, sign);
9282 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9283 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9284 /* the last shift is signed */
9285 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9286 addSign (result, MSB32, sign);
9291 /* 1 <= shCount <= 7 */
9294 shiftRLong (left, LSB, result, sign);
9296 shiftRLong (result, LSB, result, sign);
9300 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9301 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9302 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9307 /*-----------------------------------------------------------------*/
9308 /* genRightShiftLiteral - right shifting by known count */
9309 /*-----------------------------------------------------------------*/
9311 genRightShiftLiteral (operand * left,
9317 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9320 D (emitcode (";", "genRightShiftLiteral"));
9322 freeAsmop (right, NULL, ic, TRUE);
9324 aopOp (left, ic, FALSE);
9325 aopOp (result, ic, FALSE);
9328 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9332 size = getDataSize (left);
9333 /* test the LEFT size !!! */
9335 /* I suppose that the left size >= result size */
9338 size = getDataSize (result);
9340 movLeft2Result (left, size, result, size, 0);
9343 else if (shCount >= (size * 8))
9347 /* get sign in acc.7 */
9348 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9350 addSign (result, LSB, sign);
9357 genrshOne (result, left, shCount, sign);
9361 genrshTwo (result, left, shCount, sign);
9365 genrshFour (result, left, shCount, sign);
9371 freeAsmop (result, NULL, ic, TRUE);
9372 freeAsmop (left, NULL, ic, TRUE);
9375 /*-----------------------------------------------------------------*/
9376 /* genSignedRightShift - right shift of signed number */
9377 /*-----------------------------------------------------------------*/
9379 genSignedRightShift (iCode * ic)
9381 operand *right, *left, *result;
9384 symbol *tlbl, *tlbl1;
9387 D (emitcode (";", "genSignedRightShift"));
9389 /* we do it the hard way put the shift count in b
9390 and loop thru preserving the sign */
9392 right = IC_RIGHT (ic);
9393 left = IC_LEFT (ic);
9394 result = IC_RESULT (ic);
9396 aopOp (right, ic, FALSE);
9399 if (AOP_TYPE (right) == AOP_LIT)
9401 genRightShiftLiteral (left, right, result, ic, 1);
9404 /* shift count is unknown then we have to form
9405 a loop get the loop count in B : Note: we take
9406 only the lower order byte since shifting
9407 more that 32 bits make no sense anyway, ( the
9408 largest size of an object can be only 32 bits ) */
9411 MOVB (aopGet (right, 0, FALSE, FALSE));
9412 emitcode ("inc", "b");
9413 freeAsmop (right, NULL, ic, TRUE);
9414 aopOp (left, ic, FALSE);
9415 aopOp (result, ic, FALSE);
9417 /* now move the left to the result if they are not the
9419 if (!sameRegs (AOP (left), AOP (result)) &&
9420 AOP_SIZE (result) > 1)
9423 size = AOP_SIZE (result);
9427 l = aopGet (left, offset, FALSE, TRUE);
9428 if (*l == '@' && IS_AOP_PREG (result))
9431 emitcode ("mov", "a,%s", l);
9432 aopPut (result, "a", offset);
9435 aopPut (result, l, offset);
9440 /* mov the highest order bit to OVR */
9441 tlbl = newiTempLabel (NULL);
9442 tlbl1 = newiTempLabel (NULL);
9444 size = AOP_SIZE (result);
9446 MOVA (aopGet (left, offset, FALSE, FALSE));
9447 emitcode ("rlc", "a");
9448 emitcode ("mov", "ov,c");
9449 /* if it is only one byte then */
9452 l = aopGet (left, 0, FALSE, FALSE);
9454 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9456 emitcode ("mov", "c,ov");
9457 emitcode ("rrc", "a");
9459 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9461 aopPut (result, "a", 0);
9465 reAdjustPreg (AOP (result));
9466 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9468 emitcode ("mov", "c,ov");
9471 l = aopGet (result, offset, FALSE, FALSE);
9473 emitcode ("rrc", "a");
9474 aopPut (result, "a", offset--);
9476 reAdjustPreg (AOP (result));
9478 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9482 freeAsmop (result, NULL, ic, TRUE);
9483 freeAsmop (left, NULL, ic, TRUE);
9486 /*-----------------------------------------------------------------*/
9487 /* genRightShift - generate code for right shifting */
9488 /*-----------------------------------------------------------------*/
9490 genRightShift (iCode * ic)
9492 operand *right, *left, *result;
9496 symbol *tlbl, *tlbl1;
9499 D (emitcode (";", "genRightShift"));
9501 /* if signed then we do it the hard way preserve the
9502 sign bit moving it inwards */
9503 letype = getSpec (operandType (IC_LEFT (ic)));
9505 if (!SPEC_USIGN (letype))
9507 genSignedRightShift (ic);
9511 /* signed & unsigned types are treated the same : i.e. the
9512 signed is NOT propagated inwards : quoting from the
9513 ANSI - standard : "for E1 >> E2, is equivalent to division
9514 by 2**E2 if unsigned or if it has a non-negative value,
9515 otherwise the result is implementation defined ", MY definition
9516 is that the sign does not get propagated */
9518 right = IC_RIGHT (ic);
9519 left = IC_LEFT (ic);
9520 result = IC_RESULT (ic);
9522 aopOp (right, ic, FALSE);
9524 /* if the shift count is known then do it
9525 as efficiently as possible */
9526 if (AOP_TYPE (right) == AOP_LIT)
9528 genRightShiftLiteral (left, right, result, ic, 0);
9532 /* shift count is unknown then we have to form
9533 a loop get the loop count in B : Note: we take
9534 only the lower order byte since shifting
9535 more that 32 bits make no sense anyway, ( the
9536 largest size of an object can be only 32 bits ) */
9539 MOVB (aopGet (right, 0, FALSE, FALSE));
9540 emitcode ("inc", "b");
9541 freeAsmop (right, NULL, ic, TRUE);
9542 aopOp (left, ic, FALSE);
9543 aopOp (result, ic, FALSE);
9545 /* now move the left to the result if they are not the
9547 if (!sameRegs (AOP (left), AOP (result)) &&
9548 AOP_SIZE (result) > 1)
9550 size = AOP_SIZE (result);
9554 l = aopGet (left, offset, FALSE, TRUE);
9555 if (*l == '@' && IS_AOP_PREG (result))
9558 emitcode ("mov", "a,%s", l);
9559 aopPut (result, "a", offset);
9562 aopPut (result, l, offset);
9567 tlbl = newiTempLabel (NULL);
9568 tlbl1 = newiTempLabel (NULL);
9569 size = AOP_SIZE (result);
9572 /* if it is only one byte then */
9575 l = aopGet (left, 0, FALSE, FALSE);
9577 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9580 emitcode ("rrc", "a");
9582 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9584 aopPut (result, "a", 0);
9588 reAdjustPreg (AOP (result));
9589 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9594 l = aopGet (result, offset, FALSE, FALSE);
9596 emitcode ("rrc", "a");
9597 aopPut (result, "a", offset--);
9599 reAdjustPreg (AOP (result));
9602 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9606 freeAsmop (result, NULL, ic, TRUE);
9607 freeAsmop (left, NULL, ic, TRUE);
9610 /*-----------------------------------------------------------------*/
9611 /* emitPtrByteGet - emits code to get a byte into A through a */
9612 /* pointer register (R0, R1, or DPTR). The */
9613 /* original value of A can be preserved in B. */
9614 /*-----------------------------------------------------------------*/
9616 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9623 emitcode ("mov", "b,a");
9624 emitcode ("mov", "a,@%s", rname);
9629 emitcode ("mov", "b,a");
9630 emitcode ("movx", "a,@%s", rname);
9635 emitcode ("mov", "b,a");
9636 emitcode ("movx", "a,@dptr");
9641 emitcode ("mov", "b,a");
9642 emitcode ("clr", "a");
9643 emitcode ("movc", "a,@a+dptr");
9649 emitcode ("push", "b");
9650 emitcode ("push", "acc");
9652 emitcode ("lcall", "__gptrget");
9654 emitcode ("pop", "b");
9659 /*-----------------------------------------------------------------*/
9660 /* emitPtrByteSet - emits code to set a byte from src through a */
9661 /* pointer register (R0, R1, or DPTR). */
9662 /*-----------------------------------------------------------------*/
9664 emitPtrByteSet (char *rname, int p_type, char *src)
9673 emitcode ("mov", "@%s,a", rname);
9676 emitcode ("mov", "@%s,%s", rname, src);
9681 emitcode ("movx", "@%s,a", rname);
9686 emitcode ("movx", "@dptr,a");
9691 emitcode ("lcall", "__gptrput");
9696 /*-----------------------------------------------------------------*/
9697 /* genUnpackBits - generates code for unpacking bits */
9698 /*-----------------------------------------------------------------*/
9700 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9702 int offset = 0; /* result byte offset */
9703 int rsize; /* result size */
9704 int rlen = 0; /* remaining bitfield length */
9705 sym_link *etype; /* bitfield type information */
9706 int blen; /* bitfield length */
9707 int bstr; /* bitfield starting bit within byte */
9710 D(emitcode ("; genUnpackBits",""));
9712 etype = getSpec (operandType (result));
9713 rsize = getSize (operandType (result));
9714 blen = SPEC_BLEN (etype);
9715 bstr = SPEC_BSTR (etype);
9717 if (ifx && blen <= 8)
9719 emitPtrByteGet (rname, ptype, FALSE);
9722 SNPRINTF (buffer, sizeof(buffer),
9724 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9729 emitcode ("anl", "a,#0x%02x",
9730 (((unsigned char) -1) >> (8 - blen)) << bstr);
9731 genIfxJump (ifx, "a", NULL, NULL, NULL);
9737 /* If the bitfield length is less than a byte */
9740 emitPtrByteGet (rname, ptype, FALSE);
9742 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9743 if (!SPEC_USIGN (etype))
9745 /* signed bitfield */
9746 symbol *tlbl = newiTempLabel (NULL);
9748 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9749 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9752 aopPut (result, "a", offset++);
9756 /* Bit field did not fit in a byte. Copy all
9757 but the partial byte at the end. */
9758 for (rlen=blen;rlen>=8;rlen-=8)
9760 emitPtrByteGet (rname, ptype, FALSE);
9761 aopPut (result, "a", offset++);
9763 emitcode ("inc", "%s", rname);
9766 /* Handle the partial byte at the end */
9769 emitPtrByteGet (rname, ptype, FALSE);
9770 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9771 if (!SPEC_USIGN (etype))
9773 /* signed bitfield */
9774 symbol *tlbl = newiTempLabel (NULL);
9776 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9777 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9780 aopPut (result, "a", offset++);
9788 if (SPEC_USIGN (etype))
9792 /* signed bitfield: sign extension with 0x00 or 0xff */
9793 emitcode ("rlc", "a");
9794 emitcode ("subb", "a,acc");
9800 aopPut (result, source, offset++);
9805 /*-----------------------------------------------------------------*/
9806 /* genDataPointerGet - generates code when ptr offset is known */
9807 /*-----------------------------------------------------------------*/
9809 genDataPointerGet (operand * left,
9815 int size, offset = 0;
9817 D (emitcode (";", "genDataPointerGet"));
9819 aopOp (result, ic, TRUE);
9821 /* get the string representation of the name */
9822 l = aopGet (left, 0, FALSE, TRUE);
9824 size = AOP_SIZE (result);
9829 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9833 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9835 aopPut (result, buffer, offset++);
9838 freeAsmop (result, NULL, ic, TRUE);
9839 freeAsmop (left, NULL, ic, TRUE);
9842 /*-----------------------------------------------------------------*/
9843 /* genNearPointerGet - emitcode for near pointer fetch */
9844 /*-----------------------------------------------------------------*/
9846 genNearPointerGet (operand * left,
9855 sym_link *rtype, *retype;
9856 sym_link *ltype = operandType (left);
9859 D (emitcode (";", "genNearPointerGet"));
9861 rtype = operandType (result);
9862 retype = getSpec (rtype);
9864 aopOp (left, ic, FALSE);
9866 /* if left is rematerialisable and
9867 result is not bitfield variable type and
9868 the left is pointer to data space i.e
9869 lower 128 bytes of space */
9870 if (AOP_TYPE (left) == AOP_IMMD &&
9871 !IS_BITFIELD (retype) &&
9872 DCL_TYPE (ltype) == POINTER)
9874 genDataPointerGet (left, result, ic);
9878 /* if the value is already in a pointer register
9879 then don't need anything more */
9880 if (!AOP_INPREG (AOP (left)))
9882 if (IS_AOP_PREG (left))
9884 // Aha, it is a pointer, just in disguise.
9885 rname = aopGet (left, 0, FALSE, FALSE);
9888 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9889 __FILE__, __LINE__);
9894 emitcode ("mov", "a%s,%s", rname + 1, rname);
9895 rname++; // skip the '@'.
9900 /* otherwise get a free pointer register */
9902 preg = getFreePtr (ic, &aop, FALSE);
9903 emitcode ("mov", "%s,%s",
9905 aopGet (left, 0, FALSE, TRUE));
9910 rname = aopGet (left, 0, FALSE, FALSE);
9912 //aopOp (result, ic, FALSE);
9913 aopOp (result, ic, result?TRUE:FALSE);
9915 /* if bitfield then unpack the bits */
9916 if (IS_BITFIELD (retype))
9917 genUnpackBits (result, rname, POINTER, ifx);
9920 /* we have can just get the values */
9921 int size = AOP_SIZE (result);
9926 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9929 emitcode ("mov", "a,@%s", rname);
9931 aopPut (result, "a", offset);
9935 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9936 aopPut (result, buffer, offset);
9940 emitcode ("inc", "%s", rname);
9944 /* now some housekeeping stuff */
9945 if (aop) /* we had to allocate for this iCode */
9947 if (pi) { /* post increment present */
9948 aopPut (left, rname, 0);
9950 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9954 /* we did not allocate which means left
9955 already in a pointer register, then
9956 if size > 0 && this could be used again
9957 we have to point it back to where it
9959 if ((AOP_SIZE (result) > 1 &&
9960 !OP_SYMBOL (left)->remat &&
9961 (OP_SYMBOL (left)->liveTo > ic->seq ||
9965 int size = AOP_SIZE (result) - 1;
9967 emitcode ("dec", "%s", rname);
9971 if (ifx && !ifx->generated)
9973 genIfxJump (ifx, "a", left, NULL, result);
9977 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9978 freeAsmop (left, NULL, ic, TRUE);
9979 if (pi) pi->generated = 1;
9982 /*-----------------------------------------------------------------*/
9983 /* genPagedPointerGet - emitcode for paged pointer fetch */
9984 /*-----------------------------------------------------------------*/
9986 genPagedPointerGet (operand * left,
9995 sym_link *rtype, *retype;
9997 D (emitcode (";", "genPagedPointerGet"));
9999 rtype = operandType (result);
10000 retype = getSpec (rtype);
10002 aopOp (left, ic, FALSE);
10004 /* if the value is already in a pointer register
10005 then don't need anything more */
10006 if (!AOP_INPREG (AOP (left)))
10008 /* otherwise get a free pointer register */
10009 aop = newAsmop (0);
10010 preg = getFreePtr (ic, &aop, FALSE);
10011 emitcode ("mov", "%s,%s",
10013 aopGet (left, 0, FALSE, TRUE));
10014 rname = preg->name;
10017 rname = aopGet (left, 0, FALSE, FALSE);
10019 aopOp (result, ic, FALSE);
10021 /* if bitfield then unpack the bits */
10022 if (IS_BITFIELD (retype))
10023 genUnpackBits (result, rname, PPOINTER, ifx);
10026 /* we have can just get the values */
10027 int size = AOP_SIZE (result);
10033 emitcode ("movx", "a,@%s", rname);
10035 aopPut (result, "a", offset);
10040 emitcode ("inc", "%s", rname);
10044 /* now some housekeeping stuff */
10045 if (aop) /* we had to allocate for this iCode */
10048 aopPut (left, rname, 0);
10049 freeAsmop (NULL, aop, ic, TRUE);
10053 /* we did not allocate which means left
10054 already in a pointer register, then
10055 if size > 0 && this could be used again
10056 we have to point it back to where it
10058 if ((AOP_SIZE (result) > 1 &&
10059 !OP_SYMBOL (left)->remat &&
10060 (OP_SYMBOL (left)->liveTo > ic->seq ||
10064 int size = AOP_SIZE (result) - 1;
10066 emitcode ("dec", "%s", rname);
10070 if (ifx && !ifx->generated)
10072 genIfxJump (ifx, "a", left, NULL, result);
10076 freeAsmop (result, NULL, ic, TRUE);
10077 freeAsmop (left, NULL, ic, TRUE);
10078 if (pi) pi->generated = 1;
10081 /*--------------------------------------------------------------------*/
10082 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10083 /*--------------------------------------------------------------------*/
10085 loadDptrFromOperand (operand *op, bool loadBToo)
10087 if (AOP_TYPE (op) != AOP_STR)
10089 /* if this is rematerializable */
10090 if (AOP_TYPE (op) == AOP_IMMD)
10092 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10095 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10096 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10099 wassertl(FALSE, "need pointerCode");
10100 emitcode ("", "; mov b,???");
10101 /* genPointerGet and genPointerSet originally did different
10102 ** things for this case. Both seem wrong.
10103 ** from genPointerGet:
10104 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10105 ** from genPointerSet:
10106 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10111 else if (AOP_TYPE (op) == AOP_DPTR)
10115 MOVA (aopGet (op, 0, FALSE, FALSE));
10116 emitcode ("push", "acc");
10117 MOVA (aopGet (op, 1, FALSE, FALSE));
10118 emitcode ("push", "acc");
10119 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10120 emitcode ("pop", "dph");
10121 emitcode ("pop", "dpl");
10125 MOVA (aopGet (op, 0, FALSE, FALSE));
10126 emitcode ("push", "acc");
10127 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10128 emitcode ("pop", "dpl");
10132 { /* we need to get it byte by byte */
10133 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10134 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10136 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10141 /*-----------------------------------------------------------------*/
10142 /* genFarPointerGet - get value from far space */
10143 /*-----------------------------------------------------------------*/
10145 genFarPointerGet (operand * left,
10146 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10149 sym_link *retype = getSpec (operandType (result));
10151 D (emitcode (";", "genFarPointerGet"));
10153 aopOp (left, ic, FALSE);
10154 loadDptrFromOperand (left, FALSE);
10156 /* so dptr now contains the address */
10157 aopOp (result, ic, FALSE);
10159 /* if bit then unpack */
10160 if (IS_BITFIELD (retype))
10161 genUnpackBits (result, "dptr", FPOINTER, ifx);
10164 size = AOP_SIZE (result);
10169 emitcode ("movx", "a,@dptr");
10171 aopPut (result, "a", offset++);
10173 emitcode ("inc", "dptr");
10177 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10179 aopPut (left, "dpl", 0);
10180 aopPut (left, "dph", 1);
10184 if (ifx && !ifx->generated)
10186 genIfxJump (ifx, "a", left, NULL, result);
10189 freeAsmop (result, NULL, ic, TRUE);
10190 freeAsmop (left, NULL, ic, TRUE);
10193 /*-----------------------------------------------------------------*/
10194 /* genCodePointerGet - get value from code space */
10195 /*-----------------------------------------------------------------*/
10197 genCodePointerGet (operand * left,
10198 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10201 sym_link *retype = getSpec (operandType (result));
10203 D (emitcode (";", "genCodePointerGet"));
10205 aopOp (left, ic, FALSE);
10206 loadDptrFromOperand (left, FALSE);
10208 /* so dptr now contains the address */
10209 aopOp (result, ic, FALSE);
10211 /* if bit then unpack */
10212 if (IS_BITFIELD (retype))
10213 genUnpackBits (result, "dptr", CPOINTER, ifx);
10216 size = AOP_SIZE (result);
10221 emitcode ("clr", "a");
10222 emitcode ("movc", "a,@a+dptr");
10224 aopPut (result, "a", offset++);
10226 emitcode ("inc", "dptr");
10230 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10232 aopPut (left, "dpl", 0);
10233 aopPut (left, "dph", 1);
10237 if (ifx && !ifx->generated)
10239 genIfxJump (ifx, "a", left, NULL, result);
10242 freeAsmop (result, NULL, ic, TRUE);
10243 freeAsmop (left, NULL, ic, TRUE);
10246 /*-----------------------------------------------------------------*/
10247 /* genGenPointerGet - get value from generic pointer space */
10248 /*-----------------------------------------------------------------*/
10250 genGenPointerGet (operand * left,
10251 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10254 sym_link *retype = getSpec (operandType (result));
10256 D (emitcode (";", "genGenPointerGet"));
10258 aopOp (left, ic, FALSE);
10259 loadDptrFromOperand (left, TRUE);
10261 /* so dptr now contains the address */
10262 aopOp (result, ic, FALSE);
10264 /* if bit then unpack */
10265 if (IS_BITFIELD (retype))
10267 genUnpackBits (result, "dptr", GPOINTER, ifx);
10271 size = AOP_SIZE (result);
10276 emitcode ("lcall", "__gptrget");
10278 aopPut (result, "a", offset++);
10280 emitcode ("inc", "dptr");
10284 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10286 aopPut (left, "dpl", 0);
10287 aopPut (left, "dph", 1);
10291 if (ifx && !ifx->generated)
10293 genIfxJump (ifx, "a", left, NULL, result);
10296 freeAsmop (result, NULL, ic, TRUE);
10297 freeAsmop (left, NULL, ic, TRUE);
10300 /*-----------------------------------------------------------------*/
10301 /* genPointerGet - generate code for pointer get */
10302 /*-----------------------------------------------------------------*/
10304 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10306 operand *left, *result;
10307 sym_link *type, *etype;
10310 D (emitcode (";", "genPointerGet"));
10312 left = IC_LEFT (ic);
10313 result = IC_RESULT (ic);
10315 if (getSize (operandType (result))>1)
10318 /* depending on the type of pointer we need to
10319 move it to the correct pointer register */
10320 type = operandType (left);
10321 etype = getSpec (type);
10322 /* if left is of type of pointer then it is simple */
10323 if (IS_PTR (type) && !IS_FUNC (type->next))
10324 p_type = DCL_TYPE (type);
10327 /* we have to go by the storage class */
10328 p_type = PTR_TYPE (SPEC_OCLS (etype));
10331 /* special case when cast remat */
10332 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10333 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10335 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10336 type = operandType (left);
10337 p_type = DCL_TYPE (type);
10339 /* now that we have the pointer type we assign
10340 the pointer values */
10346 genNearPointerGet (left, result, ic, pi, ifx);
10350 genPagedPointerGet (left, result, ic, pi, ifx);
10354 genFarPointerGet (left, result, ic, pi, ifx);
10358 genCodePointerGet (left, result, ic, pi, ifx);
10362 genGenPointerGet (left, result, ic, pi, ifx);
10368 /*-----------------------------------------------------------------*/
10369 /* genPackBits - generates code for packed bit storage */
10370 /*-----------------------------------------------------------------*/
10372 genPackBits (sym_link * etype,
10374 char *rname, int p_type)
10376 int offset = 0; /* source byte offset */
10377 int rlen = 0; /* remaining bitfield length */
10378 int blen; /* bitfield length */
10379 int bstr; /* bitfield starting bit within byte */
10380 int litval; /* source literal value (if AOP_LIT) */
10381 unsigned char mask; /* bitmask within current byte */
10383 D(emitcode ("; genPackBits",""));
10385 blen = SPEC_BLEN (etype);
10386 bstr = SPEC_BSTR (etype);
10388 /* If the bitfield length is less than a byte */
10391 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10392 (unsigned char) (0xFF >> (8 - bstr)));
10394 if (AOP_TYPE (right) == AOP_LIT)
10396 /* Case with a bitfield length <8 and literal source
10398 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10400 litval &= (~mask) & 0xff;
10401 emitPtrByteGet (rname, p_type, FALSE);
10402 if ((mask|litval)!=0xff)
10403 emitcode ("anl","a,#0x%02x", mask);
10405 emitcode ("orl","a,#0x%02x", litval);
10409 if ((blen==1) && (p_type!=GPOINTER))
10411 /* Case with a bitfield length == 1 and no generic pointer
10413 if (AOP_TYPE (right) == AOP_CRY)
10414 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10417 MOVA (aopGet (right, 0, FALSE, FALSE));
10418 emitcode ("rrc","a");
10420 emitPtrByteGet (rname, p_type, FALSE);
10421 emitcode ("mov","acc.%d,c",bstr);
10426 /* Case with a bitfield length < 8 and arbitrary source
10428 MOVA (aopGet (right, 0, FALSE, FALSE));
10429 /* shift and mask source value */
10431 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10433 pushedB = pushB ();
10434 /* transfer A to B and get next byte */
10435 emitPtrByteGet (rname, p_type, TRUE);
10437 emitcode ("anl", "a,#0x%02x", mask);
10438 emitcode ("orl", "a,b");
10439 if (p_type == GPOINTER)
10440 emitcode ("pop", "b");
10446 emitPtrByteSet (rname, p_type, "a");
10450 /* Bit length is greater than 7 bits. In this case, copy */
10451 /* all except the partial byte at the end */
10452 for (rlen=blen;rlen>=8;rlen-=8)
10454 emitPtrByteSet (rname, p_type,
10455 aopGet (right, offset++, FALSE, TRUE) );
10457 emitcode ("inc", "%s", rname);
10460 /* If there was a partial byte at the end */
10463 mask = (((unsigned char) -1 << rlen) & 0xff);
10465 if (AOP_TYPE (right) == AOP_LIT)
10467 /* Case with partial byte and literal source
10469 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10470 litval >>= (blen-rlen);
10471 litval &= (~mask) & 0xff;
10472 emitPtrByteGet (rname, p_type, FALSE);
10473 if ((mask|litval)!=0xff)
10474 emitcode ("anl","a,#0x%02x", mask);
10476 emitcode ("orl","a,#0x%02x", litval);
10481 /* Case with partial byte and arbitrary source
10483 MOVA (aopGet (right, offset++, FALSE, FALSE));
10484 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10486 pushedB = pushB ();
10487 /* transfer A to B and get next byte */
10488 emitPtrByteGet (rname, p_type, TRUE);
10490 emitcode ("anl", "a,#0x%02x", mask);
10491 emitcode ("orl", "a,b");
10492 if (p_type == GPOINTER)
10493 emitcode ("pop", "b");
10497 emitPtrByteSet (rname, p_type, "a");
10502 /*-----------------------------------------------------------------*/
10503 /* genDataPointerSet - remat pointer to data space */
10504 /*-----------------------------------------------------------------*/
10506 genDataPointerSet (operand * right,
10510 int size, offset = 0;
10511 char *l, buffer[256];
10513 D (emitcode (";", "genDataPointerSet"));
10515 aopOp (right, ic, FALSE);
10517 l = aopGet (result, 0, FALSE, TRUE);
10519 size = AOP_SIZE (right);
10523 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10525 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10526 emitcode ("mov", "%s,%s", buffer,
10527 aopGet (right, offset++, FALSE, FALSE));
10530 freeAsmop (result, NULL, ic, TRUE);
10531 freeAsmop (right, NULL, ic, TRUE);
10534 /*-----------------------------------------------------------------*/
10535 /* genNearPointerSet - emitcode for near pointer put */
10536 /*-----------------------------------------------------------------*/
10538 genNearPointerSet (operand * right,
10546 sym_link *retype, *letype;
10547 sym_link *ptype = operandType (result);
10549 D (emitcode (";", "genNearPointerSet"));
10551 retype = getSpec (operandType (right));
10552 letype = getSpec (ptype);
10554 aopOp (result, ic, FALSE);
10556 /* if the result is rematerializable &
10557 in data space & not a bit variable */
10558 if (AOP_TYPE (result) == AOP_IMMD &&
10559 DCL_TYPE (ptype) == POINTER &&
10560 !IS_BITVAR (retype) &&
10561 !IS_BITVAR (letype))
10563 genDataPointerSet (right, result, ic);
10567 /* if the value is already in a pointer register
10568 then don't need anything more */
10569 if (!AOP_INPREG (AOP (result)))
10572 //AOP_TYPE (result) == AOP_STK
10573 IS_AOP_PREG(result)
10576 // Aha, it is a pointer, just in disguise.
10577 rname = aopGet (result, 0, FALSE, FALSE);
10580 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10581 __FILE__, __LINE__);
10586 emitcode ("mov", "a%s,%s", rname + 1, rname);
10587 rname++; // skip the '@'.
10592 /* otherwise get a free pointer register */
10593 aop = newAsmop (0);
10594 preg = getFreePtr (ic, &aop, FALSE);
10595 emitcode ("mov", "%s,%s",
10597 aopGet (result, 0, FALSE, TRUE));
10598 rname = preg->name;
10603 rname = aopGet (result, 0, FALSE, FALSE);
10606 aopOp (right, ic, FALSE);
10608 /* if bitfield then unpack the bits */
10609 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10610 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10613 /* we can just get the values */
10614 int size = AOP_SIZE (right);
10619 l = aopGet (right, offset, FALSE, TRUE);
10620 if ((*l == '@') || (strcmp (l, "acc") == 0))
10623 emitcode ("mov", "@%s,a", rname);
10626 emitcode ("mov", "@%s,%s", rname, l);
10628 emitcode ("inc", "%s", rname);
10633 /* now some housekeeping stuff */
10634 if (aop) /* we had to allocate for this iCode */
10637 aopPut (result, rname, 0);
10638 freeAsmop (NULL, aop, ic, TRUE);
10642 /* we did not allocate which means left
10643 already in a pointer register, then
10644 if size > 0 && this could be used again
10645 we have to point it back to where it
10647 if ((AOP_SIZE (right) > 1 &&
10648 !OP_SYMBOL (result)->remat &&
10649 (OP_SYMBOL (result)->liveTo > ic->seq ||
10653 int size = AOP_SIZE (right) - 1;
10655 emitcode ("dec", "%s", rname);
10660 if (pi) pi->generated = 1;
10661 freeAsmop (result, NULL, ic, TRUE);
10662 freeAsmop (right, NULL, ic, TRUE);
10665 /*-----------------------------------------------------------------*/
10666 /* genPagedPointerSet - emitcode for Paged pointer put */
10667 /*-----------------------------------------------------------------*/
10669 genPagedPointerSet (operand * right,
10677 sym_link *retype, *letype;
10679 D (emitcode (";", "genPagedPointerSet"));
10681 retype = getSpec (operandType (right));
10682 letype = getSpec (operandType (result));
10684 aopOp (result, ic, FALSE);
10686 /* if the value is already in a pointer register
10687 then don't need anything more */
10688 if (!AOP_INPREG (AOP (result)))
10690 /* otherwise get a free pointer register */
10691 aop = newAsmop (0);
10692 preg = getFreePtr (ic, &aop, FALSE);
10693 emitcode ("mov", "%s,%s",
10695 aopGet (result, 0, FALSE, TRUE));
10696 rname = preg->name;
10699 rname = aopGet (result, 0, FALSE, FALSE);
10701 aopOp (right, ic, FALSE);
10703 /* if bitfield then unpack the bits */
10704 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10705 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10708 /* we have can just get the values */
10709 int size = AOP_SIZE (right);
10714 l = aopGet (right, offset, FALSE, TRUE);
10716 emitcode ("movx", "@%s,a", rname);
10719 emitcode ("inc", "%s", rname);
10725 /* now some housekeeping stuff */
10726 if (aop) /* we had to allocate for this iCode */
10729 aopPut (result, rname, 0);
10730 freeAsmop (NULL, aop, ic, TRUE);
10734 /* we did not allocate which means left
10735 already in a pointer register, then
10736 if size > 0 && this could be used again
10737 we have to point it back to where it
10739 if (AOP_SIZE (right) > 1 &&
10740 !OP_SYMBOL (result)->remat &&
10741 (OP_SYMBOL (result)->liveTo > ic->seq ||
10744 int size = AOP_SIZE (right) - 1;
10746 emitcode ("dec", "%s", rname);
10751 if (pi) pi->generated = 1;
10752 freeAsmop (result, NULL, ic, TRUE);
10753 freeAsmop (right, NULL, ic, TRUE);
10756 /*-----------------------------------------------------------------*/
10757 /* genFarPointerSet - set value from far space */
10758 /*-----------------------------------------------------------------*/
10760 genFarPointerSet (operand * right,
10761 operand * result, iCode * ic, iCode * pi)
10764 sym_link *retype = getSpec (operandType (right));
10765 sym_link *letype = getSpec (operandType (result));
10767 D(emitcode ("; genFarPointerSet",""));
10769 aopOp (result, ic, FALSE);
10770 loadDptrFromOperand (result, FALSE);
10772 /* so dptr now contains the address */
10773 aopOp (right, ic, FALSE);
10775 /* if bit then unpack */
10776 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10777 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10780 size = AOP_SIZE (right);
10785 char *l = aopGet (right, offset++, FALSE, FALSE);
10787 emitcode ("movx", "@dptr,a");
10789 emitcode ("inc", "dptr");
10792 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10793 aopPut (result, "dpl", 0);
10794 aopPut (result, "dph", 1);
10797 freeAsmop (result, NULL, ic, TRUE);
10798 freeAsmop (right, NULL, ic, TRUE);
10801 /*-----------------------------------------------------------------*/
10802 /* genGenPointerSet - set value from generic pointer space */
10803 /*-----------------------------------------------------------------*/
10805 genGenPointerSet (operand * right,
10806 operand * result, iCode * ic, iCode * pi)
10809 sym_link *retype = getSpec (operandType (right));
10810 sym_link *letype = getSpec (operandType (result));
10812 D (emitcode (";", "genGenPointerSet"));
10814 aopOp (result, ic, FALSE);
10815 loadDptrFromOperand (result, TRUE);
10817 /* so dptr now contains the address */
10818 aopOp (right, ic, FALSE);
10820 /* if bit then unpack */
10821 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10823 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10827 size = AOP_SIZE (right);
10832 char *l = aopGet (right, offset++, FALSE, FALSE);
10834 emitcode ("lcall", "__gptrput");
10836 emitcode ("inc", "dptr");
10840 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10841 aopPut (result, "dpl", 0);
10842 aopPut (result, "dph", 1);
10845 freeAsmop (result, NULL, ic, TRUE);
10846 freeAsmop (right, NULL, ic, TRUE);
10849 /*-----------------------------------------------------------------*/
10850 /* genPointerSet - stores the value into a pointer location */
10851 /*-----------------------------------------------------------------*/
10853 genPointerSet (iCode * ic, iCode *pi)
10855 operand *right, *result;
10856 sym_link *type, *etype;
10859 D (emitcode (";", "genPointerSet"));
10861 right = IC_RIGHT (ic);
10862 result = IC_RESULT (ic);
10864 /* depending on the type of pointer we need to
10865 move it to the correct pointer register */
10866 type = operandType (result);
10867 etype = getSpec (type);
10868 /* if left is of type of pointer then it is simple */
10869 if (IS_PTR (type) && !IS_FUNC (type->next))
10871 p_type = DCL_TYPE (type);
10875 /* we have to go by the storage class */
10876 p_type = PTR_TYPE (SPEC_OCLS (etype));
10879 /* special case when cast remat */
10880 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10881 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10882 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10883 type = operandType (result);
10884 p_type = DCL_TYPE (type);
10887 /* now that we have the pointer type we assign
10888 the pointer values */
10894 genNearPointerSet (right, result, ic, pi);
10898 genPagedPointerSet (right, result, ic, pi);
10902 genFarPointerSet (right, result, ic, pi);
10906 genGenPointerSet (right, result, ic, pi);
10910 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10911 "genPointerSet: illegal pointer type");
10915 /*-----------------------------------------------------------------*/
10916 /* genIfx - generate code for Ifx statement */
10917 /*-----------------------------------------------------------------*/
10919 genIfx (iCode * ic, iCode * popIc)
10921 operand *cond = IC_COND (ic);
10925 D (emitcode (";", "genIfx"));
10927 aopOp (cond, ic, FALSE);
10929 /* get the value into acc */
10930 if (AOP_TYPE (cond) != AOP_CRY)
10937 if (AOP(cond)->aopu.aop_dir)
10938 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10941 /* the result is now in the accumulator or a directly addressable bit */
10942 freeAsmop (cond, NULL, ic, TRUE);
10944 /* if there was something to be popped then do it */
10948 /* if the condition is a bit variable */
10950 genIfxJump(ic, dup, NULL, NULL, NULL);
10951 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10952 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10953 else if (isbit && !IS_ITEMP (cond))
10954 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10956 genIfxJump (ic, "a", NULL, NULL, NULL);
10961 /*-----------------------------------------------------------------*/
10962 /* genAddrOf - generates code for address of */
10963 /*-----------------------------------------------------------------*/
10965 genAddrOf (iCode * ic)
10967 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10970 D (emitcode (";", "genAddrOf"));
10972 aopOp (IC_RESULT (ic), ic, FALSE);
10974 /* if the operand is on the stack then we
10975 need to get the stack offset of this
10979 /* if it has an offset then we need to compute it */
10982 int stack_offset = ((sym->stack < 0) ?
10983 ((char) (sym->stack - _G.nRegsSaved)) :
10984 ((char) sym->stack)) & 0xff;
10985 if ((abs(stack_offset) == 1) &&
10986 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10987 !isOperandVolatile (IC_RESULT (ic), FALSE))
10989 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10990 if (stack_offset > 0)
10991 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10993 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10997 emitcode ("mov", "a,%s", SYM_BP (sym));
10998 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10999 aopPut (IC_RESULT (ic), "a", 0);
11004 /* we can just move _bp */
11005 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11007 /* fill the result with zero */
11008 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11013 aopPut (IC_RESULT (ic), zero, offset++);
11018 /* object not on stack then we need the name */
11019 size = AOP_SIZE (IC_RESULT (ic));
11024 char s[SDCC_NAME_MAX];
11026 sprintf (s, "#(%s >> %d)",
11030 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11031 aopPut (IC_RESULT (ic), s, offset++);
11035 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11039 /*-----------------------------------------------------------------*/
11040 /* genFarFarAssign - assignment when both are in far space */
11041 /*-----------------------------------------------------------------*/
11043 genFarFarAssign (operand * result, operand * right, iCode * ic)
11045 int size = AOP_SIZE (right);
11049 D (emitcode (";", "genFarFarAssign"));
11051 /* first push the right side on to the stack */
11054 l = aopGet (right, offset++, FALSE, FALSE);
11056 emitcode ("push", "acc");
11059 freeAsmop (right, NULL, ic, FALSE);
11060 /* now assign DPTR to result */
11061 aopOp (result, ic, FALSE);
11062 size = AOP_SIZE (result);
11065 emitcode ("pop", "acc");
11066 aopPut (result, "a", --offset);
11068 freeAsmop (result, NULL, ic, FALSE);
11071 /*-----------------------------------------------------------------*/
11072 /* genAssign - generate code for assignment */
11073 /*-----------------------------------------------------------------*/
11075 genAssign (iCode * ic)
11077 operand *result, *right;
11079 unsigned long lit = 0L;
11081 D (emitcode (";", "genAssign"));
11083 result = IC_RESULT (ic);
11084 right = IC_RIGHT (ic);
11086 /* if they are the same */
11087 if (operandsEqu (result, right) &&
11088 !isOperandVolatile (result, FALSE) &&
11089 !isOperandVolatile (right, FALSE))
11092 aopOp (right, ic, FALSE);
11094 /* special case both in far space */
11095 if (AOP_TYPE (right) == AOP_DPTR &&
11096 IS_TRUE_SYMOP (result) &&
11097 isOperandInFarSpace (result))
11099 genFarFarAssign (result, right, ic);
11103 aopOp (result, ic, TRUE);
11105 /* if they are the same registers */
11106 if (sameRegs (AOP (right), AOP (result)) &&
11107 !isOperandVolatile (result, FALSE) &&
11108 !isOperandVolatile (right, FALSE))
11111 /* if the result is a bit */
11112 if (AOP_TYPE (result) == AOP_CRY)
11114 assignBit (result, right);
11118 /* bit variables done */
11120 size = AOP_SIZE (result);
11122 if (AOP_TYPE (right) == AOP_LIT)
11123 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11126 (AOP_TYPE (result) != AOP_REG) &&
11127 (AOP_TYPE (right) == AOP_LIT) &&
11128 !IS_FLOAT (operandType (right)) &&
11131 while ((size) && (lit))
11134 aopGet (right, offset, FALSE, FALSE),
11140 /* And now fill the rest with zeros. */
11143 emitcode ("clr", "a");
11147 aopPut (result, "a", offset);
11156 aopGet (right, offset, FALSE, FALSE),
11163 freeAsmop (result, NULL, ic, TRUE);
11164 freeAsmop (right, NULL, ic, TRUE);
11167 /*-----------------------------------------------------------------*/
11168 /* genJumpTab - generates code for jump table */
11169 /*-----------------------------------------------------------------*/
11171 genJumpTab (iCode * ic)
11173 symbol *jtab,*jtablo,*jtabhi;
11175 unsigned int count;
11177 D (emitcode (";", "genJumpTab"));
11179 count = elementsInSet( IC_JTLABELS (ic) );
11183 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11184 if the switch argument is in a register.
11185 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11186 /* Peephole may not convert ljmp to sjmp or ret
11187 labelIsReturnOnly & labelInRange must check
11188 currPl->ic->op != JUMPTABLE */
11189 aopOp (IC_JTCOND (ic), ic, FALSE);
11190 /* get the condition into accumulator */
11191 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11193 /* multiply by three */
11194 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11196 emitcode ("mov", "b,#3");
11197 emitcode ("mul", "ab");
11201 emitcode ("add", "a,acc");
11202 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11204 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11206 jtab = newiTempLabel (NULL);
11207 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11208 emitcode ("jmp", "@a+dptr");
11210 /* now generate the jump labels */
11211 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11212 jtab = setNextItem (IC_JTLABELS (ic)))
11213 emitcode ("ljmp", "%05d$", jtab->key + 100);
11217 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11218 if the switch argument is in a register.
11219 For n>6 this algorithm may be more compact */
11220 jtablo = newiTempLabel (NULL);
11221 jtabhi = newiTempLabel (NULL);
11223 /* get the condition into accumulator.
11224 Using b as temporary storage, if register push/pop is needed */
11225 aopOp (IC_JTCOND (ic), ic, FALSE);
11226 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11227 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11228 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11230 // (MB) what if B is in use???
11231 wassertl(!BINUSE, "B was in use");
11232 emitcode ("mov", "b,%s", l);
11235 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11239 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11240 emitcode ("movc", "a,@a+pc");
11241 emitcode ("push", "acc");
11244 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11245 emitcode ("movc", "a,@a+pc");
11246 emitcode ("push", "acc");
11250 /* this scales up to n<=255, but needs two more bytes
11251 and changes dptr */
11252 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11253 emitcode ("movc", "a,@a+dptr");
11254 emitcode ("push", "acc");
11257 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11258 emitcode ("movc", "a,@a+dptr");
11259 emitcode ("push", "acc");
11262 emitcode ("ret", "");
11264 /* now generate jump table, LSB */
11265 emitLabel (jtablo);
11266 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11267 jtab = setNextItem (IC_JTLABELS (ic)))
11268 emitcode (".db", "%05d$", jtab->key + 100);
11270 /* now generate jump table, MSB */
11271 emitLabel (jtabhi);
11272 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11273 jtab = setNextItem (IC_JTLABELS (ic)))
11274 emitcode (".db", "%05d$>>8", jtab->key + 100);
11278 /*-----------------------------------------------------------------*/
11279 /* genCast - gen code for casting */
11280 /*-----------------------------------------------------------------*/
11282 genCast (iCode * ic)
11284 operand *result = IC_RESULT (ic);
11285 sym_link *ctype = operandType (IC_LEFT (ic));
11286 sym_link *rtype = operandType (IC_RIGHT (ic));
11287 operand *right = IC_RIGHT (ic);
11290 D (emitcode (";", "genCast"));
11292 /* if they are equivalent then do nothing */
11293 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11296 aopOp (right, ic, FALSE);
11297 aopOp (result, ic, FALSE);
11299 /* if the result is a bit (and not a bitfield) */
11300 if (IS_BIT (OP_SYMBOL (result)->type))
11302 assignBit (result, right);
11306 /* if they are the same size : or less */
11307 if (AOP_SIZE (result) <= AOP_SIZE (right))
11310 /* if they are in the same place */
11311 if (sameRegs (AOP (right), AOP (result)))
11314 /* if they in different places then copy */
11315 size = AOP_SIZE (result);
11320 aopGet (right, offset, FALSE, FALSE),
11327 /* if the result is of type pointer */
11328 if (IS_PTR (ctype))
11332 sym_link *type = operandType (right);
11333 sym_link *etype = getSpec (type);
11335 /* pointer to generic pointer */
11336 if (IS_GENPTR (ctype))
11340 p_type = DCL_TYPE (type);
11344 if (SPEC_SCLS(etype)==S_REGISTER) {
11345 // let's assume it is a generic pointer
11348 /* we have to go by the storage class */
11349 p_type = PTR_TYPE (SPEC_OCLS (etype));
11353 /* the first two bytes are known */
11354 size = GPTRSIZE - 1;
11359 aopGet (right, offset, FALSE, FALSE),
11363 /* the last byte depending on type */
11365 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11370 // pointerTypeToGPByte will have bitched.
11374 sprintf(gpValStr, "#0x%x", gpVal);
11375 aopPut (result, gpValStr, GPTRSIZE - 1);
11380 /* just copy the pointers */
11381 size = AOP_SIZE (result);
11386 aopGet (right, offset, FALSE, FALSE),
11393 /* so we now know that the size of destination is greater
11394 than the size of the source */
11395 /* we move to result for the size of source */
11396 size = AOP_SIZE (right);
11401 aopGet (right, offset, FALSE, FALSE),
11406 /* now depending on the sign of the source && destination */
11407 size = AOP_SIZE (result) - AOP_SIZE (right);
11408 /* if unsigned or not an integral type */
11409 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11412 aopPut (result, zero, offset++);
11416 /* we need to extend the sign :{ */
11417 char *l = aopGet (right, AOP_SIZE (right) - 1,
11420 emitcode ("rlc", "a");
11421 emitcode ("subb", "a,acc");
11423 aopPut (result, "a", offset++);
11426 /* we are done hurray !!!! */
11429 freeAsmop (result, NULL, ic, TRUE);
11430 freeAsmop (right, NULL, ic, TRUE);
11433 /*-----------------------------------------------------------------*/
11434 /* genDjnz - generate decrement & jump if not zero instrucion */
11435 /*-----------------------------------------------------------------*/
11437 genDjnz (iCode * ic, iCode * ifx)
11439 symbol *lbl, *lbl1;
11443 /* if the if condition has a false label
11444 then we cannot save */
11445 if (IC_FALSE (ifx))
11448 /* if the minus is not of the form a = a - 1 */
11449 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11450 !IS_OP_LITERAL (IC_RIGHT (ic)))
11453 if (operandLitValue (IC_RIGHT (ic)) != 1)
11456 /* if the size of this greater than one then no
11458 if (getSize (operandType (IC_RESULT (ic))) > 1)
11461 /* otherwise we can save BIG */
11463 D (emitcode (";", "genDjnz"));
11465 lbl = newiTempLabel (NULL);
11466 lbl1 = newiTempLabel (NULL);
11468 aopOp (IC_RESULT (ic), ic, FALSE);
11470 if (AOP_NEEDSACC(IC_RESULT(ic)))
11472 /* If the result is accessed indirectly via
11473 * the accumulator, we must explicitly write
11474 * it back after the decrement.
11476 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11478 if (strcmp(rByte, "a"))
11480 /* Something is hopelessly wrong */
11481 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11482 __FILE__, __LINE__);
11483 /* We can just give up; the generated code will be inefficient,
11484 * but what the hey.
11486 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11489 emitcode ("dec", "%s", rByte);
11490 aopPut (IC_RESULT (ic), rByte, 0);
11491 emitcode ("jnz", "%05d$", lbl->key + 100);
11493 else if (IS_AOP_PREG (IC_RESULT (ic)))
11495 emitcode ("dec", "%s",
11496 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11497 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11498 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11499 ifx->generated = 1;
11500 emitcode ("jnz", "%05d$", lbl->key + 100);
11504 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11507 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11509 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11512 if (!ifx->generated)
11513 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11514 ifx->generated = 1;
11518 /*-----------------------------------------------------------------*/
11519 /* genReceive - generate code for a receive iCode */
11520 /*-----------------------------------------------------------------*/
11522 genReceive (iCode * ic)
11524 int size = getSize (operandType (IC_RESULT (ic)));
11527 D (emitcode (";", "genReceive"));
11529 if (ic->argreg == 1)
11530 { /* first parameter */
11531 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11532 isOperandInPagedSpace (IC_RESULT (ic))) &&
11533 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11534 IS_TRUE_SYMOP (IC_RESULT (ic))))
11537 int receivingA = 0;
11540 for (offset = 0; offset<size; offset++)
11541 if (!strcmp (fReturn[offset], "a"))
11546 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11548 for (offset = size-1; offset>0; offset--)
11549 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11550 emitcode("mov","a,%s", fReturn[0]);
11552 aopOp (IC_RESULT (ic), ic, FALSE);
11554 aopPut (IC_RESULT (ic), "a", offset);
11555 for (offset = 1; offset<size; offset++)
11556 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11562 if (getTempRegs(tempRegs, size, ic))
11564 for (offset = 0; offset<size; offset++)
11565 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11566 aopOp (IC_RESULT (ic), ic, FALSE);
11567 for (offset = 0; offset<size; offset++)
11568 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11573 offset = fReturnSizeMCS51 - size;
11576 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11577 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11580 aopOp (IC_RESULT (ic), ic, FALSE);
11581 size = AOP_SIZE (IC_RESULT (ic));
11585 emitcode ("pop", "acc");
11586 aopPut (IC_RESULT (ic), "a", offset++);
11592 aopOp (IC_RESULT (ic), ic, FALSE);
11594 assignResultValue (IC_RESULT (ic), NULL);
11597 else if (ic->argreg > 12)
11598 { /* bit parameters */
11599 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11601 aopOp (IC_RESULT (ic), ic, FALSE);
11602 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11603 outBitC(IC_RESULT (ic));
11607 { /* other parameters */
11609 aopOp (IC_RESULT (ic), ic, FALSE);
11610 rb1off = ic->argreg;
11613 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11618 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11621 /*-----------------------------------------------------------------*/
11622 /* genDummyRead - generate code for dummy read of volatiles */
11623 /*-----------------------------------------------------------------*/
11625 genDummyRead (iCode * ic)
11630 D (emitcode(";", "genDummyRead"));
11632 op = IC_RIGHT (ic);
11633 if (op && IS_SYMOP (op))
11635 aopOp (op, ic, FALSE);
11637 /* if the result is a bit */
11638 if (AOP_TYPE (op) == AOP_CRY)
11639 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11642 /* bit variables done */
11644 size = AOP_SIZE (op);
11648 MOVA (aopGet (op, offset, FALSE, FALSE));
11653 freeAsmop (op, NULL, ic, TRUE);
11657 if (op && IS_SYMOP (op))
11659 aopOp (op, ic, FALSE);
11661 /* if the result is a bit */
11662 if (AOP_TYPE (op) == AOP_CRY)
11663 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11666 /* bit variables done */
11668 size = AOP_SIZE (op);
11672 MOVA (aopGet (op, offset, FALSE, FALSE));
11677 freeAsmop (op, NULL, ic, TRUE);
11681 /*-----------------------------------------------------------------*/
11682 /* genCritical - generate code for start of a critical sequence */
11683 /*-----------------------------------------------------------------*/
11685 genCritical (iCode *ic)
11687 symbol *tlbl = newiTempLabel (NULL);
11689 D (emitcode(";", "genCritical"));
11691 if (IC_RESULT (ic))
11693 aopOp (IC_RESULT (ic), ic, TRUE);
11694 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11695 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11696 aopPut (IC_RESULT (ic), zero, 0);
11698 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11702 emitcode ("setb", "c");
11703 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11704 emitcode ("clr", "c");
11706 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11710 /*-----------------------------------------------------------------*/
11711 /* genEndCritical - generate code for end of a critical sequence */
11712 /*-----------------------------------------------------------------*/
11714 genEndCritical (iCode *ic)
11716 D(emitcode("; genEndCritical",""));
11720 aopOp (IC_RIGHT (ic), ic, FALSE);
11721 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11723 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11724 emitcode ("mov", "ea,c");
11728 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11729 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11730 emitcode ("rrc", "a");
11731 emitcode ("mov", "ea,c");
11733 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11737 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11738 emitcode ("mov", "ea,c");
11742 /*-----------------------------------------------------------------*/
11743 /* gen51Code - generate code for 8051 based controllers */
11744 /*-----------------------------------------------------------------*/
11746 gen51Code (iCode * lic)
11750 /* int cseq = 0; */
11752 _G.currentFunc = NULL;
11753 lineHead = lineCurr = NULL;
11755 /* print the allocation information */
11756 if (allocInfo && currFunc)
11757 printAllocInfo (currFunc, codeOutBuf);
11758 /* if debug information required */
11759 if (options.debug && currFunc)
11761 debugFile->writeFunction (currFunc, lic);
11763 /* stack pointer name */
11764 if (options.useXstack)
11770 for (ic = lic; ic; ic = ic->next)
11772 _G.current_iCode = ic;
11774 if (ic->lineno && cln != ic->lineno)
11778 debugFile->writeCLine (ic);
11780 if (!options.noCcodeInAsm) {
11781 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11782 printCLine(ic->filename, ic->lineno));
11787 if (ic->seqPoint && ic->seqPoint != cseq)
11789 emitcode ("", "; sequence point %d", ic->seqPoint);
11790 cseq = ic->seqPoint;
11793 if (options.iCodeInAsm) {
11794 char regsInUse[80];
11799 for (i=0; i<8; i++) {
11800 sprintf (®sInUse[i],
11801 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11804 strcpy (regsInUse, "--------");
11805 for (i=0; i < 8; i++) {
11806 if (bitVectBitValue (ic->rMask, i))
11808 int offset = regs8051[i].offset;
11809 regsInUse[offset] = offset + '0'; /* show rMask */
11813 iLine = printILine(ic);
11814 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11817 /* if the result is marked as
11818 spilt and rematerializable or code for
11819 this has already been generated then
11821 if (resultRemat (ic) || ic->generated)
11824 /* depending on the operation */
11844 /* IPOP happens only when trying to restore a
11845 spilt live range, if there is an ifx statement
11846 following this pop then the if statement might
11847 be using some of the registers being popped which
11848 would destory the contents of the register so
11849 we need to check for this condition and handle it */
11851 ic->next->op == IFX &&
11852 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11853 genIfx (ic->next, ic);
11871 genEndFunction (ic);
11891 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11908 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11912 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11919 /* note these two are xlated by algebraic equivalence
11920 in decorateType() in SDCCast.c */
11921 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11922 "got '>=' or '<=' shouldn't have come here");
11926 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11938 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11942 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11946 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11982 genRightShift (ic);
11985 case GET_VALUE_AT_ADDRESS:
11987 hasInc (IC_LEFT (ic), ic,
11988 getSize (operandType (IC_RESULT (ic)))),
11989 ifxForOp (IC_RESULT (ic), ic) );
11993 if (POINTER_SET (ic))
11995 hasInc (IC_RESULT (ic), ic,
11996 getSize (operandType (IC_RIGHT (ic)))));
12022 addSet (&_G.sendSet, ic);
12025 case DUMMY_READ_VOLATILE:
12034 genEndCritical (ic);
12046 _G.current_iCode = NULL;
12048 /* now we are ready to call the
12049 peep hole optimizer */
12050 if (!options.nopeep)
12051 peepHole (&lineHead);
12053 /* now do the actual printing */
12054 printLine (lineHead, codeOutBuf);