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 = operandSize (op);
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);
1495 const char *d = NULL;
1497 if (aop->size && offset > (aop->size - 1))
1499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1500 "aopPut got offset > aop->size");
1504 /* will assign value to value */
1505 /* depending on where it is ofcourse */
1509 MOVA (s); /* read s in case it was volatile */
1514 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1516 SNPRINTF (buffer, sizeof(buffer),
1518 aop->aopu.aop_dir, offset * 8);
1522 SNPRINTF (buffer, sizeof(buffer),
1524 aop->aopu.aop_dir, offset);
1528 SNPRINTF (buffer, sizeof(buffer),
1533 if (strcmp (buffer, s) || bvolatile)
1535 emitcode ("mov", "%s,%s", buffer, s);
1537 if (!strcmp (buffer, "acc"))
1544 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1545 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1548 strcmp (s, "r0") == 0 ||
1549 strcmp (s, "r1") == 0 ||
1550 strcmp (s, "r2") == 0 ||
1551 strcmp (s, "r3") == 0 ||
1552 strcmp (s, "r4") == 0 ||
1553 strcmp (s, "r5") == 0 ||
1554 strcmp (s, "r6") == 0 ||
1555 strcmp (s, "r7") == 0)
1557 emitcode ("mov", "%s,%s",
1558 aop->aopu.aop_reg[offset]->dname, s);
1562 emitcode ("mov", "%s,%s",
1563 aop->aopu.aop_reg[offset]->name, s);
1571 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1572 "aopPut writing to code space");
1576 while (offset > aop->coff)
1579 emitcode ("inc", "dptr");
1582 while (offset < aop->coff)
1585 emitcode ("lcall", "__decdptr");
1590 /* if not in accumulator */
1593 emitcode ("movx", "@dptr,a");
1598 while (offset > aop->coff)
1601 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1603 while (offset < aop->coff)
1606 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1613 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1618 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1620 else if (strcmp (s, "r0") == 0 ||
1621 strcmp (s, "r1") == 0 ||
1622 strcmp (s, "r2") == 0 ||
1623 strcmp (s, "r3") == 0 ||
1624 strcmp (s, "r4") == 0 ||
1625 strcmp (s, "r5") == 0 ||
1626 strcmp (s, "r6") == 0 ||
1627 strcmp (s, "r7") == 0)
1630 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1631 emitcode ("mov", "@%s,%s",
1632 aop->aopu.aop_ptr->name, buffer);
1636 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1641 if (strcmp (s, "a") == 0)
1643 emitcode ("push", "acc");
1648 emitcode ("push", "acc");
1650 else if (strcmp (s, "r0") == 0 ||
1651 strcmp (s, "r1") == 0 ||
1652 strcmp (s, "r2") == 0 ||
1653 strcmp (s, "r3") == 0 ||
1654 strcmp (s, "r4") == 0 ||
1655 strcmp (s, "r5") == 0 ||
1656 strcmp (s, "r6") == 0 ||
1657 strcmp (s, "r7") == 0)
1660 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1661 emitcode ("push", buffer);
1665 emitcode ("push", s);
1671 // destination is carry for return-use-only
1672 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1673 // source is no literal and not in carry
1674 if ((s != zero) && (s != one) && strcmp (s, "c"))
1677 /* set C, if a >= 1 */
1678 emitcode ("add", "a,#0xff");
1681 // now source is zero, one or carry
1683 /* if result no bit variable */
1686 if (!strcmp (s, "c"))
1688 /* inefficient: move carry into A and use jz/jnz */
1689 emitcode ("clr", "a");
1690 emitcode ("rlc", "a");
1700 emitcode ("clr", "%s", d);
1702 emitcode ("setb", "%s", d);
1703 else if (strcmp (s, d))
1704 emitcode ("mov", "%s,c", d);
1709 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1710 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1716 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1719 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1720 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1724 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1725 "aopPut got unsupported aop->type");
1734 /*-----------------------------------------------------------------*/
1735 /* pointToEnd :- points to the last byte of the operand */
1736 /*-----------------------------------------------------------------*/
1738 pointToEnd (asmop * aop)
1744 aop->coff = count = (aop->size - 1);
1750 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1754 emitcode ("inc", "dptr");
1761 /*-----------------------------------------------------------------*/
1762 /* reAdjustPreg - points a register back to where it should */
1763 /*-----------------------------------------------------------------*/
1765 reAdjustPreg (asmop * aop)
1767 if ((aop->coff==0) || (aop->size <= 1))
1775 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1780 emitcode ("lcall", "__decdptr");
1787 /*-----------------------------------------------------------------*/
1788 /* opIsGptr: returns non-zero if the passed operand is */
1789 /* a generic pointer type. */
1790 /*-----------------------------------------------------------------*/
1792 opIsGptr (operand * op)
1794 sym_link *type = operandType (op);
1796 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1803 /*-----------------------------------------------------------------*/
1804 /* getDataSize - get the operand data size */
1805 /*-----------------------------------------------------------------*/
1807 getDataSize (operand * op)
1810 size = AOP_SIZE (op);
1811 if (size == GPTRSIZE)
1813 sym_link *type = operandType (op);
1814 if (IS_GENPTR (type))
1816 /* generic pointer; arithmetic operations
1817 * should ignore the high byte (pointer type).
1825 /*-----------------------------------------------------------------*/
1826 /* outAcc - output Acc */
1827 /*-----------------------------------------------------------------*/
1829 outAcc (operand * result)
1832 size = getDataSize (result);
1835 aopPut (result, "a", 0);
1838 /* unsigned or positive */
1841 aopPut (result, zero, offset++);
1846 /*-----------------------------------------------------------------*/
1847 /* outBitC - output a bit C */
1848 /*-----------------------------------------------------------------*/
1850 outBitC (operand * result)
1852 /* if the result is bit */
1853 if (AOP_TYPE (result) == AOP_CRY)
1855 if (!IS_OP_RUONLY (result))
1856 aopPut (result, "c", 0);
1860 emitcode ("clr", "a");
1861 emitcode ("rlc", "a");
1866 /*-----------------------------------------------------------------*/
1867 /* toBoolean - emit code for orl a,operator(sizeop) */
1868 /*-----------------------------------------------------------------*/
1870 toBoolean (operand * oper)
1872 int size = AOP_SIZE (oper) - 1;
1874 bool AccUsed = FALSE;
1877 while (!AccUsed && size--)
1879 AccUsed |= aopGetUsesAcc(oper, offset++);
1882 size = AOP_SIZE (oper) - 1;
1884 MOVA (aopGet (oper, 0, FALSE, FALSE));
1885 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1888 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1892 emitcode ("orl", "b,a");
1894 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1895 emitcode ("orl", "a,b");
1902 emitcode ("orl", "a,%s",
1903 aopGet (oper, offset++, FALSE, FALSE));
1908 /*-----------------------------------------------------------------*/
1909 /* toCarry - make boolean and move into carry */
1910 /*-----------------------------------------------------------------*/
1912 toCarry (operand * oper)
1914 /* if the operand is a literal then
1915 we know what the value is */
1916 if (AOP_TYPE (oper) == AOP_LIT)
1918 if ((int) operandLitValue (oper))
1923 else if (AOP_TYPE (oper) == AOP_CRY)
1925 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1929 /* or the operand into a */
1931 /* set C, if a >= 1 */
1932 emitcode ("add", "a,#0xff");
1936 /*-----------------------------------------------------------------*/
1937 /* assignBit - assign operand to bit operand */
1938 /*-----------------------------------------------------------------*/
1940 assignBit (operand * result, operand * right)
1942 /* if the right side is a literal then
1943 we know what the value is */
1944 if (AOP_TYPE (right) == AOP_LIT)
1946 if ((int) operandLitValue (right))
1947 aopPut (result, one, 0);
1949 aopPut (result, zero, 0);
1954 aopPut (result, "c", 0);
1959 /*-------------------------------------------------------------------*/
1960 /* xch_a_aopGet - for exchanging acc with value of the aop */
1961 /*-------------------------------------------------------------------*/
1963 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1967 if (aopGetUsesAcc (oper, offset))
1969 emitcode("mov", "b,a");
1970 MOVA (aopGet (oper, offset, bit16, dname));
1971 emitcode("xch", "a,b");
1972 aopPut (oper, "a", offset);
1973 emitcode("xch", "a,b");
1978 l = aopGet (oper, offset, bit16, dname);
1979 emitcode("xch", "a,%s", l);
1985 /*-----------------------------------------------------------------*/
1986 /* genNot - generate code for ! operation */
1987 /*-----------------------------------------------------------------*/
1993 D (emitcode (";", "genNot"));
1995 /* assign asmOps to operand & result */
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1997 aopOp (IC_RESULT (ic), ic, TRUE);
1999 /* if in bit space then a special case */
2000 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2002 /* if left==result then cpl bit */
2003 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2005 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2009 toCarry (IC_LEFT (ic));
2010 emitcode ("cpl", "c");
2011 outBitC (IC_RESULT (ic));
2016 toBoolean (IC_LEFT (ic));
2018 /* set C, if a == 0 */
2019 tlbl = newiTempLabel (NULL);
2020 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2022 outBitC (IC_RESULT (ic));
2025 /* release the aops */
2026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2027 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2031 /*-----------------------------------------------------------------*/
2032 /* genCpl - generate code for complement */
2033 /*-----------------------------------------------------------------*/
2040 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2042 D(emitcode (";", "genCpl"));
2044 /* assign asmOps to operand & result */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2046 aopOp (IC_RESULT (ic), ic, TRUE);
2048 /* special case if in bit space */
2049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2054 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2056 /* promotion rules are responsible for this strange result:
2057 bit -> int -> ~int -> bit
2058 uchar -> int -> ~int -> bit
2060 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2064 tlbl=newiTempLabel(NULL);
2065 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2066 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2068 IS_AOP_PREG (IC_LEFT (ic)))
2070 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2075 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2078 outBitC (IC_RESULT(ic));
2082 size = AOP_SIZE (IC_RESULT (ic));
2085 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2087 emitcode ("cpl", "a");
2088 aopPut (IC_RESULT (ic), "a", offset++);
2093 /* release the aops */
2094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2098 /*-----------------------------------------------------------------*/
2099 /* genUminusFloat - unary minus for floating points */
2100 /*-----------------------------------------------------------------*/
2102 genUminusFloat (operand * op, operand * result)
2104 int size, offset = 0;
2107 D (emitcode (";", "genUminusFloat"));
2109 /* for this we just copy and then flip the bit */
2111 size = AOP_SIZE (op) - 1;
2116 aopGet (op, offset, FALSE, FALSE),
2121 l = aopGet (op, offset, FALSE, FALSE);
2124 emitcode ("cpl", "acc.7");
2125 aopPut (result, "a", offset);
2128 /*-----------------------------------------------------------------*/
2129 /* genUminus - unary minus code generation */
2130 /*-----------------------------------------------------------------*/
2132 genUminus (iCode * ic)
2137 D (emitcode (";", "genUminus"));
2140 aopOp (IC_LEFT (ic), ic, FALSE);
2141 aopOp (IC_RESULT (ic), ic, TRUE);
2143 /* if both in bit space then special
2145 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2146 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2149 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2150 emitcode ("cpl", "c");
2151 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2155 optype = operandType (IC_LEFT (ic));
2157 /* if float then do float stuff */
2158 if (IS_FLOAT (optype))
2160 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2164 /* otherwise subtract from zero */
2165 size = AOP_SIZE (IC_LEFT (ic));
2169 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2170 if (!strcmp (l, "a"))
2174 emitcode ("cpl", "a");
2175 emitcode ("addc", "a,#0");
2181 emitcode ("clr", "a");
2182 emitcode ("subb", "a,%s", l);
2184 aopPut (IC_RESULT (ic), "a", offset++);
2187 /* if any remaining bytes in the result */
2188 /* we just need to propagate the sign */
2189 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2191 emitcode ("rlc", "a");
2192 emitcode ("subb", "a,acc");
2194 aopPut (IC_RESULT (ic), "a", offset++);
2198 /* release the aops */
2199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2200 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2203 /*-----------------------------------------------------------------*/
2204 /* saveRegisters - will look for a call and save the registers */
2205 /*-----------------------------------------------------------------*/
2207 saveRegisters (iCode * lic)
2214 for (ic = lic; ic; ic = ic->next)
2215 if (ic->op == CALL || ic->op == PCALL)
2220 fprintf (stderr, "found parameter push with no function call\n");
2224 /* if the registers have been saved already or don't need to be then
2228 if (IS_SYMOP(IC_LEFT(ic)) &&
2229 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2230 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2233 /* save the registers in use at this time but skip the
2234 ones for the result */
2235 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2236 mcs51_rUmaskForOp (IC_RESULT(ic)));
2239 if (options.useXstack)
2241 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2242 int nBits = bitVectnBitsOn (rsavebits);
2243 int count = bitVectnBitsOn (rsave);
2247 count = count - nBits + 1;
2248 /* remove all but the first bits as they are pushed all at once */
2249 rsave = bitVectCplAnd (rsave, rsavebits);
2250 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2252 freeBitVect (rsavebits);
2256 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2257 if (reg->type == REG_BIT)
2259 emitcode ("mov", "a,%s", reg->base);
2263 emitcode ("mov", "a,%s", reg->name);
2265 emitcode ("mov", "r0,%s", spname);
2266 emitcode ("inc", "%s", spname);// allocate before use
2267 emitcode ("movx", "@r0,a");
2268 if (bitVectBitValue (rsave, R0_IDX))
2269 emitcode ("mov", "r0,a");
2271 else if (count != 0)
2273 if (bitVectBitValue (rsave, R0_IDX))
2275 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2277 emitcode ("mov", "r0,%s", spname);
2279 emitcode ("add", "a,#%d", count);
2280 emitcode ("mov", "%s,a", spname);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (bitVectBitValue (rsave, i))
2285 regs * reg = REG_WITH_INDEX (i);
2288 emitcode ("pop", "acc");
2289 emitcode ("push", "acc");
2291 else if (reg->type == REG_BIT)
2293 emitcode ("mov", "a,%s", reg->base);
2297 emitcode ("mov", "a,%s", reg->name);
2299 emitcode ("movx", "@r0,a");
2302 emitcode ("inc", "r0");
2306 if (bitVectBitValue (rsave, R0_IDX))
2308 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2314 bool bits_pushed = FALSE;
2315 for (i = 0; i < mcs51_nRegs; i++)
2317 if (bitVectBitValue (rsave, i))
2319 bits_pushed = pushReg (i, bits_pushed);
2323 freeBitVect (rsave);
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers */
2328 /*-----------------------------------------------------------------*/
2330 unsaveRegisters (iCode * ic)
2335 /* restore the registers in use at this time but skip the
2336 ones for the result */
2337 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2338 mcs51_rUmaskForOp (IC_RESULT(ic)));
2340 if (options.useXstack)
2342 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2343 int nBits = bitVectnBitsOn (rsavebits);
2344 int count = bitVectnBitsOn (rsave);
2348 count = count - nBits + 1;
2349 /* remove all but the first bits as they are popped all at once */
2350 rsave = bitVectCplAnd (rsave, rsavebits);
2351 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2353 freeBitVect (rsavebits);
2357 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2358 emitcode ("mov", "r0,%s", spname);
2359 emitcode ("dec", "r0");
2360 emitcode ("movx", "a,@r0");
2361 if (reg->type == REG_BIT)
2363 emitcode ("mov", "%s,a", reg->base);
2367 emitcode ("mov", "%s,a", reg->name);
2369 emitcode ("dec", "%s", spname);
2371 else if (count != 0)
2373 emitcode ("mov", "r0,%s", spname);
2374 for (i = mcs51_nRegs; i >= 0; i--)
2376 if (bitVectBitValue (rsave, i))
2378 regs * reg = REG_WITH_INDEX (i);
2379 emitcode ("dec", "r0");
2380 emitcode ("movx", "a,@r0");
2383 emitcode ("push", "acc");
2385 else if (reg->type == REG_BIT)
2387 emitcode ("mov", "%s,a", reg->base);
2391 emitcode ("mov", "%s,a", reg->name);
2395 emitcode ("mov", "%s,r0", spname);
2396 if (bitVectBitValue (rsave, R0_IDX))
2398 emitcode ("pop", "ar0");
2404 bool bits_popped = FALSE;
2405 for (i = mcs51_nRegs; i >= 0; i--)
2407 if (bitVectBitValue (rsave, i))
2409 bits_popped = popReg (i, bits_popped);
2413 freeBitVect (rsave);
2417 /*-----------------------------------------------------------------*/
2419 /*-----------------------------------------------------------------*/
2421 pushSide (operand * oper, int size)
2426 char *l = aopGet (oper, offset++, FALSE, TRUE);
2427 if (AOP_TYPE (oper) != AOP_REG &&
2428 AOP_TYPE (oper) != AOP_DIR &&
2432 emitcode ("push", "acc");
2436 emitcode ("push", "%s", l);
2441 /*-----------------------------------------------------------------*/
2442 /* assignResultValue - also indicates if acc is in use afterwards */
2443 /*-----------------------------------------------------------------*/
2445 assignResultValue (operand * oper, operand * func)
2448 int size = AOP_SIZE (oper);
2449 bool accuse = FALSE;
2450 bool pushedA = FALSE;
2452 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2458 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2460 emitcode ("push", "acc");
2465 if ((offset == 3) && pushedA)
2466 emitcode ("pop", "acc");
2467 accuse |= aopPut (oper, fReturn[offset], offset);
2474 /*-----------------------------------------------------------------*/
2475 /* genXpush - pushes onto the external stack */
2476 /*-----------------------------------------------------------------*/
2478 genXpush (iCode * ic)
2480 asmop *aop = newAsmop (0);
2482 int size, offset = 0;
2484 D (emitcode (";", "genXpush"));
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2487 r = getFreePtr (ic, &aop, FALSE);
2489 size = AOP_SIZE (IC_LEFT (ic));
2493 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2494 emitcode ("mov", "%s,%s", r->name, spname);
2495 emitcode ("inc", "%s", spname); // allocate space first
2496 emitcode ("movx", "@%s,a", r->name);
2500 // allocate space first
2501 emitcode ("mov", "%s,%s", r->name, spname);
2503 emitcode ("add", "a,#%d", size);
2504 emitcode ("mov", "%s,a", spname);
2508 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2509 emitcode ("movx", "@%s,a", r->name);
2510 emitcode ("inc", "%s", r->name);
2514 freeAsmop (NULL, aop, ic, TRUE);
2515 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2518 /*-----------------------------------------------------------------*/
2519 /* genIpush - generate code for pushing this gets a little complex */
2520 /*-----------------------------------------------------------------*/
2522 genIpush (iCode * ic)
2524 int size, offset = 0;
2528 D (emitcode (";", "genIpush"));
2530 /* if this is not a parm push : ie. it is spill push
2531 and spill push is always done on the local stack */
2535 /* and the item is spilt then do nothing */
2536 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2539 aopOp (IC_LEFT (ic), ic, FALSE);
2540 size = AOP_SIZE (IC_LEFT (ic));
2541 /* push it on the stack */
2544 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2550 emitcode ("push", "%s", l);
2555 /* this is a parameter push: in this case we call
2556 the routine to find the call and save those
2557 registers that need to be saved */
2560 /* if use external stack then call the external
2561 stack pushing routine */
2562 if (options.useXstack)
2568 /* then do the push */
2569 aopOp (IC_LEFT (ic), ic, FALSE);
2571 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2572 size = AOP_SIZE (IC_LEFT (ic));
2576 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2577 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2578 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2580 if (strcmp (l, prev) || *l == '@')
2582 emitcode ("push", "acc");
2586 emitcode ("push", "%s", l);
2591 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling */
2596 /*-----------------------------------------------------------------*/
2598 genIpop (iCode * ic)
2602 D (emitcode (";", "genIpop"));
2604 /* if the temp was not pushed then */
2605 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2608 aopOp (IC_LEFT (ic), ic, FALSE);
2609 size = AOP_SIZE (IC_LEFT (ic));
2610 offset = (size - 1);
2613 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2617 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* saveRBank - saves an entire register bank on the stack */
2622 /*-----------------------------------------------------------------*/
2624 saveRBank (int bank, iCode * ic, bool pushPsw)
2627 int count = 8 + (pushPsw ? 1 : 0);
2631 if (options.useXstack)
2635 /* Assume r0 is available for use. */
2636 r = REG_WITH_INDEX (R0_IDX);
2641 r = getFreePtr (ic, &aop, FALSE);
2643 // allocate space first
2644 emitcode ("mov", "%s,%s", r->name, spname);
2646 emitcode ("add", "a,#%d", count);
2647 emitcode ("mov", "%s,a", spname);
2650 for (i = 0; i < 8; i++)
2652 if (options.useXstack)
2654 emitcode ("mov", "a,(%s+%d)",
2655 regs8051[i].base, 8 * bank + regs8051[i].offset);
2656 emitcode ("movx", "@%s,a", r->name);
2658 emitcode ("inc", "%s", r->name);
2661 emitcode ("push", "(%s+%d)",
2662 regs8051[i].base, 8 * bank + regs8051[i].offset);
2667 if (options.useXstack)
2669 emitcode ("mov", "a,psw");
2670 emitcode ("movx", "@%s,a", r->name);
2674 emitcode ("push", "psw");
2677 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2682 freeAsmop (NULL, aop, ic, TRUE);
2691 /*-----------------------------------------------------------------*/
2692 /* unsaveRBank - restores the register bank from stack */
2693 /*-----------------------------------------------------------------*/
2695 unsaveRBank (int bank, iCode * ic, bool popPsw)
2701 if (options.useXstack)
2705 /* Assume r0 is available for use. */
2706 r = REG_WITH_INDEX (R0_IDX);;
2711 r = getFreePtr (ic, &aop, FALSE);
2713 emitcode ("mov", "%s,%s", r->name, spname);
2718 if (options.useXstack)
2720 emitcode ("dec", "%s", r->name);
2721 emitcode ("movx", "a,@%s", r->name);
2722 emitcode ("mov", "psw,a");
2726 emitcode ("pop", "psw");
2730 for (i = 7; i >= 0; i--)
2732 if (options.useXstack)
2734 emitcode ("dec", "%s", r->name);
2735 emitcode ("movx", "a,@%s", r->name);
2736 emitcode ("mov", "(%s+%d),a",
2737 regs8051[i].base, 8 * bank + regs8051[i].offset);
2741 emitcode ("pop", "(%s+%d)",
2742 regs8051[i].base, 8 * bank + regs8051[i].offset);
2746 if (options.useXstack)
2748 emitcode ("mov", "%s,%s", spname, r->name);
2753 freeAsmop (NULL, aop, ic, TRUE);
2757 /*-----------------------------------------------------------------*/
2758 /* genSend - gen code for SEND */
2759 /*-----------------------------------------------------------------*/
2760 static void genSend(set *sendSet)
2765 /* first we do all bit parameters */
2766 for (sic = setFirstItem (sendSet); sic;
2767 sic = setNextItem (sendSet))
2769 if (sic->argreg > 12)
2771 int bit = sic->argreg-13;
2773 aopOp (IC_LEFT (sic), sic, FALSE);
2775 /* if left is a literal then
2776 we know what the value is */
2777 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2779 if (((int) operandLitValue (IC_LEFT (sic))))
2780 emitcode ("setb", "b[%d]", bit);
2782 emitcode ("clr", "b[%d]", bit);
2787 toCarry (IC_LEFT (sic));
2788 emitcode ("mov", "b[%d],c", bit);
2793 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2799 saveRegisters (setFirstItem (sendSet));
2800 emitcode ("mov", "bits,b");
2803 /* then we do all other parameters */
2804 for (sic = setFirstItem (sendSet); sic;
2805 sic = setNextItem (sendSet))
2807 if (sic->argreg <= 12)
2809 int size, offset = 0;
2810 aopOp (IC_LEFT (sic), sic, FALSE);
2811 size = AOP_SIZE (IC_LEFT (sic));
2813 if (sic->argreg == 1)
2817 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2818 if (strcmp (l, fReturn[offset]))
2820 emitcode ("mov", "%s,%s", fReturn[offset], l);
2829 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2830 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2834 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2839 /*-----------------------------------------------------------------*/
2840 /* selectRegBank - emit code to select the register bank */
2841 /*-----------------------------------------------------------------*/
2843 selectRegBank (short bank, bool keepFlags)
2845 /* if f.e. result is in carry */
2848 emitcode ("anl", "psw,#0xE7");
2850 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2854 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2858 /*-----------------------------------------------------------------*/
2859 /* genCall - generates a call statement */
2860 /*-----------------------------------------------------------------*/
2862 genCall (iCode * ic)
2866 // bool restoreBank = FALSE;
2867 bool swapBanks = FALSE;
2868 bool accuse = FALSE;
2869 bool accPushed = FALSE;
2870 bool resultInF0 = FALSE;
2871 bool assignResultGenerated = FALSE;
2873 D (emitcode (";", "genCall"));
2875 dtype = operandType (IC_LEFT (ic));
2876 etype = getSpec(dtype);
2877 /* if send set is not empty then assign */
2880 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2881 genSend(reverseSet(_G.sendSet));
2883 genSend(_G.sendSet);
2888 /* if we are calling a not _naked function that is not using
2889 the same register bank then we need to save the
2890 destination registers on the stack */
2891 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2892 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2893 !IFFUNC_ISISR (dtype))
2898 /* if caller saves & we have not saved then */
2904 emitcode ("mov", "psw,#0x%02x",
2905 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2909 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2911 if (IFFUNC_CALLEESAVES(dtype))
2913 werror (E_BANKED_WITH_CALLEESAVES);
2917 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2918 OP_SYMBOL (IC_LEFT (ic))->rname :
2919 OP_SYMBOL (IC_LEFT (ic))->name);
2921 emitcode ("mov", "r0,#%s", l);
2922 emitcode ("mov", "r1,#(%s >> 8)", l);
2923 emitcode ("mov", "r2,#(%s >> 16)", l);
2924 emitcode ("lcall", "__sdcc_banked_call");
2929 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2930 OP_SYMBOL (IC_LEFT (ic))->rname :
2931 OP_SYMBOL (IC_LEFT (ic))->name));
2936 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2939 /* if we need assign a result value */
2940 if ((IS_ITEMP (IC_RESULT (ic)) &&
2941 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2942 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2943 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2944 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2945 IS_TRUE_SYMOP (IC_RESULT (ic)))
2949 aopOp (IC_RESULT (ic), ic, FALSE);
2952 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2953 assignResultGenerated = TRUE;
2955 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2958 /* adjust the stack for parameters if required */
2962 if (ic->parmBytes > 3)
2966 emitcode ("push", "acc");
2969 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2970 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2971 !assignResultGenerated)
2973 emitcode ("mov", "F0,c");
2977 emitcode ("mov", "a,%s", spname);
2978 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2979 emitcode ("mov", "%s,a", spname);
2981 /* unsaveRegisters from xstack needs acc, but */
2982 /* unsaveRegisters from stack needs this popped */
2983 if (accPushed && !options.useXstack)
2985 emitcode ("pop", "acc");
2990 for (i = 0; i < ic->parmBytes; i++)
2991 emitcode ("dec", "%s", spname);
2994 /* if we had saved some registers then unsave them */
2995 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2997 if (accuse && !accPushed && options.useXstack)
2999 /* xstack needs acc, but doesn't touch normal stack */
3000 emitcode ("push", "acc");
3003 unsaveRegisters (ic);
3006 // /* if register bank was saved then pop them */
3008 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3010 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3013 emitcode ("mov", "c,F0");
3015 aopOp (IC_RESULT (ic), ic, FALSE);
3016 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3017 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3021 emitcode ("pop", "acc");
3024 /*-----------------------------------------------------------------*/
3025 /* genPcall - generates a call by pointer statement */
3026 /*-----------------------------------------------------------------*/
3028 genPcall (iCode * ic)
3032 symbol *rlbl = newiTempLabel (NULL);
3033 // bool restoreBank=FALSE;
3034 bool swapBanks = FALSE;
3035 bool resultInF0 = FALSE;
3037 D (emitcode (";", "genPcall"));
3039 dtype = operandType (IC_LEFT (ic))->next;
3040 etype = getSpec(dtype);
3041 /* if caller saves & we have not saved then */
3045 /* if we are calling a not _naked function that is not using
3046 the same register bank then we need to save the
3047 destination registers on the stack */
3048 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3049 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3050 !IFFUNC_ISISR (dtype))
3052 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3053 // restoreBank=TRUE;
3055 // need caution message to user here
3058 if (IS_LITERAL (etype))
3060 /* if send set is not empty then assign */
3063 genSend(reverseSet(_G.sendSet));
3069 emitcode ("mov", "psw,#0x%02x",
3070 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3073 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3075 if (IFFUNC_CALLEESAVES (dtype))
3077 werror (E_BANKED_WITH_CALLEESAVES);
3081 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3083 emitcode ("mov", "r0,#%s", l);
3084 emitcode ("mov", "r1,#(%s >> 8)", l);
3085 emitcode ("mov", "r2,#(%s >> 16)", l);
3086 emitcode ("lcall", "__sdcc_banked_call");
3091 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3096 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3098 if (IFFUNC_CALLEESAVES (dtype))
3100 werror (E_BANKED_WITH_CALLEESAVES);
3104 aopOp (IC_LEFT (ic), ic, FALSE);
3108 /* what if aopGet needs r0 or r1 ??? */
3109 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3110 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3111 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3115 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3116 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3117 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3118 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3121 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3123 /* if send set is not empty then assign */
3126 genSend(reverseSet(_G.sendSet));
3132 emitcode ("mov", "psw,#0x%02x",
3133 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3137 emitcode ("lcall", "__sdcc_banked_call");
3140 else if (_G.sendSet)
3142 /* push the return address on to the stack */
3143 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3144 emitcode ("push", "acc");
3145 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3146 emitcode ("push", "acc");
3148 /* now push the calling address */
3149 aopOp (IC_LEFT (ic), ic, FALSE);
3151 pushSide (IC_LEFT (ic), FPTRSIZE);
3153 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3155 /* if send set is not empty the assign */
3158 genSend(reverseSet(_G.sendSet));
3164 emitcode ("mov", "psw,#0x%02x",
3165 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3169 emitcode ("ret", "");
3172 else /* the send set is empty */
3175 /* now get the calling address into dptr */
3176 aopOp (IC_LEFT (ic), ic, FALSE);
3178 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3179 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3181 emitcode ("mov", "r0,%s", l);
3182 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3183 emitcode ("mov", "dph,%s", l);
3184 emitcode ("mov", "dpl,r0");
3188 emitcode ("mov", "dpl,%s", l);
3189 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3190 emitcode ("mov", "dph,%s", l);
3193 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3197 emitcode ("mov", "psw,#0x%02x",
3198 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3202 emitcode ("lcall", "__sdcc_call_dptr");
3207 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3210 /* if we need assign a result value */
3211 if ((IS_ITEMP (IC_RESULT (ic)) &&
3212 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3213 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3214 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3215 IS_TRUE_SYMOP (IC_RESULT (ic)))
3219 aopOp (IC_RESULT (ic), ic, FALSE);
3222 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3224 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3227 /* adjust the stack for parameters if required */
3231 if (ic->parmBytes > 3)
3233 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3234 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3236 emitcode ("mov", "F0,c");
3240 emitcode ("mov", "a,%s", spname);
3241 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3242 emitcode ("mov", "%s,a", spname);
3245 for (i = 0; i < ic->parmBytes; i++)
3246 emitcode ("dec", "%s", spname);
3249 // /* if register bank was saved then unsave them */
3251 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3253 /* if we had saved some registers then unsave them */
3254 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3255 unsaveRegisters (ic);
3257 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3260 emitcode ("mov", "c,F0");
3262 aopOp (IC_RESULT (ic), ic, FALSE);
3263 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3264 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3268 /*-----------------------------------------------------------------*/
3269 /* resultRemat - result is rematerializable */
3270 /*-----------------------------------------------------------------*/
3272 resultRemat (iCode * ic)
3274 if (SKIP_IC (ic) || ic->op == IFX)
3277 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3279 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3280 if (sym->remat && !POINTER_SET (ic))
3287 /*-----------------------------------------------------------------*/
3288 /* inExcludeList - return 1 if the string is in exclude Reg list */
3289 /*-----------------------------------------------------------------*/
3291 regsCmp(void *p1, void *p2)
3293 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3297 inExcludeList (char *s)
3299 const char *p = setFirstItem(options.excludeRegsSet);
3301 if (p == NULL || STRCASECMP(p, "none") == 0)
3305 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3308 /*-----------------------------------------------------------------*/
3309 /* genFunction - generated code for function entry */
3310 /*-----------------------------------------------------------------*/
3312 genFunction (iCode * ic)
3314 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3316 bool switchedPSW = FALSE;
3317 int calleesaves_saved_register = -1;
3318 int stackAdjust = sym->stack;
3319 int accIsFree = sym->recvSize < 4;
3320 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3321 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3324 /* create the function header */
3325 emitcode (";", "-----------------------------------------");
3326 emitcode (";", " function %s", sym->name);
3327 emitcode (";", "-----------------------------------------");
3329 emitcode ("", "%s:", sym->rname);
3330 lineCurr->isLabel = 1;
3331 ftype = operandType (IC_LEFT (ic));
3332 _G.currentFunc = sym;
3334 if (IFFUNC_ISNAKED(ftype))
3336 emitcode(";", "naked function: no prologue.");
3340 /* here we need to generate the equates for the
3341 register bank if required */
3342 if (FUNC_REGBANK (ftype) != rbank)
3346 rbank = FUNC_REGBANK (ftype);
3347 for (i = 0; i < mcs51_nRegs; i++)
3349 if (regs8051[i].type != REG_BIT)
3351 if (strcmp (regs8051[i].base, "0") == 0)
3352 emitcode ("", "%s = 0x%02x",
3354 8 * rbank + regs8051[i].offset);
3356 emitcode ("", "%s = %s + 0x%02x",
3359 8 * rbank + regs8051[i].offset);
3364 /* if this is an interrupt service routine then
3365 save acc, b, dpl, dph */
3366 if (IFFUNC_ISISR (sym->type))
3370 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3371 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3373 emitcode ("push", "bits");
3376 freeBitVect (rsavebits);
3378 if (!inExcludeList ("acc"))
3379 emitcode ("push", "acc");
3380 if (!inExcludeList ("b"))
3381 emitcode ("push", "b");
3382 if (!inExcludeList ("dpl"))
3383 emitcode ("push", "dpl");
3384 if (!inExcludeList ("dph"))
3385 emitcode ("push", "dph");
3386 /* if this isr has no bank i.e. is going to
3387 run with bank 0 , then we need to save more
3389 if (!FUNC_REGBANK (sym->type))
3393 /* if this function does not call any other
3394 function then we can be economical and
3395 save only those registers that are used */
3396 if (!IFFUNC_HASFCALL(sym->type))
3398 /* if any registers used */
3401 /* save the registers used */
3402 for (i = 0; i < sym->regsUsed->size; i++)
3404 if (bitVectBitValue (sym->regsUsed, i))
3411 /* this function has a function call. We cannot
3412 determine register usage so we will have to push the
3414 saveRBank (0, ic, FALSE);
3415 if (options.parms_in_bank1) {
3416 for (i=0; i < 8 ; i++ ) {
3417 emitcode ("push","%s",rb1regs[i]);
3424 /* This ISR uses a non-zero bank.
3426 * We assume that the bank is available for our
3429 * However, if this ISR calls a function which uses some
3430 * other bank, we must save that bank entirely.
3432 unsigned long banksToSave = 0;
3434 if (IFFUNC_HASFCALL(sym->type))
3437 #define MAX_REGISTER_BANKS 4
3442 for (i = ic; i; i = i->next)
3444 if (i->op == ENDFUNCTION)
3446 /* we got to the end OK. */
3454 dtype = operandType (IC_LEFT(i));
3456 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3458 /* Mark this bank for saving. */
3459 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3461 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3465 banksToSave |= (1 << FUNC_REGBANK(dtype));
3468 /* And note that we don't need to do it in
3476 /* This is a mess; we have no idea what
3477 * register bank the called function might
3480 * The only thing I can think of to do is
3481 * throw a warning and hope.
3483 werror(W_FUNCPTR_IN_USING_ISR);
3487 if (banksToSave && options.useXstack)
3489 /* Since we aren't passing it an ic,
3490 * saveRBank will assume r0 is available to abuse.
3492 * So switch to our (trashable) bank now, so
3493 * the caller's R0 isn't trashed.
3495 emitcode ("push", "psw");
3496 emitcode ("mov", "psw,#0x%02x",
3497 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3501 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3503 if (banksToSave & (1 << ix))
3505 saveRBank(ix, NULL, FALSE);
3509 // TODO: this needs a closer look
3510 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3513 /* Set the register bank to the desired value if nothing else */
3514 /* has done so yet. */
3517 emitcode ("push", "psw");
3518 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3523 /* This is a non-ISR function. The caller has already switched register */
3524 /* banks, if necessary, so just handle the callee-saves option. */
3526 /* if callee-save to be used for this function
3527 then save the registers being used in this function */
3528 if (IFFUNC_CALLEESAVES(sym->type))
3532 /* if any registers used */
3535 bool bits_pushed = FALSE;
3536 /* save the registers used */
3537 for (i = 0; i < sym->regsUsed->size; i++)
3539 if (bitVectBitValue (sym->regsUsed, i))
3541 /* remember one saved register for later usage */
3542 if (calleesaves_saved_register < 0)
3543 calleesaves_saved_register = i;
3544 bits_pushed = pushReg (i, bits_pushed);
3554 if (options.useXstack)
3556 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3558 emitcode ("mov", "r0,%s", spname);
3559 emitcode ("inc", "%s", spname);
3560 emitcode ("xch", "a,_bpx");
3561 emitcode ("movx", "@r0,a");
3562 emitcode ("inc", "r0");
3563 emitcode ("mov", "a,r0");
3564 emitcode ("xch", "a,_bpx");
3568 emitcode ("push", "_bp"); /* save the callers stack */
3569 emitcode ("mov", "_bp,sp");
3574 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3576 /* set up the stack */
3577 emitcode ("push", "_bp"); /* save the callers stack */
3578 emitcode ("mov", "_bp,sp");
3583 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3584 /* before setting up the stack frame completely. */
3585 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3587 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3591 if (rsym && rsym->regType == REG_CND)
3593 if (rsym && (rsym->accuse || rsym->ruonly))
3595 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3596 rsym = rsym->usl.spillLoc;
3599 /* If the RECEIVE operand immediately spills to the first entry on the */
3600 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3601 /* rather than the usual @r0/r1 machinations. */
3602 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3606 _G.current_iCode = ric;
3607 D(emitcode (";", "genReceive"));
3608 for (ofs=0; ofs < sym->recvSize; ofs++)
3610 if (!strcmp (fReturn[ofs], "a"))
3611 emitcode ("push", "acc");
3613 emitcode ("push", fReturn[ofs]);
3615 stackAdjust -= sym->recvSize;
3618 assert (stackAdjust>=0);
3621 _G.current_iCode = ic;
3625 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3626 /* to free up the accumulator. */
3627 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3631 _G.current_iCode = ric;
3632 D(emitcode (";", "genReceive"));
3633 for (ofs=0; ofs < sym->recvSize; ofs++)
3635 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3637 _G.current_iCode = ic;
3643 /* adjust the stack for the function */
3646 int i = stackAdjust;
3648 werror (W_STACK_OVERFLOW, sym->name);
3650 if (i > 3 && accIsFree)
3652 emitcode ("mov", "a,sp");
3653 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3654 emitcode ("mov", "sp,a");
3658 /* The accumulator is not free, so we will need another register */
3659 /* to clobber. No need to worry about a possible conflict with */
3660 /* the above early RECEIVE optimizations since they would have */
3661 /* freed the accumulator if they were generated. */
3663 if (IFFUNC_CALLEESAVES(sym->type))
3665 /* if it's a callee-saves function we need a saved register */
3666 if (calleesaves_saved_register >= 0)
3668 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3672 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3675 /* do it the hard way */
3677 emitcode ("inc", "sp");
3681 /* not callee-saves, we can clobber r0 */
3682 emitcode ("mov", "r0,a");
3683 emitcode ("mov", "a,sp");
3684 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3685 emitcode ("mov", "sp,a");
3686 emitcode ("mov", "a,r0");
3691 emitcode ("inc", "sp");
3696 char i = ((char) sym->xstack & 0xff);
3698 if (i > 3 && accIsFree)
3700 emitcode ("mov", "a,_spx");
3701 emitcode ("add", "a,#0x%02x", i & 0xff);
3702 emitcode ("mov", "_spx,a");
3706 emitcode ("push", "acc");
3707 emitcode ("mov", "a,_spx");
3708 emitcode ("add", "a,#0x%02x", i & 0xff);
3709 emitcode ("mov", "_spx,a");
3710 emitcode ("pop", "acc");
3715 emitcode ("inc", "_spx");
3719 /* if critical function then turn interrupts off */
3720 if (IFFUNC_ISCRITICAL (ftype))
3722 symbol *tlbl = newiTempLabel (NULL);
3723 emitcode ("setb", "c");
3724 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3725 emitcode ("clr", "c");
3727 emitcode ("push", "psw"); /* save old ea via c in psw */
3731 /*-----------------------------------------------------------------*/
3732 /* genEndFunction - generates epilogue for functions */
3733 /*-----------------------------------------------------------------*/
3735 genEndFunction (iCode * ic)
3737 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3738 lineNode *lnp = lineCurr;
3740 bitVect *regsUsedPrologue;
3741 bitVect *regsUnneeded;
3744 _G.currentFunc = NULL;
3745 if (IFFUNC_ISNAKED(sym->type))
3747 emitcode(";", "naked function: no epilogue.");
3748 if (options.debug && currFunc)
3749 debugFile->writeEndFunction (currFunc, ic, 0);
3753 if (IFFUNC_ISCRITICAL (sym->type))
3755 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3757 emitcode ("rlc", "a"); /* save c in a */
3758 emitcode ("pop", "psw"); /* restore ea via c in psw */
3759 emitcode ("mov", "ea,c");
3760 emitcode ("rrc", "a"); /* restore c from a */
3764 emitcode ("pop", "psw"); /* restore ea via c in psw */
3765 emitcode ("mov", "ea,c");
3769 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3771 if (options.useXstack)
3775 emitcode ("mov", "sp,_bp");
3776 emitcode ("pop", "_bp");
3778 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3780 emitcode ("xch", "a,_bpx");
3781 emitcode ("mov", "r0,a");
3782 emitcode ("dec", "r0");
3783 emitcode ("movx", "a,@r0");
3784 emitcode ("xch", "a,_bpx");
3785 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3788 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3791 emitcode ("mov", "sp,_bp");
3792 emitcode ("pop", "_bp");
3796 /* restore the register bank */
3797 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3799 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3800 || !options.useXstack)
3802 /* Special case of ISR using non-zero bank with useXstack
3805 emitcode ("pop", "psw");
3809 if (IFFUNC_ISISR (sym->type))
3813 /* now we need to restore the registers */
3814 /* if this isr has no bank i.e. is going to
3815 run with bank 0 , then we need to save more
3817 if (!FUNC_REGBANK (sym->type))
3820 /* if this function does not call any other
3821 function then we can be economical and
3822 save only those registers that are used */
3823 if (!IFFUNC_HASFCALL(sym->type))
3825 /* if any registers used */
3828 /* save the registers used */
3829 for (i = sym->regsUsed->size; i >= 0; i--)
3831 if (bitVectBitValue (sym->regsUsed, i))
3838 if (options.parms_in_bank1) {
3839 for (i = 7 ; i >= 0 ; i-- ) {
3840 emitcode ("pop","%s",rb1regs[i]);
3843 /* this function has a function call. We cannot
3844 determine register usage so we will have to pop the
3846 unsaveRBank (0, ic, FALSE);
3851 /* This ISR uses a non-zero bank.
3853 * Restore any register banks saved by genFunction
3856 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3859 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3861 if (savedBanks & (1 << ix))
3863 unsaveRBank(ix, NULL, FALSE);
3867 if (options.useXstack)
3869 /* Restore bank AFTER calling unsaveRBank,
3870 * since it can trash r0.
3872 emitcode ("pop", "psw");
3876 if (!inExcludeList ("dph"))
3877 emitcode ("pop", "dph");
3878 if (!inExcludeList ("dpl"))
3879 emitcode ("pop", "dpl");
3880 if (!inExcludeList ("b"))
3881 emitcode ("pop", "b");
3882 if (!inExcludeList ("acc"))
3883 emitcode ("pop", "acc");
3885 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3886 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3887 emitcode ("pop", "bits");
3888 freeBitVect (rsavebits);
3890 /* if debug then send end of function */
3891 if (options.debug && currFunc)
3893 debugFile->writeEndFunction (currFunc, ic, 1);
3896 emitcode ("reti", "");
3900 if (IFFUNC_CALLEESAVES(sym->type))
3904 /* if any registers used */
3907 /* save the registers used */
3908 for (i = sym->regsUsed->size; i >= 0; i--)
3910 if (bitVectBitValue (sym->regsUsed, i) ||
3911 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3912 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3915 else if (mcs51_ptrRegReq)
3917 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3918 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3923 /* if debug then send end of function */
3924 if (options.debug && currFunc)
3926 debugFile->writeEndFunction (currFunc, ic, 1);
3929 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3931 emitcode ("ljmp", "__sdcc_banked_ret");
3935 emitcode ("ret", "");
3939 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3942 /* If this was an interrupt handler using bank 0 that called another */
3943 /* function, then all registers must be saved; nothing to optimized. */
3944 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3945 && !FUNC_REGBANK(sym->type))
3948 /* There are no push/pops to optimize if not callee-saves or ISR */
3949 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3952 /* If there were stack parameters, we cannot optimize without also */
3953 /* fixing all of the stack offsets; this is too dificult to consider. */
3954 if (FUNC_HASSTACKPARM(sym->type))
3957 /* Compute the registers actually used */
3958 regsUsed = newBitVect (mcs51_nRegs);
3959 regsUsedPrologue = newBitVect (mcs51_nRegs);
3962 if (lnp->ic && lnp->ic->op == FUNCTION)
3963 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3965 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3967 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3968 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3975 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3976 && !bitVectBitValue (regsUsed, CND_IDX))
3978 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3979 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3980 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3981 bitVectUnSetBit (regsUsed, CND_IDX);
3984 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3986 /* If this was an interrupt handler that called another function */
3987 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3988 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3990 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3991 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3992 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3997 /* Remove the unneeded push/pops */
3998 regsUnneeded = newBitVect (mcs51_nRegs);
4001 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4003 if (!strncmp(lnp->line, "push", 4))
4005 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4006 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4008 connectLine (lnp->prev, lnp->next);
4009 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4012 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4014 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4015 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4017 connectLine (lnp->prev, lnp->next);
4018 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4025 for (idx = 0; idx < regsUnneeded->size; idx++)
4026 if (bitVectBitValue (regsUnneeded, idx))
4027 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4029 freeBitVect (regsUnneeded);
4030 freeBitVect (regsUsed);
4031 freeBitVect (regsUsedPrologue);
4034 /*-----------------------------------------------------------------*/
4035 /* genRet - generate code for return statement */
4036 /*-----------------------------------------------------------------*/
4040 int size, offset = 0, pushed = 0;
4042 D (emitcode (";", "genRet"));
4044 /* if we have no return value then
4045 just generate the "ret" */
4049 /* we have something to return then
4050 move the return value into place */
4051 aopOp (IC_LEFT (ic), ic, FALSE);
4052 size = AOP_SIZE (IC_LEFT (ic));
4054 if (IS_BIT(_G.currentFunc->etype))
4056 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4057 toCarry (IC_LEFT (ic));
4064 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4067 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4068 emitcode ("push", "%s", l);
4073 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4074 if (strcmp (fReturn[offset], l))
4075 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4082 if (strcmp (fReturn[pushed], "a"))
4083 emitcode ("pop", fReturn[pushed]);
4085 emitcode ("pop", "acc");
4088 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4091 /* generate a jump to the return label
4092 if the next is not the return statement */
4093 if (!(ic->next && ic->next->op == LABEL &&
4094 IC_LABEL (ic->next) == returnLabel))
4096 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4100 /*-----------------------------------------------------------------*/
4101 /* genLabel - generates a label */
4102 /*-----------------------------------------------------------------*/
4104 genLabel (iCode * ic)
4106 /* special case never generate */
4107 if (IC_LABEL (ic) == entryLabel)
4110 emitLabel (IC_LABEL (ic));
4113 /*-----------------------------------------------------------------*/
4114 /* genGoto - generates a ljmp */
4115 /*-----------------------------------------------------------------*/
4117 genGoto (iCode * ic)
4119 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4122 /*-----------------------------------------------------------------*/
4123 /* findLabelBackwards: walks back through the iCode chain looking */
4124 /* for the given label. Returns number of iCode instructions */
4125 /* between that label and given ic. */
4126 /* Returns zero if label not found. */
4127 /*-----------------------------------------------------------------*/
4129 findLabelBackwards (iCode * ic, int key)
4138 /* If we have any pushes or pops, we cannot predict the distance.
4139 I don't like this at all, this should be dealt with in the
4141 if (ic->op == IPUSH || ic->op == IPOP) {
4145 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4154 /*-----------------------------------------------------------------*/
4155 /* genPlusIncr :- does addition with increment if possible */
4156 /*-----------------------------------------------------------------*/
4158 genPlusIncr (iCode * ic)
4160 unsigned int icount;
4161 unsigned int size = getDataSize (IC_RESULT (ic));
4163 /* will try to generate an increment */
4164 /* if the right side is not a literal
4166 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4169 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4171 D(emitcode (";","genPlusIncr"));
4173 /* if increment >=16 bits in register or direct space */
4174 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4175 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4176 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4177 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4178 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4186 /* If the next instruction is a goto and the goto target
4187 * is < 10 instructions previous to this, we can generate
4188 * jumps straight to that target.
4190 if (ic->next && ic->next->op == GOTO
4191 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4192 && labelRange <= 10)
4194 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4195 tlbl = IC_LABEL (ic->next);
4200 tlbl = newiTempLabel (NULL);
4203 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4204 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4205 IS_AOP_PREG (IC_RESULT (ic)))
4206 emitcode ("cjne", "%s,#0x00,%05d$",
4207 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4211 emitcode ("clr", "a");
4212 emitcode ("cjne", "a,%s,%05d$",
4213 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4217 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4220 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221 IS_AOP_PREG (IC_RESULT (ic)))
4222 emitcode ("cjne", "%s,#0x00,%05d$",
4223 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4226 emitcode ("cjne", "a,%s,%05d$",
4227 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4230 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4235 IS_AOP_PREG (IC_RESULT (ic)))
4236 emitcode ("cjne", "%s,#0x00,%05d$",
4237 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4241 emitcode ("cjne", "a,%s,%05d$",
4242 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4245 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4255 /* if result is dptr */
4256 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4257 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4258 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4259 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4261 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4267 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4270 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4271 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4273 emitcode ("inc", "dptr");
4278 /* if the literal value of the right hand side
4279 is greater than 4 then it is not worth it */
4283 /* if the sizes are greater than 1 then we cannot */
4284 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4285 AOP_SIZE (IC_LEFT (ic)) > 1)
4288 /* we can if the aops of the left & result match or
4289 if they are in registers and the registers are the
4291 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4295 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4296 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4297 aopPut (IC_RESULT (ic), "a", 0);
4303 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4312 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313 emitcode ("inc", "a");
4314 aopPut (IC_RESULT (ic), "a", 0);
4321 /*-----------------------------------------------------------------*/
4322 /* outBitAcc - output a bit in acc */
4323 /*-----------------------------------------------------------------*/
4325 outBitAcc (operand * result)
4327 symbol *tlbl = newiTempLabel (NULL);
4328 /* if the result is a bit */
4329 if (AOP_TYPE (result) == AOP_CRY)
4331 aopPut (result, "a", 0);
4335 emitcode ("jz", "%05d$", tlbl->key + 100);
4336 emitcode ("mov", "a,%s", one);
4342 /*-----------------------------------------------------------------*/
4343 /* genPlusBits - generates code for addition of two bits */
4344 /*-----------------------------------------------------------------*/
4346 genPlusBits (iCode * ic)
4348 D (emitcode (";", "genPlusBits"));
4350 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4351 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4353 symbol *lbl = newiTempLabel (NULL);
4354 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4355 emitcode ("cpl", "c");
4357 outBitC (IC_RESULT (ic));
4361 emitcode ("clr", "a");
4362 emitcode ("rlc", "a");
4363 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4364 emitcode ("addc", "a,%s", zero);
4365 outAcc (IC_RESULT (ic));
4370 /* This is the original version of this code.
4372 * This is being kept around for reference,
4373 * because I am not entirely sure I got it right...
4376 adjustArithmeticResult (iCode * ic)
4378 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4380 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4381 aopPut (IC_RESULT (ic),
4382 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4385 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4386 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4387 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4388 aopPut (IC_RESULT (ic),
4389 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4392 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4393 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4394 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4395 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4396 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4399 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4400 aopPut (IC_RESULT (ic), buffer, 2);
4404 /* This is the pure and virtuous version of this code.
4405 * I'm pretty certain it's right, but not enough to toss the old
4409 adjustArithmeticResult (iCode * ic)
4411 if (opIsGptr (IC_RESULT (ic)) &&
4412 opIsGptr (IC_LEFT (ic)) &&
4413 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4415 aopPut (IC_RESULT (ic),
4416 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4420 if (opIsGptr (IC_RESULT (ic)) &&
4421 opIsGptr (IC_RIGHT (ic)) &&
4422 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4424 aopPut (IC_RESULT (ic),
4425 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4429 if (opIsGptr (IC_RESULT (ic)) &&
4430 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4431 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4433 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4436 SNPRINTF (buffer, sizeof(buffer),
4437 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4438 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4443 /*-----------------------------------------------------------------*/
4444 /* genPlus - generates code for addition */
4445 /*-----------------------------------------------------------------*/
4447 genPlus (iCode * ic)
4449 int size, offset = 0;
4452 bool swappedLR = FALSE;
4453 operand *leftOp, *rightOp;
4456 D (emitcode (";", "genPlus"));
4458 /* special cases :- */
4460 aopOp (IC_LEFT (ic), ic, FALSE);
4461 aopOp (IC_RIGHT (ic), ic, FALSE);
4462 aopOp (IC_RESULT (ic), ic, TRUE);
4464 /* if literal, literal on the right or
4465 if left requires ACC or right is already
4467 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4468 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4469 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4471 operand *t = IC_RIGHT (ic);
4472 IC_RIGHT (ic) = IC_LEFT (ic);
4477 /* if both left & right are in bit
4479 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4480 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4486 /* if left in bit space & right literal */
4487 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4488 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4490 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4491 /* if result in bit space */
4492 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4494 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4495 emitcode ("cpl", "c");
4496 outBitC (IC_RESULT (ic));
4500 size = getDataSize (IC_RESULT (ic));
4503 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4504 emitcode ("addc", "a,%s", zero);
4505 aopPut (IC_RESULT (ic), "a", offset++);
4511 /* if I can do an increment instead
4512 of add then GOOD for ME */
4513 if (genPlusIncr (ic) == TRUE)
4516 size = getDataSize (IC_RESULT (ic));
4517 leftOp = IC_LEFT(ic);
4518 rightOp = IC_RIGHT(ic);
4521 /* if this is an add for an array access
4522 at a 256 byte boundary */
4524 && AOP_TYPE (op) == AOP_IMMD
4526 && IS_SPEC (OP_SYM_ETYPE (op))
4527 && SPEC_ABSA (OP_SYM_ETYPE (op))
4528 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4531 D(emitcode (";", "genPlus aligned array"));
4532 aopPut (IC_RESULT (ic),
4533 aopGet (rightOp, 0, FALSE, FALSE),
4536 if( 1 == getDataSize (IC_RIGHT (ic)) )
4538 aopPut (IC_RESULT (ic),
4539 aopGet (leftOp, 1, FALSE, FALSE),
4544 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4545 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4546 aopPut (IC_RESULT (ic), "a", 1);
4551 /* if the lower bytes of a literal are zero skip the addition */
4552 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4554 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4555 (skip_bytes+1 < size))
4560 D(emitcode (";", "genPlus shortcut"));
4565 if( offset >= skip_bytes )
4567 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4570 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4572 emitcode("xch", "a,b");
4573 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4574 emitcode (add, "a,b");
4577 else if (aopGetUsesAcc (leftOp, offset))
4579 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4580 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4584 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4585 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4587 aopPut (IC_RESULT (ic), "a", offset);
4588 add = "addc"; /* further adds must propagate carry */
4592 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4593 isOperandVolatile (IC_RESULT (ic), FALSE))
4596 aopPut (IC_RESULT (ic),
4597 aopGet (leftOp, offset, FALSE, FALSE),
4604 adjustArithmeticResult (ic);
4607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4610 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 /*-----------------------------------------------------------------*/
4621 /* genMinusDec :- does subtraction with decrement if possible */
4622 /*-----------------------------------------------------------------*/
4624 genMinusDec (iCode * ic)
4626 unsigned int icount;
4627 unsigned int size = getDataSize (IC_RESULT (ic));
4629 /* will try to generate an increment */
4630 /* if the right side is not a literal
4632 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4635 /* if the literal value of the right hand side
4636 is greater than 4 then it is not worth it */
4637 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4640 D (emitcode (";", "genMinusDec"));
4642 /* if decrement >=16 bits in register or direct space */
4643 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4644 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4645 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4646 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4654 /* If the next instruction is a goto and the goto target
4655 * is <= 10 instructions previous to this, we can generate
4656 * jumps straight to that target.
4658 if (ic->next && ic->next->op == GOTO
4659 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4660 && labelRange <= 10)
4662 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4663 tlbl = IC_LABEL (ic->next);
4668 tlbl = newiTempLabel (NULL);
4672 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4673 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4674 IS_AOP_PREG (IC_RESULT (ic)))
4675 emitcode ("cjne", "%s,#0xff,%05d$"
4676 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4680 emitcode ("mov", "a,#0xff");
4681 emitcode ("cjne", "a,%s,%05d$"
4682 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4685 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4688 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4689 IS_AOP_PREG (IC_RESULT (ic)))
4690 emitcode ("cjne", "%s,#0xff,%05d$"
4691 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4695 emitcode ("cjne", "a,%s,%05d$"
4696 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4699 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4703 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4704 IS_AOP_PREG (IC_RESULT (ic)))
4705 emitcode ("cjne", "%s,#0xff,%05d$"
4706 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4710 emitcode ("cjne", "a,%s,%05d$"
4711 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4714 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4723 /* if the sizes are greater than 1 then we cannot */
4724 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4725 AOP_SIZE (IC_LEFT (ic)) > 1)
4728 /* we can if the aops of the left & result match or
4729 if they are in registers and the registers are the
4731 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4735 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4737 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4742 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4747 emitcode ("dec", "%s", l);
4750 if (AOP_NEEDSACC (IC_RESULT (ic)))
4751 aopPut (IC_RESULT (ic), "a", 0);
4758 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4759 emitcode ("dec", "a");
4760 aopPut (IC_RESULT (ic), "a", 0);
4767 /*-----------------------------------------------------------------*/
4768 /* addSign - complete with sign */
4769 /*-----------------------------------------------------------------*/
4771 addSign (operand * result, int offset, int sign)
4773 int size = (getDataSize (result) - offset);
4778 emitcode ("rlc", "a");
4779 emitcode ("subb", "a,acc");
4782 aopPut (result, "a", offset++);
4789 aopPut (result, zero, offset++);
4795 /*-----------------------------------------------------------------*/
4796 /* genMinusBits - generates code for subtraction of two bits */
4797 /*-----------------------------------------------------------------*/
4799 genMinusBits (iCode * ic)
4801 symbol *lbl = newiTempLabel (NULL);
4803 D (emitcode (";", "genMinusBits"));
4805 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4807 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4808 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4809 emitcode ("cpl", "c");
4811 outBitC (IC_RESULT (ic));
4815 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4816 emitcode ("subb", "a,acc");
4817 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4818 emitcode ("inc", "a");
4820 aopPut (IC_RESULT (ic), "a", 0);
4821 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4825 /*-----------------------------------------------------------------*/
4826 /* genMinus - generates code for subtraction */
4827 /*-----------------------------------------------------------------*/
4829 genMinus (iCode * ic)
4831 int size, offset = 0;
4833 D (emitcode (";", "genMinus"));
4835 aopOp (IC_LEFT (ic), ic, FALSE);
4836 aopOp (IC_RIGHT (ic), ic, FALSE);
4837 aopOp (IC_RESULT (ic), ic, TRUE);
4839 /* special cases :- */
4840 /* if both left & right are in bit space */
4841 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4842 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4848 /* if I can do an decrement instead
4849 of subtract then GOOD for ME */
4850 if (genMinusDec (ic) == TRUE)
4853 size = getDataSize (IC_RESULT (ic));
4855 /* if literal, add a,#-lit, else normal subb */
4856 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4858 unsigned long lit = 0L;
4859 bool useCarry = FALSE;
4861 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4866 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4868 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4869 if (!offset && !size && lit== (unsigned long) -1)
4871 emitcode ("dec", "a");
4875 /* first add without previous c */
4876 emitcode ("add", "a,#0x%02x",
4877 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4882 emitcode ("addc", "a,#0x%02x",
4883 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4885 aopPut (IC_RESULT (ic), "a", offset++);
4889 /* no need to add zeroes */
4890 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4892 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4901 operand *leftOp, *rightOp;
4903 leftOp = IC_LEFT(ic);
4904 rightOp = IC_RIGHT(ic);
4908 if (aopGetUsesAcc(rightOp, offset)) {
4909 if (aopGetUsesAcc(leftOp, offset)) {
4912 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4914 emitcode ("mov", "b,a");
4917 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4918 emitcode ("subb", "a,b");
4921 /* reverse subtraction with 2's complement */
4923 emitcode( "setb", "c");
4925 emitcode( "cpl", "c");
4926 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4927 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4928 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4929 emitcode("cpl", "a");
4930 if (size) /* skip if last byte */
4931 emitcode( "cpl", "c");
4934 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4937 emitcode ("subb", "a,%s",
4938 aopGet(rightOp, offset, FALSE, TRUE));
4941 aopPut (IC_RESULT (ic), "a", offset++);
4945 adjustArithmeticResult (ic);
4948 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4949 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4954 /*-----------------------------------------------------------------*/
4955 /* genMultbits :- multiplication of bits */
4956 /*-----------------------------------------------------------------*/
4958 genMultbits (operand * left,
4962 D (emitcode (";", "genMultbits"));
4964 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4965 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4969 /*-----------------------------------------------------------------*/
4970 /* genMultOneByte : 8*8=8/16 bit multiplication */
4971 /*-----------------------------------------------------------------*/
4973 genMultOneByte (operand * left,
4978 int size = AOP_SIZE (result);
4979 bool runtimeSign, compiletimeSign;
4980 bool lUnsigned, rUnsigned, pushedB;
4982 D (emitcode (";", "genMultOneByte"));
4984 if (size < 1 || size > 2)
4986 /* this should never happen */
4987 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4988 AOP_SIZE(result), __FILE__, lineno);
4992 /* (if two literals: the value is computed before) */
4993 /* if one literal, literal on the right */
4994 if (AOP_TYPE (left) == AOP_LIT)
4999 /* emitcode (";", "swapped left and right"); */
5001 /* if no literal, unsigned on the right: shorter code */
5002 if ( AOP_TYPE (right) != AOP_LIT
5003 && SPEC_USIGN (getSpec (operandType (left))))
5010 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5011 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5015 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5016 no need to take care about the signedness! */
5017 || (lUnsigned && rUnsigned))
5019 /* just an unsigned 8 * 8 = 8 multiply
5021 /* emitcode (";","unsigned"); */
5022 /* TODO: check for accumulator clash between left & right aops? */
5024 if (AOP_TYPE (right) == AOP_LIT)
5026 /* moving to accumulator first helps peepholes */
5027 MOVA (aopGet (left, 0, FALSE, FALSE));
5028 MOVB (aopGet (right, 0, FALSE, FALSE));
5032 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5033 MOVA (aopGet (left, 0, FALSE, FALSE));
5036 emitcode ("mul", "ab");
5037 aopPut (result, "a", 0);
5039 aopPut (result, "b", 1);
5045 /* we have to do a signed multiply */
5046 /* emitcode (";", "signed"); */
5048 /* now sign adjust for both left & right */
5050 /* let's see what's needed: */
5051 /* apply negative sign during runtime */
5052 runtimeSign = FALSE;
5053 /* negative sign from literals */
5054 compiletimeSign = FALSE;
5058 if (AOP_TYPE(left) == AOP_LIT)
5060 /* signed literal */
5061 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5063 compiletimeSign = TRUE;
5066 /* signed but not literal */
5072 if (AOP_TYPE(right) == AOP_LIT)
5074 /* signed literal */
5075 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5077 compiletimeSign ^= TRUE;
5080 /* signed but not literal */
5084 /* initialize F0, which stores the runtime sign */
5087 if (compiletimeSign)
5088 emitcode ("setb", "F0"); /* set sign flag */
5090 emitcode ("clr", "F0"); /* reset sign flag */
5093 /* save the signs of the operands */
5094 if (AOP_TYPE(right) == AOP_LIT)
5096 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5098 if (!rUnsigned && val < 0)
5099 emitcode ("mov", "b,#0x%02x", -val);
5101 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5103 else /* ! literal */
5105 if (rUnsigned) /* emitcode (";", "signed"); */
5106 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5109 MOVA (aopGet (right, 0, FALSE, FALSE));
5110 lbl = newiTempLabel (NULL);
5111 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5112 emitcode ("cpl", "F0"); /* complement sign flag */
5113 emitcode ("cpl", "a"); /* 2's complement */
5114 emitcode ("inc", "a");
5116 emitcode ("mov", "b,a");
5120 if (AOP_TYPE(left) == AOP_LIT)
5122 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5124 if (!lUnsigned && val < 0)
5125 emitcode ("mov", "a,#0x%02x", -val);
5127 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5129 else /* ! literal */
5131 MOVA (aopGet (left, 0, FALSE, FALSE));
5135 lbl = newiTempLabel (NULL);
5136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5137 emitcode ("cpl", "F0"); /* complement sign flag */
5138 emitcode ("cpl", "a"); /* 2's complement */
5139 emitcode ("inc", "a");
5144 /* now the multiplication */
5145 emitcode ("mul", "ab");
5146 if (runtimeSign || compiletimeSign)
5148 lbl = newiTempLabel (NULL);
5150 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5151 emitcode ("cpl", "a"); /* lsb 2's complement */
5153 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5156 emitcode ("add", "a,#1"); /* this sets carry flag */
5157 emitcode ("xch", "a,b");
5158 emitcode ("cpl", "a"); /* msb 2's complement */
5159 emitcode ("addc", "a,#0");
5160 emitcode ("xch", "a,b");
5164 aopPut (result, "a", 0);
5166 aopPut (result, "b", 1);
5171 /*-----------------------------------------------------------------*/
5172 /* genMult - generates code for multiplication */
5173 /*-----------------------------------------------------------------*/
5175 genMult (iCode * ic)
5177 operand *left = IC_LEFT (ic);
5178 operand *right = IC_RIGHT (ic);
5179 operand *result = IC_RESULT (ic);
5181 D (emitcode (";", "genMult"));
5183 /* assign the asmops */
5184 aopOp (left, ic, FALSE);
5185 aopOp (right, ic, FALSE);
5186 aopOp (result, ic, TRUE);
5188 /* special cases first */
5190 if (AOP_TYPE (left) == AOP_CRY &&
5191 AOP_TYPE (right) == AOP_CRY)
5193 genMultbits (left, right, result);
5197 /* if both are of size == 1 */
5198 #if 0 // one of them can be a sloc shared with the result
5199 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5201 if (getSize(operandType(left)) == 1 &&
5202 getSize(operandType(right)) == 1)
5205 genMultOneByte (left, right, result);
5209 /* should have been converted to function call */
5210 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5211 getSize(OP_SYMBOL(right)->type));
5215 freeAsmop (result, NULL, ic, TRUE);
5216 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5217 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5220 /*-----------------------------------------------------------------*/
5221 /* genDivbits :- division of bits */
5222 /*-----------------------------------------------------------------*/
5224 genDivbits (operand * left,
5231 D(emitcode (";", "genDivbits"));
5235 /* the result must be bit */
5236 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5237 l = aopGet (left, 0, FALSE, FALSE);
5241 emitcode ("div", "ab");
5242 emitcode ("rrc", "a");
5246 aopPut (result, "c", 0);
5249 /*-----------------------------------------------------------------*/
5250 /* genDivOneByte : 8 bit division */
5251 /*-----------------------------------------------------------------*/
5253 genDivOneByte (operand * left,
5257 bool lUnsigned, rUnsigned, pushedB;
5258 bool runtimeSign, compiletimeSign;
5259 bool accuse = FALSE;
5260 bool pushedA = FALSE;
5264 D(emitcode (";", "genDivOneByte"));
5266 /* Why is it necessary that genDivOneByte() can return an int result?
5269 volatile unsigned char uc;
5270 volatile signed char sc1, sc2;
5283 In all cases a one byte result would overflow, the following cast to int
5284 would return the wrong result.
5286 Two possible solution:
5287 a) cast operands to int, if ((unsigned) / (signed)) or
5288 ((signed) / (signed))
5289 b) return an 16 bit signed int; this is what we're doing here!
5292 size = AOP_SIZE (result) - 1;
5294 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5295 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5299 /* signed or unsigned */
5300 if (lUnsigned && rUnsigned)
5302 /* unsigned is easy */
5303 MOVB (aopGet (right, 0, FALSE, FALSE));
5304 MOVA (aopGet (left, 0, FALSE, FALSE));
5305 emitcode ("div", "ab");
5306 aopPut (result, "a", 0);
5308 aopPut (result, zero, offset++);
5314 /* signed is a little bit more difficult */
5316 /* now sign adjust for both left & right */
5318 /* let's see what's needed: */
5319 /* apply negative sign during runtime */
5320 runtimeSign = FALSE;
5321 /* negative sign from literals */
5322 compiletimeSign = FALSE;
5326 if (AOP_TYPE(left) == AOP_LIT)
5328 /* signed literal */
5329 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5331 compiletimeSign = TRUE;
5334 /* signed but not literal */
5340 if (AOP_TYPE(right) == AOP_LIT)
5342 /* signed literal */
5343 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5345 compiletimeSign ^= TRUE;
5348 /* signed but not literal */
5352 /* initialize F0, which stores the runtime sign */
5355 if (compiletimeSign)
5356 emitcode ("setb", "F0"); /* set sign flag */
5358 emitcode ("clr", "F0"); /* reset sign flag */
5361 /* save the signs of the operands */
5362 if (AOP_TYPE(right) == AOP_LIT)
5364 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5366 if (!rUnsigned && val < 0)
5367 emitcode ("mov", "b,#0x%02x", -val);
5369 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5371 else /* ! literal */
5374 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5377 MOVA (aopGet (right, 0, FALSE, FALSE));
5378 lbl = newiTempLabel (NULL);
5379 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5380 emitcode ("cpl", "F0"); /* complement sign flag */
5381 emitcode ("cpl", "a"); /* 2's complement */
5382 emitcode ("inc", "a");
5384 emitcode ("mov", "b,a");
5388 if (AOP_TYPE(left) == AOP_LIT)
5390 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5392 if (!lUnsigned && val < 0)
5393 emitcode ("mov", "a,#0x%02x", -val);
5395 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5397 else /* ! literal */
5399 MOVA (aopGet (left, 0, FALSE, FALSE));
5403 lbl = newiTempLabel (NULL);
5404 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5405 emitcode ("cpl", "F0"); /* complement sign flag */
5406 emitcode ("cpl", "a"); /* 2's complement */
5407 emitcode ("inc", "a");
5412 /* now the division */
5413 emitcode ("div", "ab");
5415 if (runtimeSign || compiletimeSign)
5417 lbl = newiTempLabel (NULL);
5419 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5420 emitcode ("cpl", "a"); /* lsb 2's complement */
5421 emitcode ("inc", "a");
5424 accuse = aopPut (result, "a", 0);
5427 /* msb is 0x00 or 0xff depending on the sign */
5432 emitcode ("push", "acc");
5435 emitcode ("mov", "c,F0");
5436 emitcode ("subb", "a,acc");
5438 aopPut (result, "a", offset++);
5440 else /* compiletimeSign */
5442 if (aopPutUsesAcc (result, "#0xFF", offset))
5444 emitcode ("push", "acc");
5448 aopPut (result, "#0xff", offset++);
5454 aopPut (result, "a", 0);
5456 aopPut (result, zero, offset++);
5460 emitcode ("pop", "acc");
5464 /*-----------------------------------------------------------------*/
5465 /* genDiv - generates code for division */
5466 /*-----------------------------------------------------------------*/
5470 operand *left = IC_LEFT (ic);
5471 operand *right = IC_RIGHT (ic);
5472 operand *result = IC_RESULT (ic);
5474 D (emitcode (";", "genDiv"));
5476 /* assign the asmops */
5477 aopOp (left, ic, FALSE);
5478 aopOp (right, ic, FALSE);
5479 aopOp (result, ic, TRUE);
5481 /* special cases first */
5483 if (AOP_TYPE (left) == AOP_CRY &&
5484 AOP_TYPE (right) == AOP_CRY)
5486 genDivbits (left, right, result);
5490 /* if both are of size == 1 */
5491 if (AOP_SIZE (left) == 1 &&
5492 AOP_SIZE (right) == 1)
5494 genDivOneByte (left, right, result);
5498 /* should have been converted to function call */
5501 freeAsmop (result, NULL, ic, TRUE);
5502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506 /*-----------------------------------------------------------------*/
5507 /* genModbits :- modulus of bits */
5508 /*-----------------------------------------------------------------*/
5510 genModbits (operand * left,
5517 D (emitcode (";", "genModbits"));
5521 /* the result must be bit */
5522 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5523 l = aopGet (left, 0, FALSE, FALSE);
5527 emitcode ("div", "ab");
5528 emitcode ("mov", "a,b");
5529 emitcode ("rrc", "a");
5533 aopPut (result, "c", 0);
5536 /*-----------------------------------------------------------------*/
5537 /* genModOneByte : 8 bit modulus */
5538 /*-----------------------------------------------------------------*/
5540 genModOneByte (operand * left,
5544 bool lUnsigned, rUnsigned, pushedB;
5545 bool runtimeSign, compiletimeSign;
5549 D (emitcode (";", "genModOneByte"));
5551 size = AOP_SIZE (result) - 1;
5553 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5554 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5556 /* if right is a literal, check it for 2^n */
5557 if (AOP_TYPE(right) == AOP_LIT)
5559 unsigned char val = abs((int) operandLitValue(right));
5560 symbol *lbl2 = NULL;
5564 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5574 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5575 /* because iCode should have been changed to genAnd */
5576 /* see file "SDCCopt.c", function "convertToFcall()" */
5578 MOVA (aopGet (left, 0, FALSE, FALSE));
5579 emitcode ("mov", "c,acc.7");
5580 emitcode ("anl", "a,#0x%02x", val - 1);
5581 lbl = newiTempLabel (NULL);
5582 emitcode ("jz", "%05d$", (lbl->key + 100));
5583 emitcode ("jnc", "%05d$", (lbl->key + 100));
5584 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5590 aopPut (result, "a", 0);
5592 aopPut (result, "#0xff", offs2++);
5593 lbl2 = newiTempLabel (NULL);
5594 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5597 aopPut (result, "a", 0);
5599 aopPut (result, zero, offset++);
5613 /* signed or unsigned */
5614 if (lUnsigned && rUnsigned)
5616 /* unsigned is easy */
5617 MOVB (aopGet (right, 0, FALSE, FALSE));
5618 MOVA (aopGet (left, 0, FALSE, FALSE));
5619 emitcode ("div", "ab");
5620 aopPut (result, "b", 0);
5622 aopPut (result, zero, offset++);
5628 /* signed is a little bit more difficult */
5630 /* now sign adjust for both left & right */
5632 /* modulus: sign of the right operand has no influence on the result! */
5633 if (AOP_TYPE(right) == AOP_LIT)
5635 signed char val = (char) operandLitValue(right);
5637 if (!rUnsigned && val < 0)
5638 emitcode ("mov", "b,#0x%02x", -val);
5640 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5642 else /* not literal */
5645 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5648 MOVA (aopGet (right, 0, FALSE, FALSE));
5649 lbl = newiTempLabel (NULL);
5650 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5651 emitcode ("cpl", "a"); /* 2's complement */
5652 emitcode ("inc", "a");
5654 emitcode ("mov", "b,a");
5658 /* let's see what's needed: */
5659 /* apply negative sign during runtime */
5660 runtimeSign = FALSE;
5661 /* negative sign from literals */
5662 compiletimeSign = FALSE;
5664 /* sign adjust left side */
5665 if (AOP_TYPE(left) == AOP_LIT)
5667 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5669 if (!lUnsigned && val < 0)
5671 compiletimeSign = TRUE; /* set sign flag */
5672 emitcode ("mov", "a,#0x%02x", -val);
5675 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5677 else /* ! literal */
5679 MOVA (aopGet (left, 0, FALSE, FALSE));
5684 emitcode ("clr", "F0"); /* clear sign flag */
5686 lbl = newiTempLabel (NULL);
5687 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5688 emitcode ("setb", "F0"); /* set sign flag */
5689 emitcode ("cpl", "a"); /* 2's complement */
5690 emitcode ("inc", "a");
5695 /* now the modulus */
5696 emitcode ("div", "ab");
5698 if (runtimeSign || compiletimeSign)
5700 emitcode ("mov", "a,b");
5701 lbl = newiTempLabel (NULL);
5703 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5704 emitcode ("cpl", "a"); /* 2's complement */
5705 emitcode ("inc", "a");
5708 aopPut (result, "a", 0);
5711 /* msb is 0x00 or 0xff depending on the sign */
5714 emitcode ("mov", "c,F0");
5715 emitcode ("subb", "a,acc");
5717 aopPut (result, "a", offset++);
5719 else /* compiletimeSign */
5721 aopPut (result, "#0xff", offset++);
5726 aopPut (result, "b", 0);
5728 aopPut (result, zero, offset++);
5734 /*-----------------------------------------------------------------*/
5735 /* genMod - generates code for division */
5736 /*-----------------------------------------------------------------*/
5740 operand *left = IC_LEFT (ic);
5741 operand *right = IC_RIGHT (ic);
5742 operand *result = IC_RESULT (ic);
5744 D (emitcode (";", "genMod"));
5746 /* assign the asmops */
5747 aopOp (left, ic, FALSE);
5748 aopOp (right, ic, FALSE);
5749 aopOp (result, ic, TRUE);
5751 /* special cases first */
5753 if (AOP_TYPE (left) == AOP_CRY &&
5754 AOP_TYPE (right) == AOP_CRY)
5756 genModbits (left, right, result);
5760 /* if both are of size == 1 */
5761 if (AOP_SIZE (left) == 1 &&
5762 AOP_SIZE (right) == 1)
5764 genModOneByte (left, right, result);
5768 /* should have been converted to function call */
5772 freeAsmop (result, NULL, ic, TRUE);
5773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 /*-----------------------------------------------------------------*/
5778 /* genIfxJump :- will create a jump depending on the ifx */
5779 /*-----------------------------------------------------------------*/
5781 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5784 symbol *tlbl = newiTempLabel (NULL);
5787 D (emitcode (";", "genIfxJump"));
5789 /* if true label then we jump if condition
5793 jlbl = IC_TRUE (ic);
5794 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5795 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5799 /* false label is present */
5800 jlbl = IC_FALSE (ic);
5801 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5802 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5804 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5805 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5807 emitcode (inst, "%05d$", tlbl->key + 100);
5808 freeForBranchAsmop (result);
5809 freeForBranchAsmop (right);
5810 freeForBranchAsmop (left);
5811 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5814 /* mark the icode as generated */
5818 /*-----------------------------------------------------------------*/
5819 /* genCmp :- greater or less than comparison */
5820 /*-----------------------------------------------------------------*/
5822 genCmp (operand * left, operand * right,
5823 operand * result, iCode * ifx, int sign, iCode *ic)
5825 int size, offset = 0;
5826 unsigned long lit = 0L;
5829 D (emitcode (";", "genCmp"));
5831 /* if left & right are bit variables */
5832 if (AOP_TYPE (left) == AOP_CRY &&
5833 AOP_TYPE (right) == AOP_CRY)
5835 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5836 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5840 /* subtract right from left if at the
5841 end the carry flag is set then we know that
5842 left is greater than right */
5843 size = max (AOP_SIZE (left), AOP_SIZE (right));
5845 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5846 if ((size == 1) && !sign &&
5847 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5849 symbol *lbl = newiTempLabel (NULL);
5850 emitcode ("cjne", "%s,%s,%05d$",
5851 aopGet (left, offset, FALSE, FALSE),
5852 aopGet (right, offset, FALSE, FALSE),
5858 if (AOP_TYPE (right) == AOP_LIT)
5860 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5861 /* optimize if(x < 0) or if(x >= 0) */
5870 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5871 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5873 genIfxJump (ifx, "acc.7", left, right, result);
5874 freeAsmop (right, NULL, ic, TRUE);
5875 freeAsmop (left, NULL, ic, TRUE);
5881 emitcode ("rlc", "a");
5888 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5889 while (size && (bytelit == 0))
5892 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5898 MOVA (aopGet (left, offset, FALSE, FALSE));
5899 if (sign && size == 0)
5901 emitcode ("xrl", "a,#0x80");
5902 emitcode ("subb", "a,#0x%02x",
5903 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5907 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5917 bool pushedB = FALSE;
5918 rightInB = aopGetUsesAcc(right, offset);
5922 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5924 MOVA (aopGet (left, offset, FALSE, FALSE));
5925 if (sign && size == 0)
5927 emitcode ("xrl", "a,#0x80");
5932 MOVB (aopGet (right, offset, FALSE, FALSE));
5934 emitcode ("xrl", "b,#0x80");
5935 emitcode ("subb", "a,b");
5940 emitcode ("subb", "a,b");
5942 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5954 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5960 /* if the result is used in the next
5961 ifx conditional branch then generate
5962 code a little differently */
5965 genIfxJump (ifx, "c", NULL, NULL, result);
5971 /* leave the result in acc */
5975 /*-----------------------------------------------------------------*/
5976 /* genCmpGt :- greater than comparison */
5977 /*-----------------------------------------------------------------*/
5979 genCmpGt (iCode * ic, iCode * ifx)
5981 operand *left, *right, *result;
5982 sym_link *letype, *retype;
5985 D (emitcode (";", "genCmpGt"));
5987 left = IC_LEFT (ic);
5988 right = IC_RIGHT (ic);
5989 result = IC_RESULT (ic);
5991 letype = getSpec (operandType (left));
5992 retype = getSpec (operandType (right));
5993 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5994 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5995 /* assign the asmops */
5996 aopOp (result, ic, TRUE);
5997 aopOp (left, ic, FALSE);
5998 aopOp (right, ic, FALSE);
6000 genCmp (right, left, result, ifx, sign, ic);
6002 freeAsmop (result, NULL, ic, TRUE);
6005 /*-----------------------------------------------------------------*/
6006 /* genCmpLt - less than comparisons */
6007 /*-----------------------------------------------------------------*/
6009 genCmpLt (iCode * ic, iCode * ifx)
6011 operand *left, *right, *result;
6012 sym_link *letype, *retype;
6015 D (emitcode (";", "genCmpLt"));
6017 left = IC_LEFT (ic);
6018 right = IC_RIGHT (ic);
6019 result = IC_RESULT (ic);
6021 letype = getSpec (operandType (left));
6022 retype = getSpec (operandType (right));
6023 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6024 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6025 /* assign the asmops */
6026 aopOp (result, ic, TRUE);
6027 aopOp (left, ic, FALSE);
6028 aopOp (right, ic, FALSE);
6030 genCmp (left, right, result, ifx, sign, ic);
6032 freeAsmop (result, NULL, ic, TRUE);
6035 /*-----------------------------------------------------------------*/
6036 /* gencjneshort - compare and jump if not equal */
6037 /*-----------------------------------------------------------------*/
6039 gencjneshort (operand * left, operand * right, symbol * lbl)
6041 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6043 unsigned long lit = 0L;
6045 D (emitcode (";", "gencjneshort"));
6047 /* if the left side is a literal or
6048 if the right is in a pointer register and left
6050 if ((AOP_TYPE (left) == AOP_LIT) ||
6051 (AOP_TYPE (left) == AOP_IMMD) ||
6052 (AOP_TYPE (left) == AOP_DIR) ||
6053 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6060 if (AOP_TYPE (right) == AOP_LIT)
6061 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6063 /* if the right side is a literal then anything goes */
6064 if (AOP_TYPE (right) == AOP_LIT &&
6065 AOP_TYPE (left) != AOP_DIR &&
6066 AOP_TYPE (left) != AOP_IMMD)
6070 emitcode ("cjne", "%s,%s,%05d$",
6071 aopGet (left, offset, FALSE, FALSE),
6072 aopGet (right, offset, FALSE, FALSE),
6078 /* if the right side is in a register or in direct space or
6079 if the left is a pointer register & right is not */
6080 else if (AOP_TYPE (right) == AOP_REG ||
6081 AOP_TYPE (right) == AOP_DIR ||
6082 AOP_TYPE (right) == AOP_LIT ||
6083 AOP_TYPE (right) == AOP_IMMD ||
6084 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6085 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6089 MOVA (aopGet (left, offset, FALSE, FALSE));
6090 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6091 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6092 emitcode ("jnz", "%05d$", lbl->key + 100);
6094 emitcode ("cjne", "a,%s,%05d$",
6095 aopGet (right, offset, FALSE, TRUE),
6102 /* right is a pointer reg need both a & b */
6105 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6106 wassertl(!BINUSE, "B was in use");
6107 MOVB (aopGet (left, offset, FALSE, FALSE));
6108 MOVA (aopGet (right, offset, FALSE, FALSE));
6109 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6115 /*-----------------------------------------------------------------*/
6116 /* gencjne - compare and jump if not equal */
6117 /*-----------------------------------------------------------------*/
6119 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6121 symbol *tlbl = newiTempLabel (NULL);
6123 D (emitcode (";", "gencjne"));
6125 gencjneshort (left, right, lbl);
6131 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6140 /*-----------------------------------------------------------------*/
6141 /* genCmpEq - generates code for equal to */
6142 /*-----------------------------------------------------------------*/
6144 genCmpEq (iCode * ic, iCode * ifx)
6146 bool swappedLR = FALSE;
6147 operand *left, *right, *result;
6149 D (emitcode (";", "genCmpEq"));
6151 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6152 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6153 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6155 /* if literal, literal on the right or
6156 if the right is in a pointer register and left
6158 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6159 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6161 operand *t = IC_RIGHT (ic);
6162 IC_RIGHT (ic) = IC_LEFT (ic);
6167 if (ifx && !AOP_SIZE (result))
6170 /* if they are both bit variables */
6171 if (AOP_TYPE (left) == AOP_CRY &&
6172 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6174 if (AOP_TYPE (right) == AOP_LIT)
6176 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6179 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6180 emitcode ("cpl", "c");
6184 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6188 emitcode ("clr", "c");
6190 /* AOP_TYPE(right) == AOP_CRY */
6194 symbol *lbl = newiTempLabel (NULL);
6195 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6196 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6197 emitcode ("cpl", "c");
6200 /* if true label then we jump if condition
6202 tlbl = newiTempLabel (NULL);
6205 emitcode ("jnc", "%05d$", tlbl->key + 100);
6206 freeForBranchAsmop (result);
6207 freeForBranchAsmop (right);
6208 freeForBranchAsmop (left);
6209 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6213 emitcode ("jc", "%05d$", tlbl->key + 100);
6214 freeForBranchAsmop (result);
6215 freeForBranchAsmop (right);
6216 freeForBranchAsmop (left);
6217 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6223 tlbl = newiTempLabel (NULL);
6224 gencjneshort (left, right, tlbl);
6227 freeForBranchAsmop (result);
6228 freeForBranchAsmop (right);
6229 freeForBranchAsmop (left);
6230 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6235 symbol *lbl = newiTempLabel (NULL);
6236 emitcode ("sjmp", "%05d$", lbl->key + 100);
6238 freeForBranchAsmop (result);
6239 freeForBranchAsmop (right);
6240 freeForBranchAsmop (left);
6241 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6245 /* mark the icode as generated */
6250 /* if they are both bit variables */
6251 if (AOP_TYPE (left) == AOP_CRY &&
6252 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6254 if (AOP_TYPE (right) == AOP_LIT)
6256 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6260 emitcode ("cpl", "c");
6264 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6268 emitcode ("clr", "c");
6270 /* AOP_TYPE(right) == AOP_CRY */
6274 symbol *lbl = newiTempLabel (NULL);
6275 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6276 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6277 emitcode ("cpl", "c");
6281 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6288 genIfxJump (ifx, "c", left, right, result);
6291 /* if the result is used in an arithmetic operation
6292 then put the result in place */
6297 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6299 gencjne (left, right, newiTempLabel (NULL), TRUE);
6300 aopPut (result, "c", 0);
6303 gencjne (left, right, newiTempLabel (NULL), FALSE);
6306 genIfxJump (ifx, "a", left, right, result);
6309 /* if the result is used in an arithmetic operation
6310 then put the result in place */
6311 if (AOP_TYPE (result) != AOP_CRY)
6313 /* leave the result in acc */
6317 freeAsmop (result, NULL, ic, TRUE);
6320 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6321 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6330 /*-----------------------------------------------------------------*/
6331 /* ifxForOp - returns the icode containing the ifx for operand */
6332 /*-----------------------------------------------------------------*/
6334 ifxForOp (operand * op, iCode * ic)
6336 /* if true symbol then needs to be assigned */
6337 if (IS_TRUE_SYMOP (op))
6340 /* if this has register type condition and
6341 the next instruction is ifx with the same operand
6342 and live to of the operand is upto the ifx only then */
6344 ic->next->op == IFX &&
6345 IC_COND (ic->next)->key == op->key &&
6346 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6352 /*-----------------------------------------------------------------*/
6353 /* hasInc - operand is incremented before any other use */
6354 /*-----------------------------------------------------------------*/
6356 hasInc (operand *op, iCode *ic, int osize)
6358 sym_link *type = operandType(op);
6359 sym_link *retype = getSpec (type);
6360 iCode *lic = ic->next;
6363 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6364 if (!IS_SYMOP(op)) return NULL;
6366 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6367 if (IS_AGGREGATE(type->next)) return NULL;
6368 if (osize != (isize = getSize(type->next))) return NULL;
6371 /* if operand of the form op = op + <sizeof *op> */
6372 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6373 isOperandEqual(IC_RESULT(lic),op) &&
6374 isOperandLiteral(IC_RIGHT(lic)) &&
6375 operandLitValue(IC_RIGHT(lic)) == isize) {
6378 /* if the operand used or deffed */
6379 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6382 /* if GOTO or IFX */
6383 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6389 /*-----------------------------------------------------------------*/
6390 /* genAndOp - for && operation */
6391 /*-----------------------------------------------------------------*/
6393 genAndOp (iCode * ic)
6395 operand *left, *right, *result;
6398 D (emitcode (";", "genAndOp"));
6400 /* note here that && operations that are in an
6401 if statement are taken away by backPatchLabels
6402 only those used in arthmetic operations remain */
6403 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6404 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6405 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6407 /* if both are bit variables */
6408 if (AOP_TYPE (left) == AOP_CRY &&
6409 AOP_TYPE (right) == AOP_CRY)
6411 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6412 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6417 tlbl = newiTempLabel (NULL);
6419 emitcode ("jz", "%05d$", tlbl->key + 100);
6425 freeAsmop (result, NULL, ic, TRUE);
6426 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6427 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431 /*-----------------------------------------------------------------*/
6432 /* genOrOp - for || operation */
6433 /*-----------------------------------------------------------------*/
6435 genOrOp (iCode * ic)
6437 operand *left, *right, *result;
6440 D (emitcode (";", "genOrOp"));
6442 /* note here that || operations that are in an
6443 if statement are taken away by backPatchLabels
6444 only those used in arthmetic operations remain */
6445 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6446 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6447 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6449 /* if both are bit variables */
6450 if (AOP_TYPE (left) == AOP_CRY &&
6451 AOP_TYPE (right) == AOP_CRY)
6453 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6454 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6459 tlbl = newiTempLabel (NULL);
6461 emitcode ("jnz", "%05d$", tlbl->key + 100);
6467 freeAsmop (result, NULL, ic, TRUE);
6468 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6472 /*-----------------------------------------------------------------*/
6473 /* isLiteralBit - test if lit == 2^n */
6474 /*-----------------------------------------------------------------*/
6476 isLiteralBit (unsigned long lit)
6478 unsigned long pw[32] =
6479 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6480 0x100L, 0x200L, 0x400L, 0x800L,
6481 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6482 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6483 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6484 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6485 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6488 for (idx = 0; idx < 32; idx++)
6494 /*-----------------------------------------------------------------*/
6495 /* continueIfTrue - */
6496 /*-----------------------------------------------------------------*/
6498 continueIfTrue (iCode * ic)
6501 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6505 /*-----------------------------------------------------------------*/
6507 /*-----------------------------------------------------------------*/
6509 jumpIfTrue (iCode * ic)
6512 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6516 /*-----------------------------------------------------------------*/
6517 /* jmpTrueOrFalse - */
6518 /*-----------------------------------------------------------------*/
6520 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6522 // ugly but optimized by peephole
6525 symbol *nlbl = newiTempLabel (NULL);
6526 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6528 freeForBranchAsmop (result);
6529 freeForBranchAsmop (right);
6530 freeForBranchAsmop (left);
6531 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6536 freeForBranchAsmop (result);
6537 freeForBranchAsmop (right);
6538 freeForBranchAsmop (left);
6539 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6545 /*-----------------------------------------------------------------*/
6546 /* genAnd - code for and */
6547 /*-----------------------------------------------------------------*/
6549 genAnd (iCode * ic, iCode * ifx)
6551 operand *left, *right, *result;
6552 int size, offset = 0;
6553 unsigned long lit = 0L;
6557 D (emitcode (";", "genAnd"));
6559 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6560 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6561 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6564 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6566 AOP_TYPE (left), AOP_TYPE (right));
6567 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6569 AOP_SIZE (left), AOP_SIZE (right));
6572 /* if left is a literal & right is not then exchange them */
6573 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6574 AOP_NEEDSACC (left))
6576 operand *tmp = right;
6581 /* if result = right then exchange left and right */
6582 if (sameRegs (AOP (result), AOP (right)))
6584 operand *tmp = right;
6589 /* if right is bit then exchange them */
6590 if (AOP_TYPE (right) == AOP_CRY &&
6591 AOP_TYPE (left) != AOP_CRY)
6593 operand *tmp = right;
6597 if (AOP_TYPE (right) == AOP_LIT)
6598 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6600 size = AOP_SIZE (result);
6603 // result = bit & yy;
6604 if (AOP_TYPE (left) == AOP_CRY)
6606 // c = bit & literal;
6607 if (AOP_TYPE (right) == AOP_LIT)
6611 if (size && sameRegs (AOP (result), AOP (left)))
6614 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6619 if (size && (AOP_TYPE (result) == AOP_CRY))
6621 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6624 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6629 emitcode ("clr", "c");
6634 if (AOP_TYPE (right) == AOP_CRY)
6637 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6638 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6643 MOVA (aopGet (right, 0, FALSE, FALSE));
6645 emitcode ("rrc", "a");
6646 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6654 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6655 genIfxJump (ifx, "c", left, right, result);
6659 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6660 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6661 if ((AOP_TYPE (right) == AOP_LIT) &&
6662 (AOP_TYPE (result) == AOP_CRY) &&
6663 (AOP_TYPE (left) != AOP_CRY))
6665 int posbit = isLiteralBit (lit);
6670 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6674 switch (posbit & 0x07)
6676 case 0: emitcode ("rrc", "a");
6678 case 7: emitcode ("rlc", "a");
6680 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6689 SNPRINTF (buffer, sizeof(buffer),
6690 "acc.%d", posbit & 0x07);
6691 genIfxJump (ifx, buffer, left, right, result);
6694 {// what is this case? just found it in ds390/gen.c
6695 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6702 symbol *tlbl = newiTempLabel (NULL);
6703 int sizel = AOP_SIZE (left);
6705 emitcode ("setb", "c");
6708 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6710 MOVA (aopGet (left, offset, FALSE, FALSE));
6712 if ((posbit = isLiteralBit (bytelit)) != 0)
6713 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6716 if (bytelit != 0x0FFL)
6717 emitcode ("anl", "a,%s",
6718 aopGet (right, offset, FALSE, TRUE));
6719 emitcode ("jnz", "%05d$", tlbl->key + 100);
6724 // bit = left & literal
6727 emitcode ("clr", "c");
6730 // if(left & literal)
6734 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6744 /* if left is same as result */
6745 if (sameRegs (AOP (result), AOP (left)))
6747 for (; size--; offset++)
6749 if (AOP_TYPE (right) == AOP_LIT)
6751 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6752 if (bytelit == 0x0FF)
6754 /* dummy read of volatile operand */
6755 if (isOperandVolatile (left, FALSE))
6756 MOVA (aopGet (left, offset, FALSE, FALSE));
6760 else if (bytelit == 0)
6762 aopPut (result, zero, offset);
6764 else if (IS_AOP_PREG (result))
6766 MOVA (aopGet (left, offset, FALSE, TRUE));
6767 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6768 aopPut (result, "a", offset);
6771 emitcode ("anl", "%s,%s",
6772 aopGet (left, offset, FALSE, TRUE),
6773 aopGet (right, offset, FALSE, FALSE));
6777 if (AOP_TYPE (left) == AOP_ACC)
6780 emitcode("mov", "a,b");
6781 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6783 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6785 MOVB (aopGet (left, offset, FALSE, FALSE));
6786 MOVA (aopGet (right, offset, FALSE, FALSE));
6787 emitcode ("anl", "a,b");
6788 aopPut (result, "a", offset);
6790 else if (aopGetUsesAcc (left, offset))
6792 MOVA (aopGet (left, offset, FALSE, FALSE));
6793 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6794 aopPut (result, "a", offset);
6798 MOVA (aopGet (right, offset, FALSE, FALSE));
6799 if (IS_AOP_PREG (result))
6801 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6802 aopPut (result, "a", offset);
6805 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6812 // left & result in different registers
6813 if (AOP_TYPE (result) == AOP_CRY)
6816 // if(size), result in bit
6817 // if(!size && ifx), conditional oper: if(left & right)
6818 symbol *tlbl = newiTempLabel (NULL);
6819 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6821 emitcode ("setb", "c");
6824 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6825 && AOP_TYPE(left)==AOP_ACC)
6828 emitcode("mov", "a,b");
6829 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6831 else if (AOP_TYPE(left)==AOP_ACC)
6835 bool pushedB = pushB ();
6836 emitcode("mov", "b,a");
6837 MOVA (aopGet (right, offset, FALSE, FALSE));
6838 emitcode("anl", "a,b");
6843 MOVA (aopGet (right, offset, FALSE, FALSE));
6844 emitcode("anl", "a,b");
6847 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6849 MOVB (aopGet (left, offset, FALSE, FALSE));
6850 MOVA (aopGet (right, offset, FALSE, FALSE));
6851 emitcode ("anl", "a,b");
6853 else if (aopGetUsesAcc (left, offset))
6855 MOVA (aopGet (left, offset, FALSE, FALSE));
6856 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6860 MOVA (aopGet (right, offset, FALSE, FALSE));
6861 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6864 emitcode ("jnz", "%05d$", tlbl->key + 100);
6874 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6880 for (; (size--); offset++)
6883 // result = left & right
6884 if (AOP_TYPE (right) == AOP_LIT)
6886 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6887 if (bytelit == 0x0FF)
6890 aopGet (left, offset, FALSE, FALSE),
6894 else if (bytelit == 0)
6896 /* dummy read of volatile operand */
6897 if (isOperandVolatile (left, FALSE))
6898 MOVA (aopGet (left, offset, FALSE, FALSE));
6899 aopPut (result, zero, offset);
6902 else if (AOP_TYPE (left) == AOP_ACC)
6906 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6907 aopPut (result, "a", offset);
6912 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6913 aopPut (result, "b", offset);
6918 // faster than result <- left, anl result,right
6919 // and better if result is SFR
6920 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6921 && AOP_TYPE(left)==AOP_ACC)
6924 emitcode("mov", "a,b");
6925 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6927 else if (AOP_TYPE(left)==AOP_ACC)
6931 bool pushedB = pushB ();
6932 emitcode("mov", "b,a");
6933 MOVA (aopGet (right, offset, FALSE, FALSE));
6934 emitcode("anl", "a,b");
6939 MOVA (aopGet (right, offset, FALSE, FALSE));
6940 emitcode("anl", "a,b");
6943 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6945 MOVB (aopGet (left, offset, FALSE, FALSE));
6946 MOVA (aopGet (right, offset, FALSE, FALSE));
6947 emitcode ("anl", "a,b");
6949 else if (aopGetUsesAcc (left, offset))
6951 MOVA (aopGet (left, offset, FALSE, FALSE));
6952 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6956 MOVA (aopGet (right, offset, FALSE, FALSE));
6957 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6959 aopPut (result, "a", offset);
6965 freeAsmop (result, NULL, ic, TRUE);
6966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6970 /*-----------------------------------------------------------------*/
6971 /* genOr - code for or */
6972 /*-----------------------------------------------------------------*/
6974 genOr (iCode * ic, iCode * ifx)
6976 operand *left, *right, *result;
6977 int size, offset = 0;
6978 unsigned long lit = 0L;
6981 D (emitcode (";", "genOr"));
6983 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6984 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6985 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6988 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6990 AOP_TYPE (left), AOP_TYPE (right));
6991 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6993 AOP_SIZE (left), AOP_SIZE (right));
6996 /* if left is a literal & right is not then exchange them */
6997 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6998 AOP_NEEDSACC (left))
7000 operand *tmp = right;
7005 /* if result = right then exchange them */
7006 if (sameRegs (AOP (result), AOP (right)))
7008 operand *tmp = right;
7013 /* if right is bit then exchange them */
7014 if (AOP_TYPE (right) == AOP_CRY &&
7015 AOP_TYPE (left) != AOP_CRY)
7017 operand *tmp = right;
7021 if (AOP_TYPE (right) == AOP_LIT)
7022 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7024 size = AOP_SIZE (result);
7028 if (AOP_TYPE (left) == AOP_CRY)
7030 if (AOP_TYPE (right) == AOP_LIT)
7032 // c = bit | literal;
7035 // lit != 0 => result = 1
7036 if (AOP_TYPE (result) == AOP_CRY)
7039 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7041 continueIfTrue (ifx);
7044 emitcode ("setb", "c");
7048 // lit == 0 => result = left
7049 if (size && sameRegs (AOP (result), AOP (left)))
7051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7056 if (AOP_TYPE (right) == AOP_CRY)
7059 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7060 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7065 symbol *tlbl = newiTempLabel (NULL);
7066 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7067 emitcode ("setb", "c");
7068 emitcode ("jb", "%s,%05d$",
7069 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7071 emitcode ("jnz", "%05d$", tlbl->key + 100);
7072 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7074 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7089 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7090 genIfxJump (ifx, "c", left, right, result);
7094 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7095 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7096 if ((AOP_TYPE (right) == AOP_LIT) &&
7097 (AOP_TYPE (result) == AOP_CRY) &&
7098 (AOP_TYPE (left) != AOP_CRY))
7104 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7106 continueIfTrue (ifx);
7111 // lit = 0, result = boolean(left)
7113 emitcode ("setb", "c");
7117 symbol *tlbl = newiTempLabel (NULL);
7118 emitcode ("jnz", "%05d$", tlbl->key + 100);
7124 genIfxJump (ifx, "a", left, right, result);
7132 /* if left is same as result */
7133 if (sameRegs (AOP (result), AOP (left)))
7135 for (; size--; offset++)
7137 if (AOP_TYPE (right) == AOP_LIT)
7139 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7142 /* dummy read of volatile operand */
7143 if (isOperandVolatile (left, FALSE))
7144 MOVA (aopGet (left, offset, FALSE, FALSE));
7148 else if (bytelit == 0x0FF)
7150 aopPut (result, "#0xFF", offset);
7152 else if (IS_AOP_PREG (left))
7154 MOVA (aopGet (left, offset, FALSE, TRUE));
7155 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7156 aopPut (result, "a", offset);
7160 emitcode ("orl", "%s,%s",
7161 aopGet (left, offset, FALSE, TRUE),
7162 aopGet (right, offset, FALSE, FALSE));
7167 if (AOP_TYPE (left) == AOP_ACC)
7170 emitcode("mov", "a,b");
7171 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7173 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7175 MOVB (aopGet (left, offset, FALSE, FALSE));
7176 MOVA (aopGet (right, offset, FALSE, FALSE));
7177 emitcode ("orl", "a,b");
7178 aopPut (result, "a", offset);
7180 else if (aopGetUsesAcc (left, offset))
7182 MOVA (aopGet (left, offset, FALSE, FALSE));
7183 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184 aopPut (result, "a", offset);
7188 MOVA (aopGet (right, offset, FALSE, FALSE));
7189 if (IS_AOP_PREG (left))
7191 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7192 aopPut (result, "a", offset);
7196 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7204 // left & result in different registers
7205 if (AOP_TYPE (result) == AOP_CRY)
7208 // if(size), result in bit
7209 // if(!size && ifx), conditional oper: if(left | right)
7210 symbol *tlbl = newiTempLabel (NULL);
7211 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7213 emitcode ("setb", "c");
7216 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7217 && AOP_TYPE(left)==AOP_ACC)
7220 emitcode("mov", "a,b");
7221 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7223 else if (AOP_TYPE(left)==AOP_ACC)
7227 bool pushedB = pushB ();
7228 emitcode("mov", "b,a");
7229 MOVA (aopGet (right, offset, FALSE, FALSE));
7230 emitcode("orl", "a,b");
7235 MOVA (aopGet (right, offset, FALSE, FALSE));
7236 emitcode("orl", "a,b");
7239 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7241 MOVB (aopGet (left, offset, FALSE, FALSE));
7242 MOVA (aopGet (right, offset, FALSE, FALSE));
7243 emitcode ("orl", "a,b");
7245 else if (aopGetUsesAcc (left, offset))
7247 MOVA (aopGet (left, offset, FALSE, FALSE));
7248 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7252 MOVA (aopGet (right, offset, FALSE, FALSE));
7253 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7256 emitcode ("jnz", "%05d$", tlbl->key + 100);
7266 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7272 for (; (size--); offset++)
7275 // result = left | right
7276 if (AOP_TYPE (right) == AOP_LIT)
7278 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7282 aopGet (left, offset, FALSE, FALSE),
7286 else if (bytelit == 0x0FF)
7288 /* dummy read of volatile operand */
7289 if (isOperandVolatile (left, FALSE))
7290 MOVA (aopGet (left, offset, FALSE, FALSE));
7291 aopPut (result, "#0xFF", offset);
7295 // faster than result <- left, orl result,right
7296 // and better if result is SFR
7297 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7298 && AOP_TYPE(left)==AOP_ACC)
7301 emitcode("mov", "a,b");
7302 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7304 else if (AOP_TYPE(left)==AOP_ACC)
7308 bool pushedB = pushB ();
7309 emitcode("mov", "b,a");
7310 MOVA (aopGet (right, offset, FALSE, FALSE));
7311 emitcode("orl", "a,b");
7316 MOVA (aopGet (right, offset, FALSE, FALSE));
7317 emitcode("orl", "a,b");
7320 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7322 MOVB (aopGet (left, offset, FALSE, FALSE));
7323 MOVA (aopGet (right, offset, FALSE, FALSE));
7324 emitcode ("orl", "a,b");
7326 else if (aopGetUsesAcc (left, offset))
7328 MOVA (aopGet (left, offset, FALSE, FALSE));
7329 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7333 MOVA (aopGet (right, offset, FALSE, FALSE));
7334 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7336 aopPut (result, "a", offset);
7342 freeAsmop (result, NULL, ic, TRUE);
7343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7344 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7347 /*-----------------------------------------------------------------*/
7348 /* genXor - code for xclusive or */
7349 /*-----------------------------------------------------------------*/
7351 genXor (iCode * ic, iCode * ifx)
7353 operand *left, *right, *result;
7354 int size, offset = 0;
7355 unsigned long lit = 0L;
7358 D (emitcode (";", "genXor"));
7360 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7361 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7362 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7365 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7367 AOP_TYPE (left), AOP_TYPE (right));
7368 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7370 AOP_SIZE (left), AOP_SIZE (right));
7373 /* if left is a literal & right is not ||
7374 if left needs acc & right does not */
7375 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7376 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7378 operand *tmp = right;
7383 /* if result = right then exchange them */
7384 if (sameRegs (AOP (result), AOP (right)))
7386 operand *tmp = right;
7391 /* if right is bit then exchange them */
7392 if (AOP_TYPE (right) == AOP_CRY &&
7393 AOP_TYPE (left) != AOP_CRY)
7395 operand *tmp = right;
7400 if (AOP_TYPE (right) == AOP_LIT)
7401 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7403 size = AOP_SIZE (result);
7407 if (AOP_TYPE (left) == AOP_CRY)
7409 if (AOP_TYPE (right) == AOP_LIT)
7411 // c = bit & literal;
7414 // lit>>1 != 0 => result = 1
7415 if (AOP_TYPE (result) == AOP_CRY)
7418 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7420 continueIfTrue (ifx);
7423 emitcode ("setb", "c");
7430 // lit == 0, result = left
7431 if (size && sameRegs (AOP (result), AOP (left)))
7433 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7437 // lit == 1, result = not(left)
7438 if (size && sameRegs (AOP (result), AOP (left)))
7440 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7445 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7446 emitcode ("cpl", "c");
7454 symbol *tlbl = newiTempLabel (NULL);
7455 if (AOP_TYPE (right) == AOP_CRY)
7458 if (IS_SYMOP (left) && OP_SYMBOL (left) && OP_SYMBOL (left)->accuse)
7459 {// left already is in the carry
7460 operand *tmp = right;
7466 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7474 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7475 emitcode ("cpl", "c");
7483 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7484 genIfxJump (ifx, "c", left, right, result);
7488 /* if left is same as result */
7489 if (sameRegs (AOP (result), AOP (left)))
7491 for (; size--; offset++)
7493 if (AOP_TYPE (right) == AOP_LIT)
7495 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7498 /* dummy read of volatile operand */
7499 if (isOperandVolatile (left, FALSE))
7500 MOVA (aopGet (left, offset, FALSE, FALSE));
7504 else if (IS_AOP_PREG (left))
7506 MOVA (aopGet (left, offset, FALSE, TRUE));
7507 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7508 aopPut (result, "a", offset);
7512 emitcode ("xrl", "%s,%s",
7513 aopGet (left, offset, FALSE, TRUE),
7514 aopGet (right, offset, FALSE, FALSE));
7519 if (AOP_TYPE (left) == AOP_ACC)
7522 emitcode("mov", "a,b");
7523 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7525 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7527 MOVB (aopGet (left, offset, FALSE, FALSE));
7528 MOVA (aopGet (right, offset, FALSE, FALSE));
7529 emitcode ("xrl", "a,b");
7530 aopPut (result, "a", offset);
7532 else if (aopGetUsesAcc (left, offset))
7534 MOVA (aopGet (left, offset, FALSE, FALSE));
7535 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7536 aopPut (result, "a", offset);
7540 MOVA (aopGet (right, offset, FALSE, FALSE));
7541 if (IS_AOP_PREG (left))
7543 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7544 aopPut (result, "a", offset);
7547 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7554 // left & result in different registers
7555 if (AOP_TYPE (result) == AOP_CRY)
7558 // if(size), result in bit
7559 // if(!size && ifx), conditional oper: if(left ^ right)
7560 symbol *tlbl = newiTempLabel (NULL);
7561 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7564 emitcode ("setb", "c");
7567 if ((AOP_TYPE (right) == AOP_LIT) &&
7568 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7570 MOVA (aopGet (left, offset, FALSE, FALSE));
7572 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7573 && AOP_TYPE(left)==AOP_ACC)
7576 emitcode("mov", "a,b");
7577 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7579 else if (AOP_TYPE(left)==AOP_ACC)
7583 bool pushedB = pushB ();
7584 emitcode("mov", "b,a");
7585 MOVA (aopGet (right, offset, FALSE, FALSE));
7586 emitcode("xrl", "a,b");
7591 MOVA (aopGet (right, offset, FALSE, FALSE));
7592 emitcode("xrl", "a,b");
7595 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7597 MOVB (aopGet (left, offset, FALSE, FALSE));
7598 MOVA (aopGet (right, offset, FALSE, FALSE));
7599 emitcode ("xrl", "a,b");
7601 else if (aopGetUsesAcc (left, offset))
7603 MOVA (aopGet (left, offset, FALSE, FALSE));
7604 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7608 MOVA (aopGet (right, offset, FALSE, FALSE));
7609 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7612 emitcode ("jnz", "%05d$", tlbl->key + 100);
7622 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7626 for (; (size--); offset++)
7629 // result = left ^ right
7630 if (AOP_TYPE (right) == AOP_LIT)
7632 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7636 aopGet (left, offset, FALSE, FALSE),
7641 // faster than result <- left, xrl result,right
7642 // and better if result is SFR
7643 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7644 && AOP_TYPE(left)==AOP_ACC)
7647 emitcode("mov", "a,b");
7648 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7650 else if (AOP_TYPE(left)==AOP_ACC)
7654 bool pushedB = pushB ();
7655 emitcode("mov", "b,a");
7656 MOVA (aopGet (right, offset, FALSE, FALSE));
7657 emitcode("xrl", "a,b");
7662 MOVA (aopGet (right, offset, FALSE, FALSE));
7663 emitcode("xrl", "a,b");
7666 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7668 MOVB (aopGet (left, offset, FALSE, FALSE));
7669 MOVA (aopGet (right, offset, FALSE, FALSE));
7670 emitcode ("xrl", "a,b");
7672 else if (aopGetUsesAcc (left, offset))
7674 MOVA (aopGet (left, offset, FALSE, FALSE));
7675 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7679 MOVA (aopGet (right, offset, FALSE, FALSE));
7680 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7682 aopPut (result, "a", offset);
7688 freeAsmop (result, NULL, ic, TRUE);
7689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7690 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7693 /*-----------------------------------------------------------------*/
7694 /* genInline - write the inline code out */
7695 /*-----------------------------------------------------------------*/
7697 genInline (iCode * ic)
7699 char *buffer, *bp, *bp1;
7700 bool inComment = FALSE;
7702 D (emitcode (";", "genInline"));
7704 _G.inLine += (!options.asmpeep);
7706 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7708 /* emit each line as a code */
7726 /* Add \n for labels, not dirs such as c:\mydir */
7727 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7745 _G.inLine -= (!options.asmpeep);
7748 /*-----------------------------------------------------------------*/
7749 /* genRRC - rotate right with carry */
7750 /*-----------------------------------------------------------------*/
7754 operand *left, *result;
7758 D (emitcode (";", "genRRC"));
7760 /* rotate right with carry */
7761 left = IC_LEFT (ic);
7762 result = IC_RESULT (ic);
7763 aopOp (left, ic, FALSE);
7764 aopOp (result, ic, FALSE);
7766 /* move it to the result */
7767 size = AOP_SIZE (result);
7769 if (size == 1) { /* special case for 1 byte */
7770 l = aopGet (left, offset, FALSE, FALSE);
7772 emitcode ("rr", "a");
7775 /* no need to clear carry, bit7 will be written later */
7778 l = aopGet (left, offset, FALSE, FALSE);
7780 emitcode ("rrc", "a");
7781 if (AOP_SIZE (result) > 1)
7782 aopPut (result, "a", offset--);
7784 /* now we need to put the carry into the
7785 highest order byte of the result */
7786 if (AOP_SIZE (result) > 1)
7788 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7791 emitcode ("mov", "acc.7,c");
7793 aopPut (result, "a", AOP_SIZE (result) - 1);
7794 freeAsmop (result, NULL, ic, TRUE);
7795 freeAsmop (left, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genRLC - generate code for rotate left with carry */
7800 /*-----------------------------------------------------------------*/
7804 operand *left, *result;
7808 D (emitcode (";", "genRLC"));
7810 /* rotate right with carry */
7811 left = IC_LEFT (ic);
7812 result = IC_RESULT (ic);
7813 aopOp (left, ic, FALSE);
7814 aopOp (result, ic, FALSE);
7816 /* move it to the result */
7817 size = AOP_SIZE (result);
7821 l = aopGet (left, offset, FALSE, FALSE);
7823 if (size == 0) { /* special case for 1 byte */
7827 emitcode("rlc","a"); /* bit0 will be written later */
7828 if (AOP_SIZE (result) > 1)
7830 aopPut (result, "a", offset++);
7835 l = aopGet (left, offset, FALSE, FALSE);
7837 emitcode ("rlc", "a");
7838 if (AOP_SIZE (result) > 1)
7839 aopPut (result, "a", offset++);
7842 /* now we need to put the carry into the
7843 highest order byte of the result */
7844 if (AOP_SIZE (result) > 1)
7846 l = aopGet (result, 0, FALSE, FALSE);
7849 emitcode ("mov", "acc.0,c");
7851 aopPut (result, "a", 0);
7852 freeAsmop (result, NULL, ic, TRUE);
7853 freeAsmop (left, NULL, ic, TRUE);
7856 /*-----------------------------------------------------------------*/
7857 /* genGetHbit - generates code get highest order bit */
7858 /*-----------------------------------------------------------------*/
7860 genGetHbit (iCode * ic)
7862 operand *left, *result;
7864 D (emitcode (";", "genGetHbit"));
7866 left = IC_LEFT (ic);
7867 result = IC_RESULT (ic);
7868 aopOp (left, ic, FALSE);
7869 aopOp (result, ic, FALSE);
7871 /* get the highest order byte into a */
7872 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7873 if (AOP_TYPE (result) == AOP_CRY)
7875 emitcode ("rlc", "a");
7880 emitcode ("rl", "a");
7881 emitcode ("anl", "a,#0x01");
7885 freeAsmop (result, NULL, ic, TRUE);
7886 freeAsmop (left, NULL, ic, TRUE);
7889 /*-----------------------------------------------------------------*/
7890 /* genGetAbit - generates code get a single bit */
7891 /*-----------------------------------------------------------------*/
7893 genGetAbit (iCode * ic)
7895 operand *left, *right, *result;
7898 D (emitcode (";", "genGetAbit"));
7900 left = IC_LEFT (ic);
7901 right = IC_RIGHT (ic);
7902 result = IC_RESULT (ic);
7903 aopOp (left, ic, FALSE);
7904 aopOp (right, ic, FALSE);
7905 aopOp (result, ic, FALSE);
7907 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7909 /* get the needed byte into a */
7910 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7912 if (AOP_TYPE (result) == AOP_CRY)
7915 emitcode ("rlc", "a");
7916 else if ((shCount) == 0)
7917 emitcode ("rrc", "a");
7919 emitcode ("mov", "c,acc[%d]", shCount);
7927 emitcode ("rr", "a");
7930 emitcode ("rr", "a");
7933 emitcode ("anl", "a,#0x01");
7937 emitcode ("mov", "c,acc[%d]", shCount);
7938 emitcode ("clr", "a");
7939 emitcode ("rlc", "a");
7942 emitcode ("swap", "a");
7943 emitcode ("anl", "a,#0x01");
7946 emitcode ("rl", "a");
7949 emitcode ("rl", "a");
7950 emitcode ("anl", "a,#0x01");
7956 freeAsmop (result, NULL, ic, TRUE);
7957 freeAsmop (right, NULL, ic, TRUE);
7958 freeAsmop (left, NULL, ic, TRUE);
7961 /*-----------------------------------------------------------------*/
7962 /* genGetByte - generates code get a single byte */
7963 /*-----------------------------------------------------------------*/
7965 genGetByte (iCode * ic)
7967 operand *left, *right, *result;
7970 D (emitcode (";", "genGetByte"));
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 freeAsmop (result, NULL, ic, TRUE);
7985 freeAsmop (right, NULL, ic, TRUE);
7986 freeAsmop (left, NULL, ic, TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genGetWord - generates code get two bytes */
7991 /*-----------------------------------------------------------------*/
7993 genGetWord (iCode * ic)
7995 operand *left, *right, *result;
7998 D (emitcode (";", "genGetWord"));
8000 left = IC_LEFT (ic);
8001 right = IC_RIGHT (ic);
8002 result = IC_RESULT (ic);
8003 aopOp (left, ic, FALSE);
8004 aopOp (right, ic, FALSE);
8005 aopOp (result, ic, FALSE);
8007 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
8009 aopGet (left, offset, FALSE, FALSE),
8012 aopGet (left, offset+1, FALSE, FALSE),
8015 freeAsmop (result, NULL, ic, TRUE);
8016 freeAsmop (right, NULL, ic, TRUE);
8017 freeAsmop (left, NULL, ic, TRUE);
8020 /*-----------------------------------------------------------------*/
8021 /* genSwap - generates code to swap nibbles or bytes */
8022 /*-----------------------------------------------------------------*/
8024 genSwap (iCode * ic)
8026 operand *left, *result;
8028 D(emitcode (";", "genSwap"));
8030 left = IC_LEFT (ic);
8031 result = IC_RESULT (ic);
8032 aopOp (left, ic, FALSE);
8033 aopOp (result, ic, FALSE);
8035 switch (AOP_SIZE (left))
8037 case 1: /* swap nibbles in byte */
8038 MOVA (aopGet (left, 0, FALSE, FALSE));
8039 emitcode ("swap", "a");
8040 aopPut (result, "a", 0);
8042 case 2: /* swap bytes in word */
8043 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8045 MOVA (aopGet (left, 0, FALSE, FALSE));
8046 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8047 aopPut (result, "a", 1);
8049 else if (operandsEqu (left, result))
8052 bool pushedB = FALSE, leftInB = FALSE;
8054 MOVA (aopGet (left, 0, FALSE, FALSE));
8055 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8058 emitcode ("mov", "b,a");
8062 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8063 aopPut (result, reg, 1);
8070 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8071 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8075 wassertl(FALSE, "unsupported SWAP operand size");
8078 freeAsmop (result, NULL, ic, TRUE);
8079 freeAsmop (left, NULL, ic, TRUE);
8082 /*-----------------------------------------------------------------*/
8083 /* AccRol - rotate left accumulator by known count */
8084 /*-----------------------------------------------------------------*/
8086 AccRol (int shCount)
8088 shCount &= 0x0007; // shCount : 0..7
8095 emitcode ("rl", "a");
8098 emitcode ("rl", "a");
8099 emitcode ("rl", "a");
8102 emitcode ("swap", "a");
8103 emitcode ("rr", "a");
8106 emitcode ("swap", "a");
8109 emitcode ("swap", "a");
8110 emitcode ("rl", "a");
8113 emitcode ("rr", "a");
8114 emitcode ("rr", "a");
8117 emitcode ("rr", "a");
8122 /*-----------------------------------------------------------------*/
8123 /* AccLsh - left shift accumulator by known count */
8124 /*-----------------------------------------------------------------*/
8126 AccLsh (int shCount)
8131 emitcode ("add", "a,acc");
8132 else if (shCount == 2)
8134 emitcode ("add", "a,acc");
8135 emitcode ("add", "a,acc");
8139 /* rotate left accumulator */
8141 /* and kill the lower order bits */
8142 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8147 /*-----------------------------------------------------------------*/
8148 /* AccRsh - right shift accumulator by known count */
8149 /*-----------------------------------------------------------------*/
8151 AccRsh (int shCount)
8158 emitcode ("rrc", "a");
8162 /* rotate right accumulator */
8163 AccRol (8 - shCount);
8164 /* and kill the higher order bits */
8165 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8170 /*-----------------------------------------------------------------*/
8171 /* AccSRsh - signed right shift accumulator by known count */
8172 /*-----------------------------------------------------------------*/
8174 AccSRsh (int shCount)
8181 emitcode ("mov", "c,acc.7");
8182 emitcode ("rrc", "a");
8184 else if (shCount == 2)
8186 emitcode ("mov", "c,acc.7");
8187 emitcode ("rrc", "a");
8188 emitcode ("mov", "c,acc.7");
8189 emitcode ("rrc", "a");
8193 tlbl = newiTempLabel (NULL);
8194 /* rotate right accumulator */
8195 AccRol (8 - shCount);
8196 /* and kill the higher order bits */
8197 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8198 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8199 emitcode ("orl", "a,#0x%02x",
8200 (unsigned char) ~SRMask[shCount]);
8206 /*-----------------------------------------------------------------*/
8207 /* shiftR1Left2Result - shift right one byte from left to result */
8208 /*-----------------------------------------------------------------*/
8210 shiftR1Left2Result (operand * left, int offl,
8211 operand * result, int offr,
8212 int shCount, int sign)
8214 MOVA (aopGet (left, offl, FALSE, FALSE));
8215 /* shift right accumulator */
8220 aopPut (result, "a", offr);
8223 /*-----------------------------------------------------------------*/
8224 /* shiftL1Left2Result - shift left one byte from left to result */
8225 /*-----------------------------------------------------------------*/
8227 shiftL1Left2Result (operand * left, int offl,
8228 operand * result, int offr, int shCount)
8231 l = aopGet (left, offl, FALSE, FALSE);
8233 /* shift left accumulator */
8235 aopPut (result, "a", offr);
8238 /*-----------------------------------------------------------------*/
8239 /* movLeft2Result - move byte from left to result */
8240 /*-----------------------------------------------------------------*/
8242 movLeft2Result (operand * left, int offl,
8243 operand * result, int offr, int sign)
8246 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8248 l = aopGet (left, offl, FALSE, FALSE);
8250 if (*l == '@' && (IS_AOP_PREG (result)))
8252 emitcode ("mov", "a,%s", l);
8253 aopPut (result, "a", offr);
8259 aopPut (result, l, offr);
8263 /* MSB sign in acc.7 ! */
8264 if (getDataSize (left) == offl + 1)
8267 aopPut (result, "a", offr);
8274 /*-----------------------------------------------------------------*/
8275 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8276 /*-----------------------------------------------------------------*/
8280 emitcode ("rrc", "a");
8281 emitcode ("xch", "a,%s", x);
8282 emitcode ("rrc", "a");
8283 emitcode ("xch", "a,%s", x);
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8288 /*-----------------------------------------------------------------*/
8292 emitcode ("xch", "a,%s", x);
8293 emitcode ("rlc", "a");
8294 emitcode ("xch", "a,%s", x);
8295 emitcode ("rlc", "a");
8298 /*-----------------------------------------------------------------*/
8299 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8300 /*-----------------------------------------------------------------*/
8304 emitcode ("xch", "a,%s", x);
8305 emitcode ("add", "a,acc");
8306 emitcode ("xch", "a,%s", x);
8307 emitcode ("rlc", "a");
8310 /*-----------------------------------------------------------------*/
8311 /* AccAXLsh - left shift a:x by known count (0..7) */
8312 /*-----------------------------------------------------------------*/
8314 AccAXLsh (char *x, int shCount)
8329 case 5: // AAAAABBB:CCCCCDDD
8331 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8333 emitcode ("anl", "a,#0x%02x",
8334 SLMask[shCount]); // BBB00000:CCCCCDDD
8336 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8338 AccRol (shCount); // DDDCCCCC:BBB00000
8340 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8342 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8344 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8346 emitcode ("anl", "a,#0x%02x",
8347 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8349 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8351 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8354 case 6: // AAAAAABB:CCCCCCDD
8355 emitcode ("anl", "a,#0x%02x",
8356 SRMask[shCount]); // 000000BB:CCCCCCDD
8357 emitcode ("mov", "c,acc.0"); // c = B
8358 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8360 AccAXRrl1 (x); // BCCCCCCD:D000000B
8361 AccAXRrl1 (x); // BBCCCCCC:DD000000
8363 emitcode("rrc","a");
8364 emitcode("xch","a,%s", x);
8365 emitcode("rrc","a");
8366 emitcode("mov","c,acc.0"); //<< get correct bit
8367 emitcode("xch","a,%s", x);
8369 emitcode("rrc","a");
8370 emitcode("xch","a,%s", x);
8371 emitcode("rrc","a");
8372 emitcode("xch","a,%s", x);
8375 case 7: // a:x <<= 7
8377 emitcode ("anl", "a,#0x%02x",
8378 SRMask[shCount]); // 0000000B:CCCCCCCD
8380 emitcode ("mov", "c,acc.0"); // c = B
8382 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8384 AccAXRrl1 (x); // BCCCCCCC:D0000000
8392 /*-----------------------------------------------------------------*/
8393 /* AccAXRsh - right shift a:x known count (0..7) */
8394 /*-----------------------------------------------------------------*/
8396 AccAXRsh (char *x, int shCount)
8404 AccAXRrl1 (x); // 0->a:x
8409 AccAXRrl1 (x); // 0->a:x
8412 AccAXRrl1 (x); // 0->a:x
8417 case 5: // AAAAABBB:CCCCCDDD = a:x
8419 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8421 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8423 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8425 emitcode ("anl", "a,#0x%02x",
8426 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8428 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8430 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8432 emitcode ("anl", "a,#0x%02x",
8433 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8435 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8437 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8439 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8442 case 6: // AABBBBBB:CCDDDDDD
8444 emitcode ("mov", "c,acc.7");
8445 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8447 emitcode ("mov", "c,acc.7");
8448 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8450 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8452 emitcode ("anl", "a,#0x%02x",
8453 SRMask[shCount]); // 000000AA:BBBBBBCC
8456 case 7: // ABBBBBBB:CDDDDDDD
8458 emitcode ("mov", "c,acc.7"); // c = A
8460 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8462 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8464 emitcode ("anl", "a,#0x%02x",
8465 SRMask[shCount]); // 0000000A:BBBBBBBC
8473 /*-----------------------------------------------------------------*/
8474 /* AccAXRshS - right shift signed a:x known count (0..7) */
8475 /*-----------------------------------------------------------------*/
8477 AccAXRshS (char *x, int shCount)
8485 emitcode ("mov", "c,acc.7");
8486 AccAXRrl1 (x); // s->a:x
8490 emitcode ("mov", "c,acc.7");
8491 AccAXRrl1 (x); // s->a:x
8493 emitcode ("mov", "c,acc.7");
8494 AccAXRrl1 (x); // s->a:x
8499 case 5: // AAAAABBB:CCCCCDDD = a:x
8501 tlbl = newiTempLabel (NULL);
8502 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8504 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8506 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8508 emitcode ("anl", "a,#0x%02x",
8509 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8511 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8513 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8515 emitcode ("anl", "a,#0x%02x",
8516 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8518 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8520 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8522 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8524 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8525 emitcode ("orl", "a,#0x%02x",
8526 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8529 break; // SSSSAAAA:BBBCCCCC
8531 case 6: // AABBBBBB:CCDDDDDD
8533 tlbl = newiTempLabel (NULL);
8534 emitcode ("mov", "c,acc.7");
8535 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8537 emitcode ("mov", "c,acc.7");
8538 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8540 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8542 emitcode ("anl", "a,#0x%02x",
8543 SRMask[shCount]); // 000000AA:BBBBBBCC
8545 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8546 emitcode ("orl", "a,#0x%02x",
8547 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8551 case 7: // ABBBBBBB:CDDDDDDD
8553 tlbl = newiTempLabel (NULL);
8554 emitcode ("mov", "c,acc.7"); // c = A
8556 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8558 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8560 emitcode ("anl", "a,#0x%02x",
8561 SRMask[shCount]); // 0000000A:BBBBBBBC
8563 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8564 emitcode ("orl", "a,#0x%02x",
8565 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8574 /*-----------------------------------------------------------------*/
8575 /* shiftL2Left2Result - shift left two bytes from left to result */
8576 /*-----------------------------------------------------------------*/
8578 shiftL2Left2Result (operand * left, int offl,
8579 operand * result, int offr, int shCount)
8582 bool pushedB = FALSE;
8585 if (sameRegs (AOP (result), AOP (left)) &&
8586 ((offl + MSB16) == offr))
8588 /* don't crash result[offr] */
8589 MOVA (aopGet (left, offl, FALSE, FALSE));
8590 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8591 usedB = !strncmp(x, "b", 1);
8593 else if (aopGetUsesAcc (result, offr))
8595 movLeft2Result (left, offl, result, offr, 0);
8598 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8599 MOVA (aopGet (result, offr, FALSE, FALSE));
8600 emitcode ("xch", "a,b");
8605 movLeft2Result (left, offl, result, offr, 0);
8606 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8607 x = aopGet (result, offr, FALSE, FALSE);
8609 /* ax << shCount (x = lsb(result)) */
8610 AccAXLsh (x, shCount);
8613 emitcode ("xch", "a,b");
8614 aopPut (result, "a", offr);
8615 aopPut (result, "b", offr + MSB16);
8620 aopPut (result, "a", offr + MSB16);
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR2Left2Result - shift right two bytes from left to result */
8627 /*-----------------------------------------------------------------*/
8629 shiftR2Left2Result (operand * left, int offl,
8630 operand * result, int offr,
8631 int shCount, int sign)
8634 bool pushedB = FALSE;
8637 if (sameRegs (AOP (result), AOP (left)) &&
8638 ((offl + MSB16) == offr))
8640 /* don't crash result[offr] */
8641 MOVA (aopGet (left, offl, FALSE, FALSE));
8642 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8643 usedB = !strncmp(x, "b", 1);
8645 else if (aopGetUsesAcc (result, offr))
8647 movLeft2Result (left, offl, result, offr, 0);
8650 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8651 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8656 movLeft2Result (left, offl, result, offr, 0);
8657 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8658 x = aopGet (result, offr, FALSE, FALSE);
8660 /* a:x >> shCount (x = lsb(result)) */
8662 AccAXRshS (x, shCount);
8664 AccAXRsh (x, shCount);
8667 emitcode ("xch", "a,b");
8668 aopPut (result, "a", offr);
8669 emitcode ("xch", "a,b");
8672 if (getDataSize (result) > 1)
8673 aopPut (result, "a", offr + MSB16);
8676 /*-----------------------------------------------------------------*/
8677 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8678 /*-----------------------------------------------------------------*/
8680 shiftLLeftOrResult (operand * left, int offl,
8681 operand * result, int offr, int shCount)
8683 MOVA (aopGet (left, offl, FALSE, FALSE));
8684 /* shift left accumulator */
8686 /* or with result */
8687 if (aopGetUsesAcc (result, offr))
8689 emitcode ("xch", "a,b");
8690 MOVA (aopGet (result, offr, FALSE, FALSE));
8691 emitcode ("orl", "a,b");
8695 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8697 /* back to result */
8698 aopPut (result, "a", offr);
8701 /*-----------------------------------------------------------------*/
8702 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8703 /*-----------------------------------------------------------------*/
8705 shiftRLeftOrResult (operand * left, int offl,
8706 operand * result, int offr, int shCount)
8708 MOVA (aopGet (left, offl, FALSE, FALSE));
8709 /* shift right accumulator */
8711 /* or with result */
8712 if (aopGetUsesAcc(result, offr))
8714 emitcode ("xch", "a,b");
8715 MOVA (aopGet (result, offr, FALSE, FALSE));
8716 emitcode ("orl", "a,b");
8720 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8722 /* back to result */
8723 aopPut (result, "a", offr);
8726 /*-----------------------------------------------------------------*/
8727 /* genlshOne - left shift a one byte quantity by known count */
8728 /*-----------------------------------------------------------------*/
8730 genlshOne (operand * result, operand * left, int shCount)
8732 D (emitcode (";", "genlshOne"));
8734 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8737 /*-----------------------------------------------------------------*/
8738 /* genlshTwo - left shift two bytes by known amount != 0 */
8739 /*-----------------------------------------------------------------*/
8741 genlshTwo (operand * result, operand * left, int shCount)
8745 D (emitcode (";", "genlshTwo"));
8747 size = getDataSize (result);
8749 /* if shCount >= 8 */
8757 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8759 movLeft2Result (left, LSB, result, MSB16, 0);
8761 aopPut (result, zero, LSB);
8764 /* 1 <= shCount <= 7 */
8768 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8770 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8774 /*-----------------------------------------------------------------*/
8775 /* shiftLLong - shift left one long from left to result */
8776 /* offl = LSB or MSB16 */
8777 /*-----------------------------------------------------------------*/
8779 shiftLLong (operand * left, operand * result, int offr)
8782 int size = AOP_SIZE (result);
8784 if (size >= LSB + offr)
8786 l = aopGet (left, LSB, FALSE, FALSE);
8788 emitcode ("add", "a,acc");
8789 if (sameRegs (AOP (left), AOP (result)) &&
8790 size >= MSB16 + offr && offr != LSB)
8791 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8793 aopPut (result, "a", LSB + offr);
8796 if (size >= MSB16 + offr)
8798 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8800 l = aopGet (left, MSB16, FALSE, FALSE);
8803 emitcode ("rlc", "a");
8804 if (sameRegs (AOP (left), AOP (result)) &&
8805 size >= MSB24 + offr && offr != LSB)
8806 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8808 aopPut (result, "a", MSB16 + offr);
8811 if (size >= MSB24 + offr)
8813 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8815 l = aopGet (left, MSB24, FALSE, FALSE);
8818 emitcode ("rlc", "a");
8819 if (sameRegs (AOP (left), AOP (result)) &&
8820 size >= MSB32 + offr && offr != LSB)
8821 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8823 aopPut (result, "a", MSB24 + offr);
8826 if (size > MSB32 + offr)
8828 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8830 l = aopGet (left, MSB32, FALSE, FALSE);
8833 emitcode ("rlc", "a");
8834 aopPut (result, "a", MSB32 + offr);
8837 aopPut (result, zero, LSB);
8840 /*-----------------------------------------------------------------*/
8841 /* genlshFour - shift four byte by a known amount != 0 */
8842 /*-----------------------------------------------------------------*/
8844 genlshFour (operand * result, operand * left, int shCount)
8848 D (emitcode (";", "genlshFour"));
8850 size = AOP_SIZE (result);
8852 /* if shifting more that 3 bytes */
8857 /* lowest order of left goes to the highest
8858 order of the destination */
8859 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8861 movLeft2Result (left, LSB, result, MSB32, 0);
8862 aopPut (result, zero, LSB);
8863 aopPut (result, zero, MSB16);
8864 aopPut (result, zero, MSB24);
8868 /* more than two bytes */
8869 else if (shCount >= 16)
8871 /* lower order two bytes goes to higher order two bytes */
8873 /* if some more remaining */
8875 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8878 movLeft2Result (left, MSB16, result, MSB32, 0);
8879 movLeft2Result (left, LSB, result, MSB24, 0);
8881 aopPut (result, zero, MSB16);
8882 aopPut (result, zero, LSB);
8886 /* if more than 1 byte */
8887 else if (shCount >= 8)
8889 /* lower order three bytes goes to higher order three bytes */
8894 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8896 movLeft2Result (left, LSB, result, MSB16, 0);
8902 movLeft2Result (left, MSB24, result, MSB32, 0);
8903 movLeft2Result (left, MSB16, result, MSB24, 0);
8904 movLeft2Result (left, LSB, result, MSB16, 0);
8905 aopPut (result, zero, LSB);
8907 else if (shCount == 1)
8908 shiftLLong (left, result, MSB16);
8911 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8912 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8913 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8914 aopPut (result, zero, LSB);
8919 /* 1 <= shCount <= 7 */
8920 else if (shCount <= 2)
8922 shiftLLong (left, result, LSB);
8924 shiftLLong (result, result, LSB);
8926 /* 3 <= shCount <= 7, optimize */
8929 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8930 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8931 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8935 /*-----------------------------------------------------------------*/
8936 /* genLeftShiftLiteral - left shifting by known count */
8937 /*-----------------------------------------------------------------*/
8939 genLeftShiftLiteral (operand * left,
8944 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8947 D (emitcode (";", "genLeftShiftLiteral"));
8949 freeAsmop (right, NULL, ic, TRUE);
8951 aopOp (left, ic, FALSE);
8952 aopOp (result, ic, FALSE);
8954 size = getSize (operandType (result));
8957 emitcode ("; shift left ", "result %d, left %d", size,
8961 /* I suppose that the left size >= result size */
8966 movLeft2Result (left, size, result, size, 0);
8969 else if (shCount >= (size * 8))
8973 aopPut (result, zero, size);
8981 genlshOne (result, left, shCount);
8985 genlshTwo (result, left, shCount);
8989 genlshFour (result, left, shCount);
8992 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8993 "*** ack! mystery literal shift!\n");
8997 freeAsmop (result, NULL, ic, TRUE);
8998 freeAsmop (left, NULL, ic, TRUE);
9001 /*-----------------------------------------------------------------*/
9002 /* genLeftShift - generates code for left shifting */
9003 /*-----------------------------------------------------------------*/
9005 genLeftShift (iCode * ic)
9007 operand *left, *right, *result;
9010 symbol *tlbl, *tlbl1;
9013 D (emitcode (";", "genLeftShift"));
9015 right = IC_RIGHT (ic);
9016 left = IC_LEFT (ic);
9017 result = IC_RESULT (ic);
9019 aopOp (right, ic, FALSE);
9021 /* if the shift count is known then do it
9022 as efficiently as possible */
9023 if (AOP_TYPE (right) == AOP_LIT)
9025 genLeftShiftLiteral (left, right, result, ic);
9029 /* shift count is unknown then we have to form
9030 a loop get the loop count in B : Note: we take
9031 only the lower order byte since shifting
9032 more that 32 bits make no sense anyway, ( the
9033 largest size of an object can be only 32 bits ) */
9036 MOVB (aopGet (right, 0, FALSE, FALSE));
9037 emitcode ("inc", "b");
9038 freeAsmop (right, NULL, ic, TRUE);
9039 aopOp (left, ic, FALSE);
9040 aopOp (result, ic, FALSE);
9042 /* now move the left to the result if they are not the same */
9043 if (!sameRegs (AOP (left), AOP (result)) &&
9044 AOP_SIZE (result) > 1)
9047 size = AOP_SIZE (result);
9051 l = aopGet (left, offset, FALSE, TRUE);
9052 if (*l == '@' && (IS_AOP_PREG (result)))
9055 emitcode ("mov", "a,%s", l);
9056 aopPut (result, "a", offset);
9059 aopPut (result, l, offset);
9064 tlbl = newiTempLabel (NULL);
9065 size = AOP_SIZE (result);
9067 tlbl1 = newiTempLabel (NULL);
9069 /* if it is only one byte then */
9072 symbol *tlbl1 = newiTempLabel (NULL);
9074 l = aopGet (left, 0, FALSE, FALSE);
9076 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9078 emitcode ("add", "a,acc");
9080 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9082 aopPut (result, "a", 0);
9086 reAdjustPreg (AOP (result));
9088 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9090 l = aopGet (result, offset, FALSE, FALSE);
9092 emitcode ("add", "a,acc");
9093 aopPut (result, "a", offset++);
9096 l = aopGet (result, offset, FALSE, FALSE);
9098 emitcode ("rlc", "a");
9099 aopPut (result, "a", offset++);
9101 reAdjustPreg (AOP (result));
9104 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9107 freeAsmop (result, NULL, ic, TRUE);
9108 freeAsmop (left, NULL, ic, TRUE);
9111 /*-----------------------------------------------------------------*/
9112 /* genrshOne - right shift a one byte quantity by known count */
9113 /*-----------------------------------------------------------------*/
9115 genrshOne (operand * result, operand * left,
9116 int shCount, int sign)
9118 D (emitcode (";", "genrshOne"));
9120 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9123 /*-----------------------------------------------------------------*/
9124 /* genrshTwo - right shift two bytes by known amount != 0 */
9125 /*-----------------------------------------------------------------*/
9127 genrshTwo (operand * result, operand * left,
9128 int shCount, int sign)
9130 D (emitcode (";", "genrshTwo"));
9132 /* if shCount >= 8 */
9137 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9139 movLeft2Result (left, MSB16, result, LSB, sign);
9140 addSign (result, MSB16, sign);
9143 /* 1 <= shCount <= 7 */
9145 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9148 /*-----------------------------------------------------------------*/
9149 /* shiftRLong - shift right one long from left to result */
9150 /* offl = LSB or MSB16 */
9151 /*-----------------------------------------------------------------*/
9153 shiftRLong (operand * left, int offl,
9154 operand * result, int sign)
9156 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9158 if (overlapping && offl>1)
9160 // we are in big trouble, but this shouldn't happen
9161 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9164 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9171 emitcode ("rlc", "a");
9172 emitcode ("subb", "a,acc");
9173 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9175 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9179 aopPut (result, "a", MSB32);
9180 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9185 if (aopPutUsesAcc (result, zero, MSB32))
9187 emitcode("xch", "a,b");
9188 aopPut (result, zero, MSB32);
9189 emitcode("xch", "a,b");
9193 aopPut (result, zero, MSB32);
9200 emitcode ("clr", "c");
9204 emitcode ("mov", "c,acc.7");
9207 emitcode ("rrc", "a");
9209 if (overlapping && offl==MSB16 &&
9210 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9212 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9216 aopPut (result, "a", MSB32 - offl);
9217 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9220 emitcode ("rrc", "a");
9221 if (overlapping && offl==MSB16 &&
9222 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9224 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9228 aopPut (result, "a", MSB24 - offl);
9229 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9232 emitcode ("rrc", "a");
9235 aopPut (result, "a", MSB16 - offl);
9240 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9242 xch_a_aopGet (left, LSB, FALSE, FALSE);
9246 aopPut (result, "a", MSB16 - offl);
9247 MOVA (aopGet (left, LSB, FALSE, FALSE));
9249 emitcode ("rrc", "a");
9250 aopPut (result, "a", LSB);
9254 /*-----------------------------------------------------------------*/
9255 /* genrshFour - shift four byte by a known amount != 0 */
9256 /*-----------------------------------------------------------------*/
9258 genrshFour (operand * result, operand * left,
9259 int shCount, int sign)
9261 D (emitcode (";", "genrshFour"));
9263 /* if shifting more that 3 bytes */
9268 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9270 movLeft2Result (left, MSB32, result, LSB, sign);
9271 addSign (result, MSB16, sign);
9273 else if (shCount >= 16)
9277 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9280 movLeft2Result (left, MSB24, result, LSB, 0);
9281 movLeft2Result (left, MSB32, result, MSB16, sign);
9283 addSign (result, MSB24, sign);
9285 else if (shCount >= 8)
9290 shiftRLong (left, MSB16, result, sign);
9292 else if (shCount == 0)
9294 movLeft2Result (left, MSB16, result, LSB, 0);
9295 movLeft2Result (left, MSB24, result, MSB16, 0);
9296 movLeft2Result (left, MSB32, result, MSB24, sign);
9297 addSign (result, MSB32, sign);
9301 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9302 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9303 /* the last shift is signed */
9304 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9305 addSign (result, MSB32, sign);
9310 /* 1 <= shCount <= 7 */
9313 shiftRLong (left, LSB, result, sign);
9315 shiftRLong (result, LSB, result, sign);
9319 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9320 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9321 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9326 /*-----------------------------------------------------------------*/
9327 /* genRightShiftLiteral - right shifting by known count */
9328 /*-----------------------------------------------------------------*/
9330 genRightShiftLiteral (operand * left,
9336 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9339 D (emitcode (";", "genRightShiftLiteral"));
9341 freeAsmop (right, NULL, ic, TRUE);
9343 aopOp (left, ic, FALSE);
9344 aopOp (result, ic, FALSE);
9347 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9351 size = getDataSize (left);
9352 /* test the LEFT size !!! */
9354 /* I suppose that the left size >= result size */
9357 size = getDataSize (result);
9359 movLeft2Result (left, size, result, size, 0);
9362 else if (shCount >= (size * 8))
9366 /* get sign in acc.7 */
9367 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9369 addSign (result, LSB, sign);
9376 genrshOne (result, left, shCount, sign);
9380 genrshTwo (result, left, shCount, sign);
9384 genrshFour (result, left, shCount, sign);
9390 freeAsmop (result, NULL, ic, TRUE);
9391 freeAsmop (left, NULL, ic, TRUE);
9394 /*-----------------------------------------------------------------*/
9395 /* genSignedRightShift - right shift of signed number */
9396 /*-----------------------------------------------------------------*/
9398 genSignedRightShift (iCode * ic)
9400 operand *right, *left, *result;
9403 symbol *tlbl, *tlbl1;
9406 D (emitcode (";", "genSignedRightShift"));
9408 /* we do it the hard way put the shift count in b
9409 and loop thru preserving the sign */
9411 right = IC_RIGHT (ic);
9412 left = IC_LEFT (ic);
9413 result = IC_RESULT (ic);
9415 aopOp (right, ic, FALSE);
9418 if (AOP_TYPE (right) == AOP_LIT)
9420 genRightShiftLiteral (left, right, result, ic, 1);
9423 /* shift count is unknown then we have to form
9424 a loop get the loop count in B : Note: we take
9425 only the lower order byte since shifting
9426 more that 32 bits make no sense anyway, ( the
9427 largest size of an object can be only 32 bits ) */
9430 MOVB (aopGet (right, 0, FALSE, FALSE));
9431 emitcode ("inc", "b");
9432 freeAsmop (right, NULL, ic, TRUE);
9433 aopOp (left, ic, FALSE);
9434 aopOp (result, ic, FALSE);
9436 /* now move the left to the result if they are not the
9438 if (!sameRegs (AOP (left), AOP (result)) &&
9439 AOP_SIZE (result) > 1)
9442 size = AOP_SIZE (result);
9446 l = aopGet (left, offset, FALSE, TRUE);
9447 if (*l == '@' && IS_AOP_PREG (result))
9450 emitcode ("mov", "a,%s", l);
9451 aopPut (result, "a", offset);
9454 aopPut (result, l, offset);
9459 /* mov the highest order bit to OVR */
9460 tlbl = newiTempLabel (NULL);
9461 tlbl1 = newiTempLabel (NULL);
9463 size = AOP_SIZE (result);
9465 MOVA (aopGet (left, offset, FALSE, FALSE));
9466 emitcode ("rlc", "a");
9467 emitcode ("mov", "ov,c");
9468 /* if it is only one byte then */
9471 l = aopGet (left, 0, FALSE, FALSE);
9473 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9475 emitcode ("mov", "c,ov");
9476 emitcode ("rrc", "a");
9478 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9480 aopPut (result, "a", 0);
9484 reAdjustPreg (AOP (result));
9485 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9487 emitcode ("mov", "c,ov");
9490 l = aopGet (result, offset, FALSE, FALSE);
9492 emitcode ("rrc", "a");
9493 aopPut (result, "a", offset--);
9495 reAdjustPreg (AOP (result));
9497 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9501 freeAsmop (result, NULL, ic, TRUE);
9502 freeAsmop (left, NULL, ic, TRUE);
9505 /*-----------------------------------------------------------------*/
9506 /* genRightShift - generate code for right shifting */
9507 /*-----------------------------------------------------------------*/
9509 genRightShift (iCode * ic)
9511 operand *right, *left, *result;
9515 symbol *tlbl, *tlbl1;
9518 D (emitcode (";", "genRightShift"));
9520 /* if signed then we do it the hard way preserve the
9521 sign bit moving it inwards */
9522 letype = getSpec (operandType (IC_LEFT (ic)));
9524 if (!SPEC_USIGN (letype))
9526 genSignedRightShift (ic);
9530 /* signed & unsigned types are treated the same : i.e. the
9531 signed is NOT propagated inwards : quoting from the
9532 ANSI - standard : "for E1 >> E2, is equivalent to division
9533 by 2**E2 if unsigned or if it has a non-negative value,
9534 otherwise the result is implementation defined ", MY definition
9535 is that the sign does not get propagated */
9537 right = IC_RIGHT (ic);
9538 left = IC_LEFT (ic);
9539 result = IC_RESULT (ic);
9541 aopOp (right, ic, FALSE);
9543 /* if the shift count is known then do it
9544 as efficiently as possible */
9545 if (AOP_TYPE (right) == AOP_LIT)
9547 genRightShiftLiteral (left, right, result, ic, 0);
9551 /* shift count is unknown then we have to form
9552 a loop get the loop count in B : Note: we take
9553 only the lower order byte since shifting
9554 more that 32 bits make no sense anyway, ( the
9555 largest size of an object can be only 32 bits ) */
9558 MOVB (aopGet (right, 0, FALSE, FALSE));
9559 emitcode ("inc", "b");
9560 freeAsmop (right, NULL, ic, TRUE);
9561 aopOp (left, ic, FALSE);
9562 aopOp (result, ic, FALSE);
9564 /* now move the left to the result if they are not the
9566 if (!sameRegs (AOP (left), AOP (result)) &&
9567 AOP_SIZE (result) > 1)
9569 size = AOP_SIZE (result);
9573 l = aopGet (left, offset, FALSE, TRUE);
9574 if (*l == '@' && IS_AOP_PREG (result))
9577 emitcode ("mov", "a,%s", l);
9578 aopPut (result, "a", offset);
9581 aopPut (result, l, offset);
9586 tlbl = newiTempLabel (NULL);
9587 tlbl1 = newiTempLabel (NULL);
9588 size = AOP_SIZE (result);
9591 /* if it is only one byte then */
9594 l = aopGet (left, 0, FALSE, FALSE);
9596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9599 emitcode ("rrc", "a");
9601 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9603 aopPut (result, "a", 0);
9607 reAdjustPreg (AOP (result));
9608 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9613 l = aopGet (result, offset, FALSE, FALSE);
9615 emitcode ("rrc", "a");
9616 aopPut (result, "a", offset--);
9618 reAdjustPreg (AOP (result));
9621 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9625 freeAsmop (result, NULL, ic, TRUE);
9626 freeAsmop (left, NULL, ic, TRUE);
9629 /*-----------------------------------------------------------------*/
9630 /* emitPtrByteGet - emits code to get a byte into A through a */
9631 /* pointer register (R0, R1, or DPTR). The */
9632 /* original value of A can be preserved in B. */
9633 /*-----------------------------------------------------------------*/
9635 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9642 emitcode ("mov", "b,a");
9643 emitcode ("mov", "a,@%s", rname);
9648 emitcode ("mov", "b,a");
9649 emitcode ("movx", "a,@%s", rname);
9654 emitcode ("mov", "b,a");
9655 emitcode ("movx", "a,@dptr");
9660 emitcode ("mov", "b,a");
9661 emitcode ("clr", "a");
9662 emitcode ("movc", "a,@a+dptr");
9668 emitcode ("push", "b");
9669 emitcode ("push", "acc");
9671 emitcode ("lcall", "__gptrget");
9673 emitcode ("pop", "b");
9678 /*-----------------------------------------------------------------*/
9679 /* emitPtrByteSet - emits code to set a byte from src through a */
9680 /* pointer register (R0, R1, or DPTR). */
9681 /*-----------------------------------------------------------------*/
9683 emitPtrByteSet (char *rname, int p_type, char *src)
9692 emitcode ("mov", "@%s,a", rname);
9695 emitcode ("mov", "@%s,%s", rname, src);
9700 emitcode ("movx", "@%s,a", rname);
9705 emitcode ("movx", "@dptr,a");
9710 emitcode ("lcall", "__gptrput");
9715 /*-----------------------------------------------------------------*/
9716 /* genUnpackBits - generates code for unpacking bits */
9717 /*-----------------------------------------------------------------*/
9719 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9721 int offset = 0; /* result byte offset */
9722 int rsize; /* result size */
9723 int rlen = 0; /* remaining bitfield length */
9724 sym_link *etype; /* bitfield type information */
9725 int blen; /* bitfield length */
9726 int bstr; /* bitfield starting bit within byte */
9729 D(emitcode (";", "genUnpackBits"));
9731 etype = getSpec (operandType (result));
9732 rsize = getSize (operandType (result));
9733 blen = SPEC_BLEN (etype);
9734 bstr = SPEC_BSTR (etype);
9736 if (ifx && blen <= 8)
9738 emitPtrByteGet (rname, ptype, FALSE);
9741 SNPRINTF (buffer, sizeof(buffer),
9743 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9748 emitcode ("anl", "a,#0x%02x",
9749 (((unsigned char) -1) >> (8 - blen)) << bstr);
9750 genIfxJump (ifx, "a", NULL, NULL, NULL);
9756 /* If the bitfield length is less than a byte */
9759 emitPtrByteGet (rname, ptype, FALSE);
9761 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9762 if (!SPEC_USIGN (etype))
9764 /* signed bitfield */
9765 symbol *tlbl = newiTempLabel (NULL);
9767 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9768 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9771 aopPut (result, "a", offset++);
9775 /* Bit field did not fit in a byte. Copy all
9776 but the partial byte at the end. */
9777 for (rlen=blen;rlen>=8;rlen-=8)
9779 emitPtrByteGet (rname, ptype, FALSE);
9780 aopPut (result, "a", offset++);
9782 emitcode ("inc", "%s", rname);
9785 /* Handle the partial byte at the end */
9788 emitPtrByteGet (rname, ptype, FALSE);
9789 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9790 if (!SPEC_USIGN (etype))
9792 /* signed bitfield */
9793 symbol *tlbl = newiTempLabel (NULL);
9795 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9796 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9799 aopPut (result, "a", offset++);
9807 if (SPEC_USIGN (etype))
9811 /* signed bitfield: sign extension with 0x00 or 0xff */
9812 emitcode ("rlc", "a");
9813 emitcode ("subb", "a,acc");
9819 aopPut (result, source, offset++);
9824 /*-----------------------------------------------------------------*/
9825 /* genDataPointerGet - generates code when ptr offset is known */
9826 /*-----------------------------------------------------------------*/
9828 genDataPointerGet (operand * left,
9834 int size, offset = 0;
9836 D (emitcode (";", "genDataPointerGet"));
9838 aopOp (result, ic, TRUE);
9840 /* get the string representation of the name */
9841 l = aopGet (left, 0, FALSE, TRUE);
9843 size = AOP_SIZE (result);
9848 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9852 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9854 aopPut (result, buffer, offset++);
9857 freeAsmop (result, NULL, ic, TRUE);
9858 freeAsmop (left, NULL, ic, TRUE);
9861 /*-----------------------------------------------------------------*/
9862 /* genNearPointerGet - emitcode for near pointer fetch */
9863 /*-----------------------------------------------------------------*/
9865 genNearPointerGet (operand * left,
9874 sym_link *rtype, *retype;
9875 sym_link *ltype = operandType (left);
9878 D (emitcode (";", "genNearPointerGet"));
9880 rtype = operandType (result);
9881 retype = getSpec (rtype);
9883 aopOp (left, ic, FALSE);
9885 /* if left is rematerialisable and
9886 result is not bitfield variable type and
9887 the left is pointer to data space i.e
9888 lower 128 bytes of space */
9889 if (AOP_TYPE (left) == AOP_IMMD &&
9890 !IS_BITFIELD (retype) &&
9891 DCL_TYPE (ltype) == POINTER)
9893 genDataPointerGet (left, result, ic);
9897 /* if the value is already in a pointer register
9898 then don't need anything more */
9899 if (!AOP_INPREG (AOP (left)))
9901 if (IS_AOP_PREG (left))
9903 // Aha, it is a pointer, just in disguise.
9904 rname = aopGet (left, 0, FALSE, FALSE);
9907 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9908 __FILE__, __LINE__);
9913 emitcode ("mov", "a%s,%s", rname + 1, rname);
9914 rname++; // skip the '@'.
9919 /* otherwise get a free pointer register */
9921 preg = getFreePtr (ic, &aop, FALSE);
9922 emitcode ("mov", "%s,%s",
9924 aopGet (left, 0, FALSE, TRUE));
9929 rname = aopGet (left, 0, FALSE, FALSE);
9931 //aopOp (result, ic, FALSE);
9932 aopOp (result, ic, result?TRUE:FALSE);
9934 /* if bitfield then unpack the bits */
9935 if (IS_BITFIELD (retype))
9936 genUnpackBits (result, rname, POINTER, ifx);
9939 /* we have can just get the values */
9940 int size = AOP_SIZE (result);
9945 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9948 emitcode ("mov", "a,@%s", rname);
9950 aopPut (result, "a", offset);
9954 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9955 aopPut (result, buffer, offset);
9959 emitcode ("inc", "%s", rname);
9963 /* now some housekeeping stuff */
9964 if (aop) /* we had to allocate for this iCode */
9966 if (pi) { /* post increment present */
9967 aopPut (left, rname, 0);
9969 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9973 /* we did not allocate which means left
9974 already in a pointer register, then
9975 if size > 0 && this could be used again
9976 we have to point it back to where it
9978 if ((AOP_SIZE (result) > 1 &&
9979 !OP_SYMBOL (left)->remat &&
9980 (OP_SYMBOL (left)->liveTo > ic->seq ||
9984 int size = AOP_SIZE (result) - 1;
9986 emitcode ("dec", "%s", rname);
9990 if (ifx && !ifx->generated)
9992 genIfxJump (ifx, "a", left, NULL, result);
9996 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9997 freeAsmop (left, NULL, ic, TRUE);
9998 if (pi) pi->generated = 1;
10001 /*-----------------------------------------------------------------*/
10002 /* genPagedPointerGet - emitcode for paged pointer fetch */
10003 /*-----------------------------------------------------------------*/
10005 genPagedPointerGet (operand * left,
10014 sym_link *rtype, *retype;
10016 D (emitcode (";", "genPagedPointerGet"));
10018 rtype = operandType (result);
10019 retype = getSpec (rtype);
10021 aopOp (left, ic, FALSE);
10023 /* if the value is already in a pointer register
10024 then don't need anything more */
10025 if (!AOP_INPREG (AOP (left)))
10027 /* otherwise get a free pointer register */
10028 aop = newAsmop (0);
10029 preg = getFreePtr (ic, &aop, FALSE);
10030 emitcode ("mov", "%s,%s",
10032 aopGet (left, 0, FALSE, TRUE));
10033 rname = preg->name;
10036 rname = aopGet (left, 0, FALSE, FALSE);
10038 aopOp (result, ic, FALSE);
10040 /* if bitfield then unpack the bits */
10041 if (IS_BITFIELD (retype))
10042 genUnpackBits (result, rname, PPOINTER, ifx);
10045 /* we have can just get the values */
10046 int size = AOP_SIZE (result);
10052 emitcode ("movx", "a,@%s", rname);
10054 aopPut (result, "a", offset);
10059 emitcode ("inc", "%s", rname);
10063 /* now some housekeeping stuff */
10064 if (aop) /* we had to allocate for this iCode */
10067 aopPut (left, rname, 0);
10068 freeAsmop (NULL, aop, ic, TRUE);
10072 /* we did not allocate which means left
10073 already in a pointer register, then
10074 if size > 0 && this could be used again
10075 we have to point it back to where it
10077 if ((AOP_SIZE (result) > 1 &&
10078 !OP_SYMBOL (left)->remat &&
10079 (OP_SYMBOL (left)->liveTo > ic->seq ||
10083 int size = AOP_SIZE (result) - 1;
10085 emitcode ("dec", "%s", rname);
10089 if (ifx && !ifx->generated)
10091 genIfxJump (ifx, "a", left, NULL, result);
10095 freeAsmop (result, NULL, ic, TRUE);
10096 freeAsmop (left, NULL, ic, TRUE);
10097 if (pi) pi->generated = 1;
10100 /*--------------------------------------------------------------------*/
10101 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10102 /*--------------------------------------------------------------------*/
10104 loadDptrFromOperand (operand *op, bool loadBToo)
10106 if (AOP_TYPE (op) != AOP_STR)
10108 /* if this is rematerializable */
10109 if (AOP_TYPE (op) == AOP_IMMD)
10111 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10114 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10115 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10118 wassertl(FALSE, "need pointerCode");
10119 emitcode (";", "mov b,???");
10120 /* genPointerGet and genPointerSet originally did different
10121 ** things for this case. Both seem wrong.
10122 ** from genPointerGet:
10123 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10124 ** from genPointerSet:
10125 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10130 else if (AOP_TYPE (op) == AOP_DPTR)
10134 MOVA (aopGet (op, 0, FALSE, FALSE));
10135 emitcode ("push", "acc");
10136 MOVA (aopGet (op, 1, FALSE, FALSE));
10137 emitcode ("push", "acc");
10138 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10139 emitcode ("pop", "dph");
10140 emitcode ("pop", "dpl");
10144 MOVA (aopGet (op, 0, FALSE, FALSE));
10145 emitcode ("push", "acc");
10146 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10147 emitcode ("pop", "dpl");
10151 { /* we need to get it byte by byte */
10152 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10153 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10155 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10160 /*-----------------------------------------------------------------*/
10161 /* genFarPointerGet - get value from far space */
10162 /*-----------------------------------------------------------------*/
10164 genFarPointerGet (operand * left,
10165 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10168 sym_link *retype = getSpec (operandType (result));
10170 D (emitcode (";", "genFarPointerGet"));
10172 aopOp (left, ic, FALSE);
10173 loadDptrFromOperand (left, FALSE);
10175 /* so dptr now contains the address */
10176 aopOp (result, ic, FALSE);
10178 /* if bit then unpack */
10179 if (IS_BITFIELD (retype))
10180 genUnpackBits (result, "dptr", FPOINTER, ifx);
10183 size = AOP_SIZE (result);
10188 emitcode ("movx", "a,@dptr");
10190 aopPut (result, "a", offset++);
10192 emitcode ("inc", "dptr");
10196 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10198 aopPut (left, "dpl", 0);
10199 aopPut (left, "dph", 1);
10203 if (ifx && !ifx->generated)
10205 genIfxJump (ifx, "a", left, NULL, result);
10208 freeAsmop (result, NULL, ic, TRUE);
10209 freeAsmop (left, NULL, ic, TRUE);
10212 /*-----------------------------------------------------------------*/
10213 /* genCodePointerGet - get value from code space */
10214 /*-----------------------------------------------------------------*/
10216 genCodePointerGet (operand * left,
10217 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10220 sym_link *retype = getSpec (operandType (result));
10222 D (emitcode (";", "genCodePointerGet"));
10224 aopOp (left, ic, FALSE);
10225 loadDptrFromOperand (left, FALSE);
10227 /* so dptr now contains the address */
10228 aopOp (result, ic, FALSE);
10230 /* if bit then unpack */
10231 if (IS_BITFIELD (retype))
10232 genUnpackBits (result, "dptr", CPOINTER, ifx);
10235 size = AOP_SIZE (result);
10240 emitcode ("clr", "a");
10241 emitcode ("movc", "a,@a+dptr");
10243 aopPut (result, "a", offset++);
10245 emitcode ("inc", "dptr");
10249 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10251 aopPut (left, "dpl", 0);
10252 aopPut (left, "dph", 1);
10256 if (ifx && !ifx->generated)
10258 genIfxJump (ifx, "a", left, NULL, result);
10261 freeAsmop (result, NULL, ic, TRUE);
10262 freeAsmop (left, NULL, ic, TRUE);
10265 /*-----------------------------------------------------------------*/
10266 /* genGenPointerGet - get value from generic pointer space */
10267 /*-----------------------------------------------------------------*/
10269 genGenPointerGet (operand * left,
10270 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10273 sym_link *retype = getSpec (operandType (result));
10275 D (emitcode (";", "genGenPointerGet"));
10277 aopOp (left, ic, FALSE);
10278 loadDptrFromOperand (left, TRUE);
10280 /* so dptr now contains the address */
10281 aopOp (result, ic, FALSE);
10283 /* if bit then unpack */
10284 if (IS_BITFIELD (retype))
10286 genUnpackBits (result, "dptr", GPOINTER, ifx);
10290 size = AOP_SIZE (result);
10295 emitcode ("lcall", "__gptrget");
10297 aopPut (result, "a", offset++);
10299 emitcode ("inc", "dptr");
10303 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10305 aopPut (left, "dpl", 0);
10306 aopPut (left, "dph", 1);
10310 if (ifx && !ifx->generated)
10312 genIfxJump (ifx, "a", left, NULL, result);
10315 freeAsmop (result, NULL, ic, TRUE);
10316 freeAsmop (left, NULL, ic, TRUE);
10319 /*-----------------------------------------------------------------*/
10320 /* genPointerGet - generate code for pointer get */
10321 /*-----------------------------------------------------------------*/
10323 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10325 operand *left, *result;
10326 sym_link *type, *etype;
10329 D (emitcode (";", "genPointerGet"));
10331 left = IC_LEFT (ic);
10332 result = IC_RESULT (ic);
10334 if (getSize (operandType (result))>1)
10337 /* depending on the type of pointer we need to
10338 move it to the correct pointer register */
10339 type = operandType (left);
10340 etype = getSpec (type);
10341 /* if left is of type of pointer then it is simple */
10342 if (IS_PTR (type) && !IS_FUNC (type->next))
10343 p_type = DCL_TYPE (type);
10346 /* we have to go by the storage class */
10347 p_type = PTR_TYPE (SPEC_OCLS (etype));
10350 /* special case when cast remat */
10351 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10352 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10354 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10355 type = operandType (left);
10356 p_type = DCL_TYPE (type);
10358 /* now that we have the pointer type we assign
10359 the pointer values */
10365 genNearPointerGet (left, result, ic, pi, ifx);
10369 genPagedPointerGet (left, result, ic, pi, ifx);
10373 genFarPointerGet (left, result, ic, pi, ifx);
10377 genCodePointerGet (left, result, ic, pi, ifx);
10381 genGenPointerGet (left, result, ic, pi, ifx);
10387 /*-----------------------------------------------------------------*/
10388 /* genPackBits - generates code for packed bit storage */
10389 /*-----------------------------------------------------------------*/
10391 genPackBits (sym_link * etype,
10393 char *rname, int p_type)
10395 int offset = 0; /* source byte offset */
10396 int rlen = 0; /* remaining bitfield length */
10397 int blen; /* bitfield length */
10398 int bstr; /* bitfield starting bit within byte */
10399 int litval; /* source literal value (if AOP_LIT) */
10400 unsigned char mask; /* bitmask within current byte */
10402 D(emitcode (";", "genPackBits"));
10404 blen = SPEC_BLEN (etype);
10405 bstr = SPEC_BSTR (etype);
10407 /* If the bitfield length is less than a byte */
10410 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10411 (unsigned char) (0xFF >> (8 - bstr)));
10413 if (AOP_TYPE (right) == AOP_LIT)
10415 /* Case with a bitfield length <8 and literal source
10417 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10419 litval &= (~mask) & 0xff;
10420 emitPtrByteGet (rname, p_type, FALSE);
10421 if ((mask|litval)!=0xff)
10422 emitcode ("anl","a,#0x%02x", mask);
10424 emitcode ("orl","a,#0x%02x", litval);
10428 if ((blen==1) && (p_type!=GPOINTER))
10430 /* Case with a bitfield length == 1 and no generic pointer
10432 if (AOP_TYPE (right) == AOP_CRY)
10433 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10436 MOVA (aopGet (right, 0, FALSE, FALSE));
10437 emitcode ("rrc","a");
10439 emitPtrByteGet (rname, p_type, FALSE);
10440 emitcode ("mov","acc.%d,c",bstr);
10445 /* Case with a bitfield length < 8 and arbitrary source
10447 MOVA (aopGet (right, 0, FALSE, FALSE));
10448 /* shift and mask source value */
10450 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10452 pushedB = pushB ();
10453 /* transfer A to B and get next byte */
10454 emitPtrByteGet (rname, p_type, TRUE);
10456 emitcode ("anl", "a,#0x%02x", mask);
10457 emitcode ("orl", "a,b");
10458 if (p_type == GPOINTER)
10459 emitcode ("pop", "b");
10465 emitPtrByteSet (rname, p_type, "a");
10469 /* Bit length is greater than 7 bits. In this case, copy */
10470 /* all except the partial byte at the end */
10471 for (rlen=blen;rlen>=8;rlen-=8)
10473 emitPtrByteSet (rname, p_type,
10474 aopGet (right, offset++, FALSE, TRUE) );
10476 emitcode ("inc", "%s", rname);
10479 /* If there was a partial byte at the end */
10482 mask = (((unsigned char) -1 << rlen) & 0xff);
10484 if (AOP_TYPE (right) == AOP_LIT)
10486 /* Case with partial byte and literal source
10488 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10489 litval >>= (blen-rlen);
10490 litval &= (~mask) & 0xff;
10491 emitPtrByteGet (rname, p_type, FALSE);
10492 if ((mask|litval)!=0xff)
10493 emitcode ("anl","a,#0x%02x", mask);
10495 emitcode ("orl","a,#0x%02x", litval);
10500 /* Case with partial byte and arbitrary source
10502 MOVA (aopGet (right, offset++, FALSE, FALSE));
10503 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10505 pushedB = pushB ();
10506 /* transfer A to B and get next byte */
10507 emitPtrByteGet (rname, p_type, TRUE);
10509 emitcode ("anl", "a,#0x%02x", mask);
10510 emitcode ("orl", "a,b");
10511 if (p_type == GPOINTER)
10512 emitcode ("pop", "b");
10516 emitPtrByteSet (rname, p_type, "a");
10521 /*-----------------------------------------------------------------*/
10522 /* genDataPointerSet - remat pointer to data space */
10523 /*-----------------------------------------------------------------*/
10525 genDataPointerSet (operand * right,
10529 int size, offset = 0;
10530 char *l, buffer[256];
10532 D (emitcode (";", "genDataPointerSet"));
10534 aopOp (right, ic, FALSE);
10536 l = aopGet (result, 0, FALSE, TRUE);
10538 size = AOP_SIZE (result);
10542 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10544 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10545 emitcode ("mov", "%s,%s", buffer,
10546 aopGet (right, offset++, FALSE, FALSE));
10549 freeAsmop (right, NULL, ic, TRUE);
10550 freeAsmop (result, NULL, ic, TRUE);
10553 /*-----------------------------------------------------------------*/
10554 /* genNearPointerSet - emitcode for near pointer put */
10555 /*-----------------------------------------------------------------*/
10557 genNearPointerSet (operand * right,
10565 sym_link *retype, *letype;
10566 sym_link *ptype = operandType (result);
10568 D (emitcode (";", "genNearPointerSet"));
10570 retype = getSpec (operandType (right));
10571 letype = getSpec (ptype);
10573 aopOp (result, ic, FALSE);
10575 /* if the result is rematerializable &
10576 in data space & not a bit variable */
10577 if (AOP_TYPE (result) == AOP_IMMD &&
10578 DCL_TYPE (ptype) == POINTER &&
10579 !IS_BITVAR (retype) &&
10580 !IS_BITVAR (letype))
10582 genDataPointerSet (right, result, ic);
10586 /* if the value is already in a pointer register
10587 then don't need anything more */
10588 if (!AOP_INPREG (AOP (result)))
10591 //AOP_TYPE (result) == AOP_STK
10592 IS_AOP_PREG(result)
10595 // Aha, it is a pointer, just in disguise.
10596 rname = aopGet (result, 0, FALSE, FALSE);
10599 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10600 __FILE__, __LINE__);
10605 emitcode ("mov", "a%s,%s", rname + 1, rname);
10606 rname++; // skip the '@'.
10611 /* otherwise get a free pointer register */
10612 aop = newAsmop (0);
10613 preg = getFreePtr (ic, &aop, FALSE);
10614 emitcode ("mov", "%s,%s",
10616 aopGet (result, 0, FALSE, TRUE));
10617 rname = preg->name;
10622 rname = aopGet (result, 0, FALSE, FALSE);
10625 aopOp (right, ic, FALSE);
10627 /* if bitfield then unpack the bits */
10628 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10629 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10632 /* we can just get the values */
10633 int size = AOP_SIZE (right);
10638 l = aopGet (right, offset, FALSE, TRUE);
10639 if ((*l == '@') || (strcmp (l, "acc") == 0))
10642 emitcode ("mov", "@%s,a", rname);
10645 emitcode ("mov", "@%s,%s", rname, l);
10647 emitcode ("inc", "%s", rname);
10652 /* now some housekeeping stuff */
10653 if (aop) /* we had to allocate for this iCode */
10656 aopPut (result, rname, 0);
10657 freeAsmop (NULL, aop, ic, TRUE);
10661 /* we did not allocate which means left
10662 already in a pointer register, then
10663 if size > 0 && this could be used again
10664 we have to point it back to where it
10666 if ((AOP_SIZE (right) > 1 &&
10667 !OP_SYMBOL (result)->remat &&
10668 (OP_SYMBOL (result)->liveTo > ic->seq ||
10672 int size = AOP_SIZE (right) - 1;
10674 emitcode ("dec", "%s", rname);
10681 freeAsmop (right, NULL, ic, TRUE);
10682 freeAsmop (result, NULL, ic, TRUE);
10685 /*-----------------------------------------------------------------*/
10686 /* genPagedPointerSet - emitcode for Paged pointer put */
10687 /*-----------------------------------------------------------------*/
10689 genPagedPointerSet (operand * right,
10697 sym_link *retype, *letype;
10699 D (emitcode (";", "genPagedPointerSet"));
10701 retype = getSpec (operandType (right));
10702 letype = getSpec (operandType (result));
10704 aopOp (result, ic, FALSE);
10706 /* if the value is already in a pointer register
10707 then don't need anything more */
10708 if (!AOP_INPREG (AOP (result)))
10710 /* otherwise get a free pointer register */
10711 aop = newAsmop (0);
10712 preg = getFreePtr (ic, &aop, FALSE);
10713 emitcode ("mov", "%s,%s",
10715 aopGet (result, 0, FALSE, TRUE));
10716 rname = preg->name;
10719 rname = aopGet (result, 0, FALSE, FALSE);
10721 aopOp (right, ic, FALSE);
10723 /* if bitfield then unpack the bits */
10724 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10725 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10728 /* we have can just get the values */
10729 int size = AOP_SIZE (right);
10734 l = aopGet (right, offset, FALSE, TRUE);
10736 emitcode ("movx", "@%s,a", rname);
10739 emitcode ("inc", "%s", rname);
10745 /* now some housekeeping stuff */
10746 if (aop) /* we had to allocate for this iCode */
10749 aopPut (result, rname, 0);
10750 freeAsmop (NULL, aop, ic, TRUE);
10754 /* we did not allocate which means left
10755 already in a pointer register, then
10756 if size > 0 && this could be used again
10757 we have to point it back to where it
10759 if (AOP_SIZE (right) > 1 &&
10760 !OP_SYMBOL (result)->remat &&
10761 (OP_SYMBOL (result)->liveTo > ic->seq ||
10764 int size = AOP_SIZE (right) - 1;
10766 emitcode ("dec", "%s", rname);
10771 if (pi) pi->generated = 1;
10772 freeAsmop (result, NULL, ic, TRUE);
10773 freeAsmop (right, NULL, ic, TRUE);
10776 /*-----------------------------------------------------------------*/
10777 /* genFarPointerSet - set value from far space */
10778 /*-----------------------------------------------------------------*/
10780 genFarPointerSet (operand * right,
10781 operand * result, iCode * ic, iCode * pi)
10784 sym_link *retype = getSpec (operandType (right));
10785 sym_link *letype = getSpec (operandType (result));
10787 D(emitcode (";", "genFarPointerSet"));
10789 aopOp (result, ic, FALSE);
10790 loadDptrFromOperand (result, FALSE);
10792 /* so dptr now contains the address */
10793 aopOp (right, ic, FALSE);
10795 /* if bit then unpack */
10796 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10797 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10800 size = AOP_SIZE (right);
10805 char *l = aopGet (right, offset++, FALSE, FALSE);
10807 emitcode ("movx", "@dptr,a");
10809 emitcode ("inc", "dptr");
10812 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10813 aopPut (result, "dpl", 0);
10814 aopPut (result, "dph", 1);
10817 freeAsmop (result, NULL, ic, TRUE);
10818 freeAsmop (right, NULL, ic, TRUE);
10821 /*-----------------------------------------------------------------*/
10822 /* genGenPointerSet - set value from generic pointer space */
10823 /*-----------------------------------------------------------------*/
10825 genGenPointerSet (operand * right,
10826 operand * result, iCode * ic, iCode * pi)
10829 sym_link *retype = getSpec (operandType (right));
10830 sym_link *letype = getSpec (operandType (result));
10832 D (emitcode (";", "genGenPointerSet"));
10834 aopOp (result, ic, FALSE);
10835 loadDptrFromOperand (result, TRUE);
10837 /* so dptr now contains the address */
10838 aopOp (right, ic, FALSE);
10840 /* if bit then unpack */
10841 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10843 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10847 size = AOP_SIZE (right);
10852 char *l = aopGet (right, offset++, FALSE, FALSE);
10854 emitcode ("lcall", "__gptrput");
10856 emitcode ("inc", "dptr");
10860 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10861 aopPut (result, "dpl", 0);
10862 aopPut (result, "dph", 1);
10865 freeAsmop (result, NULL, ic, TRUE);
10866 freeAsmop (right, NULL, ic, TRUE);
10869 /*-----------------------------------------------------------------*/
10870 /* genPointerSet - stores the value into a pointer location */
10871 /*-----------------------------------------------------------------*/
10873 genPointerSet (iCode * ic, iCode *pi)
10875 operand *right, *result;
10876 sym_link *type, *etype;
10879 D (emitcode (";", "genPointerSet"));
10881 right = IC_RIGHT (ic);
10882 result = IC_RESULT (ic);
10884 /* depending on the type of pointer we need to
10885 move it to the correct pointer register */
10886 type = operandType (result);
10887 etype = getSpec (type);
10888 /* if left is of type of pointer then it is simple */
10889 if (IS_PTR (type) && !IS_FUNC (type->next))
10891 p_type = DCL_TYPE (type);
10895 /* we have to go by the storage class */
10896 p_type = PTR_TYPE (SPEC_OCLS (etype));
10899 /* special case when cast remat */
10900 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10901 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10902 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10903 type = operandType (result);
10904 p_type = DCL_TYPE (type);
10907 /* now that we have the pointer type we assign
10908 the pointer values */
10914 genNearPointerSet (right, result, ic, pi);
10918 genPagedPointerSet (right, result, ic, pi);
10922 genFarPointerSet (right, result, ic, pi);
10926 genGenPointerSet (right, result, ic, pi);
10930 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10931 "genPointerSet: illegal pointer type");
10935 /*-----------------------------------------------------------------*/
10936 /* genIfx - generate code for Ifx statement */
10937 /*-----------------------------------------------------------------*/
10939 genIfx (iCode * ic, iCode * popIc)
10941 operand *cond = IC_COND (ic);
10945 D (emitcode (";", "genIfx"));
10947 aopOp (cond, ic, FALSE);
10949 /* get the value into acc */
10950 if (AOP_TYPE (cond) != AOP_CRY)
10957 if (AOP(cond)->aopu.aop_dir)
10958 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10961 /* the result is now in the accumulator or a directly addressable bit */
10962 freeAsmop (cond, NULL, ic, TRUE);
10964 /* if there was something to be popped then do it */
10968 /* if the condition is a bit variable */
10970 genIfxJump(ic, dup, NULL, NULL, NULL);
10971 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10972 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10973 else if (isbit && !IS_ITEMP (cond))
10974 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10976 genIfxJump (ic, "a", NULL, NULL, NULL);
10981 /*-----------------------------------------------------------------*/
10982 /* genAddrOf - generates code for address of */
10983 /*-----------------------------------------------------------------*/
10985 genAddrOf (iCode * ic)
10987 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10990 D (emitcode (";", "genAddrOf"));
10992 aopOp (IC_RESULT (ic), ic, FALSE);
10994 /* if the operand is on the stack then we
10995 need to get the stack offset of this
10999 /* if it has an offset then we need to compute it */
11002 int stack_offset = ((sym->stack < 0) ?
11003 ((char) (sym->stack - _G.nRegsSaved)) :
11004 ((char) sym->stack)) & 0xff;
11005 if ((abs(stack_offset) == 1) &&
11006 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11007 !isOperandVolatile (IC_RESULT (ic), FALSE))
11009 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11010 if (stack_offset > 0)
11011 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11013 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11017 emitcode ("mov", "a,%s", SYM_BP (sym));
11018 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11019 aopPut (IC_RESULT (ic), "a", 0);
11024 /* we can just move _bp */
11025 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11027 /* fill the result with zero */
11028 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11033 aopPut (IC_RESULT (ic), zero, offset++);
11038 /* object not on stack then we need the name */
11039 size = AOP_SIZE (IC_RESULT (ic));
11044 char s[SDCC_NAME_MAX];
11046 sprintf (s, "#(%s >> %d)",
11050 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11051 aopPut (IC_RESULT (ic), s, offset++);
11055 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11059 /*-----------------------------------------------------------------*/
11060 /* genFarFarAssign - assignment when both are in far space */
11061 /*-----------------------------------------------------------------*/
11063 genFarFarAssign (operand * result, operand * right, iCode * ic)
11065 int size = AOP_SIZE (right);
11069 D (emitcode (";", "genFarFarAssign"));
11071 /* first push the right side on to the stack */
11074 l = aopGet (right, offset++, FALSE, FALSE);
11076 emitcode ("push", "acc");
11079 freeAsmop (right, NULL, ic, FALSE);
11080 /* now assign DPTR to result */
11081 aopOp (result, ic, FALSE);
11082 size = AOP_SIZE (result);
11085 emitcode ("pop", "acc");
11086 aopPut (result, "a", --offset);
11088 freeAsmop (result, NULL, ic, FALSE);
11091 /*-----------------------------------------------------------------*/
11092 /* genAssign - generate code for assignment */
11093 /*-----------------------------------------------------------------*/
11095 genAssign (iCode * ic)
11097 operand *result, *right;
11099 unsigned long lit = 0L;
11101 D (emitcode (";", "genAssign"));
11103 result = IC_RESULT (ic);
11104 right = IC_RIGHT (ic);
11106 /* if they are the same */
11107 if (operandsEqu (result, right) &&
11108 !isOperandVolatile (result, FALSE) &&
11109 !isOperandVolatile (right, FALSE))
11112 aopOp (right, ic, FALSE);
11114 /* special case both in far space */
11115 if (AOP_TYPE (right) == AOP_DPTR &&
11116 IS_TRUE_SYMOP (result) &&
11117 isOperandInFarSpace (result))
11119 genFarFarAssign (result, right, ic);
11123 aopOp (result, ic, TRUE);
11125 /* if they are the same registers */
11126 if (sameRegs (AOP (right), AOP (result)) &&
11127 !isOperandVolatile (result, FALSE) &&
11128 !isOperandVolatile (right, FALSE))
11131 /* if the result is a bit */
11132 if (AOP_TYPE (result) == AOP_CRY)
11134 assignBit (result, right);
11138 /* bit variables done */
11140 size = AOP_SIZE (result);
11142 if (AOP_TYPE (right) == AOP_LIT)
11143 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11146 (AOP_TYPE (result) != AOP_REG) &&
11147 (AOP_TYPE (right) == AOP_LIT) &&
11148 !IS_FLOAT (operandType (right)) &&
11151 while ((size) && (lit))
11154 aopGet (right, offset, FALSE, FALSE),
11160 /* And now fill the rest with zeros. */
11163 emitcode ("clr", "a");
11167 aopPut (result, "a", offset);
11176 aopGet (right, offset, FALSE, FALSE),
11183 freeAsmop (result, NULL, ic, TRUE);
11184 freeAsmop (right, NULL, ic, TRUE);
11187 /*-----------------------------------------------------------------*/
11188 /* genJumpTab - generates code for jump table */
11189 /*-----------------------------------------------------------------*/
11191 genJumpTab (iCode * ic)
11193 symbol *jtab,*jtablo,*jtabhi;
11195 unsigned int count;
11197 D (emitcode (";", "genJumpTab"));
11199 count = elementsInSet( IC_JTLABELS (ic) );
11203 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11204 if the switch argument is in a register.
11205 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11206 /* Peephole may not convert ljmp to sjmp or ret
11207 labelIsReturnOnly & labelInRange must check
11208 currPl->ic->op != JUMPTABLE */
11209 aopOp (IC_JTCOND (ic), ic, FALSE);
11210 /* get the condition into accumulator */
11211 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11213 /* multiply by three */
11214 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11216 emitcode ("mov", "b,#3");
11217 emitcode ("mul", "ab");
11221 emitcode ("add", "a,acc");
11222 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11224 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11226 jtab = newiTempLabel (NULL);
11227 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11228 emitcode ("jmp", "@a+dptr");
11230 /* now generate the jump labels */
11231 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11232 jtab = setNextItem (IC_JTLABELS (ic)))
11233 emitcode ("ljmp", "%05d$", jtab->key + 100);
11237 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11238 if the switch argument is in a register.
11239 For n>6 this algorithm may be more compact */
11240 jtablo = newiTempLabel (NULL);
11241 jtabhi = newiTempLabel (NULL);
11243 /* get the condition into accumulator.
11244 Using b as temporary storage, if register push/pop is needed */
11245 aopOp (IC_JTCOND (ic), ic, FALSE);
11246 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11247 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11248 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11250 // (MB) what if B is in use???
11251 wassertl(!BINUSE, "B was in use");
11252 emitcode ("mov", "b,%s", l);
11255 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11259 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11260 emitcode ("movc", "a,@a+pc");
11261 emitcode ("push", "acc");
11264 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11265 emitcode ("movc", "a,@a+pc");
11266 emitcode ("push", "acc");
11270 /* this scales up to n<=255, but needs two more bytes
11271 and changes dptr */
11272 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11273 emitcode ("movc", "a,@a+dptr");
11274 emitcode ("push", "acc");
11277 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11278 emitcode ("movc", "a,@a+dptr");
11279 emitcode ("push", "acc");
11282 emitcode ("ret", "");
11284 /* now generate jump table, LSB */
11285 emitLabel (jtablo);
11286 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11287 jtab = setNextItem (IC_JTLABELS (ic)))
11288 emitcode (".db", "%05d$", jtab->key + 100);
11290 /* now generate jump table, MSB */
11291 emitLabel (jtabhi);
11292 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11293 jtab = setNextItem (IC_JTLABELS (ic)))
11294 emitcode (".db", "%05d$>>8", jtab->key + 100);
11298 /*-----------------------------------------------------------------*/
11299 /* genCast - gen code for casting */
11300 /*-----------------------------------------------------------------*/
11302 genCast (iCode * ic)
11304 operand *result = IC_RESULT (ic);
11305 sym_link *ctype = operandType (IC_LEFT (ic));
11306 sym_link *rtype = operandType (IC_RIGHT (ic));
11307 operand *right = IC_RIGHT (ic);
11310 D (emitcode (";", "genCast"));
11312 /* if they are equivalent then do nothing */
11313 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11316 aopOp (right, ic, FALSE);
11317 aopOp (result, ic, FALSE);
11319 /* if the result is a bit (and not a bitfield) */
11320 if (IS_BIT (OP_SYMBOL (result)->type))
11322 assignBit (result, right);
11326 /* if they are the same size : or less */
11327 if (AOP_SIZE (result) <= AOP_SIZE (right))
11330 /* if they are in the same place */
11331 if (sameRegs (AOP (right), AOP (result)))
11334 /* if they in different places then copy */
11335 size = AOP_SIZE (result);
11340 aopGet (right, offset, FALSE, FALSE),
11347 /* if the result is of type pointer */
11348 if (IS_PTR (ctype))
11352 sym_link *type = operandType (right);
11353 sym_link *etype = getSpec (type);
11355 /* pointer to generic pointer */
11356 if (IS_GENPTR (ctype))
11360 p_type = DCL_TYPE (type);
11364 if (SPEC_SCLS(etype)==S_REGISTER) {
11365 // let's assume it is a generic pointer
11368 /* we have to go by the storage class */
11369 p_type = PTR_TYPE (SPEC_OCLS (etype));
11373 /* the first two bytes are known */
11374 size = GPTRSIZE - 1;
11379 aopGet (right, offset, FALSE, FALSE),
11383 /* the last byte depending on type */
11385 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11390 // pointerTypeToGPByte will have bitched.
11394 sprintf(gpValStr, "#0x%x", gpVal);
11395 aopPut (result, gpValStr, GPTRSIZE - 1);
11400 /* just copy the pointers */
11401 size = AOP_SIZE (result);
11406 aopGet (right, offset, FALSE, FALSE),
11413 /* so we now know that the size of destination is greater
11414 than the size of the source */
11415 /* we move to result for the size of source */
11416 size = AOP_SIZE (right);
11421 aopGet (right, offset, FALSE, FALSE),
11426 /* now depending on the sign of the source && destination */
11427 size = AOP_SIZE (result) - AOP_SIZE (right);
11428 /* if unsigned or not an integral type */
11429 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11432 aopPut (result, zero, offset++);
11436 /* we need to extend the sign :{ */
11437 char *l = aopGet (right, AOP_SIZE (right) - 1,
11440 emitcode ("rlc", "a");
11441 emitcode ("subb", "a,acc");
11443 aopPut (result, "a", offset++);
11446 /* we are done hurray !!!! */
11449 freeAsmop (result, NULL, ic, TRUE);
11450 freeAsmop (right, NULL, ic, TRUE);
11453 /*-----------------------------------------------------------------*/
11454 /* genDjnz - generate decrement & jump if not zero instrucion */
11455 /*-----------------------------------------------------------------*/
11457 genDjnz (iCode * ic, iCode * ifx)
11459 symbol *lbl, *lbl1;
11463 /* if the if condition has a false label
11464 then we cannot save */
11465 if (IC_FALSE (ifx))
11468 /* if the minus is not of the form a = a - 1 */
11469 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11470 !IS_OP_LITERAL (IC_RIGHT (ic)))
11473 if (operandLitValue (IC_RIGHT (ic)) != 1)
11476 /* if the size of this greater than one then no
11478 if (getSize (operandType (IC_RESULT (ic))) > 1)
11481 /* otherwise we can save BIG */
11483 D (emitcode (";", "genDjnz"));
11485 lbl = newiTempLabel (NULL);
11486 lbl1 = newiTempLabel (NULL);
11488 aopOp (IC_RESULT (ic), ic, FALSE);
11490 if (AOP_NEEDSACC(IC_RESULT(ic)))
11492 /* If the result is accessed indirectly via
11493 * the accumulator, we must explicitly write
11494 * it back after the decrement.
11496 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11498 if (strcmp(rByte, "a"))
11500 /* Something is hopelessly wrong */
11501 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11502 __FILE__, __LINE__);
11503 /* We can just give up; the generated code will be inefficient,
11504 * but what the hey.
11506 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11509 emitcode ("dec", "%s", rByte);
11510 aopPut (IC_RESULT (ic), rByte, 0);
11511 emitcode ("jnz", "%05d$", lbl->key + 100);
11513 else if (IS_AOP_PREG (IC_RESULT (ic)))
11515 emitcode ("dec", "%s",
11516 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11517 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11518 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11519 ifx->generated = 1;
11520 emitcode ("jnz", "%05d$", lbl->key + 100);
11524 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11527 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11529 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11532 if (!ifx->generated)
11533 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11534 ifx->generated = 1;
11538 /*-----------------------------------------------------------------*/
11539 /* genReceive - generate code for a receive iCode */
11540 /*-----------------------------------------------------------------*/
11542 genReceive (iCode * ic)
11544 int size = getSize (operandType (IC_RESULT (ic)));
11547 D (emitcode (";", "genReceive"));
11549 if (ic->argreg == 1)
11550 { /* first parameter */
11551 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11552 isOperandInPagedSpace (IC_RESULT (ic))) &&
11553 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11554 IS_TRUE_SYMOP (IC_RESULT (ic))))
11557 int receivingA = 0;
11560 for (offset = 0; offset<size; offset++)
11561 if (!strcmp (fReturn[offset], "a"))
11566 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11568 for (offset = size-1; offset>0; offset--)
11569 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11570 emitcode("mov","a,%s", fReturn[0]);
11572 aopOp (IC_RESULT (ic), ic, FALSE);
11574 aopPut (IC_RESULT (ic), "a", offset);
11575 for (offset = 1; offset<size; offset++)
11576 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11582 if (getTempRegs(tempRegs, size, ic))
11584 for (offset = 0; offset<size; offset++)
11585 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11586 aopOp (IC_RESULT (ic), ic, FALSE);
11587 for (offset = 0; offset<size; offset++)
11588 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11593 offset = fReturnSizeMCS51 - size;
11596 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11597 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11600 aopOp (IC_RESULT (ic), ic, FALSE);
11601 size = AOP_SIZE (IC_RESULT (ic));
11605 emitcode ("pop", "acc");
11606 aopPut (IC_RESULT (ic), "a", offset++);
11612 aopOp (IC_RESULT (ic), ic, FALSE);
11614 assignResultValue (IC_RESULT (ic), NULL);
11617 else if (ic->argreg > 12)
11618 { /* bit parameters */
11619 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11621 aopOp (IC_RESULT (ic), ic, FALSE);
11622 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11623 outBitC(IC_RESULT (ic));
11627 { /* other parameters */
11629 aopOp (IC_RESULT (ic), ic, FALSE);
11630 rb1off = ic->argreg;
11633 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11638 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11641 /*-----------------------------------------------------------------*/
11642 /* genDummyRead - generate code for dummy read of volatiles */
11643 /*-----------------------------------------------------------------*/
11645 genDummyRead (iCode * ic)
11650 D (emitcode(";", "genDummyRead"));
11652 op = IC_RIGHT (ic);
11653 if (op && IS_SYMOP (op))
11655 aopOp (op, ic, FALSE);
11657 /* if the result is a bit */
11658 if (AOP_TYPE (op) == AOP_CRY)
11659 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11662 /* bit variables done */
11664 size = AOP_SIZE (op);
11668 MOVA (aopGet (op, offset, FALSE, FALSE));
11673 freeAsmop (op, NULL, ic, TRUE);
11677 if (op && IS_SYMOP (op))
11679 aopOp (op, ic, FALSE);
11681 /* if the result is a bit */
11682 if (AOP_TYPE (op) == AOP_CRY)
11683 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11686 /* bit variables done */
11688 size = AOP_SIZE (op);
11692 MOVA (aopGet (op, offset, FALSE, FALSE));
11697 freeAsmop (op, NULL, ic, TRUE);
11701 /*-----------------------------------------------------------------*/
11702 /* genCritical - generate code for start of a critical sequence */
11703 /*-----------------------------------------------------------------*/
11705 genCritical (iCode *ic)
11707 symbol *tlbl = newiTempLabel (NULL);
11709 D (emitcode(";", "genCritical"));
11711 if (IC_RESULT (ic))
11713 aopOp (IC_RESULT (ic), ic, TRUE);
11714 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11715 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11716 aopPut (IC_RESULT (ic), zero, 0);
11718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11722 emitcode ("setb", "c");
11723 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11724 emitcode ("clr", "c");
11726 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11730 /*-----------------------------------------------------------------*/
11731 /* genEndCritical - generate code for end of a critical sequence */
11732 /*-----------------------------------------------------------------*/
11734 genEndCritical (iCode *ic)
11736 D(emitcode(";", "genEndCritical"));
11740 aopOp (IC_RIGHT (ic), ic, FALSE);
11741 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11743 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11744 emitcode ("mov", "ea,c");
11748 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11749 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11750 emitcode ("rrc", "a");
11751 emitcode ("mov", "ea,c");
11753 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11757 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11758 emitcode ("mov", "ea,c");
11762 /*-----------------------------------------------------------------*/
11763 /* gen51Code - generate code for 8051 based controllers */
11764 /*-----------------------------------------------------------------*/
11766 gen51Code (iCode * lic)
11770 /* int cseq = 0; */
11772 _G.currentFunc = NULL;
11773 lineHead = lineCurr = NULL;
11775 /* print the allocation information */
11776 if (allocInfo && currFunc)
11777 printAllocInfo (currFunc, codeOutBuf);
11778 /* if debug information required */
11779 if (options.debug && currFunc)
11781 debugFile->writeFunction (currFunc, lic);
11783 /* stack pointer name */
11784 if (options.useXstack)
11790 for (ic = lic; ic; ic = ic->next)
11792 _G.current_iCode = ic;
11794 if (ic->lineno && cln != ic->lineno)
11798 debugFile->writeCLine (ic);
11800 if (!options.noCcodeInAsm) {
11801 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11802 printCLine(ic->filename, ic->lineno));
11807 if (ic->seqPoint && ic->seqPoint != cseq)
11809 emitcode (";", "sequence point %d", ic->seqPoint);
11810 cseq = ic->seqPoint;
11813 if (options.iCodeInAsm) {
11814 char regsInUse[80];
11819 for (i=0; i<8; i++) {
11820 sprintf (®sInUse[i],
11821 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11824 strcpy (regsInUse, "--------");
11825 for (i=0; i < 8; i++) {
11826 if (bitVectBitValue (ic->rMask, i))
11828 int offset = regs8051[i].offset;
11829 regsInUse[offset] = offset + '0'; /* show rMask */
11833 iLine = printILine(ic);
11834 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11837 /* if the result is marked as
11838 spilt and rematerializable or code for
11839 this has already been generated then
11841 if (resultRemat (ic) || ic->generated)
11844 /* depending on the operation */
11864 /* IPOP happens only when trying to restore a
11865 spilt live range, if there is an ifx statement
11866 following this pop then the if statement might
11867 be using some of the registers being popped which
11868 would destory the contents of the register so
11869 we need to check for this condition and handle it */
11871 ic->next->op == IFX &&
11872 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11873 genIfx (ic->next, ic);
11891 genEndFunction (ic);
11911 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11928 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11932 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11939 /* note these two are xlated by algebraic equivalence
11940 in decorateType() in SDCCast.c */
11941 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11942 "got '>=' or '<=' shouldn't have come here");
11946 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11958 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11962 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11966 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12002 genRightShift (ic);
12005 case GET_VALUE_AT_ADDRESS:
12007 hasInc (IC_LEFT (ic), ic,
12008 getSize (operandType (IC_RESULT (ic)))),
12009 ifxForOp (IC_RESULT (ic), ic) );
12013 if (POINTER_SET (ic))
12015 hasInc (IC_RESULT (ic), ic,
12016 getSize (operandType (IC_RIGHT (ic)))));
12042 addSet (&_G.sendSet, ic);
12045 case DUMMY_READ_VOLATILE:
12054 genEndCritical (ic);
12066 _G.current_iCode = NULL;
12068 /* now we are ready to call the
12069 peep hole optimizer */
12070 if (!options.nopeep)
12071 peepHole (&lineHead);
12073 /* now do the actual printing */
12074 printLine (lineHead, codeOutBuf);