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 symbol *tlbl = newiTempLabel (NULL);
7080 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7081 emitcode ("setb", "c");
7082 emitcode ("jb", "%s,%05d$",
7083 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7085 emitcode ("jnz", "%05d$", tlbl->key + 100);
7086 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7088 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7103 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7104 genIfxJump (ifx, "c", left, right, result);
7108 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7109 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7110 if ((AOP_TYPE (right) == AOP_LIT) &&
7111 (AOP_TYPE (result) == AOP_CRY) &&
7112 (AOP_TYPE (left) != AOP_CRY))
7118 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7120 continueIfTrue (ifx);
7125 // lit = 0, result = boolean(left)
7127 emitcode ("setb", "c");
7131 symbol *tlbl = newiTempLabel (NULL);
7132 emitcode ("jnz", "%05d$", tlbl->key + 100);
7138 genIfxJump (ifx, "a", left, right, result);
7146 /* if left is same as result */
7147 if (sameRegs (AOP (result), AOP (left)))
7149 for (; size--; offset++)
7151 if (AOP_TYPE (right) == AOP_LIT)
7153 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7156 /* dummy read of volatile operand */
7157 if (isOperandVolatile (left, FALSE))
7158 MOVA (aopGet (left, offset, FALSE, FALSE));
7162 else if (bytelit == 0x0FF)
7164 aopPut (result, "#0xFF", offset);
7166 else if (IS_AOP_PREG (left))
7168 MOVA (aopGet (left, offset, FALSE, TRUE));
7169 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7170 aopPut (result, "a", offset);
7174 emitcode ("orl", "%s,%s",
7175 aopGet (left, offset, FALSE, TRUE),
7176 aopGet (right, offset, FALSE, FALSE));
7181 if (AOP_TYPE (left) == AOP_ACC)
7184 emitcode("mov", "a,b");
7185 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7187 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7189 MOVB (aopGet (left, offset, FALSE, FALSE));
7190 MOVA (aopGet (right, offset, FALSE, FALSE));
7191 emitcode ("orl", "a,b");
7192 aopPut (result, "a", offset);
7194 else if (aopGetUsesAcc (left, offset))
7196 MOVA (aopGet (left, offset, FALSE, FALSE));
7197 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7198 aopPut (result, "a", offset);
7202 MOVA (aopGet (right, offset, FALSE, FALSE));
7203 if (IS_AOP_PREG (left))
7205 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7206 aopPut (result, "a", offset);
7210 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7218 // left & result in different registers
7219 if (AOP_TYPE (result) == AOP_CRY)
7222 // if(size), result in bit
7223 // if(!size && ifx), conditional oper: if(left | right)
7224 symbol *tlbl = newiTempLabel (NULL);
7225 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7227 emitcode ("setb", "c");
7230 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7231 && AOP_TYPE(left)==AOP_ACC)
7234 emitcode("mov", "a,b");
7235 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237 else if (AOP_TYPE(left)==AOP_ACC)
7241 bool pushedB = pushB ();
7242 emitcode("mov", "b,a");
7243 MOVA (aopGet (right, offset, FALSE, FALSE));
7244 emitcode("orl", "a,b");
7249 MOVA (aopGet (right, offset, FALSE, FALSE));
7250 emitcode("orl", "a,b");
7253 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7255 MOVB (aopGet (left, offset, FALSE, FALSE));
7256 MOVA (aopGet (right, offset, FALSE, FALSE));
7257 emitcode ("orl", "a,b");
7259 else if (aopGetUsesAcc (left, offset))
7261 MOVA (aopGet (left, offset, FALSE, FALSE));
7262 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7266 MOVA (aopGet (right, offset, FALSE, FALSE));
7267 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7270 emitcode ("jnz", "%05d$", tlbl->key + 100);
7280 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7286 for (; (size--); offset++)
7289 // result = left | right
7290 if (AOP_TYPE (right) == AOP_LIT)
7292 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7296 aopGet (left, offset, FALSE, FALSE),
7300 else if (bytelit == 0x0FF)
7302 /* dummy read of volatile operand */
7303 if (isOperandVolatile (left, FALSE))
7304 MOVA (aopGet (left, offset, FALSE, FALSE));
7305 aopPut (result, "#0xFF", offset);
7309 // faster than result <- left, orl result,right
7310 // and better if result is SFR
7311 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7312 && AOP_TYPE(left)==AOP_ACC)
7315 emitcode("mov", "a,b");
7316 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7318 else if (AOP_TYPE(left)==AOP_ACC)
7322 bool pushedB = pushB ();
7323 emitcode("mov", "b,a");
7324 MOVA (aopGet (right, offset, FALSE, FALSE));
7325 emitcode("orl", "a,b");
7330 MOVA (aopGet (right, offset, FALSE, FALSE));
7331 emitcode("orl", "a,b");
7334 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7336 MOVB (aopGet (left, offset, FALSE, FALSE));
7337 MOVA (aopGet (right, offset, FALSE, FALSE));
7338 emitcode ("orl", "a,b");
7340 else if (aopGetUsesAcc (left, offset))
7342 MOVA (aopGet (left, offset, FALSE, FALSE));
7343 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7347 MOVA (aopGet (right, offset, FALSE, FALSE));
7348 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7350 aopPut (result, "a", offset);
7356 freeAsmop (result, NULL, ic, TRUE);
7357 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7358 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7361 /*-----------------------------------------------------------------*/
7362 /* genXor - code for xclusive or */
7363 /*-----------------------------------------------------------------*/
7365 genXor (iCode * ic, iCode * ifx)
7367 operand *left, *right, *result;
7368 int size, offset = 0;
7369 unsigned long lit = 0L;
7372 D (emitcode (";", "genXor"));
7374 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7375 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7376 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7379 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7381 AOP_TYPE (left), AOP_TYPE (right));
7382 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7384 AOP_SIZE (left), AOP_SIZE (right));
7387 /* if left is a literal & right is not ||
7388 if left needs acc & right does not */
7389 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7390 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7392 operand *tmp = right;
7397 /* if result = right then exchange them */
7398 if (sameRegs (AOP (result), AOP (right)))
7400 operand *tmp = right;
7405 /* if right is bit then exchange them */
7406 if (AOP_TYPE (right) == AOP_CRY &&
7407 AOP_TYPE (left) != AOP_CRY)
7409 operand *tmp = right;
7414 if (AOP_TYPE (right) == AOP_LIT)
7415 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7417 size = AOP_SIZE (result);
7421 if (AOP_TYPE (left) == AOP_CRY)
7423 if (AOP_TYPE (right) == AOP_LIT)
7425 // c = bit & literal;
7428 // lit>>1 != 0 => result = 1
7429 if (AOP_TYPE (result) == AOP_CRY)
7432 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7434 continueIfTrue (ifx);
7437 emitcode ("setb", "c");
7444 // lit == 0, result = left
7445 if (size && sameRegs (AOP (result), AOP (left)))
7447 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7451 // lit == 1, result = not(left)
7452 if (size && sameRegs (AOP (result), AOP (left)))
7454 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7459 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7460 emitcode ("cpl", "c");
7468 symbol *tlbl = newiTempLabel (NULL);
7469 if (AOP_TYPE (right) == AOP_CRY)
7472 if (IS_OP_ACCUSE (left))
7473 {// left already is in the carry
7474 operand *tmp = right;
7488 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7489 emitcode ("cpl", "c");
7497 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7498 genIfxJump (ifx, "c", left, right, result);
7502 /* if left is same as result */
7503 if (sameRegs (AOP (result), AOP (left)))
7505 for (; size--; offset++)
7507 if (AOP_TYPE (right) == AOP_LIT)
7509 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7512 /* dummy read of volatile operand */
7513 if (isOperandVolatile (left, FALSE))
7514 MOVA (aopGet (left, offset, FALSE, FALSE));
7518 else if (IS_AOP_PREG (left))
7520 MOVA (aopGet (left, offset, FALSE, TRUE));
7521 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7522 aopPut (result, "a", offset);
7526 emitcode ("xrl", "%s,%s",
7527 aopGet (left, offset, FALSE, TRUE),
7528 aopGet (right, offset, FALSE, FALSE));
7533 if (AOP_TYPE (left) == AOP_ACC)
7536 emitcode("mov", "a,b");
7537 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7539 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7541 MOVB (aopGet (left, offset, FALSE, FALSE));
7542 MOVA (aopGet (right, offset, FALSE, FALSE));
7543 emitcode ("xrl", "a,b");
7544 aopPut (result, "a", offset);
7546 else if (aopGetUsesAcc (left, offset))
7548 MOVA (aopGet (left, offset, FALSE, FALSE));
7549 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7550 aopPut (result, "a", offset);
7554 MOVA (aopGet (right, offset, FALSE, FALSE));
7555 if (IS_AOP_PREG (left))
7557 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7558 aopPut (result, "a", offset);
7561 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7568 // left & result in different registers
7569 if (AOP_TYPE (result) == AOP_CRY)
7572 // if(size), result in bit
7573 // if(!size && ifx), conditional oper: if(left ^ right)
7574 symbol *tlbl = newiTempLabel (NULL);
7575 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7578 emitcode ("setb", "c");
7581 if ((AOP_TYPE (right) == AOP_LIT) &&
7582 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7584 MOVA (aopGet (left, offset, FALSE, FALSE));
7586 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7587 && AOP_TYPE(left)==AOP_ACC)
7590 emitcode("mov", "a,b");
7591 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7593 else if (AOP_TYPE(left)==AOP_ACC)
7597 bool pushedB = pushB ();
7598 emitcode("mov", "b,a");
7599 MOVA (aopGet (right, offset, FALSE, FALSE));
7600 emitcode("xrl", "a,b");
7605 MOVA (aopGet (right, offset, FALSE, FALSE));
7606 emitcode("xrl", "a,b");
7609 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7611 MOVB (aopGet (left, offset, FALSE, FALSE));
7612 MOVA (aopGet (right, offset, FALSE, FALSE));
7613 emitcode ("xrl", "a,b");
7615 else if (aopGetUsesAcc (left, offset))
7617 MOVA (aopGet (left, offset, FALSE, FALSE));
7618 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7622 MOVA (aopGet (right, offset, FALSE, FALSE));
7623 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7626 emitcode ("jnz", "%05d$", tlbl->key + 100);
7636 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7640 for (; (size--); offset++)
7643 // result = left ^ right
7644 if (AOP_TYPE (right) == AOP_LIT)
7646 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7650 aopGet (left, offset, FALSE, FALSE),
7655 // faster than result <- left, xrl result,right
7656 // and better if result is SFR
7657 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7658 && AOP_TYPE(left)==AOP_ACC)
7661 emitcode("mov", "a,b");
7662 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7664 else if (AOP_TYPE(left)==AOP_ACC)
7668 bool pushedB = pushB ();
7669 emitcode("mov", "b,a");
7670 MOVA (aopGet (right, offset, FALSE, FALSE));
7671 emitcode("xrl", "a,b");
7676 MOVA (aopGet (right, offset, FALSE, FALSE));
7677 emitcode("xrl", "a,b");
7680 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7682 MOVB (aopGet (left, offset, FALSE, FALSE));
7683 MOVA (aopGet (right, offset, FALSE, FALSE));
7684 emitcode ("xrl", "a,b");
7686 else if (aopGetUsesAcc (left, offset))
7688 MOVA (aopGet (left, offset, FALSE, FALSE));
7689 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7693 MOVA (aopGet (right, offset, FALSE, FALSE));
7694 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7696 aopPut (result, "a", offset);
7702 freeAsmop (result, NULL, ic, TRUE);
7703 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7704 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7707 /*-----------------------------------------------------------------*/
7708 /* genInline - write the inline code out */
7709 /*-----------------------------------------------------------------*/
7711 genInline (iCode * ic)
7713 char *buffer, *bp, *bp1;
7714 bool inComment = FALSE;
7716 D (emitcode (";", "genInline"));
7718 _G.inLine += (!options.asmpeep);
7720 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7722 /* emit each line as a code */
7740 /* Add \n for labels, not dirs such as c:\mydir */
7741 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7759 _G.inLine -= (!options.asmpeep);
7762 /*-----------------------------------------------------------------*/
7763 /* genRRC - rotate right with carry */
7764 /*-----------------------------------------------------------------*/
7768 operand *left, *result;
7772 D (emitcode (";", "genRRC"));
7774 /* rotate right with carry */
7775 left = IC_LEFT (ic);
7776 result = IC_RESULT (ic);
7777 aopOp (left, ic, FALSE);
7778 aopOp (result, ic, FALSE);
7780 /* move it to the result */
7781 size = AOP_SIZE (result);
7783 if (size == 1) { /* special case for 1 byte */
7784 l = aopGet (left, offset, FALSE, FALSE);
7786 emitcode ("rr", "a");
7789 /* no need to clear carry, bit7 will be written later */
7792 l = aopGet (left, offset, FALSE, FALSE);
7794 emitcode ("rrc", "a");
7795 if (AOP_SIZE (result) > 1)
7796 aopPut (result, "a", offset--);
7798 /* now we need to put the carry into the
7799 highest order byte of the result */
7800 if (AOP_SIZE (result) > 1)
7802 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7805 emitcode ("mov", "acc.7,c");
7807 aopPut (result, "a", AOP_SIZE (result) - 1);
7808 freeAsmop (result, NULL, ic, TRUE);
7809 freeAsmop (left, NULL, ic, TRUE);
7812 /*-----------------------------------------------------------------*/
7813 /* genRLC - generate code for rotate left with carry */
7814 /*-----------------------------------------------------------------*/
7818 operand *left, *result;
7822 D (emitcode (";", "genRLC"));
7824 /* rotate right with carry */
7825 left = IC_LEFT (ic);
7826 result = IC_RESULT (ic);
7827 aopOp (left, ic, FALSE);
7828 aopOp (result, ic, FALSE);
7830 /* move it to the result */
7831 size = AOP_SIZE (result);
7835 l = aopGet (left, offset, FALSE, FALSE);
7837 if (size == 0) { /* special case for 1 byte */
7841 emitcode("rlc","a"); /* bit0 will be written later */
7842 if (AOP_SIZE (result) > 1)
7844 aopPut (result, "a", offset++);
7849 l = aopGet (left, offset, FALSE, FALSE);
7851 emitcode ("rlc", "a");
7852 if (AOP_SIZE (result) > 1)
7853 aopPut (result, "a", offset++);
7856 /* now we need to put the carry into the
7857 highest order byte of the result */
7858 if (AOP_SIZE (result) > 1)
7860 l = aopGet (result, 0, FALSE, FALSE);
7863 emitcode ("mov", "acc.0,c");
7865 aopPut (result, "a", 0);
7866 freeAsmop (result, NULL, ic, TRUE);
7867 freeAsmop (left, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genGetHbit - generates code get highest order bit */
7872 /*-----------------------------------------------------------------*/
7874 genGetHbit (iCode * ic)
7876 operand *left, *result;
7878 D (emitcode (";", "genGetHbit"));
7880 left = IC_LEFT (ic);
7881 result = IC_RESULT (ic);
7882 aopOp (left, ic, FALSE);
7883 aopOp (result, ic, FALSE);
7885 /* get the highest order byte into a */
7886 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7887 if (AOP_TYPE (result) == AOP_CRY)
7889 emitcode ("rlc", "a");
7894 emitcode ("rl", "a");
7895 emitcode ("anl", "a,#0x01");
7899 freeAsmop (result, NULL, ic, TRUE);
7900 freeAsmop (left, NULL, ic, TRUE);
7903 /*-----------------------------------------------------------------*/
7904 /* genGetAbit - generates code get a single bit */
7905 /*-----------------------------------------------------------------*/
7907 genGetAbit (iCode * ic)
7909 operand *left, *right, *result;
7912 D (emitcode (";", "genGetAbit"));
7914 left = IC_LEFT (ic);
7915 right = IC_RIGHT (ic);
7916 result = IC_RESULT (ic);
7917 aopOp (left, ic, FALSE);
7918 aopOp (right, ic, FALSE);
7919 aopOp (result, ic, FALSE);
7921 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7923 /* get the needed byte into a */
7924 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7926 if (AOP_TYPE (result) == AOP_CRY)
7929 emitcode ("rlc", "a");
7930 else if ((shCount) == 0)
7931 emitcode ("rrc", "a");
7933 emitcode ("mov", "c,acc[%d]", shCount);
7941 emitcode ("rr", "a");
7944 emitcode ("rr", "a");
7947 emitcode ("anl", "a,#0x01");
7951 emitcode ("mov", "c,acc[%d]", shCount);
7952 emitcode ("clr", "a");
7953 emitcode ("rlc", "a");
7956 emitcode ("swap", "a");
7957 emitcode ("anl", "a,#0x01");
7960 emitcode ("rl", "a");
7963 emitcode ("rl", "a");
7964 emitcode ("anl", "a,#0x01");
7970 freeAsmop (result, NULL, ic, TRUE);
7971 freeAsmop (right, NULL, ic, TRUE);
7972 freeAsmop (left, NULL, ic, TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genGetByte - generates code get a single byte */
7977 /*-----------------------------------------------------------------*/
7979 genGetByte (iCode * ic)
7981 operand *left, *right, *result;
7984 D (emitcode (";", "genGetByte"));
7986 left = IC_LEFT (ic);
7987 right = IC_RIGHT (ic);
7988 result = IC_RESULT (ic);
7989 aopOp (left, ic, FALSE);
7990 aopOp (right, ic, FALSE);
7991 aopOp (result, ic, FALSE);
7993 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
7995 aopGet (left, offset, FALSE, FALSE),
7998 freeAsmop (result, NULL, ic, TRUE);
7999 freeAsmop (right, NULL, ic, TRUE);
8000 freeAsmop (left, NULL, ic, TRUE);
8003 /*-----------------------------------------------------------------*/
8004 /* genGetWord - generates code get two bytes */
8005 /*-----------------------------------------------------------------*/
8007 genGetWord (iCode * ic)
8009 operand *left, *right, *result;
8012 D (emitcode (";", "genGetWord"));
8014 left = IC_LEFT (ic);
8015 right = IC_RIGHT (ic);
8016 result = IC_RESULT (ic);
8017 aopOp (left, ic, FALSE);
8018 aopOp (right, ic, FALSE);
8019 aopOp (result, ic, FALSE);
8021 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8023 aopGet (left, offset, FALSE, FALSE),
8026 aopGet (left, offset+1, FALSE, FALSE),
8029 freeAsmop (result, NULL, ic, TRUE);
8030 freeAsmop (right, NULL, ic, TRUE);
8031 freeAsmop (left, NULL, ic, TRUE);
8034 /*-----------------------------------------------------------------*/
8035 /* genSwap - generates code to swap nibbles or bytes */
8036 /*-----------------------------------------------------------------*/
8038 genSwap (iCode * ic)
8040 operand *left, *result;
8042 D(emitcode (";", "genSwap"));
8044 left = IC_LEFT (ic);
8045 result = IC_RESULT (ic);
8046 aopOp (left, ic, FALSE);
8047 aopOp (result, ic, FALSE);
8049 switch (AOP_SIZE (left))
8051 case 1: /* swap nibbles in byte */
8052 MOVA (aopGet (left, 0, FALSE, FALSE));
8053 emitcode ("swap", "a");
8054 aopPut (result, "a", 0);
8056 case 2: /* swap bytes in word */
8057 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8059 MOVA (aopGet (left, 0, FALSE, FALSE));
8060 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8061 aopPut (result, "a", 1);
8063 else if (operandsEqu (left, result))
8066 bool pushedB = FALSE, leftInB = FALSE;
8068 MOVA (aopGet (left, 0, FALSE, FALSE));
8069 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8072 emitcode ("mov", "b,a");
8076 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8077 aopPut (result, reg, 1);
8084 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8085 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8089 wassertl(FALSE, "unsupported SWAP operand size");
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (left, NULL, ic, TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* AccRol - rotate left accumulator by known count */
8098 /*-----------------------------------------------------------------*/
8100 AccRol (int shCount)
8102 shCount &= 0x0007; // shCount : 0..7
8109 emitcode ("rl", "a");
8112 emitcode ("rl", "a");
8113 emitcode ("rl", "a");
8116 emitcode ("swap", "a");
8117 emitcode ("rr", "a");
8120 emitcode ("swap", "a");
8123 emitcode ("swap", "a");
8124 emitcode ("rl", "a");
8127 emitcode ("rr", "a");
8128 emitcode ("rr", "a");
8131 emitcode ("rr", "a");
8136 /*-----------------------------------------------------------------*/
8137 /* AccLsh - left shift accumulator by known count */
8138 /*-----------------------------------------------------------------*/
8140 AccLsh (int shCount)
8145 emitcode ("add", "a,acc");
8146 else if (shCount == 2)
8148 emitcode ("add", "a,acc");
8149 emitcode ("add", "a,acc");
8153 /* rotate left accumulator */
8155 /* and kill the lower order bits */
8156 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8161 /*-----------------------------------------------------------------*/
8162 /* AccRsh - right shift accumulator by known count */
8163 /*-----------------------------------------------------------------*/
8165 AccRsh (int shCount)
8172 emitcode ("rrc", "a");
8176 /* rotate right accumulator */
8177 AccRol (8 - shCount);
8178 /* and kill the higher order bits */
8179 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8184 /*-----------------------------------------------------------------*/
8185 /* AccSRsh - signed right shift accumulator by known count */
8186 /*-----------------------------------------------------------------*/
8188 AccSRsh (int shCount)
8195 emitcode ("mov", "c,acc.7");
8196 emitcode ("rrc", "a");
8198 else if (shCount == 2)
8200 emitcode ("mov", "c,acc.7");
8201 emitcode ("rrc", "a");
8202 emitcode ("mov", "c,acc.7");
8203 emitcode ("rrc", "a");
8207 tlbl = newiTempLabel (NULL);
8208 /* rotate right accumulator */
8209 AccRol (8 - shCount);
8210 /* and kill the higher order bits */
8211 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8212 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8213 emitcode ("orl", "a,#0x%02x",
8214 (unsigned char) ~SRMask[shCount]);
8220 /*-----------------------------------------------------------------*/
8221 /* shiftR1Left2Result - shift right one byte from left to result */
8222 /*-----------------------------------------------------------------*/
8224 shiftR1Left2Result (operand * left, int offl,
8225 operand * result, int offr,
8226 int shCount, int sign)
8228 MOVA (aopGet (left, offl, FALSE, FALSE));
8229 /* shift right accumulator */
8234 aopPut (result, "a", offr);
8237 /*-----------------------------------------------------------------*/
8238 /* shiftL1Left2Result - shift left one byte from left to result */
8239 /*-----------------------------------------------------------------*/
8241 shiftL1Left2Result (operand * left, int offl,
8242 operand * result, int offr, int shCount)
8245 l = aopGet (left, offl, FALSE, FALSE);
8247 /* shift left accumulator */
8249 aopPut (result, "a", offr);
8252 /*-----------------------------------------------------------------*/
8253 /* movLeft2Result - move byte from left to result */
8254 /*-----------------------------------------------------------------*/
8256 movLeft2Result (operand * left, int offl,
8257 operand * result, int offr, int sign)
8260 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8262 l = aopGet (left, offl, FALSE, FALSE);
8264 if (*l == '@' && (IS_AOP_PREG (result)))
8266 emitcode ("mov", "a,%s", l);
8267 aopPut (result, "a", offr);
8273 aopPut (result, l, offr);
8277 /* MSB sign in acc.7 ! */
8278 if (getDataSize (left) == offl + 1)
8281 aopPut (result, "a", offr);
8288 /*-----------------------------------------------------------------*/
8289 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8290 /*-----------------------------------------------------------------*/
8294 emitcode ("rrc", "a");
8295 emitcode ("xch", "a,%s", x);
8296 emitcode ("rrc", "a");
8297 emitcode ("xch", "a,%s", x);
8300 /*-----------------------------------------------------------------*/
8301 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8302 /*-----------------------------------------------------------------*/
8306 emitcode ("xch", "a,%s", x);
8307 emitcode ("rlc", "a");
8308 emitcode ("xch", "a,%s", x);
8309 emitcode ("rlc", "a");
8312 /*-----------------------------------------------------------------*/
8313 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8314 /*-----------------------------------------------------------------*/
8318 emitcode ("xch", "a,%s", x);
8319 emitcode ("add", "a,acc");
8320 emitcode ("xch", "a,%s", x);
8321 emitcode ("rlc", "a");
8324 /*-----------------------------------------------------------------*/
8325 /* AccAXLsh - left shift a:x by known count (0..7) */
8326 /*-----------------------------------------------------------------*/
8328 AccAXLsh (char *x, int shCount)
8343 case 5: // AAAAABBB:CCCCCDDD
8345 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8347 emitcode ("anl", "a,#0x%02x",
8348 SLMask[shCount]); // BBB00000:CCCCCDDD
8350 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8352 AccRol (shCount); // DDDCCCCC:BBB00000
8354 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8356 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8358 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8360 emitcode ("anl", "a,#0x%02x",
8361 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8363 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8365 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8368 case 6: // AAAAAABB:CCCCCCDD
8369 emitcode ("anl", "a,#0x%02x",
8370 SRMask[shCount]); // 000000BB:CCCCCCDD
8371 emitcode ("mov", "c,acc.0"); // c = B
8372 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8374 AccAXRrl1 (x); // BCCCCCCD:D000000B
8375 AccAXRrl1 (x); // BBCCCCCC:DD000000
8377 emitcode("rrc","a");
8378 emitcode("xch","a,%s", x);
8379 emitcode("rrc","a");
8380 emitcode("mov","c,acc.0"); //<< get correct bit
8381 emitcode("xch","a,%s", x);
8383 emitcode("rrc","a");
8384 emitcode("xch","a,%s", x);
8385 emitcode("rrc","a");
8386 emitcode("xch","a,%s", x);
8389 case 7: // a:x <<= 7
8391 emitcode ("anl", "a,#0x%02x",
8392 SRMask[shCount]); // 0000000B:CCCCCCCD
8394 emitcode ("mov", "c,acc.0"); // c = B
8396 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8398 AccAXRrl1 (x); // BCCCCCCC:D0000000
8406 /*-----------------------------------------------------------------*/
8407 /* AccAXRsh - right shift a:x known count (0..7) */
8408 /*-----------------------------------------------------------------*/
8410 AccAXRsh (char *x, int shCount)
8418 AccAXRrl1 (x); // 0->a:x
8423 AccAXRrl1 (x); // 0->a:x
8426 AccAXRrl1 (x); // 0->a:x
8431 case 5: // AAAAABBB:CCCCCDDD = a:x
8433 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8435 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8437 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8439 emitcode ("anl", "a,#0x%02x",
8440 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8442 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8444 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8446 emitcode ("anl", "a,#0x%02x",
8447 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8449 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8451 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8453 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8456 case 6: // AABBBBBB:CCDDDDDD
8458 emitcode ("mov", "c,acc.7");
8459 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8461 emitcode ("mov", "c,acc.7");
8462 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8464 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8466 emitcode ("anl", "a,#0x%02x",
8467 SRMask[shCount]); // 000000AA:BBBBBBCC
8470 case 7: // ABBBBBBB:CDDDDDDD
8472 emitcode ("mov", "c,acc.7"); // c = A
8474 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8476 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8478 emitcode ("anl", "a,#0x%02x",
8479 SRMask[shCount]); // 0000000A:BBBBBBBC
8487 /*-----------------------------------------------------------------*/
8488 /* AccAXRshS - right shift signed a:x known count (0..7) */
8489 /*-----------------------------------------------------------------*/
8491 AccAXRshS (char *x, int shCount)
8499 emitcode ("mov", "c,acc.7");
8500 AccAXRrl1 (x); // s->a:x
8504 emitcode ("mov", "c,acc.7");
8505 AccAXRrl1 (x); // s->a:x
8507 emitcode ("mov", "c,acc.7");
8508 AccAXRrl1 (x); // s->a:x
8513 case 5: // AAAAABBB:CCCCCDDD = a:x
8515 tlbl = newiTempLabel (NULL);
8516 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8518 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8520 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8522 emitcode ("anl", "a,#0x%02x",
8523 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8525 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8527 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8529 emitcode ("anl", "a,#0x%02x",
8530 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8532 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8534 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8536 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8538 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8539 emitcode ("orl", "a,#0x%02x",
8540 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8543 break; // SSSSAAAA:BBBCCCCC
8545 case 6: // AABBBBBB:CCDDDDDD
8547 tlbl = newiTempLabel (NULL);
8548 emitcode ("mov", "c,acc.7");
8549 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8551 emitcode ("mov", "c,acc.7");
8552 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8554 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8556 emitcode ("anl", "a,#0x%02x",
8557 SRMask[shCount]); // 000000AA:BBBBBBCC
8559 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8560 emitcode ("orl", "a,#0x%02x",
8561 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8565 case 7: // ABBBBBBB:CDDDDDDD
8567 tlbl = newiTempLabel (NULL);
8568 emitcode ("mov", "c,acc.7"); // c = A
8570 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8572 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8574 emitcode ("anl", "a,#0x%02x",
8575 SRMask[shCount]); // 0000000A:BBBBBBBC
8577 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8578 emitcode ("orl", "a,#0x%02x",
8579 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8588 /*-----------------------------------------------------------------*/
8589 /* shiftL2Left2Result - shift left two bytes from left to result */
8590 /*-----------------------------------------------------------------*/
8592 shiftL2Left2Result (operand * left, int offl,
8593 operand * result, int offr, int shCount)
8596 bool pushedB = FALSE;
8599 if (sameRegs (AOP (result), AOP (left)) &&
8600 ((offl + MSB16) == offr))
8602 /* don't crash result[offr] */
8603 MOVA (aopGet (left, offl, FALSE, FALSE));
8604 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8605 usedB = !strncmp(x, "b", 1);
8607 else if (aopGetUsesAcc (result, offr))
8609 movLeft2Result (left, offl, result, offr, 0);
8612 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8613 MOVA (aopGet (result, offr, FALSE, FALSE));
8614 emitcode ("xch", "a,b");
8619 movLeft2Result (left, offl, result, offr, 0);
8620 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8621 x = aopGet (result, offr, FALSE, FALSE);
8623 /* ax << shCount (x = lsb(result)) */
8624 AccAXLsh (x, shCount);
8627 emitcode ("xch", "a,b");
8628 aopPut (result, "a", offr);
8629 aopPut (result, "b", offr + MSB16);
8634 aopPut (result, "a", offr + MSB16);
8639 /*-----------------------------------------------------------------*/
8640 /* shiftR2Left2Result - shift right two bytes from left to result */
8641 /*-----------------------------------------------------------------*/
8643 shiftR2Left2Result (operand * left, int offl,
8644 operand * result, int offr,
8645 int shCount, int sign)
8648 bool pushedB = FALSE;
8651 if (sameRegs (AOP (result), AOP (left)) &&
8652 ((offl + MSB16) == offr))
8654 /* don't crash result[offr] */
8655 MOVA (aopGet (left, offl, FALSE, FALSE));
8656 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8657 usedB = !strncmp(x, "b", 1);
8659 else if (aopGetUsesAcc (result, offr))
8661 movLeft2Result (left, offl, result, offr, 0);
8664 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8665 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8670 movLeft2Result (left, offl, result, offr, 0);
8671 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8672 x = aopGet (result, offr, FALSE, FALSE);
8674 /* a:x >> shCount (x = lsb(result)) */
8676 AccAXRshS (x, shCount);
8678 AccAXRsh (x, shCount);
8681 emitcode ("xch", "a,b");
8682 aopPut (result, "a", offr);
8683 emitcode ("xch", "a,b");
8686 if (getDataSize (result) > 1)
8687 aopPut (result, "a", offr + MSB16);
8690 /*-----------------------------------------------------------------*/
8691 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8692 /*-----------------------------------------------------------------*/
8694 shiftLLeftOrResult (operand * left, int offl,
8695 operand * result, int offr, int shCount)
8697 MOVA (aopGet (left, offl, FALSE, FALSE));
8698 /* shift left accumulator */
8700 /* or with result */
8701 if (aopGetUsesAcc (result, offr))
8703 emitcode ("xch", "a,b");
8704 MOVA (aopGet (result, offr, FALSE, FALSE));
8705 emitcode ("orl", "a,b");
8709 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8711 /* back to result */
8712 aopPut (result, "a", offr);
8715 /*-----------------------------------------------------------------*/
8716 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8717 /*-----------------------------------------------------------------*/
8719 shiftRLeftOrResult (operand * left, int offl,
8720 operand * result, int offr, int shCount)
8722 MOVA (aopGet (left, offl, FALSE, FALSE));
8723 /* shift right accumulator */
8725 /* or with result */
8726 if (aopGetUsesAcc(result, offr))
8728 emitcode ("xch", "a,b");
8729 MOVA (aopGet (result, offr, FALSE, FALSE));
8730 emitcode ("orl", "a,b");
8734 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8736 /* back to result */
8737 aopPut (result, "a", offr);
8740 /*-----------------------------------------------------------------*/
8741 /* genlshOne - left shift a one byte quantity by known count */
8742 /*-----------------------------------------------------------------*/
8744 genlshOne (operand * result, operand * left, int shCount)
8746 D (emitcode (";", "genlshOne"));
8748 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8751 /*-----------------------------------------------------------------*/
8752 /* genlshTwo - left shift two bytes by known amount != 0 */
8753 /*-----------------------------------------------------------------*/
8755 genlshTwo (operand * result, operand * left, int shCount)
8759 D (emitcode (";", "genlshTwo"));
8761 size = getDataSize (result);
8763 /* if shCount >= 8 */
8771 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8773 movLeft2Result (left, LSB, result, MSB16, 0);
8775 aopPut (result, zero, LSB);
8778 /* 1 <= shCount <= 7 */
8782 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8784 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8788 /*-----------------------------------------------------------------*/
8789 /* shiftLLong - shift left one long from left to result */
8790 /* offl = LSB or MSB16 */
8791 /*-----------------------------------------------------------------*/
8793 shiftLLong (operand * left, operand * result, int offr)
8796 int size = AOP_SIZE (result);
8798 if (size >= LSB + offr)
8800 l = aopGet (left, LSB, FALSE, FALSE);
8802 emitcode ("add", "a,acc");
8803 if (sameRegs (AOP (left), AOP (result)) &&
8804 size >= MSB16 + offr && offr != LSB)
8805 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8807 aopPut (result, "a", LSB + offr);
8810 if (size >= MSB16 + offr)
8812 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8814 l = aopGet (left, MSB16, FALSE, FALSE);
8817 emitcode ("rlc", "a");
8818 if (sameRegs (AOP (left), AOP (result)) &&
8819 size >= MSB24 + offr && offr != LSB)
8820 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8822 aopPut (result, "a", MSB16 + offr);
8825 if (size >= MSB24 + offr)
8827 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8829 l = aopGet (left, MSB24, FALSE, FALSE);
8832 emitcode ("rlc", "a");
8833 if (sameRegs (AOP (left), AOP (result)) &&
8834 size >= MSB32 + offr && offr != LSB)
8835 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8837 aopPut (result, "a", MSB24 + offr);
8840 if (size > MSB32 + offr)
8842 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8844 l = aopGet (left, MSB32, FALSE, FALSE);
8847 emitcode ("rlc", "a");
8848 aopPut (result, "a", MSB32 + offr);
8851 aopPut (result, zero, LSB);
8854 /*-----------------------------------------------------------------*/
8855 /* genlshFour - shift four byte by a known amount != 0 */
8856 /*-----------------------------------------------------------------*/
8858 genlshFour (operand * result, operand * left, int shCount)
8862 D (emitcode (";", "genlshFour"));
8864 size = AOP_SIZE (result);
8866 /* if shifting more that 3 bytes */
8871 /* lowest order of left goes to the highest
8872 order of the destination */
8873 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8875 movLeft2Result (left, LSB, result, MSB32, 0);
8876 aopPut (result, zero, LSB);
8877 aopPut (result, zero, MSB16);
8878 aopPut (result, zero, MSB24);
8882 /* more than two bytes */
8883 else if (shCount >= 16)
8885 /* lower order two bytes goes to higher order two bytes */
8887 /* if some more remaining */
8889 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8892 movLeft2Result (left, MSB16, result, MSB32, 0);
8893 movLeft2Result (left, LSB, result, MSB24, 0);
8895 aopPut (result, zero, MSB16);
8896 aopPut (result, zero, LSB);
8900 /* if more than 1 byte */
8901 else if (shCount >= 8)
8903 /* lower order three bytes goes to higher order three bytes */
8908 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8910 movLeft2Result (left, LSB, result, MSB16, 0);
8916 movLeft2Result (left, MSB24, result, MSB32, 0);
8917 movLeft2Result (left, MSB16, result, MSB24, 0);
8918 movLeft2Result (left, LSB, result, MSB16, 0);
8919 aopPut (result, zero, LSB);
8921 else if (shCount == 1)
8922 shiftLLong (left, result, MSB16);
8925 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8926 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8927 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8928 aopPut (result, zero, LSB);
8933 /* 1 <= shCount <= 7 */
8934 else if (shCount <= 2)
8936 shiftLLong (left, result, LSB);
8938 shiftLLong (result, result, LSB);
8940 /* 3 <= shCount <= 7, optimize */
8943 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8944 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8945 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8949 /*-----------------------------------------------------------------*/
8950 /* genLeftShiftLiteral - left shifting by known count */
8951 /*-----------------------------------------------------------------*/
8953 genLeftShiftLiteral (operand * left,
8958 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8961 D (emitcode (";", "genLeftShiftLiteral"));
8963 freeAsmop (right, NULL, ic, TRUE);
8965 aopOp (left, ic, FALSE);
8966 aopOp (result, ic, FALSE);
8968 size = getSize (operandType (result));
8971 emitcode ("; shift left ", "result %d, left %d", size,
8975 /* I suppose that the left size >= result size */
8980 movLeft2Result (left, size, result, size, 0);
8983 else if (shCount >= (size * 8))
8987 aopPut (result, zero, size);
8995 genlshOne (result, left, shCount);
8999 genlshTwo (result, left, shCount);
9003 genlshFour (result, left, shCount);
9006 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9007 "*** ack! mystery literal shift!\n");
9011 freeAsmop (result, NULL, ic, TRUE);
9012 freeAsmop (left, NULL, ic, TRUE);
9015 /*-----------------------------------------------------------------*/
9016 /* genLeftShift - generates code for left shifting */
9017 /*-----------------------------------------------------------------*/
9019 genLeftShift (iCode * ic)
9021 operand *left, *right, *result;
9024 symbol *tlbl, *tlbl1;
9027 D (emitcode (";", "genLeftShift"));
9029 right = IC_RIGHT (ic);
9030 left = IC_LEFT (ic);
9031 result = IC_RESULT (ic);
9033 aopOp (right, ic, FALSE);
9035 /* if the shift count is known then do it
9036 as efficiently as possible */
9037 if (AOP_TYPE (right) == AOP_LIT)
9039 genLeftShiftLiteral (left, right, result, ic);
9043 /* shift count is unknown then we have to form
9044 a loop get the loop count in B : Note: we take
9045 only the lower order byte since shifting
9046 more that 32 bits make no sense anyway, ( the
9047 largest size of an object can be only 32 bits ) */
9050 MOVB (aopGet (right, 0, FALSE, FALSE));
9051 emitcode ("inc", "b");
9052 freeAsmop (right, NULL, ic, TRUE);
9053 aopOp (left, ic, FALSE);
9054 aopOp (result, ic, FALSE);
9056 /* now move the left to the result if they are not the same */
9057 if (!sameRegs (AOP (left), AOP (result)) &&
9058 AOP_SIZE (result) > 1)
9061 size = AOP_SIZE (result);
9065 l = aopGet (left, offset, FALSE, TRUE);
9066 if (*l == '@' && (IS_AOP_PREG (result)))
9069 emitcode ("mov", "a,%s", l);
9070 aopPut (result, "a", offset);
9073 aopPut (result, l, offset);
9078 tlbl = newiTempLabel (NULL);
9079 size = AOP_SIZE (result);
9081 tlbl1 = newiTempLabel (NULL);
9083 /* if it is only one byte then */
9086 symbol *tlbl1 = newiTempLabel (NULL);
9088 l = aopGet (left, 0, FALSE, FALSE);
9090 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9092 emitcode ("add", "a,acc");
9094 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9096 aopPut (result, "a", 0);
9100 reAdjustPreg (AOP (result));
9102 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9104 l = aopGet (result, offset, FALSE, FALSE);
9106 emitcode ("add", "a,acc");
9107 aopPut (result, "a", offset++);
9110 l = aopGet (result, offset, FALSE, FALSE);
9112 emitcode ("rlc", "a");
9113 aopPut (result, "a", offset++);
9115 reAdjustPreg (AOP (result));
9118 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9121 freeAsmop (result, NULL, ic, TRUE);
9122 freeAsmop (left, NULL, ic, TRUE);
9125 /*-----------------------------------------------------------------*/
9126 /* genrshOne - right shift a one byte quantity by known count */
9127 /*-----------------------------------------------------------------*/
9129 genrshOne (operand * result, operand * left,
9130 int shCount, int sign)
9132 D (emitcode (";", "genrshOne"));
9134 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9137 /*-----------------------------------------------------------------*/
9138 /* genrshTwo - right shift two bytes by known amount != 0 */
9139 /*-----------------------------------------------------------------*/
9141 genrshTwo (operand * result, operand * left,
9142 int shCount, int sign)
9144 D (emitcode (";", "genrshTwo"));
9146 /* if shCount >= 8 */
9151 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9153 movLeft2Result (left, MSB16, result, LSB, sign);
9154 addSign (result, MSB16, sign);
9157 /* 1 <= shCount <= 7 */
9159 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9162 /*-----------------------------------------------------------------*/
9163 /* shiftRLong - shift right one long from left to result */
9164 /* offl = LSB or MSB16 */
9165 /*-----------------------------------------------------------------*/
9167 shiftRLong (operand * left, int offl,
9168 operand * result, int sign)
9170 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9172 if (overlapping && offl>1)
9174 // we are in big trouble, but this shouldn't happen
9175 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9178 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9185 emitcode ("rlc", "a");
9186 emitcode ("subb", "a,acc");
9187 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9189 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9193 aopPut (result, "a", MSB32);
9194 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9199 if (aopPutUsesAcc (result, zero, MSB32))
9201 emitcode("xch", "a,b");
9202 aopPut (result, zero, MSB32);
9203 emitcode("xch", "a,b");
9207 aopPut (result, zero, MSB32);
9214 emitcode ("clr", "c");
9218 emitcode ("mov", "c,acc.7");
9221 emitcode ("rrc", "a");
9223 if (overlapping && offl==MSB16 &&
9224 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9226 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9230 aopPut (result, "a", MSB32 - offl);
9231 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9234 emitcode ("rrc", "a");
9235 if (overlapping && offl==MSB16 &&
9236 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9238 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9242 aopPut (result, "a", MSB24 - offl);
9243 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9246 emitcode ("rrc", "a");
9249 aopPut (result, "a", MSB16 - offl);
9254 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9256 xch_a_aopGet (left, LSB, FALSE, FALSE);
9260 aopPut (result, "a", MSB16 - offl);
9261 MOVA (aopGet (left, LSB, FALSE, FALSE));
9263 emitcode ("rrc", "a");
9264 aopPut (result, "a", LSB);
9268 /*-----------------------------------------------------------------*/
9269 /* genrshFour - shift four byte by a known amount != 0 */
9270 /*-----------------------------------------------------------------*/
9272 genrshFour (operand * result, operand * left,
9273 int shCount, int sign)
9275 D (emitcode (";", "genrshFour"));
9277 /* if shifting more that 3 bytes */
9282 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9284 movLeft2Result (left, MSB32, result, LSB, sign);
9285 addSign (result, MSB16, sign);
9287 else if (shCount >= 16)
9291 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9294 movLeft2Result (left, MSB24, result, LSB, 0);
9295 movLeft2Result (left, MSB32, result, MSB16, sign);
9297 addSign (result, MSB24, sign);
9299 else if (shCount >= 8)
9304 shiftRLong (left, MSB16, result, sign);
9306 else if (shCount == 0)
9308 movLeft2Result (left, MSB16, result, LSB, 0);
9309 movLeft2Result (left, MSB24, result, MSB16, 0);
9310 movLeft2Result (left, MSB32, result, MSB24, sign);
9311 addSign (result, MSB32, sign);
9315 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9316 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9317 /* the last shift is signed */
9318 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9319 addSign (result, MSB32, sign);
9324 /* 1 <= shCount <= 7 */
9327 shiftRLong (left, LSB, result, sign);
9329 shiftRLong (result, LSB, result, sign);
9333 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9334 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9335 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9340 /*-----------------------------------------------------------------*/
9341 /* genRightShiftLiteral - right shifting by known count */
9342 /*-----------------------------------------------------------------*/
9344 genRightShiftLiteral (operand * left,
9350 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9353 D (emitcode (";", "genRightShiftLiteral"));
9355 freeAsmop (right, NULL, ic, TRUE);
9357 aopOp (left, ic, FALSE);
9358 aopOp (result, ic, FALSE);
9361 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9365 size = getDataSize (left);
9366 /* test the LEFT size !!! */
9368 /* I suppose that the left size >= result size */
9371 size = getDataSize (result);
9373 movLeft2Result (left, size, result, size, 0);
9376 else if (shCount >= (size * 8))
9380 /* get sign in acc.7 */
9381 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9383 addSign (result, LSB, sign);
9390 genrshOne (result, left, shCount, sign);
9394 genrshTwo (result, left, shCount, sign);
9398 genrshFour (result, left, shCount, sign);
9404 freeAsmop (result, NULL, ic, TRUE);
9405 freeAsmop (left, NULL, ic, TRUE);
9408 /*-----------------------------------------------------------------*/
9409 /* genSignedRightShift - right shift of signed number */
9410 /*-----------------------------------------------------------------*/
9412 genSignedRightShift (iCode * ic)
9414 operand *right, *left, *result;
9417 symbol *tlbl, *tlbl1;
9420 D (emitcode (";", "genSignedRightShift"));
9422 /* we do it the hard way put the shift count in b
9423 and loop thru preserving the sign */
9425 right = IC_RIGHT (ic);
9426 left = IC_LEFT (ic);
9427 result = IC_RESULT (ic);
9429 aopOp (right, ic, FALSE);
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 genRightShiftLiteral (left, right, result, ic, 1);
9437 /* shift count is unknown then we have to form
9438 a loop get the loop count in B : Note: we take
9439 only the lower order byte since shifting
9440 more that 32 bits make no sense anyway, ( the
9441 largest size of an object can be only 32 bits ) */
9444 MOVB (aopGet (right, 0, FALSE, FALSE));
9445 emitcode ("inc", "b");
9446 freeAsmop (right, NULL, ic, TRUE);
9447 aopOp (left, ic, FALSE);
9448 aopOp (result, ic, FALSE);
9450 /* now move the left to the result if they are not the
9452 if (!sameRegs (AOP (left), AOP (result)) &&
9453 AOP_SIZE (result) > 1)
9456 size = AOP_SIZE (result);
9460 l = aopGet (left, offset, FALSE, TRUE);
9461 if (*l == '@' && IS_AOP_PREG (result))
9464 emitcode ("mov", "a,%s", l);
9465 aopPut (result, "a", offset);
9468 aopPut (result, l, offset);
9473 /* mov the highest order bit to OVR */
9474 tlbl = newiTempLabel (NULL);
9475 tlbl1 = newiTempLabel (NULL);
9477 size = AOP_SIZE (result);
9479 MOVA (aopGet (left, offset, FALSE, FALSE));
9480 emitcode ("rlc", "a");
9481 emitcode ("mov", "ov,c");
9482 /* if it is only one byte then */
9485 l = aopGet (left, 0, FALSE, FALSE);
9487 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9489 emitcode ("mov", "c,ov");
9490 emitcode ("rrc", "a");
9492 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9494 aopPut (result, "a", 0);
9498 reAdjustPreg (AOP (result));
9499 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9501 emitcode ("mov", "c,ov");
9504 l = aopGet (result, offset, FALSE, FALSE);
9506 emitcode ("rrc", "a");
9507 aopPut (result, "a", offset--);
9509 reAdjustPreg (AOP (result));
9511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9515 freeAsmop (result, NULL, ic, TRUE);
9516 freeAsmop (left, NULL, ic, TRUE);
9519 /*-----------------------------------------------------------------*/
9520 /* genRightShift - generate code for right shifting */
9521 /*-----------------------------------------------------------------*/
9523 genRightShift (iCode * ic)
9525 operand *right, *left, *result;
9529 symbol *tlbl, *tlbl1;
9532 D (emitcode (";", "genRightShift"));
9534 /* if signed then we do it the hard way preserve the
9535 sign bit moving it inwards */
9536 letype = getSpec (operandType (IC_LEFT (ic)));
9538 if (!SPEC_USIGN (letype))
9540 genSignedRightShift (ic);
9544 /* signed & unsigned types are treated the same : i.e. the
9545 signed is NOT propagated inwards : quoting from the
9546 ANSI - standard : "for E1 >> E2, is equivalent to division
9547 by 2**E2 if unsigned or if it has a non-negative value,
9548 otherwise the result is implementation defined ", MY definition
9549 is that the sign does not get propagated */
9551 right = IC_RIGHT (ic);
9552 left = IC_LEFT (ic);
9553 result = IC_RESULT (ic);
9555 aopOp (right, ic, FALSE);
9557 /* if the shift count is known then do it
9558 as efficiently as possible */
9559 if (AOP_TYPE (right) == AOP_LIT)
9561 genRightShiftLiteral (left, right, result, ic, 0);
9565 /* shift count is unknown then we have to form
9566 a loop get the loop count in B : Note: we take
9567 only the lower order byte since shifting
9568 more that 32 bits make no sense anyway, ( the
9569 largest size of an object can be only 32 bits ) */
9572 MOVB (aopGet (right, 0, FALSE, FALSE));
9573 emitcode ("inc", "b");
9574 freeAsmop (right, NULL, ic, TRUE);
9575 aopOp (left, ic, FALSE);
9576 aopOp (result, ic, FALSE);
9578 /* now move the left to the result if they are not the
9580 if (!sameRegs (AOP (left), AOP (result)) &&
9581 AOP_SIZE (result) > 1)
9583 size = AOP_SIZE (result);
9587 l = aopGet (left, offset, FALSE, TRUE);
9588 if (*l == '@' && IS_AOP_PREG (result))
9591 emitcode ("mov", "a,%s", l);
9592 aopPut (result, "a", offset);
9595 aopPut (result, l, offset);
9600 tlbl = newiTempLabel (NULL);
9601 tlbl1 = newiTempLabel (NULL);
9602 size = AOP_SIZE (result);
9605 /* if it is only one byte then */
9608 l = aopGet (left, 0, FALSE, FALSE);
9610 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9613 emitcode ("rrc", "a");
9615 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9617 aopPut (result, "a", 0);
9621 reAdjustPreg (AOP (result));
9622 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9627 l = aopGet (result, offset, FALSE, FALSE);
9629 emitcode ("rrc", "a");
9630 aopPut (result, "a", offset--);
9632 reAdjustPreg (AOP (result));
9635 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9639 freeAsmop (result, NULL, ic, TRUE);
9640 freeAsmop (left, NULL, ic, TRUE);
9643 /*-----------------------------------------------------------------*/
9644 /* emitPtrByteGet - emits code to get a byte into A through a */
9645 /* pointer register (R0, R1, or DPTR). The */
9646 /* original value of A can be preserved in B. */
9647 /*-----------------------------------------------------------------*/
9649 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9656 emitcode ("mov", "b,a");
9657 emitcode ("mov", "a,@%s", rname);
9662 emitcode ("mov", "b,a");
9663 emitcode ("movx", "a,@%s", rname);
9668 emitcode ("mov", "b,a");
9669 emitcode ("movx", "a,@dptr");
9674 emitcode ("mov", "b,a");
9675 emitcode ("clr", "a");
9676 emitcode ("movc", "a,@a+dptr");
9682 emitcode ("push", "b");
9683 emitcode ("push", "acc");
9685 emitcode ("lcall", "__gptrget");
9687 emitcode ("pop", "b");
9692 /*-----------------------------------------------------------------*/
9693 /* emitPtrByteSet - emits code to set a byte from src through a */
9694 /* pointer register (R0, R1, or DPTR). */
9695 /*-----------------------------------------------------------------*/
9697 emitPtrByteSet (char *rname, int p_type, char *src)
9706 emitcode ("mov", "@%s,a", rname);
9709 emitcode ("mov", "@%s,%s", rname, src);
9714 emitcode ("movx", "@%s,a", rname);
9719 emitcode ("movx", "@dptr,a");
9724 emitcode ("lcall", "__gptrput");
9729 /*-----------------------------------------------------------------*/
9730 /* genUnpackBits - generates code for unpacking bits */
9731 /*-----------------------------------------------------------------*/
9733 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9735 int offset = 0; /* result byte offset */
9736 int rsize; /* result size */
9737 int rlen = 0; /* remaining bitfield length */
9738 sym_link *etype; /* bitfield type information */
9739 int blen; /* bitfield length */
9740 int bstr; /* bitfield starting bit within byte */
9743 D(emitcode (";", "genUnpackBits"));
9745 etype = getSpec (operandType (result));
9746 rsize = getSize (operandType (result));
9747 blen = SPEC_BLEN (etype);
9748 bstr = SPEC_BSTR (etype);
9750 if (ifx && blen <= 8)
9752 emitPtrByteGet (rname, ptype, FALSE);
9755 SNPRINTF (buffer, sizeof(buffer),
9757 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9762 emitcode ("anl", "a,#0x%02x",
9763 (((unsigned char) -1) >> (8 - blen)) << bstr);
9764 genIfxJump (ifx, "a", NULL, NULL, NULL);
9770 /* If the bitfield length is less than a byte */
9773 emitPtrByteGet (rname, ptype, FALSE);
9775 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9776 if (!SPEC_USIGN (etype))
9778 /* signed bitfield */
9779 symbol *tlbl = newiTempLabel (NULL);
9781 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9782 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9785 aopPut (result, "a", offset++);
9789 /* Bit field did not fit in a byte. Copy all
9790 but the partial byte at the end. */
9791 for (rlen=blen;rlen>=8;rlen-=8)
9793 emitPtrByteGet (rname, ptype, FALSE);
9794 aopPut (result, "a", offset++);
9796 emitcode ("inc", "%s", rname);
9799 /* Handle the partial byte at the end */
9802 emitPtrByteGet (rname, ptype, FALSE);
9803 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9804 if (!SPEC_USIGN (etype))
9806 /* signed bitfield */
9807 symbol *tlbl = newiTempLabel (NULL);
9809 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9810 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9813 aopPut (result, "a", offset++);
9821 if (SPEC_USIGN (etype))
9825 /* signed bitfield: sign extension with 0x00 or 0xff */
9826 emitcode ("rlc", "a");
9827 emitcode ("subb", "a,acc");
9833 aopPut (result, source, offset++);
9838 /*-----------------------------------------------------------------*/
9839 /* genDataPointerGet - generates code when ptr offset is known */
9840 /*-----------------------------------------------------------------*/
9842 genDataPointerGet (operand * left,
9848 int size, offset = 0;
9850 D (emitcode (";", "genDataPointerGet"));
9852 aopOp (result, ic, TRUE);
9854 /* get the string representation of the name */
9855 l = aopGet (left, 0, FALSE, TRUE);
9857 size = AOP_SIZE (result);
9862 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9866 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9868 aopPut (result, buffer, offset++);
9871 freeAsmop (result, NULL, ic, TRUE);
9872 freeAsmop (left, NULL, ic, TRUE);
9875 /*-----------------------------------------------------------------*/
9876 /* genNearPointerGet - emitcode for near pointer fetch */
9877 /*-----------------------------------------------------------------*/
9879 genNearPointerGet (operand * left,
9888 sym_link *rtype, *retype;
9889 sym_link *ltype = operandType (left);
9892 D (emitcode (";", "genNearPointerGet"));
9894 rtype = operandType (result);
9895 retype = getSpec (rtype);
9897 aopOp (left, ic, FALSE);
9899 /* if left is rematerialisable and
9900 result is not bitfield variable type and
9901 the left is pointer to data space i.e
9902 lower 128 bytes of space */
9903 if (AOP_TYPE (left) == AOP_IMMD &&
9904 !IS_BITFIELD (retype) &&
9905 DCL_TYPE (ltype) == POINTER)
9907 genDataPointerGet (left, result, ic);
9911 /* if the value is already in a pointer register
9912 then don't need anything more */
9913 if (!AOP_INPREG (AOP (left)))
9915 if (IS_AOP_PREG (left))
9917 // Aha, it is a pointer, just in disguise.
9918 rname = aopGet (left, 0, FALSE, FALSE);
9921 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9922 __FILE__, __LINE__);
9927 emitcode ("mov", "a%s,%s", rname + 1, rname);
9928 rname++; // skip the '@'.
9933 /* otherwise get a free pointer register */
9935 preg = getFreePtr (ic, &aop, FALSE);
9936 emitcode ("mov", "%s,%s",
9938 aopGet (left, 0, FALSE, TRUE));
9943 rname = aopGet (left, 0, FALSE, FALSE);
9945 //aopOp (result, ic, FALSE);
9946 aopOp (result, ic, result?TRUE:FALSE);
9948 /* if bitfield then unpack the bits */
9949 if (IS_BITFIELD (retype))
9950 genUnpackBits (result, rname, POINTER, ifx);
9953 /* we have can just get the values */
9954 int size = AOP_SIZE (result);
9959 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9962 emitcode ("mov", "a,@%s", rname);
9964 aopPut (result, "a", offset);
9968 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9969 aopPut (result, buffer, offset);
9973 emitcode ("inc", "%s", rname);
9977 /* now some housekeeping stuff */
9978 if (aop) /* we had to allocate for this iCode */
9980 if (pi) { /* post increment present */
9981 aopPut (left, rname, 0);
9983 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9987 /* we did not allocate which means left
9988 already in a pointer register, then
9989 if size > 0 && this could be used again
9990 we have to point it back to where it
9992 if ((AOP_SIZE (result) > 1 &&
9993 !OP_SYMBOL (left)->remat &&
9994 (OP_SYMBOL (left)->liveTo > ic->seq ||
9998 int size = AOP_SIZE (result) - 1;
10000 emitcode ("dec", "%s", rname);
10004 if (ifx && !ifx->generated)
10006 genIfxJump (ifx, "a", left, NULL, result);
10010 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10011 freeAsmop (left, NULL, ic, TRUE);
10012 if (pi) pi->generated = 1;
10015 /*-----------------------------------------------------------------*/
10016 /* genPagedPointerGet - emitcode for paged pointer fetch */
10017 /*-----------------------------------------------------------------*/
10019 genPagedPointerGet (operand * left,
10028 sym_link *rtype, *retype;
10030 D (emitcode (";", "genPagedPointerGet"));
10032 rtype = operandType (result);
10033 retype = getSpec (rtype);
10035 aopOp (left, ic, FALSE);
10037 /* if the value is already in a pointer register
10038 then don't need anything more */
10039 if (!AOP_INPREG (AOP (left)))
10041 /* otherwise get a free pointer register */
10042 aop = newAsmop (0);
10043 preg = getFreePtr (ic, &aop, FALSE);
10044 emitcode ("mov", "%s,%s",
10046 aopGet (left, 0, FALSE, TRUE));
10047 rname = preg->name;
10050 rname = aopGet (left, 0, FALSE, FALSE);
10052 aopOp (result, ic, FALSE);
10054 /* if bitfield then unpack the bits */
10055 if (IS_BITFIELD (retype))
10056 genUnpackBits (result, rname, PPOINTER, ifx);
10059 /* we have can just get the values */
10060 int size = AOP_SIZE (result);
10066 emitcode ("movx", "a,@%s", rname);
10068 aopPut (result, "a", offset);
10073 emitcode ("inc", "%s", rname);
10077 /* now some housekeeping stuff */
10078 if (aop) /* we had to allocate for this iCode */
10081 aopPut (left, rname, 0);
10082 freeAsmop (NULL, aop, ic, TRUE);
10086 /* we did not allocate which means left
10087 already in a pointer register, then
10088 if size > 0 && this could be used again
10089 we have to point it back to where it
10091 if ((AOP_SIZE (result) > 1 &&
10092 !OP_SYMBOL (left)->remat &&
10093 (OP_SYMBOL (left)->liveTo > ic->seq ||
10097 int size = AOP_SIZE (result) - 1;
10099 emitcode ("dec", "%s", rname);
10103 if (ifx && !ifx->generated)
10105 genIfxJump (ifx, "a", left, NULL, result);
10109 freeAsmop (result, NULL, ic, TRUE);
10110 freeAsmop (left, NULL, ic, TRUE);
10111 if (pi) pi->generated = 1;
10114 /*--------------------------------------------------------------------*/
10115 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10116 /*--------------------------------------------------------------------*/
10118 loadDptrFromOperand (operand *op, bool loadBToo)
10120 if (AOP_TYPE (op) != AOP_STR)
10122 /* if this is rematerializable */
10123 if (AOP_TYPE (op) == AOP_IMMD)
10125 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10128 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10129 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10132 wassertl(FALSE, "need pointerCode");
10133 emitcode (";", "mov b,???");
10134 /* genPointerGet and genPointerSet originally did different
10135 ** things for this case. Both seem wrong.
10136 ** from genPointerGet:
10137 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10138 ** from genPointerSet:
10139 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10144 else if (AOP_TYPE (op) == AOP_DPTR)
10148 MOVA (aopGet (op, 0, FALSE, FALSE));
10149 emitcode ("push", "acc");
10150 MOVA (aopGet (op, 1, FALSE, FALSE));
10151 emitcode ("push", "acc");
10152 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10153 emitcode ("pop", "dph");
10154 emitcode ("pop", "dpl");
10158 MOVA (aopGet (op, 0, FALSE, FALSE));
10159 emitcode ("push", "acc");
10160 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10161 emitcode ("pop", "dpl");
10165 { /* we need to get it byte by byte */
10166 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10167 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10169 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10174 /*-----------------------------------------------------------------*/
10175 /* genFarPointerGet - get value from far space */
10176 /*-----------------------------------------------------------------*/
10178 genFarPointerGet (operand * left,
10179 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10182 sym_link *retype = getSpec (operandType (result));
10184 D (emitcode (";", "genFarPointerGet"));
10186 aopOp (left, ic, FALSE);
10187 loadDptrFromOperand (left, FALSE);
10189 /* so dptr now contains the address */
10190 aopOp (result, ic, FALSE);
10192 /* if bit then unpack */
10193 if (IS_BITFIELD (retype))
10194 genUnpackBits (result, "dptr", FPOINTER, ifx);
10197 size = AOP_SIZE (result);
10202 emitcode ("movx", "a,@dptr");
10204 aopPut (result, "a", offset++);
10206 emitcode ("inc", "dptr");
10210 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10212 aopPut (left, "dpl", 0);
10213 aopPut (left, "dph", 1);
10217 if (ifx && !ifx->generated)
10219 genIfxJump (ifx, "a", left, NULL, result);
10222 freeAsmop (result, NULL, ic, TRUE);
10223 freeAsmop (left, NULL, ic, TRUE);
10226 /*-----------------------------------------------------------------*/
10227 /* genCodePointerGet - get value from code space */
10228 /*-----------------------------------------------------------------*/
10230 genCodePointerGet (operand * left,
10231 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10234 sym_link *retype = getSpec (operandType (result));
10236 D (emitcode (";", "genCodePointerGet"));
10238 aopOp (left, ic, FALSE);
10239 loadDptrFromOperand (left, FALSE);
10241 /* so dptr now contains the address */
10242 aopOp (result, ic, FALSE);
10244 /* if bit then unpack */
10245 if (IS_BITFIELD (retype))
10246 genUnpackBits (result, "dptr", CPOINTER, ifx);
10249 size = AOP_SIZE (result);
10254 emitcode ("clr", "a");
10255 emitcode ("movc", "a,@a+dptr");
10257 aopPut (result, "a", offset++);
10259 emitcode ("inc", "dptr");
10263 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10265 aopPut (left, "dpl", 0);
10266 aopPut (left, "dph", 1);
10270 if (ifx && !ifx->generated)
10272 genIfxJump (ifx, "a", left, NULL, result);
10275 freeAsmop (result, NULL, ic, TRUE);
10276 freeAsmop (left, NULL, ic, TRUE);
10279 /*-----------------------------------------------------------------*/
10280 /* genGenPointerGet - get value from generic pointer space */
10281 /*-----------------------------------------------------------------*/
10283 genGenPointerGet (operand * left,
10284 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10287 sym_link *retype = getSpec (operandType (result));
10289 D (emitcode (";", "genGenPointerGet"));
10291 aopOp (left, ic, FALSE);
10292 loadDptrFromOperand (left, TRUE);
10294 /* so dptr now contains the address */
10295 aopOp (result, ic, FALSE);
10297 /* if bit then unpack */
10298 if (IS_BITFIELD (retype))
10300 genUnpackBits (result, "dptr", GPOINTER, ifx);
10304 size = AOP_SIZE (result);
10309 emitcode ("lcall", "__gptrget");
10311 aopPut (result, "a", offset++);
10313 emitcode ("inc", "dptr");
10317 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10319 aopPut (left, "dpl", 0);
10320 aopPut (left, "dph", 1);
10324 if (ifx && !ifx->generated)
10326 genIfxJump (ifx, "a", left, NULL, result);
10329 freeAsmop (result, NULL, ic, TRUE);
10330 freeAsmop (left, NULL, ic, TRUE);
10333 /*-----------------------------------------------------------------*/
10334 /* genPointerGet - generate code for pointer get */
10335 /*-----------------------------------------------------------------*/
10337 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10339 operand *left, *result;
10340 sym_link *type, *etype;
10343 D (emitcode (";", "genPointerGet"));
10345 left = IC_LEFT (ic);
10346 result = IC_RESULT (ic);
10348 if (getSize (operandType (result))>1)
10351 /* depending on the type of pointer we need to
10352 move it to the correct pointer register */
10353 type = operandType (left);
10354 etype = getSpec (type);
10355 /* if left is of type of pointer then it is simple */
10356 if (IS_PTR (type) && !IS_FUNC (type->next))
10357 p_type = DCL_TYPE (type);
10360 /* we have to go by the storage class */
10361 p_type = PTR_TYPE (SPEC_OCLS (etype));
10364 /* special case when cast remat */
10365 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10366 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10368 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10369 type = operandType (left);
10370 p_type = DCL_TYPE (type);
10372 /* now that we have the pointer type we assign
10373 the pointer values */
10379 genNearPointerGet (left, result, ic, pi, ifx);
10383 genPagedPointerGet (left, result, ic, pi, ifx);
10387 genFarPointerGet (left, result, ic, pi, ifx);
10391 genCodePointerGet (left, result, ic, pi, ifx);
10395 genGenPointerGet (left, result, ic, pi, ifx);
10401 /*-----------------------------------------------------------------*/
10402 /* genPackBits - generates code for packed bit storage */
10403 /*-----------------------------------------------------------------*/
10405 genPackBits (sym_link * etype,
10407 char *rname, int p_type)
10409 int offset = 0; /* source byte offset */
10410 int rlen = 0; /* remaining bitfield length */
10411 int blen; /* bitfield length */
10412 int bstr; /* bitfield starting bit within byte */
10413 int litval; /* source literal value (if AOP_LIT) */
10414 unsigned char mask; /* bitmask within current byte */
10416 D(emitcode (";", "genPackBits"));
10418 blen = SPEC_BLEN (etype);
10419 bstr = SPEC_BSTR (etype);
10421 /* If the bitfield length is less than a byte */
10424 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10425 (unsigned char) (0xFF >> (8 - bstr)));
10427 if (AOP_TYPE (right) == AOP_LIT)
10429 /* Case with a bitfield length <8 and literal source
10431 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10433 litval &= (~mask) & 0xff;
10434 emitPtrByteGet (rname, p_type, FALSE);
10435 if ((mask|litval)!=0xff)
10436 emitcode ("anl","a,#0x%02x", mask);
10438 emitcode ("orl","a,#0x%02x", litval);
10442 if ((blen==1) && (p_type!=GPOINTER))
10444 /* Case with a bitfield length == 1 and no generic pointer
10446 if (AOP_TYPE (right) == AOP_CRY)
10447 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10450 MOVA (aopGet (right, 0, FALSE, FALSE));
10451 emitcode ("rrc","a");
10453 emitPtrByteGet (rname, p_type, FALSE);
10454 emitcode ("mov","acc.%d,c",bstr);
10459 /* Case with a bitfield length < 8 and arbitrary source
10461 MOVA (aopGet (right, 0, FALSE, FALSE));
10462 /* shift and mask source value */
10464 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10466 pushedB = pushB ();
10467 /* transfer A to B and get next byte */
10468 emitPtrByteGet (rname, p_type, TRUE);
10470 emitcode ("anl", "a,#0x%02x", mask);
10471 emitcode ("orl", "a,b");
10472 if (p_type == GPOINTER)
10473 emitcode ("pop", "b");
10479 emitPtrByteSet (rname, p_type, "a");
10483 /* Bit length is greater than 7 bits. In this case, copy */
10484 /* all except the partial byte at the end */
10485 for (rlen=blen;rlen>=8;rlen-=8)
10487 emitPtrByteSet (rname, p_type,
10488 aopGet (right, offset++, FALSE, TRUE) );
10490 emitcode ("inc", "%s", rname);
10493 /* If there was a partial byte at the end */
10496 mask = (((unsigned char) -1 << rlen) & 0xff);
10498 if (AOP_TYPE (right) == AOP_LIT)
10500 /* Case with partial byte and literal source
10502 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10503 litval >>= (blen-rlen);
10504 litval &= (~mask) & 0xff;
10505 emitPtrByteGet (rname, p_type, FALSE);
10506 if ((mask|litval)!=0xff)
10507 emitcode ("anl","a,#0x%02x", mask);
10509 emitcode ("orl","a,#0x%02x", litval);
10514 /* Case with partial byte and arbitrary source
10516 MOVA (aopGet (right, offset++, FALSE, FALSE));
10517 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10519 pushedB = pushB ();
10520 /* transfer A to B and get next byte */
10521 emitPtrByteGet (rname, p_type, TRUE);
10523 emitcode ("anl", "a,#0x%02x", mask);
10524 emitcode ("orl", "a,b");
10525 if (p_type == GPOINTER)
10526 emitcode ("pop", "b");
10530 emitPtrByteSet (rname, p_type, "a");
10535 /*-----------------------------------------------------------------*/
10536 /* genDataPointerSet - remat pointer to data space */
10537 /*-----------------------------------------------------------------*/
10539 genDataPointerSet (operand * right,
10543 int size, offset = 0;
10544 char *l, buffer[256];
10546 D (emitcode (";", "genDataPointerSet"));
10548 aopOp (right, ic, FALSE);
10550 l = aopGet (result, 0, FALSE, TRUE);
10552 size = max (AOP_SIZE (right), AOP_SIZE (result));
10556 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10558 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10559 emitcode ("mov", "%s,%s", buffer,
10560 aopGet (right, offset++, FALSE, FALSE));
10563 freeAsmop (right, NULL, ic, TRUE);
10564 freeAsmop (result, NULL, ic, TRUE);
10567 /*-----------------------------------------------------------------*/
10568 /* genNearPointerSet - emitcode for near pointer put */
10569 /*-----------------------------------------------------------------*/
10571 genNearPointerSet (operand * right,
10579 sym_link *retype, *letype;
10580 sym_link *ptype = operandType (result);
10582 D (emitcode (";", "genNearPointerSet"));
10584 retype = getSpec (operandType (right));
10585 letype = getSpec (ptype);
10587 aopOp (result, ic, FALSE);
10589 /* if the result is rematerializable &
10590 in data space & not a bit variable */
10591 if (AOP_TYPE (result) == AOP_IMMD &&
10592 DCL_TYPE (ptype) == POINTER &&
10593 !IS_BITVAR (retype) &&
10594 !IS_BITVAR (letype))
10596 genDataPointerSet (right, result, ic);
10600 /* if the value is already in a pointer register
10601 then don't need anything more */
10602 if (!AOP_INPREG (AOP (result)))
10605 //AOP_TYPE (result) == AOP_STK
10606 IS_AOP_PREG(result)
10609 // Aha, it is a pointer, just in disguise.
10610 rname = aopGet (result, 0, FALSE, FALSE);
10613 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10614 __FILE__, __LINE__);
10619 emitcode ("mov", "a%s,%s", rname + 1, rname);
10620 rname++; // skip the '@'.
10625 /* otherwise get a free pointer register */
10626 aop = newAsmop (0);
10627 preg = getFreePtr (ic, &aop, FALSE);
10628 emitcode ("mov", "%s,%s",
10630 aopGet (result, 0, FALSE, TRUE));
10631 rname = preg->name;
10636 rname = aopGet (result, 0, FALSE, FALSE);
10639 aopOp (right, ic, FALSE);
10641 /* if bitfield then unpack the bits */
10642 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10643 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10646 /* we can just get the values */
10647 int size = AOP_SIZE (right);
10652 l = aopGet (right, offset, FALSE, TRUE);
10653 if ((*l == '@') || (strcmp (l, "acc") == 0))
10656 emitcode ("mov", "@%s,a", rname);
10659 emitcode ("mov", "@%s,%s", rname, l);
10661 emitcode ("inc", "%s", rname);
10666 /* now some housekeeping stuff */
10667 if (aop) /* we had to allocate for this iCode */
10670 aopPut (result, rname, 0);
10671 freeAsmop (NULL, aop, ic, TRUE);
10675 /* we did not allocate which means left
10676 already in a pointer register, then
10677 if size > 0 && this could be used again
10678 we have to point it back to where it
10680 if ((AOP_SIZE (right) > 1 &&
10681 !OP_SYMBOL (result)->remat &&
10682 (OP_SYMBOL (result)->liveTo > ic->seq ||
10686 int size = AOP_SIZE (right) - 1;
10688 emitcode ("dec", "%s", rname);
10695 freeAsmop (right, NULL, ic, TRUE);
10696 freeAsmop (result, NULL, ic, TRUE);
10699 /*-----------------------------------------------------------------*/
10700 /* genPagedPointerSet - emitcode for Paged pointer put */
10701 /*-----------------------------------------------------------------*/
10703 genPagedPointerSet (operand * right,
10711 sym_link *retype, *letype;
10713 D (emitcode (";", "genPagedPointerSet"));
10715 retype = getSpec (operandType (right));
10716 letype = getSpec (operandType (result));
10718 aopOp (result, ic, FALSE);
10720 /* if the value is already in a pointer register
10721 then don't need anything more */
10722 if (!AOP_INPREG (AOP (result)))
10724 /* otherwise get a free pointer register */
10725 aop = newAsmop (0);
10726 preg = getFreePtr (ic, &aop, FALSE);
10727 emitcode ("mov", "%s,%s",
10729 aopGet (result, 0, FALSE, TRUE));
10730 rname = preg->name;
10733 rname = aopGet (result, 0, FALSE, FALSE);
10735 aopOp (right, ic, FALSE);
10737 /* if bitfield then unpack the bits */
10738 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10739 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10742 /* we have can just get the values */
10743 int size = AOP_SIZE (right);
10748 l = aopGet (right, offset, FALSE, TRUE);
10750 emitcode ("movx", "@%s,a", rname);
10753 emitcode ("inc", "%s", rname);
10759 /* now some housekeeping stuff */
10760 if (aop) /* we had to allocate for this iCode */
10763 aopPut (result, rname, 0);
10764 freeAsmop (NULL, aop, ic, TRUE);
10768 /* we did not allocate which means left
10769 already in a pointer register, then
10770 if size > 0 && this could be used again
10771 we have to point it back to where it
10773 if (AOP_SIZE (right) > 1 &&
10774 !OP_SYMBOL (result)->remat &&
10775 (OP_SYMBOL (result)->liveTo > ic->seq ||
10778 int size = AOP_SIZE (right) - 1;
10780 emitcode ("dec", "%s", rname);
10785 if (pi) pi->generated = 1;
10786 freeAsmop (result, NULL, ic, TRUE);
10787 freeAsmop (right, NULL, ic, TRUE);
10790 /*-----------------------------------------------------------------*/
10791 /* genFarPointerSet - set value from far space */
10792 /*-----------------------------------------------------------------*/
10794 genFarPointerSet (operand * right,
10795 operand * result, iCode * ic, iCode * pi)
10798 sym_link *retype = getSpec (operandType (right));
10799 sym_link *letype = getSpec (operandType (result));
10801 D(emitcode (";", "genFarPointerSet"));
10803 aopOp (result, ic, FALSE);
10804 loadDptrFromOperand (result, FALSE);
10806 /* so dptr now contains the address */
10807 aopOp (right, ic, FALSE);
10809 /* if bit then unpack */
10810 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10811 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10814 size = AOP_SIZE (right);
10819 char *l = aopGet (right, offset++, FALSE, FALSE);
10821 emitcode ("movx", "@dptr,a");
10823 emitcode ("inc", "dptr");
10826 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10827 aopPut (result, "dpl", 0);
10828 aopPut (result, "dph", 1);
10831 freeAsmop (result, NULL, ic, TRUE);
10832 freeAsmop (right, NULL, ic, TRUE);
10835 /*-----------------------------------------------------------------*/
10836 /* genGenPointerSet - set value from generic pointer space */
10837 /*-----------------------------------------------------------------*/
10839 genGenPointerSet (operand * right,
10840 operand * result, iCode * ic, iCode * pi)
10843 sym_link *retype = getSpec (operandType (right));
10844 sym_link *letype = getSpec (operandType (result));
10846 D (emitcode (";", "genGenPointerSet"));
10848 aopOp (result, ic, FALSE);
10849 loadDptrFromOperand (result, TRUE);
10851 /* so dptr now contains the address */
10852 aopOp (right, ic, FALSE);
10854 /* if bit then unpack */
10855 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10857 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10861 size = AOP_SIZE (right);
10866 char *l = aopGet (right, offset++, FALSE, FALSE);
10868 emitcode ("lcall", "__gptrput");
10870 emitcode ("inc", "dptr");
10874 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10875 aopPut (result, "dpl", 0);
10876 aopPut (result, "dph", 1);
10879 freeAsmop (result, NULL, ic, TRUE);
10880 freeAsmop (right, NULL, ic, TRUE);
10883 /*-----------------------------------------------------------------*/
10884 /* genPointerSet - stores the value into a pointer location */
10885 /*-----------------------------------------------------------------*/
10887 genPointerSet (iCode * ic, iCode *pi)
10889 operand *right, *result;
10890 sym_link *type, *etype;
10893 D (emitcode (";", "genPointerSet"));
10895 right = IC_RIGHT (ic);
10896 result = IC_RESULT (ic);
10898 /* depending on the type of pointer we need to
10899 move it to the correct pointer register */
10900 type = operandType (result);
10901 etype = getSpec (type);
10902 /* if left is of type of pointer then it is simple */
10903 if (IS_PTR (type) && !IS_FUNC (type->next))
10905 p_type = DCL_TYPE (type);
10909 /* we have to go by the storage class */
10910 p_type = PTR_TYPE (SPEC_OCLS (etype));
10913 /* special case when cast remat */
10914 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10915 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10916 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10917 type = operandType (result);
10918 p_type = DCL_TYPE (type);
10921 /* now that we have the pointer type we assign
10922 the pointer values */
10928 genNearPointerSet (right, result, ic, pi);
10932 genPagedPointerSet (right, result, ic, pi);
10936 genFarPointerSet (right, result, ic, pi);
10940 genGenPointerSet (right, result, ic, pi);
10944 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10945 "genPointerSet: illegal pointer type");
10949 /*-----------------------------------------------------------------*/
10950 /* genIfx - generate code for Ifx statement */
10951 /*-----------------------------------------------------------------*/
10953 genIfx (iCode * ic, iCode * popIc)
10955 operand *cond = IC_COND (ic);
10959 D (emitcode (";", "genIfx"));
10961 aopOp (cond, ic, FALSE);
10963 /* get the value into acc */
10964 if (AOP_TYPE (cond) != AOP_CRY)
10971 if (AOP(cond)->aopu.aop_dir)
10972 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10975 /* the result is now in the accumulator or a directly addressable bit */
10976 freeAsmop (cond, NULL, ic, TRUE);
10978 /* if there was something to be popped then do it */
10982 /* if the condition is a bit variable */
10984 genIfxJump(ic, dup, NULL, NULL, NULL);
10985 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10986 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10987 else if (isbit && !IS_ITEMP (cond))
10988 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10990 genIfxJump (ic, "a", NULL, NULL, NULL);
10995 /*-----------------------------------------------------------------*/
10996 /* genAddrOf - generates code for address of */
10997 /*-----------------------------------------------------------------*/
10999 genAddrOf (iCode * ic)
11001 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11004 D (emitcode (";", "genAddrOf"));
11006 aopOp (IC_RESULT (ic), ic, FALSE);
11008 /* if the operand is on the stack then we
11009 need to get the stack offset of this
11013 /* if it has an offset then we need to compute it */
11016 int stack_offset = ((sym->stack < 0) ?
11017 ((char) (sym->stack - _G.nRegsSaved)) :
11018 ((char) sym->stack)) & 0xff;
11019 if ((abs(stack_offset) == 1) &&
11020 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11021 !isOperandVolatile (IC_RESULT (ic), FALSE))
11023 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11024 if (stack_offset > 0)
11025 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11027 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11031 emitcode ("mov", "a,%s", SYM_BP (sym));
11032 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11033 aopPut (IC_RESULT (ic), "a", 0);
11038 /* we can just move _bp */
11039 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11041 /* fill the result with zero */
11042 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11047 aopPut (IC_RESULT (ic), zero, offset++);
11052 /* object not on stack then we need the name */
11053 size = AOP_SIZE (IC_RESULT (ic));
11058 char s[SDCC_NAME_MAX];
11060 sprintf (s, "#(%s >> %d)",
11064 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11065 aopPut (IC_RESULT (ic), s, offset++);
11069 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11073 /*-----------------------------------------------------------------*/
11074 /* genFarFarAssign - assignment when both are in far space */
11075 /*-----------------------------------------------------------------*/
11077 genFarFarAssign (operand * result, operand * right, iCode * ic)
11079 int size = AOP_SIZE (right);
11083 D (emitcode (";", "genFarFarAssign"));
11085 /* first push the right side on to the stack */
11088 l = aopGet (right, offset++, FALSE, FALSE);
11090 emitcode ("push", "acc");
11093 freeAsmop (right, NULL, ic, FALSE);
11094 /* now assign DPTR to result */
11095 aopOp (result, ic, FALSE);
11096 size = AOP_SIZE (result);
11099 emitcode ("pop", "acc");
11100 aopPut (result, "a", --offset);
11102 freeAsmop (result, NULL, ic, FALSE);
11105 /*-----------------------------------------------------------------*/
11106 /* genAssign - generate code for assignment */
11107 /*-----------------------------------------------------------------*/
11109 genAssign (iCode * ic)
11111 operand *result, *right;
11113 unsigned long lit = 0L;
11115 D (emitcode (";", "genAssign"));
11117 result = IC_RESULT (ic);
11118 right = IC_RIGHT (ic);
11120 /* if they are the same */
11121 if (operandsEqu (result, right) &&
11122 !isOperandVolatile (result, FALSE) &&
11123 !isOperandVolatile (right, FALSE))
11126 aopOp (right, ic, FALSE);
11128 /* special case both in far space */
11129 if (AOP_TYPE (right) == AOP_DPTR &&
11130 IS_TRUE_SYMOP (result) &&
11131 isOperandInFarSpace (result))
11133 genFarFarAssign (result, right, ic);
11137 aopOp (result, ic, TRUE);
11139 /* if they are the same registers */
11140 if (sameRegs (AOP (right), AOP (result)) &&
11141 !isOperandVolatile (result, FALSE) &&
11142 !isOperandVolatile (right, FALSE))
11145 /* if the result is a bit */
11146 if (AOP_TYPE (result) == AOP_CRY)
11148 assignBit (result, right);
11152 /* bit variables done */
11154 size = AOP_SIZE (result);
11156 if (AOP_TYPE (right) == AOP_LIT)
11157 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11160 (AOP_TYPE (result) != AOP_REG) &&
11161 (AOP_TYPE (right) == AOP_LIT) &&
11162 !IS_FLOAT (operandType (right)) &&
11165 while ((size) && (lit))
11168 aopGet (right, offset, FALSE, FALSE),
11174 /* And now fill the rest with zeros. */
11177 emitcode ("clr", "a");
11181 aopPut (result, "a", offset);
11190 aopGet (right, offset, FALSE, FALSE),
11197 freeAsmop (result, NULL, ic, TRUE);
11198 freeAsmop (right, NULL, ic, TRUE);
11201 /*-----------------------------------------------------------------*/
11202 /* genJumpTab - generates code for jump table */
11203 /*-----------------------------------------------------------------*/
11205 genJumpTab (iCode * ic)
11207 symbol *jtab,*jtablo,*jtabhi;
11209 unsigned int count;
11211 D (emitcode (";", "genJumpTab"));
11213 count = elementsInSet( IC_JTLABELS (ic) );
11217 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11218 if the switch argument is in a register.
11219 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11220 /* Peephole may not convert ljmp to sjmp or ret
11221 labelIsReturnOnly & labelInRange must check
11222 currPl->ic->op != JUMPTABLE */
11223 aopOp (IC_JTCOND (ic), ic, FALSE);
11224 /* get the condition into accumulator */
11225 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11227 /* multiply by three */
11228 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11230 emitcode ("mov", "b,#3");
11231 emitcode ("mul", "ab");
11235 emitcode ("add", "a,acc");
11236 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11238 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11240 jtab = newiTempLabel (NULL);
11241 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11242 emitcode ("jmp", "@a+dptr");
11244 /* now generate the jump labels */
11245 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11246 jtab = setNextItem (IC_JTLABELS (ic)))
11247 emitcode ("ljmp", "%05d$", jtab->key + 100);
11251 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11252 if the switch argument is in a register.
11253 For n>6 this algorithm may be more compact */
11254 jtablo = newiTempLabel (NULL);
11255 jtabhi = newiTempLabel (NULL);
11257 /* get the condition into accumulator.
11258 Using b as temporary storage, if register push/pop is needed */
11259 aopOp (IC_JTCOND (ic), ic, FALSE);
11260 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11261 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11262 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11264 // (MB) what if B is in use???
11265 wassertl(!BINUSE, "B was in use");
11266 emitcode ("mov", "b,%s", l);
11269 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11273 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11274 emitcode ("movc", "a,@a+pc");
11275 emitcode ("push", "acc");
11278 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11279 emitcode ("movc", "a,@a+pc");
11280 emitcode ("push", "acc");
11284 /* this scales up to n<=255, but needs two more bytes
11285 and changes dptr */
11286 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11287 emitcode ("movc", "a,@a+dptr");
11288 emitcode ("push", "acc");
11291 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11292 emitcode ("movc", "a,@a+dptr");
11293 emitcode ("push", "acc");
11296 emitcode ("ret", "");
11298 /* now generate jump table, LSB */
11299 emitLabel (jtablo);
11300 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11301 jtab = setNextItem (IC_JTLABELS (ic)))
11302 emitcode (".db", "%05d$", jtab->key + 100);
11304 /* now generate jump table, MSB */
11305 emitLabel (jtabhi);
11306 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11307 jtab = setNextItem (IC_JTLABELS (ic)))
11308 emitcode (".db", "%05d$>>8", jtab->key + 100);
11312 /*-----------------------------------------------------------------*/
11313 /* genCast - gen code for casting */
11314 /*-----------------------------------------------------------------*/
11316 genCast (iCode * ic)
11318 operand *result = IC_RESULT (ic);
11319 sym_link *ctype = operandType (IC_LEFT (ic));
11320 sym_link *rtype = operandType (IC_RIGHT (ic));
11321 operand *right = IC_RIGHT (ic);
11324 D (emitcode (";", "genCast"));
11326 /* if they are equivalent then do nothing */
11327 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11330 aopOp (right, ic, FALSE);
11331 aopOp (result, ic, FALSE);
11333 /* if the result is a bit (and not a bitfield) */
11334 if (IS_BIT (OP_SYMBOL (result)->type))
11336 assignBit (result, right);
11340 /* if they are the same size : or less */
11341 if (AOP_SIZE (result) <= AOP_SIZE (right))
11344 /* if they are in the same place */
11345 if (sameRegs (AOP (right), AOP (result)))
11348 /* if they in different places then copy */
11349 size = AOP_SIZE (result);
11354 aopGet (right, offset, FALSE, FALSE),
11361 /* if the result is of type pointer */
11362 if (IS_PTR (ctype))
11366 sym_link *type = operandType (right);
11367 sym_link *etype = getSpec (type);
11369 /* pointer to generic pointer */
11370 if (IS_GENPTR (ctype))
11374 p_type = DCL_TYPE (type);
11378 if (SPEC_SCLS(etype)==S_REGISTER) {
11379 // let's assume it is a generic pointer
11382 /* we have to go by the storage class */
11383 p_type = PTR_TYPE (SPEC_OCLS (etype));
11387 /* the first two bytes are known */
11388 size = GPTRSIZE - 1;
11393 aopGet (right, offset, FALSE, FALSE),
11397 /* the last byte depending on type */
11399 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11404 // pointerTypeToGPByte will have bitched.
11408 sprintf(gpValStr, "#0x%x", gpVal);
11409 aopPut (result, gpValStr, GPTRSIZE - 1);
11414 /* just copy the pointers */
11415 size = AOP_SIZE (result);
11420 aopGet (right, offset, FALSE, FALSE),
11427 /* so we now know that the size of destination is greater
11428 than the size of the source */
11429 /* we move to result for the size of source */
11430 size = AOP_SIZE (right);
11435 aopGet (right, offset, FALSE, FALSE),
11440 /* now depending on the sign of the source && destination */
11441 size = AOP_SIZE (result) - AOP_SIZE (right);
11442 /* if unsigned or not an integral type */
11443 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11446 aopPut (result, zero, offset++);
11450 /* we need to extend the sign :{ */
11451 char *l = aopGet (right, AOP_SIZE (right) - 1,
11454 emitcode ("rlc", "a");
11455 emitcode ("subb", "a,acc");
11457 aopPut (result, "a", offset++);
11460 /* we are done hurray !!!! */
11463 freeAsmop (result, NULL, ic, TRUE);
11464 freeAsmop (right, NULL, ic, TRUE);
11467 /*-----------------------------------------------------------------*/
11468 /* genDjnz - generate decrement & jump if not zero instrucion */
11469 /*-----------------------------------------------------------------*/
11471 genDjnz (iCode * ic, iCode * ifx)
11473 symbol *lbl, *lbl1;
11477 /* if the if condition has a false label
11478 then we cannot save */
11479 if (IC_FALSE (ifx))
11482 /* if the minus is not of the form a = a - 1 */
11483 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11484 !IS_OP_LITERAL (IC_RIGHT (ic)))
11487 if (operandLitValue (IC_RIGHT (ic)) != 1)
11490 /* if the size of this greater than one then no
11492 if (getSize (operandType (IC_RESULT (ic))) > 1)
11495 /* otherwise we can save BIG */
11497 D (emitcode (";", "genDjnz"));
11499 lbl = newiTempLabel (NULL);
11500 lbl1 = newiTempLabel (NULL);
11502 aopOp (IC_RESULT (ic), ic, FALSE);
11504 if (AOP_NEEDSACC(IC_RESULT(ic)))
11506 /* If the result is accessed indirectly via
11507 * the accumulator, we must explicitly write
11508 * it back after the decrement.
11510 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11512 if (strcmp(rByte, "a"))
11514 /* Something is hopelessly wrong */
11515 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11516 __FILE__, __LINE__);
11517 /* We can just give up; the generated code will be inefficient,
11518 * but what the hey.
11520 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11523 emitcode ("dec", "%s", rByte);
11524 aopPut (IC_RESULT (ic), rByte, 0);
11525 emitcode ("jnz", "%05d$", lbl->key + 100);
11527 else if (IS_AOP_PREG (IC_RESULT (ic)))
11529 emitcode ("dec", "%s",
11530 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11531 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11532 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11533 ifx->generated = 1;
11534 emitcode ("jnz", "%05d$", lbl->key + 100);
11538 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11541 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11543 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11546 if (!ifx->generated)
11547 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11548 ifx->generated = 1;
11552 /*-----------------------------------------------------------------*/
11553 /* genReceive - generate code for a receive iCode */
11554 /*-----------------------------------------------------------------*/
11556 genReceive (iCode * ic)
11558 int size = getSize (operandType (IC_RESULT (ic)));
11561 D (emitcode (";", "genReceive"));
11563 if (ic->argreg == 1)
11564 { /* first parameter */
11565 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11566 isOperandInPagedSpace (IC_RESULT (ic))) &&
11567 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11568 IS_TRUE_SYMOP (IC_RESULT (ic))))
11571 int receivingA = 0;
11574 for (offset = 0; offset<size; offset++)
11575 if (!strcmp (fReturn[offset], "a"))
11580 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11582 for (offset = size-1; offset>0; offset--)
11583 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11584 emitcode("mov","a,%s", fReturn[0]);
11586 aopOp (IC_RESULT (ic), ic, FALSE);
11588 aopPut (IC_RESULT (ic), "a", offset);
11589 for (offset = 1; offset<size; offset++)
11590 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11596 if (getTempRegs(tempRegs, size, ic))
11598 for (offset = 0; offset<size; offset++)
11599 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11600 aopOp (IC_RESULT (ic), ic, FALSE);
11601 for (offset = 0; offset<size; offset++)
11602 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11607 offset = fReturnSizeMCS51 - size;
11610 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11611 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11614 aopOp (IC_RESULT (ic), ic, FALSE);
11615 size = AOP_SIZE (IC_RESULT (ic));
11619 emitcode ("pop", "acc");
11620 aopPut (IC_RESULT (ic), "a", offset++);
11626 aopOp (IC_RESULT (ic), ic, FALSE);
11628 assignResultValue (IC_RESULT (ic), NULL);
11631 else if (ic->argreg > 12)
11632 { /* bit parameters */
11633 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11636 if (!reg || reg->rIdx != ic->argreg-5)
11638 aopOp (IC_RESULT (ic), ic, FALSE);
11639 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11640 outBitC(IC_RESULT (ic));
11644 { /* other parameters */
11646 aopOp (IC_RESULT (ic), ic, FALSE);
11647 rb1off = ic->argreg;
11650 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11655 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11658 /*-----------------------------------------------------------------*/
11659 /* genDummyRead - generate code for dummy read of volatiles */
11660 /*-----------------------------------------------------------------*/
11662 genDummyRead (iCode * ic)
11667 D (emitcode(";", "genDummyRead"));
11669 op = IC_RIGHT (ic);
11670 if (op && IS_SYMOP (op))
11672 aopOp (op, ic, FALSE);
11674 /* if the result is a bit */
11675 if (AOP_TYPE (op) == AOP_CRY)
11676 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11679 /* bit variables done */
11681 size = AOP_SIZE (op);
11685 MOVA (aopGet (op, offset, FALSE, FALSE));
11690 freeAsmop (op, NULL, ic, TRUE);
11694 if (op && IS_SYMOP (op))
11696 aopOp (op, ic, FALSE);
11698 /* if the result is a bit */
11699 if (AOP_TYPE (op) == AOP_CRY)
11700 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11703 /* bit variables done */
11705 size = AOP_SIZE (op);
11709 MOVA (aopGet (op, offset, FALSE, FALSE));
11714 freeAsmop (op, NULL, ic, TRUE);
11718 /*-----------------------------------------------------------------*/
11719 /* genCritical - generate code for start of a critical sequence */
11720 /*-----------------------------------------------------------------*/
11722 genCritical (iCode *ic)
11724 symbol *tlbl = newiTempLabel (NULL);
11726 D (emitcode(";", "genCritical"));
11728 if (IC_RESULT (ic))
11730 aopOp (IC_RESULT (ic), ic, TRUE);
11731 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11732 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11733 aopPut (IC_RESULT (ic), zero, 0);
11735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11739 emitcode ("setb", "c");
11740 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11741 emitcode ("clr", "c");
11743 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11747 /*-----------------------------------------------------------------*/
11748 /* genEndCritical - generate code for end of a critical sequence */
11749 /*-----------------------------------------------------------------*/
11751 genEndCritical (iCode *ic)
11753 D(emitcode(";", "genEndCritical"));
11757 aopOp (IC_RIGHT (ic), ic, FALSE);
11758 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11760 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11761 emitcode ("mov", "ea,c");
11765 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11766 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11767 emitcode ("rrc", "a");
11768 emitcode ("mov", "ea,c");
11770 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11774 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11775 emitcode ("mov", "ea,c");
11779 /*-----------------------------------------------------------------*/
11780 /* gen51Code - generate code for 8051 based controllers */
11781 /*-----------------------------------------------------------------*/
11783 gen51Code (iCode * lic)
11787 /* int cseq = 0; */
11789 _G.currentFunc = NULL;
11790 lineHead = lineCurr = NULL;
11792 /* print the allocation information */
11793 if (allocInfo && currFunc)
11794 printAllocInfo (currFunc, codeOutBuf);
11795 /* if debug information required */
11796 if (options.debug && currFunc)
11798 debugFile->writeFunction (currFunc, lic);
11800 /* stack pointer name */
11801 if (options.useXstack)
11807 for (ic = lic; ic; ic = ic->next)
11809 _G.current_iCode = ic;
11811 if (ic->lineno && cln != ic->lineno)
11815 debugFile->writeCLine (ic);
11817 if (!options.noCcodeInAsm) {
11818 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11819 printCLine(ic->filename, ic->lineno));
11824 if (ic->seqPoint && ic->seqPoint != cseq)
11826 emitcode (";", "sequence point %d", ic->seqPoint);
11827 cseq = ic->seqPoint;
11830 if (options.iCodeInAsm) {
11831 char regsInUse[80];
11836 for (i=0; i<8; i++) {
11837 sprintf (®sInUse[i],
11838 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11841 strcpy (regsInUse, "--------");
11842 for (i=0; i < 8; i++) {
11843 if (bitVectBitValue (ic->rMask, i))
11845 int offset = regs8051[i].offset;
11846 regsInUse[offset] = offset + '0'; /* show rMask */
11850 iLine = printILine(ic);
11851 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11854 /* if the result is marked as
11855 spilt and rematerializable or code for
11856 this has already been generated then
11858 if (resultRemat (ic) || ic->generated)
11861 /* depending on the operation */
11881 /* IPOP happens only when trying to restore a
11882 spilt live range, if there is an ifx statement
11883 following this pop then the if statement might
11884 be using some of the registers being popped which
11885 would destory the contents of the register so
11886 we need to check for this condition and handle it */
11888 ic->next->op == IFX &&
11889 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11890 genIfx (ic->next, ic);
11908 genEndFunction (ic);
11928 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11945 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11949 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11956 /* note these two are xlated by algebraic equivalence
11957 in decorateType() in SDCCast.c */
11958 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11959 "got '>=' or '<=' shouldn't have come here");
11963 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11975 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11979 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11983 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12019 genRightShift (ic);
12022 case GET_VALUE_AT_ADDRESS:
12024 hasInc (IC_LEFT (ic), ic,
12025 getSize (operandType (IC_RESULT (ic)))),
12026 ifxForOp (IC_RESULT (ic), ic) );
12030 if (POINTER_SET (ic))
12032 hasInc (IC_RESULT (ic), ic,
12033 getSize (operandType (IC_RIGHT (ic)))));
12059 addSet (&_G.sendSet, ic);
12062 case DUMMY_READ_VOLATILE:
12071 genEndCritical (ic);
12083 _G.current_iCode = NULL;
12085 /* now we are ready to call the
12086 peep hole optimizer */
12087 if (!options.nopeep)
12088 peepHole (&lineHead);
12090 /* now do the actual printing */
12091 printLine (lineHead, codeOutBuf);