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_OP_ACCUSE (op))
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_OP_ACCUSE (op))
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_OP_ACCUSE (op))
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_OP_ACCUSE (op))
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) ulFromVal (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 (ulFromVal (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) ulFromVal (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) ulFromVal (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 = ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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 = ulFromVal (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 = ulFromVal (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 = ulFromVal (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 = ulFromVal (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 = ulFromVal (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 if (IS_OP_ACCUSE (left))
6639 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6643 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6644 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6650 MOVA (aopGet (right, 0, FALSE, FALSE));
6652 emitcode ("rrc", "a");
6653 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6661 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6662 genIfxJump (ifx, "c", left, right, result);
6666 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6667 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6668 if ((AOP_TYPE (right) == AOP_LIT) &&
6669 (AOP_TYPE (result) == AOP_CRY) &&
6670 (AOP_TYPE (left) != AOP_CRY))
6672 int posbit = isLiteralBit (lit);
6677 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6681 switch (posbit & 0x07)
6683 case 0: emitcode ("rrc", "a");
6685 case 7: emitcode ("rlc", "a");
6687 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6696 SNPRINTF (buffer, sizeof(buffer),
6697 "acc.%d", posbit & 0x07);
6698 genIfxJump (ifx, buffer, left, right, result);
6701 {// what is this case? just found it in ds390/gen.c
6702 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6709 symbol *tlbl = newiTempLabel (NULL);
6710 int sizel = AOP_SIZE (left);
6712 emitcode ("setb", "c");
6715 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6717 MOVA (aopGet (left, offset, FALSE, FALSE));
6719 if ((posbit = isLiteralBit (bytelit)) != 0)
6720 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6723 if (bytelit != 0x0FFL)
6724 emitcode ("anl", "a,%s",
6725 aopGet (right, offset, FALSE, TRUE));
6726 emitcode ("jnz", "%05d$", tlbl->key + 100);
6731 // bit = left & literal
6734 emitcode ("clr", "c");
6737 // if(left & literal)
6741 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6751 /* if left is same as result */
6752 if (sameRegs (AOP (result), AOP (left)))
6754 for (; size--; offset++)
6756 if (AOP_TYPE (right) == AOP_LIT)
6758 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6759 if (bytelit == 0x0FF)
6761 /* dummy read of volatile operand */
6762 if (isOperandVolatile (left, FALSE))
6763 MOVA (aopGet (left, offset, FALSE, FALSE));
6767 else if (bytelit == 0)
6769 aopPut (result, zero, offset);
6771 else if (IS_AOP_PREG (result))
6773 MOVA (aopGet (left, offset, FALSE, TRUE));
6774 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6775 aopPut (result, "a", offset);
6778 emitcode ("anl", "%s,%s",
6779 aopGet (left, offset, FALSE, TRUE),
6780 aopGet (right, offset, FALSE, FALSE));
6784 if (AOP_TYPE (left) == AOP_ACC)
6787 emitcode("mov", "a,b");
6788 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6790 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6792 MOVB (aopGet (left, offset, FALSE, FALSE));
6793 MOVA (aopGet (right, offset, FALSE, FALSE));
6794 emitcode ("anl", "a,b");
6795 aopPut (result, "a", offset);
6797 else if (aopGetUsesAcc (left, offset))
6799 MOVA (aopGet (left, offset, FALSE, FALSE));
6800 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6801 aopPut (result, "a", offset);
6805 MOVA (aopGet (right, offset, FALSE, FALSE));
6806 if (IS_AOP_PREG (result))
6808 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6809 aopPut (result, "a", offset);
6812 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6819 // left & result in different registers
6820 if (AOP_TYPE (result) == AOP_CRY)
6823 // if(size), result in bit
6824 // if(!size && ifx), conditional oper: if(left & right)
6825 symbol *tlbl = newiTempLabel (NULL);
6826 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6828 emitcode ("setb", "c");
6831 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6832 && AOP_TYPE(left)==AOP_ACC)
6835 emitcode("mov", "a,b");
6836 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6838 else if (AOP_TYPE(left)==AOP_ACC)
6842 bool pushedB = pushB ();
6843 emitcode("mov", "b,a");
6844 MOVA (aopGet (right, offset, FALSE, FALSE));
6845 emitcode("anl", "a,b");
6850 MOVA (aopGet (right, offset, FALSE, FALSE));
6851 emitcode("anl", "a,b");
6854 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6856 MOVB (aopGet (left, offset, FALSE, FALSE));
6857 MOVA (aopGet (right, offset, FALSE, FALSE));
6858 emitcode ("anl", "a,b");
6860 else if (aopGetUsesAcc (left, offset))
6862 MOVA (aopGet (left, offset, FALSE, FALSE));
6863 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6867 MOVA (aopGet (right, offset, FALSE, FALSE));
6868 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6871 emitcode ("jnz", "%05d$", tlbl->key + 100);
6881 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6887 for (; (size--); offset++)
6890 // result = left & right
6891 if (AOP_TYPE (right) == AOP_LIT)
6893 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6894 if (bytelit == 0x0FF)
6897 aopGet (left, offset, FALSE, FALSE),
6901 else if (bytelit == 0)
6903 /* dummy read of volatile operand */
6904 if (isOperandVolatile (left, FALSE))
6905 MOVA (aopGet (left, offset, FALSE, FALSE));
6906 aopPut (result, zero, offset);
6909 else if (AOP_TYPE (left) == AOP_ACC)
6913 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6914 aopPut (result, "a", offset);
6919 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6920 aopPut (result, "b", offset);
6925 // faster than result <- left, anl result,right
6926 // and better if result is SFR
6927 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6928 && AOP_TYPE(left)==AOP_ACC)
6931 emitcode("mov", "a,b");
6932 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 else if (AOP_TYPE(left)==AOP_ACC)
6938 bool pushedB = pushB ();
6939 emitcode("mov", "b,a");
6940 MOVA (aopGet (right, offset, FALSE, FALSE));
6941 emitcode("anl", "a,b");
6946 MOVA (aopGet (right, offset, FALSE, FALSE));
6947 emitcode("anl", "a,b");
6950 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6952 MOVB (aopGet (left, offset, FALSE, FALSE));
6953 MOVA (aopGet (right, offset, FALSE, FALSE));
6954 emitcode ("anl", "a,b");
6956 else if (aopGetUsesAcc (left, offset))
6958 MOVA (aopGet (left, offset, FALSE, FALSE));
6959 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6963 MOVA (aopGet (right, offset, FALSE, FALSE));
6964 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6966 aopPut (result, "a", offset);
6972 freeAsmop (result, NULL, ic, TRUE);
6973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6974 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6977 /*-----------------------------------------------------------------*/
6978 /* genOr - code for or */
6979 /*-----------------------------------------------------------------*/
6981 genOr (iCode * ic, iCode * ifx)
6983 operand *left, *right, *result;
6984 int size, offset = 0;
6985 unsigned long lit = 0L;
6988 D (emitcode (";", "genOr"));
6990 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6991 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6992 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6995 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6997 AOP_TYPE (left), AOP_TYPE (right));
6998 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7000 AOP_SIZE (left), AOP_SIZE (right));
7003 /* if left is a literal & right is not then exchange them */
7004 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7005 AOP_NEEDSACC (left))
7007 operand *tmp = right;
7012 /* if result = right then exchange them */
7013 if (sameRegs (AOP (result), AOP (right)))
7015 operand *tmp = right;
7020 /* if right is bit then exchange them */
7021 if (AOP_TYPE (right) == AOP_CRY &&
7022 AOP_TYPE (left) != AOP_CRY)
7024 operand *tmp = right;
7028 if (AOP_TYPE (right) == AOP_LIT)
7029 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7031 size = AOP_SIZE (result);
7035 if (AOP_TYPE (left) == AOP_CRY)
7037 if (AOP_TYPE (right) == AOP_LIT)
7039 // c = bit | literal;
7042 // lit != 0 => result = 1
7043 if (AOP_TYPE (result) == AOP_CRY)
7046 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7048 continueIfTrue (ifx);
7051 emitcode ("setb", "c");
7055 // lit == 0 => result = left
7056 if (size && sameRegs (AOP (result), AOP (left)))
7058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7063 if (AOP_TYPE (right) == AOP_CRY)
7066 if (IS_OP_ACCUSE (left))
7068 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7072 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7073 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7079 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7081 symbol *tlbl = newiTempLabel (NULL);
7082 emitcode ("jb", "%s,%05d$",
7083 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7085 emitcode ("jnz", "%05d$", tlbl->key + 100);
7086 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7092 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7101 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7102 genIfxJump (ifx, "c", left, right, result);
7106 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7107 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7108 if ((AOP_TYPE (right) == AOP_LIT) &&
7109 (AOP_TYPE (result) == AOP_CRY) &&
7110 (AOP_TYPE (left) != AOP_CRY))
7116 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7118 continueIfTrue (ifx);
7123 // lit = 0, result = boolean(left)
7125 emitcode ("setb", "c");
7129 symbol *tlbl = newiTempLabel (NULL);
7130 emitcode ("jnz", "%05d$", tlbl->key + 100);
7136 genIfxJump (ifx, "a", left, right, result);
7144 /* if left is same as result */
7145 if (sameRegs (AOP (result), AOP (left)))
7147 for (; size--; offset++)
7149 if (AOP_TYPE (right) == AOP_LIT)
7151 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7154 /* dummy read of volatile operand */
7155 if (isOperandVolatile (left, FALSE))
7156 MOVA (aopGet (left, offset, FALSE, FALSE));
7160 else if (bytelit == 0x0FF)
7162 aopPut (result, "#0xFF", offset);
7164 else if (IS_AOP_PREG (left))
7166 MOVA (aopGet (left, offset, FALSE, TRUE));
7167 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7168 aopPut (result, "a", offset);
7172 emitcode ("orl", "%s,%s",
7173 aopGet (left, offset, FALSE, TRUE),
7174 aopGet (right, offset, FALSE, FALSE));
7179 if (AOP_TYPE (left) == AOP_ACC)
7182 emitcode("mov", "a,b");
7183 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7185 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7187 MOVB (aopGet (left, offset, FALSE, FALSE));
7188 MOVA (aopGet (right, offset, FALSE, FALSE));
7189 emitcode ("orl", "a,b");
7190 aopPut (result, "a", offset);
7192 else if (aopGetUsesAcc (left, offset))
7194 MOVA (aopGet (left, offset, FALSE, FALSE));
7195 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7196 aopPut (result, "a", offset);
7200 MOVA (aopGet (right, offset, FALSE, FALSE));
7201 if (IS_AOP_PREG (left))
7203 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7204 aopPut (result, "a", offset);
7208 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7216 // left & result in different registers
7217 if (AOP_TYPE (result) == AOP_CRY)
7220 // if(size), result in bit
7221 // if(!size && ifx), conditional oper: if(left | right)
7222 symbol *tlbl = newiTempLabel (NULL);
7223 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7225 emitcode ("setb", "c");
7228 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7229 && AOP_TYPE(left)==AOP_ACC)
7232 emitcode("mov", "a,b");
7233 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7235 else if (AOP_TYPE(left)==AOP_ACC)
7239 bool pushedB = pushB ();
7240 emitcode("mov", "b,a");
7241 MOVA (aopGet (right, offset, FALSE, FALSE));
7242 emitcode("orl", "a,b");
7247 MOVA (aopGet (right, offset, FALSE, FALSE));
7248 emitcode("orl", "a,b");
7251 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7253 MOVB (aopGet (left, offset, FALSE, FALSE));
7254 MOVA (aopGet (right, offset, FALSE, FALSE));
7255 emitcode ("orl", "a,b");
7257 else if (aopGetUsesAcc (left, offset))
7259 MOVA (aopGet (left, offset, FALSE, FALSE));
7260 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7264 MOVA (aopGet (right, offset, FALSE, FALSE));
7265 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7268 emitcode ("jnz", "%05d$", tlbl->key + 100);
7278 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7284 for (; (size--); offset++)
7287 // result = left | right
7288 if (AOP_TYPE (right) == AOP_LIT)
7290 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7294 aopGet (left, offset, FALSE, FALSE),
7298 else if (bytelit == 0x0FF)
7300 /* dummy read of volatile operand */
7301 if (isOperandVolatile (left, FALSE))
7302 MOVA (aopGet (left, offset, FALSE, FALSE));
7303 aopPut (result, "#0xFF", offset);
7307 // faster than result <- left, orl result,right
7308 // and better if result is SFR
7309 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7310 && AOP_TYPE(left)==AOP_ACC)
7313 emitcode("mov", "a,b");
7314 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7316 else if (AOP_TYPE(left)==AOP_ACC)
7320 bool pushedB = pushB ();
7321 emitcode("mov", "b,a");
7322 MOVA (aopGet (right, offset, FALSE, FALSE));
7323 emitcode("orl", "a,b");
7328 MOVA (aopGet (right, offset, FALSE, FALSE));
7329 emitcode("orl", "a,b");
7332 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7334 MOVB (aopGet (left, offset, FALSE, FALSE));
7335 MOVA (aopGet (right, offset, FALSE, FALSE));
7336 emitcode ("orl", "a,b");
7338 else if (aopGetUsesAcc (left, offset))
7340 MOVA (aopGet (left, offset, FALSE, FALSE));
7341 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7345 MOVA (aopGet (right, offset, FALSE, FALSE));
7346 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7348 aopPut (result, "a", offset);
7354 freeAsmop (result, NULL, ic, TRUE);
7355 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7359 /*-----------------------------------------------------------------*/
7360 /* genXor - code for xclusive or */
7361 /*-----------------------------------------------------------------*/
7363 genXor (iCode * ic, iCode * ifx)
7365 operand *left, *right, *result;
7366 int size, offset = 0;
7367 unsigned long lit = 0L;
7370 D (emitcode (";", "genXor"));
7372 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7373 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7374 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7377 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7379 AOP_TYPE (left), AOP_TYPE (right));
7380 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7382 AOP_SIZE (left), AOP_SIZE (right));
7385 /* if left is a literal & right is not ||
7386 if left needs acc & right does not */
7387 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7388 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7390 operand *tmp = right;
7395 /* if result = right then exchange them */
7396 if (sameRegs (AOP (result), AOP (right)))
7398 operand *tmp = right;
7403 /* if right is bit then exchange them */
7404 if (AOP_TYPE (right) == AOP_CRY &&
7405 AOP_TYPE (left) != AOP_CRY)
7407 operand *tmp = right;
7412 if (AOP_TYPE (right) == AOP_LIT)
7413 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7415 size = AOP_SIZE (result);
7419 if (AOP_TYPE (left) == AOP_CRY)
7421 if (AOP_TYPE (right) == AOP_LIT)
7423 // c = bit & literal;
7426 // lit>>1 != 0 => result = 1
7427 if (AOP_TYPE (result) == AOP_CRY)
7430 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7432 continueIfTrue (ifx);
7435 emitcode ("setb", "c");
7442 // lit == 0, result = left
7443 if (size && sameRegs (AOP (result), AOP (left)))
7445 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7449 // lit == 1, result = not(left)
7450 if (size && sameRegs (AOP (result), AOP (left)))
7452 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7457 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7458 emitcode ("cpl", "c");
7466 symbol *tlbl = newiTempLabel (NULL);
7467 if (AOP_TYPE (right) == AOP_CRY)
7470 if (IS_OP_ACCUSE (left))
7471 {// left already is in the carry
7472 operand *tmp = right;
7486 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7487 emitcode ("cpl", "c");
7495 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7496 genIfxJump (ifx, "c", left, right, result);
7500 /* if left is same as result */
7501 if (sameRegs (AOP (result), AOP (left)))
7503 for (; size--; offset++)
7505 if (AOP_TYPE (right) == AOP_LIT)
7507 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7510 /* dummy read of volatile operand */
7511 if (isOperandVolatile (left, FALSE))
7512 MOVA (aopGet (left, offset, FALSE, FALSE));
7516 else if (IS_AOP_PREG (left))
7518 MOVA (aopGet (left, offset, FALSE, TRUE));
7519 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7520 aopPut (result, "a", offset);
7524 emitcode ("xrl", "%s,%s",
7525 aopGet (left, offset, FALSE, TRUE),
7526 aopGet (right, offset, FALSE, FALSE));
7531 if (AOP_TYPE (left) == AOP_ACC)
7534 emitcode("mov", "a,b");
7535 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7537 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7539 MOVB (aopGet (left, offset, FALSE, FALSE));
7540 MOVA (aopGet (right, offset, FALSE, FALSE));
7541 emitcode ("xrl", "a,b");
7542 aopPut (result, "a", offset);
7544 else if (aopGetUsesAcc (left, offset))
7546 MOVA (aopGet (left, offset, FALSE, FALSE));
7547 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7548 aopPut (result, "a", offset);
7552 MOVA (aopGet (right, offset, FALSE, FALSE));
7553 if (IS_AOP_PREG (left))
7555 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7556 aopPut (result, "a", offset);
7559 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7566 // left & result in different registers
7567 if (AOP_TYPE (result) == AOP_CRY)
7570 // if(size), result in bit
7571 // if(!size && ifx), conditional oper: if(left ^ right)
7572 symbol *tlbl = newiTempLabel (NULL);
7573 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7576 emitcode ("setb", "c");
7579 if ((AOP_TYPE (right) == AOP_LIT) &&
7580 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7582 MOVA (aopGet (left, offset, FALSE, FALSE));
7584 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7585 && AOP_TYPE(left)==AOP_ACC)
7588 emitcode("mov", "a,b");
7589 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7591 else if (AOP_TYPE(left)==AOP_ACC)
7595 bool pushedB = pushB ();
7596 emitcode("mov", "b,a");
7597 MOVA (aopGet (right, offset, FALSE, FALSE));
7598 emitcode("xrl", "a,b");
7603 MOVA (aopGet (right, offset, FALSE, FALSE));
7604 emitcode("xrl", "a,b");
7607 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7609 MOVB (aopGet (left, offset, FALSE, FALSE));
7610 MOVA (aopGet (right, offset, FALSE, FALSE));
7611 emitcode ("xrl", "a,b");
7613 else if (aopGetUsesAcc (left, offset))
7615 MOVA (aopGet (left, offset, FALSE, FALSE));
7616 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7620 MOVA (aopGet (right, offset, FALSE, FALSE));
7621 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7624 emitcode ("jnz", "%05d$", tlbl->key + 100);
7634 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7638 for (; (size--); offset++)
7641 // result = left ^ right
7642 if (AOP_TYPE (right) == AOP_LIT)
7644 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7648 aopGet (left, offset, FALSE, FALSE),
7653 // faster than result <- left, xrl result,right
7654 // and better if result is SFR
7655 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7656 && AOP_TYPE(left)==AOP_ACC)
7659 emitcode("mov", "a,b");
7660 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7662 else if (AOP_TYPE(left)==AOP_ACC)
7666 bool pushedB = pushB ();
7667 emitcode("mov", "b,a");
7668 MOVA (aopGet (right, offset, FALSE, FALSE));
7669 emitcode("xrl", "a,b");
7674 MOVA (aopGet (right, offset, FALSE, FALSE));
7675 emitcode("xrl", "a,b");
7678 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7680 MOVB (aopGet (left, offset, FALSE, FALSE));
7681 MOVA (aopGet (right, offset, FALSE, FALSE));
7682 emitcode ("xrl", "a,b");
7684 else if (aopGetUsesAcc (left, offset))
7686 MOVA (aopGet (left, offset, FALSE, FALSE));
7687 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7691 MOVA (aopGet (right, offset, FALSE, FALSE));
7692 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7694 aopPut (result, "a", offset);
7700 freeAsmop (result, NULL, ic, TRUE);
7701 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7702 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7705 /*-----------------------------------------------------------------*/
7706 /* genInline - write the inline code out */
7707 /*-----------------------------------------------------------------*/
7709 genInline (iCode * ic)
7711 char *buffer, *bp, *bp1;
7712 bool inComment = FALSE;
7714 D (emitcode (";", "genInline"));
7716 _G.inLine += (!options.asmpeep);
7718 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7720 /* emit each line as a code */
7738 /* Add \n for labels, not dirs such as c:\mydir */
7739 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7757 _G.inLine -= (!options.asmpeep);
7760 /*-----------------------------------------------------------------*/
7761 /* genRRC - rotate right with carry */
7762 /*-----------------------------------------------------------------*/
7766 operand *left, *result;
7770 D (emitcode (";", "genRRC"));
7772 /* rotate right with carry */
7773 left = IC_LEFT (ic);
7774 result = IC_RESULT (ic);
7775 aopOp (left, ic, FALSE);
7776 aopOp (result, ic, FALSE);
7778 /* move it to the result */
7779 size = AOP_SIZE (result);
7781 if (size == 1) { /* special case for 1 byte */
7782 l = aopGet (left, offset, FALSE, FALSE);
7784 emitcode ("rr", "a");
7787 /* no need to clear carry, bit7 will be written later */
7790 l = aopGet (left, offset, FALSE, FALSE);
7792 emitcode ("rrc", "a");
7793 if (AOP_SIZE (result) > 1)
7794 aopPut (result, "a", offset--);
7796 /* now we need to put the carry into the
7797 highest order byte of the result */
7798 if (AOP_SIZE (result) > 1)
7800 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7803 emitcode ("mov", "acc.7,c");
7805 aopPut (result, "a", AOP_SIZE (result) - 1);
7806 freeAsmop (result, NULL, ic, TRUE);
7807 freeAsmop (left, NULL, ic, TRUE);
7810 /*-----------------------------------------------------------------*/
7811 /* genRLC - generate code for rotate left with carry */
7812 /*-----------------------------------------------------------------*/
7816 operand *left, *result;
7820 D (emitcode (";", "genRLC"));
7822 /* rotate right with carry */
7823 left = IC_LEFT (ic);
7824 result = IC_RESULT (ic);
7825 aopOp (left, ic, FALSE);
7826 aopOp (result, ic, FALSE);
7828 /* move it to the result */
7829 size = AOP_SIZE (result);
7833 l = aopGet (left, offset, FALSE, FALSE);
7835 if (size == 0) { /* special case for 1 byte */
7839 emitcode("rlc","a"); /* bit0 will be written later */
7840 if (AOP_SIZE (result) > 1)
7842 aopPut (result, "a", offset++);
7847 l = aopGet (left, offset, FALSE, FALSE);
7849 emitcode ("rlc", "a");
7850 if (AOP_SIZE (result) > 1)
7851 aopPut (result, "a", offset++);
7854 /* now we need to put the carry into the
7855 highest order byte of the result */
7856 if (AOP_SIZE (result) > 1)
7858 l = aopGet (result, 0, FALSE, FALSE);
7861 emitcode ("mov", "acc.0,c");
7863 aopPut (result, "a", 0);
7864 freeAsmop (result, NULL, ic, TRUE);
7865 freeAsmop (left, NULL, ic, TRUE);
7868 /*-----------------------------------------------------------------*/
7869 /* genGetHbit - generates code get highest order bit */
7870 /*-----------------------------------------------------------------*/
7872 genGetHbit (iCode * ic)
7874 operand *left, *result;
7876 D (emitcode (";", "genGetHbit"));
7878 left = IC_LEFT (ic);
7879 result = IC_RESULT (ic);
7880 aopOp (left, ic, FALSE);
7881 aopOp (result, ic, FALSE);
7883 /* get the highest order byte into a */
7884 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7885 if (AOP_TYPE (result) == AOP_CRY)
7887 emitcode ("rlc", "a");
7892 emitcode ("rl", "a");
7893 emitcode ("anl", "a,#0x01");
7897 freeAsmop (result, NULL, ic, TRUE);
7898 freeAsmop (left, NULL, ic, TRUE);
7901 /*-----------------------------------------------------------------*/
7902 /* genGetAbit - generates code get a single bit */
7903 /*-----------------------------------------------------------------*/
7905 genGetAbit (iCode * ic)
7907 operand *left, *right, *result;
7910 D (emitcode (";", "genGetAbit"));
7912 left = IC_LEFT (ic);
7913 right = IC_RIGHT (ic);
7914 result = IC_RESULT (ic);
7915 aopOp (left, ic, FALSE);
7916 aopOp (right, ic, FALSE);
7917 aopOp (result, ic, FALSE);
7919 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7921 /* get the needed byte into a */
7922 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7924 if (AOP_TYPE (result) == AOP_CRY)
7927 emitcode ("rlc", "a");
7928 else if ((shCount) == 0)
7929 emitcode ("rrc", "a");
7931 emitcode ("mov", "c,acc[%d]", shCount);
7939 emitcode ("rr", "a");
7942 emitcode ("rr", "a");
7945 emitcode ("anl", "a,#0x01");
7949 emitcode ("mov", "c,acc[%d]", shCount);
7950 emitcode ("clr", "a");
7951 emitcode ("rlc", "a");
7954 emitcode ("swap", "a");
7955 emitcode ("anl", "a,#0x01");
7958 emitcode ("rl", "a");
7961 emitcode ("rl", "a");
7962 emitcode ("anl", "a,#0x01");
7968 freeAsmop (result, NULL, ic, TRUE);
7969 freeAsmop (right, NULL, ic, TRUE);
7970 freeAsmop (left, NULL, ic, TRUE);
7973 /*-----------------------------------------------------------------*/
7974 /* genGetByte - generates code get a single byte */
7975 /*-----------------------------------------------------------------*/
7977 genGetByte (iCode * ic)
7979 operand *left, *right, *result;
7982 D (emitcode (";", "genGetByte"));
7984 left = IC_LEFT (ic);
7985 right = IC_RIGHT (ic);
7986 result = IC_RESULT (ic);
7987 aopOp (left, ic, FALSE);
7988 aopOp (right, ic, FALSE);
7989 aopOp (result, ic, FALSE);
7991 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
7993 aopGet (left, offset, FALSE, FALSE),
7996 freeAsmop (result, NULL, ic, TRUE);
7997 freeAsmop (right, NULL, ic, TRUE);
7998 freeAsmop (left, NULL, ic, TRUE);
8001 /*-----------------------------------------------------------------*/
8002 /* genGetWord - generates code get two bytes */
8003 /*-----------------------------------------------------------------*/
8005 genGetWord (iCode * ic)
8007 operand *left, *right, *result;
8010 D (emitcode (";", "genGetWord"));
8012 left = IC_LEFT (ic);
8013 right = IC_RIGHT (ic);
8014 result = IC_RESULT (ic);
8015 aopOp (left, ic, FALSE);
8016 aopOp (right, ic, FALSE);
8017 aopOp (result, ic, FALSE);
8019 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8021 aopGet (left, offset, FALSE, FALSE),
8024 aopGet (left, offset+1, FALSE, FALSE),
8027 freeAsmop (result, NULL, ic, TRUE);
8028 freeAsmop (right, NULL, ic, TRUE);
8029 freeAsmop (left, NULL, ic, TRUE);
8032 /*-----------------------------------------------------------------*/
8033 /* genSwap - generates code to swap nibbles or bytes */
8034 /*-----------------------------------------------------------------*/
8036 genSwap (iCode * ic)
8038 operand *left, *result;
8040 D(emitcode (";", "genSwap"));
8042 left = IC_LEFT (ic);
8043 result = IC_RESULT (ic);
8044 aopOp (left, ic, FALSE);
8045 aopOp (result, ic, FALSE);
8047 switch (AOP_SIZE (left))
8049 case 1: /* swap nibbles in byte */
8050 MOVA (aopGet (left, 0, FALSE, FALSE));
8051 emitcode ("swap", "a");
8052 aopPut (result, "a", 0);
8054 case 2: /* swap bytes in word */
8055 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8057 MOVA (aopGet (left, 0, FALSE, FALSE));
8058 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8059 aopPut (result, "a", 1);
8061 else if (operandsEqu (left, result))
8064 bool pushedB = FALSE, leftInB = FALSE;
8066 MOVA (aopGet (left, 0, FALSE, FALSE));
8067 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8070 emitcode ("mov", "b,a");
8074 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8075 aopPut (result, reg, 1);
8082 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8083 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8087 wassertl(FALSE, "unsupported SWAP operand size");
8090 freeAsmop (result, NULL, ic, TRUE);
8091 freeAsmop (left, NULL, ic, TRUE);
8094 /*-----------------------------------------------------------------*/
8095 /* AccRol - rotate left accumulator by known count */
8096 /*-----------------------------------------------------------------*/
8098 AccRol (int shCount)
8100 shCount &= 0x0007; // shCount : 0..7
8107 emitcode ("rl", "a");
8110 emitcode ("rl", "a");
8111 emitcode ("rl", "a");
8114 emitcode ("swap", "a");
8115 emitcode ("rr", "a");
8118 emitcode ("swap", "a");
8121 emitcode ("swap", "a");
8122 emitcode ("rl", "a");
8125 emitcode ("rr", "a");
8126 emitcode ("rr", "a");
8129 emitcode ("rr", "a");
8134 /*-----------------------------------------------------------------*/
8135 /* AccLsh - left shift accumulator by known count */
8136 /*-----------------------------------------------------------------*/
8138 AccLsh (int shCount)
8143 emitcode ("add", "a,acc");
8144 else if (shCount == 2)
8146 emitcode ("add", "a,acc");
8147 emitcode ("add", "a,acc");
8151 /* rotate left accumulator */
8153 /* and kill the lower order bits */
8154 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8159 /*-----------------------------------------------------------------*/
8160 /* AccRsh - right shift accumulator by known count */
8161 /*-----------------------------------------------------------------*/
8163 AccRsh (int shCount)
8170 emitcode ("rrc", "a");
8174 /* rotate right accumulator */
8175 AccRol (8 - shCount);
8176 /* and kill the higher order bits */
8177 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8182 /*-----------------------------------------------------------------*/
8183 /* AccSRsh - signed right shift accumulator by known count */
8184 /*-----------------------------------------------------------------*/
8186 AccSRsh (int shCount)
8193 emitcode ("mov", "c,acc.7");
8194 emitcode ("rrc", "a");
8196 else if (shCount == 2)
8198 emitcode ("mov", "c,acc.7");
8199 emitcode ("rrc", "a");
8200 emitcode ("mov", "c,acc.7");
8201 emitcode ("rrc", "a");
8205 tlbl = newiTempLabel (NULL);
8206 /* rotate right accumulator */
8207 AccRol (8 - shCount);
8208 /* and kill the higher order bits */
8209 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8210 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8211 emitcode ("orl", "a,#0x%02x",
8212 (unsigned char) ~SRMask[shCount]);
8218 /*-----------------------------------------------------------------*/
8219 /* shiftR1Left2Result - shift right one byte from left to result */
8220 /*-----------------------------------------------------------------*/
8222 shiftR1Left2Result (operand * left, int offl,
8223 operand * result, int offr,
8224 int shCount, int sign)
8226 MOVA (aopGet (left, offl, FALSE, FALSE));
8227 /* shift right accumulator */
8232 aopPut (result, "a", offr);
8235 /*-----------------------------------------------------------------*/
8236 /* shiftL1Left2Result - shift left one byte from left to result */
8237 /*-----------------------------------------------------------------*/
8239 shiftL1Left2Result (operand * left, int offl,
8240 operand * result, int offr, int shCount)
8243 l = aopGet (left, offl, FALSE, FALSE);
8245 /* shift left accumulator */
8247 aopPut (result, "a", offr);
8250 /*-----------------------------------------------------------------*/
8251 /* movLeft2Result - move byte from left to result */
8252 /*-----------------------------------------------------------------*/
8254 movLeft2Result (operand * left, int offl,
8255 operand * result, int offr, int sign)
8258 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8260 l = aopGet (left, offl, FALSE, FALSE);
8262 if (*l == '@' && (IS_AOP_PREG (result)))
8264 emitcode ("mov", "a,%s", l);
8265 aopPut (result, "a", offr);
8271 aopPut (result, l, offr);
8275 /* MSB sign in acc.7 ! */
8276 if (getDataSize (left) == offl + 1)
8279 aopPut (result, "a", offr);
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8288 /*-----------------------------------------------------------------*/
8292 emitcode ("rrc", "a");
8293 emitcode ("xch", "a,%s", x);
8294 emitcode ("rrc", "a");
8295 emitcode ("xch", "a,%s", x);
8298 /*-----------------------------------------------------------------*/
8299 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8300 /*-----------------------------------------------------------------*/
8304 emitcode ("xch", "a,%s", x);
8305 emitcode ("rlc", "a");
8306 emitcode ("xch", "a,%s", x);
8307 emitcode ("rlc", "a");
8310 /*-----------------------------------------------------------------*/
8311 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8312 /*-----------------------------------------------------------------*/
8316 emitcode ("xch", "a,%s", x);
8317 emitcode ("add", "a,acc");
8318 emitcode ("xch", "a,%s", x);
8319 emitcode ("rlc", "a");
8322 /*-----------------------------------------------------------------*/
8323 /* AccAXLsh - left shift a:x by known count (0..7) */
8324 /*-----------------------------------------------------------------*/
8326 AccAXLsh (char *x, int shCount)
8341 case 5: // AAAAABBB:CCCCCDDD
8343 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8345 emitcode ("anl", "a,#0x%02x",
8346 SLMask[shCount]); // BBB00000:CCCCCDDD
8348 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8350 AccRol (shCount); // DDDCCCCC:BBB00000
8352 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8354 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8356 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8358 emitcode ("anl", "a,#0x%02x",
8359 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8361 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8363 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8366 case 6: // AAAAAABB:CCCCCCDD
8367 emitcode ("anl", "a,#0x%02x",
8368 SRMask[shCount]); // 000000BB:CCCCCCDD
8369 emitcode ("mov", "c,acc.0"); // c = B
8370 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8372 AccAXRrl1 (x); // BCCCCCCD:D000000B
8373 AccAXRrl1 (x); // BBCCCCCC:DD000000
8375 emitcode("rrc","a");
8376 emitcode("xch","a,%s", x);
8377 emitcode("rrc","a");
8378 emitcode("mov","c,acc.0"); //<< get correct bit
8379 emitcode("xch","a,%s", x);
8381 emitcode("rrc","a");
8382 emitcode("xch","a,%s", x);
8383 emitcode("rrc","a");
8384 emitcode("xch","a,%s", x);
8387 case 7: // a:x <<= 7
8389 emitcode ("anl", "a,#0x%02x",
8390 SRMask[shCount]); // 0000000B:CCCCCCCD
8392 emitcode ("mov", "c,acc.0"); // c = B
8394 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8396 AccAXRrl1 (x); // BCCCCCCC:D0000000
8404 /*-----------------------------------------------------------------*/
8405 /* AccAXRsh - right shift a:x known count (0..7) */
8406 /*-----------------------------------------------------------------*/
8408 AccAXRsh (char *x, int shCount)
8416 AccAXRrl1 (x); // 0->a:x
8421 AccAXRrl1 (x); // 0->a:x
8424 AccAXRrl1 (x); // 0->a:x
8429 case 5: // AAAAABBB:CCCCCDDD = a:x
8431 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8433 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8435 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8437 emitcode ("anl", "a,#0x%02x",
8438 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8440 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8442 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8444 emitcode ("anl", "a,#0x%02x",
8445 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8447 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8449 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8451 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8454 case 6: // AABBBBBB:CCDDDDDD
8456 emitcode ("mov", "c,acc.7");
8457 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8459 emitcode ("mov", "c,acc.7");
8460 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8462 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8464 emitcode ("anl", "a,#0x%02x",
8465 SRMask[shCount]); // 000000AA:BBBBBBCC
8468 case 7: // ABBBBBBB:CDDDDDDD
8470 emitcode ("mov", "c,acc.7"); // c = A
8472 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8474 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8476 emitcode ("anl", "a,#0x%02x",
8477 SRMask[shCount]); // 0000000A:BBBBBBBC
8485 /*-----------------------------------------------------------------*/
8486 /* AccAXRshS - right shift signed a:x known count (0..7) */
8487 /*-----------------------------------------------------------------*/
8489 AccAXRshS (char *x, int shCount)
8497 emitcode ("mov", "c,acc.7");
8498 AccAXRrl1 (x); // s->a:x
8502 emitcode ("mov", "c,acc.7");
8503 AccAXRrl1 (x); // s->a:x
8505 emitcode ("mov", "c,acc.7");
8506 AccAXRrl1 (x); // s->a:x
8511 case 5: // AAAAABBB:CCCCCDDD = a:x
8513 tlbl = newiTempLabel (NULL);
8514 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8516 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8518 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8520 emitcode ("anl", "a,#0x%02x",
8521 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8523 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8525 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8527 emitcode ("anl", "a,#0x%02x",
8528 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8530 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8532 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8534 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8536 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8537 emitcode ("orl", "a,#0x%02x",
8538 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8541 break; // SSSSAAAA:BBBCCCCC
8543 case 6: // AABBBBBB:CCDDDDDD
8545 tlbl = newiTempLabel (NULL);
8546 emitcode ("mov", "c,acc.7");
8547 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8549 emitcode ("mov", "c,acc.7");
8550 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8552 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8554 emitcode ("anl", "a,#0x%02x",
8555 SRMask[shCount]); // 000000AA:BBBBBBCC
8557 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8558 emitcode ("orl", "a,#0x%02x",
8559 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8563 case 7: // ABBBBBBB:CDDDDDDD
8565 tlbl = newiTempLabel (NULL);
8566 emitcode ("mov", "c,acc.7"); // c = A
8568 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8570 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8572 emitcode ("anl", "a,#0x%02x",
8573 SRMask[shCount]); // 0000000A:BBBBBBBC
8575 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8576 emitcode ("orl", "a,#0x%02x",
8577 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8586 /*-----------------------------------------------------------------*/
8587 /* shiftL2Left2Result - shift left two bytes from left to result */
8588 /*-----------------------------------------------------------------*/
8590 shiftL2Left2Result (operand * left, int offl,
8591 operand * result, int offr, int shCount)
8594 bool pushedB = FALSE;
8597 if (sameRegs (AOP (result), AOP (left)) &&
8598 ((offl + MSB16) == offr))
8600 /* don't crash result[offr] */
8601 MOVA (aopGet (left, offl, FALSE, FALSE));
8602 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8603 usedB = !strncmp(x, "b", 1);
8605 else if (aopGetUsesAcc (result, offr))
8607 movLeft2Result (left, offl, result, offr, 0);
8610 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8611 MOVA (aopGet (result, offr, FALSE, FALSE));
8612 emitcode ("xch", "a,b");
8617 movLeft2Result (left, offl, result, offr, 0);
8618 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8619 x = aopGet (result, offr, FALSE, FALSE);
8621 /* ax << shCount (x = lsb(result)) */
8622 AccAXLsh (x, shCount);
8625 emitcode ("xch", "a,b");
8626 aopPut (result, "a", offr);
8627 aopPut (result, "b", offr + MSB16);
8632 aopPut (result, "a", offr + MSB16);
8637 /*-----------------------------------------------------------------*/
8638 /* shiftR2Left2Result - shift right two bytes from left to result */
8639 /*-----------------------------------------------------------------*/
8641 shiftR2Left2Result (operand * left, int offl,
8642 operand * result, int offr,
8643 int shCount, int sign)
8646 bool pushedB = FALSE;
8649 if (sameRegs (AOP (result), AOP (left)) &&
8650 ((offl + MSB16) == offr))
8652 /* don't crash result[offr] */
8653 MOVA (aopGet (left, offl, FALSE, FALSE));
8654 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8655 usedB = !strncmp(x, "b", 1);
8657 else if (aopGetUsesAcc (result, offr))
8659 movLeft2Result (left, offl, result, offr, 0);
8662 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8663 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8668 movLeft2Result (left, offl, result, offr, 0);
8669 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8670 x = aopGet (result, offr, FALSE, FALSE);
8672 /* a:x >> shCount (x = lsb(result)) */
8674 AccAXRshS (x, shCount);
8676 AccAXRsh (x, shCount);
8679 emitcode ("xch", "a,b");
8680 aopPut (result, "a", offr);
8681 emitcode ("xch", "a,b");
8684 if (getDataSize (result) > 1)
8685 aopPut (result, "a", offr + MSB16);
8688 /*-----------------------------------------------------------------*/
8689 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8690 /*-----------------------------------------------------------------*/
8692 shiftLLeftOrResult (operand * left, int offl,
8693 operand * result, int offr, int shCount)
8695 MOVA (aopGet (left, offl, FALSE, FALSE));
8696 /* shift left accumulator */
8698 /* or with result */
8699 if (aopGetUsesAcc (result, offr))
8701 emitcode ("xch", "a,b");
8702 MOVA (aopGet (result, offr, FALSE, FALSE));
8703 emitcode ("orl", "a,b");
8707 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8709 /* back to result */
8710 aopPut (result, "a", offr);
8713 /*-----------------------------------------------------------------*/
8714 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8715 /*-----------------------------------------------------------------*/
8717 shiftRLeftOrResult (operand * left, int offl,
8718 operand * result, int offr, int shCount)
8720 MOVA (aopGet (left, offl, FALSE, FALSE));
8721 /* shift right accumulator */
8723 /* or with result */
8724 if (aopGetUsesAcc(result, offr))
8726 emitcode ("xch", "a,b");
8727 MOVA (aopGet (result, offr, FALSE, FALSE));
8728 emitcode ("orl", "a,b");
8732 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8734 /* back to result */
8735 aopPut (result, "a", offr);
8738 /*-----------------------------------------------------------------*/
8739 /* genlshOne - left shift a one byte quantity by known count */
8740 /*-----------------------------------------------------------------*/
8742 genlshOne (operand * result, operand * left, int shCount)
8744 D (emitcode (";", "genlshOne"));
8746 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8749 /*-----------------------------------------------------------------*/
8750 /* genlshTwo - left shift two bytes by known amount != 0 */
8751 /*-----------------------------------------------------------------*/
8753 genlshTwo (operand * result, operand * left, int shCount)
8757 D (emitcode (";", "genlshTwo"));
8759 size = getDataSize (result);
8761 /* if shCount >= 8 */
8769 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8771 movLeft2Result (left, LSB, result, MSB16, 0);
8773 aopPut (result, zero, LSB);
8776 /* 1 <= shCount <= 7 */
8780 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8782 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8786 /*-----------------------------------------------------------------*/
8787 /* shiftLLong - shift left one long from left to result */
8788 /* offl = LSB or MSB16 */
8789 /*-----------------------------------------------------------------*/
8791 shiftLLong (operand * left, operand * result, int offr)
8794 int size = AOP_SIZE (result);
8796 if (size >= LSB + offr)
8798 l = aopGet (left, LSB, FALSE, FALSE);
8800 emitcode ("add", "a,acc");
8801 if (sameRegs (AOP (left), AOP (result)) &&
8802 size >= MSB16 + offr && offr != LSB)
8803 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8805 aopPut (result, "a", LSB + offr);
8808 if (size >= MSB16 + offr)
8810 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8812 l = aopGet (left, MSB16, FALSE, FALSE);
8815 emitcode ("rlc", "a");
8816 if (sameRegs (AOP (left), AOP (result)) &&
8817 size >= MSB24 + offr && offr != LSB)
8818 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8820 aopPut (result, "a", MSB16 + offr);
8823 if (size >= MSB24 + offr)
8825 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8827 l = aopGet (left, MSB24, FALSE, FALSE);
8830 emitcode ("rlc", "a");
8831 if (sameRegs (AOP (left), AOP (result)) &&
8832 size >= MSB32 + offr && offr != LSB)
8833 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8835 aopPut (result, "a", MSB24 + offr);
8838 if (size > MSB32 + offr)
8840 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8842 l = aopGet (left, MSB32, FALSE, FALSE);
8845 emitcode ("rlc", "a");
8846 aopPut (result, "a", MSB32 + offr);
8849 aopPut (result, zero, LSB);
8852 /*-----------------------------------------------------------------*/
8853 /* genlshFour - shift four byte by a known amount != 0 */
8854 /*-----------------------------------------------------------------*/
8856 genlshFour (operand * result, operand * left, int shCount)
8860 D (emitcode (";", "genlshFour"));
8862 size = AOP_SIZE (result);
8864 /* if shifting more that 3 bytes */
8869 /* lowest order of left goes to the highest
8870 order of the destination */
8871 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8873 movLeft2Result (left, LSB, result, MSB32, 0);
8874 aopPut (result, zero, LSB);
8875 aopPut (result, zero, MSB16);
8876 aopPut (result, zero, MSB24);
8880 /* more than two bytes */
8881 else if (shCount >= 16)
8883 /* lower order two bytes goes to higher order two bytes */
8885 /* if some more remaining */
8887 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8890 movLeft2Result (left, MSB16, result, MSB32, 0);
8891 movLeft2Result (left, LSB, result, MSB24, 0);
8893 aopPut (result, zero, MSB16);
8894 aopPut (result, zero, LSB);
8898 /* if more than 1 byte */
8899 else if (shCount >= 8)
8901 /* lower order three bytes goes to higher order three bytes */
8906 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8908 movLeft2Result (left, LSB, result, MSB16, 0);
8914 movLeft2Result (left, MSB24, result, MSB32, 0);
8915 movLeft2Result (left, MSB16, result, MSB24, 0);
8916 movLeft2Result (left, LSB, result, MSB16, 0);
8917 aopPut (result, zero, LSB);
8919 else if (shCount == 1)
8920 shiftLLong (left, result, MSB16);
8923 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8924 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8925 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8926 aopPut (result, zero, LSB);
8931 /* 1 <= shCount <= 7 */
8932 else if (shCount <= 2)
8934 shiftLLong (left, result, LSB);
8936 shiftLLong (result, result, LSB);
8938 /* 3 <= shCount <= 7, optimize */
8941 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8942 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8943 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8947 /*-----------------------------------------------------------------*/
8948 /* genLeftShiftLiteral - left shifting by known count */
8949 /*-----------------------------------------------------------------*/
8951 genLeftShiftLiteral (operand * left,
8956 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8959 D (emitcode (";", "genLeftShiftLiteral"));
8961 freeAsmop (right, NULL, ic, TRUE);
8963 aopOp (left, ic, FALSE);
8964 aopOp (result, ic, FALSE);
8966 size = getSize (operandType (result));
8969 emitcode ("; shift left ", "result %d, left %d", size,
8973 /* I suppose that the left size >= result size */
8978 movLeft2Result (left, size, result, size, 0);
8981 else if (shCount >= (size * 8))
8985 aopPut (result, zero, size);
8993 genlshOne (result, left, shCount);
8997 genlshTwo (result, left, shCount);
9001 genlshFour (result, left, shCount);
9004 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9005 "*** ack! mystery literal shift!\n");
9009 freeAsmop (result, NULL, ic, TRUE);
9010 freeAsmop (left, NULL, ic, TRUE);
9013 /*-----------------------------------------------------------------*/
9014 /* genLeftShift - generates code for left shifting */
9015 /*-----------------------------------------------------------------*/
9017 genLeftShift (iCode * ic)
9019 operand *left, *right, *result;
9022 symbol *tlbl, *tlbl1;
9025 D (emitcode (";", "genLeftShift"));
9027 right = IC_RIGHT (ic);
9028 left = IC_LEFT (ic);
9029 result = IC_RESULT (ic);
9031 aopOp (right, ic, FALSE);
9033 /* if the shift count is known then do it
9034 as efficiently as possible */
9035 if (AOP_TYPE (right) == AOP_LIT)
9037 genLeftShiftLiteral (left, right, result, ic);
9041 /* shift count is unknown then we have to form
9042 a loop get the loop count in B : Note: we take
9043 only the lower order byte since shifting
9044 more that 32 bits make no sense anyway, ( the
9045 largest size of an object can be only 32 bits ) */
9048 MOVB (aopGet (right, 0, FALSE, FALSE));
9049 emitcode ("inc", "b");
9050 freeAsmop (right, NULL, ic, TRUE);
9051 aopOp (left, ic, FALSE);
9052 aopOp (result, ic, FALSE);
9054 /* now move the left to the result if they are not the same */
9055 if (!sameRegs (AOP (left), AOP (result)) &&
9056 AOP_SIZE (result) > 1)
9059 size = AOP_SIZE (result);
9063 l = aopGet (left, offset, FALSE, TRUE);
9064 if (*l == '@' && (IS_AOP_PREG (result)))
9067 emitcode ("mov", "a,%s", l);
9068 aopPut (result, "a", offset);
9071 aopPut (result, l, offset);
9076 tlbl = newiTempLabel (NULL);
9077 size = AOP_SIZE (result);
9079 tlbl1 = newiTempLabel (NULL);
9081 /* if it is only one byte then */
9084 symbol *tlbl1 = newiTempLabel (NULL);
9086 l = aopGet (left, 0, FALSE, FALSE);
9088 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9090 emitcode ("add", "a,acc");
9092 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9094 aopPut (result, "a", 0);
9098 reAdjustPreg (AOP (result));
9100 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9102 l = aopGet (result, offset, FALSE, FALSE);
9104 emitcode ("add", "a,acc");
9105 aopPut (result, "a", offset++);
9108 l = aopGet (result, offset, FALSE, FALSE);
9110 emitcode ("rlc", "a");
9111 aopPut (result, "a", offset++);
9113 reAdjustPreg (AOP (result));
9116 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9119 freeAsmop (result, NULL, ic, TRUE);
9120 freeAsmop (left, NULL, ic, TRUE);
9123 /*-----------------------------------------------------------------*/
9124 /* genrshOne - right shift a one byte quantity by known count */
9125 /*-----------------------------------------------------------------*/
9127 genrshOne (operand * result, operand * left,
9128 int shCount, int sign)
9130 D (emitcode (";", "genrshOne"));
9132 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9135 /*-----------------------------------------------------------------*/
9136 /* genrshTwo - right shift two bytes by known amount != 0 */
9137 /*-----------------------------------------------------------------*/
9139 genrshTwo (operand * result, operand * left,
9140 int shCount, int sign)
9142 D (emitcode (";", "genrshTwo"));
9144 /* if shCount >= 8 */
9149 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9151 movLeft2Result (left, MSB16, result, LSB, sign);
9152 addSign (result, MSB16, sign);
9155 /* 1 <= shCount <= 7 */
9157 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9160 /*-----------------------------------------------------------------*/
9161 /* shiftRLong - shift right one long from left to result */
9162 /* offl = LSB or MSB16 */
9163 /*-----------------------------------------------------------------*/
9165 shiftRLong (operand * left, int offl,
9166 operand * result, int sign)
9168 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9170 if (overlapping && offl>1)
9172 // we are in big trouble, but this shouldn't happen
9173 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9176 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9183 emitcode ("rlc", "a");
9184 emitcode ("subb", "a,acc");
9185 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9187 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9191 aopPut (result, "a", MSB32);
9192 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9197 if (aopPutUsesAcc (result, zero, MSB32))
9199 emitcode("xch", "a,b");
9200 aopPut (result, zero, MSB32);
9201 emitcode("xch", "a,b");
9205 aopPut (result, zero, MSB32);
9212 emitcode ("clr", "c");
9216 emitcode ("mov", "c,acc.7");
9219 emitcode ("rrc", "a");
9221 if (overlapping && offl==MSB16 &&
9222 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9224 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9228 aopPut (result, "a", MSB32 - offl);
9229 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9232 emitcode ("rrc", "a");
9233 if (overlapping && offl==MSB16 &&
9234 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9236 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9240 aopPut (result, "a", MSB24 - offl);
9241 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9244 emitcode ("rrc", "a");
9247 aopPut (result, "a", MSB16 - offl);
9252 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9254 xch_a_aopGet (left, LSB, FALSE, FALSE);
9258 aopPut (result, "a", MSB16 - offl);
9259 MOVA (aopGet (left, LSB, FALSE, FALSE));
9261 emitcode ("rrc", "a");
9262 aopPut (result, "a", LSB);
9266 /*-----------------------------------------------------------------*/
9267 /* genrshFour - shift four byte by a known amount != 0 */
9268 /*-----------------------------------------------------------------*/
9270 genrshFour (operand * result, operand * left,
9271 int shCount, int sign)
9273 D (emitcode (";", "genrshFour"));
9275 /* if shifting more that 3 bytes */
9280 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9282 movLeft2Result (left, MSB32, result, LSB, sign);
9283 addSign (result, MSB16, sign);
9285 else if (shCount >= 16)
9289 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9292 movLeft2Result (left, MSB24, result, LSB, 0);
9293 movLeft2Result (left, MSB32, result, MSB16, sign);
9295 addSign (result, MSB24, sign);
9297 else if (shCount >= 8)
9302 shiftRLong (left, MSB16, result, sign);
9304 else if (shCount == 0)
9306 movLeft2Result (left, MSB16, result, LSB, 0);
9307 movLeft2Result (left, MSB24, result, MSB16, 0);
9308 movLeft2Result (left, MSB32, result, MSB24, sign);
9309 addSign (result, MSB32, sign);
9313 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9314 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9315 /* the last shift is signed */
9316 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9317 addSign (result, MSB32, sign);
9322 /* 1 <= shCount <= 7 */
9325 shiftRLong (left, LSB, result, sign);
9327 shiftRLong (result, LSB, result, sign);
9331 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9332 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9333 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9338 /*-----------------------------------------------------------------*/
9339 /* genRightShiftLiteral - right shifting by known count */
9340 /*-----------------------------------------------------------------*/
9342 genRightShiftLiteral (operand * left,
9348 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9351 D (emitcode (";", "genRightShiftLiteral"));
9353 freeAsmop (right, NULL, ic, TRUE);
9355 aopOp (left, ic, FALSE);
9356 aopOp (result, ic, FALSE);
9359 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9363 size = getDataSize (left);
9364 /* test the LEFT size !!! */
9366 /* I suppose that the left size >= result size */
9369 size = getDataSize (result);
9371 movLeft2Result (left, size, result, size, 0);
9374 else if (shCount >= (size * 8))
9378 /* get sign in acc.7 */
9379 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9381 addSign (result, LSB, sign);
9388 genrshOne (result, left, shCount, sign);
9392 genrshTwo (result, left, shCount, sign);
9396 genrshFour (result, left, shCount, sign);
9402 freeAsmop (result, NULL, ic, TRUE);
9403 freeAsmop (left, NULL, ic, TRUE);
9406 /*-----------------------------------------------------------------*/
9407 /* genSignedRightShift - right shift of signed number */
9408 /*-----------------------------------------------------------------*/
9410 genSignedRightShift (iCode * ic)
9412 operand *right, *left, *result;
9415 symbol *tlbl, *tlbl1;
9418 D (emitcode (";", "genSignedRightShift"));
9420 /* we do it the hard way put the shift count in b
9421 and loop thru preserving the sign */
9423 right = IC_RIGHT (ic);
9424 left = IC_LEFT (ic);
9425 result = IC_RESULT (ic);
9427 aopOp (right, ic, FALSE);
9430 if (AOP_TYPE (right) == AOP_LIT)
9432 genRightShiftLiteral (left, right, result, ic, 1);
9435 /* shift count is unknown then we have to form
9436 a loop get the loop count in B : Note: we take
9437 only the lower order byte since shifting
9438 more that 32 bits make no sense anyway, ( the
9439 largest size of an object can be only 32 bits ) */
9442 MOVB (aopGet (right, 0, FALSE, FALSE));
9443 emitcode ("inc", "b");
9444 freeAsmop (right, NULL, ic, TRUE);
9445 aopOp (left, ic, FALSE);
9446 aopOp (result, ic, FALSE);
9448 /* now move the left to the result if they are not the
9450 if (!sameRegs (AOP (left), AOP (result)) &&
9451 AOP_SIZE (result) > 1)
9454 size = AOP_SIZE (result);
9458 l = aopGet (left, offset, FALSE, TRUE);
9459 if (*l == '@' && IS_AOP_PREG (result))
9462 emitcode ("mov", "a,%s", l);
9463 aopPut (result, "a", offset);
9466 aopPut (result, l, offset);
9471 /* mov the highest order bit to OVR */
9472 tlbl = newiTempLabel (NULL);
9473 tlbl1 = newiTempLabel (NULL);
9475 size = AOP_SIZE (result);
9477 MOVA (aopGet (left, offset, FALSE, FALSE));
9478 emitcode ("rlc", "a");
9479 emitcode ("mov", "ov,c");
9480 /* if it is only one byte then */
9483 l = aopGet (left, 0, FALSE, FALSE);
9485 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9487 emitcode ("mov", "c,ov");
9488 emitcode ("rrc", "a");
9490 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9492 aopPut (result, "a", 0);
9496 reAdjustPreg (AOP (result));
9497 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9499 emitcode ("mov", "c,ov");
9502 l = aopGet (result, offset, FALSE, FALSE);
9504 emitcode ("rrc", "a");
9505 aopPut (result, "a", offset--);
9507 reAdjustPreg (AOP (result));
9509 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9513 freeAsmop (result, NULL, ic, TRUE);
9514 freeAsmop (left, NULL, ic, TRUE);
9517 /*-----------------------------------------------------------------*/
9518 /* genRightShift - generate code for right shifting */
9519 /*-----------------------------------------------------------------*/
9521 genRightShift (iCode * ic)
9523 operand *right, *left, *result;
9527 symbol *tlbl, *tlbl1;
9530 D (emitcode (";", "genRightShift"));
9532 /* if signed then we do it the hard way preserve the
9533 sign bit moving it inwards */
9534 letype = getSpec (operandType (IC_LEFT (ic)));
9536 if (!SPEC_USIGN (letype))
9538 genSignedRightShift (ic);
9542 /* signed & unsigned types are treated the same : i.e. the
9543 signed is NOT propagated inwards : quoting from the
9544 ANSI - standard : "for E1 >> E2, is equivalent to division
9545 by 2**E2 if unsigned or if it has a non-negative value,
9546 otherwise the result is implementation defined ", MY definition
9547 is that the sign does not get propagated */
9549 right = IC_RIGHT (ic);
9550 left = IC_LEFT (ic);
9551 result = IC_RESULT (ic);
9553 aopOp (right, ic, FALSE);
9555 /* if the shift count is known then do it
9556 as efficiently as possible */
9557 if (AOP_TYPE (right) == AOP_LIT)
9559 genRightShiftLiteral (left, right, result, ic, 0);
9563 /* shift count is unknown then we have to form
9564 a loop get the loop count in B : Note: we take
9565 only the lower order byte since shifting
9566 more that 32 bits make no sense anyway, ( the
9567 largest size of an object can be only 32 bits ) */
9570 MOVB (aopGet (right, 0, FALSE, FALSE));
9571 emitcode ("inc", "b");
9572 freeAsmop (right, NULL, ic, TRUE);
9573 aopOp (left, ic, FALSE);
9574 aopOp (result, ic, FALSE);
9576 /* now move the left to the result if they are not the
9578 if (!sameRegs (AOP (left), AOP (result)) &&
9579 AOP_SIZE (result) > 1)
9581 size = AOP_SIZE (result);
9585 l = aopGet (left, offset, FALSE, TRUE);
9586 if (*l == '@' && IS_AOP_PREG (result))
9589 emitcode ("mov", "a,%s", l);
9590 aopPut (result, "a", offset);
9593 aopPut (result, l, offset);
9598 tlbl = newiTempLabel (NULL);
9599 tlbl1 = newiTempLabel (NULL);
9600 size = AOP_SIZE (result);
9603 /* if it is only one byte then */
9606 l = aopGet (left, 0, FALSE, FALSE);
9608 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9611 emitcode ("rrc", "a");
9613 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9615 aopPut (result, "a", 0);
9619 reAdjustPreg (AOP (result));
9620 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9625 l = aopGet (result, offset, FALSE, FALSE);
9627 emitcode ("rrc", "a");
9628 aopPut (result, "a", offset--);
9630 reAdjustPreg (AOP (result));
9633 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9637 freeAsmop (result, NULL, ic, TRUE);
9638 freeAsmop (left, NULL, ic, TRUE);
9641 /*-----------------------------------------------------------------*/
9642 /* emitPtrByteGet - emits code to get a byte into A through a */
9643 /* pointer register (R0, R1, or DPTR). The */
9644 /* original value of A can be preserved in B. */
9645 /*-----------------------------------------------------------------*/
9647 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9654 emitcode ("mov", "b,a");
9655 emitcode ("mov", "a,@%s", rname);
9660 emitcode ("mov", "b,a");
9661 emitcode ("movx", "a,@%s", rname);
9666 emitcode ("mov", "b,a");
9667 emitcode ("movx", "a,@dptr");
9672 emitcode ("mov", "b,a");
9673 emitcode ("clr", "a");
9674 emitcode ("movc", "a,@a+dptr");
9680 emitcode ("push", "b");
9681 emitcode ("push", "acc");
9683 emitcode ("lcall", "__gptrget");
9685 emitcode ("pop", "b");
9690 /*-----------------------------------------------------------------*/
9691 /* emitPtrByteSet - emits code to set a byte from src through a */
9692 /* pointer register (R0, R1, or DPTR). */
9693 /*-----------------------------------------------------------------*/
9695 emitPtrByteSet (char *rname, int p_type, char *src)
9704 emitcode ("mov", "@%s,a", rname);
9707 emitcode ("mov", "@%s,%s", rname, src);
9712 emitcode ("movx", "@%s,a", rname);
9717 emitcode ("movx", "@dptr,a");
9722 emitcode ("lcall", "__gptrput");
9727 /*-----------------------------------------------------------------*/
9728 /* genUnpackBits - generates code for unpacking bits */
9729 /*-----------------------------------------------------------------*/
9731 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9733 int offset = 0; /* result byte offset */
9734 int rsize; /* result size */
9735 int rlen = 0; /* remaining bitfield length */
9736 sym_link *etype; /* bitfield type information */
9737 int blen; /* bitfield length */
9738 int bstr; /* bitfield starting bit within byte */
9741 D(emitcode (";", "genUnpackBits"));
9743 etype = getSpec (operandType (result));
9744 rsize = getSize (operandType (result));
9745 blen = SPEC_BLEN (etype);
9746 bstr = SPEC_BSTR (etype);
9748 if (ifx && blen <= 8)
9750 emitPtrByteGet (rname, ptype, FALSE);
9753 SNPRINTF (buffer, sizeof(buffer),
9755 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9760 emitcode ("anl", "a,#0x%02x",
9761 (((unsigned char) -1) >> (8 - blen)) << bstr);
9762 genIfxJump (ifx, "a", NULL, NULL, NULL);
9768 /* If the bitfield length is less than a byte */
9771 emitPtrByteGet (rname, ptype, FALSE);
9773 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9774 if (!SPEC_USIGN (etype))
9776 /* signed bitfield */
9777 symbol *tlbl = newiTempLabel (NULL);
9779 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9780 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9783 aopPut (result, "a", offset++);
9787 /* Bit field did not fit in a byte. Copy all
9788 but the partial byte at the end. */
9789 for (rlen=blen;rlen>=8;rlen-=8)
9791 emitPtrByteGet (rname, ptype, FALSE);
9792 aopPut (result, "a", offset++);
9794 emitcode ("inc", "%s", rname);
9797 /* Handle the partial byte at the end */
9800 emitPtrByteGet (rname, ptype, FALSE);
9801 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9802 if (!SPEC_USIGN (etype))
9804 /* signed bitfield */
9805 symbol *tlbl = newiTempLabel (NULL);
9807 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9808 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9811 aopPut (result, "a", offset++);
9819 if (SPEC_USIGN (etype))
9823 /* signed bitfield: sign extension with 0x00 or 0xff */
9824 emitcode ("rlc", "a");
9825 emitcode ("subb", "a,acc");
9831 aopPut (result, source, offset++);
9836 /*-----------------------------------------------------------------*/
9837 /* genDataPointerGet - generates code when ptr offset is known */
9838 /*-----------------------------------------------------------------*/
9840 genDataPointerGet (operand * left,
9846 int size, offset = 0;
9848 D (emitcode (";", "genDataPointerGet"));
9850 aopOp (result, ic, TRUE);
9852 /* get the string representation of the name */
9853 l = aopGet (left, 0, FALSE, TRUE);
9855 size = AOP_SIZE (result);
9860 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9864 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9866 aopPut (result, buffer, offset++);
9869 freeAsmop (result, NULL, ic, TRUE);
9870 freeAsmop (left, NULL, ic, TRUE);
9873 /*-----------------------------------------------------------------*/
9874 /* genNearPointerGet - emitcode for near pointer fetch */
9875 /*-----------------------------------------------------------------*/
9877 genNearPointerGet (operand * left,
9886 sym_link *rtype, *retype;
9887 sym_link *ltype = operandType (left);
9890 D (emitcode (";", "genNearPointerGet"));
9892 rtype = operandType (result);
9893 retype = getSpec (rtype);
9895 aopOp (left, ic, FALSE);
9897 /* if left is rematerialisable and
9898 result is not bitfield variable type and
9899 the left is pointer to data space i.e
9900 lower 128 bytes of space */
9901 if (AOP_TYPE (left) == AOP_IMMD &&
9902 !IS_BITFIELD (retype) &&
9903 DCL_TYPE (ltype) == POINTER)
9905 genDataPointerGet (left, result, ic);
9909 /* if the value is already in a pointer register
9910 then don't need anything more */
9911 if (!AOP_INPREG (AOP (left)))
9913 if (IS_AOP_PREG (left))
9915 // Aha, it is a pointer, just in disguise.
9916 rname = aopGet (left, 0, FALSE, FALSE);
9919 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9920 __FILE__, __LINE__);
9925 emitcode ("mov", "a%s,%s", rname + 1, rname);
9926 rname++; // skip the '@'.
9931 /* otherwise get a free pointer register */
9933 preg = getFreePtr (ic, &aop, FALSE);
9934 emitcode ("mov", "%s,%s",
9936 aopGet (left, 0, FALSE, TRUE));
9941 rname = aopGet (left, 0, FALSE, FALSE);
9943 //aopOp (result, ic, FALSE);
9944 aopOp (result, ic, result?TRUE:FALSE);
9946 /* if bitfield then unpack the bits */
9947 if (IS_BITFIELD (retype))
9948 genUnpackBits (result, rname, POINTER, ifx);
9951 /* we have can just get the values */
9952 int size = AOP_SIZE (result);
9957 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9960 emitcode ("mov", "a,@%s", rname);
9962 aopPut (result, "a", offset);
9966 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9967 aopPut (result, buffer, offset);
9971 emitcode ("inc", "%s", rname);
9975 /* now some housekeeping stuff */
9976 if (aop) /* we had to allocate for this iCode */
9978 if (pi) { /* post increment present */
9979 aopPut (left, rname, 0);
9981 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9985 /* we did not allocate which means left
9986 already in a pointer register, then
9987 if size > 0 && this could be used again
9988 we have to point it back to where it
9990 if ((AOP_SIZE (result) > 1 &&
9991 !OP_SYMBOL (left)->remat &&
9992 (OP_SYMBOL (left)->liveTo > ic->seq ||
9996 int size = AOP_SIZE (result) - 1;
9998 emitcode ("dec", "%s", rname);
10002 if (ifx && !ifx->generated)
10004 genIfxJump (ifx, "a", left, NULL, result);
10008 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10009 freeAsmop (left, NULL, ic, TRUE);
10010 if (pi) pi->generated = 1;
10013 /*-----------------------------------------------------------------*/
10014 /* genPagedPointerGet - emitcode for paged pointer fetch */
10015 /*-----------------------------------------------------------------*/
10017 genPagedPointerGet (operand * left,
10026 sym_link *rtype, *retype;
10028 D (emitcode (";", "genPagedPointerGet"));
10030 rtype = operandType (result);
10031 retype = getSpec (rtype);
10033 aopOp (left, ic, FALSE);
10035 /* if the value is already in a pointer register
10036 then don't need anything more */
10037 if (!AOP_INPREG (AOP (left)))
10039 /* otherwise get a free pointer register */
10040 aop = newAsmop (0);
10041 preg = getFreePtr (ic, &aop, FALSE);
10042 emitcode ("mov", "%s,%s",
10044 aopGet (left, 0, FALSE, TRUE));
10045 rname = preg->name;
10048 rname = aopGet (left, 0, FALSE, FALSE);
10050 aopOp (result, ic, FALSE);
10052 /* if bitfield then unpack the bits */
10053 if (IS_BITFIELD (retype))
10054 genUnpackBits (result, rname, PPOINTER, ifx);
10057 /* we have can just get the values */
10058 int size = AOP_SIZE (result);
10064 emitcode ("movx", "a,@%s", rname);
10066 aopPut (result, "a", offset);
10071 emitcode ("inc", "%s", rname);
10075 /* now some housekeeping stuff */
10076 if (aop) /* we had to allocate for this iCode */
10079 aopPut (left, rname, 0);
10080 freeAsmop (NULL, aop, ic, TRUE);
10084 /* we did not allocate which means left
10085 already in a pointer register, then
10086 if size > 0 && this could be used again
10087 we have to point it back to where it
10089 if ((AOP_SIZE (result) > 1 &&
10090 !OP_SYMBOL (left)->remat &&
10091 (OP_SYMBOL (left)->liveTo > ic->seq ||
10095 int size = AOP_SIZE (result) - 1;
10097 emitcode ("dec", "%s", rname);
10101 if (ifx && !ifx->generated)
10103 genIfxJump (ifx, "a", left, NULL, result);
10107 freeAsmop (result, NULL, ic, TRUE);
10108 freeAsmop (left, NULL, ic, TRUE);
10109 if (pi) pi->generated = 1;
10112 /*--------------------------------------------------------------------*/
10113 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10114 /*--------------------------------------------------------------------*/
10116 loadDptrFromOperand (operand *op, bool loadBToo)
10118 if (AOP_TYPE (op) != AOP_STR)
10120 /* if this is rematerializable */
10121 if (AOP_TYPE (op) == AOP_IMMD)
10123 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10126 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10127 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10130 wassertl(FALSE, "need pointerCode");
10131 emitcode (";", "mov b,???");
10132 /* genPointerGet and genPointerSet originally did different
10133 ** things for this case. Both seem wrong.
10134 ** from genPointerGet:
10135 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10136 ** from genPointerSet:
10137 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10142 else if (AOP_TYPE (op) == AOP_DPTR)
10146 MOVA (aopGet (op, 0, FALSE, FALSE));
10147 emitcode ("push", "acc");
10148 MOVA (aopGet (op, 1, FALSE, FALSE));
10149 emitcode ("push", "acc");
10150 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10151 emitcode ("pop", "dph");
10152 emitcode ("pop", "dpl");
10156 MOVA (aopGet (op, 0, FALSE, FALSE));
10157 emitcode ("push", "acc");
10158 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10159 emitcode ("pop", "dpl");
10163 { /* we need to get it byte by byte */
10164 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10165 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10167 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10172 /*-----------------------------------------------------------------*/
10173 /* genFarPointerGet - get value from far space */
10174 /*-----------------------------------------------------------------*/
10176 genFarPointerGet (operand * left,
10177 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10180 sym_link *retype = getSpec (operandType (result));
10182 D (emitcode (";", "genFarPointerGet"));
10184 aopOp (left, ic, FALSE);
10185 loadDptrFromOperand (left, FALSE);
10187 /* so dptr now contains the address */
10188 aopOp (result, ic, FALSE);
10190 /* if bit then unpack */
10191 if (IS_BITFIELD (retype))
10192 genUnpackBits (result, "dptr", FPOINTER, ifx);
10195 size = AOP_SIZE (result);
10200 emitcode ("movx", "a,@dptr");
10202 aopPut (result, "a", offset++);
10204 emitcode ("inc", "dptr");
10208 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10210 aopPut (left, "dpl", 0);
10211 aopPut (left, "dph", 1);
10215 if (ifx && !ifx->generated)
10217 genIfxJump (ifx, "a", left, NULL, result);
10220 freeAsmop (result, NULL, ic, TRUE);
10221 freeAsmop (left, NULL, ic, TRUE);
10224 /*-----------------------------------------------------------------*/
10225 /* genCodePointerGet - get value from code space */
10226 /*-----------------------------------------------------------------*/
10228 genCodePointerGet (operand * left,
10229 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10232 sym_link *retype = getSpec (operandType (result));
10234 D (emitcode (";", "genCodePointerGet"));
10236 aopOp (left, ic, FALSE);
10237 loadDptrFromOperand (left, FALSE);
10239 /* so dptr now contains the address */
10240 aopOp (result, ic, FALSE);
10242 /* if bit then unpack */
10243 if (IS_BITFIELD (retype))
10244 genUnpackBits (result, "dptr", CPOINTER, ifx);
10247 size = AOP_SIZE (result);
10252 emitcode ("clr", "a");
10253 emitcode ("movc", "a,@a+dptr");
10255 aopPut (result, "a", offset++);
10257 emitcode ("inc", "dptr");
10261 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10263 aopPut (left, "dpl", 0);
10264 aopPut (left, "dph", 1);
10268 if (ifx && !ifx->generated)
10270 genIfxJump (ifx, "a", left, NULL, result);
10273 freeAsmop (result, NULL, ic, TRUE);
10274 freeAsmop (left, NULL, ic, TRUE);
10277 /*-----------------------------------------------------------------*/
10278 /* genGenPointerGet - get value from generic pointer space */
10279 /*-----------------------------------------------------------------*/
10281 genGenPointerGet (operand * left,
10282 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10285 sym_link *retype = getSpec (operandType (result));
10287 D (emitcode (";", "genGenPointerGet"));
10289 aopOp (left, ic, FALSE);
10290 loadDptrFromOperand (left, TRUE);
10292 /* so dptr now contains the address */
10293 aopOp (result, ic, FALSE);
10295 /* if bit then unpack */
10296 if (IS_BITFIELD (retype))
10298 genUnpackBits (result, "dptr", GPOINTER, ifx);
10302 size = AOP_SIZE (result);
10307 emitcode ("lcall", "__gptrget");
10309 aopPut (result, "a", offset++);
10311 emitcode ("inc", "dptr");
10315 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10317 aopPut (left, "dpl", 0);
10318 aopPut (left, "dph", 1);
10322 if (ifx && !ifx->generated)
10324 genIfxJump (ifx, "a", left, NULL, result);
10327 freeAsmop (result, NULL, ic, TRUE);
10328 freeAsmop (left, NULL, ic, TRUE);
10331 /*-----------------------------------------------------------------*/
10332 /* genPointerGet - generate code for pointer get */
10333 /*-----------------------------------------------------------------*/
10335 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10337 operand *left, *result;
10338 sym_link *type, *etype;
10341 D (emitcode (";", "genPointerGet"));
10343 left = IC_LEFT (ic);
10344 result = IC_RESULT (ic);
10346 if (getSize (operandType (result))>1)
10349 /* depending on the type of pointer we need to
10350 move it to the correct pointer register */
10351 type = operandType (left);
10352 etype = getSpec (type);
10353 /* if left is of type of pointer then it is simple */
10354 if (IS_PTR (type) && !IS_FUNC (type->next))
10355 p_type = DCL_TYPE (type);
10358 /* we have to go by the storage class */
10359 p_type = PTR_TYPE (SPEC_OCLS (etype));
10362 /* special case when cast remat */
10363 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10364 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10366 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10367 type = operandType (left);
10368 p_type = DCL_TYPE (type);
10370 /* now that we have the pointer type we assign
10371 the pointer values */
10377 genNearPointerGet (left, result, ic, pi, ifx);
10381 genPagedPointerGet (left, result, ic, pi, ifx);
10385 genFarPointerGet (left, result, ic, pi, ifx);
10389 genCodePointerGet (left, result, ic, pi, ifx);
10393 genGenPointerGet (left, result, ic, pi, ifx);
10399 /*-----------------------------------------------------------------*/
10400 /* genPackBits - generates code for packed bit storage */
10401 /*-----------------------------------------------------------------*/
10403 genPackBits (sym_link * etype,
10405 char *rname, int p_type)
10407 int offset = 0; /* source byte offset */
10408 int rlen = 0; /* remaining bitfield length */
10409 int blen; /* bitfield length */
10410 int bstr; /* bitfield starting bit within byte */
10411 int litval; /* source literal value (if AOP_LIT) */
10412 unsigned char mask; /* bitmask within current byte */
10414 D(emitcode (";", "genPackBits"));
10416 blen = SPEC_BLEN (etype);
10417 bstr = SPEC_BSTR (etype);
10419 /* If the bitfield length is less than a byte */
10422 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10423 (unsigned char) (0xFF >> (8 - bstr)));
10425 if (AOP_TYPE (right) == AOP_LIT)
10427 /* Case with a bitfield length <8 and literal source
10429 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10431 litval &= (~mask) & 0xff;
10432 emitPtrByteGet (rname, p_type, FALSE);
10433 if ((mask|litval)!=0xff)
10434 emitcode ("anl","a,#0x%02x", mask);
10436 emitcode ("orl","a,#0x%02x", litval);
10440 if ((blen==1) && (p_type!=GPOINTER))
10442 /* Case with a bitfield length == 1 and no generic pointer
10444 if (AOP_TYPE (right) == AOP_CRY)
10445 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10448 MOVA (aopGet (right, 0, FALSE, FALSE));
10449 emitcode ("rrc","a");
10451 emitPtrByteGet (rname, p_type, FALSE);
10452 emitcode ("mov","acc.%d,c",bstr);
10457 /* Case with a bitfield length < 8 and arbitrary source
10459 MOVA (aopGet (right, 0, FALSE, FALSE));
10460 /* shift and mask source value */
10462 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10464 pushedB = pushB ();
10465 /* transfer A to B and get next byte */
10466 emitPtrByteGet (rname, p_type, TRUE);
10468 emitcode ("anl", "a,#0x%02x", mask);
10469 emitcode ("orl", "a,b");
10470 if (p_type == GPOINTER)
10471 emitcode ("pop", "b");
10477 emitPtrByteSet (rname, p_type, "a");
10481 /* Bit length is greater than 7 bits. In this case, copy */
10482 /* all except the partial byte at the end */
10483 for (rlen=blen;rlen>=8;rlen-=8)
10485 emitPtrByteSet (rname, p_type,
10486 aopGet (right, offset++, FALSE, TRUE) );
10488 emitcode ("inc", "%s", rname);
10491 /* If there was a partial byte at the end */
10494 mask = (((unsigned char) -1 << rlen) & 0xff);
10496 if (AOP_TYPE (right) == AOP_LIT)
10498 /* Case with partial byte and literal source
10500 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10501 litval >>= (blen-rlen);
10502 litval &= (~mask) & 0xff;
10503 emitPtrByteGet (rname, p_type, FALSE);
10504 if ((mask|litval)!=0xff)
10505 emitcode ("anl","a,#0x%02x", mask);
10507 emitcode ("orl","a,#0x%02x", litval);
10512 /* Case with partial byte and arbitrary source
10514 MOVA (aopGet (right, offset++, FALSE, FALSE));
10515 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10517 pushedB = pushB ();
10518 /* transfer A to B and get next byte */
10519 emitPtrByteGet (rname, p_type, TRUE);
10521 emitcode ("anl", "a,#0x%02x", mask);
10522 emitcode ("orl", "a,b");
10523 if (p_type == GPOINTER)
10524 emitcode ("pop", "b");
10528 emitPtrByteSet (rname, p_type, "a");
10533 /*-----------------------------------------------------------------*/
10534 /* genDataPointerSet - remat pointer to data space */
10535 /*-----------------------------------------------------------------*/
10537 genDataPointerSet (operand * right,
10541 int size, offset = 0;
10542 char *l, buffer[256];
10544 D (emitcode (";", "genDataPointerSet"));
10546 aopOp (right, ic, FALSE);
10548 l = aopGet (result, 0, FALSE, TRUE);
10550 size = max (AOP_SIZE (right), AOP_SIZE (result));
10554 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10556 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10557 emitcode ("mov", "%s,%s", buffer,
10558 aopGet (right, offset++, FALSE, FALSE));
10561 freeAsmop (right, NULL, ic, TRUE);
10562 freeAsmop (result, NULL, ic, TRUE);
10565 /*-----------------------------------------------------------------*/
10566 /* genNearPointerSet - emitcode for near pointer put */
10567 /*-----------------------------------------------------------------*/
10569 genNearPointerSet (operand * right,
10577 sym_link *retype, *letype;
10578 sym_link *ptype = operandType (result);
10580 D (emitcode (";", "genNearPointerSet"));
10582 retype = getSpec (operandType (right));
10583 letype = getSpec (ptype);
10585 aopOp (result, ic, FALSE);
10587 /* if the result is rematerializable &
10588 in data space & not a bit variable */
10589 if (AOP_TYPE (result) == AOP_IMMD &&
10590 DCL_TYPE (ptype) == POINTER &&
10591 !IS_BITVAR (retype) &&
10592 !IS_BITVAR (letype))
10594 genDataPointerSet (right, result, ic);
10598 /* if the value is already in a pointer register
10599 then don't need anything more */
10600 if (!AOP_INPREG (AOP (result)))
10603 //AOP_TYPE (result) == AOP_STK
10604 IS_AOP_PREG(result)
10607 // Aha, it is a pointer, just in disguise.
10608 rname = aopGet (result, 0, FALSE, FALSE);
10611 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10612 __FILE__, __LINE__);
10617 emitcode ("mov", "a%s,%s", rname + 1, rname);
10618 rname++; // skip the '@'.
10623 /* otherwise get a free pointer register */
10624 aop = newAsmop (0);
10625 preg = getFreePtr (ic, &aop, FALSE);
10626 emitcode ("mov", "%s,%s",
10628 aopGet (result, 0, FALSE, TRUE));
10629 rname = preg->name;
10634 rname = aopGet (result, 0, FALSE, FALSE);
10637 aopOp (right, ic, FALSE);
10639 /* if bitfield then unpack the bits */
10640 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10641 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10644 /* we can just get the values */
10645 int size = AOP_SIZE (right);
10650 l = aopGet (right, offset, FALSE, TRUE);
10651 if ((*l == '@') || (strcmp (l, "acc") == 0))
10654 emitcode ("mov", "@%s,a", rname);
10657 emitcode ("mov", "@%s,%s", rname, l);
10659 emitcode ("inc", "%s", rname);
10664 /* now some housekeeping stuff */
10665 if (aop) /* we had to allocate for this iCode */
10668 aopPut (result, rname, 0);
10669 freeAsmop (NULL, aop, ic, TRUE);
10673 /* we did not allocate which means left
10674 already in a pointer register, then
10675 if size > 0 && this could be used again
10676 we have to point it back to where it
10678 if ((AOP_SIZE (right) > 1 &&
10679 !OP_SYMBOL (result)->remat &&
10680 (OP_SYMBOL (result)->liveTo > ic->seq ||
10684 int size = AOP_SIZE (right) - 1;
10686 emitcode ("dec", "%s", rname);
10693 freeAsmop (right, NULL, ic, TRUE);
10694 freeAsmop (result, NULL, ic, TRUE);
10697 /*-----------------------------------------------------------------*/
10698 /* genPagedPointerSet - emitcode for Paged pointer put */
10699 /*-----------------------------------------------------------------*/
10701 genPagedPointerSet (operand * right,
10709 sym_link *retype, *letype;
10711 D (emitcode (";", "genPagedPointerSet"));
10713 retype = getSpec (operandType (right));
10714 letype = getSpec (operandType (result));
10716 aopOp (result, ic, FALSE);
10718 /* if the value is already in a pointer register
10719 then don't need anything more */
10720 if (!AOP_INPREG (AOP (result)))
10722 /* otherwise get a free pointer register */
10723 aop = newAsmop (0);
10724 preg = getFreePtr (ic, &aop, FALSE);
10725 emitcode ("mov", "%s,%s",
10727 aopGet (result, 0, FALSE, TRUE));
10728 rname = preg->name;
10731 rname = aopGet (result, 0, FALSE, FALSE);
10733 aopOp (right, ic, FALSE);
10735 /* if bitfield then unpack the bits */
10736 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10737 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10740 /* we have can just get the values */
10741 int size = AOP_SIZE (right);
10746 l = aopGet (right, offset, FALSE, TRUE);
10748 emitcode ("movx", "@%s,a", rname);
10751 emitcode ("inc", "%s", rname);
10757 /* now some housekeeping stuff */
10758 if (aop) /* we had to allocate for this iCode */
10761 aopPut (result, rname, 0);
10762 freeAsmop (NULL, aop, ic, TRUE);
10766 /* we did not allocate which means left
10767 already in a pointer register, then
10768 if size > 0 && this could be used again
10769 we have to point it back to where it
10771 if (AOP_SIZE (right) > 1 &&
10772 !OP_SYMBOL (result)->remat &&
10773 (OP_SYMBOL (result)->liveTo > ic->seq ||
10776 int size = AOP_SIZE (right) - 1;
10778 emitcode ("dec", "%s", rname);
10783 if (pi) pi->generated = 1;
10784 freeAsmop (result, NULL, ic, TRUE);
10785 freeAsmop (right, NULL, ic, TRUE);
10788 /*-----------------------------------------------------------------*/
10789 /* genFarPointerSet - set value from far space */
10790 /*-----------------------------------------------------------------*/
10792 genFarPointerSet (operand * right,
10793 operand * result, iCode * ic, iCode * pi)
10796 sym_link *retype = getSpec (operandType (right));
10797 sym_link *letype = getSpec (operandType (result));
10799 D(emitcode (";", "genFarPointerSet"));
10801 aopOp (result, ic, FALSE);
10802 loadDptrFromOperand (result, FALSE);
10804 /* so dptr now contains the address */
10805 aopOp (right, ic, FALSE);
10807 /* if bit then unpack */
10808 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10809 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10812 size = AOP_SIZE (right);
10817 char *l = aopGet (right, offset++, FALSE, FALSE);
10819 emitcode ("movx", "@dptr,a");
10821 emitcode ("inc", "dptr");
10824 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10825 aopPut (result, "dpl", 0);
10826 aopPut (result, "dph", 1);
10829 freeAsmop (result, NULL, ic, TRUE);
10830 freeAsmop (right, NULL, ic, TRUE);
10833 /*-----------------------------------------------------------------*/
10834 /* genGenPointerSet - set value from generic pointer space */
10835 /*-----------------------------------------------------------------*/
10837 genGenPointerSet (operand * right,
10838 operand * result, iCode * ic, iCode * pi)
10841 sym_link *retype = getSpec (operandType (right));
10842 sym_link *letype = getSpec (operandType (result));
10844 D (emitcode (";", "genGenPointerSet"));
10846 aopOp (result, ic, FALSE);
10847 loadDptrFromOperand (result, TRUE);
10849 /* so dptr now contains the address */
10850 aopOp (right, ic, FALSE);
10852 /* if bit then unpack */
10853 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10855 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10859 size = AOP_SIZE (right);
10864 char *l = aopGet (right, offset++, FALSE, FALSE);
10866 emitcode ("lcall", "__gptrput");
10868 emitcode ("inc", "dptr");
10872 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10873 aopPut (result, "dpl", 0);
10874 aopPut (result, "dph", 1);
10877 freeAsmop (result, NULL, ic, TRUE);
10878 freeAsmop (right, NULL, ic, TRUE);
10881 /*-----------------------------------------------------------------*/
10882 /* genPointerSet - stores the value into a pointer location */
10883 /*-----------------------------------------------------------------*/
10885 genPointerSet (iCode * ic, iCode *pi)
10887 operand *right, *result;
10888 sym_link *type, *etype;
10891 D (emitcode (";", "genPointerSet"));
10893 right = IC_RIGHT (ic);
10894 result = IC_RESULT (ic);
10896 /* depending on the type of pointer we need to
10897 move it to the correct pointer register */
10898 type = operandType (result);
10899 etype = getSpec (type);
10900 /* if left is of type of pointer then it is simple */
10901 if (IS_PTR (type) && !IS_FUNC (type->next))
10903 p_type = DCL_TYPE (type);
10907 /* we have to go by the storage class */
10908 p_type = PTR_TYPE (SPEC_OCLS (etype));
10911 /* special case when cast remat */
10912 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10913 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10914 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10915 type = operandType (result);
10916 p_type = DCL_TYPE (type);
10919 /* now that we have the pointer type we assign
10920 the pointer values */
10926 genNearPointerSet (right, result, ic, pi);
10930 genPagedPointerSet (right, result, ic, pi);
10934 genFarPointerSet (right, result, ic, pi);
10938 genGenPointerSet (right, result, ic, pi);
10942 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10943 "genPointerSet: illegal pointer type");
10947 /*-----------------------------------------------------------------*/
10948 /* genIfx - generate code for Ifx statement */
10949 /*-----------------------------------------------------------------*/
10951 genIfx (iCode * ic, iCode * popIc)
10953 operand *cond = IC_COND (ic);
10957 D (emitcode (";", "genIfx"));
10959 aopOp (cond, ic, FALSE);
10961 /* get the value into acc */
10962 if (AOP_TYPE (cond) != AOP_CRY)
10969 if (AOP(cond)->aopu.aop_dir)
10970 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10973 /* the result is now in the accumulator or a directly addressable bit */
10974 freeAsmop (cond, NULL, ic, TRUE);
10976 /* if there was something to be popped then do it */
10980 /* if the condition is a bit variable */
10982 genIfxJump(ic, dup, NULL, NULL, NULL);
10983 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10984 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10985 else if (isbit && !IS_ITEMP (cond))
10986 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10988 genIfxJump (ic, "a", NULL, NULL, NULL);
10993 /*-----------------------------------------------------------------*/
10994 /* genAddrOf - generates code for address of */
10995 /*-----------------------------------------------------------------*/
10997 genAddrOf (iCode * ic)
10999 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11002 D (emitcode (";", "genAddrOf"));
11004 aopOp (IC_RESULT (ic), ic, FALSE);
11006 /* if the operand is on the stack then we
11007 need to get the stack offset of this
11011 /* if it has an offset then we need to compute it */
11014 int stack_offset = ((sym->stack < 0) ?
11015 ((char) (sym->stack - _G.nRegsSaved)) :
11016 ((char) sym->stack)) & 0xff;
11017 if ((abs(stack_offset) == 1) &&
11018 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11019 !isOperandVolatile (IC_RESULT (ic), FALSE))
11021 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11022 if (stack_offset > 0)
11023 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11025 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11029 emitcode ("mov", "a,%s", SYM_BP (sym));
11030 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11031 aopPut (IC_RESULT (ic), "a", 0);
11036 /* we can just move _bp */
11037 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11039 /* fill the result with zero */
11040 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11045 aopPut (IC_RESULT (ic), zero, offset++);
11050 /* object not on stack then we need the name */
11051 size = AOP_SIZE (IC_RESULT (ic));
11056 char s[SDCC_NAME_MAX];
11058 sprintf (s, "#(%s >> %d)",
11062 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11063 aopPut (IC_RESULT (ic), s, offset++);
11067 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11071 /*-----------------------------------------------------------------*/
11072 /* genFarFarAssign - assignment when both are in far space */
11073 /*-----------------------------------------------------------------*/
11075 genFarFarAssign (operand * result, operand * right, iCode * ic)
11077 int size = AOP_SIZE (right);
11081 D (emitcode (";", "genFarFarAssign"));
11083 /* first push the right side on to the stack */
11086 l = aopGet (right, offset++, FALSE, FALSE);
11088 emitcode ("push", "acc");
11091 freeAsmop (right, NULL, ic, FALSE);
11092 /* now assign DPTR to result */
11093 aopOp (result, ic, FALSE);
11094 size = AOP_SIZE (result);
11097 emitcode ("pop", "acc");
11098 aopPut (result, "a", --offset);
11100 freeAsmop (result, NULL, ic, FALSE);
11103 /*-----------------------------------------------------------------*/
11104 /* genAssign - generate code for assignment */
11105 /*-----------------------------------------------------------------*/
11107 genAssign (iCode * ic)
11109 operand *result, *right;
11111 unsigned long lit = 0L;
11113 D (emitcode (";", "genAssign"));
11115 result = IC_RESULT (ic);
11116 right = IC_RIGHT (ic);
11118 /* if they are the same */
11119 if (operandsEqu (result, right) &&
11120 !isOperandVolatile (result, FALSE) &&
11121 !isOperandVolatile (right, FALSE))
11124 aopOp (right, ic, FALSE);
11126 /* special case both in far space */
11127 if (AOP_TYPE (right) == AOP_DPTR &&
11128 IS_TRUE_SYMOP (result) &&
11129 isOperandInFarSpace (result))
11131 genFarFarAssign (result, right, ic);
11135 aopOp (result, ic, TRUE);
11137 /* if they are the same registers */
11138 if (sameRegs (AOP (right), AOP (result)) &&
11139 !isOperandVolatile (result, FALSE) &&
11140 !isOperandVolatile (right, FALSE))
11143 /* if the result is a bit */
11144 if (AOP_TYPE (result) == AOP_CRY)
11146 assignBit (result, right);
11150 /* bit variables done */
11152 size = AOP_SIZE (result);
11154 if (AOP_TYPE (right) == AOP_LIT)
11155 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11158 (AOP_TYPE (result) != AOP_REG) &&
11159 (AOP_TYPE (right) == AOP_LIT) &&
11160 !IS_FLOAT (operandType (right)) &&
11163 while ((size) && (lit))
11166 aopGet (right, offset, FALSE, FALSE),
11172 /* And now fill the rest with zeros. */
11175 emitcode ("clr", "a");
11179 aopPut (result, "a", offset);
11188 aopGet (right, offset, FALSE, FALSE),
11195 freeAsmop (result, NULL, ic, TRUE);
11196 freeAsmop (right, NULL, ic, TRUE);
11199 /*-----------------------------------------------------------------*/
11200 /* genJumpTab - generates code for jump table */
11201 /*-----------------------------------------------------------------*/
11203 genJumpTab (iCode * ic)
11205 symbol *jtab,*jtablo,*jtabhi;
11207 unsigned int count;
11209 D (emitcode (";", "genJumpTab"));
11211 count = elementsInSet( IC_JTLABELS (ic) );
11215 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11216 if the switch argument is in a register.
11217 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11218 /* Peephole may not convert ljmp to sjmp or ret
11219 labelIsReturnOnly & labelInRange must check
11220 currPl->ic->op != JUMPTABLE */
11221 aopOp (IC_JTCOND (ic), ic, FALSE);
11222 /* get the condition into accumulator */
11223 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11225 /* multiply by three */
11226 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11228 emitcode ("mov", "b,#3");
11229 emitcode ("mul", "ab");
11233 emitcode ("add", "a,acc");
11234 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11236 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11238 jtab = newiTempLabel (NULL);
11239 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11240 emitcode ("jmp", "@a+dptr");
11242 /* now generate the jump labels */
11243 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11244 jtab = setNextItem (IC_JTLABELS (ic)))
11245 emitcode ("ljmp", "%05d$", jtab->key + 100);
11249 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11250 if the switch argument is in a register.
11251 For n>6 this algorithm may be more compact */
11252 jtablo = newiTempLabel (NULL);
11253 jtabhi = newiTempLabel (NULL);
11255 /* get the condition into accumulator.
11256 Using b as temporary storage, if register push/pop is needed */
11257 aopOp (IC_JTCOND (ic), ic, FALSE);
11258 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11259 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11260 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11262 // (MB) what if B is in use???
11263 wassertl(!BINUSE, "B was in use");
11264 emitcode ("mov", "b,%s", l);
11267 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11271 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11272 emitcode ("movc", "a,@a+pc");
11273 emitcode ("push", "acc");
11276 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11277 emitcode ("movc", "a,@a+pc");
11278 emitcode ("push", "acc");
11282 /* this scales up to n<=255, but needs two more bytes
11283 and changes dptr */
11284 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11285 emitcode ("movc", "a,@a+dptr");
11286 emitcode ("push", "acc");
11289 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11290 emitcode ("movc", "a,@a+dptr");
11291 emitcode ("push", "acc");
11294 emitcode ("ret", "");
11296 /* now generate jump table, LSB */
11297 emitLabel (jtablo);
11298 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11299 jtab = setNextItem (IC_JTLABELS (ic)))
11300 emitcode (".db", "%05d$", jtab->key + 100);
11302 /* now generate jump table, MSB */
11303 emitLabel (jtabhi);
11304 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11305 jtab = setNextItem (IC_JTLABELS (ic)))
11306 emitcode (".db", "%05d$>>8", jtab->key + 100);
11310 /*-----------------------------------------------------------------*/
11311 /* genCast - gen code for casting */
11312 /*-----------------------------------------------------------------*/
11314 genCast (iCode * ic)
11316 operand *result = IC_RESULT (ic);
11317 sym_link *ctype = operandType (IC_LEFT (ic));
11318 sym_link *rtype = operandType (IC_RIGHT (ic));
11319 operand *right = IC_RIGHT (ic);
11322 D (emitcode (";", "genCast"));
11324 /* if they are equivalent then do nothing */
11325 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11328 aopOp (right, ic, FALSE);
11329 aopOp (result, ic, FALSE);
11331 /* if the result is a bit (and not a bitfield) */
11332 if (IS_BIT (OP_SYMBOL (result)->type))
11334 assignBit (result, right);
11338 /* if they are the same size : or less */
11339 if (AOP_SIZE (result) <= AOP_SIZE (right))
11342 /* if they are in the same place */
11343 if (sameRegs (AOP (right), AOP (result)))
11346 /* if they in different places then copy */
11347 size = AOP_SIZE (result);
11352 aopGet (right, offset, FALSE, FALSE),
11359 /* if the result is of type pointer */
11360 if (IS_PTR (ctype))
11364 sym_link *type = operandType (right);
11365 sym_link *etype = getSpec (type);
11367 /* pointer to generic pointer */
11368 if (IS_GENPTR (ctype))
11372 p_type = DCL_TYPE (type);
11376 if (SPEC_SCLS(etype)==S_REGISTER) {
11377 // let's assume it is a generic pointer
11380 /* we have to go by the storage class */
11381 p_type = PTR_TYPE (SPEC_OCLS (etype));
11385 /* the first two bytes are known */
11386 size = GPTRSIZE - 1;
11391 aopGet (right, offset, FALSE, FALSE),
11395 /* the last byte depending on type */
11397 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11402 // pointerTypeToGPByte will have bitched.
11406 sprintf(gpValStr, "#0x%x", gpVal);
11407 aopPut (result, gpValStr, GPTRSIZE - 1);
11412 /* just copy the pointers */
11413 size = AOP_SIZE (result);
11418 aopGet (right, offset, FALSE, FALSE),
11425 /* so we now know that the size of destination is greater
11426 than the size of the source */
11427 /* we move to result for the size of source */
11428 size = AOP_SIZE (right);
11433 aopGet (right, offset, FALSE, FALSE),
11438 /* now depending on the sign of the source && destination */
11439 size = AOP_SIZE (result) - AOP_SIZE (right);
11440 /* if unsigned or not an integral type */
11441 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11444 aopPut (result, zero, offset++);
11448 /* we need to extend the sign :{ */
11449 char *l = aopGet (right, AOP_SIZE (right) - 1,
11452 emitcode ("rlc", "a");
11453 emitcode ("subb", "a,acc");
11455 aopPut (result, "a", offset++);
11458 /* we are done hurray !!!! */
11461 freeAsmop (result, NULL, ic, TRUE);
11462 freeAsmop (right, NULL, ic, TRUE);
11465 /*-----------------------------------------------------------------*/
11466 /* genDjnz - generate decrement & jump if not zero instrucion */
11467 /*-----------------------------------------------------------------*/
11469 genDjnz (iCode * ic, iCode * ifx)
11471 symbol *lbl, *lbl1;
11475 /* if the if condition has a false label
11476 then we cannot save */
11477 if (IC_FALSE (ifx))
11480 /* if the minus is not of the form a = a - 1 */
11481 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11482 !IS_OP_LITERAL (IC_RIGHT (ic)))
11485 if (operandLitValue (IC_RIGHT (ic)) != 1)
11488 /* if the size of this greater than one then no
11490 if (getSize (operandType (IC_RESULT (ic))) > 1)
11493 /* otherwise we can save BIG */
11495 D (emitcode (";", "genDjnz"));
11497 lbl = newiTempLabel (NULL);
11498 lbl1 = newiTempLabel (NULL);
11500 aopOp (IC_RESULT (ic), ic, FALSE);
11502 if (AOP_NEEDSACC(IC_RESULT(ic)))
11504 /* If the result is accessed indirectly via
11505 * the accumulator, we must explicitly write
11506 * it back after the decrement.
11508 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11510 if (strcmp(rByte, "a"))
11512 /* Something is hopelessly wrong */
11513 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11514 __FILE__, __LINE__);
11515 /* We can just give up; the generated code will be inefficient,
11516 * but what the hey.
11518 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11521 emitcode ("dec", "%s", rByte);
11522 aopPut (IC_RESULT (ic), rByte, 0);
11523 emitcode ("jnz", "%05d$", lbl->key + 100);
11525 else if (IS_AOP_PREG (IC_RESULT (ic)))
11527 emitcode ("dec", "%s",
11528 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11529 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11530 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11531 ifx->generated = 1;
11532 emitcode ("jnz", "%05d$", lbl->key + 100);
11536 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11539 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11541 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11544 if (!ifx->generated)
11545 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11546 ifx->generated = 1;
11550 /*-----------------------------------------------------------------*/
11551 /* genReceive - generate code for a receive iCode */
11552 /*-----------------------------------------------------------------*/
11554 genReceive (iCode * ic)
11556 int size = getSize (operandType (IC_RESULT (ic)));
11559 D (emitcode (";", "genReceive"));
11561 if (ic->argreg == 1)
11562 { /* first parameter */
11563 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11564 isOperandInPagedSpace (IC_RESULT (ic))) &&
11565 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11566 IS_TRUE_SYMOP (IC_RESULT (ic))))
11569 int receivingA = 0;
11572 for (offset = 0; offset<size; offset++)
11573 if (!strcmp (fReturn[offset], "a"))
11578 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11580 for (offset = size-1; offset>0; offset--)
11581 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11582 emitcode("mov","a,%s", fReturn[0]);
11584 aopOp (IC_RESULT (ic), ic, FALSE);
11586 aopPut (IC_RESULT (ic), "a", offset);
11587 for (offset = 1; offset<size; offset++)
11588 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11594 if (getTempRegs(tempRegs, size, ic))
11596 for (offset = 0; offset<size; offset++)
11597 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11598 aopOp (IC_RESULT (ic), ic, FALSE);
11599 for (offset = 0; offset<size; offset++)
11600 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11605 offset = fReturnSizeMCS51 - size;
11608 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11609 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11612 aopOp (IC_RESULT (ic), ic, FALSE);
11613 size = AOP_SIZE (IC_RESULT (ic));
11617 emitcode ("pop", "acc");
11618 aopPut (IC_RESULT (ic), "a", offset++);
11624 aopOp (IC_RESULT (ic), ic, FALSE);
11626 assignResultValue (IC_RESULT (ic), NULL);
11629 else if (ic->argreg > 12)
11630 { /* bit parameters */
11631 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11634 if (!reg || reg->rIdx != ic->argreg-5)
11636 aopOp (IC_RESULT (ic), ic, FALSE);
11637 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11638 outBitC(IC_RESULT (ic));
11642 { /* other parameters */
11644 aopOp (IC_RESULT (ic), ic, FALSE);
11645 rb1off = ic->argreg;
11648 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11653 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11656 /*-----------------------------------------------------------------*/
11657 /* genDummyRead - generate code for dummy read of volatiles */
11658 /*-----------------------------------------------------------------*/
11660 genDummyRead (iCode * ic)
11665 D (emitcode(";", "genDummyRead"));
11667 op = IC_RIGHT (ic);
11668 if (op && IS_SYMOP (op))
11670 aopOp (op, ic, FALSE);
11672 /* if the result is a bit */
11673 if (AOP_TYPE (op) == AOP_CRY)
11674 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11677 /* bit variables done */
11679 size = AOP_SIZE (op);
11683 MOVA (aopGet (op, offset, FALSE, FALSE));
11688 freeAsmop (op, NULL, ic, TRUE);
11692 if (op && IS_SYMOP (op))
11694 aopOp (op, ic, FALSE);
11696 /* if the result is a bit */
11697 if (AOP_TYPE (op) == AOP_CRY)
11698 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11701 /* bit variables done */
11703 size = AOP_SIZE (op);
11707 MOVA (aopGet (op, offset, FALSE, FALSE));
11712 freeAsmop (op, NULL, ic, TRUE);
11716 /*-----------------------------------------------------------------*/
11717 /* genCritical - generate code for start of a critical sequence */
11718 /*-----------------------------------------------------------------*/
11720 genCritical (iCode *ic)
11722 symbol *tlbl = newiTempLabel (NULL);
11724 D (emitcode(";", "genCritical"));
11726 if (IC_RESULT (ic))
11728 aopOp (IC_RESULT (ic), ic, TRUE);
11729 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11730 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11731 aopPut (IC_RESULT (ic), zero, 0);
11733 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11737 emitcode ("setb", "c");
11738 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11739 emitcode ("clr", "c");
11741 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11745 /*-----------------------------------------------------------------*/
11746 /* genEndCritical - generate code for end of a critical sequence */
11747 /*-----------------------------------------------------------------*/
11749 genEndCritical (iCode *ic)
11751 D(emitcode(";", "genEndCritical"));
11755 aopOp (IC_RIGHT (ic), ic, FALSE);
11756 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11758 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11759 emitcode ("mov", "ea,c");
11763 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11764 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11765 emitcode ("rrc", "a");
11766 emitcode ("mov", "ea,c");
11768 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11772 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11773 emitcode ("mov", "ea,c");
11777 /*-----------------------------------------------------------------*/
11778 /* gen51Code - generate code for 8051 based controllers */
11779 /*-----------------------------------------------------------------*/
11781 gen51Code (iCode * lic)
11785 /* int cseq = 0; */
11787 _G.currentFunc = NULL;
11788 lineHead = lineCurr = NULL;
11790 /* print the allocation information */
11791 if (allocInfo && currFunc)
11792 printAllocInfo (currFunc, codeOutBuf);
11793 /* if debug information required */
11794 if (options.debug && currFunc)
11796 debugFile->writeFunction (currFunc, lic);
11798 /* stack pointer name */
11799 if (options.useXstack)
11805 for (ic = lic; ic; ic = ic->next)
11807 _G.current_iCode = ic;
11809 if (ic->lineno && cln != ic->lineno)
11813 debugFile->writeCLine (ic);
11815 if (!options.noCcodeInAsm) {
11816 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11817 printCLine(ic->filename, ic->lineno));
11822 if (ic->seqPoint && ic->seqPoint != cseq)
11824 emitcode (";", "sequence point %d", ic->seqPoint);
11825 cseq = ic->seqPoint;
11828 if (options.iCodeInAsm) {
11829 char regsInUse[80];
11834 for (i=0; i<8; i++) {
11835 sprintf (®sInUse[i],
11836 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11839 strcpy (regsInUse, "--------");
11840 for (i=0; i < 8; i++) {
11841 if (bitVectBitValue (ic->rMask, i))
11843 int offset = regs8051[i].offset;
11844 regsInUse[offset] = offset + '0'; /* show rMask */
11848 iLine = printILine(ic);
11849 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11852 /* if the result is marked as
11853 spilt and rematerializable or code for
11854 this has already been generated then
11856 if (resultRemat (ic) || ic->generated)
11859 /* depending on the operation */
11879 /* IPOP happens only when trying to restore a
11880 spilt live range, if there is an ifx statement
11881 following this pop then the if statement might
11882 be using some of the registers being popped which
11883 would destory the contents of the register so
11884 we need to check for this condition and handle it */
11886 ic->next->op == IFX &&
11887 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11888 genIfx (ic->next, ic);
11906 genEndFunction (ic);
11926 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11943 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11947 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11954 /* note these two are xlated by algebraic equivalence
11955 in decorateType() in SDCCast.c */
11956 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11957 "got '>=' or '<=' shouldn't have come here");
11961 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11973 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11977 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11981 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12017 genRightShift (ic);
12020 case GET_VALUE_AT_ADDRESS:
12022 hasInc (IC_LEFT (ic), ic,
12023 getSize (operandType (IC_RESULT (ic)))),
12024 ifxForOp (IC_RESULT (ic), ic) );
12028 if (POINTER_SET (ic))
12030 hasInc (IC_RESULT (ic), ic,
12031 getSize (operandType (IC_RIGHT (ic)))));
12057 addSet (&_G.sendSet, ic);
12060 case DUMMY_READ_VOLATILE:
12069 genEndCritical (ic);
12081 _G.current_iCode = NULL;
12083 /* now we are ready to call the
12084 peep hole optimizer */
12085 if (!options.nopeep)
12086 peepHole (&lineHead);
12088 /* now do the actual printing */
12089 printLine (lineHead, codeOutBuf);