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.verboseAsm) {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;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 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 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
958 aop->size = sym->ruonly ? 1 : 0;
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 sym->aop = op->aop = 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 sym->aop = op->aop = 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 if (!OP_SYMBOL (result)->ruonly)
1843 aopPut (result, "c", 0);
1847 emitcode ("clr", "a");
1848 emitcode ("rlc", "a");
1853 /*-----------------------------------------------------------------*/
1854 /* toBoolean - emit code for orl a,operator(sizeop) */
1855 /*-----------------------------------------------------------------*/
1857 toBoolean (operand * oper)
1859 int size = AOP_SIZE (oper) - 1;
1861 bool AccUsed = FALSE;
1864 while (!AccUsed && size--)
1866 AccUsed |= aopGetUsesAcc(oper, offset++);
1869 size = AOP_SIZE (oper) - 1;
1871 MOVA (aopGet (oper, 0, FALSE, FALSE));
1872 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1875 emitcode("mov", "b,a");
1878 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1879 emitcode ("orl", "b,a");
1881 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1882 emitcode ("orl", "a,b");
1889 emitcode ("orl", "a,%s",
1890 aopGet (oper, offset++, FALSE, FALSE));
1895 /*-----------------------------------------------------------------*/
1896 /* toCarry - make boolean and move into carry */
1897 /*-----------------------------------------------------------------*/
1899 toCarry (operand * oper)
1901 /* if the operand is a literal then
1902 we know what the value is */
1903 if (AOP_TYPE (oper) == AOP_LIT)
1905 if ((int) operandLitValue (oper))
1910 else if (AOP_TYPE (oper) == AOP_CRY)
1912 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1916 /* or the operand into a */
1918 /* set C, if a >= 1 */
1919 emitcode ("add", "a,#0xff");
1923 /*-----------------------------------------------------------------*/
1924 /* assignBit - assign operand to bit operand */
1925 /*-----------------------------------------------------------------*/
1927 assignBit (operand * result, operand * right)
1929 /* if the right side is a literal then
1930 we know what the value is */
1931 if (AOP_TYPE (right) == AOP_LIT)
1933 if ((int) operandLitValue (right))
1934 aopPut (result, one, 0);
1936 aopPut (result, zero, 0);
1941 aopPut (result, "c", 0);
1946 /*-------------------------------------------------------------------*/
1947 /* xch_a_aopGet - for exchanging acc with value of the aop */
1948 /*-------------------------------------------------------------------*/
1950 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1954 if (aopGetUsesAcc (oper, offset))
1956 emitcode("mov", "b,a");
1957 MOVA (aopGet (oper, offset, bit16, dname));
1958 emitcode("xch", "a,b");
1959 aopPut (oper, "a", offset);
1960 emitcode("xch", "a,b");
1965 l = aopGet (oper, offset, bit16, dname);
1966 emitcode("xch", "a,%s", l);
1972 /*-----------------------------------------------------------------*/
1973 /* genNot - generate code for ! operation */
1974 /*-----------------------------------------------------------------*/
1980 D (emitcode (";", "genNot"));
1982 /* assign asmOps to operand & result */
1983 aopOp (IC_LEFT (ic), ic, FALSE);
1984 aopOp (IC_RESULT (ic), ic, TRUE);
1986 /* if in bit space then a special case */
1987 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1989 /* if left==result then cpl bit */
1990 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1992 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997 emitcode ("cpl", "c");
1998 outBitC (IC_RESULT (ic));
2003 toBoolean (IC_LEFT (ic));
2005 /* set C, if a == 0 */
2006 tlbl = newiTempLabel (NULL);
2007 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2009 outBitC (IC_RESULT (ic));
2012 /* release the aops */
2013 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2014 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2018 /*-----------------------------------------------------------------*/
2019 /* genCpl - generate code for complement */
2020 /*-----------------------------------------------------------------*/
2027 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2029 D(emitcode (";", "genCpl"));
2031 /* assign asmOps to operand & result */
2032 aopOp (IC_LEFT (ic), ic, FALSE);
2033 aopOp (IC_RESULT (ic), ic, TRUE);
2035 /* special case if in bit space */
2036 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2040 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2041 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2043 /* promotion rules are responsible for this strange result:
2044 bit -> int -> ~int -> bit
2045 uchar -> int -> ~int -> bit
2047 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2051 tlbl=newiTempLabel(NULL);
2052 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2053 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2054 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2055 IS_AOP_PREG (IC_LEFT (ic)))
2057 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2062 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2065 outBitC (IC_RESULT(ic));
2069 size = AOP_SIZE (IC_RESULT (ic));
2072 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2074 emitcode ("cpl", "a");
2075 aopPut (IC_RESULT (ic), "a", offset++);
2080 /* release the aops */
2081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2082 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2085 /*-----------------------------------------------------------------*/
2086 /* genUminusFloat - unary minus for floating points */
2087 /*-----------------------------------------------------------------*/
2089 genUminusFloat (operand * op, operand * result)
2091 int size, offset = 0;
2094 D (emitcode (";", "genUminusFloat"));
2096 /* for this we just copy and then flip the bit */
2098 size = AOP_SIZE (op) - 1;
2103 aopGet (op, offset, FALSE, FALSE),
2108 l = aopGet (op, offset, FALSE, FALSE);
2111 emitcode ("cpl", "acc.7");
2112 aopPut (result, "a", offset);
2115 /*-----------------------------------------------------------------*/
2116 /* genUminus - unary minus code generation */
2117 /*-----------------------------------------------------------------*/
2119 genUminus (iCode * ic)
2124 D (emitcode (";", "genUminus"));
2127 aopOp (IC_LEFT (ic), ic, FALSE);
2128 aopOp (IC_RESULT (ic), ic, TRUE);
2130 /* if both in bit space then special
2132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2133 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2136 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2137 emitcode ("cpl", "c");
2138 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2142 optype = operandType (IC_LEFT (ic));
2144 /* if float then do float stuff */
2145 if (IS_FLOAT (optype))
2147 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2151 /* otherwise subtract from zero */
2152 size = AOP_SIZE (IC_LEFT (ic));
2156 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2157 if (!strcmp (l, "a"))
2161 emitcode ("cpl", "a");
2162 emitcode ("addc", "a,#0");
2168 emitcode ("clr", "a");
2169 emitcode ("subb", "a,%s", l);
2171 aopPut (IC_RESULT (ic), "a", offset++);
2174 /* if any remaining bytes in the result */
2175 /* we just need to propagate the sign */
2176 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2178 emitcode ("rlc", "a");
2179 emitcode ("subb", "a,acc");
2181 aopPut (IC_RESULT (ic), "a", offset++);
2185 /* release the aops */
2186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2187 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2190 /*-----------------------------------------------------------------*/
2191 /* saveRegisters - will look for a call and save the registers */
2192 /*-----------------------------------------------------------------*/
2194 saveRegisters (iCode * lic)
2201 for (ic = lic; ic; ic = ic->next)
2202 if (ic->op == CALL || ic->op == PCALL)
2207 fprintf (stderr, "found parameter push with no function call\n");
2211 /* if the registers have been saved already or don't need to be then
2215 if (IS_SYMOP(IC_LEFT(ic)) &&
2216 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2217 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2220 /* save the registers in use at this time but skip the
2221 ones for the result */
2222 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2223 mcs51_rUmaskForOp (IC_RESULT(ic)));
2226 if (options.useXstack)
2228 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2229 int nBits = bitVectnBitsOn (rsavebits);
2230 int count = bitVectnBitsOn (rsave);
2234 count = count - nBits + 1;
2235 /* remove all but the first bits as they are pushed all at once */
2236 rsave = bitVectCplAnd (rsave, rsavebits);
2237 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2239 freeBitVect (rsavebits);
2243 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2244 if (reg->type == REG_BIT)
2246 emitcode ("mov", "a,%s", reg->base);
2250 emitcode ("mov", "a,%s", reg->name);
2252 emitcode ("mov", "r0,%s", spname);
2253 emitcode ("inc", "%s", spname);// allocate before use
2254 emitcode ("movx", "@r0,a");
2255 if (bitVectBitValue (rsave, R0_IDX))
2256 emitcode ("mov", "r0,a");
2258 else if (count != 0)
2260 if (bitVectBitValue (rsave, R0_IDX))
2262 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2264 emitcode ("mov", "r0,%s", spname);
2266 emitcode ("add", "a,#%d", count);
2267 emitcode ("mov", "%s,a", spname);
2268 for (i = 0; i < mcs51_nRegs; i++)
2270 if (bitVectBitValue (rsave, i))
2272 regs * reg = REG_WITH_INDEX (i);
2275 emitcode ("pop", "acc");
2276 emitcode ("push", "acc");
2278 else if (reg->type == REG_BIT)
2280 emitcode ("mov", "a,%s", reg->base);
2284 emitcode ("mov", "a,%s", reg->name);
2286 emitcode ("movx", "@r0,a");
2289 emitcode ("inc", "r0");
2293 if (bitVectBitValue (rsave, R0_IDX))
2295 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2301 bool bits_pushed = FALSE;
2302 for (i = 0; i < mcs51_nRegs; i++)
2304 if (bitVectBitValue (rsave, i))
2306 bits_pushed = pushReg (i, bits_pushed);
2310 freeBitVect (rsave);
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRegisters - pop the pushed registers */
2315 /*-----------------------------------------------------------------*/
2317 unsaveRegisters (iCode * ic)
2322 /* restore the registers in use at this time but skip the
2323 ones for the result */
2324 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2325 mcs51_rUmaskForOp (IC_RESULT(ic)));
2327 if (options.useXstack)
2329 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2330 int nBits = bitVectnBitsOn (rsavebits);
2331 int count = bitVectnBitsOn (rsave);
2335 count = count - nBits + 1;
2336 /* remove all but the first bits as they are popped all at once */
2337 rsave = bitVectCplAnd (rsave, rsavebits);
2338 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2340 freeBitVect (rsavebits);
2344 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2345 emitcode ("mov", "r0,%s", spname);
2346 emitcode ("dec", "r0");
2347 emitcode ("movx", "a,@r0");
2348 if (reg->type == REG_BIT)
2350 emitcode ("mov", "%s,a", reg->base);
2354 emitcode ("mov", "%s,a", reg->name);
2356 emitcode ("dec", "%s", spname);
2358 else if (count != 0)
2360 emitcode ("mov", "r0,%s", spname);
2361 for (i = mcs51_nRegs; i >= 0; i--)
2363 if (bitVectBitValue (rsave, i))
2365 regs * reg = REG_WITH_INDEX (i);
2366 emitcode ("dec", "r0");
2367 emitcode ("movx", "a,@r0");
2370 emitcode ("push", "acc");
2372 else if (reg->type == REG_BIT)
2374 emitcode ("mov", "%s,a", reg->base);
2378 emitcode ("mov", "%s,a", reg->name);
2382 emitcode ("mov", "%s,r0", spname);
2383 if (bitVectBitValue (rsave, R0_IDX))
2385 emitcode ("pop", "ar0");
2391 bool bits_popped = FALSE;
2392 for (i = mcs51_nRegs; i >= 0; i--)
2394 if (bitVectBitValue (rsave, i))
2396 bits_popped = popReg (i, bits_popped);
2400 freeBitVect (rsave);
2404 /*-----------------------------------------------------------------*/
2406 /*-----------------------------------------------------------------*/
2408 pushSide (operand * oper, int size)
2413 char *l = aopGet (oper, offset++, FALSE, TRUE);
2414 if (AOP_TYPE (oper) != AOP_REG &&
2415 AOP_TYPE (oper) != AOP_DIR &&
2419 emitcode ("push", "acc");
2423 emitcode ("push", "%s", l);
2428 /*-----------------------------------------------------------------*/
2429 /* assignResultValue - also indicates if acc is in use afterwards */
2430 /*-----------------------------------------------------------------*/
2432 assignResultValue (operand * oper, operand * func)
2435 int size = AOP_SIZE (oper);
2436 bool accuse = FALSE;
2437 bool pushedA = FALSE;
2439 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2445 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2447 emitcode ("push", "acc");
2452 if ((offset == 3) && pushedA)
2453 emitcode ("pop", "acc");
2454 accuse |= aopPut (oper, fReturn[offset], offset);
2461 /*-----------------------------------------------------------------*/
2462 /* genXpush - pushes onto the external stack */
2463 /*-----------------------------------------------------------------*/
2465 genXpush (iCode * ic)
2467 asmop *aop = newAsmop (0);
2469 int size, offset = 0;
2471 D (emitcode (";", "genXpush"));
2473 aopOp (IC_LEFT (ic), ic, FALSE);
2474 r = getFreePtr (ic, &aop, FALSE);
2476 size = AOP_SIZE (IC_LEFT (ic));
2480 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2481 emitcode ("mov", "%s,%s", r->name, spname);
2482 emitcode ("inc", "%s", spname); // allocate space first
2483 emitcode ("movx", "@%s,a", r->name);
2487 // allocate space first
2488 emitcode ("mov", "%s,%s", r->name, spname);
2490 emitcode ("add", "a,#%d", size);
2491 emitcode ("mov", "%s,a", spname);
2495 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2496 emitcode ("movx", "@%s,a", r->name);
2497 emitcode ("inc", "%s", r->name);
2501 freeAsmop (NULL, aop, ic, TRUE);
2502 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2505 /*-----------------------------------------------------------------*/
2506 /* genIpush - generate code for pushing this gets a little complex */
2507 /*-----------------------------------------------------------------*/
2509 genIpush (iCode * ic)
2511 int size, offset = 0;
2515 D (emitcode (";", "genIpush"));
2517 /* if this is not a parm push : ie. it is spill push
2518 and spill push is always done on the local stack */
2522 /* and the item is spilt then do nothing */
2523 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2526 aopOp (IC_LEFT (ic), ic, FALSE);
2527 size = AOP_SIZE (IC_LEFT (ic));
2528 /* push it on the stack */
2531 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2537 emitcode ("push", "%s", l);
2542 /* this is a parameter push: in this case we call
2543 the routine to find the call and save those
2544 registers that need to be saved */
2547 /* if use external stack then call the external
2548 stack pushing routine */
2549 if (options.useXstack)
2555 /* then do the push */
2556 aopOp (IC_LEFT (ic), ic, FALSE);
2558 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2559 size = AOP_SIZE (IC_LEFT (ic));
2563 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2564 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2565 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2567 if (strcmp (l, prev) || *l == '@')
2569 emitcode ("push", "acc");
2573 emitcode ("push", "%s", l);
2578 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2581 /*-----------------------------------------------------------------*/
2582 /* genIpop - recover the registers: can happen only for spilling */
2583 /*-----------------------------------------------------------------*/
2585 genIpop (iCode * ic)
2589 D (emitcode (";", "genIpop"));
2591 /* if the temp was not pushed then */
2592 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2595 aopOp (IC_LEFT (ic), ic, FALSE);
2596 size = AOP_SIZE (IC_LEFT (ic));
2597 offset = (size - 1);
2600 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2604 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2607 /*-----------------------------------------------------------------*/
2608 /* saveRBank - saves an entire register bank on the stack */
2609 /*-----------------------------------------------------------------*/
2611 saveRBank (int bank, iCode * ic, bool pushPsw)
2614 int count = 8 + (pushPsw ? 1 : 0);
2618 if (options.useXstack)
2622 /* Assume r0 is available for use. */
2623 r = REG_WITH_INDEX (R0_IDX);
2628 r = getFreePtr (ic, &aop, FALSE);
2630 // allocate space first
2631 emitcode ("mov", "%s,%s", r->name, spname);
2633 emitcode ("add", "a,#%d", count);
2634 emitcode ("mov", "%s,a", spname);
2637 for (i = 0; i < 8; i++)
2639 if (options.useXstack)
2641 emitcode ("mov", "a,(%s+%d)",
2642 regs8051[i].base, 8 * bank + regs8051[i].offset);
2643 emitcode ("movx", "@%s,a", r->name);
2645 emitcode ("inc", "%s", r->name);
2648 emitcode ("push", "(%s+%d)",
2649 regs8051[i].base, 8 * bank + regs8051[i].offset);
2654 if (options.useXstack)
2656 emitcode ("mov", "a,psw");
2657 emitcode ("movx", "@%s,a", r->name);
2661 emitcode ("push", "psw");
2664 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2669 freeAsmop (NULL, aop, ic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* unsaveRBank - restores the register bank from stack */
2680 /*-----------------------------------------------------------------*/
2682 unsaveRBank (int bank, iCode * ic, bool popPsw)
2688 if (options.useXstack)
2692 /* Assume r0 is available for use. */
2693 r = REG_WITH_INDEX (R0_IDX);;
2698 r = getFreePtr (ic, &aop, FALSE);
2700 emitcode ("mov", "%s,%s", r->name, spname);
2705 if (options.useXstack)
2707 emitcode ("dec", "%s", r->name);
2708 emitcode ("movx", "a,@%s", r->name);
2709 emitcode ("mov", "psw,a");
2713 emitcode ("pop", "psw");
2717 for (i = 7; i >= 0; i--)
2719 if (options.useXstack)
2721 emitcode ("dec", "%s", r->name);
2722 emitcode ("movx", "a,@%s", r->name);
2723 emitcode ("mov", "(%s+%d),a",
2724 regs8051[i].base, 8 * bank + regs8051[i].offset);
2728 emitcode ("pop", "(%s+%d)",
2729 regs8051[i].base, 8 * bank + regs8051[i].offset);
2733 if (options.useXstack)
2735 emitcode ("mov", "%s,%s", spname, r->name);
2740 freeAsmop (NULL, aop, ic, TRUE);
2744 /*-----------------------------------------------------------------*/
2745 /* genSend - gen code for SEND */
2746 /*-----------------------------------------------------------------*/
2747 static void genSend(set *sendSet)
2752 /* first we do all bit parameters */
2753 for (sic = setFirstItem (sendSet); sic;
2754 sic = setNextItem (sendSet))
2756 if (sic->argreg > 12)
2758 int bit = sic->argreg-13;
2760 aopOp (IC_LEFT (sic), sic, FALSE);
2762 /* if left is a literal then
2763 we know what the value is */
2764 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2766 if (((int) operandLitValue (IC_LEFT (sic))))
2767 emitcode ("setb", "b[%d]", bit);
2769 emitcode ("clr", "b[%d]", bit);
2774 toCarry (IC_LEFT (sic));
2775 emitcode ("mov", "b[%d],c", bit);
2780 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2786 saveRegisters (setFirstItem (sendSet));
2787 emitcode ("mov", "bits,b");
2790 /* then we do all other parameters */
2791 for (sic = setFirstItem (sendSet); sic;
2792 sic = setNextItem (sendSet))
2794 if (sic->argreg <= 12)
2796 int size, offset = 0;
2797 aopOp (IC_LEFT (sic), sic, FALSE);
2798 size = AOP_SIZE (IC_LEFT (sic));
2800 if (sic->argreg == 1)
2804 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2805 if (strcmp (l, fReturn[offset]))
2807 emitcode ("mov", "%s,%s", fReturn[offset], l);
2816 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2817 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2821 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2826 /*-----------------------------------------------------------------*/
2827 /* selectRegBank - emit code to select the register bank */
2828 /*-----------------------------------------------------------------*/
2830 selectRegBank (short bank, bool keepFlags)
2832 /* if f.e. result is in carry */
2835 emitcode ("anl", "psw,#0xE7");
2837 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2841 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2845 /*-----------------------------------------------------------------*/
2846 /* genCall - generates a call statement */
2847 /*-----------------------------------------------------------------*/
2849 genCall (iCode * ic)
2853 // bool restoreBank = FALSE;
2854 bool swapBanks = FALSE;
2855 bool accuse = FALSE;
2856 bool accPushed = FALSE;
2857 bool resultInF0 = FALSE;
2858 bool assignResultGenerated = FALSE;
2860 D (emitcode (";", "genCall"));
2862 dtype = operandType (IC_LEFT (ic));
2863 etype = getSpec(dtype);
2864 /* if send set is not empty then assign */
2867 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2868 genSend(reverseSet(_G.sendSet));
2870 genSend(_G.sendSet);
2875 /* if we are calling a not _naked function that is not using
2876 the same register bank then we need to save the
2877 destination registers on the stack */
2878 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2879 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2880 !IFFUNC_ISISR (dtype))
2885 /* if caller saves & we have not saved then */
2891 emitcode ("mov", "psw,#0x%02x",
2892 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2896 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2898 if (IFFUNC_CALLEESAVES(dtype))
2900 werror (E_BANKED_WITH_CALLEESAVES);
2904 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2905 OP_SYMBOL (IC_LEFT (ic))->rname :
2906 OP_SYMBOL (IC_LEFT (ic))->name);
2908 emitcode ("mov", "r0,#%s", l);
2909 emitcode ("mov", "r1,#(%s >> 8)", l);
2910 emitcode ("mov", "r2,#(%s >> 16)", l);
2911 emitcode ("lcall", "__sdcc_banked_call");
2916 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2917 OP_SYMBOL (IC_LEFT (ic))->rname :
2918 OP_SYMBOL (IC_LEFT (ic))->name));
2923 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2926 /* if we need assign a result value */
2927 if ((IS_ITEMP (IC_RESULT (ic)) &&
2928 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2929 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2930 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2931 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2932 IS_TRUE_SYMOP (IC_RESULT (ic)))
2936 aopOp (IC_RESULT (ic), ic, FALSE);
2939 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2940 assignResultGenerated = TRUE;
2942 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2945 /* adjust the stack for parameters if required */
2949 if (ic->parmBytes > 3)
2953 emitcode ("push", "acc");
2956 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2957 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2958 !assignResultGenerated)
2960 emitcode ("mov", "F0,c");
2964 emitcode ("mov", "a,%s", spname);
2965 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2966 emitcode ("mov", "%s,a", spname);
2968 /* unsaveRegisters from xstack needs acc, but */
2969 /* unsaveRegisters from stack needs this popped */
2970 if (accPushed && !options.useXstack)
2972 emitcode ("pop", "acc");
2977 for (i = 0; i < ic->parmBytes; i++)
2978 emitcode ("dec", "%s", spname);
2981 /* if we had saved some registers then unsave them */
2982 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2984 if (accuse && !accPushed && options.useXstack)
2986 /* xstack needs acc, but doesn't touch normal stack */
2987 emitcode ("push", "acc");
2990 unsaveRegisters (ic);
2993 // /* if register bank was saved then pop them */
2995 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2997 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3000 emitcode ("mov", "c,F0");
3002 aopOp (IC_RESULT (ic), ic, FALSE);
3003 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3008 emitcode ("pop", "acc");
3011 /*-----------------------------------------------------------------*/
3012 /* genPcall - generates a call by pointer statement */
3013 /*-----------------------------------------------------------------*/
3015 genPcall (iCode * ic)
3019 symbol *rlbl = newiTempLabel (NULL);
3020 // bool restoreBank=FALSE;
3021 bool swapBanks = FALSE;
3022 bool resultInF0 = FALSE;
3024 D (emitcode (";", "genPcall"));
3026 dtype = operandType (IC_LEFT (ic))->next;
3027 etype = getSpec(dtype);
3028 /* if caller saves & we have not saved then */
3032 /* if we are calling a not _naked function that is not using
3033 the same register bank then we need to save the
3034 destination registers on the stack */
3035 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3036 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3037 !IFFUNC_ISISR (dtype))
3039 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3040 // restoreBank=TRUE;
3042 // need caution message to user here
3045 if (IS_LITERAL (etype))
3047 /* if send set is not empty then assign */
3050 genSend(reverseSet(_G.sendSet));
3056 emitcode ("mov", "psw,#0x%02x",
3057 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3060 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3062 if (IFFUNC_CALLEESAVES (dtype))
3064 werror (E_BANKED_WITH_CALLEESAVES);
3068 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3070 emitcode ("mov", "r0,#%s", l);
3071 emitcode ("mov", "r1,#(%s >> 8)", l);
3072 emitcode ("mov", "r2,#(%s >> 16)", l);
3073 emitcode ("lcall", "__sdcc_banked_call");
3078 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3083 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3085 if (IFFUNC_CALLEESAVES (dtype))
3087 werror (E_BANKED_WITH_CALLEESAVES);
3091 aopOp (IC_LEFT (ic), ic, FALSE);
3095 /* what if aopGet needs r0 or r1 ??? */
3096 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3097 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3098 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3102 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3103 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3104 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3105 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3110 /* if send set is not empty then assign */
3113 genSend(reverseSet(_G.sendSet));
3119 emitcode ("mov", "psw,#0x%02x",
3120 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3124 emitcode ("lcall", "__sdcc_banked_call");
3127 else if (_G.sendSet)
3129 /* push the return address on to the stack */
3130 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3131 emitcode ("push", "acc");
3132 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3133 emitcode ("push", "acc");
3135 /* now push the calling address */
3136 aopOp (IC_LEFT (ic), ic, FALSE);
3138 pushSide (IC_LEFT (ic), FPTRSIZE);
3140 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3142 /* if send set is not empty the assign */
3145 genSend(reverseSet(_G.sendSet));
3151 emitcode ("mov", "psw,#0x%02x",
3152 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3156 emitcode ("ret", "");
3159 else /* the send set is empty */
3162 /* now get the calling address into dptr */
3163 aopOp (IC_LEFT (ic), ic, FALSE);
3165 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3166 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3168 emitcode ("mov", "r0,%s", l);
3169 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3170 emitcode ("mov", "dph,%s", l);
3171 emitcode ("mov", "dpl,r0");
3175 emitcode ("mov", "dpl,%s", l);
3176 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3177 emitcode ("mov", "dph,%s", l);
3180 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3184 emitcode ("mov", "psw,#0x%02x",
3185 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3189 emitcode ("lcall", "__sdcc_call_dptr");
3194 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3197 /* if we need assign a result value */
3198 if ((IS_ITEMP (IC_RESULT (ic)) &&
3199 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3200 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3201 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3202 IS_TRUE_SYMOP (IC_RESULT (ic)))
3206 aopOp (IC_RESULT (ic), ic, FALSE);
3209 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3211 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3214 /* adjust the stack for parameters if required */
3218 if (ic->parmBytes > 3)
3220 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3221 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3223 emitcode ("mov", "F0,c");
3227 emitcode ("mov", "a,%s", spname);
3228 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3229 emitcode ("mov", "%s,a", spname);
3232 for (i = 0; i < ic->parmBytes; i++)
3233 emitcode ("dec", "%s", spname);
3236 // /* if register bank was saved then unsave them */
3238 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3240 /* if we had saved some registers then unsave them */
3241 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3242 unsaveRegisters (ic);
3244 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3247 emitcode ("mov", "c,F0");
3249 aopOp (IC_RESULT (ic), ic, FALSE);
3250 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3251 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3255 /*-----------------------------------------------------------------*/
3256 /* resultRemat - result is rematerializable */
3257 /*-----------------------------------------------------------------*/
3259 resultRemat (iCode * ic)
3261 if (SKIP_IC (ic) || ic->op == IFX)
3264 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3266 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3267 if (sym->remat && !POINTER_SET (ic))
3274 /*-----------------------------------------------------------------*/
3275 /* inExcludeList - return 1 if the string is in exclude Reg list */
3276 /*-----------------------------------------------------------------*/
3278 regsCmp(void *p1, void *p2)
3280 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3284 inExcludeList (char *s)
3286 const char *p = setFirstItem(options.excludeRegsSet);
3288 if (p == NULL || STRCASECMP(p, "none") == 0)
3292 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3295 /*-----------------------------------------------------------------*/
3296 /* genFunction - generated code for function entry */
3297 /*-----------------------------------------------------------------*/
3299 genFunction (iCode * ic)
3301 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3303 bool switchedPSW = FALSE;
3304 int calleesaves_saved_register = -1;
3305 int stackAdjust = sym->stack;
3306 int accIsFree = sym->recvSize < 4;
3307 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3308 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3311 /* create the function header */
3312 emitcode (";", "-----------------------------------------");
3313 emitcode (";", " function %s", sym->name);
3314 emitcode (";", "-----------------------------------------");
3316 emitcode ("", "%s:", sym->rname);
3317 lineCurr->isLabel = 1;
3318 ftype = operandType (IC_LEFT (ic));
3319 _G.currentFunc = sym;
3321 if (IFFUNC_ISNAKED(ftype))
3323 emitcode(";", "naked function: no prologue.");
3327 /* here we need to generate the equates for the
3328 register bank if required */
3329 if (FUNC_REGBANK (ftype) != rbank)
3333 rbank = FUNC_REGBANK (ftype);
3334 for (i = 0; i < mcs51_nRegs; i++)
3336 if (regs8051[i].type != REG_BIT)
3338 if (strcmp (regs8051[i].base, "0") == 0)
3339 emitcode ("", "%s = 0x%02x",
3341 8 * rbank + regs8051[i].offset);
3343 emitcode ("", "%s = %s + 0x%02x",
3346 8 * rbank + regs8051[i].offset);
3351 /* if this is an interrupt service routine then
3352 save acc, b, dpl, dph */
3353 if (IFFUNC_ISISR (sym->type))
3357 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3358 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3360 emitcode ("push", "bits");
3363 freeBitVect (rsavebits);
3365 if (!inExcludeList ("acc"))
3366 emitcode ("push", "acc");
3367 if (!inExcludeList ("b"))
3368 emitcode ("push", "b");
3369 if (!inExcludeList ("dpl"))
3370 emitcode ("push", "dpl");
3371 if (!inExcludeList ("dph"))
3372 emitcode ("push", "dph");
3373 /* if this isr has no bank i.e. is going to
3374 run with bank 0 , then we need to save more
3376 if (!FUNC_REGBANK (sym->type))
3380 /* if this function does not call any other
3381 function then we can be economical and
3382 save only those registers that are used */
3383 if (!IFFUNC_HASFCALL(sym->type))
3385 /* if any registers used */
3388 /* save the registers used */
3389 for (i = 0; i < sym->regsUsed->size; i++)
3391 if (bitVectBitValue (sym->regsUsed, i))
3398 /* this function has a function call. We cannot
3399 determine register usage so we will have to push the
3401 saveRBank (0, ic, FALSE);
3402 if (options.parms_in_bank1) {
3403 for (i=0; i < 8 ; i++ ) {
3404 emitcode ("push","%s",rb1regs[i]);
3411 /* This ISR uses a non-zero bank.
3413 * We assume that the bank is available for our
3416 * However, if this ISR calls a function which uses some
3417 * other bank, we must save that bank entirely.
3419 unsigned long banksToSave = 0;
3421 if (IFFUNC_HASFCALL(sym->type))
3424 #define MAX_REGISTER_BANKS 4
3429 for (i = ic; i; i = i->next)
3431 if (i->op == ENDFUNCTION)
3433 /* we got to the end OK. */
3441 dtype = operandType (IC_LEFT(i));
3443 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3445 /* Mark this bank for saving. */
3446 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3448 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3452 banksToSave |= (1 << FUNC_REGBANK(dtype));
3455 /* And note that we don't need to do it in
3463 /* This is a mess; we have no idea what
3464 * register bank the called function might
3467 * The only thing I can think of to do is
3468 * throw a warning and hope.
3470 werror(W_FUNCPTR_IN_USING_ISR);
3474 if (banksToSave && options.useXstack)
3476 /* Since we aren't passing it an ic,
3477 * saveRBank will assume r0 is available to abuse.
3479 * So switch to our (trashable) bank now, so
3480 * the caller's R0 isn't trashed.
3482 emitcode ("push", "psw");
3483 emitcode ("mov", "psw,#0x%02x",
3484 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3488 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3490 if (banksToSave & (1 << ix))
3492 saveRBank(ix, NULL, FALSE);
3496 // TODO: this needs a closer look
3497 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3500 /* Set the register bank to the desired value if nothing else */
3501 /* has done so yet. */
3504 emitcode ("push", "psw");
3505 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3510 /* This is a non-ISR function. The caller has already switched register */
3511 /* banks, if necessary, so just handle the callee-saves option. */
3513 /* if callee-save to be used for this function
3514 then save the registers being used in this function */
3515 if (IFFUNC_CALLEESAVES(sym->type))
3519 /* if any registers used */
3522 bool bits_pushed = FALSE;
3523 /* save the registers used */
3524 for (i = 0; i < sym->regsUsed->size; i++)
3526 if (bitVectBitValue (sym->regsUsed, i))
3528 /* remember one saved register for later usage */
3529 if (calleesaves_saved_register < 0)
3530 calleesaves_saved_register = i;
3531 bits_pushed = pushReg (i, bits_pushed);
3541 if (options.useXstack)
3543 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3545 emitcode ("mov", "r0,%s", spname);
3546 emitcode ("inc", "%s", spname);
3547 emitcode ("xch", "a,_bpx");
3548 emitcode ("movx", "@r0,a");
3549 emitcode ("inc", "r0");
3550 emitcode ("mov", "a,r0");
3551 emitcode ("xch", "a,_bpx");
3555 emitcode ("push", "_bp"); /* save the callers stack */
3556 emitcode ("mov", "_bp,sp");
3561 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3563 /* set up the stack */
3564 emitcode ("push", "_bp"); /* save the callers stack */
3565 emitcode ("mov", "_bp,sp");
3570 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3571 /* before setting up the stack frame completely. */
3572 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3574 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3578 if (rsym && rsym->regType == REG_CND)
3580 if (rsym && (rsym->accuse || rsym->ruonly))
3582 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3583 rsym = rsym->usl.spillLoc;
3586 /* If the RECEIVE operand immediately spills to the first entry on the */
3587 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3588 /* rather than the usual @r0/r1 machinations. */
3589 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3593 _G.current_iCode = ric;
3594 D(emitcode (";", "genReceive"));
3595 for (ofs=0; ofs < sym->recvSize; ofs++)
3597 if (!strcmp (fReturn[ofs], "a"))
3598 emitcode ("push", "acc");
3600 emitcode ("push", fReturn[ofs]);
3602 stackAdjust -= sym->recvSize;
3605 assert (stackAdjust>=0);
3608 _G.current_iCode = ic;
3612 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3613 /* to free up the accumulator. */
3614 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3618 _G.current_iCode = ric;
3619 D(emitcode (";", "genReceive"));
3620 for (ofs=0; ofs < sym->recvSize; ofs++)
3622 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3624 _G.current_iCode = ic;
3630 /* adjust the stack for the function */
3633 int i = stackAdjust;
3635 werror (W_STACK_OVERFLOW, sym->name);
3637 if (i > 3 && accIsFree)
3639 emitcode ("mov", "a,sp");
3640 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3641 emitcode ("mov", "sp,a");
3645 /* The accumulator is not free, so we will need another register */
3646 /* to clobber. No need to worry about a possible conflict with */
3647 /* the above early RECEIVE optimizations since they would have */
3648 /* freed the accumulator if they were generated. */
3650 if (IFFUNC_CALLEESAVES(sym->type))
3652 /* if it's a callee-saves function we need a saved register */
3653 if (calleesaves_saved_register >= 0)
3655 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3656 emitcode ("mov", "a,sp");
3657 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3658 emitcode ("mov", "sp,a");
3659 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3662 /* do it the hard way */
3664 emitcode ("inc", "sp");
3668 /* not callee-saves, we can clobber r0 */
3669 emitcode ("mov", "r0,a");
3670 emitcode ("mov", "a,sp");
3671 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3672 emitcode ("mov", "sp,a");
3673 emitcode ("mov", "a,r0");
3678 emitcode ("inc", "sp");
3683 char i = ((char) sym->xstack & 0xff);
3685 if (i > 3 && accIsFree)
3687 emitcode ("mov", "a,_spx");
3688 emitcode ("add", "a,#0x%02x", i & 0xff);
3689 emitcode ("mov", "_spx,a");
3693 emitcode ("push", "acc");
3694 emitcode ("mov", "a,_spx");
3695 emitcode ("add", "a,#0x%02x", i & 0xff);
3696 emitcode ("mov", "_spx,a");
3697 emitcode ("pop", "acc");
3702 emitcode ("inc", "_spx");
3706 /* if critical function then turn interrupts off */
3707 if (IFFUNC_ISCRITICAL (ftype))
3709 symbol *tlbl = newiTempLabel (NULL);
3710 emitcode ("setb", "c");
3711 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3712 emitcode ("clr", "c");
3714 emitcode ("push", "psw"); /* save old ea via c in psw */
3718 /*-----------------------------------------------------------------*/
3719 /* genEndFunction - generates epilogue for functions */
3720 /*-----------------------------------------------------------------*/
3722 genEndFunction (iCode * ic)
3724 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3725 lineNode *lnp = lineCurr;
3727 bitVect *regsUsedPrologue;
3728 bitVect *regsUnneeded;
3731 _G.currentFunc = NULL;
3732 if (IFFUNC_ISNAKED(sym->type))
3734 emitcode(";", "naked function: no epilogue.");
3735 if (options.debug && currFunc)
3736 debugFile->writeEndFunction (currFunc, ic, 0);
3740 if (IFFUNC_ISCRITICAL (sym->type))
3742 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3744 emitcode ("rlc", "a"); /* save c in a */
3745 emitcode ("pop", "psw"); /* restore ea via c in psw */
3746 emitcode ("mov", "ea,c");
3747 emitcode ("rrc", "a"); /* restore c from a */
3751 emitcode ("pop", "psw"); /* restore ea via c in psw */
3752 emitcode ("mov", "ea,c");
3756 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3758 if (options.useXstack)
3762 emitcode ("mov", "sp,_bp");
3763 emitcode ("pop", "_bp");
3765 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3767 emitcode ("xch", "a,_bpx");
3768 emitcode ("mov", "r0,a");
3769 emitcode ("dec", "r0");
3770 emitcode ("movx", "a,@r0");
3771 emitcode ("xch", "a,_bpx");
3772 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3775 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3778 emitcode ("mov", "sp,_bp");
3779 emitcode ("pop", "_bp");
3783 /* restore the register bank */
3784 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3786 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3787 || !options.useXstack)
3789 /* Special case of ISR using non-zero bank with useXstack
3792 emitcode ("pop", "psw");
3796 if (IFFUNC_ISISR (sym->type))
3800 /* now we need to restore the registers */
3801 /* if this isr has no bank i.e. is going to
3802 run with bank 0 , then we need to save more
3804 if (!FUNC_REGBANK (sym->type))
3807 /* if this function does not call any other
3808 function then we can be economical and
3809 save only those registers that are used */
3810 if (!IFFUNC_HASFCALL(sym->type))
3812 /* if any registers used */
3815 /* save the registers used */
3816 for (i = sym->regsUsed->size; i >= 0; i--)
3818 if (bitVectBitValue (sym->regsUsed, i))
3825 if (options.parms_in_bank1) {
3826 for (i = 7 ; i >= 0 ; i-- ) {
3827 emitcode ("pop","%s",rb1regs[i]);
3830 /* this function has a function call. We cannot
3831 determine register usage so we will have to pop the
3833 unsaveRBank (0, ic, FALSE);
3838 /* This ISR uses a non-zero bank.
3840 * Restore any register banks saved by genFunction
3843 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3846 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3848 if (savedBanks & (1 << ix))
3850 unsaveRBank(ix, NULL, FALSE);
3854 if (options.useXstack)
3856 /* Restore bank AFTER calling unsaveRBank,
3857 * since it can trash r0.
3859 emitcode ("pop", "psw");
3863 if (!inExcludeList ("dph"))
3864 emitcode ("pop", "dph");
3865 if (!inExcludeList ("dpl"))
3866 emitcode ("pop", "dpl");
3867 if (!inExcludeList ("b"))
3868 emitcode ("pop", "b");
3869 if (!inExcludeList ("acc"))
3870 emitcode ("pop", "acc");
3872 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3873 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3874 emitcode ("pop", "bits");
3875 freeBitVect (rsavebits);
3877 /* if debug then send end of function */
3878 if (options.debug && currFunc)
3880 debugFile->writeEndFunction (currFunc, ic, 1);
3883 emitcode ("reti", "");
3887 if (IFFUNC_CALLEESAVES(sym->type))
3891 /* if any registers used */
3894 /* save the registers used */
3895 for (i = sym->regsUsed->size; i >= 0; i--)
3897 if (bitVectBitValue (sym->regsUsed, i) ||
3898 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3899 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3902 else if (mcs51_ptrRegReq)
3904 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3905 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3910 /* if debug then send end of function */
3911 if (options.debug && currFunc)
3913 debugFile->writeEndFunction (currFunc, ic, 1);
3916 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3918 emitcode ("ljmp", "__sdcc_banked_ret");
3922 emitcode ("ret", "");
3926 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3929 /* If this was an interrupt handler using bank 0 that called another */
3930 /* function, then all registers must be saved; nothing to optimized. */
3931 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3932 && !FUNC_REGBANK(sym->type))
3935 /* There are no push/pops to optimize if not callee-saves or ISR */
3936 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3939 /* If there were stack parameters, we cannot optimize without also */
3940 /* fixing all of the stack offsets; this is too dificult to consider. */
3941 if (FUNC_HASSTACKPARM(sym->type))
3944 /* Compute the registers actually used */
3945 regsUsed = newBitVect (mcs51_nRegs);
3946 regsUsedPrologue = newBitVect (mcs51_nRegs);
3949 if (lnp->ic && lnp->ic->op == FUNCTION)
3950 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3952 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3954 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3955 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3962 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3963 && !bitVectBitValue (regsUsed, CND_IDX))
3965 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3966 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3967 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3968 bitVectUnSetBit (regsUsed, CND_IDX);
3971 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3973 /* If this was an interrupt handler that called another function */
3974 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3975 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3977 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3984 /* Remove the unneeded push/pops */
3985 regsUnneeded = newBitVect (mcs51_nRegs);
3988 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3990 if (!strncmp(lnp->line, "push", 4))
3992 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3993 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3995 connectLine (lnp->prev, lnp->next);
3996 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3999 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4001 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4002 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4004 connectLine (lnp->prev, lnp->next);
4005 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4012 for (idx = 0; idx < regsUnneeded->size; idx++)
4013 if (bitVectBitValue (regsUnneeded, idx))
4014 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4016 freeBitVect (regsUnneeded);
4017 freeBitVect (regsUsed);
4018 freeBitVect (regsUsedPrologue);
4021 /*-----------------------------------------------------------------*/
4022 /* genRet - generate code for return statement */
4023 /*-----------------------------------------------------------------*/
4027 int size, offset = 0, pushed = 0;
4029 D (emitcode (";", "genRet"));
4031 /* if we have no return value then
4032 just generate the "ret" */
4036 /* we have something to return then
4037 move the return value into place */
4038 aopOp (IC_LEFT (ic), ic, FALSE);
4039 size = AOP_SIZE (IC_LEFT (ic));
4041 if (IS_BIT(_G.currentFunc->etype))
4043 if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
4044 toCarry (IC_LEFT (ic));
4051 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4054 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4055 emitcode ("push", "%s", l);
4060 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4061 if (strcmp (fReturn[offset], l))
4062 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4069 if (strcmp (fReturn[pushed], "a"))
4070 emitcode ("pop", fReturn[pushed]);
4072 emitcode ("pop", "acc");
4075 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4078 /* generate a jump to the return label
4079 if the next is not the return statement */
4080 if (!(ic->next && ic->next->op == LABEL &&
4081 IC_LABEL (ic->next) == returnLabel))
4083 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4087 /*-----------------------------------------------------------------*/
4088 /* genLabel - generates a label */
4089 /*-----------------------------------------------------------------*/
4091 genLabel (iCode * ic)
4093 /* special case never generate */
4094 if (IC_LABEL (ic) == entryLabel)
4097 emitLabel (IC_LABEL (ic));
4100 /*-----------------------------------------------------------------*/
4101 /* genGoto - generates a ljmp */
4102 /*-----------------------------------------------------------------*/
4104 genGoto (iCode * ic)
4106 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4109 /*-----------------------------------------------------------------*/
4110 /* findLabelBackwards: walks back through the iCode chain looking */
4111 /* for the given label. Returns number of iCode instructions */
4112 /* between that label and given ic. */
4113 /* Returns zero if label not found. */
4114 /*-----------------------------------------------------------------*/
4116 findLabelBackwards (iCode * ic, int key)
4125 /* If we have any pushes or pops, we cannot predict the distance.
4126 I don't like this at all, this should be dealt with in the
4128 if (ic->op == IPUSH || ic->op == IPOP) {
4132 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4141 /*-----------------------------------------------------------------*/
4142 /* genPlusIncr :- does addition with increment if possible */
4143 /*-----------------------------------------------------------------*/
4145 genPlusIncr (iCode * ic)
4147 unsigned int icount;
4148 unsigned int size = getDataSize (IC_RESULT (ic));
4150 /* will try to generate an increment */
4151 /* if the right side is not a literal
4153 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4156 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4158 D(emitcode (";","genPlusIncr"));
4160 /* if increment >=16 bits in register or direct space */
4161 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4162 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4163 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4164 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4165 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4173 /* If the next instruction is a goto and the goto target
4174 * is < 10 instructions previous to this, we can generate
4175 * jumps straight to that target.
4177 if (ic->next && ic->next->op == GOTO
4178 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4179 && labelRange <= 10)
4181 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4182 tlbl = IC_LABEL (ic->next);
4187 tlbl = newiTempLabel (NULL);
4190 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4191 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4192 IS_AOP_PREG (IC_RESULT (ic)))
4193 emitcode ("cjne", "%s,#0x00,%05d$",
4194 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4198 emitcode ("clr", "a");
4199 emitcode ("cjne", "a,%s,%05d$",
4200 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4204 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208 IS_AOP_PREG (IC_RESULT (ic)))
4209 emitcode ("cjne", "%s,#0x00,%05d$",
4210 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4213 emitcode ("cjne", "a,%s,%05d$",
4214 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4217 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4222 IS_AOP_PREG (IC_RESULT (ic)))
4223 emitcode ("cjne", "%s,#0x00,%05d$",
4224 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4228 emitcode ("cjne", "a,%s,%05d$",
4229 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4232 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4242 /* if result is dptr */
4243 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4244 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4245 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4246 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4248 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4254 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4257 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4258 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4260 emitcode ("inc", "dptr");
4265 /* if the literal value of the right hand side
4266 is greater than 4 then it is not worth it */
4270 /* if the sizes are greater than 1 then we cannot */
4271 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4272 AOP_SIZE (IC_LEFT (ic)) > 1)
4275 /* we can if the aops of the left & result match or
4276 if they are in registers and the registers are the
4278 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4282 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4283 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4284 aopPut (IC_RESULT (ic), "a", 0);
4290 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4299 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4300 emitcode ("inc", "a");
4301 aopPut (IC_RESULT (ic), "a", 0);
4308 /*-----------------------------------------------------------------*/
4309 /* outBitAcc - output a bit in acc */
4310 /*-----------------------------------------------------------------*/
4312 outBitAcc (operand * result)
4314 symbol *tlbl = newiTempLabel (NULL);
4315 /* if the result is a bit */
4316 if (AOP_TYPE (result) == AOP_CRY)
4318 aopPut (result, "a", 0);
4322 emitcode ("jz", "%05d$", tlbl->key + 100);
4323 emitcode ("mov", "a,%s", one);
4329 /*-----------------------------------------------------------------*/
4330 /* genPlusBits - generates code for addition of two bits */
4331 /*-----------------------------------------------------------------*/
4333 genPlusBits (iCode * ic)
4335 D (emitcode (";", "genPlusBits"));
4337 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4338 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4340 symbol *lbl = newiTempLabel (NULL);
4341 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4342 emitcode ("cpl", "c");
4344 outBitC (IC_RESULT (ic));
4348 emitcode ("clr", "a");
4349 emitcode ("rlc", "a");
4350 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4351 emitcode ("addc", "a,%s", zero);
4352 outAcc (IC_RESULT (ic));
4357 /* This is the original version of this code.
4359 * This is being kept around for reference,
4360 * because I am not entirely sure I got it right...
4363 adjustArithmeticResult (iCode * ic)
4365 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4366 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4367 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4368 aopPut (IC_RESULT (ic),
4369 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4372 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4373 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4374 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4375 aopPut (IC_RESULT (ic),
4376 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4379 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4380 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4381 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4383 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4386 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4387 aopPut (IC_RESULT (ic), buffer, 2);
4391 /* This is the pure and virtuous version of this code.
4392 * I'm pretty certain it's right, but not enough to toss the old
4396 adjustArithmeticResult (iCode * ic)
4398 if (opIsGptr (IC_RESULT (ic)) &&
4399 opIsGptr (IC_LEFT (ic)) &&
4400 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4402 aopPut (IC_RESULT (ic),
4403 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4407 if (opIsGptr (IC_RESULT (ic)) &&
4408 opIsGptr (IC_RIGHT (ic)) &&
4409 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4411 aopPut (IC_RESULT (ic),
4412 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4416 if (opIsGptr (IC_RESULT (ic)) &&
4417 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4418 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4419 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4420 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4423 SNPRINTF (buffer, sizeof(buffer),
4424 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4425 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4430 /*-----------------------------------------------------------------*/
4431 /* genPlus - generates code for addition */
4432 /*-----------------------------------------------------------------*/
4434 genPlus (iCode * ic)
4436 int size, offset = 0;
4439 bool swappedLR = FALSE;
4440 operand *leftOp, *rightOp;
4443 D (emitcode (";", "genPlus"));
4445 /* special cases :- */
4447 aopOp (IC_LEFT (ic), ic, FALSE);
4448 aopOp (IC_RIGHT (ic), ic, FALSE);
4449 aopOp (IC_RESULT (ic), ic, TRUE);
4451 /* if literal, literal on the right or
4452 if left requires ACC or right is already
4454 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4455 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4456 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4458 operand *t = IC_RIGHT (ic);
4459 IC_RIGHT (ic) = IC_LEFT (ic);
4464 /* if both left & right are in bit
4466 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4467 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4473 /* if left in bit space & right literal */
4474 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4475 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4477 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4478 /* if result in bit space */
4479 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4481 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4482 emitcode ("cpl", "c");
4483 outBitC (IC_RESULT (ic));
4487 size = getDataSize (IC_RESULT (ic));
4490 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4491 emitcode ("addc", "a,%s", zero);
4492 aopPut (IC_RESULT (ic), "a", offset++);
4498 /* if I can do an increment instead
4499 of add then GOOD for ME */
4500 if (genPlusIncr (ic) == TRUE)
4503 size = getDataSize (IC_RESULT (ic));
4504 leftOp = IC_LEFT(ic);
4505 rightOp = IC_RIGHT(ic);
4508 /* if this is an add for an array access
4509 at a 256 byte boundary */
4511 && AOP_TYPE (op) == AOP_IMMD
4513 && IS_SPEC (OP_SYM_ETYPE (op))
4514 && SPEC_ABSA (OP_SYM_ETYPE (op))
4515 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4518 D(emitcode (";", "genPlus aligned array"));
4519 aopPut (IC_RESULT (ic),
4520 aopGet (rightOp, 0, FALSE, FALSE),
4523 if( 1 == getDataSize (IC_RIGHT (ic)) )
4525 aopPut (IC_RESULT (ic),
4526 aopGet (leftOp, 1, FALSE, FALSE),
4531 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4532 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4533 aopPut (IC_RESULT (ic), "a", 1);
4538 /* if the lower bytes of a literal are zero skip the addition */
4539 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4541 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4542 (skip_bytes+1 < size))
4547 D(emitcode (";", "genPlus shortcut"));
4552 if( offset >= skip_bytes )
4554 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4557 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4559 emitcode("xch", "a,b");
4560 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4561 emitcode (add, "a,b");
4564 else if (aopGetUsesAcc (leftOp, offset))
4566 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4567 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4571 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4572 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4574 aopPut (IC_RESULT (ic), "a", offset);
4575 add = "addc"; /* further adds must propagate carry */
4579 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4580 isOperandVolatile (IC_RESULT (ic), FALSE))
4583 aopPut (IC_RESULT (ic),
4584 aopGet (leftOp, offset, FALSE, FALSE),
4591 adjustArithmeticResult (ic);
4594 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4597 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4607 /*-----------------------------------------------------------------*/
4608 /* genMinusDec :- does subtraction with decrement if possible */
4609 /*-----------------------------------------------------------------*/
4611 genMinusDec (iCode * ic)
4613 unsigned int icount;
4614 unsigned int size = getDataSize (IC_RESULT (ic));
4616 /* will try to generate an increment */
4617 /* if the right side is not a literal
4619 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4622 /* if the literal value of the right hand side
4623 is greater than 4 then it is not worth it */
4624 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4627 D (emitcode (";", "genMinusDec"));
4629 /* if decrement >=16 bits in register or direct space */
4630 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4631 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4632 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4633 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4641 /* If the next instruction is a goto and the goto target
4642 * is <= 10 instructions previous to this, we can generate
4643 * jumps straight to that target.
4645 if (ic->next && ic->next->op == GOTO
4646 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4647 && labelRange <= 10)
4649 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4650 tlbl = IC_LABEL (ic->next);
4655 tlbl = newiTempLabel (NULL);
4659 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4660 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4661 IS_AOP_PREG (IC_RESULT (ic)))
4662 emitcode ("cjne", "%s,#0xff,%05d$"
4663 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4667 emitcode ("mov", "a,#0xff");
4668 emitcode ("cjne", "a,%s,%05d$"
4669 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4672 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4675 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4676 IS_AOP_PREG (IC_RESULT (ic)))
4677 emitcode ("cjne", "%s,#0xff,%05d$"
4678 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4682 emitcode ("cjne", "a,%s,%05d$"
4683 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4686 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4690 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4691 IS_AOP_PREG (IC_RESULT (ic)))
4692 emitcode ("cjne", "%s,#0xff,%05d$"
4693 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4697 emitcode ("cjne", "a,%s,%05d$"
4698 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4701 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4710 /* if the sizes are greater than 1 then we cannot */
4711 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4712 AOP_SIZE (IC_LEFT (ic)) > 1)
4715 /* we can if the aops of the left & result match or
4716 if they are in registers and the registers are the
4718 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4722 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4724 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4729 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4734 emitcode ("dec", "%s", l);
4737 if (AOP_NEEDSACC (IC_RESULT (ic)))
4738 aopPut (IC_RESULT (ic), "a", 0);
4745 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4746 emitcode ("dec", "a");
4747 aopPut (IC_RESULT (ic), "a", 0);
4754 /*-----------------------------------------------------------------*/
4755 /* addSign - complete with sign */
4756 /*-----------------------------------------------------------------*/
4758 addSign (operand * result, int offset, int sign)
4760 int size = (getDataSize (result) - offset);
4765 emitcode ("rlc", "a");
4766 emitcode ("subb", "a,acc");
4769 aopPut (result, "a", offset++);
4776 aopPut (result, zero, offset++);
4782 /*-----------------------------------------------------------------*/
4783 /* genMinusBits - generates code for subtraction of two bits */
4784 /*-----------------------------------------------------------------*/
4786 genMinusBits (iCode * ic)
4788 symbol *lbl = newiTempLabel (NULL);
4790 D (emitcode (";", "genMinusBits"));
4792 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4794 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4795 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4796 emitcode ("cpl", "c");
4798 outBitC (IC_RESULT (ic));
4802 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4803 emitcode ("subb", "a,acc");
4804 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4805 emitcode ("inc", "a");
4807 aopPut (IC_RESULT (ic), "a", 0);
4808 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4812 /*-----------------------------------------------------------------*/
4813 /* genMinus - generates code for subtraction */
4814 /*-----------------------------------------------------------------*/
4816 genMinus (iCode * ic)
4818 int size, offset = 0;
4820 D (emitcode (";", "genMinus"));
4822 aopOp (IC_LEFT (ic), ic, FALSE);
4823 aopOp (IC_RIGHT (ic), ic, FALSE);
4824 aopOp (IC_RESULT (ic), ic, TRUE);
4826 /* special cases :- */
4827 /* if both left & right are in bit space */
4828 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4829 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4835 /* if I can do an decrement instead
4836 of subtract then GOOD for ME */
4837 if (genMinusDec (ic) == TRUE)
4840 size = getDataSize (IC_RESULT (ic));
4842 /* if literal, add a,#-lit, else normal subb */
4843 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4845 unsigned long lit = 0L;
4846 bool useCarry = FALSE;
4848 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4853 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4855 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4856 if (!offset && !size && lit== (unsigned long) -1)
4858 emitcode ("dec", "a");
4862 /* first add without previous c */
4863 emitcode ("add", "a,#0x%02x",
4864 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4869 emitcode ("addc", "a,#0x%02x",
4870 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4872 aopPut (IC_RESULT (ic), "a", offset++);
4876 /* no need to add zeroes */
4877 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4879 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4888 operand *leftOp, *rightOp;
4890 leftOp = IC_LEFT(ic);
4891 rightOp = IC_RIGHT(ic);
4895 if (aopGetUsesAcc(rightOp, offset)) {
4896 if (aopGetUsesAcc(leftOp, offset)) {
4899 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4901 emitcode ("mov", "b,a");
4904 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4905 emitcode ("subb", "a,b");
4908 /* reverse subtraction with 2's complement */
4910 emitcode( "setb", "c");
4912 emitcode( "cpl", "c");
4913 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4914 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4915 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4916 emitcode("cpl", "a");
4917 if (size) /* skip if last byte */
4918 emitcode( "cpl", "c");
4921 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4924 emitcode ("subb", "a,%s",
4925 aopGet(rightOp, offset, FALSE, TRUE));
4928 aopPut (IC_RESULT (ic), "a", offset++);
4932 adjustArithmeticResult (ic);
4935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4936 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4941 /*-----------------------------------------------------------------*/
4942 /* genMultbits :- multiplication of bits */
4943 /*-----------------------------------------------------------------*/
4945 genMultbits (operand * left,
4949 D (emitcode (";", "genMultbits"));
4951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4952 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4956 /*-----------------------------------------------------------------*/
4957 /* genMultOneByte : 8*8=8/16 bit multiplication */
4958 /*-----------------------------------------------------------------*/
4960 genMultOneByte (operand * left,
4965 int size = AOP_SIZE (result);
4966 bool runtimeSign, compiletimeSign;
4967 bool lUnsigned, rUnsigned, pushedB;
4969 D (emitcode (";", "genMultOneByte"));
4971 if (size < 1 || size > 2)
4973 /* this should never happen */
4974 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4975 AOP_SIZE(result), __FILE__, lineno);
4979 /* (if two literals: the value is computed before) */
4980 /* if one literal, literal on the right */
4981 if (AOP_TYPE (left) == AOP_LIT)
4986 /* emitcode (";", "swapped left and right"); */
4988 /* if no literal, unsigned on the right: shorter code */
4989 if ( AOP_TYPE (right) != AOP_LIT
4990 && SPEC_USIGN (getSpec (operandType (left))))
4997 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4998 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5002 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5003 no need to take care about the signedness! */
5004 || (lUnsigned && rUnsigned))
5006 /* just an unsigned 8 * 8 = 8 multiply
5008 /* emitcode (";","unsigned"); */
5009 /* TODO: check for accumulator clash between left & right aops? */
5011 if (AOP_TYPE (right) == AOP_LIT)
5013 /* moving to accumulator first helps peepholes */
5014 MOVA (aopGet (left, 0, FALSE, FALSE));
5015 MOVB (aopGet (right, 0, FALSE, FALSE));
5019 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5020 MOVA (aopGet (left, 0, FALSE, FALSE));
5023 emitcode ("mul", "ab");
5024 aopPut (result, "a", 0);
5026 aopPut (result, "b", 1);
5032 /* we have to do a signed multiply */
5033 /* emitcode (";", "signed"); */
5035 /* now sign adjust for both left & right */
5037 /* let's see what's needed: */
5038 /* apply negative sign during runtime */
5039 runtimeSign = FALSE;
5040 /* negative sign from literals */
5041 compiletimeSign = FALSE;
5045 if (AOP_TYPE(left) == AOP_LIT)
5047 /* signed literal */
5048 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5050 compiletimeSign = TRUE;
5053 /* signed but not literal */
5059 if (AOP_TYPE(right) == AOP_LIT)
5061 /* signed literal */
5062 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5064 compiletimeSign ^= TRUE;
5067 /* signed but not literal */
5071 /* initialize F0, which stores the runtime sign */
5074 if (compiletimeSign)
5075 emitcode ("setb", "F0"); /* set sign flag */
5077 emitcode ("clr", "F0"); /* reset sign flag */
5080 /* save the signs of the operands */
5081 if (AOP_TYPE(right) == AOP_LIT)
5083 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5085 if (!rUnsigned && val < 0)
5086 emitcode ("mov", "b,#0x%02x", -val);
5088 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5090 else /* ! literal */
5092 if (rUnsigned) /* emitcode (";", "signed"); */
5093 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5096 MOVA (aopGet (right, 0, FALSE, FALSE));
5097 lbl = newiTempLabel (NULL);
5098 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5099 emitcode ("cpl", "F0"); /* complement sign flag */
5100 emitcode ("cpl", "a"); /* 2's complement */
5101 emitcode ("inc", "a");
5103 emitcode ("mov", "b,a");
5107 if (AOP_TYPE(left) == AOP_LIT)
5109 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5111 if (!lUnsigned && val < 0)
5112 emitcode ("mov", "a,#0x%02x", -val);
5114 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5116 else /* ! literal */
5118 MOVA (aopGet (left, 0, FALSE, FALSE));
5122 lbl = newiTempLabel (NULL);
5123 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5124 emitcode ("cpl", "F0"); /* complement sign flag */
5125 emitcode ("cpl", "a"); /* 2's complement */
5126 emitcode ("inc", "a");
5131 /* now the multiplication */
5132 emitcode ("mul", "ab");
5133 if (runtimeSign || compiletimeSign)
5135 lbl = newiTempLabel (NULL);
5137 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5138 emitcode ("cpl", "a"); /* lsb 2's complement */
5140 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5143 emitcode ("add", "a,#1"); /* this sets carry flag */
5144 emitcode ("xch", "a,b");
5145 emitcode ("cpl", "a"); /* msb 2's complement */
5146 emitcode ("addc", "a,#0");
5147 emitcode ("xch", "a,b");
5151 aopPut (result, "a", 0);
5153 aopPut (result, "b", 1);
5158 /*-----------------------------------------------------------------*/
5159 /* genMult - generates code for multiplication */
5160 /*-----------------------------------------------------------------*/
5162 genMult (iCode * ic)
5164 operand *left = IC_LEFT (ic);
5165 operand *right = IC_RIGHT (ic);
5166 operand *result = IC_RESULT (ic);
5168 D (emitcode (";", "genMult"));
5170 /* assign the asmops */
5171 aopOp (left, ic, FALSE);
5172 aopOp (right, ic, FALSE);
5173 aopOp (result, ic, TRUE);
5175 /* special cases first */
5177 if (AOP_TYPE (left) == AOP_CRY &&
5178 AOP_TYPE (right) == AOP_CRY)
5180 genMultbits (left, right, result);
5184 /* if both are of size == 1 */
5185 #if 0 // one of them can be a sloc shared with the result
5186 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5188 if (getSize(operandType(left)) == 1 &&
5189 getSize(operandType(right)) == 1)
5192 genMultOneByte (left, right, result);
5196 /* should have been converted to function call */
5197 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5198 getSize(OP_SYMBOL(right)->type));
5202 freeAsmop (result, NULL, ic, TRUE);
5203 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 /*-----------------------------------------------------------------*/
5208 /* genDivbits :- division of bits */
5209 /*-----------------------------------------------------------------*/
5211 genDivbits (operand * left,
5218 D(emitcode (";", "genDivbits"));
5222 /* the result must be bit */
5223 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5224 l = aopGet (left, 0, FALSE, FALSE);
5228 emitcode ("div", "ab");
5229 emitcode ("rrc", "a");
5233 aopPut (result, "c", 0);
5236 /*-----------------------------------------------------------------*/
5237 /* genDivOneByte : 8 bit division */
5238 /*-----------------------------------------------------------------*/
5240 genDivOneByte (operand * left,
5244 bool lUnsigned, rUnsigned, pushedB;
5245 bool runtimeSign, compiletimeSign;
5246 bool accuse = FALSE;
5247 bool pushedA = FALSE;
5251 D(emitcode (";", "genDivOneByte"));
5253 /* Why is it necessary that genDivOneByte() can return an int result?
5256 volatile unsigned char uc;
5257 volatile signed char sc1, sc2;
5270 In all cases a one byte result would overflow, the following cast to int
5271 would return the wrong result.
5273 Two possible solution:
5274 a) cast operands to int, if ((unsigned) / (signed)) or
5275 ((signed) / (signed))
5276 b) return an 16 bit signed int; this is what we're doing here!
5279 size = AOP_SIZE (result) - 1;
5281 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5282 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5286 /* signed or unsigned */
5287 if (lUnsigned && rUnsigned)
5289 /* unsigned is easy */
5290 MOVB (aopGet (right, 0, FALSE, FALSE));
5291 MOVA (aopGet (left, 0, FALSE, FALSE));
5292 emitcode ("div", "ab");
5293 aopPut (result, "a", 0);
5295 aopPut (result, zero, offset++);
5301 /* signed is a little bit more difficult */
5303 /* now sign adjust for both left & right */
5305 /* let's see what's needed: */
5306 /* apply negative sign during runtime */
5307 runtimeSign = FALSE;
5308 /* negative sign from literals */
5309 compiletimeSign = FALSE;
5313 if (AOP_TYPE(left) == AOP_LIT)
5315 /* signed literal */
5316 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5318 compiletimeSign = TRUE;
5321 /* signed but not literal */
5327 if (AOP_TYPE(right) == AOP_LIT)
5329 /* signed literal */
5330 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5332 compiletimeSign ^= TRUE;
5335 /* signed but not literal */
5339 /* initialize F0, which stores the runtime sign */
5342 if (compiletimeSign)
5343 emitcode ("setb", "F0"); /* set sign flag */
5345 emitcode ("clr", "F0"); /* reset sign flag */
5348 /* save the signs of the operands */
5349 if (AOP_TYPE(right) == AOP_LIT)
5351 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5353 if (!rUnsigned && val < 0)
5354 emitcode ("mov", "b,#0x%02x", -val);
5356 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5358 else /* ! literal */
5361 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5364 MOVA (aopGet (right, 0, FALSE, FALSE));
5365 lbl = newiTempLabel (NULL);
5366 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5367 emitcode ("cpl", "F0"); /* complement sign flag */
5368 emitcode ("cpl", "a"); /* 2's complement */
5369 emitcode ("inc", "a");
5371 emitcode ("mov", "b,a");
5375 if (AOP_TYPE(left) == AOP_LIT)
5377 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5379 if (!lUnsigned && val < 0)
5380 emitcode ("mov", "a,#0x%02x", -val);
5382 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5384 else /* ! literal */
5386 MOVA (aopGet (left, 0, FALSE, FALSE));
5390 lbl = newiTempLabel (NULL);
5391 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5392 emitcode ("cpl", "F0"); /* complement sign flag */
5393 emitcode ("cpl", "a"); /* 2's complement */
5394 emitcode ("inc", "a");
5399 /* now the division */
5400 emitcode ("div", "ab");
5402 if (runtimeSign || compiletimeSign)
5404 lbl = newiTempLabel (NULL);
5406 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5407 emitcode ("cpl", "a"); /* lsb 2's complement */
5408 emitcode ("inc", "a");
5411 accuse = aopPut (result, "a", 0);
5414 /* msb is 0x00 or 0xff depending on the sign */
5419 emitcode ("push", "acc");
5422 emitcode ("mov", "c,F0");
5423 emitcode ("subb", "a,acc");
5425 aopPut (result, "a", offset++);
5427 else /* compiletimeSign */
5429 if (aopPutUsesAcc (result, "#0xFF", offset))
5431 emitcode ("push", "acc");
5435 aopPut (result, "#0xff", offset++);
5441 aopPut (result, "a", 0);
5443 aopPut (result, zero, offset++);
5447 emitcode ("pop", "acc");
5451 /*-----------------------------------------------------------------*/
5452 /* genDiv - generates code for division */
5453 /*-----------------------------------------------------------------*/
5457 operand *left = IC_LEFT (ic);
5458 operand *right = IC_RIGHT (ic);
5459 operand *result = IC_RESULT (ic);
5461 D (emitcode (";", "genDiv"));
5463 /* assign the asmops */
5464 aopOp (left, ic, FALSE);
5465 aopOp (right, ic, FALSE);
5466 aopOp (result, ic, TRUE);
5468 /* special cases first */
5470 if (AOP_TYPE (left) == AOP_CRY &&
5471 AOP_TYPE (right) == AOP_CRY)
5473 genDivbits (left, right, result);
5477 /* if both are of size == 1 */
5478 if (AOP_SIZE (left) == 1 &&
5479 AOP_SIZE (right) == 1)
5481 genDivOneByte (left, right, result);
5485 /* should have been converted to function call */
5488 freeAsmop (result, NULL, ic, TRUE);
5489 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493 /*-----------------------------------------------------------------*/
5494 /* genModbits :- modulus of bits */
5495 /*-----------------------------------------------------------------*/
5497 genModbits (operand * left,
5504 D (emitcode (";", "genModbits"));
5508 /* the result must be bit */
5509 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5510 l = aopGet (left, 0, FALSE, FALSE);
5514 emitcode ("div", "ab");
5515 emitcode ("mov", "a,b");
5516 emitcode ("rrc", "a");
5520 aopPut (result, "c", 0);
5523 /*-----------------------------------------------------------------*/
5524 /* genModOneByte : 8 bit modulus */
5525 /*-----------------------------------------------------------------*/
5527 genModOneByte (operand * left,
5531 bool lUnsigned, rUnsigned, pushedB;
5532 bool runtimeSign, compiletimeSign;
5536 D (emitcode (";", "genModOneByte"));
5538 size = AOP_SIZE (result) - 1;
5540 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5541 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5543 /* if right is a literal, check it for 2^n */
5544 if (AOP_TYPE(right) == AOP_LIT)
5546 unsigned char val = abs((int) operandLitValue(right));
5547 symbol *lbl2 = NULL;
5551 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5560 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5561 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5562 /* because iCode should have been changed to genAnd */
5563 /* see file "SDCCopt.c", function "convertToFcall()" */
5565 MOVA (aopGet (left, 0, FALSE, FALSE));
5566 emitcode ("mov", "c,acc.7");
5567 emitcode ("anl", "a,#0x%02x", val - 1);
5568 lbl = newiTempLabel (NULL);
5569 emitcode ("jz", "%05d$", (lbl->key + 100));
5570 emitcode ("jnc", "%05d$", (lbl->key + 100));
5571 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5577 aopPut (result, "a", 0);
5579 aopPut (result, "#0xff", offs2++);
5580 lbl2 = newiTempLabel (NULL);
5581 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5584 aopPut (result, "a", 0);
5586 aopPut (result, zero, offset++);
5600 /* signed or unsigned */
5601 if (lUnsigned && rUnsigned)
5603 /* unsigned is easy */
5604 MOVB (aopGet (right, 0, FALSE, FALSE));
5605 MOVA (aopGet (left, 0, FALSE, FALSE));
5606 emitcode ("div", "ab");
5607 aopPut (result, "b", 0);
5609 aopPut (result, zero, offset++);
5615 /* signed is a little bit more difficult */
5617 /* now sign adjust for both left & right */
5619 /* modulus: sign of the right operand has no influence on the result! */
5620 if (AOP_TYPE(right) == AOP_LIT)
5622 signed char val = (char) operandLitValue(right);
5624 if (!rUnsigned && val < 0)
5625 emitcode ("mov", "b,#0x%02x", -val);
5627 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5629 else /* not literal */
5632 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5635 MOVA (aopGet (right, 0, FALSE, FALSE));
5636 lbl = newiTempLabel (NULL);
5637 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5638 emitcode ("cpl", "a"); /* 2's complement */
5639 emitcode ("inc", "a");
5641 emitcode ("mov", "b,a");
5645 /* let's see what's needed: */
5646 /* apply negative sign during runtime */
5647 runtimeSign = FALSE;
5648 /* negative sign from literals */
5649 compiletimeSign = FALSE;
5651 /* sign adjust left side */
5652 if (AOP_TYPE(left) == AOP_LIT)
5654 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5656 if (!lUnsigned && val < 0)
5658 compiletimeSign = TRUE; /* set sign flag */
5659 emitcode ("mov", "a,#0x%02x", -val);
5662 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5664 else /* ! literal */
5666 MOVA (aopGet (left, 0, FALSE, FALSE));
5671 emitcode ("clr", "F0"); /* clear sign flag */
5673 lbl = newiTempLabel (NULL);
5674 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5675 emitcode ("setb", "F0"); /* set sign flag */
5676 emitcode ("cpl", "a"); /* 2's complement */
5677 emitcode ("inc", "a");
5682 /* now the modulus */
5683 emitcode ("div", "ab");
5685 if (runtimeSign || compiletimeSign)
5687 emitcode ("mov", "a,b");
5688 lbl = newiTempLabel (NULL);
5690 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5691 emitcode ("cpl", "a"); /* 2's complement */
5692 emitcode ("inc", "a");
5695 aopPut (result, "a", 0);
5698 /* msb is 0x00 or 0xff depending on the sign */
5701 emitcode ("mov", "c,F0");
5702 emitcode ("subb", "a,acc");
5704 aopPut (result, "a", offset++);
5706 else /* compiletimeSign */
5708 aopPut (result, "#0xff", offset++);
5713 aopPut (result, "b", 0);
5715 aopPut (result, zero, offset++);
5721 /*-----------------------------------------------------------------*/
5722 /* genMod - generates code for division */
5723 /*-----------------------------------------------------------------*/
5727 operand *left = IC_LEFT (ic);
5728 operand *right = IC_RIGHT (ic);
5729 operand *result = IC_RESULT (ic);
5731 D (emitcode (";", "genMod"));
5733 /* assign the asmops */
5734 aopOp (left, ic, FALSE);
5735 aopOp (right, ic, FALSE);
5736 aopOp (result, ic, TRUE);
5738 /* special cases first */
5740 if (AOP_TYPE (left) == AOP_CRY &&
5741 AOP_TYPE (right) == AOP_CRY)
5743 genModbits (left, right, result);
5747 /* if both are of size == 1 */
5748 if (AOP_SIZE (left) == 1 &&
5749 AOP_SIZE (right) == 1)
5751 genModOneByte (left, right, result);
5755 /* should have been converted to function call */
5759 freeAsmop (result, NULL, ic, TRUE);
5760 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5764 /*-----------------------------------------------------------------*/
5765 /* genIfxJump :- will create a jump depending on the ifx */
5766 /*-----------------------------------------------------------------*/
5768 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5771 symbol *tlbl = newiTempLabel (NULL);
5774 D (emitcode (";", "genIfxJump"));
5776 /* if true label then we jump if condition
5780 jlbl = IC_TRUE (ic);
5781 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5782 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5786 /* false label is present */
5787 jlbl = IC_FALSE (ic);
5788 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5789 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5791 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5792 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5794 emitcode (inst, "%05d$", tlbl->key + 100);
5795 freeForBranchAsmop (result);
5796 freeForBranchAsmop (right);
5797 freeForBranchAsmop (left);
5798 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5801 /* mark the icode as generated */
5805 /*-----------------------------------------------------------------*/
5806 /* genCmp :- greater or less than comparison */
5807 /*-----------------------------------------------------------------*/
5809 genCmp (operand * left, operand * right,
5810 operand * result, iCode * ifx, int sign, iCode *ic)
5812 int size, offset = 0;
5813 unsigned long lit = 0L;
5816 D (emitcode (";", "genCmp"));
5818 /* if left & right are bit variables */
5819 if (AOP_TYPE (left) == AOP_CRY &&
5820 AOP_TYPE (right) == AOP_CRY)
5822 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5823 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5827 /* subtract right from left if at the
5828 end the carry flag is set then we know that
5829 left is greater than right */
5830 size = max (AOP_SIZE (left), AOP_SIZE (right));
5832 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5833 if ((size == 1) && !sign &&
5834 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5836 symbol *lbl = newiTempLabel (NULL);
5837 emitcode ("cjne", "%s,%s,%05d$",
5838 aopGet (left, offset, FALSE, FALSE),
5839 aopGet (right, offset, FALSE, FALSE),
5845 if (AOP_TYPE (right) == AOP_LIT)
5847 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5848 /* optimize if(x < 0) or if(x >= 0) */
5857 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5858 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5860 genIfxJump (ifx, "acc.7", left, right, result);
5861 freeAsmop (right, NULL, ic, TRUE);
5862 freeAsmop (left, NULL, ic, TRUE);
5868 emitcode ("rlc", "a");
5875 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5876 while (size && (bytelit == 0))
5879 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5885 MOVA (aopGet (left, offset, FALSE, FALSE));
5886 if (sign && size == 0)
5888 emitcode ("xrl", "a,#0x80");
5889 emitcode ("subb", "a,#0x%02x",
5890 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5894 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5904 bool pushedB = FALSE;
5905 rightInB = aopGetUsesAcc(right, offset);
5909 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5911 MOVA (aopGet (left, offset, FALSE, FALSE));
5912 if (sign && size == 0)
5914 emitcode ("xrl", "a,#0x80");
5919 MOVB (aopGet (right, offset, FALSE, FALSE));
5921 emitcode ("xrl", "b,#0x80");
5922 emitcode ("subb", "a,b");
5927 emitcode ("subb", "a,b");
5929 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5939 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5941 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5947 /* if the result is used in the next
5948 ifx conditional branch then generate
5949 code a little differently */
5952 genIfxJump (ifx, "c", NULL, NULL, result);
5958 /* leave the result in acc */
5962 /*-----------------------------------------------------------------*/
5963 /* genCmpGt :- greater than comparison */
5964 /*-----------------------------------------------------------------*/
5966 genCmpGt (iCode * ic, iCode * ifx)
5968 operand *left, *right, *result;
5969 sym_link *letype, *retype;
5972 D (emitcode (";", "genCmpGt"));
5974 left = IC_LEFT (ic);
5975 right = IC_RIGHT (ic);
5976 result = IC_RESULT (ic);
5978 letype = getSpec (operandType (left));
5979 retype = getSpec (operandType (right));
5980 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5981 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5982 /* assign the asmops */
5983 aopOp (result, ic, TRUE);
5984 aopOp (left, ic, FALSE);
5985 aopOp (right, ic, FALSE);
5987 genCmp (right, left, result, ifx, sign, ic);
5989 freeAsmop (result, NULL, ic, TRUE);
5992 /*-----------------------------------------------------------------*/
5993 /* genCmpLt - less than comparisons */
5994 /*-----------------------------------------------------------------*/
5996 genCmpLt (iCode * ic, iCode * ifx)
5998 operand *left, *right, *result;
5999 sym_link *letype, *retype;
6002 D (emitcode (";", "genCmpLt"));
6004 left = IC_LEFT (ic);
6005 right = IC_RIGHT (ic);
6006 result = IC_RESULT (ic);
6008 letype = getSpec (operandType (left));
6009 retype = getSpec (operandType (right));
6010 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6011 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6012 /* assign the asmops */
6013 aopOp (result, ic, TRUE);
6014 aopOp (left, ic, FALSE);
6015 aopOp (right, ic, FALSE);
6017 genCmp (left, right, result, ifx, sign, ic);
6019 freeAsmop (result, NULL, ic, TRUE);
6022 /*-----------------------------------------------------------------*/
6023 /* gencjneshort - compare and jump if not equal */
6024 /*-----------------------------------------------------------------*/
6026 gencjneshort (operand * left, operand * right, symbol * lbl)
6028 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6030 unsigned long lit = 0L;
6032 D (emitcode (";", "gencjneshort"));
6034 /* if the left side is a literal or
6035 if the right is in a pointer register and left
6037 if ((AOP_TYPE (left) == AOP_LIT) ||
6038 (AOP_TYPE (left) == AOP_IMMD) ||
6039 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6046 if (AOP_TYPE (right) == AOP_LIT)
6047 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6049 /* if the right side is a literal then anything goes */
6050 if (AOP_TYPE (right) == AOP_LIT &&
6051 AOP_TYPE (left) != AOP_DIR &&
6052 AOP_TYPE (left) != AOP_IMMD)
6056 emitcode ("cjne", "%s,%s,%05d$",
6057 aopGet (left, offset, FALSE, FALSE),
6058 aopGet (right, offset, FALSE, FALSE),
6064 /* if the right side is in a register or in direct space or
6065 if the left is a pointer register & right is not */
6066 else if (AOP_TYPE (right) == AOP_REG ||
6067 AOP_TYPE (right) == AOP_DIR ||
6068 AOP_TYPE (right) == AOP_LIT ||
6069 AOP_TYPE (right) == AOP_IMMD ||
6070 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6071 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6075 MOVA (aopGet (left, offset, FALSE, FALSE));
6076 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6077 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6078 emitcode ("jnz", "%05d$", lbl->key + 100);
6080 emitcode ("cjne", "a,%s,%05d$",
6081 aopGet (right, offset, FALSE, TRUE),
6088 /* right is a pointer reg need both a & b */
6091 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6092 wassertl(!BINUSE, "B was in use");
6093 MOVB (aopGet (left, offset, FALSE, FALSE));
6094 MOVA (aopGet (right, offset, FALSE, FALSE));
6095 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6101 /*-----------------------------------------------------------------*/
6102 /* gencjne - compare and jump if not equal */
6103 /*-----------------------------------------------------------------*/
6105 gencjne (operand * left, operand * right, symbol * lbl)
6107 symbol *tlbl = newiTempLabel (NULL);
6109 D (emitcode (";", "gencjne"));
6111 gencjneshort (left, right, lbl);
6113 emitcode ("mov", "a,%s", one);
6114 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6116 emitcode ("clr", "a");
6120 /*-----------------------------------------------------------------*/
6121 /* genCmpEq - generates code for equal to */
6122 /*-----------------------------------------------------------------*/
6124 genCmpEq (iCode * ic, iCode * ifx)
6126 bool swappedLR = FALSE;
6127 operand *left, *right, *result;
6129 D (emitcode (";", "genCmpEq"));
6131 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6132 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6133 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6135 /* if literal, literal on the right or
6136 if the right is in a pointer register and left
6138 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6139 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6141 operand *t = IC_RIGHT (ic);
6142 IC_RIGHT (ic) = IC_LEFT (ic);
6147 if (ifx && !AOP_SIZE (result))
6150 /* if they are both bit variables */
6151 if (AOP_TYPE (left) == AOP_CRY &&
6152 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6154 if (AOP_TYPE (right) == AOP_LIT)
6156 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6159 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6160 emitcode ("cpl", "c");
6164 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6168 emitcode ("clr", "c");
6170 /* AOP_TYPE(right) == AOP_CRY */
6174 symbol *lbl = newiTempLabel (NULL);
6175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6177 emitcode ("cpl", "c");
6180 /* if true label then we jump if condition
6182 tlbl = newiTempLabel (NULL);
6185 emitcode ("jnc", "%05d$", tlbl->key + 100);
6186 freeForBranchAsmop (result);
6187 freeForBranchAsmop (right);
6188 freeForBranchAsmop (left);
6189 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6193 emitcode ("jc", "%05d$", tlbl->key + 100);
6194 freeForBranchAsmop (result);
6195 freeForBranchAsmop (right);
6196 freeForBranchAsmop (left);
6197 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6203 tlbl = newiTempLabel (NULL);
6204 gencjneshort (left, right, tlbl);
6207 freeForBranchAsmop (result);
6208 freeForBranchAsmop (right);
6209 freeForBranchAsmop (left);
6210 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6215 symbol *lbl = newiTempLabel (NULL);
6216 emitcode ("sjmp", "%05d$", lbl->key + 100);
6218 freeForBranchAsmop (result);
6219 freeForBranchAsmop (right);
6220 freeForBranchAsmop (left);
6221 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6225 /* mark the icode as generated */
6230 /* if they are both bit variables */
6231 if (AOP_TYPE (left) == AOP_CRY &&
6232 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6234 if (AOP_TYPE (right) == AOP_LIT)
6236 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6239 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6240 emitcode ("cpl", "c");
6244 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6248 emitcode ("clr", "c");
6250 /* AOP_TYPE(right) == AOP_CRY */
6254 symbol *lbl = newiTempLabel (NULL);
6255 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6256 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6257 emitcode ("cpl", "c");
6261 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6268 genIfxJump (ifx, "c", left, right, result);
6271 /* if the result is used in an arithmetic operation
6272 then put the result in place */
6277 gencjne (left, right, newiTempLabel (NULL));
6278 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6280 aopPut (result, "a", 0);
6285 genIfxJump (ifx, "a", left, right, result);
6288 /* if the result is used in an arithmetic operation
6289 then put the result in place */
6290 if (AOP_TYPE (result) != AOP_CRY)
6292 /* leave the result in acc */
6296 freeAsmop (result, NULL, ic, TRUE);
6299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6304 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6309 /*-----------------------------------------------------------------*/
6310 /* ifxForOp - returns the icode containing the ifx for operand */
6311 /*-----------------------------------------------------------------*/
6313 ifxForOp (operand * op, iCode * ic)
6315 /* if true symbol then needs to be assigned */
6316 if (IS_TRUE_SYMOP (op))
6319 /* if this has register type condition and
6320 the next instruction is ifx with the same operand
6321 and live to of the operand is upto the ifx only then */
6323 ic->next->op == IFX &&
6324 IC_COND (ic->next)->key == op->key &&
6325 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6331 /*-----------------------------------------------------------------*/
6332 /* hasInc - operand is incremented before any other use */
6333 /*-----------------------------------------------------------------*/
6335 hasInc (operand *op, iCode *ic, int osize)
6337 sym_link *type = operandType(op);
6338 sym_link *retype = getSpec (type);
6339 iCode *lic = ic->next;
6342 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6343 if (!IS_SYMOP(op)) return NULL;
6345 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6346 if (IS_AGGREGATE(type->next)) return NULL;
6347 if (osize != (isize = getSize(type->next))) return NULL;
6350 /* if operand of the form op = op + <sizeof *op> */
6351 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6352 isOperandEqual(IC_RESULT(lic),op) &&
6353 isOperandLiteral(IC_RIGHT(lic)) &&
6354 operandLitValue(IC_RIGHT(lic)) == isize) {
6357 /* if the operand used or deffed */
6358 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6361 /* if GOTO or IFX */
6362 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6368 /*-----------------------------------------------------------------*/
6369 /* genAndOp - for && operation */
6370 /*-----------------------------------------------------------------*/
6372 genAndOp (iCode * ic)
6374 operand *left, *right, *result;
6377 D (emitcode (";", "genAndOp"));
6379 /* note here that && operations that are in an
6380 if statement are taken away by backPatchLabels
6381 only those used in arthmetic operations remain */
6382 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6383 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6384 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6386 /* if both are bit variables */
6387 if (AOP_TYPE (left) == AOP_CRY &&
6388 AOP_TYPE (right) == AOP_CRY)
6390 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6391 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6396 tlbl = newiTempLabel (NULL);
6398 emitcode ("jz", "%05d$", tlbl->key + 100);
6404 freeAsmop (result, NULL, ic, TRUE);
6405 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6406 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6410 /*-----------------------------------------------------------------*/
6411 /* genOrOp - for || operation */
6412 /*-----------------------------------------------------------------*/
6414 genOrOp (iCode * ic)
6416 operand *left, *right, *result;
6419 D (emitcode (";", "genOrOp"));
6421 /* note here that || operations that are in an
6422 if statement are taken away by backPatchLabels
6423 only those used in arthmetic operations remain */
6424 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6425 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6426 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6428 /* if both are bit variables */
6429 if (AOP_TYPE (left) == AOP_CRY &&
6430 AOP_TYPE (right) == AOP_CRY)
6432 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6433 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6438 tlbl = newiTempLabel (NULL);
6440 emitcode ("jnz", "%05d$", tlbl->key + 100);
6446 freeAsmop (result, NULL, ic, TRUE);
6447 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451 /*-----------------------------------------------------------------*/
6452 /* isLiteralBit - test if lit == 2^n */
6453 /*-----------------------------------------------------------------*/
6455 isLiteralBit (unsigned long lit)
6457 unsigned long pw[32] =
6458 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6459 0x100L, 0x200L, 0x400L, 0x800L,
6460 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6461 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6462 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6463 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6464 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6467 for (idx = 0; idx < 32; idx++)
6473 /*-----------------------------------------------------------------*/
6474 /* continueIfTrue - */
6475 /*-----------------------------------------------------------------*/
6477 continueIfTrue (iCode * ic)
6480 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6484 /*-----------------------------------------------------------------*/
6486 /*-----------------------------------------------------------------*/
6488 jumpIfTrue (iCode * ic)
6491 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6495 /*-----------------------------------------------------------------*/
6496 /* jmpTrueOrFalse - */
6497 /*-----------------------------------------------------------------*/
6499 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6501 // ugly but optimized by peephole
6504 symbol *nlbl = newiTempLabel (NULL);
6505 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6507 freeForBranchAsmop (result);
6508 freeForBranchAsmop (right);
6509 freeForBranchAsmop (left);
6510 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6515 freeForBranchAsmop (result);
6516 freeForBranchAsmop (right);
6517 freeForBranchAsmop (left);
6518 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6524 /*-----------------------------------------------------------------*/
6525 /* genAnd - code for and */
6526 /*-----------------------------------------------------------------*/
6528 genAnd (iCode * ic, iCode * ifx)
6530 operand *left, *right, *result;
6531 int size, offset = 0;
6532 unsigned long lit = 0L;
6536 D (emitcode (";", "genAnd"));
6538 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6539 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6540 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6543 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6545 AOP_TYPE (left), AOP_TYPE (right));
6546 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6548 AOP_SIZE (left), AOP_SIZE (right));
6551 /* if left is a literal & right is not then exchange them */
6552 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6553 AOP_NEEDSACC (left))
6555 operand *tmp = right;
6560 /* if result = right then exchange left and right */
6561 if (sameRegs (AOP (result), AOP (right)))
6563 operand *tmp = right;
6568 /* if right is bit then exchange them */
6569 if (AOP_TYPE (right) == AOP_CRY &&
6570 AOP_TYPE (left) != AOP_CRY)
6572 operand *tmp = right;
6576 if (AOP_TYPE (right) == AOP_LIT)
6577 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6579 size = AOP_SIZE (result);
6582 // result = bit & yy;
6583 if (AOP_TYPE (left) == AOP_CRY)
6585 // c = bit & literal;
6586 if (AOP_TYPE (right) == AOP_LIT)
6590 if (size && sameRegs (AOP (result), AOP (left)))
6593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6598 if (size && (AOP_TYPE (result) == AOP_CRY))
6600 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6603 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6608 emitcode ("clr", "c");
6613 if (AOP_TYPE (right) == AOP_CRY)
6616 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6617 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6622 MOVA (aopGet (right, 0, FALSE, FALSE));
6624 emitcode ("rrc", "a");
6625 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6633 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6634 genIfxJump (ifx, "c", left, right, result);
6638 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6639 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6640 if ((AOP_TYPE (right) == AOP_LIT) &&
6641 (AOP_TYPE (result) == AOP_CRY) &&
6642 (AOP_TYPE (left) != AOP_CRY))
6644 int posbit = isLiteralBit (lit);
6649 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6653 switch (posbit & 0x07)
6655 case 0: emitcode ("rrc", "a");
6657 case 7: emitcode ("rlc", "a");
6659 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6668 SNPRINTF (buffer, sizeof(buffer),
6669 "acc.%d", posbit & 0x07);
6670 genIfxJump (ifx, buffer, left, right, result);
6673 {// what is this case? just found it in ds390/gen.c
6674 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6681 symbol *tlbl = newiTempLabel (NULL);
6682 int sizel = AOP_SIZE (left);
6684 emitcode ("setb", "c");
6687 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6689 MOVA (aopGet (left, offset, FALSE, FALSE));
6691 if ((posbit = isLiteralBit (bytelit)) != 0)
6692 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6695 if (bytelit != 0x0FFL)
6696 emitcode ("anl", "a,%s",
6697 aopGet (right, offset, FALSE, TRUE));
6698 emitcode ("jnz", "%05d$", tlbl->key + 100);
6703 // bit = left & literal
6706 emitcode ("clr", "c");
6709 // if(left & literal)
6713 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6723 /* if left is same as result */
6724 if (sameRegs (AOP (result), AOP (left)))
6726 for (; size--; offset++)
6728 if (AOP_TYPE (right) == AOP_LIT)
6730 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6731 if (bytelit == 0x0FF)
6733 /* dummy read of volatile operand */
6734 if (isOperandVolatile (left, FALSE))
6735 MOVA (aopGet (left, offset, FALSE, FALSE));
6739 else if (bytelit == 0)
6741 aopPut (result, zero, offset);
6743 else if (IS_AOP_PREG (result))
6745 MOVA (aopGet (left, offset, FALSE, TRUE));
6746 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6747 aopPut (result, "a", offset);
6750 emitcode ("anl", "%s,%s",
6751 aopGet (left, offset, FALSE, TRUE),
6752 aopGet (right, offset, FALSE, FALSE));
6756 if (AOP_TYPE (left) == AOP_ACC)
6759 emitcode("mov", "a,b");
6760 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6762 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6764 MOVB (aopGet (left, offset, FALSE, FALSE));
6765 MOVA (aopGet (right, offset, FALSE, FALSE));
6766 emitcode ("anl", "a,b");
6767 aopPut (result, "a", offset);
6769 else if (aopGetUsesAcc (left, offset))
6771 MOVA (aopGet (left, offset, FALSE, FALSE));
6772 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6773 aopPut (result, "a", offset);
6777 MOVA (aopGet (right, offset, FALSE, FALSE));
6778 if (IS_AOP_PREG (result))
6780 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6781 aopPut (result, "a", offset);
6784 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6791 // left & result in different registers
6792 if (AOP_TYPE (result) == AOP_CRY)
6795 // if(size), result in bit
6796 // if(!size && ifx), conditional oper: if(left & right)
6797 symbol *tlbl = newiTempLabel (NULL);
6798 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6800 emitcode ("setb", "c");
6803 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6804 && AOP_TYPE(left)==AOP_ACC)
6807 emitcode("mov", "a,b");
6808 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6810 else if (AOP_TYPE(left)==AOP_ACC)
6814 bool pushedB = pushB ();
6815 emitcode("mov", "b,a");
6816 MOVA (aopGet (right, offset, FALSE, FALSE));
6817 emitcode("anl", "a,b");
6822 MOVA (aopGet (right, offset, FALSE, FALSE));
6823 emitcode("anl", "a,b");
6826 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6828 MOVB (aopGet (left, offset, FALSE, FALSE));
6829 MOVA (aopGet (right, offset, FALSE, FALSE));
6830 emitcode ("anl", "a,b");
6832 else if (aopGetUsesAcc (left, offset))
6834 MOVA (aopGet (left, offset, FALSE, FALSE));
6835 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6839 MOVA (aopGet (right, offset, FALSE, FALSE));
6840 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6843 emitcode ("jnz", "%05d$", tlbl->key + 100);
6853 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6859 for (; (size--); offset++)
6862 // result = left & right
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6866 if (bytelit == 0x0FF)
6869 aopGet (left, offset, FALSE, FALSE),
6873 else if (bytelit == 0)
6875 /* dummy read of volatile operand */
6876 if (isOperandVolatile (left, FALSE))
6877 MOVA (aopGet (left, offset, FALSE, FALSE));
6878 aopPut (result, zero, offset);
6881 else if (AOP_TYPE (left) == AOP_ACC)
6885 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6886 aopPut (result, "a", offset);
6891 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6892 aopPut (result, "b", offset);
6897 // faster than result <- left, anl result,right
6898 // and better if result is SFR
6899 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6900 && AOP_TYPE(left)==AOP_ACC)
6903 emitcode("mov", "a,b");
6904 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6906 else if (AOP_TYPE(left)==AOP_ACC)
6910 bool pushedB = pushB ();
6911 emitcode("mov", "b,a");
6912 MOVA (aopGet (right, offset, FALSE, FALSE));
6913 emitcode("anl", "a,b");
6918 MOVA (aopGet (right, offset, FALSE, FALSE));
6919 emitcode("anl", "a,b");
6922 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6924 MOVB (aopGet (left, offset, FALSE, FALSE));
6925 MOVA (aopGet (right, offset, FALSE, FALSE));
6926 emitcode ("anl", "a,b");
6928 else if (aopGetUsesAcc (left, offset))
6930 MOVA (aopGet (left, offset, FALSE, FALSE));
6931 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6935 MOVA (aopGet (right, offset, FALSE, FALSE));
6936 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6938 aopPut (result, "a", offset);
6944 freeAsmop (result, NULL, ic, TRUE);
6945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6949 /*-----------------------------------------------------------------*/
6950 /* genOr - code for or */
6951 /*-----------------------------------------------------------------*/
6953 genOr (iCode * ic, iCode * ifx)
6955 operand *left, *right, *result;
6956 int size, offset = 0;
6957 unsigned long lit = 0L;
6960 D (emitcode (";", "genOr"));
6962 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6963 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6964 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6967 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6969 AOP_TYPE (left), AOP_TYPE (right));
6970 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6972 AOP_SIZE (left), AOP_SIZE (right));
6975 /* if left is a literal & right is not then exchange them */
6976 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6977 AOP_NEEDSACC (left))
6979 operand *tmp = right;
6984 /* if result = right then exchange them */
6985 if (sameRegs (AOP (result), AOP (right)))
6987 operand *tmp = right;
6992 /* if right is bit then exchange them */
6993 if (AOP_TYPE (right) == AOP_CRY &&
6994 AOP_TYPE (left) != AOP_CRY)
6996 operand *tmp = right;
7000 if (AOP_TYPE (right) == AOP_LIT)
7001 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7003 size = AOP_SIZE (result);
7007 if (AOP_TYPE (left) == AOP_CRY)
7009 if (AOP_TYPE (right) == AOP_LIT)
7011 // c = bit | literal;
7014 // lit != 0 => result = 1
7015 if (AOP_TYPE (result) == AOP_CRY)
7018 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7020 continueIfTrue (ifx);
7023 emitcode ("setb", "c");
7027 // lit == 0 => result = left
7028 if (size && sameRegs (AOP (result), AOP (left)))
7030 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7035 if (AOP_TYPE (right) == AOP_CRY)
7038 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7039 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7044 symbol *tlbl = newiTempLabel (NULL);
7045 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7046 emitcode ("setb", "c");
7047 emitcode ("jb", "%s,%05d$",
7048 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7050 emitcode ("jnz", "%05d$", tlbl->key + 100);
7051 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7053 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7068 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7069 genIfxJump (ifx, "c", left, right, result);
7073 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7074 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7075 if ((AOP_TYPE (right) == AOP_LIT) &&
7076 (AOP_TYPE (result) == AOP_CRY) &&
7077 (AOP_TYPE (left) != AOP_CRY))
7083 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7085 continueIfTrue (ifx);
7090 // lit = 0, result = boolean(left)
7092 emitcode ("setb", "c");
7096 symbol *tlbl = newiTempLabel (NULL);
7097 emitcode ("jnz", "%05d$", tlbl->key + 100);
7103 genIfxJump (ifx, "a", left, right, result);
7111 /* if left is same as result */
7112 if (sameRegs (AOP (result), AOP (left)))
7114 for (; size--; offset++)
7116 if (AOP_TYPE (right) == AOP_LIT)
7118 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7121 /* dummy read of volatile operand */
7122 if (isOperandVolatile (left, FALSE))
7123 MOVA (aopGet (left, offset, FALSE, FALSE));
7127 else if (bytelit == 0x0FF)
7129 aopPut (result, "#0xFF", offset);
7131 else if (IS_AOP_PREG (left))
7133 MOVA (aopGet (left, offset, FALSE, TRUE));
7134 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7135 aopPut (result, "a", offset);
7139 emitcode ("orl", "%s,%s",
7140 aopGet (left, offset, FALSE, TRUE),
7141 aopGet (right, offset, FALSE, FALSE));
7146 if (AOP_TYPE (left) == AOP_ACC)
7149 emitcode("mov", "a,b");
7150 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7152 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7154 MOVB (aopGet (left, offset, FALSE, FALSE));
7155 MOVA (aopGet (right, offset, FALSE, FALSE));
7156 emitcode ("orl", "a,b");
7157 aopPut (result, "a", offset);
7159 else if (aopGetUsesAcc (left, offset))
7161 MOVA (aopGet (left, offset, FALSE, FALSE));
7162 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7163 aopPut (result, "a", offset);
7167 MOVA (aopGet (right, offset, FALSE, FALSE));
7168 if (IS_AOP_PREG (left))
7170 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7171 aopPut (result, "a", offset);
7175 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7183 // left & result in different registers
7184 if (AOP_TYPE (result) == AOP_CRY)
7187 // if(size), result in bit
7188 // if(!size && ifx), conditional oper: if(left | right)
7189 symbol *tlbl = newiTempLabel (NULL);
7190 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7192 emitcode ("setb", "c");
7195 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7196 && AOP_TYPE(left)==AOP_ACC)
7199 emitcode("mov", "a,b");
7200 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7202 else if (AOP_TYPE(left)==AOP_ACC)
7206 bool pushedB = pushB ();
7207 emitcode("mov", "b,a");
7208 MOVA (aopGet (right, offset, FALSE, FALSE));
7209 emitcode("orl", "a,b");
7214 MOVA (aopGet (right, offset, FALSE, FALSE));
7215 emitcode("orl", "a,b");
7218 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7220 MOVB (aopGet (left, offset, FALSE, FALSE));
7221 MOVA (aopGet (right, offset, FALSE, FALSE));
7222 emitcode ("orl", "a,b");
7224 else if (aopGetUsesAcc (left, offset))
7226 MOVA (aopGet (left, offset, FALSE, FALSE));
7227 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7231 MOVA (aopGet (right, offset, FALSE, FALSE));
7232 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7235 emitcode ("jnz", "%05d$", tlbl->key + 100);
7245 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7251 for (; (size--); offset++)
7254 // result = left | right
7255 if (AOP_TYPE (right) == AOP_LIT)
7257 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7261 aopGet (left, offset, FALSE, FALSE),
7265 else if (bytelit == 0x0FF)
7267 /* dummy read of volatile operand */
7268 if (isOperandVolatile (left, FALSE))
7269 MOVA (aopGet (left, offset, FALSE, FALSE));
7270 aopPut (result, "#0xFF", offset);
7274 // faster than result <- left, orl result,right
7275 // and better if result is SFR
7276 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7277 && AOP_TYPE(left)==AOP_ACC)
7280 emitcode("mov", "a,b");
7281 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7283 else if (AOP_TYPE(left)==AOP_ACC)
7287 bool pushedB = pushB ();
7288 emitcode("mov", "b,a");
7289 MOVA (aopGet (right, offset, FALSE, FALSE));
7290 emitcode("orl", "a,b");
7295 MOVA (aopGet (right, offset, FALSE, FALSE));
7296 emitcode("orl", "a,b");
7299 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7301 MOVB (aopGet (left, offset, FALSE, FALSE));
7302 MOVA (aopGet (right, offset, FALSE, FALSE));
7303 emitcode ("orl", "a,b");
7305 else if (aopGetUsesAcc (left, offset))
7307 MOVA (aopGet (left, offset, FALSE, FALSE));
7308 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7312 MOVA (aopGet (right, offset, FALSE, FALSE));
7313 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7315 aopPut (result, "a", offset);
7321 freeAsmop (result, NULL, ic, TRUE);
7322 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7326 /*-----------------------------------------------------------------*/
7327 /* genXor - code for xclusive or */
7328 /*-----------------------------------------------------------------*/
7330 genXor (iCode * ic, iCode * ifx)
7332 operand *left, *right, *result;
7333 int size, offset = 0;
7334 unsigned long lit = 0L;
7337 D (emitcode (";", "genXor"));
7339 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7340 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7341 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7344 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7346 AOP_TYPE (left), AOP_TYPE (right));
7347 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7349 AOP_SIZE (left), AOP_SIZE (right));
7352 /* if left is a literal & right is not ||
7353 if left needs acc & right does not */
7354 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7355 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7357 operand *tmp = right;
7362 /* if result = right then exchange them */
7363 if (sameRegs (AOP (result), AOP (right)))
7365 operand *tmp = right;
7370 /* if right is bit then exchange them */
7371 if (AOP_TYPE (right) == AOP_CRY &&
7372 AOP_TYPE (left) != AOP_CRY)
7374 operand *tmp = right;
7379 if (AOP_TYPE (right) == AOP_LIT)
7380 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7382 size = AOP_SIZE (result);
7386 if (AOP_TYPE (left) == AOP_CRY)
7388 if (AOP_TYPE (right) == AOP_LIT)
7390 // c = bit & literal;
7393 // lit>>1 != 0 => result = 1
7394 if (AOP_TYPE (result) == AOP_CRY)
7397 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7399 continueIfTrue (ifx);
7402 emitcode ("setb", "c");
7409 // lit == 0, result = left
7410 if (size && sameRegs (AOP (result), AOP (left)))
7412 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7416 // lit == 1, result = not(left)
7417 if (size && sameRegs (AOP (result), AOP (left)))
7419 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7424 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7425 emitcode ("cpl", "c");
7433 symbol *tlbl = newiTempLabel (NULL);
7434 if (AOP_TYPE (right) == AOP_CRY)
7437 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7441 int sizer = AOP_SIZE (right);
7443 // if val>>1 != 0, result = 1
7444 emitcode ("setb", "c");
7447 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7449 // test the msb of the lsb
7450 emitcode ("anl", "a,#0xfe");
7451 emitcode ("jnz", "%05d$", tlbl->key + 100);
7455 emitcode ("rrc", "a");
7457 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7458 emitcode ("cpl", "c");
7466 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7467 genIfxJump (ifx, "c", left, right, result);
7471 /* if left is same as result */
7472 if (sameRegs (AOP (result), AOP (left)))
7474 for (; size--; offset++)
7476 if (AOP_TYPE (right) == AOP_LIT)
7478 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7481 /* dummy read of volatile operand */
7482 if (isOperandVolatile (left, FALSE))
7483 MOVA (aopGet (left, offset, FALSE, FALSE));
7487 else if (IS_AOP_PREG (left))
7489 MOVA (aopGet (left, offset, FALSE, TRUE));
7490 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7491 aopPut (result, "a", offset);
7495 emitcode ("xrl", "%s,%s",
7496 aopGet (left, offset, FALSE, TRUE),
7497 aopGet (right, offset, FALSE, FALSE));
7502 if (AOP_TYPE (left) == AOP_ACC)
7505 emitcode("mov", "a,b");
7506 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7508 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7510 MOVB (aopGet (left, offset, FALSE, FALSE));
7511 MOVA (aopGet (right, offset, FALSE, FALSE));
7512 emitcode ("xrl", "a,b");
7513 aopPut (result, "a", offset);
7515 else if (aopGetUsesAcc (left, offset))
7517 MOVA (aopGet (left, offset, FALSE, FALSE));
7518 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7519 aopPut (result, "a", offset);
7523 MOVA (aopGet (right, offset, FALSE, FALSE));
7524 if (IS_AOP_PREG (left))
7526 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7527 aopPut (result, "a", offset);
7530 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7537 // left & result in different registers
7538 if (AOP_TYPE (result) == AOP_CRY)
7541 // if(size), result in bit
7542 // if(!size && ifx), conditional oper: if(left ^ right)
7543 symbol *tlbl = newiTempLabel (NULL);
7544 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7547 emitcode ("setb", "c");
7550 if ((AOP_TYPE (right) == AOP_LIT) &&
7551 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7553 MOVA (aopGet (left, offset, FALSE, FALSE));
7555 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7556 && AOP_TYPE(left)==AOP_ACC)
7559 emitcode("mov", "a,b");
7560 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7562 else if (AOP_TYPE(left)==AOP_ACC)
7566 bool pushedB = pushB ();
7567 emitcode("mov", "b,a");
7568 MOVA (aopGet (right, offset, FALSE, FALSE));
7569 emitcode("xrl", "a,b");
7574 MOVA (aopGet (right, offset, FALSE, FALSE));
7575 emitcode("xrl", "a,b");
7578 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7580 MOVB (aopGet (left, offset, FALSE, FALSE));
7581 MOVA (aopGet (right, offset, FALSE, FALSE));
7582 emitcode ("xrl", "a,b");
7584 else if (aopGetUsesAcc (left, offset))
7586 MOVA (aopGet (left, offset, FALSE, FALSE));
7587 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7591 MOVA (aopGet (right, offset, FALSE, FALSE));
7592 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7595 emitcode ("jnz", "%05d$", tlbl->key + 100);
7605 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7609 for (; (size--); offset++)
7612 // result = left ^ right
7613 if (AOP_TYPE (right) == AOP_LIT)
7615 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7619 aopGet (left, offset, FALSE, FALSE),
7624 // faster than result <- left, xrl result,right
7625 // and better if result is SFR
7626 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7627 && AOP_TYPE(left)==AOP_ACC)
7630 emitcode("mov", "a,b");
7631 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7633 else if (AOP_TYPE(left)==AOP_ACC)
7637 bool pushedB = pushB ();
7638 emitcode("mov", "b,a");
7639 MOVA (aopGet (right, offset, FALSE, FALSE));
7640 emitcode("xrl", "a,b");
7645 MOVA (aopGet (right, offset, FALSE, FALSE));
7646 emitcode("xrl", "a,b");
7649 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7651 MOVB (aopGet (left, offset, FALSE, FALSE));
7652 MOVA (aopGet (right, offset, FALSE, FALSE));
7653 emitcode ("xrl", "a,b");
7655 else if (aopGetUsesAcc (left, offset))
7657 MOVA (aopGet (left, offset, FALSE, FALSE));
7658 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7662 MOVA (aopGet (right, offset, FALSE, FALSE));
7663 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7665 aopPut (result, "a", offset);
7671 freeAsmop (result, NULL, ic, TRUE);
7672 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7673 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7676 /*-----------------------------------------------------------------*/
7677 /* genInline - write the inline code out */
7678 /*-----------------------------------------------------------------*/
7680 genInline (iCode * ic)
7682 char *buffer, *bp, *bp1;
7684 D (emitcode (";", "genInline"));
7686 _G.inLine += (!options.asmpeep);
7688 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7690 /* emit each line as a code */
7701 /* Add \n for labels, not dirs such as c:\mydir */
7702 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7716 /* emitcode("",buffer); */
7717 _G.inLine -= (!options.asmpeep);
7720 /*-----------------------------------------------------------------*/
7721 /* genRRC - rotate right with carry */
7722 /*-----------------------------------------------------------------*/
7726 operand *left, *result;
7730 D (emitcode (";", "genRRC"));
7732 /* rotate right with carry */
7733 left = IC_LEFT (ic);
7734 result = IC_RESULT (ic);
7735 aopOp (left, ic, FALSE);
7736 aopOp (result, ic, FALSE);
7738 /* move it to the result */
7739 size = AOP_SIZE (result);
7741 if (size == 1) { /* special case for 1 byte */
7742 l = aopGet (left, offset, FALSE, FALSE);
7744 emitcode ("rr", "a");
7747 /* no need to clear carry, bit7 will be written later */
7750 l = aopGet (left, offset, FALSE, FALSE);
7752 emitcode ("rrc", "a");
7753 if (AOP_SIZE (result) > 1)
7754 aopPut (result, "a", offset--);
7756 /* now we need to put the carry into the
7757 highest order byte of the result */
7758 if (AOP_SIZE (result) > 1)
7760 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7763 emitcode ("mov", "acc.7,c");
7765 aopPut (result, "a", AOP_SIZE (result) - 1);
7766 freeAsmop (result, NULL, ic, TRUE);
7767 freeAsmop (left, NULL, ic, TRUE);
7770 /*-----------------------------------------------------------------*/
7771 /* genRLC - generate code for rotate left with carry */
7772 /*-----------------------------------------------------------------*/
7776 operand *left, *result;
7780 D (emitcode (";", "genRLC"));
7782 /* rotate right with carry */
7783 left = IC_LEFT (ic);
7784 result = IC_RESULT (ic);
7785 aopOp (left, ic, FALSE);
7786 aopOp (result, ic, FALSE);
7788 /* move it to the result */
7789 size = AOP_SIZE (result);
7793 l = aopGet (left, offset, FALSE, FALSE);
7795 if (size == 0) { /* special case for 1 byte */
7799 emitcode("rlc","a"); /* bit0 will be written later */
7800 if (AOP_SIZE (result) > 1)
7802 aopPut (result, "a", offset++);
7807 l = aopGet (left, offset, FALSE, FALSE);
7809 emitcode ("rlc", "a");
7810 if (AOP_SIZE (result) > 1)
7811 aopPut (result, "a", offset++);
7814 /* now we need to put the carry into the
7815 highest order byte of the result */
7816 if (AOP_SIZE (result) > 1)
7818 l = aopGet (result, 0, FALSE, FALSE);
7821 emitcode ("mov", "acc.0,c");
7823 aopPut (result, "a", 0);
7824 freeAsmop (result, NULL, ic, TRUE);
7825 freeAsmop (left, NULL, ic, TRUE);
7828 /*-----------------------------------------------------------------*/
7829 /* genGetHbit - generates code get highest order bit */
7830 /*-----------------------------------------------------------------*/
7832 genGetHbit (iCode * ic)
7834 operand *left, *result;
7836 D (emitcode (";", "genGetHbit"));
7838 left = IC_LEFT (ic);
7839 result = IC_RESULT (ic);
7840 aopOp (left, ic, FALSE);
7841 aopOp (result, ic, FALSE);
7843 /* get the highest order byte into a */
7844 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7845 if (AOP_TYPE (result) == AOP_CRY)
7847 emitcode ("rlc", "a");
7852 emitcode ("rl", "a");
7853 emitcode ("anl", "a,#0x01");
7857 freeAsmop (result, NULL, ic, TRUE);
7858 freeAsmop (left, NULL, ic, TRUE);
7861 /*-----------------------------------------------------------------*/
7862 /* genGetAbit - generates code get a single bit */
7863 /*-----------------------------------------------------------------*/
7865 genGetAbit (iCode * ic)
7867 operand *left, *right, *result;
7870 D (emitcode (";", "genGetAbit"));
7872 left = IC_LEFT (ic);
7873 right = IC_RIGHT (ic);
7874 result = IC_RESULT (ic);
7875 aopOp (left, ic, FALSE);
7876 aopOp (right, ic, FALSE);
7877 aopOp (result, ic, FALSE);
7879 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7881 /* get the needed byte into a */
7882 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7884 if (AOP_TYPE (result) == AOP_CRY)
7887 emitcode ("rlc", "a");
7888 else if ((shCount) == 0)
7889 emitcode ("rrc", "a");
7891 emitcode ("mov", "c,acc[%d]", shCount);
7899 emitcode ("rr", "a");
7902 emitcode ("rr", "a");
7905 emitcode ("anl", "a,#0x01");
7909 emitcode ("mov", "c,acc[%d]", shCount);
7910 emitcode ("clr", "a");
7911 emitcode ("rlc", "a");
7914 emitcode ("swap", "a");
7915 emitcode ("anl", "a,#0x01");
7918 emitcode ("rl", "a");
7921 emitcode ("rl", "a");
7922 emitcode ("anl", "a,#0x01");
7928 freeAsmop (result, NULL, ic, TRUE);
7929 freeAsmop (right, NULL, ic, TRUE);
7930 freeAsmop (left, NULL, ic, TRUE);
7933 /*-----------------------------------------------------------------*/
7934 /* genGetByte - generates code get a single byte */
7935 /*-----------------------------------------------------------------*/
7937 genGetByte (iCode * ic)
7939 operand *left, *right, *result;
7942 D (emitcode (";", "genGetByte"));
7944 left = IC_LEFT (ic);
7945 right = IC_RIGHT (ic);
7946 result = IC_RESULT (ic);
7947 aopOp (left, ic, FALSE);
7948 aopOp (right, ic, FALSE);
7949 aopOp (result, ic, FALSE);
7951 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7953 aopGet (left, offset, FALSE, FALSE),
7956 freeAsmop (result, NULL, ic, TRUE);
7957 freeAsmop (right, NULL, ic, TRUE);
7958 freeAsmop (left, NULL, ic, TRUE);
7961 /*-----------------------------------------------------------------*/
7962 /* genGetWord - generates code get two bytes */
7963 /*-----------------------------------------------------------------*/
7965 genGetWord (iCode * ic)
7967 operand *left, *right, *result;
7970 D (emitcode (";", "genGetWord"));
7972 left = IC_LEFT (ic);
7973 right = IC_RIGHT (ic);
7974 result = IC_RESULT (ic);
7975 aopOp (left, ic, FALSE);
7976 aopOp (right, ic, FALSE);
7977 aopOp (result, ic, FALSE);
7979 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7981 aopGet (left, offset, FALSE, FALSE),
7984 aopGet (left, offset+1, FALSE, FALSE),
7987 freeAsmop (result, NULL, ic, TRUE);
7988 freeAsmop (right, NULL, ic, TRUE);
7989 freeAsmop (left, NULL, ic, TRUE);
7992 /*-----------------------------------------------------------------*/
7993 /* genSwap - generates code to swap nibbles or bytes */
7994 /*-----------------------------------------------------------------*/
7996 genSwap (iCode * ic)
7998 operand *left, *result;
8000 D(emitcode (";", "genSwap"));
8002 left = IC_LEFT (ic);
8003 result = IC_RESULT (ic);
8004 aopOp (left, ic, FALSE);
8005 aopOp (result, ic, FALSE);
8007 switch (AOP_SIZE (left))
8009 case 1: /* swap nibbles in byte */
8010 MOVA (aopGet (left, 0, FALSE, FALSE));
8011 emitcode ("swap", "a");
8012 aopPut (result, "a", 0);
8014 case 2: /* swap bytes in word */
8015 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8017 MOVA (aopGet (left, 0, FALSE, FALSE));
8018 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8019 aopPut (result, "a", 1);
8021 else if (operandsEqu (left, result))
8024 bool pushedB = FALSE, leftInB = FALSE;
8026 MOVA (aopGet (left, 0, FALSE, FALSE));
8027 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8030 emitcode ("mov", "b,a");
8034 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8035 aopPut (result, reg, 1);
8042 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8043 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8047 wassertl(FALSE, "unsupported SWAP operand size");
8050 freeAsmop (result, NULL, ic, TRUE);
8051 freeAsmop (left, NULL, ic, TRUE);
8054 /*-----------------------------------------------------------------*/
8055 /* AccRol - rotate left accumulator by known count */
8056 /*-----------------------------------------------------------------*/
8058 AccRol (int shCount)
8060 shCount &= 0x0007; // shCount : 0..7
8067 emitcode ("rl", "a");
8070 emitcode ("rl", "a");
8071 emitcode ("rl", "a");
8074 emitcode ("swap", "a");
8075 emitcode ("rr", "a");
8078 emitcode ("swap", "a");
8081 emitcode ("swap", "a");
8082 emitcode ("rl", "a");
8085 emitcode ("rr", "a");
8086 emitcode ("rr", "a");
8089 emitcode ("rr", "a");
8094 /*-----------------------------------------------------------------*/
8095 /* AccLsh - left shift accumulator by known count */
8096 /*-----------------------------------------------------------------*/
8098 AccLsh (int shCount)
8103 emitcode ("add", "a,acc");
8104 else if (shCount == 2)
8106 emitcode ("add", "a,acc");
8107 emitcode ("add", "a,acc");
8111 /* rotate left accumulator */
8113 /* and kill the lower order bits */
8114 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8119 /*-----------------------------------------------------------------*/
8120 /* AccRsh - right shift accumulator by known count */
8121 /*-----------------------------------------------------------------*/
8123 AccRsh (int shCount)
8130 emitcode ("rrc", "a");
8134 /* rotate right accumulator */
8135 AccRol (8 - shCount);
8136 /* and kill the higher order bits */
8137 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8142 /*-----------------------------------------------------------------*/
8143 /* AccSRsh - signed right shift accumulator by known count */
8144 /*-----------------------------------------------------------------*/
8146 AccSRsh (int shCount)
8153 emitcode ("mov", "c,acc.7");
8154 emitcode ("rrc", "a");
8156 else if (shCount == 2)
8158 emitcode ("mov", "c,acc.7");
8159 emitcode ("rrc", "a");
8160 emitcode ("mov", "c,acc.7");
8161 emitcode ("rrc", "a");
8165 tlbl = newiTempLabel (NULL);
8166 /* rotate right accumulator */
8167 AccRol (8 - shCount);
8168 /* and kill the higher order bits */
8169 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8170 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8171 emitcode ("orl", "a,#0x%02x",
8172 (unsigned char) ~SRMask[shCount]);
8178 /*-----------------------------------------------------------------*/
8179 /* shiftR1Left2Result - shift right one byte from left to result */
8180 /*-----------------------------------------------------------------*/
8182 shiftR1Left2Result (operand * left, int offl,
8183 operand * result, int offr,
8184 int shCount, int sign)
8186 MOVA (aopGet (left, offl, FALSE, FALSE));
8187 /* shift right accumulator */
8192 aopPut (result, "a", offr);
8195 /*-----------------------------------------------------------------*/
8196 /* shiftL1Left2Result - shift left one byte from left to result */
8197 /*-----------------------------------------------------------------*/
8199 shiftL1Left2Result (operand * left, int offl,
8200 operand * result, int offr, int shCount)
8203 l = aopGet (left, offl, FALSE, FALSE);
8205 /* shift left accumulator */
8207 aopPut (result, "a", offr);
8210 /*-----------------------------------------------------------------*/
8211 /* movLeft2Result - move byte from left to result */
8212 /*-----------------------------------------------------------------*/
8214 movLeft2Result (operand * left, int offl,
8215 operand * result, int offr, int sign)
8218 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8220 l = aopGet (left, offl, FALSE, FALSE);
8222 if (*l == '@' && (IS_AOP_PREG (result)))
8224 emitcode ("mov", "a,%s", l);
8225 aopPut (result, "a", offr);
8231 aopPut (result, l, offr);
8235 /* MSB sign in acc.7 ! */
8236 if (getDataSize (left) == offl + 1)
8239 aopPut (result, "a", offr);
8246 /*-----------------------------------------------------------------*/
8247 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8248 /*-----------------------------------------------------------------*/
8252 emitcode ("rrc", "a");
8253 emitcode ("xch", "a,%s", x);
8254 emitcode ("rrc", "a");
8255 emitcode ("xch", "a,%s", x);
8258 /*-----------------------------------------------------------------*/
8259 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8260 /*-----------------------------------------------------------------*/
8264 emitcode ("xch", "a,%s", x);
8265 emitcode ("rlc", "a");
8266 emitcode ("xch", "a,%s", x);
8267 emitcode ("rlc", "a");
8270 /*-----------------------------------------------------------------*/
8271 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8272 /*-----------------------------------------------------------------*/
8276 emitcode ("xch", "a,%s", x);
8277 emitcode ("add", "a,acc");
8278 emitcode ("xch", "a,%s", x);
8279 emitcode ("rlc", "a");
8282 /*-----------------------------------------------------------------*/
8283 /* AccAXLsh - left shift a:x by known count (0..7) */
8284 /*-----------------------------------------------------------------*/
8286 AccAXLsh (char *x, int shCount)
8301 case 5: // AAAAABBB:CCCCCDDD
8303 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8305 emitcode ("anl", "a,#0x%02x",
8306 SLMask[shCount]); // BBB00000:CCCCCDDD
8308 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8310 AccRol (shCount); // DDDCCCCC:BBB00000
8312 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8314 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8316 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8318 emitcode ("anl", "a,#0x%02x",
8319 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8321 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8323 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8326 case 6: // AAAAAABB:CCCCCCDD
8327 emitcode ("anl", "a,#0x%02x",
8328 SRMask[shCount]); // 000000BB:CCCCCCDD
8329 emitcode ("mov", "c,acc.0"); // c = B
8330 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8332 AccAXRrl1 (x); // BCCCCCCD:D000000B
8333 AccAXRrl1 (x); // BBCCCCCC:DD000000
8335 emitcode("rrc","a");
8336 emitcode("xch","a,%s", x);
8337 emitcode("rrc","a");
8338 emitcode("mov","c,acc.0"); //<< get correct bit
8339 emitcode("xch","a,%s", x);
8341 emitcode("rrc","a");
8342 emitcode("xch","a,%s", x);
8343 emitcode("rrc","a");
8344 emitcode("xch","a,%s", x);
8347 case 7: // a:x <<= 7
8349 emitcode ("anl", "a,#0x%02x",
8350 SRMask[shCount]); // 0000000B:CCCCCCCD
8352 emitcode ("mov", "c,acc.0"); // c = B
8354 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8356 AccAXRrl1 (x); // BCCCCCCC:D0000000
8364 /*-----------------------------------------------------------------*/
8365 /* AccAXRsh - right shift a:x known count (0..7) */
8366 /*-----------------------------------------------------------------*/
8368 AccAXRsh (char *x, int shCount)
8376 AccAXRrl1 (x); // 0->a:x
8381 AccAXRrl1 (x); // 0->a:x
8384 AccAXRrl1 (x); // 0->a:x
8389 case 5: // AAAAABBB:CCCCCDDD = a:x
8391 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8393 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8395 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8397 emitcode ("anl", "a,#0x%02x",
8398 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8400 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8402 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8404 emitcode ("anl", "a,#0x%02x",
8405 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8407 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8409 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8411 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8414 case 6: // AABBBBBB:CCDDDDDD
8416 emitcode ("mov", "c,acc.7");
8417 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8419 emitcode ("mov", "c,acc.7");
8420 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8422 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8424 emitcode ("anl", "a,#0x%02x",
8425 SRMask[shCount]); // 000000AA:BBBBBBCC
8428 case 7: // ABBBBBBB:CDDDDDDD
8430 emitcode ("mov", "c,acc.7"); // c = A
8432 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8434 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8436 emitcode ("anl", "a,#0x%02x",
8437 SRMask[shCount]); // 0000000A:BBBBBBBC
8445 /*-----------------------------------------------------------------*/
8446 /* AccAXRshS - right shift signed a:x known count (0..7) */
8447 /*-----------------------------------------------------------------*/
8449 AccAXRshS (char *x, int shCount)
8457 emitcode ("mov", "c,acc.7");
8458 AccAXRrl1 (x); // s->a:x
8462 emitcode ("mov", "c,acc.7");
8463 AccAXRrl1 (x); // s->a:x
8465 emitcode ("mov", "c,acc.7");
8466 AccAXRrl1 (x); // s->a:x
8471 case 5: // AAAAABBB:CCCCCDDD = a:x
8473 tlbl = newiTempLabel (NULL);
8474 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8476 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8478 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8480 emitcode ("anl", "a,#0x%02x",
8481 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8483 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8485 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8487 emitcode ("anl", "a,#0x%02x",
8488 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8490 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8492 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8494 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8496 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8497 emitcode ("orl", "a,#0x%02x",
8498 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8501 break; // SSSSAAAA:BBBCCCCC
8503 case 6: // AABBBBBB:CCDDDDDD
8505 tlbl = newiTempLabel (NULL);
8506 emitcode ("mov", "c,acc.7");
8507 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8509 emitcode ("mov", "c,acc.7");
8510 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8512 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8514 emitcode ("anl", "a,#0x%02x",
8515 SRMask[shCount]); // 000000AA:BBBBBBCC
8517 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8518 emitcode ("orl", "a,#0x%02x",
8519 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8523 case 7: // ABBBBBBB:CDDDDDDD
8525 tlbl = newiTempLabel (NULL);
8526 emitcode ("mov", "c,acc.7"); // c = A
8528 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8530 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8532 emitcode ("anl", "a,#0x%02x",
8533 SRMask[shCount]); // 0000000A:BBBBBBBC
8535 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8536 emitcode ("orl", "a,#0x%02x",
8537 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8546 /*-----------------------------------------------------------------*/
8547 /* shiftL2Left2Result - shift left two bytes from left to result */
8548 /*-----------------------------------------------------------------*/
8550 shiftL2Left2Result (operand * left, int offl,
8551 operand * result, int offr, int shCount)
8554 bool pushedB = FALSE;
8557 if (sameRegs (AOP (result), AOP (left)) &&
8558 ((offl + MSB16) == offr))
8560 /* don't crash result[offr] */
8561 MOVA (aopGet (left, offl, FALSE, FALSE));
8562 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8563 usedB = !strncmp(x, "b", 1);
8565 else if (aopGetUsesAcc (result, offr))
8567 movLeft2Result (left, offl, result, offr, 0);
8570 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8571 MOVA (aopGet (result, offr, FALSE, FALSE));
8572 emitcode ("xch", "a,b");
8577 movLeft2Result (left, offl, result, offr, 0);
8578 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8579 x = aopGet (result, offr, FALSE, FALSE);
8581 /* ax << shCount (x = lsb(result)) */
8582 AccAXLsh (x, shCount);
8585 emitcode ("xch", "a,b");
8586 aopPut (result, "a", offr);
8587 aopPut (result, "b", offr + MSB16);
8592 aopPut (result, "a", offr + MSB16);
8597 /*-----------------------------------------------------------------*/
8598 /* shiftR2Left2Result - shift right two bytes from left to result */
8599 /*-----------------------------------------------------------------*/
8601 shiftR2Left2Result (operand * left, int offl,
8602 operand * result, int offr,
8603 int shCount, int sign)
8606 bool pushedB = FALSE;
8609 if (sameRegs (AOP (result), AOP (left)) &&
8610 ((offl + MSB16) == offr))
8612 /* don't crash result[offr] */
8613 MOVA (aopGet (left, offl, FALSE, FALSE));
8614 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8615 usedB = !strncmp(x, "b", 1);
8617 else if (aopGetUsesAcc (result, offr))
8619 movLeft2Result (left, offl, result, offr, 0);
8622 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8623 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8628 movLeft2Result (left, offl, result, offr, 0);
8629 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8630 x = aopGet (result, offr, FALSE, FALSE);
8632 /* a:x >> shCount (x = lsb(result)) */
8634 AccAXRshS (x, shCount);
8636 AccAXRsh (x, shCount);
8639 emitcode ("xch", "a,b");
8640 aopPut (result, "a", offr);
8641 emitcode ("xch", "a,b");
8644 if (getDataSize (result) > 1)
8645 aopPut (result, "a", offr + MSB16);
8648 /*-----------------------------------------------------------------*/
8649 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8650 /*-----------------------------------------------------------------*/
8652 shiftLLeftOrResult (operand * left, int offl,
8653 operand * result, int offr, int shCount)
8655 MOVA (aopGet (left, offl, FALSE, FALSE));
8656 /* shift left accumulator */
8658 /* or with result */
8659 if (aopGetUsesAcc (result, offr))
8661 emitcode ("xch", "a,b");
8662 MOVA (aopGet (result, offr, FALSE, FALSE));
8663 emitcode ("orl", "a,b");
8667 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8669 /* back to result */
8670 aopPut (result, "a", offr);
8673 /*-----------------------------------------------------------------*/
8674 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8675 /*-----------------------------------------------------------------*/
8677 shiftRLeftOrResult (operand * left, int offl,
8678 operand * result, int offr, int shCount)
8680 MOVA (aopGet (left, offl, FALSE, FALSE));
8681 /* shift right accumulator */
8683 /* or with result */
8684 if (aopGetUsesAcc(result, offr))
8686 emitcode ("xch", "a,b");
8687 MOVA (aopGet (result, offr, FALSE, FALSE));
8688 emitcode ("orl", "a,b");
8692 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8694 /* back to result */
8695 aopPut (result, "a", offr);
8698 /*-----------------------------------------------------------------*/
8699 /* genlshOne - left shift a one byte quantity by known count */
8700 /*-----------------------------------------------------------------*/
8702 genlshOne (operand * result, operand * left, int shCount)
8704 D (emitcode (";", "genlshOne"));
8706 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8709 /*-----------------------------------------------------------------*/
8710 /* genlshTwo - left shift two bytes by known amount != 0 */
8711 /*-----------------------------------------------------------------*/
8713 genlshTwo (operand * result, operand * left, int shCount)
8717 D (emitcode (";", "genlshTwo"));
8719 size = getDataSize (result);
8721 /* if shCount >= 8 */
8729 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8731 movLeft2Result (left, LSB, result, MSB16, 0);
8733 aopPut (result, zero, LSB);
8736 /* 1 <= shCount <= 7 */
8740 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8742 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8746 /*-----------------------------------------------------------------*/
8747 /* shiftLLong - shift left one long from left to result */
8748 /* offl = LSB or MSB16 */
8749 /*-----------------------------------------------------------------*/
8751 shiftLLong (operand * left, operand * result, int offr)
8754 int size = AOP_SIZE (result);
8756 if (size >= LSB + offr)
8758 l = aopGet (left, LSB, FALSE, FALSE);
8760 emitcode ("add", "a,acc");
8761 if (sameRegs (AOP (left), AOP (result)) &&
8762 size >= MSB16 + offr && offr != LSB)
8763 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8765 aopPut (result, "a", LSB + offr);
8768 if (size >= MSB16 + offr)
8770 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8772 l = aopGet (left, MSB16, FALSE, FALSE);
8775 emitcode ("rlc", "a");
8776 if (sameRegs (AOP (left), AOP (result)) &&
8777 size >= MSB24 + offr && offr != LSB)
8778 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8780 aopPut (result, "a", MSB16 + offr);
8783 if (size >= MSB24 + offr)
8785 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8787 l = aopGet (left, MSB24, FALSE, FALSE);
8790 emitcode ("rlc", "a");
8791 if (sameRegs (AOP (left), AOP (result)) &&
8792 size >= MSB32 + offr && offr != LSB)
8793 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8795 aopPut (result, "a", MSB24 + offr);
8798 if (size > MSB32 + offr)
8800 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8802 l = aopGet (left, MSB32, FALSE, FALSE);
8805 emitcode ("rlc", "a");
8806 aopPut (result, "a", MSB32 + offr);
8809 aopPut (result, zero, LSB);
8812 /*-----------------------------------------------------------------*/
8813 /* genlshFour - shift four byte by a known amount != 0 */
8814 /*-----------------------------------------------------------------*/
8816 genlshFour (operand * result, operand * left, int shCount)
8820 D (emitcode (";", "genlshFour"));
8822 size = AOP_SIZE (result);
8824 /* if shifting more that 3 bytes */
8829 /* lowest order of left goes to the highest
8830 order of the destination */
8831 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8833 movLeft2Result (left, LSB, result, MSB32, 0);
8834 aopPut (result, zero, LSB);
8835 aopPut (result, zero, MSB16);
8836 aopPut (result, zero, MSB24);
8840 /* more than two bytes */
8841 else if (shCount >= 16)
8843 /* lower order two bytes goes to higher order two bytes */
8845 /* if some more remaining */
8847 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8850 movLeft2Result (left, MSB16, result, MSB32, 0);
8851 movLeft2Result (left, LSB, result, MSB24, 0);
8853 aopPut (result, zero, MSB16);
8854 aopPut (result, zero, LSB);
8858 /* if more than 1 byte */
8859 else if (shCount >= 8)
8861 /* lower order three bytes goes to higher order three bytes */
8866 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8868 movLeft2Result (left, LSB, result, MSB16, 0);
8874 movLeft2Result (left, MSB24, result, MSB32, 0);
8875 movLeft2Result (left, MSB16, result, MSB24, 0);
8876 movLeft2Result (left, LSB, result, MSB16, 0);
8877 aopPut (result, zero, LSB);
8879 else if (shCount == 1)
8880 shiftLLong (left, result, MSB16);
8883 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8884 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8885 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8886 aopPut (result, zero, LSB);
8891 /* 1 <= shCount <= 7 */
8892 else if (shCount <= 2)
8894 shiftLLong (left, result, LSB);
8896 shiftLLong (result, result, LSB);
8898 /* 3 <= shCount <= 7, optimize */
8901 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8902 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8903 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8907 /*-----------------------------------------------------------------*/
8908 /* genLeftShiftLiteral - left shifting by known count */
8909 /*-----------------------------------------------------------------*/
8911 genLeftShiftLiteral (operand * left,
8916 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8919 D (emitcode (";", "genLeftShiftLiteral"));
8921 freeAsmop (right, NULL, ic, TRUE);
8923 aopOp (left, ic, FALSE);
8924 aopOp (result, ic, FALSE);
8926 size = getSize (operandType (result));
8929 emitcode ("; shift left ", "result %d, left %d", size,
8933 /* I suppose that the left size >= result size */
8938 movLeft2Result (left, size, result, size, 0);
8941 else if (shCount >= (size * 8))
8945 aopPut (result, zero, size);
8953 genlshOne (result, left, shCount);
8957 genlshTwo (result, left, shCount);
8961 genlshFour (result, left, shCount);
8964 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8965 "*** ack! mystery literal shift!\n");
8969 freeAsmop (result, NULL, ic, TRUE);
8970 freeAsmop (left, NULL, ic, TRUE);
8973 /*-----------------------------------------------------------------*/
8974 /* genLeftShift - generates code for left shifting */
8975 /*-----------------------------------------------------------------*/
8977 genLeftShift (iCode * ic)
8979 operand *left, *right, *result;
8982 symbol *tlbl, *tlbl1;
8985 D (emitcode (";", "genLeftShift"));
8987 right = IC_RIGHT (ic);
8988 left = IC_LEFT (ic);
8989 result = IC_RESULT (ic);
8991 aopOp (right, ic, FALSE);
8993 /* if the shift count is known then do it
8994 as efficiently as possible */
8995 if (AOP_TYPE (right) == AOP_LIT)
8997 genLeftShiftLiteral (left, right, result, ic);
9001 /* shift count is unknown then we have to form
9002 a loop get the loop count in B : Note: we take
9003 only the lower order byte since shifting
9004 more that 32 bits make no sense anyway, ( the
9005 largest size of an object can be only 32 bits ) */
9008 MOVB (aopGet (right, 0, FALSE, FALSE));
9009 emitcode ("inc", "b");
9010 freeAsmop (right, NULL, ic, TRUE);
9011 aopOp (left, ic, FALSE);
9012 aopOp (result, ic, FALSE);
9014 /* now move the left to the result if they are not the same */
9015 if (!sameRegs (AOP (left), AOP (result)) &&
9016 AOP_SIZE (result) > 1)
9019 size = AOP_SIZE (result);
9023 l = aopGet (left, offset, FALSE, TRUE);
9024 if (*l == '@' && (IS_AOP_PREG (result)))
9027 emitcode ("mov", "a,%s", l);
9028 aopPut (result, "a", offset);
9031 aopPut (result, l, offset);
9036 tlbl = newiTempLabel (NULL);
9037 size = AOP_SIZE (result);
9039 tlbl1 = newiTempLabel (NULL);
9041 /* if it is only one byte then */
9044 symbol *tlbl1 = newiTempLabel (NULL);
9046 l = aopGet (left, 0, FALSE, FALSE);
9048 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9050 emitcode ("add", "a,acc");
9052 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9054 aopPut (result, "a", 0);
9058 reAdjustPreg (AOP (result));
9060 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9062 l = aopGet (result, offset, FALSE, FALSE);
9064 emitcode ("add", "a,acc");
9065 aopPut (result, "a", offset++);
9068 l = aopGet (result, offset, FALSE, FALSE);
9070 emitcode ("rlc", "a");
9071 aopPut (result, "a", offset++);
9073 reAdjustPreg (AOP (result));
9076 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9079 freeAsmop (result, NULL, ic, TRUE);
9080 freeAsmop (left, NULL, ic, TRUE);
9083 /*-----------------------------------------------------------------*/
9084 /* genrshOne - right shift a one byte quantity by known count */
9085 /*-----------------------------------------------------------------*/
9087 genrshOne (operand * result, operand * left,
9088 int shCount, int sign)
9090 D (emitcode (";", "genrshOne"));
9092 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9095 /*-----------------------------------------------------------------*/
9096 /* genrshTwo - right shift two bytes by known amount != 0 */
9097 /*-----------------------------------------------------------------*/
9099 genrshTwo (operand * result, operand * left,
9100 int shCount, int sign)
9102 D (emitcode (";", "genrshTwo"));
9104 /* if shCount >= 8 */
9109 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9111 movLeft2Result (left, MSB16, result, LSB, sign);
9112 addSign (result, MSB16, sign);
9115 /* 1 <= shCount <= 7 */
9117 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9120 /*-----------------------------------------------------------------*/
9121 /* shiftRLong - shift right one long from left to result */
9122 /* offl = LSB or MSB16 */
9123 /*-----------------------------------------------------------------*/
9125 shiftRLong (operand * left, int offl,
9126 operand * result, int sign)
9128 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9130 if (overlapping && offl>1)
9132 // we are in big trouble, but this shouldn't happen
9133 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9136 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9143 emitcode ("rlc", "a");
9144 emitcode ("subb", "a,acc");
9145 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9147 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9151 aopPut (result, "a", MSB32);
9152 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9157 if (aopPutUsesAcc (result, zero, MSB32))
9159 emitcode("xch", "a,b");
9160 aopPut (result, zero, MSB32);
9161 emitcode("xch", "a,b");
9165 aopPut (result, zero, MSB32);
9172 emitcode ("clr", "c");
9176 emitcode ("mov", "c,acc.7");
9179 emitcode ("rrc", "a");
9181 if (overlapping && offl==MSB16 &&
9182 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9184 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9188 aopPut (result, "a", MSB32 - offl);
9189 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9192 emitcode ("rrc", "a");
9193 if (overlapping && offl==MSB16 &&
9194 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9196 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9200 aopPut (result, "a", MSB24 - offl);
9201 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9204 emitcode ("rrc", "a");
9207 aopPut (result, "a", MSB16 - offl);
9212 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9214 xch_a_aopGet (left, LSB, FALSE, FALSE);
9218 aopPut (result, "a", MSB16 - offl);
9219 MOVA (aopGet (left, LSB, FALSE, FALSE));
9221 emitcode ("rrc", "a");
9222 aopPut (result, "a", LSB);
9226 /*-----------------------------------------------------------------*/
9227 /* genrshFour - shift four byte by a known amount != 0 */
9228 /*-----------------------------------------------------------------*/
9230 genrshFour (operand * result, operand * left,
9231 int shCount, int sign)
9233 D (emitcode (";", "genrshFour"));
9235 /* if shifting more that 3 bytes */
9240 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9242 movLeft2Result (left, MSB32, result, LSB, sign);
9243 addSign (result, MSB16, sign);
9245 else if (shCount >= 16)
9249 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9252 movLeft2Result (left, MSB24, result, LSB, 0);
9253 movLeft2Result (left, MSB32, result, MSB16, sign);
9255 addSign (result, MSB24, sign);
9257 else if (shCount >= 8)
9262 shiftRLong (left, MSB16, result, sign);
9264 else if (shCount == 0)
9266 movLeft2Result (left, MSB16, result, LSB, 0);
9267 movLeft2Result (left, MSB24, result, MSB16, 0);
9268 movLeft2Result (left, MSB32, result, MSB24, sign);
9269 addSign (result, MSB32, sign);
9273 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9274 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9275 /* the last shift is signed */
9276 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9277 addSign (result, MSB32, sign);
9282 /* 1 <= shCount <= 7 */
9285 shiftRLong (left, LSB, result, sign);
9287 shiftRLong (result, LSB, result, sign);
9291 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9292 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9293 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9298 /*-----------------------------------------------------------------*/
9299 /* genRightShiftLiteral - right shifting by known count */
9300 /*-----------------------------------------------------------------*/
9302 genRightShiftLiteral (operand * left,
9308 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9311 D (emitcode (";", "genRightShiftLiteral"));
9313 freeAsmop (right, NULL, ic, TRUE);
9315 aopOp (left, ic, FALSE);
9316 aopOp (result, ic, FALSE);
9319 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9323 size = getDataSize (left);
9324 /* test the LEFT size !!! */
9326 /* I suppose that the left size >= result size */
9329 size = getDataSize (result);
9331 movLeft2Result (left, size, result, size, 0);
9334 else if (shCount >= (size * 8))
9338 /* get sign in acc.7 */
9339 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9341 addSign (result, LSB, sign);
9348 genrshOne (result, left, shCount, sign);
9352 genrshTwo (result, left, shCount, sign);
9356 genrshFour (result, left, shCount, sign);
9362 freeAsmop (result, NULL, ic, TRUE);
9363 freeAsmop (left, NULL, ic, TRUE);
9366 /*-----------------------------------------------------------------*/
9367 /* genSignedRightShift - right shift of signed number */
9368 /*-----------------------------------------------------------------*/
9370 genSignedRightShift (iCode * ic)
9372 operand *right, *left, *result;
9375 symbol *tlbl, *tlbl1;
9378 D (emitcode (";", "genSignedRightShift"));
9380 /* we do it the hard way put the shift count in b
9381 and loop thru preserving the sign */
9383 right = IC_RIGHT (ic);
9384 left = IC_LEFT (ic);
9385 result = IC_RESULT (ic);
9387 aopOp (right, ic, FALSE);
9390 if (AOP_TYPE (right) == AOP_LIT)
9392 genRightShiftLiteral (left, right, result, ic, 1);
9395 /* shift count is unknown then we have to form
9396 a loop get the loop count in B : Note: we take
9397 only the lower order byte since shifting
9398 more that 32 bits make no sense anyway, ( the
9399 largest size of an object can be only 32 bits ) */
9402 MOVB (aopGet (right, 0, FALSE, FALSE));
9403 emitcode ("inc", "b");
9404 freeAsmop (right, NULL, ic, TRUE);
9405 aopOp (left, ic, FALSE);
9406 aopOp (result, ic, FALSE);
9408 /* now move the left to the result if they are not the
9410 if (!sameRegs (AOP (left), AOP (result)) &&
9411 AOP_SIZE (result) > 1)
9414 size = AOP_SIZE (result);
9418 l = aopGet (left, offset, FALSE, TRUE);
9419 if (*l == '@' && IS_AOP_PREG (result))
9422 emitcode ("mov", "a,%s", l);
9423 aopPut (result, "a", offset);
9426 aopPut (result, l, offset);
9431 /* mov the highest order bit to OVR */
9432 tlbl = newiTempLabel (NULL);
9433 tlbl1 = newiTempLabel (NULL);
9435 size = AOP_SIZE (result);
9437 MOVA (aopGet (left, offset, FALSE, FALSE));
9438 emitcode ("rlc", "a");
9439 emitcode ("mov", "ov,c");
9440 /* if it is only one byte then */
9443 l = aopGet (left, 0, FALSE, FALSE);
9445 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9447 emitcode ("mov", "c,ov");
9448 emitcode ("rrc", "a");
9450 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9452 aopPut (result, "a", 0);
9456 reAdjustPreg (AOP (result));
9457 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9459 emitcode ("mov", "c,ov");
9462 l = aopGet (result, offset, FALSE, FALSE);
9464 emitcode ("rrc", "a");
9465 aopPut (result, "a", offset--);
9467 reAdjustPreg (AOP (result));
9469 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9473 freeAsmop (result, NULL, ic, TRUE);
9474 freeAsmop (left, NULL, ic, TRUE);
9477 /*-----------------------------------------------------------------*/
9478 /* genRightShift - generate code for right shifting */
9479 /*-----------------------------------------------------------------*/
9481 genRightShift (iCode * ic)
9483 operand *right, *left, *result;
9487 symbol *tlbl, *tlbl1;
9490 D (emitcode (";", "genRightShift"));
9492 /* if signed then we do it the hard way preserve the
9493 sign bit moving it inwards */
9494 letype = getSpec (operandType (IC_LEFT (ic)));
9496 if (!SPEC_USIGN (letype))
9498 genSignedRightShift (ic);
9502 /* signed & unsigned types are treated the same : i.e. the
9503 signed is NOT propagated inwards : quoting from the
9504 ANSI - standard : "for E1 >> E2, is equivalent to division
9505 by 2**E2 if unsigned or if it has a non-negative value,
9506 otherwise the result is implementation defined ", MY definition
9507 is that the sign does not get propagated */
9509 right = IC_RIGHT (ic);
9510 left = IC_LEFT (ic);
9511 result = IC_RESULT (ic);
9513 aopOp (right, ic, FALSE);
9515 /* if the shift count is known then do it
9516 as efficiently as possible */
9517 if (AOP_TYPE (right) == AOP_LIT)
9519 genRightShiftLiteral (left, right, result, ic, 0);
9523 /* shift count is unknown then we have to form
9524 a loop get the loop count in B : Note: we take
9525 only the lower order byte since shifting
9526 more that 32 bits make no sense anyway, ( the
9527 largest size of an object can be only 32 bits ) */
9530 MOVB (aopGet (right, 0, FALSE, FALSE));
9531 emitcode ("inc", "b");
9532 freeAsmop (right, NULL, ic, TRUE);
9533 aopOp (left, ic, FALSE);
9534 aopOp (result, ic, FALSE);
9536 /* now move the left to the result if they are not the
9538 if (!sameRegs (AOP (left), AOP (result)) &&
9539 AOP_SIZE (result) > 1)
9541 size = AOP_SIZE (result);
9545 l = aopGet (left, offset, FALSE, TRUE);
9546 if (*l == '@' && IS_AOP_PREG (result))
9549 emitcode ("mov", "a,%s", l);
9550 aopPut (result, "a", offset);
9553 aopPut (result, l, offset);
9558 tlbl = newiTempLabel (NULL);
9559 tlbl1 = newiTempLabel (NULL);
9560 size = AOP_SIZE (result);
9563 /* if it is only one byte then */
9566 l = aopGet (left, 0, FALSE, FALSE);
9568 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9571 emitcode ("rrc", "a");
9573 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9575 aopPut (result, "a", 0);
9579 reAdjustPreg (AOP (result));
9580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9585 l = aopGet (result, offset, FALSE, FALSE);
9587 emitcode ("rrc", "a");
9588 aopPut (result, "a", offset--);
9590 reAdjustPreg (AOP (result));
9593 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9597 freeAsmop (result, NULL, ic, TRUE);
9598 freeAsmop (left, NULL, ic, TRUE);
9601 /*-----------------------------------------------------------------*/
9602 /* emitPtrByteGet - emits code to get a byte into A through a */
9603 /* pointer register (R0, R1, or DPTR). The */
9604 /* original value of A can be preserved in B. */
9605 /*-----------------------------------------------------------------*/
9607 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9614 emitcode ("mov", "b,a");
9615 emitcode ("mov", "a,@%s", rname);
9620 emitcode ("mov", "b,a");
9621 emitcode ("movx", "a,@%s", rname);
9626 emitcode ("mov", "b,a");
9627 emitcode ("movx", "a,@dptr");
9632 emitcode ("mov", "b,a");
9633 emitcode ("clr", "a");
9634 emitcode ("movc", "a,@a+dptr");
9640 emitcode ("push", "b");
9641 emitcode ("push", "acc");
9643 emitcode ("lcall", "__gptrget");
9645 emitcode ("pop", "b");
9650 /*-----------------------------------------------------------------*/
9651 /* emitPtrByteSet - emits code to set a byte from src through a */
9652 /* pointer register (R0, R1, or DPTR). */
9653 /*-----------------------------------------------------------------*/
9655 emitPtrByteSet (char *rname, int p_type, char *src)
9664 emitcode ("mov", "@%s,a", rname);
9667 emitcode ("mov", "@%s,%s", rname, src);
9672 emitcode ("movx", "@%s,a", rname);
9677 emitcode ("movx", "@dptr,a");
9682 emitcode ("lcall", "__gptrput");
9687 /*-----------------------------------------------------------------*/
9688 /* genUnpackBits - generates code for unpacking bits */
9689 /*-----------------------------------------------------------------*/
9691 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9693 int offset = 0; /* result byte offset */
9694 int rsize; /* result size */
9695 int rlen = 0; /* remaining bitfield length */
9696 sym_link *etype; /* bitfield type information */
9697 int blen; /* bitfield length */
9698 int bstr; /* bitfield starting bit within byte */
9701 D(emitcode (";", "genUnpackBits"));
9703 etype = getSpec (operandType (result));
9704 rsize = getSize (operandType (result));
9705 blen = SPEC_BLEN (etype);
9706 bstr = SPEC_BSTR (etype);
9708 if (ifx && blen <= 8)
9710 emitPtrByteGet (rname, ptype, FALSE);
9713 SNPRINTF (buffer, sizeof(buffer),
9715 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9720 emitcode ("anl", "a,#0x%02x",
9721 (((unsigned char) -1) >> (8 - blen)) << bstr);
9722 genIfxJump (ifx, "a", NULL, NULL, NULL);
9728 /* If the bitfield length is less than a byte */
9731 emitPtrByteGet (rname, ptype, FALSE);
9733 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9734 if (!SPEC_USIGN (etype))
9736 /* signed bitfield */
9737 symbol *tlbl = newiTempLabel (NULL);
9739 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9740 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9743 aopPut (result, "a", offset++);
9747 /* Bit field did not fit in a byte. Copy all
9748 but the partial byte at the end. */
9749 for (rlen=blen;rlen>=8;rlen-=8)
9751 emitPtrByteGet (rname, ptype, FALSE);
9752 aopPut (result, "a", offset++);
9754 emitcode ("inc", "%s", rname);
9757 /* Handle the partial byte at the end */
9760 emitPtrByteGet (rname, ptype, FALSE);
9761 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9762 if (!SPEC_USIGN (etype))
9764 /* signed bitfield */
9765 symbol *tlbl = newiTempLabel (NULL);
9767 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9768 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9771 aopPut (result, "a", offset++);
9779 if (SPEC_USIGN (etype))
9783 /* signed bitfield: sign extension with 0x00 or 0xff */
9784 emitcode ("rlc", "a");
9785 emitcode ("subb", "a,acc");
9791 aopPut (result, source, offset++);
9796 /*-----------------------------------------------------------------*/
9797 /* genDataPointerGet - generates code when ptr offset is known */
9798 /*-----------------------------------------------------------------*/
9800 genDataPointerGet (operand * left,
9806 int size, offset = 0;
9808 D (emitcode (";", "genDataPointerGet"));
9810 aopOp (result, ic, TRUE);
9812 /* get the string representation of the name */
9813 l = aopGet (left, 0, FALSE, TRUE);
9815 size = AOP_SIZE (result);
9820 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9824 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9826 aopPut (result, buffer, offset++);
9829 freeAsmop (result, NULL, ic, TRUE);
9830 freeAsmop (left, NULL, ic, TRUE);
9833 /*-----------------------------------------------------------------*/
9834 /* genNearPointerGet - emitcode for near pointer fetch */
9835 /*-----------------------------------------------------------------*/
9837 genNearPointerGet (operand * left,
9846 sym_link *rtype, *retype;
9847 sym_link *ltype = operandType (left);
9850 D (emitcode (";", "genNearPointerGet"));
9852 rtype = operandType (result);
9853 retype = getSpec (rtype);
9855 aopOp (left, ic, FALSE);
9857 /* if left is rematerialisable and
9858 result is not bitfield variable type and
9859 the left is pointer to data space i.e
9860 lower 128 bytes of space */
9861 if (AOP_TYPE (left) == AOP_IMMD &&
9862 !IS_BITFIELD (retype) &&
9863 DCL_TYPE (ltype) == POINTER)
9865 genDataPointerGet (left, result, ic);
9869 /* if the value is already in a pointer register
9870 then don't need anything more */
9871 if (!AOP_INPREG (AOP (left)))
9873 if (IS_AOP_PREG (left))
9875 // Aha, it is a pointer, just in disguise.
9876 rname = aopGet (left, 0, FALSE, FALSE);
9879 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9880 __FILE__, __LINE__);
9885 emitcode ("mov", "a%s,%s", rname + 1, rname);
9886 rname++; // skip the '@'.
9891 /* otherwise get a free pointer register */
9893 preg = getFreePtr (ic, &aop, FALSE);
9894 emitcode ("mov", "%s,%s",
9896 aopGet (left, 0, FALSE, TRUE));
9901 rname = aopGet (left, 0, FALSE, FALSE);
9903 //aopOp (result, ic, FALSE);
9904 aopOp (result, ic, result?TRUE:FALSE);
9906 /* if bitfield then unpack the bits */
9907 if (IS_BITFIELD (retype))
9908 genUnpackBits (result, rname, POINTER, ifx);
9911 /* we have can just get the values */
9912 int size = AOP_SIZE (result);
9917 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9920 emitcode ("mov", "a,@%s", rname);
9922 aopPut (result, "a", offset);
9926 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9927 aopPut (result, buffer, offset);
9931 emitcode ("inc", "%s", rname);
9935 /* now some housekeeping stuff */
9936 if (aop) /* we had to allocate for this iCode */
9938 if (pi) { /* post increment present */
9939 aopPut (left, rname, 0);
9941 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9945 /* we did not allocate which means left
9946 already in a pointer register, then
9947 if size > 0 && this could be used again
9948 we have to point it back to where it
9950 if ((AOP_SIZE (result) > 1 &&
9951 !OP_SYMBOL (left)->remat &&
9952 (OP_SYMBOL (left)->liveTo > ic->seq ||
9956 int size = AOP_SIZE (result) - 1;
9958 emitcode ("dec", "%s", rname);
9962 if (ifx && !ifx->generated)
9964 genIfxJump (ifx, "a", left, NULL, result);
9968 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9969 freeAsmop (left, NULL, ic, TRUE);
9970 if (pi) pi->generated = 1;
9973 /*-----------------------------------------------------------------*/
9974 /* genPagedPointerGet - emitcode for paged pointer fetch */
9975 /*-----------------------------------------------------------------*/
9977 genPagedPointerGet (operand * left,
9986 sym_link *rtype, *retype;
9988 D (emitcode (";", "genPagedPointerGet"));
9990 rtype = operandType (result);
9991 retype = getSpec (rtype);
9993 aopOp (left, ic, FALSE);
9995 /* if the value is already in a pointer register
9996 then don't need anything more */
9997 if (!AOP_INPREG (AOP (left)))
9999 /* otherwise get a free pointer register */
10000 aop = newAsmop (0);
10001 preg = getFreePtr (ic, &aop, FALSE);
10002 emitcode ("mov", "%s,%s",
10004 aopGet (left, 0, FALSE, TRUE));
10005 rname = preg->name;
10008 rname = aopGet (left, 0, FALSE, FALSE);
10010 aopOp (result, ic, FALSE);
10012 /* if bitfield then unpack the bits */
10013 if (IS_BITFIELD (retype))
10014 genUnpackBits (result, rname, PPOINTER, ifx);
10017 /* we have can just get the values */
10018 int size = AOP_SIZE (result);
10024 emitcode ("movx", "a,@%s", rname);
10026 aopPut (result, "a", offset);
10031 emitcode ("inc", "%s", rname);
10035 /* now some housekeeping stuff */
10036 if (aop) /* we had to allocate for this iCode */
10039 aopPut (left, rname, 0);
10040 freeAsmop (NULL, aop, ic, TRUE);
10044 /* we did not allocate which means left
10045 already in a pointer register, then
10046 if size > 0 && this could be used again
10047 we have to point it back to where it
10049 if ((AOP_SIZE (result) > 1 &&
10050 !OP_SYMBOL (left)->remat &&
10051 (OP_SYMBOL (left)->liveTo > ic->seq ||
10055 int size = AOP_SIZE (result) - 1;
10057 emitcode ("dec", "%s", rname);
10061 if (ifx && !ifx->generated)
10063 genIfxJump (ifx, "a", left, NULL, result);
10067 freeAsmop (result, NULL, ic, TRUE);
10068 freeAsmop (left, NULL, ic, TRUE);
10069 if (pi) pi->generated = 1;
10072 /*--------------------------------------------------------------------*/
10073 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10074 /*--------------------------------------------------------------------*/
10076 loadDptrFromOperand (operand *op, bool loadBToo)
10078 if (AOP_TYPE (op) != AOP_STR)
10080 /* if this is rematerializable */
10081 if (AOP_TYPE (op) == AOP_IMMD)
10083 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10086 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10087 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10090 wassertl(FALSE, "need pointerCode");
10091 emitcode (";", "mov b,???");
10092 /* genPointerGet and genPointerSet originally did different
10093 ** things for this case. Both seem wrong.
10094 ** from genPointerGet:
10095 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10096 ** from genPointerSet:
10097 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10102 else if (AOP_TYPE (op) == AOP_DPTR)
10106 MOVA (aopGet (op, 0, FALSE, FALSE));
10107 emitcode ("push", "acc");
10108 MOVA (aopGet (op, 1, FALSE, FALSE));
10109 emitcode ("push", "acc");
10110 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10111 emitcode ("pop", "dph");
10112 emitcode ("pop", "dpl");
10116 MOVA (aopGet (op, 0, FALSE, FALSE));
10117 emitcode ("push", "acc");
10118 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10119 emitcode ("pop", "dpl");
10123 { /* we need to get it byte by byte */
10124 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10125 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10127 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10132 /*-----------------------------------------------------------------*/
10133 /* genFarPointerGet - get value from far space */
10134 /*-----------------------------------------------------------------*/
10136 genFarPointerGet (operand * left,
10137 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10140 sym_link *retype = getSpec (operandType (result));
10142 D (emitcode (";", "genFarPointerGet"));
10144 aopOp (left, ic, FALSE);
10145 loadDptrFromOperand (left, FALSE);
10147 /* so dptr now contains the address */
10148 aopOp (result, ic, FALSE);
10150 /* if bit then unpack */
10151 if (IS_BITFIELD (retype))
10152 genUnpackBits (result, "dptr", FPOINTER, ifx);
10155 size = AOP_SIZE (result);
10160 emitcode ("movx", "a,@dptr");
10162 aopPut (result, "a", offset++);
10164 emitcode ("inc", "dptr");
10168 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10170 aopPut (left, "dpl", 0);
10171 aopPut (left, "dph", 1);
10175 if (ifx && !ifx->generated)
10177 genIfxJump (ifx, "a", left, NULL, result);
10180 freeAsmop (result, NULL, ic, TRUE);
10181 freeAsmop (left, NULL, ic, TRUE);
10184 /*-----------------------------------------------------------------*/
10185 /* genCodePointerGet - get value from code space */
10186 /*-----------------------------------------------------------------*/
10188 genCodePointerGet (operand * left,
10189 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10192 sym_link *retype = getSpec (operandType (result));
10194 D (emitcode (";", "genCodePointerGet"));
10196 aopOp (left, ic, FALSE);
10197 loadDptrFromOperand (left, FALSE);
10199 /* so dptr now contains the address */
10200 aopOp (result, ic, FALSE);
10202 /* if bit then unpack */
10203 if (IS_BITFIELD (retype))
10204 genUnpackBits (result, "dptr", CPOINTER, ifx);
10207 size = AOP_SIZE (result);
10212 emitcode ("clr", "a");
10213 emitcode ("movc", "a,@a+dptr");
10215 aopPut (result, "a", offset++);
10217 emitcode ("inc", "dptr");
10221 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10223 aopPut (left, "dpl", 0);
10224 aopPut (left, "dph", 1);
10228 if (ifx && !ifx->generated)
10230 genIfxJump (ifx, "a", left, NULL, result);
10233 freeAsmop (result, NULL, ic, TRUE);
10234 freeAsmop (left, NULL, ic, TRUE);
10237 /*-----------------------------------------------------------------*/
10238 /* genGenPointerGet - get value from generic pointer space */
10239 /*-----------------------------------------------------------------*/
10241 genGenPointerGet (operand * left,
10242 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10245 sym_link *retype = getSpec (operandType (result));
10247 D (emitcode (";", "genGenPointerGet"));
10249 aopOp (left, ic, FALSE);
10250 loadDptrFromOperand (left, TRUE);
10252 /* so dptr now contains the address */
10253 aopOp (result, ic, FALSE);
10255 /* if bit then unpack */
10256 if (IS_BITFIELD (retype))
10258 genUnpackBits (result, "dptr", GPOINTER, ifx);
10262 size = AOP_SIZE (result);
10267 emitcode ("lcall", "__gptrget");
10269 aopPut (result, "a", offset++);
10271 emitcode ("inc", "dptr");
10275 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10277 aopPut (left, "dpl", 0);
10278 aopPut (left, "dph", 1);
10282 if (ifx && !ifx->generated)
10284 genIfxJump (ifx, "a", left, NULL, result);
10287 freeAsmop (result, NULL, ic, TRUE);
10288 freeAsmop (left, NULL, ic, TRUE);
10291 /*-----------------------------------------------------------------*/
10292 /* genPointerGet - generate code for pointer get */
10293 /*-----------------------------------------------------------------*/
10295 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10297 operand *left, *result;
10298 sym_link *type, *etype;
10301 D (emitcode (";", "genPointerGet"));
10303 left = IC_LEFT (ic);
10304 result = IC_RESULT (ic);
10306 if (getSize (operandType (result))>1)
10309 /* depending on the type of pointer we need to
10310 move it to the correct pointer register */
10311 type = operandType (left);
10312 etype = getSpec (type);
10313 /* if left is of type of pointer then it is simple */
10314 if (IS_PTR (type) && !IS_FUNC (type->next))
10315 p_type = DCL_TYPE (type);
10318 /* we have to go by the storage class */
10319 p_type = PTR_TYPE (SPEC_OCLS (etype));
10322 /* special case when cast remat */
10323 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10324 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10326 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10327 type = operandType (left);
10328 p_type = DCL_TYPE (type);
10330 /* now that we have the pointer type we assign
10331 the pointer values */
10337 genNearPointerGet (left, result, ic, pi, ifx);
10341 genPagedPointerGet (left, result, ic, pi, ifx);
10345 genFarPointerGet (left, result, ic, pi, ifx);
10349 genCodePointerGet (left, result, ic, pi, ifx);
10353 genGenPointerGet (left, result, ic, pi, ifx);
10359 /*-----------------------------------------------------------------*/
10360 /* genPackBits - generates code for packed bit storage */
10361 /*-----------------------------------------------------------------*/
10363 genPackBits (sym_link * etype,
10365 char *rname, int p_type)
10367 int offset = 0; /* source byte offset */
10368 int rlen = 0; /* remaining bitfield length */
10369 int blen; /* bitfield length */
10370 int bstr; /* bitfield starting bit within byte */
10371 int litval; /* source literal value (if AOP_LIT) */
10372 unsigned char mask; /* bitmask within current byte */
10374 D(emitcode (";", "genPackBits"));
10376 blen = SPEC_BLEN (etype);
10377 bstr = SPEC_BSTR (etype);
10379 /* If the bitfield length is less than a byte */
10382 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10383 (unsigned char) (0xFF >> (8 - bstr)));
10385 if (AOP_TYPE (right) == AOP_LIT)
10387 /* Case with a bitfield length <8 and literal source
10389 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10391 litval &= (~mask) & 0xff;
10392 emitPtrByteGet (rname, p_type, FALSE);
10393 if ((mask|litval)!=0xff)
10394 emitcode ("anl","a,#0x%02x", mask);
10396 emitcode ("orl","a,#0x%02x", litval);
10400 if ((blen==1) && (p_type!=GPOINTER))
10402 /* Case with a bitfield length == 1 and no generic pointer
10404 if (AOP_TYPE (right) == AOP_CRY)
10405 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10408 MOVA (aopGet (right, 0, FALSE, FALSE));
10409 emitcode ("rrc","a");
10411 emitPtrByteGet (rname, p_type, FALSE);
10412 emitcode ("mov","acc.%d,c",bstr);
10417 /* Case with a bitfield length < 8 and arbitrary source
10419 MOVA (aopGet (right, 0, FALSE, FALSE));
10420 /* shift and mask source value */
10422 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10424 pushedB = pushB ();
10425 /* transfer A to B and get next byte */
10426 emitPtrByteGet (rname, p_type, TRUE);
10428 emitcode ("anl", "a,#0x%02x", mask);
10429 emitcode ("orl", "a,b");
10430 if (p_type == GPOINTER)
10431 emitcode ("pop", "b");
10437 emitPtrByteSet (rname, p_type, "a");
10441 /* Bit length is greater than 7 bits. In this case, copy */
10442 /* all except the partial byte at the end */
10443 for (rlen=blen;rlen>=8;rlen-=8)
10445 emitPtrByteSet (rname, p_type,
10446 aopGet (right, offset++, FALSE, TRUE) );
10448 emitcode ("inc", "%s", rname);
10451 /* If there was a partial byte at the end */
10454 mask = (((unsigned char) -1 << rlen) & 0xff);
10456 if (AOP_TYPE (right) == AOP_LIT)
10458 /* Case with partial byte and literal source
10460 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10461 litval >>= (blen-rlen);
10462 litval &= (~mask) & 0xff;
10463 emitPtrByteGet (rname, p_type, FALSE);
10464 if ((mask|litval)!=0xff)
10465 emitcode ("anl","a,#0x%02x", mask);
10467 emitcode ("orl","a,#0x%02x", litval);
10472 /* Case with partial byte and arbitrary source
10474 MOVA (aopGet (right, offset++, FALSE, FALSE));
10475 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10477 pushedB = pushB ();
10478 /* transfer A to B and get next byte */
10479 emitPtrByteGet (rname, p_type, TRUE);
10481 emitcode ("anl", "a,#0x%02x", mask);
10482 emitcode ("orl", "a,b");
10483 if (p_type == GPOINTER)
10484 emitcode ("pop", "b");
10488 emitPtrByteSet (rname, p_type, "a");
10493 /*-----------------------------------------------------------------*/
10494 /* genDataPointerSet - remat pointer to data space */
10495 /*-----------------------------------------------------------------*/
10497 genDataPointerSet (operand * right,
10501 int size, offset = 0;
10502 char *l, buffer[256];
10504 D (emitcode (";", "genDataPointerSet"));
10506 aopOp (right, ic, FALSE);
10508 l = aopGet (result, 0, FALSE, TRUE);
10510 size = AOP_SIZE (right);
10514 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10516 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10517 emitcode ("mov", "%s,%s", buffer,
10518 aopGet (right, offset++, FALSE, FALSE));
10521 freeAsmop (result, NULL, ic, TRUE);
10522 freeAsmop (right, NULL, ic, TRUE);
10525 /*-----------------------------------------------------------------*/
10526 /* genNearPointerSet - emitcode for near pointer put */
10527 /*-----------------------------------------------------------------*/
10529 genNearPointerSet (operand * right,
10537 sym_link *retype, *letype;
10538 sym_link *ptype = operandType (result);
10540 D (emitcode (";", "genNearPointerSet"));
10542 retype = getSpec (operandType (right));
10543 letype = getSpec (ptype);
10545 aopOp (result, ic, FALSE);
10547 /* if the result is rematerializable &
10548 in data space & not a bit variable */
10549 if (AOP_TYPE (result) == AOP_IMMD &&
10550 DCL_TYPE (ptype) == POINTER &&
10551 !IS_BITVAR (retype) &&
10552 !IS_BITVAR (letype))
10554 genDataPointerSet (right, result, ic);
10558 /* if the value is already in a pointer register
10559 then don't need anything more */
10560 if (!AOP_INPREG (AOP (result)))
10563 //AOP_TYPE (result) == AOP_STK
10564 IS_AOP_PREG(result)
10567 // Aha, it is a pointer, just in disguise.
10568 rname = aopGet (result, 0, FALSE, FALSE);
10571 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10572 __FILE__, __LINE__);
10577 emitcode ("mov", "a%s,%s", rname + 1, rname);
10578 rname++; // skip the '@'.
10583 /* otherwise get a free pointer register */
10584 aop = newAsmop (0);
10585 preg = getFreePtr (ic, &aop, FALSE);
10586 emitcode ("mov", "%s,%s",
10588 aopGet (result, 0, FALSE, TRUE));
10589 rname = preg->name;
10594 rname = aopGet (result, 0, FALSE, FALSE);
10597 aopOp (right, ic, FALSE);
10599 /* if bitfield then unpack the bits */
10600 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10601 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10604 /* we can just get the values */
10605 int size = AOP_SIZE (right);
10610 l = aopGet (right, offset, FALSE, TRUE);
10611 if ((*l == '@') || (strcmp (l, "acc") == 0))
10614 emitcode ("mov", "@%s,a", rname);
10617 emitcode ("mov", "@%s,%s", rname, l);
10619 emitcode ("inc", "%s", rname);
10624 /* now some housekeeping stuff */
10625 if (aop) /* we had to allocate for this iCode */
10628 aopPut (result, rname, 0);
10629 freeAsmop (NULL, aop, ic, TRUE);
10633 /* we did not allocate which means left
10634 already in a pointer register, then
10635 if size > 0 && this could be used again
10636 we have to point it back to where it
10638 if ((AOP_SIZE (right) > 1 &&
10639 !OP_SYMBOL (result)->remat &&
10640 (OP_SYMBOL (result)->liveTo > ic->seq ||
10644 int size = AOP_SIZE (right) - 1;
10646 emitcode ("dec", "%s", rname);
10651 if (pi) pi->generated = 1;
10652 freeAsmop (result, NULL, ic, TRUE);
10653 freeAsmop (right, NULL, ic, TRUE);
10656 /*-----------------------------------------------------------------*/
10657 /* genPagedPointerSet - emitcode for Paged pointer put */
10658 /*-----------------------------------------------------------------*/
10660 genPagedPointerSet (operand * right,
10668 sym_link *retype, *letype;
10670 D (emitcode (";", "genPagedPointerSet"));
10672 retype = getSpec (operandType (right));
10673 letype = getSpec (operandType (result));
10675 aopOp (result, ic, FALSE);
10677 /* if the value is already in a pointer register
10678 then don't need anything more */
10679 if (!AOP_INPREG (AOP (result)))
10681 /* otherwise get a free pointer register */
10682 aop = newAsmop (0);
10683 preg = getFreePtr (ic, &aop, FALSE);
10684 emitcode ("mov", "%s,%s",
10686 aopGet (result, 0, FALSE, TRUE));
10687 rname = preg->name;
10690 rname = aopGet (result, 0, FALSE, FALSE);
10692 aopOp (right, ic, FALSE);
10694 /* if bitfield then unpack the bits */
10695 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10696 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10699 /* we have can just get the values */
10700 int size = AOP_SIZE (right);
10705 l = aopGet (right, offset, FALSE, TRUE);
10707 emitcode ("movx", "@%s,a", rname);
10710 emitcode ("inc", "%s", rname);
10716 /* now some housekeeping stuff */
10717 if (aop) /* we had to allocate for this iCode */
10720 aopPut (result, rname, 0);
10721 freeAsmop (NULL, aop, ic, TRUE);
10725 /* we did not allocate which means left
10726 already in a pointer register, then
10727 if size > 0 && this could be used again
10728 we have to point it back to where it
10730 if (AOP_SIZE (right) > 1 &&
10731 !OP_SYMBOL (result)->remat &&
10732 (OP_SYMBOL (result)->liveTo > ic->seq ||
10735 int size = AOP_SIZE (right) - 1;
10737 emitcode ("dec", "%s", rname);
10742 if (pi) pi->generated = 1;
10743 freeAsmop (result, NULL, ic, TRUE);
10744 freeAsmop (right, NULL, ic, TRUE);
10747 /*-----------------------------------------------------------------*/
10748 /* genFarPointerSet - set value from far space */
10749 /*-----------------------------------------------------------------*/
10751 genFarPointerSet (operand * right,
10752 operand * result, iCode * ic, iCode * pi)
10755 sym_link *retype = getSpec (operandType (right));
10756 sym_link *letype = getSpec (operandType (result));
10758 D(emitcode (";", "genFarPointerSet"));
10760 aopOp (result, ic, FALSE);
10761 loadDptrFromOperand (result, FALSE);
10763 /* so dptr now contains the address */
10764 aopOp (right, ic, FALSE);
10766 /* if bit then unpack */
10767 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10768 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10771 size = AOP_SIZE (right);
10776 char *l = aopGet (right, offset++, FALSE, FALSE);
10778 emitcode ("movx", "@dptr,a");
10780 emitcode ("inc", "dptr");
10783 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10784 aopPut (result, "dpl", 0);
10785 aopPut (result, "dph", 1);
10788 freeAsmop (result, NULL, ic, TRUE);
10789 freeAsmop (right, NULL, ic, TRUE);
10792 /*-----------------------------------------------------------------*/
10793 /* genGenPointerSet - set value from generic pointer space */
10794 /*-----------------------------------------------------------------*/
10796 genGenPointerSet (operand * right,
10797 operand * result, iCode * ic, iCode * pi)
10800 sym_link *retype = getSpec (operandType (right));
10801 sym_link *letype = getSpec (operandType (result));
10803 D (emitcode (";", "genGenPointerSet"));
10805 aopOp (result, ic, FALSE);
10806 loadDptrFromOperand (result, TRUE);
10808 /* so dptr now contains the address */
10809 aopOp (right, ic, FALSE);
10811 /* if bit then unpack */
10812 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10814 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10818 size = AOP_SIZE (right);
10823 char *l = aopGet (right, offset++, FALSE, FALSE);
10825 emitcode ("lcall", "__gptrput");
10827 emitcode ("inc", "dptr");
10831 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10832 aopPut (result, "dpl", 0);
10833 aopPut (result, "dph", 1);
10836 freeAsmop (result, NULL, ic, TRUE);
10837 freeAsmop (right, NULL, ic, TRUE);
10840 /*-----------------------------------------------------------------*/
10841 /* genPointerSet - stores the value into a pointer location */
10842 /*-----------------------------------------------------------------*/
10844 genPointerSet (iCode * ic, iCode *pi)
10846 operand *right, *result;
10847 sym_link *type, *etype;
10850 D (emitcode (";", "genPointerSet"));
10852 right = IC_RIGHT (ic);
10853 result = IC_RESULT (ic);
10855 /* depending on the type of pointer we need to
10856 move it to the correct pointer register */
10857 type = operandType (result);
10858 etype = getSpec (type);
10859 /* if left is of type of pointer then it is simple */
10860 if (IS_PTR (type) && !IS_FUNC (type->next))
10862 p_type = DCL_TYPE (type);
10866 /* we have to go by the storage class */
10867 p_type = PTR_TYPE (SPEC_OCLS (etype));
10870 /* special case when cast remat */
10871 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10872 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10873 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10874 type = operandType (result);
10875 p_type = DCL_TYPE (type);
10878 /* now that we have the pointer type we assign
10879 the pointer values */
10885 genNearPointerSet (right, result, ic, pi);
10889 genPagedPointerSet (right, result, ic, pi);
10893 genFarPointerSet (right, result, ic, pi);
10897 genGenPointerSet (right, result, ic, pi);
10901 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10902 "genPointerSet: illegal pointer type");
10906 /*-----------------------------------------------------------------*/
10907 /* genIfx - generate code for Ifx statement */
10908 /*-----------------------------------------------------------------*/
10910 genIfx (iCode * ic, iCode * popIc)
10912 operand *cond = IC_COND (ic);
10916 D (emitcode (";", "genIfx"));
10918 aopOp (cond, ic, FALSE);
10920 /* get the value into acc */
10921 if (AOP_TYPE (cond) != AOP_CRY)
10928 if (AOP(cond)->aopu.aop_dir)
10929 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10932 /* the result is now in the accumulator or a directly addressable bit */
10933 freeAsmop (cond, NULL, ic, TRUE);
10935 /* if there was something to be popped then do it */
10939 /* if the condition is a bit variable */
10941 genIfxJump(ic, dup, NULL, NULL, NULL);
10942 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10943 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10944 else if (isbit && !IS_ITEMP (cond))
10945 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10947 genIfxJump (ic, "a", NULL, NULL, NULL);
10952 /*-----------------------------------------------------------------*/
10953 /* genAddrOf - generates code for address of */
10954 /*-----------------------------------------------------------------*/
10956 genAddrOf (iCode * ic)
10958 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10961 D (emitcode (";", "genAddrOf"));
10963 aopOp (IC_RESULT (ic), ic, FALSE);
10965 /* if the operand is on the stack then we
10966 need to get the stack offset of this
10970 /* if it has an offset then we need to compute it */
10973 int stack_offset = ((sym->stack < 0) ?
10974 ((char) (sym->stack - _G.nRegsSaved)) :
10975 ((char) sym->stack)) & 0xff;
10976 if ((abs(stack_offset) == 1) &&
10977 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10978 !isOperandVolatile (IC_RESULT (ic), FALSE))
10980 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10981 if (stack_offset > 0)
10982 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10984 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10988 emitcode ("mov", "a,%s", SYM_BP (sym));
10989 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10990 aopPut (IC_RESULT (ic), "a", 0);
10995 /* we can just move _bp */
10996 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10998 /* fill the result with zero */
10999 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11004 aopPut (IC_RESULT (ic), zero, offset++);
11009 /* object not on stack then we need the name */
11010 size = AOP_SIZE (IC_RESULT (ic));
11015 char s[SDCC_NAME_MAX];
11017 sprintf (s, "#(%s >> %d)",
11021 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11022 aopPut (IC_RESULT (ic), s, offset++);
11026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11030 /*-----------------------------------------------------------------*/
11031 /* genFarFarAssign - assignment when both are in far space */
11032 /*-----------------------------------------------------------------*/
11034 genFarFarAssign (operand * result, operand * right, iCode * ic)
11036 int size = AOP_SIZE (right);
11040 D (emitcode (";", "genFarFarAssign"));
11042 /* first push the right side on to the stack */
11045 l = aopGet (right, offset++, FALSE, FALSE);
11047 emitcode ("push", "acc");
11050 freeAsmop (right, NULL, ic, FALSE);
11051 /* now assign DPTR to result */
11052 aopOp (result, ic, FALSE);
11053 size = AOP_SIZE (result);
11056 emitcode ("pop", "acc");
11057 aopPut (result, "a", --offset);
11059 freeAsmop (result, NULL, ic, FALSE);
11062 /*-----------------------------------------------------------------*/
11063 /* genAssign - generate code for assignment */
11064 /*-----------------------------------------------------------------*/
11066 genAssign (iCode * ic)
11068 operand *result, *right;
11070 unsigned long lit = 0L;
11072 D (emitcode (";", "genAssign"));
11074 result = IC_RESULT (ic);
11075 right = IC_RIGHT (ic);
11077 /* if they are the same */
11078 if (operandsEqu (result, right) &&
11079 !isOperandVolatile (result, FALSE) &&
11080 !isOperandVolatile (right, FALSE))
11083 aopOp (right, ic, FALSE);
11085 /* special case both in far space */
11086 if (AOP_TYPE (right) == AOP_DPTR &&
11087 IS_TRUE_SYMOP (result) &&
11088 isOperandInFarSpace (result))
11090 genFarFarAssign (result, right, ic);
11094 aopOp (result, ic, TRUE);
11096 /* if they are the same registers */
11097 if (sameRegs (AOP (right), AOP (result)) &&
11098 !isOperandVolatile (result, FALSE) &&
11099 !isOperandVolatile (right, FALSE))
11102 /* if the result is a bit */
11103 if (AOP_TYPE (result) == AOP_CRY)
11105 assignBit (result, right);
11109 /* bit variables done */
11111 size = AOP_SIZE (result);
11113 if (AOP_TYPE (right) == AOP_LIT)
11114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11117 (AOP_TYPE (result) != AOP_REG) &&
11118 (AOP_TYPE (right) == AOP_LIT) &&
11119 !IS_FLOAT (operandType (right)) &&
11122 while ((size) && (lit))
11125 aopGet (right, offset, FALSE, FALSE),
11131 /* And now fill the rest with zeros. */
11134 emitcode ("clr", "a");
11138 aopPut (result, "a", offset);
11147 aopGet (right, offset, FALSE, FALSE),
11154 freeAsmop (result, NULL, ic, TRUE);
11155 freeAsmop (right, NULL, ic, TRUE);
11158 /*-----------------------------------------------------------------*/
11159 /* genJumpTab - generates code for jump table */
11160 /*-----------------------------------------------------------------*/
11162 genJumpTab (iCode * ic)
11164 symbol *jtab,*jtablo,*jtabhi;
11166 unsigned int count;
11168 D (emitcode (";", "genJumpTab"));
11170 count = elementsInSet( IC_JTLABELS (ic) );
11174 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11175 if the switch argument is in a register.
11176 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11177 /* Peephole may not convert ljmp to sjmp or ret
11178 labelIsReturnOnly & labelInRange must check
11179 currPl->ic->op != JUMPTABLE */
11180 aopOp (IC_JTCOND (ic), ic, FALSE);
11181 /* get the condition into accumulator */
11182 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11184 /* multiply by three */
11185 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11187 emitcode ("mov", "b,#3");
11188 emitcode ("mul", "ab");
11192 emitcode ("add", "a,acc");
11193 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11195 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11197 jtab = newiTempLabel (NULL);
11198 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11199 emitcode ("jmp", "@a+dptr");
11201 /* now generate the jump labels */
11202 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11203 jtab = setNextItem (IC_JTLABELS (ic)))
11204 emitcode ("ljmp", "%05d$", jtab->key + 100);
11208 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11209 if the switch argument is in a register.
11210 For n>6 this algorithm may be more compact */
11211 jtablo = newiTempLabel (NULL);
11212 jtabhi = newiTempLabel (NULL);
11214 /* get the condition into accumulator.
11215 Using b as temporary storage, if register push/pop is needed */
11216 aopOp (IC_JTCOND (ic), ic, FALSE);
11217 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11218 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11219 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11221 // (MB) what if B is in use???
11222 wassertl(!BINUSE, "B was in use");
11223 emitcode ("mov", "b,%s", l);
11226 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11230 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11231 emitcode ("movc", "a,@a+pc");
11232 emitcode ("push", "acc");
11235 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11236 emitcode ("movc", "a,@a+pc");
11237 emitcode ("push", "acc");
11241 /* this scales up to n<=255, but needs two more bytes
11242 and changes dptr */
11243 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11244 emitcode ("movc", "a,@a+dptr");
11245 emitcode ("push", "acc");
11248 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11249 emitcode ("movc", "a,@a+dptr");
11250 emitcode ("push", "acc");
11253 emitcode ("ret", "");
11255 /* now generate jump table, LSB */
11256 emitLabel (jtablo);
11257 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11258 jtab = setNextItem (IC_JTLABELS (ic)))
11259 emitcode (".db", "%05d$", jtab->key + 100);
11261 /* now generate jump table, MSB */
11262 emitLabel (jtabhi);
11263 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11264 jtab = setNextItem (IC_JTLABELS (ic)))
11265 emitcode (".db", "%05d$>>8", jtab->key + 100);
11269 /*-----------------------------------------------------------------*/
11270 /* genCast - gen code for casting */
11271 /*-----------------------------------------------------------------*/
11273 genCast (iCode * ic)
11275 operand *result = IC_RESULT (ic);
11276 sym_link *ctype = operandType (IC_LEFT (ic));
11277 sym_link *rtype = operandType (IC_RIGHT (ic));
11278 operand *right = IC_RIGHT (ic);
11281 D (emitcode (";", "genCast"));
11283 /* if they are equivalent then do nothing */
11284 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11287 aopOp (right, ic, FALSE);
11288 aopOp (result, ic, FALSE);
11290 /* if the result is a bit (and not a bitfield) */
11291 if (IS_BIT (OP_SYMBOL (result)->type))
11293 assignBit (result, right);
11297 /* if they are the same size : or less */
11298 if (AOP_SIZE (result) <= AOP_SIZE (right))
11301 /* if they are in the same place */
11302 if (sameRegs (AOP (right), AOP (result)))
11305 /* if they in different places then copy */
11306 size = AOP_SIZE (result);
11311 aopGet (right, offset, FALSE, FALSE),
11318 /* if the result is of type pointer */
11319 if (IS_PTR (ctype))
11323 sym_link *type = operandType (right);
11324 sym_link *etype = getSpec (type);
11326 /* pointer to generic pointer */
11327 if (IS_GENPTR (ctype))
11331 p_type = DCL_TYPE (type);
11335 if (SPEC_SCLS(etype)==S_REGISTER) {
11336 // let's assume it is a generic pointer
11339 /* we have to go by the storage class */
11340 p_type = PTR_TYPE (SPEC_OCLS (etype));
11344 /* the first two bytes are known */
11345 size = GPTRSIZE - 1;
11350 aopGet (right, offset, FALSE, FALSE),
11354 /* the last byte depending on type */
11356 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11361 // pointerTypeToGPByte will have bitched.
11365 sprintf(gpValStr, "#0x%x", gpVal);
11366 aopPut (result, gpValStr, GPTRSIZE - 1);
11371 /* just copy the pointers */
11372 size = AOP_SIZE (result);
11377 aopGet (right, offset, FALSE, FALSE),
11384 /* so we now know that the size of destination is greater
11385 than the size of the source */
11386 /* we move to result for the size of source */
11387 size = AOP_SIZE (right);
11392 aopGet (right, offset, FALSE, FALSE),
11397 /* now depending on the sign of the source && destination */
11398 size = AOP_SIZE (result) - AOP_SIZE (right);
11399 /* if unsigned or not an integral type */
11400 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11403 aopPut (result, zero, offset++);
11407 /* we need to extend the sign :{ */
11408 char *l = aopGet (right, AOP_SIZE (right) - 1,
11411 emitcode ("rlc", "a");
11412 emitcode ("subb", "a,acc");
11414 aopPut (result, "a", offset++);
11417 /* we are done hurray !!!! */
11420 freeAsmop (result, NULL, ic, TRUE);
11421 freeAsmop (right, NULL, ic, TRUE);
11424 /*-----------------------------------------------------------------*/
11425 /* genDjnz - generate decrement & jump if not zero instrucion */
11426 /*-----------------------------------------------------------------*/
11428 genDjnz (iCode * ic, iCode * ifx)
11430 symbol *lbl, *lbl1;
11434 /* if the if condition has a false label
11435 then we cannot save */
11436 if (IC_FALSE (ifx))
11439 /* if the minus is not of the form a = a - 1 */
11440 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11441 !IS_OP_LITERAL (IC_RIGHT (ic)))
11444 if (operandLitValue (IC_RIGHT (ic)) != 1)
11447 /* if the size of this greater than one then no
11449 if (getSize (operandType (IC_RESULT (ic))) > 1)
11452 /* otherwise we can save BIG */
11454 D (emitcode (";", "genDjnz"));
11456 lbl = newiTempLabel (NULL);
11457 lbl1 = newiTempLabel (NULL);
11459 aopOp (IC_RESULT (ic), ic, FALSE);
11461 if (AOP_NEEDSACC(IC_RESULT(ic)))
11463 /* If the result is accessed indirectly via
11464 * the accumulator, we must explicitly write
11465 * it back after the decrement.
11467 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11469 if (strcmp(rByte, "a"))
11471 /* Something is hopelessly wrong */
11472 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11473 __FILE__, __LINE__);
11474 /* We can just give up; the generated code will be inefficient,
11475 * but what the hey.
11477 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11480 emitcode ("dec", "%s", rByte);
11481 aopPut (IC_RESULT (ic), rByte, 0);
11482 emitcode ("jnz", "%05d$", lbl->key + 100);
11484 else if (IS_AOP_PREG (IC_RESULT (ic)))
11486 emitcode ("dec", "%s",
11487 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11488 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11490 ifx->generated = 1;
11491 emitcode ("jnz", "%05d$", lbl->key + 100);
11495 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11498 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11500 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11503 if (!ifx->generated)
11504 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11505 ifx->generated = 1;
11509 /*-----------------------------------------------------------------*/
11510 /* genReceive - generate code for a receive iCode */
11511 /*-----------------------------------------------------------------*/
11513 genReceive (iCode * ic)
11515 int size = getSize (operandType (IC_RESULT (ic)));
11518 D (emitcode (";", "genReceive"));
11520 if (ic->argreg == 1)
11521 { /* first parameter */
11522 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11523 isOperandInPagedSpace (IC_RESULT (ic))) &&
11524 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11525 IS_TRUE_SYMOP (IC_RESULT (ic))))
11528 int receivingA = 0;
11531 for (offset = 0; offset<size; offset++)
11532 if (!strcmp (fReturn[offset], "a"))
11537 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11539 for (offset = size-1; offset>0; offset--)
11540 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11541 emitcode("mov","a,%s", fReturn[0]);
11543 aopOp (IC_RESULT (ic), ic, FALSE);
11545 aopPut (IC_RESULT (ic), "a", offset);
11546 for (offset = 1; offset<size; offset++)
11547 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11553 if (getTempRegs(tempRegs, size, ic))
11555 for (offset = 0; offset<size; offset++)
11556 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11557 aopOp (IC_RESULT (ic), ic, FALSE);
11558 for (offset = 0; offset<size; offset++)
11559 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11564 offset = fReturnSizeMCS51 - size;
11567 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11568 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11571 aopOp (IC_RESULT (ic), ic, FALSE);
11572 size = AOP_SIZE (IC_RESULT (ic));
11576 emitcode ("pop", "acc");
11577 aopPut (IC_RESULT (ic), "a", offset++);
11583 aopOp (IC_RESULT (ic), ic, FALSE);
11585 assignResultValue (IC_RESULT (ic), NULL);
11588 else if (ic->argreg > 12)
11589 { /* bit parameters */
11590 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11592 aopOp (IC_RESULT (ic), ic, FALSE);
11593 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11594 outBitC(IC_RESULT (ic));
11598 { /* other parameters */
11600 aopOp (IC_RESULT (ic), ic, FALSE);
11601 rb1off = ic->argreg;
11604 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11609 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11612 /*-----------------------------------------------------------------*/
11613 /* genDummyRead - generate code for dummy read of volatiles */
11614 /*-----------------------------------------------------------------*/
11616 genDummyRead (iCode * ic)
11621 D (emitcode(";", "genDummyRead"));
11623 op = IC_RIGHT (ic);
11624 if (op && IS_SYMOP (op))
11626 aopOp (op, ic, FALSE);
11628 /* if the result is a bit */
11629 if (AOP_TYPE (op) == AOP_CRY)
11630 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11633 /* bit variables done */
11635 size = AOP_SIZE (op);
11639 MOVA (aopGet (op, offset, FALSE, FALSE));
11644 freeAsmop (op, NULL, ic, TRUE);
11648 if (op && IS_SYMOP (op))
11650 aopOp (op, ic, FALSE);
11652 /* if the result is a bit */
11653 if (AOP_TYPE (op) == AOP_CRY)
11654 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11657 /* bit variables done */
11659 size = AOP_SIZE (op);
11663 MOVA (aopGet (op, offset, FALSE, FALSE));
11668 freeAsmop (op, NULL, ic, TRUE);
11672 /*-----------------------------------------------------------------*/
11673 /* genCritical - generate code for start of a critical sequence */
11674 /*-----------------------------------------------------------------*/
11676 genCritical (iCode *ic)
11678 symbol *tlbl = newiTempLabel (NULL);
11680 D (emitcode(";", "genCritical"));
11682 if (IC_RESULT (ic))
11684 aopOp (IC_RESULT (ic), ic, TRUE);
11685 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11686 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11687 aopPut (IC_RESULT (ic), zero, 0);
11689 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11693 emitcode ("setb", "c");
11694 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11695 emitcode ("clr", "c");
11697 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11701 /*-----------------------------------------------------------------*/
11702 /* genEndCritical - generate code for end of a critical sequence */
11703 /*-----------------------------------------------------------------*/
11705 genEndCritical (iCode *ic)
11707 D(emitcode(";", "genEndCritical"));
11711 aopOp (IC_RIGHT (ic), ic, FALSE);
11712 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11714 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11715 emitcode ("mov", "ea,c");
11719 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11720 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11721 emitcode ("rrc", "a");
11722 emitcode ("mov", "ea,c");
11724 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11728 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11729 emitcode ("mov", "ea,c");
11733 /*-----------------------------------------------------------------*/
11734 /* gen51Code - generate code for 8051 based controllers */
11735 /*-----------------------------------------------------------------*/
11737 gen51Code (iCode * lic)
11741 /* int cseq = 0; */
11743 _G.currentFunc = NULL;
11744 lineHead = lineCurr = NULL;
11746 /* print the allocation information */
11747 if (allocInfo && currFunc)
11748 printAllocInfo (currFunc, codeOutBuf);
11749 /* if debug information required */
11750 if (options.debug && currFunc)
11752 debugFile->writeFunction (currFunc, lic);
11754 /* stack pointer name */
11755 if (options.useXstack)
11761 for (ic = lic; ic; ic = ic->next)
11763 _G.current_iCode = ic;
11765 if (ic->lineno && cln != ic->lineno)
11769 debugFile->writeCLine (ic);
11771 if (!options.noCcodeInAsm) {
11772 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11773 printCLine(ic->filename, ic->lineno));
11778 if (ic->seqPoint && ic->seqPoint != cseq)
11780 emitcode (";", "sequence point %d", ic->seqPoint);
11781 cseq = ic->seqPoint;
11784 if (options.iCodeInAsm) {
11785 char regsInUse[80];
11790 for (i=0; i<8; i++) {
11791 sprintf (®sInUse[i],
11792 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11795 strcpy (regsInUse, "--------");
11796 for (i=0; i < 8; i++) {
11797 if (bitVectBitValue (ic->rMask, i))
11799 int offset = regs8051[i].offset;
11800 regsInUse[offset] = offset + '0'; /* show rMask */
11804 iLine = printILine(ic);
11805 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11808 /* if the result is marked as
11809 spilt and rematerializable or code for
11810 this has already been generated then
11812 if (resultRemat (ic) || ic->generated)
11815 /* depending on the operation */
11835 /* IPOP happens only when trying to restore a
11836 spilt live range, if there is an ifx statement
11837 following this pop then the if statement might
11838 be using some of the registers being popped which
11839 would destory the contents of the register so
11840 we need to check for this condition and handle it */
11842 ic->next->op == IFX &&
11843 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11844 genIfx (ic->next, ic);
11862 genEndFunction (ic);
11882 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11899 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11903 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11910 /* note these two are xlated by algebraic equivalence
11911 in decorateType() in SDCCast.c */
11912 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11913 "got '>=' or '<=' shouldn't have come here");
11917 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11929 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11933 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11937 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11973 genRightShift (ic);
11976 case GET_VALUE_AT_ADDRESS:
11978 hasInc (IC_LEFT (ic), ic,
11979 getSize (operandType (IC_RESULT (ic)))),
11980 ifxForOp (IC_RESULT (ic), ic) );
11984 if (POINTER_SET (ic))
11986 hasInc (IC_RESULT (ic), ic,
11987 getSize (operandType (IC_RIGHT (ic)))));
12013 addSet (&_G.sendSet, ic);
12016 case DUMMY_READ_VOLATILE:
12025 genEndCritical (ic);
12037 _G.current_iCode = NULL;
12039 /* now we are ready to call the
12040 peep hole optimizer */
12041 if (!options.nopeep)
12042 peepHole (&lineHead);
12044 /* now do the actual printing */
12045 printLine (lineHead, codeOutBuf);