1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerialzes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic)) {
732 sym_link *from_type = operandType(IC_RIGHT(ic));
733 aop->aopu.aop_immd.from_cast_remat = 1;
734 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
735 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
739 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
744 SNPRINTF (buffer, sizeof(buffer),
746 OP_SYMBOL (IC_LEFT (ic))->rname,
747 val >= 0 ? '+' : '-',
752 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
755 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
756 /* set immd2 field if required */
757 if (aop->aopu.aop_immd.from_cast_remat)
759 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
760 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
766 /*-----------------------------------------------------------------*/
767 /* regsInCommon - two operands have some registers in common */
768 /*-----------------------------------------------------------------*/
770 regsInCommon (operand * op1, operand * op2)
775 /* if they have registers in common */
776 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
779 sym1 = OP_SYMBOL (op1);
780 sym2 = OP_SYMBOL (op2);
782 if (sym1->nRegs == 0 || sym2->nRegs == 0)
785 for (i = 0; i < sym1->nRegs; i++)
791 for (j = 0; j < sym2->nRegs; j++)
796 if (sym2->regs[j] == sym1->regs[i])
804 /*-----------------------------------------------------------------*/
805 /* operandsEqu - equivalent */
806 /*-----------------------------------------------------------------*/
808 operandsEqu (operand * op1, operand * op2)
812 /* if they're not symbols */
813 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
816 sym1 = OP_SYMBOL (op1);
817 sym2 = OP_SYMBOL (op2);
819 /* if both are itemps & one is spilt
820 and the other is not then false */
821 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
822 sym1->isspilt != sym2->isspilt)
825 /* if they are the same */
829 /* if they have the same rname */
830 if (sym1->rname[0] && sym2->rname[0] &&
831 strcmp (sym1->rname, sym2->rname) == 0 &&
832 !(IS_PARM (op2) && IS_ITEMP (op1)))
835 /* if left is a tmp & right is not */
836 if (IS_ITEMP (op1) &&
839 (sym1->usl.spillLoc == sym2))
842 if (IS_ITEMP (op2) &&
846 (sym2->usl.spillLoc == sym1))
852 /*-----------------------------------------------------------------*/
853 /* sameByte - two asmops have the same address at given offsets */
854 /*-----------------------------------------------------------------*/
856 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
858 if (aop1 == aop2 && off1 == off2)
861 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
864 if (aop1->type != aop2->type)
867 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
873 /*-----------------------------------------------------------------*/
874 /* sameRegs - two asmops have the same registers */
875 /*-----------------------------------------------------------------*/
877 sameRegs (asmop * aop1, asmop * aop2)
884 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
887 if (aop1->type != aop2->type)
890 if (aop1->size != aop2->size)
893 for (i = 0; i < aop1->size; i++)
894 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand : */
902 /*-----------------------------------------------------------------*/
904 aopOp (operand * op, iCode * ic, bool result)
913 /* if this a literal */
914 if (IS_OP_LITERAL (op))
916 op->aop = aop = newAsmop (AOP_LIT);
917 aop->aopu.aop_lit = op->operand.valOperand;
918 aop->size = getSize (operandType (op));
922 /* if already has a asmop then continue */
925 op->aop->allocated++;
929 /* if the underlying symbol has a aop */
930 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
932 op->aop = OP_SYMBOL (op)->aop;
933 op->aop->allocated++;
937 /* if this is a true symbol */
938 if (IS_TRUE_SYMOP (op))
940 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
944 /* this is a temporary : this has
950 e) can be a return use only */
952 sym = OP_SYMBOL (op);
954 /* if the type is a conditional */
955 if (sym->regType == REG_CND)
957 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
958 aop->size = sym->ruonly ? 1 : 0;
962 /* if it is spilt then two situations
964 b) has a spill location */
965 if (sym->isspilt || sym->nRegs == 0)
968 /* rematerialize it NOW */
971 sym->aop = op->aop = aop = aopForRemat (sym);
972 aop->size = getSize (sym->type);
979 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
980 aop->size = getSize (sym->type);
981 for (i = 0; i < 2; i++)
982 aop->aopu.aop_str[i] = accUse[i];
990 sym->aop = op->aop = aop = newAsmop (AOP_STR);
991 aop->size = getSize (sym->type);
992 for (i = 0; i < fReturnSizeMCS51; i++)
993 aop->aopu.aop_str[i] = fReturn[i];
997 if (sym->usl.spillLoc)
999 asmop *oldAsmOp = NULL;
1001 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1003 /* force a new aop if sizes differ */
1004 oldAsmOp = sym->usl.spillLoc->aop;
1005 sym->usl.spillLoc->aop = NULL;
1007 sym->aop = op->aop = aop =
1008 aopForSym (ic, sym->usl.spillLoc, result);
1009 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1011 /* Don't reuse the new aop, go with the last one */
1012 sym->usl.spillLoc->aop = oldAsmOp;
1014 aop->size = getSize (sym->type);
1018 /* else must be a dummy iTemp */
1019 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020 aop->size = getSize (sym->type);
1024 /* if the type is a bit register */
1025 if (sym->regType == REG_BIT)
1027 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028 aop->size = sym->nRegs;//1???
1029 aop->aopu.aop_reg[0] = sym->regs[0];
1030 aop->aopu.aop_dir = sym->regs[0]->name;
1034 /* must be in a register */
1035 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036 aop->size = sym->nRegs;
1037 for (i = 0; i < sym->nRegs; i++)
1038 aop->aopu.aop_reg[i] = sym->regs[i];
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand */
1043 /*----------------------------------------------------------------*/
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1062 /* depending on the asmop type only three cases need work
1063 AOP_R0, AOP_R1 & AOP_STK */
1069 emitcode ("mov", "r0,b");
1072 else if (_G.r0Pushed)
1076 emitcode ("pop", "ar0");
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1086 emitcode ("mov", "r1,b");
1089 else if (_G.r1Pushed)
1093 emitcode ("pop", "ar1");
1097 bitVectUnSetBit (ic->rUsed, R1_IDX);
1103 int stk = aop->aopu.aop_stk + aop->size - 1;
1104 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 getFreePtr (ic, &aop, FALSE);
1111 emitcode ("mov", "a,_bp");
1112 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1117 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122 emitcode ("pop", "acc");
1123 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1129 freeAsmop (op, NULL, ic, TRUE);
1132 emitcode ("pop", "ar1");
1137 emitcode ("pop", "ar0");
1145 /* all other cases just dealloc */
1151 OP_SYMBOL (op)->aop = NULL;
1152 /* if the symbol has a spill */
1154 SPIL_LOC (op)->aop = NULL;
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /* pop r0 or r1 off stack if pushed */
1162 /*------------------------------------------------------------------*/
1164 freeForBranchAsmop (operand * op)
1176 if (!aop->allocated)
1184 emitcode ("mov", "r0,b");
1186 else if (_G.r0Pushed)
1188 emitcode ("pop", "ar0");
1195 emitcode ("mov", "r1,b");
1197 else if (_G.r1Pushed)
1199 emitcode ("pop", "ar1");
1206 int stk = aop->aopu.aop_stk + aop->size - 1;
1208 emitcode ("mov", "b,r0");
1211 emitcode ("mov", "a,_bp");
1212 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213 emitcode ("mov", "r0,a");
1217 emitcode ("mov", "r0,_bp");
1222 emitcode ("pop", "acc");
1223 emitcode ("mov", "@r0,a");
1226 emitcode ("dec", "r0");
1228 emitcode ("mov", "r0,b");
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1236 /* clobber the accumulator */
1237 /*-----------------------------------------------------------------*/
1239 aopGetUsesAcc (operand * oper, int offset)
1241 asmop * aop = AOP (oper);
1243 if (offset > (aop->size - 1))
1261 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1272 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1278 /* Error case --- will have been caught already */
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop */
1286 /*-------------------------------------------------------------------*/
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1290 asmop * aop = AOP (oper);
1292 /* offset is greater than
1294 if (offset > (aop->size - 1) &&
1295 aop->type != AOP_LIT)
1298 /* depending on type */
1306 /* if we need to increment it */
1307 while (offset > aop->coff)
1309 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1313 while (offset < aop->coff)
1315 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1322 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323 return (dname ? "acc" : "a");
1325 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326 return Safe_strdup(buffer);
1329 if (aop->code && aop->coff==0 && offset>=1) {
1330 emitcode ("mov", "a,#0x%02x", offset);
1331 emitcode ("movc", "a,@a+dptr");
1332 return (dname ? "acc" : "a");
1335 while (offset > aop->coff)
1337 emitcode ("inc", "dptr");
1341 while (offset < aop->coff)
1343 emitcode ("lcall", "__decdptr");
1350 emitcode ("clr", "a");
1351 emitcode ("movc", "a,@a+dptr");
1355 emitcode ("movx", "a,@dptr");
1357 return (dname ? "acc" : "a");
1360 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s",aop->aopu.aop_immd.aop_immd2);
1367 SNPRINTF(buffer, sizeof(buffer),
1368 "#%s", aop->aopu.aop_immd.aop_immd1);
1372 SNPRINTF (buffer, sizeof(buffer),
1374 aop->aopu.aop_immd.aop_immd1,
1379 SNPRINTF (buffer, sizeof(buffer),
1381 aop->aopu.aop_immd.aop_immd1);
1383 return Safe_strdup(buffer);
1386 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1388 SNPRINTF (buffer, sizeof(buffer),
1390 aop->aopu.aop_dir, offset * 8);
1394 SNPRINTF (buffer, sizeof(buffer),
1401 SNPRINTF (buffer, sizeof(buffer),
1406 return Safe_strdup(buffer);
1410 return aop->aopu.aop_reg[offset]->dname;
1412 return aop->aopu.aop_reg[offset]->name;
1415 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1416 emitcode ("clr", "a");
1417 emitcode ("rlc", "a");
1418 return (dname ? "acc" : "a");
1421 if (!offset && dname)
1423 return aop->aopu.aop_str[offset];
1426 return aopLiteral (aop->aopu.aop_lit, offset);
1430 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1434 return aop->aopu.aop_str[offset];
1438 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439 "aopget got unsupported aop->type");
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1445 /* clobber the accumulator */
1446 /*-----------------------------------------------------------------*/
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1450 asmop * aop = AOP (oper);
1452 if (offset > (aop->size - 1))
1462 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1468 return ((aop->paged) || (*s == '@'));
1472 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1480 /* Error case --- will have been caught already */
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1490 aopPut (operand * result, const char *s, int offset)
1492 bool bvolatile = isOperandVolatile (result, FALSE);
1493 bool accuse = FALSE;
1494 asmop * aop = AOP (result);
1495 const char *d = NULL;
1497 if (aop->size && offset > (aop->size - 1))
1499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1500 "aopPut got offset > aop->size");
1504 /* will assign value to value */
1505 /* depending on where it is ofcourse */
1509 MOVA (s); /* read s in case it was volatile */
1514 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1516 SNPRINTF (buffer, sizeof(buffer),
1518 aop->aopu.aop_dir, offset * 8);
1522 SNPRINTF (buffer, sizeof(buffer),
1524 aop->aopu.aop_dir, offset);
1528 SNPRINTF (buffer, sizeof(buffer),
1533 if (strcmp (buffer, s) || bvolatile)
1535 emitcode ("mov", "%s,%s", buffer, s);
1537 if (!strcmp (buffer, "acc"))
1544 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1545 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1548 strcmp (s, "r0") == 0 ||
1549 strcmp (s, "r1") == 0 ||
1550 strcmp (s, "r2") == 0 ||
1551 strcmp (s, "r3") == 0 ||
1552 strcmp (s, "r4") == 0 ||
1553 strcmp (s, "r5") == 0 ||
1554 strcmp (s, "r6") == 0 ||
1555 strcmp (s, "r7") == 0)
1557 emitcode ("mov", "%s,%s",
1558 aop->aopu.aop_reg[offset]->dname, s);
1562 emitcode ("mov", "%s,%s",
1563 aop->aopu.aop_reg[offset]->name, s);
1571 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1572 "aopPut writing to code space");
1576 while (offset > aop->coff)
1579 emitcode ("inc", "dptr");
1582 while (offset < aop->coff)
1585 emitcode ("lcall", "__decdptr");
1590 /* if not in accumulator */
1593 emitcode ("movx", "@dptr,a");
1598 while (offset > aop->coff)
1601 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1603 while (offset < aop->coff)
1606 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1613 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1618 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1620 else if (strcmp (s, "r0") == 0 ||
1621 strcmp (s, "r1") == 0 ||
1622 strcmp (s, "r2") == 0 ||
1623 strcmp (s, "r3") == 0 ||
1624 strcmp (s, "r4") == 0 ||
1625 strcmp (s, "r5") == 0 ||
1626 strcmp (s, "r6") == 0 ||
1627 strcmp (s, "r7") == 0)
1630 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1631 emitcode ("mov", "@%s,%s",
1632 aop->aopu.aop_ptr->name, buffer);
1636 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1641 if (strcmp (s, "a") == 0)
1643 emitcode ("push", "acc");
1648 emitcode ("push", "acc");
1650 else if (strcmp (s, "r0") == 0 ||
1651 strcmp (s, "r1") == 0 ||
1652 strcmp (s, "r2") == 0 ||
1653 strcmp (s, "r3") == 0 ||
1654 strcmp (s, "r4") == 0 ||
1655 strcmp (s, "r5") == 0 ||
1656 strcmp (s, "r6") == 0 ||
1657 strcmp (s, "r7") == 0)
1660 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1661 emitcode ("push", buffer);
1665 emitcode ("push", s);
1671 // destination is carry for return-use-only
1672 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1673 // source is no literal and not in carry
1674 if ((s != zero) && (s != one) && strcmp (s, "c"))
1677 /* set C, if a >= 1 */
1678 emitcode ("add", "a,#0xff");
1681 // now source is zero, one or carry
1683 /* if result no bit variable */
1686 if (!strcmp (s, "c"))
1688 /* inefficient: move carry into A and use jz/jnz */
1689 emitcode ("clr", "a");
1690 emitcode ("rlc", "a");
1700 emitcode ("clr", "%s", d);
1702 emitcode ("setb", "%s", d);
1703 else if (strcmp (s, d))
1704 emitcode ("mov", "%s,c", d);
1709 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1710 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1716 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1719 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1720 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1724 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1725 "aopPut got unsupported aop->type");
1734 /*-----------------------------------------------------------------*/
1735 /* pointToEnd :- points to the last byte of the operand */
1736 /*-----------------------------------------------------------------*/
1738 pointToEnd (asmop * aop)
1744 aop->coff = count = (aop->size - 1);
1750 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1754 emitcode ("inc", "dptr");
1761 /*-----------------------------------------------------------------*/
1762 /* reAdjustPreg - points a register back to where it should */
1763 /*-----------------------------------------------------------------*/
1765 reAdjustPreg (asmop * aop)
1767 if ((aop->coff==0) || (aop->size <= 1))
1775 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1780 emitcode ("lcall", "__decdptr");
1787 /*-----------------------------------------------------------------*/
1788 /* opIsGptr: returns non-zero if the passed operand is */
1789 /* a generic pointer type. */
1790 /*-----------------------------------------------------------------*/
1792 opIsGptr (operand * op)
1794 sym_link *type = operandType (op);
1796 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1803 /*-----------------------------------------------------------------*/
1804 /* getDataSize - get the operand data size */
1805 /*-----------------------------------------------------------------*/
1807 getDataSize (operand * op)
1810 size = AOP_SIZE (op);
1811 if (size == GPTRSIZE)
1813 sym_link *type = operandType (op);
1814 if (IS_GENPTR (type))
1816 /* generic pointer; arithmetic operations
1817 * should ignore the high byte (pointer type).
1825 /*-----------------------------------------------------------------*/
1826 /* outAcc - output Acc */
1827 /*-----------------------------------------------------------------*/
1829 outAcc (operand * result)
1832 size = getDataSize (result);
1835 aopPut (result, "a", 0);
1838 /* unsigned or positive */
1841 aopPut (result, zero, offset++);
1846 /*-----------------------------------------------------------------*/
1847 /* outBitC - output a bit C */
1848 /*-----------------------------------------------------------------*/
1850 outBitC (operand * result)
1852 /* if the result is bit */
1853 if (AOP_TYPE (result) == AOP_CRY)
1855 if (!IS_OP_RUONLY (result))
1856 aopPut (result, "c", 0);
1860 emitcode ("clr", "a");
1861 emitcode ("rlc", "a");
1866 /*-----------------------------------------------------------------*/
1867 /* toBoolean - emit code for orl a,operator(sizeop) */
1868 /*-----------------------------------------------------------------*/
1870 toBoolean (operand * oper)
1872 int size = AOP_SIZE (oper) - 1;
1874 bool AccUsed = FALSE;
1877 while (!AccUsed && size--)
1879 AccUsed |= aopGetUsesAcc(oper, offset++);
1882 size = AOP_SIZE (oper) - 1;
1884 MOVA (aopGet (oper, 0, FALSE, FALSE));
1885 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1888 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1892 emitcode ("orl", "b,a");
1894 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1895 emitcode ("orl", "a,b");
1902 emitcode ("orl", "a,%s",
1903 aopGet (oper, offset++, FALSE, FALSE));
1908 /*-----------------------------------------------------------------*/
1909 /* toCarry - make boolean and move into carry */
1910 /*-----------------------------------------------------------------*/
1912 toCarry (operand * oper)
1914 /* if the operand is a literal then
1915 we know what the value is */
1916 if (AOP_TYPE (oper) == AOP_LIT)
1918 if ((int) operandLitValue (oper))
1923 else if (AOP_TYPE (oper) == AOP_CRY)
1925 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1929 /* or the operand into a */
1931 /* set C, if a >= 1 */
1932 emitcode ("add", "a,#0xff");
1936 /*-----------------------------------------------------------------*/
1937 /* assignBit - assign operand to bit operand */
1938 /*-----------------------------------------------------------------*/
1940 assignBit (operand * result, operand * right)
1942 /* if the right side is a literal then
1943 we know what the value is */
1944 if (AOP_TYPE (right) == AOP_LIT)
1946 if ((int) operandLitValue (right))
1947 aopPut (result, one, 0);
1949 aopPut (result, zero, 0);
1954 aopPut (result, "c", 0);
1959 /*-------------------------------------------------------------------*/
1960 /* xch_a_aopGet - for exchanging acc with value of the aop */
1961 /*-------------------------------------------------------------------*/
1963 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1967 if (aopGetUsesAcc (oper, offset))
1969 emitcode("mov", "b,a");
1970 MOVA (aopGet (oper, offset, bit16, dname));
1971 emitcode("xch", "a,b");
1972 aopPut (oper, "a", offset);
1973 emitcode("xch", "a,b");
1978 l = aopGet (oper, offset, bit16, dname);
1979 emitcode("xch", "a,%s", l);
1985 /*-----------------------------------------------------------------*/
1986 /* genNot - generate code for ! operation */
1987 /*-----------------------------------------------------------------*/
1993 D (emitcode (";", "genNot"));
1995 /* assign asmOps to operand & result */
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1997 aopOp (IC_RESULT (ic), ic, TRUE);
1999 /* if in bit space then a special case */
2000 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2002 /* if left==result then cpl bit */
2003 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2005 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2009 toCarry (IC_LEFT (ic));
2010 emitcode ("cpl", "c");
2011 outBitC (IC_RESULT (ic));
2016 toBoolean (IC_LEFT (ic));
2018 /* set C, if a == 0 */
2019 tlbl = newiTempLabel (NULL);
2020 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2022 outBitC (IC_RESULT (ic));
2025 /* release the aops */
2026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2027 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2031 /*-----------------------------------------------------------------*/
2032 /* genCpl - generate code for complement */
2033 /*-----------------------------------------------------------------*/
2040 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2042 D(emitcode (";", "genCpl"));
2044 /* assign asmOps to operand & result */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2046 aopOp (IC_RESULT (ic), ic, TRUE);
2048 /* special case if in bit space */
2049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2054 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2056 /* promotion rules are responsible for this strange result:
2057 bit -> int -> ~int -> bit
2058 uchar -> int -> ~int -> bit
2060 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2064 tlbl=newiTempLabel(NULL);
2065 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2066 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2068 IS_AOP_PREG (IC_LEFT (ic)))
2070 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2075 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2078 outBitC (IC_RESULT(ic));
2082 size = AOP_SIZE (IC_RESULT (ic));
2085 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2087 emitcode ("cpl", "a");
2088 aopPut (IC_RESULT (ic), "a", offset++);
2093 /* release the aops */
2094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2098 /*-----------------------------------------------------------------*/
2099 /* genUminusFloat - unary minus for floating points */
2100 /*-----------------------------------------------------------------*/
2102 genUminusFloat (operand * op, operand * result)
2104 int size, offset = 0;
2107 D (emitcode (";", "genUminusFloat"));
2109 /* for this we just copy and then flip the bit */
2111 size = AOP_SIZE (op) - 1;
2116 aopGet (op, offset, FALSE, FALSE),
2121 l = aopGet (op, offset, FALSE, FALSE);
2124 emitcode ("cpl", "acc.7");
2125 aopPut (result, "a", offset);
2128 /*-----------------------------------------------------------------*/
2129 /* genUminus - unary minus code generation */
2130 /*-----------------------------------------------------------------*/
2132 genUminus (iCode * ic)
2137 D (emitcode (";", "genUminus"));
2140 aopOp (IC_LEFT (ic), ic, FALSE);
2141 aopOp (IC_RESULT (ic), ic, TRUE);
2143 /* if both in bit space then special
2145 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2146 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2149 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2150 emitcode ("cpl", "c");
2151 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2155 optype = operandType (IC_LEFT (ic));
2157 /* if float then do float stuff */
2158 if (IS_FLOAT (optype))
2160 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2164 /* otherwise subtract from zero */
2165 size = AOP_SIZE (IC_LEFT (ic));
2169 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2170 if (!strcmp (l, "a"))
2174 emitcode ("cpl", "a");
2175 emitcode ("addc", "a,#0");
2181 emitcode ("clr", "a");
2182 emitcode ("subb", "a,%s", l);
2184 aopPut (IC_RESULT (ic), "a", offset++);
2187 /* if any remaining bytes in the result */
2188 /* we just need to propagate the sign */
2189 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2191 emitcode ("rlc", "a");
2192 emitcode ("subb", "a,acc");
2194 aopPut (IC_RESULT (ic), "a", offset++);
2198 /* release the aops */
2199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2200 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2203 /*-----------------------------------------------------------------*/
2204 /* saveRegisters - will look for a call and save the registers */
2205 /*-----------------------------------------------------------------*/
2207 saveRegisters (iCode * lic)
2214 for (ic = lic; ic; ic = ic->next)
2215 if (ic->op == CALL || ic->op == PCALL)
2220 fprintf (stderr, "found parameter push with no function call\n");
2224 /* if the registers have been saved already or don't need to be then
2228 if (IS_SYMOP(IC_LEFT(ic)) &&
2229 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2230 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2233 /* save the registers in use at this time but skip the
2234 ones for the result */
2235 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2236 mcs51_rUmaskForOp (IC_RESULT(ic)));
2239 if (options.useXstack)
2241 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2242 int nBits = bitVectnBitsOn (rsavebits);
2243 int count = bitVectnBitsOn (rsave);
2247 count = count - nBits + 1;
2248 /* remove all but the first bits as they are pushed all at once */
2249 rsave = bitVectCplAnd (rsave, rsavebits);
2250 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2252 freeBitVect (rsavebits);
2256 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2257 if (reg->type == REG_BIT)
2259 emitcode ("mov", "a,%s", reg->base);
2263 emitcode ("mov", "a,%s", reg->name);
2265 emitcode ("mov", "r0,%s", spname);
2266 emitcode ("inc", "%s", spname);// allocate before use
2267 emitcode ("movx", "@r0,a");
2268 if (bitVectBitValue (rsave, R0_IDX))
2269 emitcode ("mov", "r0,a");
2271 else if (count != 0)
2273 if (bitVectBitValue (rsave, R0_IDX))
2275 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2277 emitcode ("mov", "r0,%s", spname);
2279 emitcode ("add", "a,#%d", count);
2280 emitcode ("mov", "%s,a", spname);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (bitVectBitValue (rsave, i))
2285 regs * reg = REG_WITH_INDEX (i);
2288 emitcode ("pop", "acc");
2289 emitcode ("push", "acc");
2291 else if (reg->type == REG_BIT)
2293 emitcode ("mov", "a,%s", reg->base);
2297 emitcode ("mov", "a,%s", reg->name);
2299 emitcode ("movx", "@r0,a");
2302 emitcode ("inc", "r0");
2306 if (bitVectBitValue (rsave, R0_IDX))
2308 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2314 bool bits_pushed = FALSE;
2315 for (i = 0; i < mcs51_nRegs; i++)
2317 if (bitVectBitValue (rsave, i))
2319 bits_pushed = pushReg (i, bits_pushed);
2323 freeBitVect (rsave);
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers */
2328 /*-----------------------------------------------------------------*/
2330 unsaveRegisters (iCode * ic)
2335 /* restore the registers in use at this time but skip the
2336 ones for the result */
2337 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2338 mcs51_rUmaskForOp (IC_RESULT(ic)));
2340 if (options.useXstack)
2342 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2343 int nBits = bitVectnBitsOn (rsavebits);
2344 int count = bitVectnBitsOn (rsave);
2348 count = count - nBits + 1;
2349 /* remove all but the first bits as they are popped all at once */
2350 rsave = bitVectCplAnd (rsave, rsavebits);
2351 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2353 freeBitVect (rsavebits);
2357 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2358 emitcode ("mov", "r0,%s", spname);
2359 emitcode ("dec", "r0");
2360 emitcode ("movx", "a,@r0");
2361 if (reg->type == REG_BIT)
2363 emitcode ("mov", "%s,a", reg->base);
2367 emitcode ("mov", "%s,a", reg->name);
2369 emitcode ("dec", "%s", spname);
2371 else if (count != 0)
2373 emitcode ("mov", "r0,%s", spname);
2374 for (i = mcs51_nRegs; i >= 0; i--)
2376 if (bitVectBitValue (rsave, i))
2378 regs * reg = REG_WITH_INDEX (i);
2379 emitcode ("dec", "r0");
2380 emitcode ("movx", "a,@r0");
2383 emitcode ("push", "acc");
2385 else if (reg->type == REG_BIT)
2387 emitcode ("mov", "%s,a", reg->base);
2391 emitcode ("mov", "%s,a", reg->name);
2395 emitcode ("mov", "%s,r0", spname);
2396 if (bitVectBitValue (rsave, R0_IDX))
2398 emitcode ("pop", "ar0");
2404 bool bits_popped = FALSE;
2405 for (i = mcs51_nRegs; i >= 0; i--)
2407 if (bitVectBitValue (rsave, i))
2409 bits_popped = popReg (i, bits_popped);
2413 freeBitVect (rsave);
2417 /*-----------------------------------------------------------------*/
2419 /*-----------------------------------------------------------------*/
2421 pushSide (operand * oper, int size)
2426 char *l = aopGet (oper, offset++, FALSE, TRUE);
2427 if (AOP_TYPE (oper) != AOP_REG &&
2428 AOP_TYPE (oper) != AOP_DIR &&
2432 emitcode ("push", "acc");
2436 emitcode ("push", "%s", l);
2441 /*-----------------------------------------------------------------*/
2442 /* assignResultValue - also indicates if acc is in use afterwards */
2443 /*-----------------------------------------------------------------*/
2445 assignResultValue (operand * oper, operand * func)
2448 int size = AOP_SIZE (oper);
2449 bool accuse = FALSE;
2450 bool pushedA = FALSE;
2452 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2458 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2460 emitcode ("push", "acc");
2465 if ((offset == 3) && pushedA)
2466 emitcode ("pop", "acc");
2467 accuse |= aopPut (oper, fReturn[offset], offset);
2474 /*-----------------------------------------------------------------*/
2475 /* genXpush - pushes onto the external stack */
2476 /*-----------------------------------------------------------------*/
2478 genXpush (iCode * ic)
2480 asmop *aop = newAsmop (0);
2482 int size, offset = 0;
2484 D (emitcode (";", "genXpush"));
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2487 r = getFreePtr (ic, &aop, FALSE);
2489 size = AOP_SIZE (IC_LEFT (ic));
2493 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2494 emitcode ("mov", "%s,%s", r->name, spname);
2495 emitcode ("inc", "%s", spname); // allocate space first
2496 emitcode ("movx", "@%s,a", r->name);
2500 // allocate space first
2501 emitcode ("mov", "%s,%s", r->name, spname);
2503 emitcode ("add", "a,#%d", size);
2504 emitcode ("mov", "%s,a", spname);
2508 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2509 emitcode ("movx", "@%s,a", r->name);
2510 emitcode ("inc", "%s", r->name);
2514 freeAsmop (NULL, aop, ic, TRUE);
2515 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2518 /*-----------------------------------------------------------------*/
2519 /* genIpush - generate code for pushing this gets a little complex */
2520 /*-----------------------------------------------------------------*/
2522 genIpush (iCode * ic)
2524 int size, offset = 0;
2528 D (emitcode (";", "genIpush"));
2530 /* if this is not a parm push : ie. it is spill push
2531 and spill push is always done on the local stack */
2535 /* and the item is spilt then do nothing */
2536 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2539 aopOp (IC_LEFT (ic), ic, FALSE);
2540 size = AOP_SIZE (IC_LEFT (ic));
2541 /* push it on the stack */
2544 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2550 emitcode ("push", "%s", l);
2555 /* this is a parameter push: in this case we call
2556 the routine to find the call and save those
2557 registers that need to be saved */
2560 /* if use external stack then call the external
2561 stack pushing routine */
2562 if (options.useXstack)
2568 /* then do the push */
2569 aopOp (IC_LEFT (ic), ic, FALSE);
2571 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2572 size = AOP_SIZE (IC_LEFT (ic));
2576 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2577 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2578 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2580 if (strcmp (l, prev) || *l == '@')
2582 emitcode ("push", "acc");
2586 emitcode ("push", "%s", l);
2591 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling */
2596 /*-----------------------------------------------------------------*/
2598 genIpop (iCode * ic)
2602 D (emitcode (";", "genIpop"));
2604 /* if the temp was not pushed then */
2605 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2608 aopOp (IC_LEFT (ic), ic, FALSE);
2609 size = AOP_SIZE (IC_LEFT (ic));
2610 offset = (size - 1);
2613 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2617 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* saveRBank - saves an entire register bank on the stack */
2622 /*-----------------------------------------------------------------*/
2624 saveRBank (int bank, iCode * ic, bool pushPsw)
2627 int count = 8 + (pushPsw ? 1 : 0);
2631 if (options.useXstack)
2635 /* Assume r0 is available for use. */
2636 r = REG_WITH_INDEX (R0_IDX);
2641 r = getFreePtr (ic, &aop, FALSE);
2643 // allocate space first
2644 emitcode ("mov", "%s,%s", r->name, spname);
2646 emitcode ("add", "a,#%d", count);
2647 emitcode ("mov", "%s,a", spname);
2650 for (i = 0; i < 8; i++)
2652 if (options.useXstack)
2654 emitcode ("mov", "a,(%s+%d)",
2655 regs8051[i].base, 8 * bank + regs8051[i].offset);
2656 emitcode ("movx", "@%s,a", r->name);
2658 emitcode ("inc", "%s", r->name);
2661 emitcode ("push", "(%s+%d)",
2662 regs8051[i].base, 8 * bank + regs8051[i].offset);
2667 if (options.useXstack)
2669 emitcode ("mov", "a,psw");
2670 emitcode ("movx", "@%s,a", r->name);
2674 emitcode ("push", "psw");
2677 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2682 freeAsmop (NULL, aop, ic, TRUE);
2691 /*-----------------------------------------------------------------*/
2692 /* unsaveRBank - restores the register bank from stack */
2693 /*-----------------------------------------------------------------*/
2695 unsaveRBank (int bank, iCode * ic, bool popPsw)
2701 if (options.useXstack)
2705 /* Assume r0 is available for use. */
2706 r = REG_WITH_INDEX (R0_IDX);;
2711 r = getFreePtr (ic, &aop, FALSE);
2713 emitcode ("mov", "%s,%s", r->name, spname);
2718 if (options.useXstack)
2720 emitcode ("dec", "%s", r->name);
2721 emitcode ("movx", "a,@%s", r->name);
2722 emitcode ("mov", "psw,a");
2726 emitcode ("pop", "psw");
2730 for (i = 7; i >= 0; i--)
2732 if (options.useXstack)
2734 emitcode ("dec", "%s", r->name);
2735 emitcode ("movx", "a,@%s", r->name);
2736 emitcode ("mov", "(%s+%d),a",
2737 regs8051[i].base, 8 * bank + regs8051[i].offset);
2741 emitcode ("pop", "(%s+%d)",
2742 regs8051[i].base, 8 * bank + regs8051[i].offset);
2746 if (options.useXstack)
2748 emitcode ("mov", "%s,%s", spname, r->name);
2753 freeAsmop (NULL, aop, ic, TRUE);
2757 /*-----------------------------------------------------------------*/
2758 /* genSend - gen code for SEND */
2759 /*-----------------------------------------------------------------*/
2760 static void genSend(set *sendSet)
2765 /* first we do all bit parameters */
2766 for (sic = setFirstItem (sendSet); sic;
2767 sic = setNextItem (sendSet))
2769 if (sic->argreg > 12)
2771 int bit = sic->argreg-13;
2773 aopOp (IC_LEFT (sic), sic, FALSE);
2775 /* if left is a literal then
2776 we know what the value is */
2777 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2779 if (((int) operandLitValue (IC_LEFT (sic))))
2780 emitcode ("setb", "b[%d]", bit);
2782 emitcode ("clr", "b[%d]", bit);
2787 toCarry (IC_LEFT (sic));
2788 emitcode ("mov", "b[%d],c", bit);
2793 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2799 saveRegisters (setFirstItem (sendSet));
2800 emitcode ("mov", "bits,b");
2803 /* then we do all other parameters */
2804 for (sic = setFirstItem (sendSet); sic;
2805 sic = setNextItem (sendSet))
2807 if (sic->argreg <= 12)
2809 int size, offset = 0;
2810 aopOp (IC_LEFT (sic), sic, FALSE);
2811 size = AOP_SIZE (IC_LEFT (sic));
2813 if (sic->argreg == 1)
2817 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2818 if (strcmp (l, fReturn[offset]))
2820 emitcode ("mov", "%s,%s", fReturn[offset], l);
2829 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2830 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2834 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2839 /*-----------------------------------------------------------------*/
2840 /* selectRegBank - emit code to select the register bank */
2841 /*-----------------------------------------------------------------*/
2843 selectRegBank (short bank, bool keepFlags)
2845 /* if f.e. result is in carry */
2848 emitcode ("anl", "psw,#0xE7");
2850 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2854 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2858 /*-----------------------------------------------------------------*/
2859 /* genCall - generates a call statement */
2860 /*-----------------------------------------------------------------*/
2862 genCall (iCode * ic)
2866 // bool restoreBank = FALSE;
2867 bool swapBanks = FALSE;
2868 bool accuse = FALSE;
2869 bool accPushed = FALSE;
2870 bool resultInF0 = FALSE;
2871 bool assignResultGenerated = FALSE;
2873 D (emitcode (";", "genCall"));
2875 dtype = operandType (IC_LEFT (ic));
2876 etype = getSpec(dtype);
2877 /* if send set is not empty then assign */
2880 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2881 genSend(reverseSet(_G.sendSet));
2883 genSend(_G.sendSet);
2888 /* if we are calling a not _naked function that is not using
2889 the same register bank then we need to save the
2890 destination registers on the stack */
2891 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2892 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2893 !IFFUNC_ISISR (dtype))
2898 /* if caller saves & we have not saved then */
2904 emitcode ("mov", "psw,#0x%02x",
2905 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2909 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2911 if (IFFUNC_CALLEESAVES(dtype))
2913 werror (E_BANKED_WITH_CALLEESAVES);
2917 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2918 OP_SYMBOL (IC_LEFT (ic))->rname :
2919 OP_SYMBOL (IC_LEFT (ic))->name);
2921 emitcode ("mov", "r0,#%s", l);
2922 emitcode ("mov", "r1,#(%s >> 8)", l);
2923 emitcode ("mov", "r2,#(%s >> 16)", l);
2924 emitcode ("lcall", "__sdcc_banked_call");
2929 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2930 OP_SYMBOL (IC_LEFT (ic))->rname :
2931 OP_SYMBOL (IC_LEFT (ic))->name));
2936 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2939 /* if we need assign a result value */
2940 if ((IS_ITEMP (IC_RESULT (ic)) &&
2941 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2942 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2943 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2944 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2945 IS_TRUE_SYMOP (IC_RESULT (ic)))
2949 aopOp (IC_RESULT (ic), ic, FALSE);
2952 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2953 assignResultGenerated = TRUE;
2955 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2958 /* adjust the stack for parameters if required */
2962 if (ic->parmBytes > 3)
2966 emitcode ("push", "acc");
2969 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2970 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2971 !assignResultGenerated)
2973 emitcode ("mov", "F0,c");
2977 emitcode ("mov", "a,%s", spname);
2978 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2979 emitcode ("mov", "%s,a", spname);
2981 /* unsaveRegisters from xstack needs acc, but */
2982 /* unsaveRegisters from stack needs this popped */
2983 if (accPushed && !options.useXstack)
2985 emitcode ("pop", "acc");
2990 for (i = 0; i < ic->parmBytes; i++)
2991 emitcode ("dec", "%s", spname);
2994 /* if we had saved some registers then unsave them */
2995 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2997 if (accuse && !accPushed && options.useXstack)
2999 /* xstack needs acc, but doesn't touch normal stack */
3000 emitcode ("push", "acc");
3003 unsaveRegisters (ic);
3006 // /* if register bank was saved then pop them */
3008 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3010 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3013 emitcode ("mov", "c,F0");
3015 aopOp (IC_RESULT (ic), ic, FALSE);
3016 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3017 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3021 emitcode ("pop", "acc");
3024 /*-----------------------------------------------------------------*/
3025 /* genPcall - generates a call by pointer statement */
3026 /*-----------------------------------------------------------------*/
3028 genPcall (iCode * ic)
3032 symbol *rlbl = newiTempLabel (NULL);
3033 // bool restoreBank=FALSE;
3034 bool swapBanks = FALSE;
3035 bool resultInF0 = FALSE;
3037 D (emitcode (";", "genPcall"));
3039 dtype = operandType (IC_LEFT (ic))->next;
3040 etype = getSpec(dtype);
3041 /* if caller saves & we have not saved then */
3045 /* if we are calling a not _naked function that is not using
3046 the same register bank then we need to save the
3047 destination registers on the stack */
3048 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3049 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3050 !IFFUNC_ISISR (dtype))
3052 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3053 // restoreBank=TRUE;
3055 // need caution message to user here
3058 if (IS_LITERAL (etype))
3060 /* if send set is not empty then assign */
3063 genSend(reverseSet(_G.sendSet));
3069 emitcode ("mov", "psw,#0x%02x",
3070 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3073 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3075 if (IFFUNC_CALLEESAVES (dtype))
3077 werror (E_BANKED_WITH_CALLEESAVES);
3081 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3083 emitcode ("mov", "r0,#%s", l);
3084 emitcode ("mov", "r1,#(%s >> 8)", l);
3085 emitcode ("mov", "r2,#(%s >> 16)", l);
3086 emitcode ("lcall", "__sdcc_banked_call");
3091 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3096 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3098 if (IFFUNC_CALLEESAVES (dtype))
3100 werror (E_BANKED_WITH_CALLEESAVES);
3104 aopOp (IC_LEFT (ic), ic, FALSE);
3108 /* what if aopGet needs r0 or r1 ??? */
3109 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3110 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3111 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3115 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3116 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3117 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3118 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3121 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3123 /* if send set is not empty then assign */
3126 genSend(reverseSet(_G.sendSet));
3132 emitcode ("mov", "psw,#0x%02x",
3133 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3137 emitcode ("lcall", "__sdcc_banked_call");
3140 else if (_G.sendSet)
3142 /* push the return address on to the stack */
3143 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3144 emitcode ("push", "acc");
3145 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3146 emitcode ("push", "acc");
3148 /* now push the calling address */
3149 aopOp (IC_LEFT (ic), ic, FALSE);
3151 pushSide (IC_LEFT (ic), FPTRSIZE);
3153 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3155 /* if send set is not empty the assign */
3158 genSend(reverseSet(_G.sendSet));
3164 emitcode ("mov", "psw,#0x%02x",
3165 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3169 emitcode ("ret", "");
3172 else /* the send set is empty */
3175 /* now get the calling address into dptr */
3176 aopOp (IC_LEFT (ic), ic, FALSE);
3178 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3179 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3181 emitcode ("mov", "r0,%s", l);
3182 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3183 emitcode ("mov", "dph,%s", l);
3184 emitcode ("mov", "dpl,r0");
3188 emitcode ("mov", "dpl,%s", l);
3189 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3190 emitcode ("mov", "dph,%s", l);
3193 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3197 emitcode ("mov", "psw,#0x%02x",
3198 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3202 emitcode ("lcall", "__sdcc_call_dptr");
3207 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3210 /* if we need assign a result value */
3211 if ((IS_ITEMP (IC_RESULT (ic)) &&
3212 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3213 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3214 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3215 IS_TRUE_SYMOP (IC_RESULT (ic)))
3219 aopOp (IC_RESULT (ic), ic, FALSE);
3222 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3224 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3227 /* adjust the stack for parameters if required */
3231 if (ic->parmBytes > 3)
3233 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3234 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3236 emitcode ("mov", "F0,c");
3240 emitcode ("mov", "a,%s", spname);
3241 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3242 emitcode ("mov", "%s,a", spname);
3245 for (i = 0; i < ic->parmBytes; i++)
3246 emitcode ("dec", "%s", spname);
3249 // /* if register bank was saved then unsave them */
3251 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3253 /* if we had saved some registers then unsave them */
3254 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3255 unsaveRegisters (ic);
3257 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3260 emitcode ("mov", "c,F0");
3262 aopOp (IC_RESULT (ic), ic, FALSE);
3263 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3264 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3268 /*-----------------------------------------------------------------*/
3269 /* resultRemat - result is rematerializable */
3270 /*-----------------------------------------------------------------*/
3272 resultRemat (iCode * ic)
3274 if (SKIP_IC (ic) || ic->op == IFX)
3277 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3279 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3280 if (sym->remat && !POINTER_SET (ic))
3287 /*-----------------------------------------------------------------*/
3288 /* inExcludeList - return 1 if the string is in exclude Reg list */
3289 /*-----------------------------------------------------------------*/
3291 regsCmp(void *p1, void *p2)
3293 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3297 inExcludeList (char *s)
3299 const char *p = setFirstItem(options.excludeRegsSet);
3301 if (p == NULL || STRCASECMP(p, "none") == 0)
3305 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3308 /*-----------------------------------------------------------------*/
3309 /* genFunction - generated code for function entry */
3310 /*-----------------------------------------------------------------*/
3312 genFunction (iCode * ic)
3314 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3316 bool switchedPSW = FALSE;
3317 int calleesaves_saved_register = -1;
3318 int stackAdjust = sym->stack;
3319 int accIsFree = sym->recvSize < 4;
3320 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3321 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3324 /* create the function header */
3325 emitcode (";", "-----------------------------------------");
3326 emitcode (";", " function %s", sym->name);
3327 emitcode (";", "-----------------------------------------");
3329 emitcode ("", "%s:", sym->rname);
3330 lineCurr->isLabel = 1;
3331 ftype = operandType (IC_LEFT (ic));
3332 _G.currentFunc = sym;
3334 if (IFFUNC_ISNAKED(ftype))
3336 emitcode(";", "naked function: no prologue.");
3340 /* here we need to generate the equates for the
3341 register bank if required */
3342 if (FUNC_REGBANK (ftype) != rbank)
3346 rbank = FUNC_REGBANK (ftype);
3347 for (i = 0; i < mcs51_nRegs; i++)
3349 if (regs8051[i].type != REG_BIT)
3351 if (strcmp (regs8051[i].base, "0") == 0)
3352 emitcode ("", "%s = 0x%02x",
3354 8 * rbank + regs8051[i].offset);
3356 emitcode ("", "%s = %s + 0x%02x",
3359 8 * rbank + regs8051[i].offset);
3364 /* if this is an interrupt service routine then
3365 save acc, b, dpl, dph */
3366 if (IFFUNC_ISISR (sym->type))
3370 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3371 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3373 emitcode ("push", "bits");
3376 freeBitVect (rsavebits);
3378 if (!inExcludeList ("acc"))
3379 emitcode ("push", "acc");
3380 if (!inExcludeList ("b"))
3381 emitcode ("push", "b");
3382 if (!inExcludeList ("dpl"))
3383 emitcode ("push", "dpl");
3384 if (!inExcludeList ("dph"))
3385 emitcode ("push", "dph");
3386 /* if this isr has no bank i.e. is going to
3387 run with bank 0 , then we need to save more
3389 if (!FUNC_REGBANK (sym->type))
3393 /* if this function does not call any other
3394 function then we can be economical and
3395 save only those registers that are used */
3396 if (!IFFUNC_HASFCALL(sym->type))
3398 /* if any registers used */
3401 /* save the registers used */
3402 for (i = 0; i < sym->regsUsed->size; i++)
3404 if (bitVectBitValue (sym->regsUsed, i))
3411 /* this function has a function call. We cannot
3412 determine register usage so we will have to push the
3414 saveRBank (0, ic, FALSE);
3415 if (options.parms_in_bank1) {
3416 for (i=0; i < 8 ; i++ ) {
3417 emitcode ("push","%s",rb1regs[i]);
3424 /* This ISR uses a non-zero bank.
3426 * We assume that the bank is available for our
3429 * However, if this ISR calls a function which uses some
3430 * other bank, we must save that bank entirely.
3432 unsigned long banksToSave = 0;
3434 if (IFFUNC_HASFCALL(sym->type))
3437 #define MAX_REGISTER_BANKS 4
3442 for (i = ic; i; i = i->next)
3444 if (i->op == ENDFUNCTION)
3446 /* we got to the end OK. */
3454 dtype = operandType (IC_LEFT(i));
3456 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3458 /* Mark this bank for saving. */
3459 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3461 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3465 banksToSave |= (1 << FUNC_REGBANK(dtype));
3468 /* And note that we don't need to do it in
3476 /* This is a mess; we have no idea what
3477 * register bank the called function might
3480 * The only thing I can think of to do is
3481 * throw a warning and hope.
3483 werror(W_FUNCPTR_IN_USING_ISR);
3487 if (banksToSave && options.useXstack)
3489 /* Since we aren't passing it an ic,
3490 * saveRBank will assume r0 is available to abuse.
3492 * So switch to our (trashable) bank now, so
3493 * the caller's R0 isn't trashed.
3495 emitcode ("push", "psw");
3496 emitcode ("mov", "psw,#0x%02x",
3497 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3501 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3503 if (banksToSave & (1 << ix))
3505 saveRBank(ix, NULL, FALSE);
3509 // TODO: this needs a closer look
3510 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3513 /* Set the register bank to the desired value if nothing else */
3514 /* has done so yet. */
3517 emitcode ("push", "psw");
3518 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3523 /* This is a non-ISR function. The caller has already switched register */
3524 /* banks, if necessary, so just handle the callee-saves option. */
3526 /* if callee-save to be used for this function
3527 then save the registers being used in this function */
3528 if (IFFUNC_CALLEESAVES(sym->type))
3532 /* if any registers used */
3535 bool bits_pushed = FALSE;
3536 /* save the registers used */
3537 for (i = 0; i < sym->regsUsed->size; i++)
3539 if (bitVectBitValue (sym->regsUsed, i))
3541 /* remember one saved register for later usage */
3542 if (calleesaves_saved_register < 0)
3543 calleesaves_saved_register = i;
3544 bits_pushed = pushReg (i, bits_pushed);
3554 if (options.useXstack)
3556 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3558 emitcode ("mov", "r0,%s", spname);
3559 emitcode ("inc", "%s", spname);
3560 emitcode ("xch", "a,_bpx");
3561 emitcode ("movx", "@r0,a");
3562 emitcode ("inc", "r0");
3563 emitcode ("mov", "a,r0");
3564 emitcode ("xch", "a,_bpx");
3568 emitcode ("push", "_bp"); /* save the callers stack */
3569 emitcode ("mov", "_bp,sp");
3574 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3576 /* set up the stack */
3577 emitcode ("push", "_bp"); /* save the callers stack */
3578 emitcode ("mov", "_bp,sp");
3583 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3584 /* before setting up the stack frame completely. */
3585 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3587 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3591 if (rsym && rsym->regType == REG_CND)
3593 if (rsym && (rsym->accuse || rsym->ruonly))
3595 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3596 rsym = rsym->usl.spillLoc;
3599 /* If the RECEIVE operand immediately spills to the first entry on the */
3600 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3601 /* rather than the usual @r0/r1 machinations. */
3602 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3606 _G.current_iCode = ric;
3607 D(emitcode (";", "genReceive"));
3608 for (ofs=0; ofs < sym->recvSize; ofs++)
3610 if (!strcmp (fReturn[ofs], "a"))
3611 emitcode ("push", "acc");
3613 emitcode ("push", fReturn[ofs]);
3615 stackAdjust -= sym->recvSize;
3618 assert (stackAdjust>=0);
3621 _G.current_iCode = ic;
3625 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3626 /* to free up the accumulator. */
3627 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3631 _G.current_iCode = ric;
3632 D(emitcode (";", "genReceive"));
3633 for (ofs=0; ofs < sym->recvSize; ofs++)
3635 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3637 _G.current_iCode = ic;
3643 /* adjust the stack for the function */
3646 int i = stackAdjust;
3648 werror (W_STACK_OVERFLOW, sym->name);
3650 if (i > 3 && accIsFree)
3652 emitcode ("mov", "a,sp");
3653 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3654 emitcode ("mov", "sp,a");
3658 /* The accumulator is not free, so we will need another register */
3659 /* to clobber. No need to worry about a possible conflict with */
3660 /* the above early RECEIVE optimizations since they would have */
3661 /* freed the accumulator if they were generated. */
3663 if (IFFUNC_CALLEESAVES(sym->type))
3665 /* if it's a callee-saves function we need a saved register */
3666 if (calleesaves_saved_register >= 0)
3668 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3672 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3675 /* do it the hard way */
3677 emitcode ("inc", "sp");
3681 /* not callee-saves, we can clobber r0 */
3682 emitcode ("mov", "r0,a");
3683 emitcode ("mov", "a,sp");
3684 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3685 emitcode ("mov", "sp,a");
3686 emitcode ("mov", "a,r0");
3691 emitcode ("inc", "sp");
3696 char i = ((char) sym->xstack & 0xff);
3698 if (i > 3 && accIsFree)
3700 emitcode ("mov", "a,_spx");
3701 emitcode ("add", "a,#0x%02x", i & 0xff);
3702 emitcode ("mov", "_spx,a");
3706 emitcode ("push", "acc");
3707 emitcode ("mov", "a,_spx");
3708 emitcode ("add", "a,#0x%02x", i & 0xff);
3709 emitcode ("mov", "_spx,a");
3710 emitcode ("pop", "acc");
3715 emitcode ("inc", "_spx");
3719 /* if critical function then turn interrupts off */
3720 if (IFFUNC_ISCRITICAL (ftype))
3722 symbol *tlbl = newiTempLabel (NULL);
3723 emitcode ("setb", "c");
3724 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3725 emitcode ("clr", "c");
3727 emitcode ("push", "psw"); /* save old ea via c in psw */
3731 /*-----------------------------------------------------------------*/
3732 /* genEndFunction - generates epilogue for functions */
3733 /*-----------------------------------------------------------------*/
3735 genEndFunction (iCode * ic)
3737 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3738 lineNode *lnp = lineCurr;
3740 bitVect *regsUsedPrologue;
3741 bitVect *regsUnneeded;
3744 _G.currentFunc = NULL;
3745 if (IFFUNC_ISNAKED(sym->type))
3747 emitcode(";", "naked function: no epilogue.");
3748 if (options.debug && currFunc)
3749 debugFile->writeEndFunction (currFunc, ic, 0);
3753 if (IFFUNC_ISCRITICAL (sym->type))
3755 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3757 emitcode ("rlc", "a"); /* save c in a */
3758 emitcode ("pop", "psw"); /* restore ea via c in psw */
3759 emitcode ("mov", "ea,c");
3760 emitcode ("rrc", "a"); /* restore c from a */
3764 emitcode ("pop", "psw"); /* restore ea via c in psw */
3765 emitcode ("mov", "ea,c");
3769 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3771 if (options.useXstack)
3775 emitcode ("mov", "sp,_bp");
3776 emitcode ("pop", "_bp");
3778 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3780 emitcode ("xch", "a,_bpx");
3781 emitcode ("mov", "r0,a");
3782 emitcode ("dec", "r0");
3783 emitcode ("movx", "a,@r0");
3784 emitcode ("xch", "a,_bpx");
3785 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3788 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3791 emitcode ("mov", "sp,_bp");
3792 emitcode ("pop", "_bp");
3796 /* restore the register bank */
3797 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3799 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3800 || !options.useXstack)
3802 /* Special case of ISR using non-zero bank with useXstack
3805 emitcode ("pop", "psw");
3809 if (IFFUNC_ISISR (sym->type))
3813 /* now we need to restore the registers */
3814 /* if this isr has no bank i.e. is going to
3815 run with bank 0 , then we need to save more
3817 if (!FUNC_REGBANK (sym->type))
3820 /* if this function does not call any other
3821 function then we can be economical and
3822 save only those registers that are used */
3823 if (!IFFUNC_HASFCALL(sym->type))
3825 /* if any registers used */
3828 /* save the registers used */
3829 for (i = sym->regsUsed->size; i >= 0; i--)
3831 if (bitVectBitValue (sym->regsUsed, i))
3838 if (options.parms_in_bank1) {
3839 for (i = 7 ; i >= 0 ; i-- ) {
3840 emitcode ("pop","%s",rb1regs[i]);
3843 /* this function has a function call. We cannot
3844 determine register usage so we will have to pop the
3846 unsaveRBank (0, ic, FALSE);
3851 /* This ISR uses a non-zero bank.
3853 * Restore any register banks saved by genFunction
3856 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3859 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3861 if (savedBanks & (1 << ix))
3863 unsaveRBank(ix, NULL, FALSE);
3867 if (options.useXstack)
3869 /* Restore bank AFTER calling unsaveRBank,
3870 * since it can trash r0.
3872 emitcode ("pop", "psw");
3876 if (!inExcludeList ("dph"))
3877 emitcode ("pop", "dph");
3878 if (!inExcludeList ("dpl"))
3879 emitcode ("pop", "dpl");
3880 if (!inExcludeList ("b"))
3881 emitcode ("pop", "b");
3882 if (!inExcludeList ("acc"))
3883 emitcode ("pop", "acc");
3885 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3886 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3887 emitcode ("pop", "bits");
3888 freeBitVect (rsavebits);
3890 /* if debug then send end of function */
3891 if (options.debug && currFunc)
3893 debugFile->writeEndFunction (currFunc, ic, 1);
3896 emitcode ("reti", "");
3900 if (IFFUNC_CALLEESAVES(sym->type))
3904 /* if any registers used */
3907 /* save the registers used */
3908 for (i = sym->regsUsed->size; i >= 0; i--)
3910 if (bitVectBitValue (sym->regsUsed, i) ||
3911 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3912 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3915 else if (mcs51_ptrRegReq)
3917 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3918 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3923 /* if debug then send end of function */
3924 if (options.debug && currFunc)
3926 debugFile->writeEndFunction (currFunc, ic, 1);
3929 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3931 emitcode ("ljmp", "__sdcc_banked_ret");
3935 emitcode ("ret", "");
3939 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3942 /* If this was an interrupt handler using bank 0 that called another */
3943 /* function, then all registers must be saved; nothing to optimized. */
3944 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3945 && !FUNC_REGBANK(sym->type))
3948 /* There are no push/pops to optimize if not callee-saves or ISR */
3949 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3952 /* If there were stack parameters, we cannot optimize without also */
3953 /* fixing all of the stack offsets; this is too dificult to consider. */
3954 if (FUNC_HASSTACKPARM(sym->type))
3957 /* Compute the registers actually used */
3958 regsUsed = newBitVect (mcs51_nRegs);
3959 regsUsedPrologue = newBitVect (mcs51_nRegs);
3962 if (lnp->ic && lnp->ic->op == FUNCTION)
3963 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3965 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3967 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3968 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3975 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3976 && !bitVectBitValue (regsUsed, CND_IDX))
3978 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3979 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3980 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3981 bitVectUnSetBit (regsUsed, CND_IDX);
3984 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3986 /* If this was an interrupt handler that called another function */
3987 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3988 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3990 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3991 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3992 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3997 /* Remove the unneeded push/pops */
3998 regsUnneeded = newBitVect (mcs51_nRegs);
4001 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4003 if (!strncmp(lnp->line, "push", 4))
4005 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4006 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4008 connectLine (lnp->prev, lnp->next);
4009 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4012 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4014 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4015 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4017 connectLine (lnp->prev, lnp->next);
4018 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4025 for (idx = 0; idx < regsUnneeded->size; idx++)
4026 if (bitVectBitValue (regsUnneeded, idx))
4027 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4029 freeBitVect (regsUnneeded);
4030 freeBitVect (regsUsed);
4031 freeBitVect (regsUsedPrologue);
4034 /*-----------------------------------------------------------------*/
4035 /* genRet - generate code for return statement */
4036 /*-----------------------------------------------------------------*/
4040 int size, offset = 0, pushed = 0;
4042 D (emitcode (";", "genRet"));
4044 /* if we have no return value then
4045 just generate the "ret" */
4049 /* we have something to return then
4050 move the return value into place */
4051 aopOp (IC_LEFT (ic), ic, FALSE);
4052 size = AOP_SIZE (IC_LEFT (ic));
4054 if (IS_BIT(_G.currentFunc->etype))
4056 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4057 toCarry (IC_LEFT (ic));
4064 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4067 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4068 emitcode ("push", "%s", l);
4073 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4074 if (strcmp (fReturn[offset], l))
4075 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4082 if (strcmp (fReturn[pushed], "a"))
4083 emitcode ("pop", fReturn[pushed]);
4085 emitcode ("pop", "acc");
4088 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4091 /* generate a jump to the return label
4092 if the next is not the return statement */
4093 if (!(ic->next && ic->next->op == LABEL &&
4094 IC_LABEL (ic->next) == returnLabel))
4096 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4100 /*-----------------------------------------------------------------*/
4101 /* genLabel - generates a label */
4102 /*-----------------------------------------------------------------*/
4104 genLabel (iCode * ic)
4106 /* special case never generate */
4107 if (IC_LABEL (ic) == entryLabel)
4110 emitLabel (IC_LABEL (ic));
4113 /*-----------------------------------------------------------------*/
4114 /* genGoto - generates a ljmp */
4115 /*-----------------------------------------------------------------*/
4117 genGoto (iCode * ic)
4119 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4122 /*-----------------------------------------------------------------*/
4123 /* findLabelBackwards: walks back through the iCode chain looking */
4124 /* for the given label. Returns number of iCode instructions */
4125 /* between that label and given ic. */
4126 /* Returns zero if label not found. */
4127 /*-----------------------------------------------------------------*/
4129 findLabelBackwards (iCode * ic, int key)
4138 /* If we have any pushes or pops, we cannot predict the distance.
4139 I don't like this at all, this should be dealt with in the
4141 if (ic->op == IPUSH || ic->op == IPOP) {
4145 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4154 /*-----------------------------------------------------------------*/
4155 /* genPlusIncr :- does addition with increment if possible */
4156 /*-----------------------------------------------------------------*/
4158 genPlusIncr (iCode * ic)
4160 unsigned int icount;
4161 unsigned int size = getDataSize (IC_RESULT (ic));
4163 /* will try to generate an increment */
4164 /* if the right side is not a literal
4166 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4169 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4171 D(emitcode (";","genPlusIncr"));
4173 /* if increment >=16 bits in register or direct space */
4174 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4175 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4176 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4177 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4178 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4186 /* If the next instruction is a goto and the goto target
4187 * is < 10 instructions previous to this, we can generate
4188 * jumps straight to that target.
4190 if (ic->next && ic->next->op == GOTO
4191 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4192 && labelRange <= 10)
4194 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4195 tlbl = IC_LABEL (ic->next);
4200 tlbl = newiTempLabel (NULL);
4203 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4204 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4205 IS_AOP_PREG (IC_RESULT (ic)))
4206 emitcode ("cjne", "%s,#0x00,%05d$",
4207 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4211 emitcode ("clr", "a");
4212 emitcode ("cjne", "a,%s,%05d$",
4213 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4217 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4220 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221 IS_AOP_PREG (IC_RESULT (ic)))
4222 emitcode ("cjne", "%s,#0x00,%05d$",
4223 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4226 emitcode ("cjne", "a,%s,%05d$",
4227 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4230 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4235 IS_AOP_PREG (IC_RESULT (ic)))
4236 emitcode ("cjne", "%s,#0x00,%05d$",
4237 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4241 emitcode ("cjne", "a,%s,%05d$",
4242 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4245 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4255 /* if result is dptr */
4256 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4257 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4258 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4259 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4261 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4267 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4270 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4271 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4273 emitcode ("inc", "dptr");
4278 /* if the literal value of the right hand side
4279 is greater than 4 then it is not worth it */
4283 /* if the sizes are greater than 1 then we cannot */
4284 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4285 AOP_SIZE (IC_LEFT (ic)) > 1)
4288 /* we can if the aops of the left & result match or
4289 if they are in registers and the registers are the
4291 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4295 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4296 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4297 aopPut (IC_RESULT (ic), "a", 0);
4303 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4312 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313 emitcode ("inc", "a");
4314 aopPut (IC_RESULT (ic), "a", 0);
4321 /*-----------------------------------------------------------------*/
4322 /* outBitAcc - output a bit in acc */
4323 /*-----------------------------------------------------------------*/
4325 outBitAcc (operand * result)
4327 symbol *tlbl = newiTempLabel (NULL);
4328 /* if the result is a bit */
4329 if (AOP_TYPE (result) == AOP_CRY)
4331 aopPut (result, "a", 0);
4335 emitcode ("jz", "%05d$", tlbl->key + 100);
4336 emitcode ("mov", "a,%s", one);
4342 /*-----------------------------------------------------------------*/
4343 /* genPlusBits - generates code for addition of two bits */
4344 /*-----------------------------------------------------------------*/
4346 genPlusBits (iCode * ic)
4348 D (emitcode (";", "genPlusBits"));
4350 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4351 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4353 symbol *lbl = newiTempLabel (NULL);
4354 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4355 emitcode ("cpl", "c");
4357 outBitC (IC_RESULT (ic));
4361 emitcode ("clr", "a");
4362 emitcode ("rlc", "a");
4363 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4364 emitcode ("addc", "a,%s", zero);
4365 outAcc (IC_RESULT (ic));
4370 /* This is the original version of this code.
4372 * This is being kept around for reference,
4373 * because I am not entirely sure I got it right...
4376 adjustArithmeticResult (iCode * ic)
4378 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4380 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4381 aopPut (IC_RESULT (ic),
4382 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4385 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4386 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4387 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4388 aopPut (IC_RESULT (ic),
4389 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4392 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4393 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4394 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4395 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4396 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4399 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4400 aopPut (IC_RESULT (ic), buffer, 2);
4404 /* This is the pure and virtuous version of this code.
4405 * I'm pretty certain it's right, but not enough to toss the old
4409 adjustArithmeticResult (iCode * ic)
4411 if (opIsGptr (IC_RESULT (ic)) &&
4412 opIsGptr (IC_LEFT (ic)) &&
4413 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4415 aopPut (IC_RESULT (ic),
4416 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4420 if (opIsGptr (IC_RESULT (ic)) &&
4421 opIsGptr (IC_RIGHT (ic)) &&
4422 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4424 aopPut (IC_RESULT (ic),
4425 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4429 if (opIsGptr (IC_RESULT (ic)) &&
4430 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4431 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4433 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4436 SNPRINTF (buffer, sizeof(buffer),
4437 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4438 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4443 /*-----------------------------------------------------------------*/
4444 /* genPlus - generates code for addition */
4445 /*-----------------------------------------------------------------*/
4447 genPlus (iCode * ic)
4449 int size, offset = 0;
4452 bool swappedLR = FALSE;
4453 operand *leftOp, *rightOp;
4456 D (emitcode (";", "genPlus"));
4458 /* special cases :- */
4460 aopOp (IC_LEFT (ic), ic, FALSE);
4461 aopOp (IC_RIGHT (ic), ic, FALSE);
4462 aopOp (IC_RESULT (ic), ic, TRUE);
4464 /* if literal, literal on the right or
4465 if left requires ACC or right is already
4467 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4468 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4469 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4471 operand *t = IC_RIGHT (ic);
4472 IC_RIGHT (ic) = IC_LEFT (ic);
4477 /* if both left & right are in bit
4479 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4480 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4486 /* if left in bit space & right literal */
4487 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4488 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4490 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4491 /* if result in bit space */
4492 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4494 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4495 emitcode ("cpl", "c");
4496 outBitC (IC_RESULT (ic));
4500 size = getDataSize (IC_RESULT (ic));
4503 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4504 emitcode ("addc", "a,%s", zero);
4505 aopPut (IC_RESULT (ic), "a", offset++);
4511 /* if I can do an increment instead
4512 of add then GOOD for ME */
4513 if (genPlusIncr (ic) == TRUE)
4516 size = getDataSize (IC_RESULT (ic));
4517 leftOp = IC_LEFT(ic);
4518 rightOp = IC_RIGHT(ic);
4521 /* if this is an add for an array access
4522 at a 256 byte boundary */
4524 && AOP_TYPE (op) == AOP_IMMD
4526 && IS_SPEC (OP_SYM_ETYPE (op))
4527 && SPEC_ABSA (OP_SYM_ETYPE (op))
4528 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4531 D(emitcode (";", "genPlus aligned array"));
4532 aopPut (IC_RESULT (ic),
4533 aopGet (rightOp, 0, FALSE, FALSE),
4536 if( 1 == getDataSize (IC_RIGHT (ic)) )
4538 aopPut (IC_RESULT (ic),
4539 aopGet (leftOp, 1, FALSE, FALSE),
4544 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4545 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4546 aopPut (IC_RESULT (ic), "a", 1);
4551 /* if the lower bytes of a literal are zero skip the addition */
4552 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4554 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4555 (skip_bytes+1 < size))
4560 D(emitcode (";", "genPlus shortcut"));
4565 if( offset >= skip_bytes )
4567 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4570 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4572 emitcode("xch", "a,b");
4573 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4574 emitcode (add, "a,b");
4577 else if (aopGetUsesAcc (leftOp, offset))
4579 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4580 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4584 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4585 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4587 aopPut (IC_RESULT (ic), "a", offset);
4588 add = "addc"; /* further adds must propagate carry */
4592 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4593 isOperandVolatile (IC_RESULT (ic), FALSE))
4596 aopPut (IC_RESULT (ic),
4597 aopGet (leftOp, offset, FALSE, FALSE),
4604 adjustArithmeticResult (ic);
4607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4610 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 /*-----------------------------------------------------------------*/
4621 /* genMinusDec :- does subtraction with decrement if possible */
4622 /*-----------------------------------------------------------------*/
4624 genMinusDec (iCode * ic)
4626 unsigned int icount;
4627 unsigned int size = getDataSize (IC_RESULT (ic));
4629 /* will try to generate an increment */
4630 /* if the right side is not a literal
4632 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4635 /* if the literal value of the right hand side
4636 is greater than 4 then it is not worth it */
4637 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4640 D (emitcode (";", "genMinusDec"));
4642 /* if decrement >=16 bits in register or direct space */
4643 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4644 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4645 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4646 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4654 /* If the next instruction is a goto and the goto target
4655 * is <= 10 instructions previous to this, we can generate
4656 * jumps straight to that target.
4658 if (ic->next && ic->next->op == GOTO
4659 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4660 && labelRange <= 10)
4662 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4663 tlbl = IC_LABEL (ic->next);
4668 tlbl = newiTempLabel (NULL);
4672 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4673 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4674 IS_AOP_PREG (IC_RESULT (ic)))
4675 emitcode ("cjne", "%s,#0xff,%05d$"
4676 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4680 emitcode ("mov", "a,#0xff");
4681 emitcode ("cjne", "a,%s,%05d$"
4682 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4685 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4688 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4689 IS_AOP_PREG (IC_RESULT (ic)))
4690 emitcode ("cjne", "%s,#0xff,%05d$"
4691 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4695 emitcode ("cjne", "a,%s,%05d$"
4696 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4699 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4703 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4704 IS_AOP_PREG (IC_RESULT (ic)))
4705 emitcode ("cjne", "%s,#0xff,%05d$"
4706 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4710 emitcode ("cjne", "a,%s,%05d$"
4711 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4714 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4723 /* if the sizes are greater than 1 then we cannot */
4724 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4725 AOP_SIZE (IC_LEFT (ic)) > 1)
4728 /* we can if the aops of the left & result match or
4729 if they are in registers and the registers are the
4731 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4735 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4737 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4742 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4747 emitcode ("dec", "%s", l);
4750 if (AOP_NEEDSACC (IC_RESULT (ic)))
4751 aopPut (IC_RESULT (ic), "a", 0);
4758 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4759 emitcode ("dec", "a");
4760 aopPut (IC_RESULT (ic), "a", 0);
4767 /*-----------------------------------------------------------------*/
4768 /* addSign - complete with sign */
4769 /*-----------------------------------------------------------------*/
4771 addSign (operand * result, int offset, int sign)
4773 int size = (getDataSize (result) - offset);
4778 emitcode ("rlc", "a");
4779 emitcode ("subb", "a,acc");
4782 aopPut (result, "a", offset++);
4789 aopPut (result, zero, offset++);
4795 /*-----------------------------------------------------------------*/
4796 /* genMinusBits - generates code for subtraction of two bits */
4797 /*-----------------------------------------------------------------*/
4799 genMinusBits (iCode * ic)
4801 symbol *lbl = newiTempLabel (NULL);
4803 D (emitcode (";", "genMinusBits"));
4805 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4807 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4808 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4809 emitcode ("cpl", "c");
4811 outBitC (IC_RESULT (ic));
4815 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4816 emitcode ("subb", "a,acc");
4817 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4818 emitcode ("inc", "a");
4820 aopPut (IC_RESULT (ic), "a", 0);
4821 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4825 /*-----------------------------------------------------------------*/
4826 /* genMinus - generates code for subtraction */
4827 /*-----------------------------------------------------------------*/
4829 genMinus (iCode * ic)
4831 int size, offset = 0;
4833 D (emitcode (";", "genMinus"));
4835 aopOp (IC_LEFT (ic), ic, FALSE);
4836 aopOp (IC_RIGHT (ic), ic, FALSE);
4837 aopOp (IC_RESULT (ic), ic, TRUE);
4839 /* special cases :- */
4840 /* if both left & right are in bit space */
4841 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4842 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4848 /* if I can do an decrement instead
4849 of subtract then GOOD for ME */
4850 if (genMinusDec (ic) == TRUE)
4853 size = getDataSize (IC_RESULT (ic));
4855 /* if literal, add a,#-lit, else normal subb */
4856 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4858 unsigned long lit = 0L;
4859 bool useCarry = FALSE;
4861 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4866 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4868 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4869 if (!offset && !size && lit== (unsigned long) -1)
4871 emitcode ("dec", "a");
4875 /* first add without previous c */
4876 emitcode ("add", "a,#0x%02x",
4877 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4882 emitcode ("addc", "a,#0x%02x",
4883 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4885 aopPut (IC_RESULT (ic), "a", offset++);
4889 /* no need to add zeroes */
4890 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4892 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4901 operand *leftOp, *rightOp;
4903 leftOp = IC_LEFT(ic);
4904 rightOp = IC_RIGHT(ic);
4908 if (aopGetUsesAcc(rightOp, offset)) {
4909 if (aopGetUsesAcc(leftOp, offset)) {
4912 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4914 emitcode ("mov", "b,a");
4917 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4918 emitcode ("subb", "a,b");
4921 /* reverse subtraction with 2's complement */
4923 emitcode( "setb", "c");
4925 emitcode( "cpl", "c");
4926 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4927 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4928 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4929 emitcode("cpl", "a");
4930 if (size) /* skip if last byte */
4931 emitcode( "cpl", "c");
4934 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4937 emitcode ("subb", "a,%s",
4938 aopGet(rightOp, offset, FALSE, TRUE));
4941 aopPut (IC_RESULT (ic), "a", offset++);
4945 adjustArithmeticResult (ic);
4948 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4949 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4954 /*-----------------------------------------------------------------*/
4955 /* genMultbits :- multiplication of bits */
4956 /*-----------------------------------------------------------------*/
4958 genMultbits (operand * left,
4962 D (emitcode (";", "genMultbits"));
4964 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4965 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4969 /*-----------------------------------------------------------------*/
4970 /* genMultOneByte : 8*8=8/16 bit multiplication */
4971 /*-----------------------------------------------------------------*/
4973 genMultOneByte (operand * left,
4978 int size = AOP_SIZE (result);
4979 bool runtimeSign, compiletimeSign;
4980 bool lUnsigned, rUnsigned, pushedB;
4982 D (emitcode (";", "genMultOneByte"));
4984 if (size < 1 || size > 2)
4986 /* this should never happen */
4987 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4988 AOP_SIZE(result), __FILE__, lineno);
4992 /* (if two literals: the value is computed before) */
4993 /* if one literal, literal on the right */
4994 if (AOP_TYPE (left) == AOP_LIT)
4999 /* emitcode (";", "swapped left and right"); */
5001 /* if no literal, unsigned on the right: shorter code */
5002 if ( AOP_TYPE (right) != AOP_LIT
5003 && SPEC_USIGN (getSpec (operandType (left))))
5010 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5011 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5015 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5016 no need to take care about the signedness! */
5017 || (lUnsigned && rUnsigned))
5019 /* just an unsigned 8 * 8 = 8 multiply
5021 /* emitcode (";","unsigned"); */
5022 /* TODO: check for accumulator clash between left & right aops? */
5024 if (AOP_TYPE (right) == AOP_LIT)
5026 /* moving to accumulator first helps peepholes */
5027 MOVA (aopGet (left, 0, FALSE, FALSE));
5028 MOVB (aopGet (right, 0, FALSE, FALSE));
5032 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5033 MOVA (aopGet (left, 0, FALSE, FALSE));
5036 emitcode ("mul", "ab");
5037 aopPut (result, "a", 0);
5039 aopPut (result, "b", 1);
5045 /* we have to do a signed multiply */
5046 /* emitcode (";", "signed"); */
5048 /* now sign adjust for both left & right */
5050 /* let's see what's needed: */
5051 /* apply negative sign during runtime */
5052 runtimeSign = FALSE;
5053 /* negative sign from literals */
5054 compiletimeSign = FALSE;
5058 if (AOP_TYPE(left) == AOP_LIT)
5060 /* signed literal */
5061 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5063 compiletimeSign = TRUE;
5066 /* signed but not literal */
5072 if (AOP_TYPE(right) == AOP_LIT)
5074 /* signed literal */
5075 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5077 compiletimeSign ^= TRUE;
5080 /* signed but not literal */
5084 /* initialize F0, which stores the runtime sign */
5087 if (compiletimeSign)
5088 emitcode ("setb", "F0"); /* set sign flag */
5090 emitcode ("clr", "F0"); /* reset sign flag */
5093 /* save the signs of the operands */
5094 if (AOP_TYPE(right) == AOP_LIT)
5096 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5098 if (!rUnsigned && val < 0)
5099 emitcode ("mov", "b,#0x%02x", -val);
5101 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5103 else /* ! literal */
5105 if (rUnsigned) /* emitcode (";", "signed"); */
5106 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5109 MOVA (aopGet (right, 0, FALSE, FALSE));
5110 lbl = newiTempLabel (NULL);
5111 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5112 emitcode ("cpl", "F0"); /* complement sign flag */
5113 emitcode ("cpl", "a"); /* 2's complement */
5114 emitcode ("inc", "a");
5116 emitcode ("mov", "b,a");
5120 if (AOP_TYPE(left) == AOP_LIT)
5122 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5124 if (!lUnsigned && val < 0)
5125 emitcode ("mov", "a,#0x%02x", -val);
5127 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5129 else /* ! literal */
5131 MOVA (aopGet (left, 0, FALSE, FALSE));
5135 lbl = newiTempLabel (NULL);
5136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5137 emitcode ("cpl", "F0"); /* complement sign flag */
5138 emitcode ("cpl", "a"); /* 2's complement */
5139 emitcode ("inc", "a");
5144 /* now the multiplication */
5145 emitcode ("mul", "ab");
5146 if (runtimeSign || compiletimeSign)
5148 lbl = newiTempLabel (NULL);
5150 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5151 emitcode ("cpl", "a"); /* lsb 2's complement */
5153 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5156 emitcode ("add", "a,#1"); /* this sets carry flag */
5157 emitcode ("xch", "a,b");
5158 emitcode ("cpl", "a"); /* msb 2's complement */
5159 emitcode ("addc", "a,#0");
5160 emitcode ("xch", "a,b");
5164 aopPut (result, "a", 0);
5166 aopPut (result, "b", 1);
5171 /*-----------------------------------------------------------------*/
5172 /* genMult - generates code for multiplication */
5173 /*-----------------------------------------------------------------*/
5175 genMult (iCode * ic)
5177 operand *left = IC_LEFT (ic);
5178 operand *right = IC_RIGHT (ic);
5179 operand *result = IC_RESULT (ic);
5181 D (emitcode (";", "genMult"));
5183 /* assign the asmops */
5184 aopOp (left, ic, FALSE);
5185 aopOp (right, ic, FALSE);
5186 aopOp (result, ic, TRUE);
5188 /* special cases first */
5190 if (AOP_TYPE (left) == AOP_CRY &&
5191 AOP_TYPE (right) == AOP_CRY)
5193 genMultbits (left, right, result);
5197 /* if both are of size == 1 */
5198 #if 0 // one of them can be a sloc shared with the result
5199 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5201 if (getSize(operandType(left)) == 1 &&
5202 getSize(operandType(right)) == 1)
5205 genMultOneByte (left, right, result);
5209 /* should have been converted to function call */
5210 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5211 getSize(OP_SYMBOL(right)->type));
5215 freeAsmop (result, NULL, ic, TRUE);
5216 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5217 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5220 /*-----------------------------------------------------------------*/
5221 /* genDivbits :- division of bits */
5222 /*-----------------------------------------------------------------*/
5224 genDivbits (operand * left,
5231 D(emitcode (";", "genDivbits"));
5235 /* the result must be bit */
5236 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5237 l = aopGet (left, 0, FALSE, FALSE);
5241 emitcode ("div", "ab");
5242 emitcode ("rrc", "a");
5246 aopPut (result, "c", 0);
5249 /*-----------------------------------------------------------------*/
5250 /* genDivOneByte : 8 bit division */
5251 /*-----------------------------------------------------------------*/
5253 genDivOneByte (operand * left,
5257 bool lUnsigned, rUnsigned, pushedB;
5258 bool runtimeSign, compiletimeSign;
5259 bool accuse = FALSE;
5260 bool pushedA = FALSE;
5264 D(emitcode (";", "genDivOneByte"));
5266 /* Why is it necessary that genDivOneByte() can return an int result?
5269 volatile unsigned char uc;
5270 volatile signed char sc1, sc2;
5283 In all cases a one byte result would overflow, the following cast to int
5284 would return the wrong result.
5286 Two possible solution:
5287 a) cast operands to int, if ((unsigned) / (signed)) or
5288 ((signed) / (signed))
5289 b) return an 16 bit signed int; this is what we're doing here!
5292 size = AOP_SIZE (result) - 1;
5294 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5295 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5299 /* signed or unsigned */
5300 if (lUnsigned && rUnsigned)
5302 /* unsigned is easy */
5303 MOVB (aopGet (right, 0, FALSE, FALSE));
5304 MOVA (aopGet (left, 0, FALSE, FALSE));
5305 emitcode ("div", "ab");
5306 aopPut (result, "a", 0);
5308 aopPut (result, zero, offset++);
5314 /* signed is a little bit more difficult */
5316 /* now sign adjust for both left & right */
5318 /* let's see what's needed: */
5319 /* apply negative sign during runtime */
5320 runtimeSign = FALSE;
5321 /* negative sign from literals */
5322 compiletimeSign = FALSE;
5326 if (AOP_TYPE(left) == AOP_LIT)
5328 /* signed literal */
5329 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5331 compiletimeSign = TRUE;
5334 /* signed but not literal */
5340 if (AOP_TYPE(right) == AOP_LIT)
5342 /* signed literal */
5343 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5345 compiletimeSign ^= TRUE;
5348 /* signed but not literal */
5352 /* initialize F0, which stores the runtime sign */
5355 if (compiletimeSign)
5356 emitcode ("setb", "F0"); /* set sign flag */
5358 emitcode ("clr", "F0"); /* reset sign flag */
5361 /* save the signs of the operands */
5362 if (AOP_TYPE(right) == AOP_LIT)
5364 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5366 if (!rUnsigned && val < 0)
5367 emitcode ("mov", "b,#0x%02x", -val);
5369 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5371 else /* ! literal */
5374 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5377 MOVA (aopGet (right, 0, FALSE, FALSE));
5378 lbl = newiTempLabel (NULL);
5379 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5380 emitcode ("cpl", "F0"); /* complement sign flag */
5381 emitcode ("cpl", "a"); /* 2's complement */
5382 emitcode ("inc", "a");
5384 emitcode ("mov", "b,a");
5388 if (AOP_TYPE(left) == AOP_LIT)
5390 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5392 if (!lUnsigned && val < 0)
5393 emitcode ("mov", "a,#0x%02x", -val);
5395 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5397 else /* ! literal */
5399 MOVA (aopGet (left, 0, FALSE, FALSE));
5403 lbl = newiTempLabel (NULL);
5404 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5405 emitcode ("cpl", "F0"); /* complement sign flag */
5406 emitcode ("cpl", "a"); /* 2's complement */
5407 emitcode ("inc", "a");
5412 /* now the division */
5413 emitcode ("div", "ab");
5415 if (runtimeSign || compiletimeSign)
5417 lbl = newiTempLabel (NULL);
5419 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5420 emitcode ("cpl", "a"); /* lsb 2's complement */
5421 emitcode ("inc", "a");
5424 accuse = aopPut (result, "a", 0);
5427 /* msb is 0x00 or 0xff depending on the sign */
5432 emitcode ("push", "acc");
5435 emitcode ("mov", "c,F0");
5436 emitcode ("subb", "a,acc");
5438 aopPut (result, "a", offset++);
5440 else /* compiletimeSign */
5442 if (aopPutUsesAcc (result, "#0xFF", offset))
5444 emitcode ("push", "acc");
5448 aopPut (result, "#0xff", offset++);
5454 aopPut (result, "a", 0);
5456 aopPut (result, zero, offset++);
5460 emitcode ("pop", "acc");
5464 /*-----------------------------------------------------------------*/
5465 /* genDiv - generates code for division */
5466 /*-----------------------------------------------------------------*/
5470 operand *left = IC_LEFT (ic);
5471 operand *right = IC_RIGHT (ic);
5472 operand *result = IC_RESULT (ic);
5474 D (emitcode (";", "genDiv"));
5476 /* assign the asmops */
5477 aopOp (left, ic, FALSE);
5478 aopOp (right, ic, FALSE);
5479 aopOp (result, ic, TRUE);
5481 /* special cases first */
5483 if (AOP_TYPE (left) == AOP_CRY &&
5484 AOP_TYPE (right) == AOP_CRY)
5486 genDivbits (left, right, result);
5490 /* if both are of size == 1 */
5491 if (AOP_SIZE (left) == 1 &&
5492 AOP_SIZE (right) == 1)
5494 genDivOneByte (left, right, result);
5498 /* should have been converted to function call */
5501 freeAsmop (result, NULL, ic, TRUE);
5502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506 /*-----------------------------------------------------------------*/
5507 /* genModbits :- modulus of bits */
5508 /*-----------------------------------------------------------------*/
5510 genModbits (operand * left,
5517 D (emitcode (";", "genModbits"));
5521 /* the result must be bit */
5522 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5523 l = aopGet (left, 0, FALSE, FALSE);
5527 emitcode ("div", "ab");
5528 emitcode ("mov", "a,b");
5529 emitcode ("rrc", "a");
5533 aopPut (result, "c", 0);
5536 /*-----------------------------------------------------------------*/
5537 /* genModOneByte : 8 bit modulus */
5538 /*-----------------------------------------------------------------*/
5540 genModOneByte (operand * left,
5544 bool lUnsigned, rUnsigned, pushedB;
5545 bool runtimeSign, compiletimeSign;
5549 D (emitcode (";", "genModOneByte"));
5551 size = AOP_SIZE (result) - 1;
5553 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5554 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5556 /* if right is a literal, check it for 2^n */
5557 if (AOP_TYPE(right) == AOP_LIT)
5559 unsigned char val = abs((int) operandLitValue(right));
5560 symbol *lbl2 = NULL;
5564 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5574 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5575 /* because iCode should have been changed to genAnd */
5576 /* see file "SDCCopt.c", function "convertToFcall()" */
5578 MOVA (aopGet (left, 0, FALSE, FALSE));
5579 emitcode ("mov", "c,acc.7");
5580 emitcode ("anl", "a,#0x%02x", val - 1);
5581 lbl = newiTempLabel (NULL);
5582 emitcode ("jz", "%05d$", (lbl->key + 100));
5583 emitcode ("jnc", "%05d$", (lbl->key + 100));
5584 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5590 aopPut (result, "a", 0);
5592 aopPut (result, "#0xff", offs2++);
5593 lbl2 = newiTempLabel (NULL);
5594 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5597 aopPut (result, "a", 0);
5599 aopPut (result, zero, offset++);
5613 /* signed or unsigned */
5614 if (lUnsigned && rUnsigned)
5616 /* unsigned is easy */
5617 MOVB (aopGet (right, 0, FALSE, FALSE));
5618 MOVA (aopGet (left, 0, FALSE, FALSE));
5619 emitcode ("div", "ab");
5620 aopPut (result, "b", 0);
5622 aopPut (result, zero, offset++);
5628 /* signed is a little bit more difficult */
5630 /* now sign adjust for both left & right */
5632 /* modulus: sign of the right operand has no influence on the result! */
5633 if (AOP_TYPE(right) == AOP_LIT)
5635 signed char val = (char) operandLitValue(right);
5637 if (!rUnsigned && val < 0)
5638 emitcode ("mov", "b,#0x%02x", -val);
5640 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5642 else /* not literal */
5645 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5648 MOVA (aopGet (right, 0, FALSE, FALSE));
5649 lbl = newiTempLabel (NULL);
5650 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5651 emitcode ("cpl", "a"); /* 2's complement */
5652 emitcode ("inc", "a");
5654 emitcode ("mov", "b,a");
5658 /* let's see what's needed: */
5659 /* apply negative sign during runtime */
5660 runtimeSign = FALSE;
5661 /* negative sign from literals */
5662 compiletimeSign = FALSE;
5664 /* sign adjust left side */
5665 if (AOP_TYPE(left) == AOP_LIT)
5667 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5669 if (!lUnsigned && val < 0)
5671 compiletimeSign = TRUE; /* set sign flag */
5672 emitcode ("mov", "a,#0x%02x", -val);
5675 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5677 else /* ! literal */
5679 MOVA (aopGet (left, 0, FALSE, FALSE));
5684 emitcode ("clr", "F0"); /* clear sign flag */
5686 lbl = newiTempLabel (NULL);
5687 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5688 emitcode ("setb", "F0"); /* set sign flag */
5689 emitcode ("cpl", "a"); /* 2's complement */
5690 emitcode ("inc", "a");
5695 /* now the modulus */
5696 emitcode ("div", "ab");
5698 if (runtimeSign || compiletimeSign)
5700 emitcode ("mov", "a,b");
5701 lbl = newiTempLabel (NULL);
5703 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5704 emitcode ("cpl", "a"); /* 2's complement */
5705 emitcode ("inc", "a");
5708 aopPut (result, "a", 0);
5711 /* msb is 0x00 or 0xff depending on the sign */
5714 emitcode ("mov", "c,F0");
5715 emitcode ("subb", "a,acc");
5717 aopPut (result, "a", offset++);
5719 else /* compiletimeSign */
5721 aopPut (result, "#0xff", offset++);
5726 aopPut (result, "b", 0);
5728 aopPut (result, zero, offset++);
5734 /*-----------------------------------------------------------------*/
5735 /* genMod - generates code for division */
5736 /*-----------------------------------------------------------------*/
5740 operand *left = IC_LEFT (ic);
5741 operand *right = IC_RIGHT (ic);
5742 operand *result = IC_RESULT (ic);
5744 D (emitcode (";", "genMod"));
5746 /* assign the asmops */
5747 aopOp (left, ic, FALSE);
5748 aopOp (right, ic, FALSE);
5749 aopOp (result, ic, TRUE);
5751 /* special cases first */
5753 if (AOP_TYPE (left) == AOP_CRY &&
5754 AOP_TYPE (right) == AOP_CRY)
5756 genModbits (left, right, result);
5760 /* if both are of size == 1 */
5761 if (AOP_SIZE (left) == 1 &&
5762 AOP_SIZE (right) == 1)
5764 genModOneByte (left, right, result);
5768 /* should have been converted to function call */
5772 freeAsmop (result, NULL, ic, TRUE);
5773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777 /*-----------------------------------------------------------------*/
5778 /* genIfxJump :- will create a jump depending on the ifx */
5779 /*-----------------------------------------------------------------*/
5781 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5784 symbol *tlbl = newiTempLabel (NULL);
5787 D (emitcode (";", "genIfxJump"));
5789 /* if true label then we jump if condition
5793 jlbl = IC_TRUE (ic);
5794 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5795 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5799 /* false label is present */
5800 jlbl = IC_FALSE (ic);
5801 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5802 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5804 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5805 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5807 emitcode (inst, "%05d$", tlbl->key + 100);
5808 freeForBranchAsmop (result);
5809 freeForBranchAsmop (right);
5810 freeForBranchAsmop (left);
5811 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5814 /* mark the icode as generated */
5818 /*-----------------------------------------------------------------*/
5819 /* genCmp :- greater or less than comparison */
5820 /*-----------------------------------------------------------------*/
5822 genCmp (operand * left, operand * right,
5823 operand * result, iCode * ifx, int sign, iCode *ic)
5825 int size, offset = 0;
5826 unsigned long lit = 0L;
5829 D (emitcode (";", "genCmp"));
5831 /* if left & right are bit variables */
5832 if (AOP_TYPE (left) == AOP_CRY &&
5833 AOP_TYPE (right) == AOP_CRY)
5835 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5836 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5840 /* subtract right from left if at the
5841 end the carry flag is set then we know that
5842 left is greater than right */
5843 size = max (AOP_SIZE (left), AOP_SIZE (right));
5845 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5846 if ((size == 1) && !sign &&
5847 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5849 symbol *lbl = newiTempLabel (NULL);
5850 emitcode ("cjne", "%s,%s,%05d$",
5851 aopGet (left, offset, FALSE, FALSE),
5852 aopGet (right, offset, FALSE, FALSE),
5858 if (AOP_TYPE (right) == AOP_LIT)
5860 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5861 /* optimize if(x < 0) or if(x >= 0) */
5870 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5871 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5873 genIfxJump (ifx, "acc.7", left, right, result);
5874 freeAsmop (right, NULL, ic, TRUE);
5875 freeAsmop (left, NULL, ic, TRUE);
5881 emitcode ("rlc", "a");
5888 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5889 while (size && (bytelit == 0))
5892 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5898 MOVA (aopGet (left, offset, FALSE, FALSE));
5899 if (sign && size == 0)
5901 emitcode ("xrl", "a,#0x80");
5902 emitcode ("subb", "a,#0x%02x",
5903 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5907 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5917 bool pushedB = FALSE;
5918 rightInB = aopGetUsesAcc(right, offset);
5922 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5924 MOVA (aopGet (left, offset, FALSE, FALSE));
5925 if (sign && size == 0)
5927 emitcode ("xrl", "a,#0x80");
5932 MOVB (aopGet (right, offset, FALSE, FALSE));
5934 emitcode ("xrl", "b,#0x80");
5935 emitcode ("subb", "a,b");
5940 emitcode ("subb", "a,b");
5942 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5954 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5960 /* if the result is used in the next
5961 ifx conditional branch then generate
5962 code a little differently */
5965 genIfxJump (ifx, "c", NULL, NULL, result);
5971 /* leave the result in acc */
5975 /*-----------------------------------------------------------------*/
5976 /* genCmpGt :- greater than comparison */
5977 /*-----------------------------------------------------------------*/
5979 genCmpGt (iCode * ic, iCode * ifx)
5981 operand *left, *right, *result;
5982 sym_link *letype, *retype;
5985 D (emitcode (";", "genCmpGt"));
5987 left = IC_LEFT (ic);
5988 right = IC_RIGHT (ic);
5989 result = IC_RESULT (ic);
5991 letype = getSpec (operandType (left));
5992 retype = getSpec (operandType (right));
5993 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5994 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5995 /* assign the asmops */
5996 aopOp (result, ic, TRUE);
5997 aopOp (left, ic, FALSE);
5998 aopOp (right, ic, FALSE);
6000 genCmp (right, left, result, ifx, sign, ic);
6002 freeAsmop (result, NULL, ic, TRUE);
6005 /*-----------------------------------------------------------------*/
6006 /* genCmpLt - less than comparisons */
6007 /*-----------------------------------------------------------------*/
6009 genCmpLt (iCode * ic, iCode * ifx)
6011 operand *left, *right, *result;
6012 sym_link *letype, *retype;
6015 D (emitcode (";", "genCmpLt"));
6017 left = IC_LEFT (ic);
6018 right = IC_RIGHT (ic);
6019 result = IC_RESULT (ic);
6021 letype = getSpec (operandType (left));
6022 retype = getSpec (operandType (right));
6023 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6024 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6025 /* assign the asmops */
6026 aopOp (result, ic, TRUE);
6027 aopOp (left, ic, FALSE);
6028 aopOp (right, ic, FALSE);
6030 genCmp (left, right, result, ifx, sign, ic);
6032 freeAsmop (result, NULL, ic, TRUE);
6035 /*-----------------------------------------------------------------*/
6036 /* gencjneshort - compare and jump if not equal */
6037 /*-----------------------------------------------------------------*/
6039 gencjneshort (operand * left, operand * right, symbol * lbl)
6041 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6043 unsigned long lit = 0L;
6045 D (emitcode (";", "gencjneshort"));
6047 /* if the left side is a literal or
6048 if the right is in a pointer register and left
6050 if ((AOP_TYPE (left) == AOP_LIT) ||
6051 (AOP_TYPE (left) == AOP_IMMD) ||
6052 (AOP_TYPE (left) == AOP_DIR) ||
6053 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6060 if (AOP_TYPE (right) == AOP_LIT)
6061 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6063 /* if the right side is a literal then anything goes */
6064 if (AOP_TYPE (right) == AOP_LIT &&
6065 AOP_TYPE (left) != AOP_DIR &&
6066 AOP_TYPE (left) != AOP_IMMD)
6070 emitcode ("cjne", "%s,%s,%05d$",
6071 aopGet (left, offset, FALSE, FALSE),
6072 aopGet (right, offset, FALSE, FALSE),
6078 /* if the right side is in a register or in direct space or
6079 if the left is a pointer register & right is not */
6080 else if (AOP_TYPE (right) == AOP_REG ||
6081 AOP_TYPE (right) == AOP_DIR ||
6082 AOP_TYPE (right) == AOP_LIT ||
6083 AOP_TYPE (right) == AOP_IMMD ||
6084 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6085 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6089 MOVA (aopGet (left, offset, FALSE, FALSE));
6090 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6091 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6092 emitcode ("jnz", "%05d$", lbl->key + 100);
6094 emitcode ("cjne", "a,%s,%05d$",
6095 aopGet (right, offset, FALSE, TRUE),
6102 /* right is a pointer reg need both a & b */
6105 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6106 wassertl(!BINUSE, "B was in use");
6107 MOVB (aopGet (left, offset, FALSE, FALSE));
6108 MOVA (aopGet (right, offset, FALSE, FALSE));
6109 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6115 /*-----------------------------------------------------------------*/
6116 /* gencjne - compare and jump if not equal */
6117 /*-----------------------------------------------------------------*/
6119 gencjne (operand * left, operand * right, symbol * lbl)
6121 symbol *tlbl = newiTempLabel (NULL);
6123 D (emitcode (";", "gencjne"));
6125 gencjneshort (left, right, lbl);
6127 emitcode ("mov", "a,%s", one);
6128 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6130 emitcode ("clr", "a");
6134 /*-----------------------------------------------------------------*/
6135 /* genCmpEq - generates code for equal to */
6136 /*-----------------------------------------------------------------*/
6138 genCmpEq (iCode * ic, iCode * ifx)
6140 bool swappedLR = FALSE;
6141 operand *left, *right, *result;
6143 D (emitcode (";", "genCmpEq"));
6145 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6146 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6147 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6149 /* if literal, literal on the right or
6150 if the right is in a pointer register and left
6152 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6153 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6155 operand *t = IC_RIGHT (ic);
6156 IC_RIGHT (ic) = IC_LEFT (ic);
6161 if (ifx && !AOP_SIZE (result))
6164 /* if they are both bit variables */
6165 if (AOP_TYPE (left) == AOP_CRY &&
6166 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6168 if (AOP_TYPE (right) == AOP_LIT)
6170 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6173 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6174 emitcode ("cpl", "c");
6178 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6182 emitcode ("clr", "c");
6184 /* AOP_TYPE(right) == AOP_CRY */
6188 symbol *lbl = newiTempLabel (NULL);
6189 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6190 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6191 emitcode ("cpl", "c");
6194 /* if true label then we jump if condition
6196 tlbl = newiTempLabel (NULL);
6199 emitcode ("jnc", "%05d$", tlbl->key + 100);
6200 freeForBranchAsmop (result);
6201 freeForBranchAsmop (right);
6202 freeForBranchAsmop (left);
6203 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6207 emitcode ("jc", "%05d$", tlbl->key + 100);
6208 freeForBranchAsmop (result);
6209 freeForBranchAsmop (right);
6210 freeForBranchAsmop (left);
6211 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6217 tlbl = newiTempLabel (NULL);
6218 gencjneshort (left, right, tlbl);
6221 freeForBranchAsmop (result);
6222 freeForBranchAsmop (right);
6223 freeForBranchAsmop (left);
6224 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6229 symbol *lbl = newiTempLabel (NULL);
6230 emitcode ("sjmp", "%05d$", lbl->key + 100);
6232 freeForBranchAsmop (result);
6233 freeForBranchAsmop (right);
6234 freeForBranchAsmop (left);
6235 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6239 /* mark the icode as generated */
6244 /* if they are both bit variables */
6245 if (AOP_TYPE (left) == AOP_CRY &&
6246 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6248 if (AOP_TYPE (right) == AOP_LIT)
6250 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6253 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6254 emitcode ("cpl", "c");
6258 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6262 emitcode ("clr", "c");
6264 /* AOP_TYPE(right) == AOP_CRY */
6268 symbol *lbl = newiTempLabel (NULL);
6269 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6270 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6271 emitcode ("cpl", "c");
6275 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6282 genIfxJump (ifx, "c", left, right, result);
6285 /* if the result is used in an arithmetic operation
6286 then put the result in place */
6291 gencjne (left, right, newiTempLabel (NULL));
6292 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6294 aopPut (result, "a", 0);
6299 genIfxJump (ifx, "a", left, right, result);
6302 /* if the result is used in an arithmetic operation
6303 then put the result in place */
6304 if (AOP_TYPE (result) != AOP_CRY)
6306 /* leave the result in acc */
6310 freeAsmop (result, NULL, ic, TRUE);
6313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323 /*-----------------------------------------------------------------*/
6324 /* ifxForOp - returns the icode containing the ifx for operand */
6325 /*-----------------------------------------------------------------*/
6327 ifxForOp (operand * op, iCode * ic)
6329 /* if true symbol then needs to be assigned */
6330 if (IS_TRUE_SYMOP (op))
6333 /* if this has register type condition and
6334 the next instruction is ifx with the same operand
6335 and live to of the operand is upto the ifx only then */
6337 ic->next->op == IFX &&
6338 IC_COND (ic->next)->key == op->key &&
6339 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6345 /*-----------------------------------------------------------------*/
6346 /* hasInc - operand is incremented before any other use */
6347 /*-----------------------------------------------------------------*/
6349 hasInc (operand *op, iCode *ic, int osize)
6351 sym_link *type = operandType(op);
6352 sym_link *retype = getSpec (type);
6353 iCode *lic = ic->next;
6356 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6357 if (!IS_SYMOP(op)) return NULL;
6359 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6360 if (IS_AGGREGATE(type->next)) return NULL;
6361 if (osize != (isize = getSize(type->next))) return NULL;
6364 /* if operand of the form op = op + <sizeof *op> */
6365 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6366 isOperandEqual(IC_RESULT(lic),op) &&
6367 isOperandLiteral(IC_RIGHT(lic)) &&
6368 operandLitValue(IC_RIGHT(lic)) == isize) {
6371 /* if the operand used or deffed */
6372 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6375 /* if GOTO or IFX */
6376 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6382 /*-----------------------------------------------------------------*/
6383 /* genAndOp - for && operation */
6384 /*-----------------------------------------------------------------*/
6386 genAndOp (iCode * ic)
6388 operand *left, *right, *result;
6391 D (emitcode (";", "genAndOp"));
6393 /* note here that && operations that are in an
6394 if statement are taken away by backPatchLabels
6395 only those used in arthmetic operations remain */
6396 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6397 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6398 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6400 /* if both are bit variables */
6401 if (AOP_TYPE (left) == AOP_CRY &&
6402 AOP_TYPE (right) == AOP_CRY)
6404 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6405 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6410 tlbl = newiTempLabel (NULL);
6412 emitcode ("jz", "%05d$", tlbl->key + 100);
6418 freeAsmop (result, NULL, ic, TRUE);
6419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 /*-----------------------------------------------------------------*/
6425 /* genOrOp - for || operation */
6426 /*-----------------------------------------------------------------*/
6428 genOrOp (iCode * ic)
6430 operand *left, *right, *result;
6433 D (emitcode (";", "genOrOp"));
6435 /* note here that || operations that are in an
6436 if statement are taken away by backPatchLabels
6437 only those used in arthmetic operations remain */
6438 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6439 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6440 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6442 /* if both are bit variables */
6443 if (AOP_TYPE (left) == AOP_CRY &&
6444 AOP_TYPE (right) == AOP_CRY)
6446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6447 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6452 tlbl = newiTempLabel (NULL);
6454 emitcode ("jnz", "%05d$", tlbl->key + 100);
6460 freeAsmop (result, NULL, ic, TRUE);
6461 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6465 /*-----------------------------------------------------------------*/
6466 /* isLiteralBit - test if lit == 2^n */
6467 /*-----------------------------------------------------------------*/
6469 isLiteralBit (unsigned long lit)
6471 unsigned long pw[32] =
6472 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6473 0x100L, 0x200L, 0x400L, 0x800L,
6474 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6475 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6476 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6477 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6478 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6481 for (idx = 0; idx < 32; idx++)
6487 /*-----------------------------------------------------------------*/
6488 /* continueIfTrue - */
6489 /*-----------------------------------------------------------------*/
6491 continueIfTrue (iCode * ic)
6494 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6498 /*-----------------------------------------------------------------*/
6500 /*-----------------------------------------------------------------*/
6502 jumpIfTrue (iCode * ic)
6505 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6509 /*-----------------------------------------------------------------*/
6510 /* jmpTrueOrFalse - */
6511 /*-----------------------------------------------------------------*/
6513 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6515 // ugly but optimized by peephole
6518 symbol *nlbl = newiTempLabel (NULL);
6519 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6521 freeForBranchAsmop (result);
6522 freeForBranchAsmop (right);
6523 freeForBranchAsmop (left);
6524 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6529 freeForBranchAsmop (result);
6530 freeForBranchAsmop (right);
6531 freeForBranchAsmop (left);
6532 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6538 /*-----------------------------------------------------------------*/
6539 /* genAnd - code for and */
6540 /*-----------------------------------------------------------------*/
6542 genAnd (iCode * ic, iCode * ifx)
6544 operand *left, *right, *result;
6545 int size, offset = 0;
6546 unsigned long lit = 0L;
6550 D (emitcode (";", "genAnd"));
6552 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6553 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6554 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6557 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6559 AOP_TYPE (left), AOP_TYPE (right));
6560 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6562 AOP_SIZE (left), AOP_SIZE (right));
6565 /* if left is a literal & right is not then exchange them */
6566 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6567 AOP_NEEDSACC (left))
6569 operand *tmp = right;
6574 /* if result = right then exchange left and right */
6575 if (sameRegs (AOP (result), AOP (right)))
6577 operand *tmp = right;
6582 /* if right is bit then exchange them */
6583 if (AOP_TYPE (right) == AOP_CRY &&
6584 AOP_TYPE (left) != AOP_CRY)
6586 operand *tmp = right;
6590 if (AOP_TYPE (right) == AOP_LIT)
6591 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6593 size = AOP_SIZE (result);
6596 // result = bit & yy;
6597 if (AOP_TYPE (left) == AOP_CRY)
6599 // c = bit & literal;
6600 if (AOP_TYPE (right) == AOP_LIT)
6604 if (size && sameRegs (AOP (result), AOP (left)))
6607 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6612 if (size && (AOP_TYPE (result) == AOP_CRY))
6614 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6617 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6622 emitcode ("clr", "c");
6627 if (AOP_TYPE (right) == AOP_CRY)
6630 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6631 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6636 MOVA (aopGet (right, 0, FALSE, FALSE));
6638 emitcode ("rrc", "a");
6639 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6647 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6648 genIfxJump (ifx, "c", left, right, result);
6652 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6653 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6654 if ((AOP_TYPE (right) == AOP_LIT) &&
6655 (AOP_TYPE (result) == AOP_CRY) &&
6656 (AOP_TYPE (left) != AOP_CRY))
6658 int posbit = isLiteralBit (lit);
6663 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6667 switch (posbit & 0x07)
6669 case 0: emitcode ("rrc", "a");
6671 case 7: emitcode ("rlc", "a");
6673 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6682 SNPRINTF (buffer, sizeof(buffer),
6683 "acc.%d", posbit & 0x07);
6684 genIfxJump (ifx, buffer, left, right, result);
6687 {// what is this case? just found it in ds390/gen.c
6688 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6695 symbol *tlbl = newiTempLabel (NULL);
6696 int sizel = AOP_SIZE (left);
6698 emitcode ("setb", "c");
6701 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6703 MOVA (aopGet (left, offset, FALSE, FALSE));
6705 if ((posbit = isLiteralBit (bytelit)) != 0)
6706 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6709 if (bytelit != 0x0FFL)
6710 emitcode ("anl", "a,%s",
6711 aopGet (right, offset, FALSE, TRUE));
6712 emitcode ("jnz", "%05d$", tlbl->key + 100);
6717 // bit = left & literal
6720 emitcode ("clr", "c");
6723 // if(left & literal)
6727 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6737 /* if left is same as result */
6738 if (sameRegs (AOP (result), AOP (left)))
6740 for (; size--; offset++)
6742 if (AOP_TYPE (right) == AOP_LIT)
6744 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6745 if (bytelit == 0x0FF)
6747 /* dummy read of volatile operand */
6748 if (isOperandVolatile (left, FALSE))
6749 MOVA (aopGet (left, offset, FALSE, FALSE));
6753 else if (bytelit == 0)
6755 aopPut (result, zero, offset);
6757 else if (IS_AOP_PREG (result))
6759 MOVA (aopGet (left, offset, FALSE, TRUE));
6760 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6761 aopPut (result, "a", offset);
6764 emitcode ("anl", "%s,%s",
6765 aopGet (left, offset, FALSE, TRUE),
6766 aopGet (right, offset, FALSE, FALSE));
6770 if (AOP_TYPE (left) == AOP_ACC)
6773 emitcode("mov", "a,b");
6774 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6776 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6778 MOVB (aopGet (left, offset, FALSE, FALSE));
6779 MOVA (aopGet (right, offset, FALSE, FALSE));
6780 emitcode ("anl", "a,b");
6781 aopPut (result, "a", offset);
6783 else if (aopGetUsesAcc (left, offset))
6785 MOVA (aopGet (left, offset, FALSE, FALSE));
6786 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6787 aopPut (result, "a", offset);
6791 MOVA (aopGet (right, offset, FALSE, FALSE));
6792 if (IS_AOP_PREG (result))
6794 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6795 aopPut (result, "a", offset);
6798 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6805 // left & result in different registers
6806 if (AOP_TYPE (result) == AOP_CRY)
6809 // if(size), result in bit
6810 // if(!size && ifx), conditional oper: if(left & right)
6811 symbol *tlbl = newiTempLabel (NULL);
6812 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6814 emitcode ("setb", "c");
6817 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6818 && AOP_TYPE(left)==AOP_ACC)
6821 emitcode("mov", "a,b");
6822 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6824 else if (AOP_TYPE(left)==AOP_ACC)
6828 bool pushedB = pushB ();
6829 emitcode("mov", "b,a");
6830 MOVA (aopGet (right, offset, FALSE, FALSE));
6831 emitcode("anl", "a,b");
6836 MOVA (aopGet (right, offset, FALSE, FALSE));
6837 emitcode("anl", "a,b");
6840 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6842 MOVB (aopGet (left, offset, FALSE, FALSE));
6843 MOVA (aopGet (right, offset, FALSE, FALSE));
6844 emitcode ("anl", "a,b");
6846 else if (aopGetUsesAcc (left, offset))
6848 MOVA (aopGet (left, offset, FALSE, FALSE));
6849 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6853 MOVA (aopGet (right, offset, FALSE, FALSE));
6854 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6857 emitcode ("jnz", "%05d$", tlbl->key + 100);
6867 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6873 for (; (size--); offset++)
6876 // result = left & right
6877 if (AOP_TYPE (right) == AOP_LIT)
6879 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6880 if (bytelit == 0x0FF)
6883 aopGet (left, offset, FALSE, FALSE),
6887 else if (bytelit == 0)
6889 /* dummy read of volatile operand */
6890 if (isOperandVolatile (left, FALSE))
6891 MOVA (aopGet (left, offset, FALSE, FALSE));
6892 aopPut (result, zero, offset);
6895 else if (AOP_TYPE (left) == AOP_ACC)
6899 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6900 aopPut (result, "a", offset);
6905 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6906 aopPut (result, "b", offset);
6911 // faster than result <- left, anl result,right
6912 // and better if result is SFR
6913 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6914 && AOP_TYPE(left)==AOP_ACC)
6917 emitcode("mov", "a,b");
6918 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6920 else if (AOP_TYPE(left)==AOP_ACC)
6924 bool pushedB = pushB ();
6925 emitcode("mov", "b,a");
6926 MOVA (aopGet (right, offset, FALSE, FALSE));
6927 emitcode("anl", "a,b");
6932 MOVA (aopGet (right, offset, FALSE, FALSE));
6933 emitcode("anl", "a,b");
6936 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6938 MOVB (aopGet (left, offset, FALSE, FALSE));
6939 MOVA (aopGet (right, offset, FALSE, FALSE));
6940 emitcode ("anl", "a,b");
6942 else if (aopGetUsesAcc (left, offset))
6944 MOVA (aopGet (left, offset, FALSE, FALSE));
6945 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6949 MOVA (aopGet (right, offset, FALSE, FALSE));
6950 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6952 aopPut (result, "a", offset);
6958 freeAsmop (result, NULL, ic, TRUE);
6959 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6960 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6963 /*-----------------------------------------------------------------*/
6964 /* genOr - code for or */
6965 /*-----------------------------------------------------------------*/
6967 genOr (iCode * ic, iCode * ifx)
6969 operand *left, *right, *result;
6970 int size, offset = 0;
6971 unsigned long lit = 0L;
6974 D (emitcode (";", "genOr"));
6976 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6977 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6978 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6981 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6983 AOP_TYPE (left), AOP_TYPE (right));
6984 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6986 AOP_SIZE (left), AOP_SIZE (right));
6989 /* if left is a literal & right is not then exchange them */
6990 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6991 AOP_NEEDSACC (left))
6993 operand *tmp = right;
6998 /* if result = right then exchange them */
6999 if (sameRegs (AOP (result), AOP (right)))
7001 operand *tmp = right;
7006 /* if right is bit then exchange them */
7007 if (AOP_TYPE (right) == AOP_CRY &&
7008 AOP_TYPE (left) != AOP_CRY)
7010 operand *tmp = right;
7014 if (AOP_TYPE (right) == AOP_LIT)
7015 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7017 size = AOP_SIZE (result);
7021 if (AOP_TYPE (left) == AOP_CRY)
7023 if (AOP_TYPE (right) == AOP_LIT)
7025 // c = bit | literal;
7028 // lit != 0 => result = 1
7029 if (AOP_TYPE (result) == AOP_CRY)
7032 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7034 continueIfTrue (ifx);
7037 emitcode ("setb", "c");
7041 // lit == 0 => result = left
7042 if (size && sameRegs (AOP (result), AOP (left)))
7044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7049 if (AOP_TYPE (right) == AOP_CRY)
7052 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7053 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7058 symbol *tlbl = newiTempLabel (NULL);
7059 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7060 emitcode ("setb", "c");
7061 emitcode ("jb", "%s,%05d$",
7062 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7064 emitcode ("jnz", "%05d$", tlbl->key + 100);
7065 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7067 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7082 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7083 genIfxJump (ifx, "c", left, right, result);
7087 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7088 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7089 if ((AOP_TYPE (right) == AOP_LIT) &&
7090 (AOP_TYPE (result) == AOP_CRY) &&
7091 (AOP_TYPE (left) != AOP_CRY))
7097 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7099 continueIfTrue (ifx);
7104 // lit = 0, result = boolean(left)
7106 emitcode ("setb", "c");
7110 symbol *tlbl = newiTempLabel (NULL);
7111 emitcode ("jnz", "%05d$", tlbl->key + 100);
7117 genIfxJump (ifx, "a", left, right, result);
7125 /* if left is same as result */
7126 if (sameRegs (AOP (result), AOP (left)))
7128 for (; size--; offset++)
7130 if (AOP_TYPE (right) == AOP_LIT)
7132 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7135 /* dummy read of volatile operand */
7136 if (isOperandVolatile (left, FALSE))
7137 MOVA (aopGet (left, offset, FALSE, FALSE));
7141 else if (bytelit == 0x0FF)
7143 aopPut (result, "#0xFF", offset);
7145 else if (IS_AOP_PREG (left))
7147 MOVA (aopGet (left, offset, FALSE, TRUE));
7148 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7149 aopPut (result, "a", offset);
7153 emitcode ("orl", "%s,%s",
7154 aopGet (left, offset, FALSE, TRUE),
7155 aopGet (right, offset, FALSE, FALSE));
7160 if (AOP_TYPE (left) == AOP_ACC)
7163 emitcode("mov", "a,b");
7164 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7166 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7168 MOVB (aopGet (left, offset, FALSE, FALSE));
7169 MOVA (aopGet (right, offset, FALSE, FALSE));
7170 emitcode ("orl", "a,b");
7171 aopPut (result, "a", offset);
7173 else if (aopGetUsesAcc (left, offset))
7175 MOVA (aopGet (left, offset, FALSE, FALSE));
7176 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7177 aopPut (result, "a", offset);
7181 MOVA (aopGet (right, offset, FALSE, FALSE));
7182 if (IS_AOP_PREG (left))
7184 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7185 aopPut (result, "a", offset);
7189 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7197 // left & result in different registers
7198 if (AOP_TYPE (result) == AOP_CRY)
7201 // if(size), result in bit
7202 // if(!size && ifx), conditional oper: if(left | right)
7203 symbol *tlbl = newiTempLabel (NULL);
7204 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7206 emitcode ("setb", "c");
7209 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7210 && AOP_TYPE(left)==AOP_ACC)
7213 emitcode("mov", "a,b");
7214 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7216 else if (AOP_TYPE(left)==AOP_ACC)
7220 bool pushedB = pushB ();
7221 emitcode("mov", "b,a");
7222 MOVA (aopGet (right, offset, FALSE, FALSE));
7223 emitcode("orl", "a,b");
7228 MOVA (aopGet (right, offset, FALSE, FALSE));
7229 emitcode("orl", "a,b");
7232 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7234 MOVB (aopGet (left, offset, FALSE, FALSE));
7235 MOVA (aopGet (right, offset, FALSE, FALSE));
7236 emitcode ("orl", "a,b");
7238 else if (aopGetUsesAcc (left, offset))
7240 MOVA (aopGet (left, offset, FALSE, FALSE));
7241 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7245 MOVA (aopGet (right, offset, FALSE, FALSE));
7246 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7249 emitcode ("jnz", "%05d$", tlbl->key + 100);
7259 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7265 for (; (size--); offset++)
7268 // result = left | right
7269 if (AOP_TYPE (right) == AOP_LIT)
7271 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7275 aopGet (left, offset, FALSE, FALSE),
7279 else if (bytelit == 0x0FF)
7281 /* dummy read of volatile operand */
7282 if (isOperandVolatile (left, FALSE))
7283 MOVA (aopGet (left, offset, FALSE, FALSE));
7284 aopPut (result, "#0xFF", offset);
7288 // faster than result <- left, orl result,right
7289 // and better if result is SFR
7290 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7291 && AOP_TYPE(left)==AOP_ACC)
7294 emitcode("mov", "a,b");
7295 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7297 else if (AOP_TYPE(left)==AOP_ACC)
7301 bool pushedB = pushB ();
7302 emitcode("mov", "b,a");
7303 MOVA (aopGet (right, offset, FALSE, FALSE));
7304 emitcode("orl", "a,b");
7309 MOVA (aopGet (right, offset, FALSE, FALSE));
7310 emitcode("orl", "a,b");
7313 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7315 MOVB (aopGet (left, offset, FALSE, FALSE));
7316 MOVA (aopGet (right, offset, FALSE, FALSE));
7317 emitcode ("orl", "a,b");
7319 else if (aopGetUsesAcc (left, offset))
7321 MOVA (aopGet (left, offset, FALSE, FALSE));
7322 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7326 MOVA (aopGet (right, offset, FALSE, FALSE));
7327 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7329 aopPut (result, "a", offset);
7335 freeAsmop (result, NULL, ic, TRUE);
7336 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7337 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7340 /*-----------------------------------------------------------------*/
7341 /* genXor - code for xclusive or */
7342 /*-----------------------------------------------------------------*/
7344 genXor (iCode * ic, iCode * ifx)
7346 operand *left, *right, *result;
7347 int size, offset = 0;
7348 unsigned long lit = 0L;
7351 D (emitcode (";", "genXor"));
7353 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7354 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7355 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7358 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7360 AOP_TYPE (left), AOP_TYPE (right));
7361 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7363 AOP_SIZE (left), AOP_SIZE (right));
7366 /* if left is a literal & right is not ||
7367 if left needs acc & right does not */
7368 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7369 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7371 operand *tmp = right;
7376 /* if result = right then exchange them */
7377 if (sameRegs (AOP (result), AOP (right)))
7379 operand *tmp = right;
7384 /* if right is bit then exchange them */
7385 if (AOP_TYPE (right) == AOP_CRY &&
7386 AOP_TYPE (left) != AOP_CRY)
7388 operand *tmp = right;
7393 if (AOP_TYPE (right) == AOP_LIT)
7394 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7396 size = AOP_SIZE (result);
7400 if (AOP_TYPE (left) == AOP_CRY)
7402 if (AOP_TYPE (right) == AOP_LIT)
7404 // c = bit & literal;
7407 // lit>>1 != 0 => result = 1
7408 if (AOP_TYPE (result) == AOP_CRY)
7411 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7413 continueIfTrue (ifx);
7416 emitcode ("setb", "c");
7423 // lit == 0, result = left
7424 if (size && sameRegs (AOP (result), AOP (left)))
7426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7430 // lit == 1, result = not(left)
7431 if (size && sameRegs (AOP (result), AOP (left)))
7433 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7438 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7439 emitcode ("cpl", "c");
7447 symbol *tlbl = newiTempLabel (NULL);
7448 if (AOP_TYPE (right) == AOP_CRY)
7451 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7458 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7459 emitcode ("cpl", "c");
7467 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7468 genIfxJump (ifx, "c", left, right, result);
7472 /* if left is same as result */
7473 if (sameRegs (AOP (result), AOP (left)))
7475 for (; size--; offset++)
7477 if (AOP_TYPE (right) == AOP_LIT)
7479 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7482 /* dummy read of volatile operand */
7483 if (isOperandVolatile (left, FALSE))
7484 MOVA (aopGet (left, offset, FALSE, FALSE));
7488 else if (IS_AOP_PREG (left))
7490 MOVA (aopGet (left, offset, FALSE, TRUE));
7491 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7492 aopPut (result, "a", offset);
7496 emitcode ("xrl", "%s,%s",
7497 aopGet (left, offset, FALSE, TRUE),
7498 aopGet (right, offset, FALSE, FALSE));
7503 if (AOP_TYPE (left) == AOP_ACC)
7506 emitcode("mov", "a,b");
7507 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7509 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7511 MOVB (aopGet (left, offset, FALSE, FALSE));
7512 MOVA (aopGet (right, offset, FALSE, FALSE));
7513 emitcode ("xrl", "a,b");
7514 aopPut (result, "a", offset);
7516 else if (aopGetUsesAcc (left, offset))
7518 MOVA (aopGet (left, offset, FALSE, FALSE));
7519 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7520 aopPut (result, "a", offset);
7524 MOVA (aopGet (right, offset, FALSE, FALSE));
7525 if (IS_AOP_PREG (left))
7527 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7528 aopPut (result, "a", offset);
7531 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7538 // left & result in different registers
7539 if (AOP_TYPE (result) == AOP_CRY)
7542 // if(size), result in bit
7543 // if(!size && ifx), conditional oper: if(left ^ right)
7544 symbol *tlbl = newiTempLabel (NULL);
7545 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7548 emitcode ("setb", "c");
7551 if ((AOP_TYPE (right) == AOP_LIT) &&
7552 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7554 MOVA (aopGet (left, offset, FALSE, FALSE));
7556 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7557 && AOP_TYPE(left)==AOP_ACC)
7560 emitcode("mov", "a,b");
7561 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7563 else if (AOP_TYPE(left)==AOP_ACC)
7567 bool pushedB = pushB ();
7568 emitcode("mov", "b,a");
7569 MOVA (aopGet (right, offset, FALSE, FALSE));
7570 emitcode("xrl", "a,b");
7575 MOVA (aopGet (right, offset, FALSE, FALSE));
7576 emitcode("xrl", "a,b");
7579 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7581 MOVB (aopGet (left, offset, FALSE, FALSE));
7582 MOVA (aopGet (right, offset, FALSE, FALSE));
7583 emitcode ("xrl", "a,b");
7585 else if (aopGetUsesAcc (left, offset))
7587 MOVA (aopGet (left, offset, FALSE, FALSE));
7588 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7592 MOVA (aopGet (right, offset, FALSE, FALSE));
7593 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7596 emitcode ("jnz", "%05d$", tlbl->key + 100);
7606 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7610 for (; (size--); offset++)
7613 // result = left ^ right
7614 if (AOP_TYPE (right) == AOP_LIT)
7616 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7620 aopGet (left, offset, FALSE, FALSE),
7625 // faster than result <- left, xrl result,right
7626 // and better if result is SFR
7627 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7628 && AOP_TYPE(left)==AOP_ACC)
7631 emitcode("mov", "a,b");
7632 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7634 else if (AOP_TYPE(left)==AOP_ACC)
7638 bool pushedB = pushB ();
7639 emitcode("mov", "b,a");
7640 MOVA (aopGet (right, offset, FALSE, FALSE));
7641 emitcode("xrl", "a,b");
7646 MOVA (aopGet (right, offset, FALSE, FALSE));
7647 emitcode("xrl", "a,b");
7650 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7652 MOVB (aopGet (left, offset, FALSE, FALSE));
7653 MOVA (aopGet (right, offset, FALSE, FALSE));
7654 emitcode ("xrl", "a,b");
7656 else if (aopGetUsesAcc (left, offset))
7658 MOVA (aopGet (left, offset, FALSE, FALSE));
7659 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7663 MOVA (aopGet (right, offset, FALSE, FALSE));
7664 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7666 aopPut (result, "a", offset);
7672 freeAsmop (result, NULL, ic, TRUE);
7673 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7674 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7677 /*-----------------------------------------------------------------*/
7678 /* genInline - write the inline code out */
7679 /*-----------------------------------------------------------------*/
7681 genInline (iCode * ic)
7683 char *buffer, *bp, *bp1;
7684 bool inComment = FALSE;
7686 D (emitcode (";", "genInline"));
7688 _G.inLine += (!options.asmpeep);
7690 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7692 /* emit each line as a code */
7710 /* Add \n for labels, not dirs such as c:\mydir */
7711 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7729 _G.inLine -= (!options.asmpeep);
7732 /*-----------------------------------------------------------------*/
7733 /* genRRC - rotate right with carry */
7734 /*-----------------------------------------------------------------*/
7738 operand *left, *result;
7742 D (emitcode (";", "genRRC"));
7744 /* rotate right with carry */
7745 left = IC_LEFT (ic);
7746 result = IC_RESULT (ic);
7747 aopOp (left, ic, FALSE);
7748 aopOp (result, ic, FALSE);
7750 /* move it to the result */
7751 size = AOP_SIZE (result);
7753 if (size == 1) { /* special case for 1 byte */
7754 l = aopGet (left, offset, FALSE, FALSE);
7756 emitcode ("rr", "a");
7759 /* no need to clear carry, bit7 will be written later */
7762 l = aopGet (left, offset, FALSE, FALSE);
7764 emitcode ("rrc", "a");
7765 if (AOP_SIZE (result) > 1)
7766 aopPut (result, "a", offset--);
7768 /* now we need to put the carry into the
7769 highest order byte of the result */
7770 if (AOP_SIZE (result) > 1)
7772 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7775 emitcode ("mov", "acc.7,c");
7777 aopPut (result, "a", AOP_SIZE (result) - 1);
7778 freeAsmop (result, NULL, ic, TRUE);
7779 freeAsmop (left, NULL, ic, TRUE);
7782 /*-----------------------------------------------------------------*/
7783 /* genRLC - generate code for rotate left with carry */
7784 /*-----------------------------------------------------------------*/
7788 operand *left, *result;
7792 D (emitcode (";", "genRLC"));
7794 /* rotate right with carry */
7795 left = IC_LEFT (ic);
7796 result = IC_RESULT (ic);
7797 aopOp (left, ic, FALSE);
7798 aopOp (result, ic, FALSE);
7800 /* move it to the result */
7801 size = AOP_SIZE (result);
7805 l = aopGet (left, offset, FALSE, FALSE);
7807 if (size == 0) { /* special case for 1 byte */
7811 emitcode("rlc","a"); /* bit0 will be written later */
7812 if (AOP_SIZE (result) > 1)
7814 aopPut (result, "a", offset++);
7819 l = aopGet (left, offset, FALSE, FALSE);
7821 emitcode ("rlc", "a");
7822 if (AOP_SIZE (result) > 1)
7823 aopPut (result, "a", offset++);
7826 /* now we need to put the carry into the
7827 highest order byte of the result */
7828 if (AOP_SIZE (result) > 1)
7830 l = aopGet (result, 0, FALSE, FALSE);
7833 emitcode ("mov", "acc.0,c");
7835 aopPut (result, "a", 0);
7836 freeAsmop (result, NULL, ic, TRUE);
7837 freeAsmop (left, NULL, ic, TRUE);
7840 /*-----------------------------------------------------------------*/
7841 /* genGetHbit - generates code get highest order bit */
7842 /*-----------------------------------------------------------------*/
7844 genGetHbit (iCode * ic)
7846 operand *left, *result;
7848 D (emitcode (";", "genGetHbit"));
7850 left = IC_LEFT (ic);
7851 result = IC_RESULT (ic);
7852 aopOp (left, ic, FALSE);
7853 aopOp (result, ic, FALSE);
7855 /* get the highest order byte into a */
7856 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7857 if (AOP_TYPE (result) == AOP_CRY)
7859 emitcode ("rlc", "a");
7864 emitcode ("rl", "a");
7865 emitcode ("anl", "a,#0x01");
7869 freeAsmop (result, NULL, ic, TRUE);
7870 freeAsmop (left, NULL, ic, TRUE);
7873 /*-----------------------------------------------------------------*/
7874 /* genGetAbit - generates code get a single bit */
7875 /*-----------------------------------------------------------------*/
7877 genGetAbit (iCode * ic)
7879 operand *left, *right, *result;
7882 D (emitcode (";", "genGetAbit"));
7884 left = IC_LEFT (ic);
7885 right = IC_RIGHT (ic);
7886 result = IC_RESULT (ic);
7887 aopOp (left, ic, FALSE);
7888 aopOp (right, ic, FALSE);
7889 aopOp (result, ic, FALSE);
7891 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7893 /* get the needed byte into a */
7894 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7896 if (AOP_TYPE (result) == AOP_CRY)
7899 emitcode ("rlc", "a");
7900 else if ((shCount) == 0)
7901 emitcode ("rrc", "a");
7903 emitcode ("mov", "c,acc[%d]", shCount);
7911 emitcode ("rr", "a");
7914 emitcode ("rr", "a");
7917 emitcode ("anl", "a,#0x01");
7921 emitcode ("mov", "c,acc[%d]", shCount);
7922 emitcode ("clr", "a");
7923 emitcode ("rlc", "a");
7926 emitcode ("swap", "a");
7927 emitcode ("anl", "a,#0x01");
7930 emitcode ("rl", "a");
7933 emitcode ("rl", "a");
7934 emitcode ("anl", "a,#0x01");
7940 freeAsmop (result, NULL, ic, TRUE);
7941 freeAsmop (right, NULL, ic, TRUE);
7942 freeAsmop (left, NULL, ic, TRUE);
7945 /*-----------------------------------------------------------------*/
7946 /* genGetByte - generates code get a single byte */
7947 /*-----------------------------------------------------------------*/
7949 genGetByte (iCode * ic)
7951 operand *left, *right, *result;
7954 D (emitcode (";", "genGetByte"));
7956 left = IC_LEFT (ic);
7957 right = IC_RIGHT (ic);
7958 result = IC_RESULT (ic);
7959 aopOp (left, ic, FALSE);
7960 aopOp (right, ic, FALSE);
7961 aopOp (result, ic, FALSE);
7963 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7965 aopGet (left, offset, FALSE, FALSE),
7968 freeAsmop (result, NULL, ic, TRUE);
7969 freeAsmop (right, NULL, ic, TRUE);
7970 freeAsmop (left, NULL, ic, TRUE);
7973 /*-----------------------------------------------------------------*/
7974 /* genGetWord - generates code get two bytes */
7975 /*-----------------------------------------------------------------*/
7977 genGetWord (iCode * ic)
7979 operand *left, *right, *result;
7982 D (emitcode (";", "genGetWord"));
7984 left = IC_LEFT (ic);
7985 right = IC_RIGHT (ic);
7986 result = IC_RESULT (ic);
7987 aopOp (left, ic, FALSE);
7988 aopOp (right, ic, FALSE);
7989 aopOp (result, ic, FALSE);
7991 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7993 aopGet (left, offset, FALSE, FALSE),
7996 aopGet (left, offset+1, FALSE, FALSE),
7999 freeAsmop (result, NULL, ic, TRUE);
8000 freeAsmop (right, NULL, ic, TRUE);
8001 freeAsmop (left, NULL, ic, TRUE);
8004 /*-----------------------------------------------------------------*/
8005 /* genSwap - generates code to swap nibbles or bytes */
8006 /*-----------------------------------------------------------------*/
8008 genSwap (iCode * ic)
8010 operand *left, *result;
8012 D(emitcode (";", "genSwap"));
8014 left = IC_LEFT (ic);
8015 result = IC_RESULT (ic);
8016 aopOp (left, ic, FALSE);
8017 aopOp (result, ic, FALSE);
8019 switch (AOP_SIZE (left))
8021 case 1: /* swap nibbles in byte */
8022 MOVA (aopGet (left, 0, FALSE, FALSE));
8023 emitcode ("swap", "a");
8024 aopPut (result, "a", 0);
8026 case 2: /* swap bytes in word */
8027 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8029 MOVA (aopGet (left, 0, FALSE, FALSE));
8030 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8031 aopPut (result, "a", 1);
8033 else if (operandsEqu (left, result))
8036 bool pushedB = FALSE, leftInB = FALSE;
8038 MOVA (aopGet (left, 0, FALSE, FALSE));
8039 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8042 emitcode ("mov", "b,a");
8046 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8047 aopPut (result, reg, 1);
8054 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8055 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8059 wassertl(FALSE, "unsupported SWAP operand size");
8062 freeAsmop (result, NULL, ic, TRUE);
8063 freeAsmop (left, NULL, ic, TRUE);
8066 /*-----------------------------------------------------------------*/
8067 /* AccRol - rotate left accumulator by known count */
8068 /*-----------------------------------------------------------------*/
8070 AccRol (int shCount)
8072 shCount &= 0x0007; // shCount : 0..7
8079 emitcode ("rl", "a");
8082 emitcode ("rl", "a");
8083 emitcode ("rl", "a");
8086 emitcode ("swap", "a");
8087 emitcode ("rr", "a");
8090 emitcode ("swap", "a");
8093 emitcode ("swap", "a");
8094 emitcode ("rl", "a");
8097 emitcode ("rr", "a");
8098 emitcode ("rr", "a");
8101 emitcode ("rr", "a");
8106 /*-----------------------------------------------------------------*/
8107 /* AccLsh - left shift accumulator by known count */
8108 /*-----------------------------------------------------------------*/
8110 AccLsh (int shCount)
8115 emitcode ("add", "a,acc");
8116 else if (shCount == 2)
8118 emitcode ("add", "a,acc");
8119 emitcode ("add", "a,acc");
8123 /* rotate left accumulator */
8125 /* and kill the lower order bits */
8126 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8131 /*-----------------------------------------------------------------*/
8132 /* AccRsh - right shift accumulator by known count */
8133 /*-----------------------------------------------------------------*/
8135 AccRsh (int shCount)
8142 emitcode ("rrc", "a");
8146 /* rotate right accumulator */
8147 AccRol (8 - shCount);
8148 /* and kill the higher order bits */
8149 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8154 /*-----------------------------------------------------------------*/
8155 /* AccSRsh - signed right shift accumulator by known count */
8156 /*-----------------------------------------------------------------*/
8158 AccSRsh (int shCount)
8165 emitcode ("mov", "c,acc.7");
8166 emitcode ("rrc", "a");
8168 else if (shCount == 2)
8170 emitcode ("mov", "c,acc.7");
8171 emitcode ("rrc", "a");
8172 emitcode ("mov", "c,acc.7");
8173 emitcode ("rrc", "a");
8177 tlbl = newiTempLabel (NULL);
8178 /* rotate right accumulator */
8179 AccRol (8 - shCount);
8180 /* and kill the higher order bits */
8181 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8182 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8183 emitcode ("orl", "a,#0x%02x",
8184 (unsigned char) ~SRMask[shCount]);
8190 /*-----------------------------------------------------------------*/
8191 /* shiftR1Left2Result - shift right one byte from left to result */
8192 /*-----------------------------------------------------------------*/
8194 shiftR1Left2Result (operand * left, int offl,
8195 operand * result, int offr,
8196 int shCount, int sign)
8198 MOVA (aopGet (left, offl, FALSE, FALSE));
8199 /* shift right accumulator */
8204 aopPut (result, "a", offr);
8207 /*-----------------------------------------------------------------*/
8208 /* shiftL1Left2Result - shift left one byte from left to result */
8209 /*-----------------------------------------------------------------*/
8211 shiftL1Left2Result (operand * left, int offl,
8212 operand * result, int offr, int shCount)
8215 l = aopGet (left, offl, FALSE, FALSE);
8217 /* shift left accumulator */
8219 aopPut (result, "a", offr);
8222 /*-----------------------------------------------------------------*/
8223 /* movLeft2Result - move byte from left to result */
8224 /*-----------------------------------------------------------------*/
8226 movLeft2Result (operand * left, int offl,
8227 operand * result, int offr, int sign)
8230 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8232 l = aopGet (left, offl, FALSE, FALSE);
8234 if (*l == '@' && (IS_AOP_PREG (result)))
8236 emitcode ("mov", "a,%s", l);
8237 aopPut (result, "a", offr);
8243 aopPut (result, l, offr);
8247 /* MSB sign in acc.7 ! */
8248 if (getDataSize (left) == offl + 1)
8251 aopPut (result, "a", offr);
8258 /*-----------------------------------------------------------------*/
8259 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8260 /*-----------------------------------------------------------------*/
8264 emitcode ("rrc", "a");
8265 emitcode ("xch", "a,%s", x);
8266 emitcode ("rrc", "a");
8267 emitcode ("xch", "a,%s", x);
8270 /*-----------------------------------------------------------------*/
8271 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8272 /*-----------------------------------------------------------------*/
8276 emitcode ("xch", "a,%s", x);
8277 emitcode ("rlc", "a");
8278 emitcode ("xch", "a,%s", x);
8279 emitcode ("rlc", "a");
8282 /*-----------------------------------------------------------------*/
8283 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8284 /*-----------------------------------------------------------------*/
8288 emitcode ("xch", "a,%s", x);
8289 emitcode ("add", "a,acc");
8290 emitcode ("xch", "a,%s", x);
8291 emitcode ("rlc", "a");
8294 /*-----------------------------------------------------------------*/
8295 /* AccAXLsh - left shift a:x by known count (0..7) */
8296 /*-----------------------------------------------------------------*/
8298 AccAXLsh (char *x, int shCount)
8313 case 5: // AAAAABBB:CCCCCDDD
8315 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8317 emitcode ("anl", "a,#0x%02x",
8318 SLMask[shCount]); // BBB00000:CCCCCDDD
8320 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8322 AccRol (shCount); // DDDCCCCC:BBB00000
8324 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8326 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8328 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8330 emitcode ("anl", "a,#0x%02x",
8331 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8333 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8335 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8338 case 6: // AAAAAABB:CCCCCCDD
8339 emitcode ("anl", "a,#0x%02x",
8340 SRMask[shCount]); // 000000BB:CCCCCCDD
8341 emitcode ("mov", "c,acc.0"); // c = B
8342 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8344 AccAXRrl1 (x); // BCCCCCCD:D000000B
8345 AccAXRrl1 (x); // BBCCCCCC:DD000000
8347 emitcode("rrc","a");
8348 emitcode("xch","a,%s", x);
8349 emitcode("rrc","a");
8350 emitcode("mov","c,acc.0"); //<< get correct bit
8351 emitcode("xch","a,%s", x);
8353 emitcode("rrc","a");
8354 emitcode("xch","a,%s", x);
8355 emitcode("rrc","a");
8356 emitcode("xch","a,%s", x);
8359 case 7: // a:x <<= 7
8361 emitcode ("anl", "a,#0x%02x",
8362 SRMask[shCount]); // 0000000B:CCCCCCCD
8364 emitcode ("mov", "c,acc.0"); // c = B
8366 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8368 AccAXRrl1 (x); // BCCCCCCC:D0000000
8376 /*-----------------------------------------------------------------*/
8377 /* AccAXRsh - right shift a:x known count (0..7) */
8378 /*-----------------------------------------------------------------*/
8380 AccAXRsh (char *x, int shCount)
8388 AccAXRrl1 (x); // 0->a:x
8393 AccAXRrl1 (x); // 0->a:x
8396 AccAXRrl1 (x); // 0->a:x
8401 case 5: // AAAAABBB:CCCCCDDD = a:x
8403 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8405 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8407 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8409 emitcode ("anl", "a,#0x%02x",
8410 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8412 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8414 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8416 emitcode ("anl", "a,#0x%02x",
8417 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8419 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8421 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8423 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8426 case 6: // AABBBBBB:CCDDDDDD
8428 emitcode ("mov", "c,acc.7");
8429 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8431 emitcode ("mov", "c,acc.7");
8432 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8434 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8436 emitcode ("anl", "a,#0x%02x",
8437 SRMask[shCount]); // 000000AA:BBBBBBCC
8440 case 7: // ABBBBBBB:CDDDDDDD
8442 emitcode ("mov", "c,acc.7"); // c = A
8444 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8446 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8448 emitcode ("anl", "a,#0x%02x",
8449 SRMask[shCount]); // 0000000A:BBBBBBBC
8457 /*-----------------------------------------------------------------*/
8458 /* AccAXRshS - right shift signed a:x known count (0..7) */
8459 /*-----------------------------------------------------------------*/
8461 AccAXRshS (char *x, int shCount)
8469 emitcode ("mov", "c,acc.7");
8470 AccAXRrl1 (x); // s->a:x
8474 emitcode ("mov", "c,acc.7");
8475 AccAXRrl1 (x); // s->a:x
8477 emitcode ("mov", "c,acc.7");
8478 AccAXRrl1 (x); // s->a:x
8483 case 5: // AAAAABBB:CCCCCDDD = a:x
8485 tlbl = newiTempLabel (NULL);
8486 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8488 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8490 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8492 emitcode ("anl", "a,#0x%02x",
8493 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8495 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8497 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8499 emitcode ("anl", "a,#0x%02x",
8500 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8502 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8504 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8506 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8508 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8509 emitcode ("orl", "a,#0x%02x",
8510 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8513 break; // SSSSAAAA:BBBCCCCC
8515 case 6: // AABBBBBB:CCDDDDDD
8517 tlbl = newiTempLabel (NULL);
8518 emitcode ("mov", "c,acc.7");
8519 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8521 emitcode ("mov", "c,acc.7");
8522 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8524 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8526 emitcode ("anl", "a,#0x%02x",
8527 SRMask[shCount]); // 000000AA:BBBBBBCC
8529 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8530 emitcode ("orl", "a,#0x%02x",
8531 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8535 case 7: // ABBBBBBB:CDDDDDDD
8537 tlbl = newiTempLabel (NULL);
8538 emitcode ("mov", "c,acc.7"); // c = A
8540 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8542 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8544 emitcode ("anl", "a,#0x%02x",
8545 SRMask[shCount]); // 0000000A:BBBBBBBC
8547 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8548 emitcode ("orl", "a,#0x%02x",
8549 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8558 /*-----------------------------------------------------------------*/
8559 /* shiftL2Left2Result - shift left two bytes from left to result */
8560 /*-----------------------------------------------------------------*/
8562 shiftL2Left2Result (operand * left, int offl,
8563 operand * result, int offr, int shCount)
8566 bool pushedB = FALSE;
8569 if (sameRegs (AOP (result), AOP (left)) &&
8570 ((offl + MSB16) == offr))
8572 /* don't crash result[offr] */
8573 MOVA (aopGet (left, offl, FALSE, FALSE));
8574 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8575 usedB = !strncmp(x, "b", 1);
8577 else if (aopGetUsesAcc (result, offr))
8579 movLeft2Result (left, offl, result, offr, 0);
8582 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8583 MOVA (aopGet (result, offr, FALSE, FALSE));
8584 emitcode ("xch", "a,b");
8589 movLeft2Result (left, offl, result, offr, 0);
8590 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8591 x = aopGet (result, offr, FALSE, FALSE);
8593 /* ax << shCount (x = lsb(result)) */
8594 AccAXLsh (x, shCount);
8597 emitcode ("xch", "a,b");
8598 aopPut (result, "a", offr);
8599 aopPut (result, "b", offr + MSB16);
8604 aopPut (result, "a", offr + MSB16);
8609 /*-----------------------------------------------------------------*/
8610 /* shiftR2Left2Result - shift right two bytes from left to result */
8611 /*-----------------------------------------------------------------*/
8613 shiftR2Left2Result (operand * left, int offl,
8614 operand * result, int offr,
8615 int shCount, int sign)
8618 bool pushedB = FALSE;
8621 if (sameRegs (AOP (result), AOP (left)) &&
8622 ((offl + MSB16) == offr))
8624 /* don't crash result[offr] */
8625 MOVA (aopGet (left, offl, FALSE, FALSE));
8626 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8627 usedB = !strncmp(x, "b", 1);
8629 else if (aopGetUsesAcc (result, offr))
8631 movLeft2Result (left, offl, result, offr, 0);
8634 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8635 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8640 movLeft2Result (left, offl, result, offr, 0);
8641 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8642 x = aopGet (result, offr, FALSE, FALSE);
8644 /* a:x >> shCount (x = lsb(result)) */
8646 AccAXRshS (x, shCount);
8648 AccAXRsh (x, shCount);
8651 emitcode ("xch", "a,b");
8652 aopPut (result, "a", offr);
8653 emitcode ("xch", "a,b");
8656 if (getDataSize (result) > 1)
8657 aopPut (result, "a", offr + MSB16);
8660 /*-----------------------------------------------------------------*/
8661 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8662 /*-----------------------------------------------------------------*/
8664 shiftLLeftOrResult (operand * left, int offl,
8665 operand * result, int offr, int shCount)
8667 MOVA (aopGet (left, offl, FALSE, FALSE));
8668 /* shift left accumulator */
8670 /* or with result */
8671 if (aopGetUsesAcc (result, offr))
8673 emitcode ("xch", "a,b");
8674 MOVA (aopGet (result, offr, FALSE, FALSE));
8675 emitcode ("orl", "a,b");
8679 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8681 /* back to result */
8682 aopPut (result, "a", offr);
8685 /*-----------------------------------------------------------------*/
8686 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8687 /*-----------------------------------------------------------------*/
8689 shiftRLeftOrResult (operand * left, int offl,
8690 operand * result, int offr, int shCount)
8692 MOVA (aopGet (left, offl, FALSE, FALSE));
8693 /* shift right accumulator */
8695 /* or with result */
8696 if (aopGetUsesAcc(result, offr))
8698 emitcode ("xch", "a,b");
8699 MOVA (aopGet (result, offr, FALSE, FALSE));
8700 emitcode ("orl", "a,b");
8704 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8706 /* back to result */
8707 aopPut (result, "a", offr);
8710 /*-----------------------------------------------------------------*/
8711 /* genlshOne - left shift a one byte quantity by known count */
8712 /*-----------------------------------------------------------------*/
8714 genlshOne (operand * result, operand * left, int shCount)
8716 D (emitcode (";", "genlshOne"));
8718 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8721 /*-----------------------------------------------------------------*/
8722 /* genlshTwo - left shift two bytes by known amount != 0 */
8723 /*-----------------------------------------------------------------*/
8725 genlshTwo (operand * result, operand * left, int shCount)
8729 D (emitcode (";", "genlshTwo"));
8731 size = getDataSize (result);
8733 /* if shCount >= 8 */
8741 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8743 movLeft2Result (left, LSB, result, MSB16, 0);
8745 aopPut (result, zero, LSB);
8748 /* 1 <= shCount <= 7 */
8752 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8754 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8758 /*-----------------------------------------------------------------*/
8759 /* shiftLLong - shift left one long from left to result */
8760 /* offl = LSB or MSB16 */
8761 /*-----------------------------------------------------------------*/
8763 shiftLLong (operand * left, operand * result, int offr)
8766 int size = AOP_SIZE (result);
8768 if (size >= LSB + offr)
8770 l = aopGet (left, LSB, FALSE, FALSE);
8772 emitcode ("add", "a,acc");
8773 if (sameRegs (AOP (left), AOP (result)) &&
8774 size >= MSB16 + offr && offr != LSB)
8775 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8777 aopPut (result, "a", LSB + offr);
8780 if (size >= MSB16 + offr)
8782 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8784 l = aopGet (left, MSB16, FALSE, FALSE);
8787 emitcode ("rlc", "a");
8788 if (sameRegs (AOP (left), AOP (result)) &&
8789 size >= MSB24 + offr && offr != LSB)
8790 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8792 aopPut (result, "a", MSB16 + offr);
8795 if (size >= MSB24 + offr)
8797 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8799 l = aopGet (left, MSB24, FALSE, FALSE);
8802 emitcode ("rlc", "a");
8803 if (sameRegs (AOP (left), AOP (result)) &&
8804 size >= MSB32 + offr && offr != LSB)
8805 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8807 aopPut (result, "a", MSB24 + offr);
8810 if (size > MSB32 + offr)
8812 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8814 l = aopGet (left, MSB32, FALSE, FALSE);
8817 emitcode ("rlc", "a");
8818 aopPut (result, "a", MSB32 + offr);
8821 aopPut (result, zero, LSB);
8824 /*-----------------------------------------------------------------*/
8825 /* genlshFour - shift four byte by a known amount != 0 */
8826 /*-----------------------------------------------------------------*/
8828 genlshFour (operand * result, operand * left, int shCount)
8832 D (emitcode (";", "genlshFour"));
8834 size = AOP_SIZE (result);
8836 /* if shifting more that 3 bytes */
8841 /* lowest order of left goes to the highest
8842 order of the destination */
8843 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8845 movLeft2Result (left, LSB, result, MSB32, 0);
8846 aopPut (result, zero, LSB);
8847 aopPut (result, zero, MSB16);
8848 aopPut (result, zero, MSB24);
8852 /* more than two bytes */
8853 else if (shCount >= 16)
8855 /* lower order two bytes goes to higher order two bytes */
8857 /* if some more remaining */
8859 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8862 movLeft2Result (left, MSB16, result, MSB32, 0);
8863 movLeft2Result (left, LSB, result, MSB24, 0);
8865 aopPut (result, zero, MSB16);
8866 aopPut (result, zero, LSB);
8870 /* if more than 1 byte */
8871 else if (shCount >= 8)
8873 /* lower order three bytes goes to higher order three bytes */
8878 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8880 movLeft2Result (left, LSB, result, MSB16, 0);
8886 movLeft2Result (left, MSB24, result, MSB32, 0);
8887 movLeft2Result (left, MSB16, result, MSB24, 0);
8888 movLeft2Result (left, LSB, result, MSB16, 0);
8889 aopPut (result, zero, LSB);
8891 else if (shCount == 1)
8892 shiftLLong (left, result, MSB16);
8895 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8896 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8897 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8898 aopPut (result, zero, LSB);
8903 /* 1 <= shCount <= 7 */
8904 else if (shCount <= 2)
8906 shiftLLong (left, result, LSB);
8908 shiftLLong (result, result, LSB);
8910 /* 3 <= shCount <= 7, optimize */
8913 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8914 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8915 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8919 /*-----------------------------------------------------------------*/
8920 /* genLeftShiftLiteral - left shifting by known count */
8921 /*-----------------------------------------------------------------*/
8923 genLeftShiftLiteral (operand * left,
8928 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8931 D (emitcode (";", "genLeftShiftLiteral"));
8933 freeAsmop (right, NULL, ic, TRUE);
8935 aopOp (left, ic, FALSE);
8936 aopOp (result, ic, FALSE);
8938 size = getSize (operandType (result));
8941 emitcode ("; shift left ", "result %d, left %d", size,
8945 /* I suppose that the left size >= result size */
8950 movLeft2Result (left, size, result, size, 0);
8953 else if (shCount >= (size * 8))
8957 aopPut (result, zero, size);
8965 genlshOne (result, left, shCount);
8969 genlshTwo (result, left, shCount);
8973 genlshFour (result, left, shCount);
8976 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8977 "*** ack! mystery literal shift!\n");
8981 freeAsmop (result, NULL, ic, TRUE);
8982 freeAsmop (left, NULL, ic, TRUE);
8985 /*-----------------------------------------------------------------*/
8986 /* genLeftShift - generates code for left shifting */
8987 /*-----------------------------------------------------------------*/
8989 genLeftShift (iCode * ic)
8991 operand *left, *right, *result;
8994 symbol *tlbl, *tlbl1;
8997 D (emitcode (";", "genLeftShift"));
8999 right = IC_RIGHT (ic);
9000 left = IC_LEFT (ic);
9001 result = IC_RESULT (ic);
9003 aopOp (right, ic, FALSE);
9005 /* if the shift count is known then do it
9006 as efficiently as possible */
9007 if (AOP_TYPE (right) == AOP_LIT)
9009 genLeftShiftLiteral (left, right, result, ic);
9013 /* shift count is unknown then we have to form
9014 a loop get the loop count in B : Note: we take
9015 only the lower order byte since shifting
9016 more that 32 bits make no sense anyway, ( the
9017 largest size of an object can be only 32 bits ) */
9020 MOVB (aopGet (right, 0, FALSE, FALSE));
9021 emitcode ("inc", "b");
9022 freeAsmop (right, NULL, ic, TRUE);
9023 aopOp (left, ic, FALSE);
9024 aopOp (result, ic, FALSE);
9026 /* now move the left to the result if they are not the same */
9027 if (!sameRegs (AOP (left), AOP (result)) &&
9028 AOP_SIZE (result) > 1)
9031 size = AOP_SIZE (result);
9035 l = aopGet (left, offset, FALSE, TRUE);
9036 if (*l == '@' && (IS_AOP_PREG (result)))
9039 emitcode ("mov", "a,%s", l);
9040 aopPut (result, "a", offset);
9043 aopPut (result, l, offset);
9048 tlbl = newiTempLabel (NULL);
9049 size = AOP_SIZE (result);
9051 tlbl1 = newiTempLabel (NULL);
9053 /* if it is only one byte then */
9056 symbol *tlbl1 = newiTempLabel (NULL);
9058 l = aopGet (left, 0, FALSE, FALSE);
9060 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9062 emitcode ("add", "a,acc");
9064 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9066 aopPut (result, "a", 0);
9070 reAdjustPreg (AOP (result));
9072 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9074 l = aopGet (result, offset, FALSE, FALSE);
9076 emitcode ("add", "a,acc");
9077 aopPut (result, "a", offset++);
9080 l = aopGet (result, offset, FALSE, FALSE);
9082 emitcode ("rlc", "a");
9083 aopPut (result, "a", offset++);
9085 reAdjustPreg (AOP (result));
9088 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9091 freeAsmop (result, NULL, ic, TRUE);
9092 freeAsmop (left, NULL, ic, TRUE);
9095 /*-----------------------------------------------------------------*/
9096 /* genrshOne - right shift a one byte quantity by known count */
9097 /*-----------------------------------------------------------------*/
9099 genrshOne (operand * result, operand * left,
9100 int shCount, int sign)
9102 D (emitcode (";", "genrshOne"));
9104 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9107 /*-----------------------------------------------------------------*/
9108 /* genrshTwo - right shift two bytes by known amount != 0 */
9109 /*-----------------------------------------------------------------*/
9111 genrshTwo (operand * result, operand * left,
9112 int shCount, int sign)
9114 D (emitcode (";", "genrshTwo"));
9116 /* if shCount >= 8 */
9121 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9123 movLeft2Result (left, MSB16, result, LSB, sign);
9124 addSign (result, MSB16, sign);
9127 /* 1 <= shCount <= 7 */
9129 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9132 /*-----------------------------------------------------------------*/
9133 /* shiftRLong - shift right one long from left to result */
9134 /* offl = LSB or MSB16 */
9135 /*-----------------------------------------------------------------*/
9137 shiftRLong (operand * left, int offl,
9138 operand * result, int sign)
9140 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9142 if (overlapping && offl>1)
9144 // we are in big trouble, but this shouldn't happen
9145 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9148 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9155 emitcode ("rlc", "a");
9156 emitcode ("subb", "a,acc");
9157 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9159 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9163 aopPut (result, "a", MSB32);
9164 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9169 if (aopPutUsesAcc (result, zero, MSB32))
9171 emitcode("xch", "a,b");
9172 aopPut (result, zero, MSB32);
9173 emitcode("xch", "a,b");
9177 aopPut (result, zero, MSB32);
9184 emitcode ("clr", "c");
9188 emitcode ("mov", "c,acc.7");
9191 emitcode ("rrc", "a");
9193 if (overlapping && offl==MSB16 &&
9194 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9196 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9200 aopPut (result, "a", MSB32 - offl);
9201 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9204 emitcode ("rrc", "a");
9205 if (overlapping && offl==MSB16 &&
9206 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9208 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9212 aopPut (result, "a", MSB24 - offl);
9213 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9216 emitcode ("rrc", "a");
9219 aopPut (result, "a", MSB16 - offl);
9224 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9226 xch_a_aopGet (left, LSB, FALSE, FALSE);
9230 aopPut (result, "a", MSB16 - offl);
9231 MOVA (aopGet (left, LSB, FALSE, FALSE));
9233 emitcode ("rrc", "a");
9234 aopPut (result, "a", LSB);
9238 /*-----------------------------------------------------------------*/
9239 /* genrshFour - shift four byte by a known amount != 0 */
9240 /*-----------------------------------------------------------------*/
9242 genrshFour (operand * result, operand * left,
9243 int shCount, int sign)
9245 D (emitcode (";", "genrshFour"));
9247 /* if shifting more that 3 bytes */
9252 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9254 movLeft2Result (left, MSB32, result, LSB, sign);
9255 addSign (result, MSB16, sign);
9257 else if (shCount >= 16)
9261 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9264 movLeft2Result (left, MSB24, result, LSB, 0);
9265 movLeft2Result (left, MSB32, result, MSB16, sign);
9267 addSign (result, MSB24, sign);
9269 else if (shCount >= 8)
9274 shiftRLong (left, MSB16, result, sign);
9276 else if (shCount == 0)
9278 movLeft2Result (left, MSB16, result, LSB, 0);
9279 movLeft2Result (left, MSB24, result, MSB16, 0);
9280 movLeft2Result (left, MSB32, result, MSB24, sign);
9281 addSign (result, MSB32, sign);
9285 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9286 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9287 /* the last shift is signed */
9288 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9289 addSign (result, MSB32, sign);
9294 /* 1 <= shCount <= 7 */
9297 shiftRLong (left, LSB, result, sign);
9299 shiftRLong (result, LSB, result, sign);
9303 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9304 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9305 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9310 /*-----------------------------------------------------------------*/
9311 /* genRightShiftLiteral - right shifting by known count */
9312 /*-----------------------------------------------------------------*/
9314 genRightShiftLiteral (operand * left,
9320 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9323 D (emitcode (";", "genRightShiftLiteral"));
9325 freeAsmop (right, NULL, ic, TRUE);
9327 aopOp (left, ic, FALSE);
9328 aopOp (result, ic, FALSE);
9331 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9335 size = getDataSize (left);
9336 /* test the LEFT size !!! */
9338 /* I suppose that the left size >= result size */
9341 size = getDataSize (result);
9343 movLeft2Result (left, size, result, size, 0);
9346 else if (shCount >= (size * 8))
9350 /* get sign in acc.7 */
9351 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9353 addSign (result, LSB, sign);
9360 genrshOne (result, left, shCount, sign);
9364 genrshTwo (result, left, shCount, sign);
9368 genrshFour (result, left, shCount, sign);
9374 freeAsmop (result, NULL, ic, TRUE);
9375 freeAsmop (left, NULL, ic, TRUE);
9378 /*-----------------------------------------------------------------*/
9379 /* genSignedRightShift - right shift of signed number */
9380 /*-----------------------------------------------------------------*/
9382 genSignedRightShift (iCode * ic)
9384 operand *right, *left, *result;
9387 symbol *tlbl, *tlbl1;
9390 D (emitcode (";", "genSignedRightShift"));
9392 /* we do it the hard way put the shift count in b
9393 and loop thru preserving the sign */
9395 right = IC_RIGHT (ic);
9396 left = IC_LEFT (ic);
9397 result = IC_RESULT (ic);
9399 aopOp (right, ic, FALSE);
9402 if (AOP_TYPE (right) == AOP_LIT)
9404 genRightShiftLiteral (left, right, result, ic, 1);
9407 /* shift count is unknown then we have to form
9408 a loop get the loop count in B : Note: we take
9409 only the lower order byte since shifting
9410 more that 32 bits make no sense anyway, ( the
9411 largest size of an object can be only 32 bits ) */
9414 MOVB (aopGet (right, 0, FALSE, FALSE));
9415 emitcode ("inc", "b");
9416 freeAsmop (right, NULL, ic, TRUE);
9417 aopOp (left, ic, FALSE);
9418 aopOp (result, ic, FALSE);
9420 /* now move the left to the result if they are not the
9422 if (!sameRegs (AOP (left), AOP (result)) &&
9423 AOP_SIZE (result) > 1)
9426 size = AOP_SIZE (result);
9430 l = aopGet (left, offset, FALSE, TRUE);
9431 if (*l == '@' && IS_AOP_PREG (result))
9434 emitcode ("mov", "a,%s", l);
9435 aopPut (result, "a", offset);
9438 aopPut (result, l, offset);
9443 /* mov the highest order bit to OVR */
9444 tlbl = newiTempLabel (NULL);
9445 tlbl1 = newiTempLabel (NULL);
9447 size = AOP_SIZE (result);
9449 MOVA (aopGet (left, offset, FALSE, FALSE));
9450 emitcode ("rlc", "a");
9451 emitcode ("mov", "ov,c");
9452 /* if it is only one byte then */
9455 l = aopGet (left, 0, FALSE, FALSE);
9457 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9459 emitcode ("mov", "c,ov");
9460 emitcode ("rrc", "a");
9462 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9464 aopPut (result, "a", 0);
9468 reAdjustPreg (AOP (result));
9469 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9471 emitcode ("mov", "c,ov");
9474 l = aopGet (result, offset, FALSE, FALSE);
9476 emitcode ("rrc", "a");
9477 aopPut (result, "a", offset--);
9479 reAdjustPreg (AOP (result));
9481 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9485 freeAsmop (result, NULL, ic, TRUE);
9486 freeAsmop (left, NULL, ic, TRUE);
9489 /*-----------------------------------------------------------------*/
9490 /* genRightShift - generate code for right shifting */
9491 /*-----------------------------------------------------------------*/
9493 genRightShift (iCode * ic)
9495 operand *right, *left, *result;
9499 symbol *tlbl, *tlbl1;
9502 D (emitcode (";", "genRightShift"));
9504 /* if signed then we do it the hard way preserve the
9505 sign bit moving it inwards */
9506 letype = getSpec (operandType (IC_LEFT (ic)));
9508 if (!SPEC_USIGN (letype))
9510 genSignedRightShift (ic);
9514 /* signed & unsigned types are treated the same : i.e. the
9515 signed is NOT propagated inwards : quoting from the
9516 ANSI - standard : "for E1 >> E2, is equivalent to division
9517 by 2**E2 if unsigned or if it has a non-negative value,
9518 otherwise the result is implementation defined ", MY definition
9519 is that the sign does not get propagated */
9521 right = IC_RIGHT (ic);
9522 left = IC_LEFT (ic);
9523 result = IC_RESULT (ic);
9525 aopOp (right, ic, FALSE);
9527 /* if the shift count is known then do it
9528 as efficiently as possible */
9529 if (AOP_TYPE (right) == AOP_LIT)
9531 genRightShiftLiteral (left, right, result, ic, 0);
9535 /* shift count is unknown then we have to form
9536 a loop get the loop count in B : Note: we take
9537 only the lower order byte since shifting
9538 more that 32 bits make no sense anyway, ( the
9539 largest size of an object can be only 32 bits ) */
9542 MOVB (aopGet (right, 0, FALSE, FALSE));
9543 emitcode ("inc", "b");
9544 freeAsmop (right, NULL, ic, TRUE);
9545 aopOp (left, ic, FALSE);
9546 aopOp (result, ic, FALSE);
9548 /* now move the left to the result if they are not the
9550 if (!sameRegs (AOP (left), AOP (result)) &&
9551 AOP_SIZE (result) > 1)
9553 size = AOP_SIZE (result);
9557 l = aopGet (left, offset, FALSE, TRUE);
9558 if (*l == '@' && IS_AOP_PREG (result))
9561 emitcode ("mov", "a,%s", l);
9562 aopPut (result, "a", offset);
9565 aopPut (result, l, offset);
9570 tlbl = newiTempLabel (NULL);
9571 tlbl1 = newiTempLabel (NULL);
9572 size = AOP_SIZE (result);
9575 /* if it is only one byte then */
9578 l = aopGet (left, 0, FALSE, FALSE);
9580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9583 emitcode ("rrc", "a");
9585 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9587 aopPut (result, "a", 0);
9591 reAdjustPreg (AOP (result));
9592 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9597 l = aopGet (result, offset, FALSE, FALSE);
9599 emitcode ("rrc", "a");
9600 aopPut (result, "a", offset--);
9602 reAdjustPreg (AOP (result));
9605 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9609 freeAsmop (result, NULL, ic, TRUE);
9610 freeAsmop (left, NULL, ic, TRUE);
9613 /*-----------------------------------------------------------------*/
9614 /* emitPtrByteGet - emits code to get a byte into A through a */
9615 /* pointer register (R0, R1, or DPTR). The */
9616 /* original value of A can be preserved in B. */
9617 /*-----------------------------------------------------------------*/
9619 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9626 emitcode ("mov", "b,a");
9627 emitcode ("mov", "a,@%s", rname);
9632 emitcode ("mov", "b,a");
9633 emitcode ("movx", "a,@%s", rname);
9638 emitcode ("mov", "b,a");
9639 emitcode ("movx", "a,@dptr");
9644 emitcode ("mov", "b,a");
9645 emitcode ("clr", "a");
9646 emitcode ("movc", "a,@a+dptr");
9652 emitcode ("push", "b");
9653 emitcode ("push", "acc");
9655 emitcode ("lcall", "__gptrget");
9657 emitcode ("pop", "b");
9662 /*-----------------------------------------------------------------*/
9663 /* emitPtrByteSet - emits code to set a byte from src through a */
9664 /* pointer register (R0, R1, or DPTR). */
9665 /*-----------------------------------------------------------------*/
9667 emitPtrByteSet (char *rname, int p_type, char *src)
9676 emitcode ("mov", "@%s,a", rname);
9679 emitcode ("mov", "@%s,%s", rname, src);
9684 emitcode ("movx", "@%s,a", rname);
9689 emitcode ("movx", "@dptr,a");
9694 emitcode ("lcall", "__gptrput");
9699 /*-----------------------------------------------------------------*/
9700 /* genUnpackBits - generates code for unpacking bits */
9701 /*-----------------------------------------------------------------*/
9703 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9705 int offset = 0; /* result byte offset */
9706 int rsize; /* result size */
9707 int rlen = 0; /* remaining bitfield length */
9708 sym_link *etype; /* bitfield type information */
9709 int blen; /* bitfield length */
9710 int bstr; /* bitfield starting bit within byte */
9713 D(emitcode (";", "genUnpackBits"));
9715 etype = getSpec (operandType (result));
9716 rsize = getSize (operandType (result));
9717 blen = SPEC_BLEN (etype);
9718 bstr = SPEC_BSTR (etype);
9720 if (ifx && blen <= 8)
9722 emitPtrByteGet (rname, ptype, FALSE);
9725 SNPRINTF (buffer, sizeof(buffer),
9727 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9732 emitcode ("anl", "a,#0x%02x",
9733 (((unsigned char) -1) >> (8 - blen)) << bstr);
9734 genIfxJump (ifx, "a", NULL, NULL, NULL);
9740 /* If the bitfield length is less than a byte */
9743 emitPtrByteGet (rname, ptype, FALSE);
9745 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9746 if (!SPEC_USIGN (etype))
9748 /* signed bitfield */
9749 symbol *tlbl = newiTempLabel (NULL);
9751 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9752 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9755 aopPut (result, "a", offset++);
9759 /* Bit field did not fit in a byte. Copy all
9760 but the partial byte at the end. */
9761 for (rlen=blen;rlen>=8;rlen-=8)
9763 emitPtrByteGet (rname, ptype, FALSE);
9764 aopPut (result, "a", offset++);
9766 emitcode ("inc", "%s", rname);
9769 /* Handle the partial byte at the end */
9772 emitPtrByteGet (rname, ptype, FALSE);
9773 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9774 if (!SPEC_USIGN (etype))
9776 /* signed bitfield */
9777 symbol *tlbl = newiTempLabel (NULL);
9779 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9780 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9783 aopPut (result, "a", offset++);
9791 if (SPEC_USIGN (etype))
9795 /* signed bitfield: sign extension with 0x00 or 0xff */
9796 emitcode ("rlc", "a");
9797 emitcode ("subb", "a,acc");
9803 aopPut (result, source, offset++);
9808 /*-----------------------------------------------------------------*/
9809 /* genDataPointerGet - generates code when ptr offset is known */
9810 /*-----------------------------------------------------------------*/
9812 genDataPointerGet (operand * left,
9818 int size, offset = 0;
9820 D (emitcode (";", "genDataPointerGet"));
9822 aopOp (result, ic, TRUE);
9824 /* get the string representation of the name */
9825 l = aopGet (left, 0, FALSE, TRUE);
9827 size = AOP_SIZE (result);
9832 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9836 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9838 aopPut (result, buffer, offset++);
9841 freeAsmop (result, NULL, ic, TRUE);
9842 freeAsmop (left, NULL, ic, TRUE);
9845 /*-----------------------------------------------------------------*/
9846 /* genNearPointerGet - emitcode for near pointer fetch */
9847 /*-----------------------------------------------------------------*/
9849 genNearPointerGet (operand * left,
9858 sym_link *rtype, *retype;
9859 sym_link *ltype = operandType (left);
9862 D (emitcode (";", "genNearPointerGet"));
9864 rtype = operandType (result);
9865 retype = getSpec (rtype);
9867 aopOp (left, ic, FALSE);
9869 /* if left is rematerialisable and
9870 result is not bitfield variable type and
9871 the left is pointer to data space i.e
9872 lower 128 bytes of space */
9873 if (AOP_TYPE (left) == AOP_IMMD &&
9874 !IS_BITFIELD (retype) &&
9875 DCL_TYPE (ltype) == POINTER)
9877 genDataPointerGet (left, result, ic);
9881 /* if the value is already in a pointer register
9882 then don't need anything more */
9883 if (!AOP_INPREG (AOP (left)))
9885 if (IS_AOP_PREG (left))
9887 // Aha, it is a pointer, just in disguise.
9888 rname = aopGet (left, 0, FALSE, FALSE);
9891 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9892 __FILE__, __LINE__);
9897 emitcode ("mov", "a%s,%s", rname + 1, rname);
9898 rname++; // skip the '@'.
9903 /* otherwise get a free pointer register */
9905 preg = getFreePtr (ic, &aop, FALSE);
9906 emitcode ("mov", "%s,%s",
9908 aopGet (left, 0, FALSE, TRUE));
9913 rname = aopGet (left, 0, FALSE, FALSE);
9915 //aopOp (result, ic, FALSE);
9916 aopOp (result, ic, result?TRUE:FALSE);
9918 /* if bitfield then unpack the bits */
9919 if (IS_BITFIELD (retype))
9920 genUnpackBits (result, rname, POINTER, ifx);
9923 /* we have can just get the values */
9924 int size = AOP_SIZE (result);
9929 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9932 emitcode ("mov", "a,@%s", rname);
9934 aopPut (result, "a", offset);
9938 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9939 aopPut (result, buffer, offset);
9943 emitcode ("inc", "%s", rname);
9947 /* now some housekeeping stuff */
9948 if (aop) /* we had to allocate for this iCode */
9950 if (pi) { /* post increment present */
9951 aopPut (left, rname, 0);
9953 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9957 /* we did not allocate which means left
9958 already in a pointer register, then
9959 if size > 0 && this could be used again
9960 we have to point it back to where it
9962 if ((AOP_SIZE (result) > 1 &&
9963 !OP_SYMBOL (left)->remat &&
9964 (OP_SYMBOL (left)->liveTo > ic->seq ||
9968 int size = AOP_SIZE (result) - 1;
9970 emitcode ("dec", "%s", rname);
9974 if (ifx && !ifx->generated)
9976 genIfxJump (ifx, "a", left, NULL, result);
9980 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9981 freeAsmop (left, NULL, ic, TRUE);
9982 if (pi) pi->generated = 1;
9985 /*-----------------------------------------------------------------*/
9986 /* genPagedPointerGet - emitcode for paged pointer fetch */
9987 /*-----------------------------------------------------------------*/
9989 genPagedPointerGet (operand * left,
9998 sym_link *rtype, *retype;
10000 D (emitcode (";", "genPagedPointerGet"));
10002 rtype = operandType (result);
10003 retype = getSpec (rtype);
10005 aopOp (left, ic, FALSE);
10007 /* if the value is already in a pointer register
10008 then don't need anything more */
10009 if (!AOP_INPREG (AOP (left)))
10011 /* otherwise get a free pointer register */
10012 aop = newAsmop (0);
10013 preg = getFreePtr (ic, &aop, FALSE);
10014 emitcode ("mov", "%s,%s",
10016 aopGet (left, 0, FALSE, TRUE));
10017 rname = preg->name;
10020 rname = aopGet (left, 0, FALSE, FALSE);
10022 aopOp (result, ic, FALSE);
10024 /* if bitfield then unpack the bits */
10025 if (IS_BITFIELD (retype))
10026 genUnpackBits (result, rname, PPOINTER, ifx);
10029 /* we have can just get the values */
10030 int size = AOP_SIZE (result);
10036 emitcode ("movx", "a,@%s", rname);
10038 aopPut (result, "a", offset);
10043 emitcode ("inc", "%s", rname);
10047 /* now some housekeeping stuff */
10048 if (aop) /* we had to allocate for this iCode */
10051 aopPut (left, rname, 0);
10052 freeAsmop (NULL, aop, ic, TRUE);
10056 /* we did not allocate which means left
10057 already in a pointer register, then
10058 if size > 0 && this could be used again
10059 we have to point it back to where it
10061 if ((AOP_SIZE (result) > 1 &&
10062 !OP_SYMBOL (left)->remat &&
10063 (OP_SYMBOL (left)->liveTo > ic->seq ||
10067 int size = AOP_SIZE (result) - 1;
10069 emitcode ("dec", "%s", rname);
10073 if (ifx && !ifx->generated)
10075 genIfxJump (ifx, "a", left, NULL, result);
10079 freeAsmop (result, NULL, ic, TRUE);
10080 freeAsmop (left, NULL, ic, TRUE);
10081 if (pi) pi->generated = 1;
10084 /*--------------------------------------------------------------------*/
10085 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10086 /*--------------------------------------------------------------------*/
10088 loadDptrFromOperand (operand *op, bool loadBToo)
10090 if (AOP_TYPE (op) != AOP_STR)
10092 /* if this is rematerializable */
10093 if (AOP_TYPE (op) == AOP_IMMD)
10095 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10098 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10099 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10102 wassertl(FALSE, "need pointerCode");
10103 emitcode (";", "mov b,???");
10104 /* genPointerGet and genPointerSet originally did different
10105 ** things for this case. Both seem wrong.
10106 ** from genPointerGet:
10107 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10108 ** from genPointerSet:
10109 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10114 else if (AOP_TYPE (op) == AOP_DPTR)
10118 MOVA (aopGet (op, 0, FALSE, FALSE));
10119 emitcode ("push", "acc");
10120 MOVA (aopGet (op, 1, FALSE, FALSE));
10121 emitcode ("push", "acc");
10122 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10123 emitcode ("pop", "dph");
10124 emitcode ("pop", "dpl");
10128 MOVA (aopGet (op, 0, FALSE, FALSE));
10129 emitcode ("push", "acc");
10130 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10131 emitcode ("pop", "dpl");
10135 { /* we need to get it byte by byte */
10136 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10137 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10139 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10144 /*-----------------------------------------------------------------*/
10145 /* genFarPointerGet - get value from far space */
10146 /*-----------------------------------------------------------------*/
10148 genFarPointerGet (operand * left,
10149 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10152 sym_link *retype = getSpec (operandType (result));
10154 D (emitcode (";", "genFarPointerGet"));
10156 aopOp (left, ic, FALSE);
10157 loadDptrFromOperand (left, FALSE);
10159 /* so dptr now contains the address */
10160 aopOp (result, ic, FALSE);
10162 /* if bit then unpack */
10163 if (IS_BITFIELD (retype))
10164 genUnpackBits (result, "dptr", FPOINTER, ifx);
10167 size = AOP_SIZE (result);
10172 emitcode ("movx", "a,@dptr");
10174 aopPut (result, "a", offset++);
10176 emitcode ("inc", "dptr");
10180 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10182 aopPut (left, "dpl", 0);
10183 aopPut (left, "dph", 1);
10187 if (ifx && !ifx->generated)
10189 genIfxJump (ifx, "a", left, NULL, result);
10192 freeAsmop (result, NULL, ic, TRUE);
10193 freeAsmop (left, NULL, ic, TRUE);
10196 /*-----------------------------------------------------------------*/
10197 /* genCodePointerGet - get value from code space */
10198 /*-----------------------------------------------------------------*/
10200 genCodePointerGet (operand * left,
10201 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10204 sym_link *retype = getSpec (operandType (result));
10206 D (emitcode (";", "genCodePointerGet"));
10208 aopOp (left, ic, FALSE);
10209 loadDptrFromOperand (left, FALSE);
10211 /* so dptr now contains the address */
10212 aopOp (result, ic, FALSE);
10214 /* if bit then unpack */
10215 if (IS_BITFIELD (retype))
10216 genUnpackBits (result, "dptr", CPOINTER, ifx);
10219 size = AOP_SIZE (result);
10224 emitcode ("clr", "a");
10225 emitcode ("movc", "a,@a+dptr");
10227 aopPut (result, "a", offset++);
10229 emitcode ("inc", "dptr");
10233 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10235 aopPut (left, "dpl", 0);
10236 aopPut (left, "dph", 1);
10240 if (ifx && !ifx->generated)
10242 genIfxJump (ifx, "a", left, NULL, result);
10245 freeAsmop (result, NULL, ic, TRUE);
10246 freeAsmop (left, NULL, ic, TRUE);
10249 /*-----------------------------------------------------------------*/
10250 /* genGenPointerGet - get value from generic pointer space */
10251 /*-----------------------------------------------------------------*/
10253 genGenPointerGet (operand * left,
10254 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10257 sym_link *retype = getSpec (operandType (result));
10259 D (emitcode (";", "genGenPointerGet"));
10261 aopOp (left, ic, FALSE);
10262 loadDptrFromOperand (left, TRUE);
10264 /* so dptr now contains the address */
10265 aopOp (result, ic, FALSE);
10267 /* if bit then unpack */
10268 if (IS_BITFIELD (retype))
10270 genUnpackBits (result, "dptr", GPOINTER, ifx);
10274 size = AOP_SIZE (result);
10279 emitcode ("lcall", "__gptrget");
10281 aopPut (result, "a", offset++);
10283 emitcode ("inc", "dptr");
10287 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10289 aopPut (left, "dpl", 0);
10290 aopPut (left, "dph", 1);
10294 if (ifx && !ifx->generated)
10296 genIfxJump (ifx, "a", left, NULL, result);
10299 freeAsmop (result, NULL, ic, TRUE);
10300 freeAsmop (left, NULL, ic, TRUE);
10303 /*-----------------------------------------------------------------*/
10304 /* genPointerGet - generate code for pointer get */
10305 /*-----------------------------------------------------------------*/
10307 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10309 operand *left, *result;
10310 sym_link *type, *etype;
10313 D (emitcode (";", "genPointerGet"));
10315 left = IC_LEFT (ic);
10316 result = IC_RESULT (ic);
10318 if (getSize (operandType (result))>1)
10321 /* depending on the type of pointer we need to
10322 move it to the correct pointer register */
10323 type = operandType (left);
10324 etype = getSpec (type);
10325 /* if left is of type of pointer then it is simple */
10326 if (IS_PTR (type) && !IS_FUNC (type->next))
10327 p_type = DCL_TYPE (type);
10330 /* we have to go by the storage class */
10331 p_type = PTR_TYPE (SPEC_OCLS (etype));
10334 /* special case when cast remat */
10335 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10336 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10338 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10339 type = operandType (left);
10340 p_type = DCL_TYPE (type);
10342 /* now that we have the pointer type we assign
10343 the pointer values */
10349 genNearPointerGet (left, result, ic, pi, ifx);
10353 genPagedPointerGet (left, result, ic, pi, ifx);
10357 genFarPointerGet (left, result, ic, pi, ifx);
10361 genCodePointerGet (left, result, ic, pi, ifx);
10365 genGenPointerGet (left, result, ic, pi, ifx);
10371 /*-----------------------------------------------------------------*/
10372 /* genPackBits - generates code for packed bit storage */
10373 /*-----------------------------------------------------------------*/
10375 genPackBits (sym_link * etype,
10377 char *rname, int p_type)
10379 int offset = 0; /* source byte offset */
10380 int rlen = 0; /* remaining bitfield length */
10381 int blen; /* bitfield length */
10382 int bstr; /* bitfield starting bit within byte */
10383 int litval; /* source literal value (if AOP_LIT) */
10384 unsigned char mask; /* bitmask within current byte */
10386 D(emitcode (";", "genPackBits"));
10388 blen = SPEC_BLEN (etype);
10389 bstr = SPEC_BSTR (etype);
10391 /* If the bitfield length is less than a byte */
10394 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10395 (unsigned char) (0xFF >> (8 - bstr)));
10397 if (AOP_TYPE (right) == AOP_LIT)
10399 /* Case with a bitfield length <8 and literal source
10401 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10403 litval &= (~mask) & 0xff;
10404 emitPtrByteGet (rname, p_type, FALSE);
10405 if ((mask|litval)!=0xff)
10406 emitcode ("anl","a,#0x%02x", mask);
10408 emitcode ("orl","a,#0x%02x", litval);
10412 if ((blen==1) && (p_type!=GPOINTER))
10414 /* Case with a bitfield length == 1 and no generic pointer
10416 if (AOP_TYPE (right) == AOP_CRY)
10417 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10420 MOVA (aopGet (right, 0, FALSE, FALSE));
10421 emitcode ("rrc","a");
10423 emitPtrByteGet (rname, p_type, FALSE);
10424 emitcode ("mov","acc.%d,c",bstr);
10429 /* Case with a bitfield length < 8 and arbitrary source
10431 MOVA (aopGet (right, 0, FALSE, FALSE));
10432 /* shift and mask source value */
10434 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10436 pushedB = pushB ();
10437 /* transfer A to B and get next byte */
10438 emitPtrByteGet (rname, p_type, TRUE);
10440 emitcode ("anl", "a,#0x%02x", mask);
10441 emitcode ("orl", "a,b");
10442 if (p_type == GPOINTER)
10443 emitcode ("pop", "b");
10449 emitPtrByteSet (rname, p_type, "a");
10453 /* Bit length is greater than 7 bits. In this case, copy */
10454 /* all except the partial byte at the end */
10455 for (rlen=blen;rlen>=8;rlen-=8)
10457 emitPtrByteSet (rname, p_type,
10458 aopGet (right, offset++, FALSE, TRUE) );
10460 emitcode ("inc", "%s", rname);
10463 /* If there was a partial byte at the end */
10466 mask = (((unsigned char) -1 << rlen) & 0xff);
10468 if (AOP_TYPE (right) == AOP_LIT)
10470 /* Case with partial byte and literal source
10472 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10473 litval >>= (blen-rlen);
10474 litval &= (~mask) & 0xff;
10475 emitPtrByteGet (rname, p_type, FALSE);
10476 if ((mask|litval)!=0xff)
10477 emitcode ("anl","a,#0x%02x", mask);
10479 emitcode ("orl","a,#0x%02x", litval);
10484 /* Case with partial byte and arbitrary source
10486 MOVA (aopGet (right, offset++, FALSE, FALSE));
10487 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10489 pushedB = pushB ();
10490 /* transfer A to B and get next byte */
10491 emitPtrByteGet (rname, p_type, TRUE);
10493 emitcode ("anl", "a,#0x%02x", mask);
10494 emitcode ("orl", "a,b");
10495 if (p_type == GPOINTER)
10496 emitcode ("pop", "b");
10500 emitPtrByteSet (rname, p_type, "a");
10505 /*-----------------------------------------------------------------*/
10506 /* genDataPointerSet - remat pointer to data space */
10507 /*-----------------------------------------------------------------*/
10509 genDataPointerSet (operand * right,
10513 int size, offset = 0;
10514 char *l, buffer[256];
10516 D (emitcode (";", "genDataPointerSet"));
10518 aopOp (right, ic, FALSE);
10520 l = aopGet (result, 0, FALSE, TRUE);
10522 size = AOP_SIZE (right);
10526 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10528 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10529 emitcode ("mov", "%s,%s", buffer,
10530 aopGet (right, offset++, FALSE, FALSE));
10533 freeAsmop (result, NULL, ic, TRUE);
10534 freeAsmop (right, NULL, ic, TRUE);
10537 /*-----------------------------------------------------------------*/
10538 /* genNearPointerSet - emitcode for near pointer put */
10539 /*-----------------------------------------------------------------*/
10541 genNearPointerSet (operand * right,
10549 sym_link *retype, *letype;
10550 sym_link *ptype = operandType (result);
10552 D (emitcode (";", "genNearPointerSet"));
10554 retype = getSpec (operandType (right));
10555 letype = getSpec (ptype);
10557 aopOp (result, ic, FALSE);
10559 /* if the result is rematerializable &
10560 in data space & not a bit variable */
10561 if (AOP_TYPE (result) == AOP_IMMD &&
10562 DCL_TYPE (ptype) == POINTER &&
10563 !IS_BITVAR (retype) &&
10564 !IS_BITVAR (letype))
10566 genDataPointerSet (right, result, ic);
10570 /* if the value is already in a pointer register
10571 then don't need anything more */
10572 if (!AOP_INPREG (AOP (result)))
10575 //AOP_TYPE (result) == AOP_STK
10576 IS_AOP_PREG(result)
10579 // Aha, it is a pointer, just in disguise.
10580 rname = aopGet (result, 0, FALSE, FALSE);
10583 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10584 __FILE__, __LINE__);
10589 emitcode ("mov", "a%s,%s", rname + 1, rname);
10590 rname++; // skip the '@'.
10595 /* otherwise get a free pointer register */
10596 aop = newAsmop (0);
10597 preg = getFreePtr (ic, &aop, FALSE);
10598 emitcode ("mov", "%s,%s",
10600 aopGet (result, 0, FALSE, TRUE));
10601 rname = preg->name;
10606 rname = aopGet (result, 0, FALSE, FALSE);
10609 aopOp (right, ic, FALSE);
10611 /* if bitfield then unpack the bits */
10612 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10613 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10616 /* we can just get the values */
10617 int size = AOP_SIZE (right);
10622 l = aopGet (right, offset, FALSE, TRUE);
10623 if ((*l == '@') || (strcmp (l, "acc") == 0))
10626 emitcode ("mov", "@%s,a", rname);
10629 emitcode ("mov", "@%s,%s", rname, l);
10631 emitcode ("inc", "%s", rname);
10636 /* now some housekeeping stuff */
10637 if (aop) /* we had to allocate for this iCode */
10640 aopPut (result, rname, 0);
10641 freeAsmop (NULL, aop, ic, TRUE);
10645 /* we did not allocate which means left
10646 already in a pointer register, then
10647 if size > 0 && this could be used again
10648 we have to point it back to where it
10650 if ((AOP_SIZE (right) > 1 &&
10651 !OP_SYMBOL (result)->remat &&
10652 (OP_SYMBOL (result)->liveTo > ic->seq ||
10656 int size = AOP_SIZE (right) - 1;
10658 emitcode ("dec", "%s", rname);
10663 if (pi) pi->generated = 1;
10664 freeAsmop (result, NULL, ic, TRUE);
10665 freeAsmop (right, NULL, ic, TRUE);
10668 /*-----------------------------------------------------------------*/
10669 /* genPagedPointerSet - emitcode for Paged pointer put */
10670 /*-----------------------------------------------------------------*/
10672 genPagedPointerSet (operand * right,
10680 sym_link *retype, *letype;
10682 D (emitcode (";", "genPagedPointerSet"));
10684 retype = getSpec (operandType (right));
10685 letype = getSpec (operandType (result));
10687 aopOp (result, ic, FALSE);
10689 /* if the value is already in a pointer register
10690 then don't need anything more */
10691 if (!AOP_INPREG (AOP (result)))
10693 /* otherwise get a free pointer register */
10694 aop = newAsmop (0);
10695 preg = getFreePtr (ic, &aop, FALSE);
10696 emitcode ("mov", "%s,%s",
10698 aopGet (result, 0, FALSE, TRUE));
10699 rname = preg->name;
10702 rname = aopGet (result, 0, FALSE, FALSE);
10704 aopOp (right, ic, FALSE);
10706 /* if bitfield then unpack the bits */
10707 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10708 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10711 /* we have can just get the values */
10712 int size = AOP_SIZE (right);
10717 l = aopGet (right, offset, FALSE, TRUE);
10719 emitcode ("movx", "@%s,a", rname);
10722 emitcode ("inc", "%s", rname);
10728 /* now some housekeeping stuff */
10729 if (aop) /* we had to allocate for this iCode */
10732 aopPut (result, rname, 0);
10733 freeAsmop (NULL, aop, ic, TRUE);
10737 /* we did not allocate which means left
10738 already in a pointer register, then
10739 if size > 0 && this could be used again
10740 we have to point it back to where it
10742 if (AOP_SIZE (right) > 1 &&
10743 !OP_SYMBOL (result)->remat &&
10744 (OP_SYMBOL (result)->liveTo > ic->seq ||
10747 int size = AOP_SIZE (right) - 1;
10749 emitcode ("dec", "%s", rname);
10754 if (pi) pi->generated = 1;
10755 freeAsmop (result, NULL, ic, TRUE);
10756 freeAsmop (right, NULL, ic, TRUE);
10759 /*-----------------------------------------------------------------*/
10760 /* genFarPointerSet - set value from far space */
10761 /*-----------------------------------------------------------------*/
10763 genFarPointerSet (operand * right,
10764 operand * result, iCode * ic, iCode * pi)
10767 sym_link *retype = getSpec (operandType (right));
10768 sym_link *letype = getSpec (operandType (result));
10770 D(emitcode (";", "genFarPointerSet"));
10772 aopOp (result, ic, FALSE);
10773 loadDptrFromOperand (result, FALSE);
10775 /* so dptr now contains the address */
10776 aopOp (right, ic, FALSE);
10778 /* if bit then unpack */
10779 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10780 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10783 size = AOP_SIZE (right);
10788 char *l = aopGet (right, offset++, FALSE, FALSE);
10790 emitcode ("movx", "@dptr,a");
10792 emitcode ("inc", "dptr");
10795 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10796 aopPut (result, "dpl", 0);
10797 aopPut (result, "dph", 1);
10800 freeAsmop (result, NULL, ic, TRUE);
10801 freeAsmop (right, NULL, ic, TRUE);
10804 /*-----------------------------------------------------------------*/
10805 /* genGenPointerSet - set value from generic pointer space */
10806 /*-----------------------------------------------------------------*/
10808 genGenPointerSet (operand * right,
10809 operand * result, iCode * ic, iCode * pi)
10812 sym_link *retype = getSpec (operandType (right));
10813 sym_link *letype = getSpec (operandType (result));
10815 D (emitcode (";", "genGenPointerSet"));
10817 aopOp (result, ic, FALSE);
10818 loadDptrFromOperand (result, TRUE);
10820 /* so dptr now contains the address */
10821 aopOp (right, ic, FALSE);
10823 /* if bit then unpack */
10824 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10826 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10830 size = AOP_SIZE (right);
10835 char *l = aopGet (right, offset++, FALSE, FALSE);
10837 emitcode ("lcall", "__gptrput");
10839 emitcode ("inc", "dptr");
10843 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10844 aopPut (result, "dpl", 0);
10845 aopPut (result, "dph", 1);
10848 freeAsmop (result, NULL, ic, TRUE);
10849 freeAsmop (right, NULL, ic, TRUE);
10852 /*-----------------------------------------------------------------*/
10853 /* genPointerSet - stores the value into a pointer location */
10854 /*-----------------------------------------------------------------*/
10856 genPointerSet (iCode * ic, iCode *pi)
10858 operand *right, *result;
10859 sym_link *type, *etype;
10862 D (emitcode (";", "genPointerSet"));
10864 right = IC_RIGHT (ic);
10865 result = IC_RESULT (ic);
10867 /* depending on the type of pointer we need to
10868 move it to the correct pointer register */
10869 type = operandType (result);
10870 etype = getSpec (type);
10871 /* if left is of type of pointer then it is simple */
10872 if (IS_PTR (type) && !IS_FUNC (type->next))
10874 p_type = DCL_TYPE (type);
10878 /* we have to go by the storage class */
10879 p_type = PTR_TYPE (SPEC_OCLS (etype));
10882 /* special case when cast remat */
10883 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10884 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10885 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10886 type = operandType (result);
10887 p_type = DCL_TYPE (type);
10890 /* now that we have the pointer type we assign
10891 the pointer values */
10897 genNearPointerSet (right, result, ic, pi);
10901 genPagedPointerSet (right, result, ic, pi);
10905 genFarPointerSet (right, result, ic, pi);
10909 genGenPointerSet (right, result, ic, pi);
10913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10914 "genPointerSet: illegal pointer type");
10918 /*-----------------------------------------------------------------*/
10919 /* genIfx - generate code for Ifx statement */
10920 /*-----------------------------------------------------------------*/
10922 genIfx (iCode * ic, iCode * popIc)
10924 operand *cond = IC_COND (ic);
10928 D (emitcode (";", "genIfx"));
10930 aopOp (cond, ic, FALSE);
10932 /* get the value into acc */
10933 if (AOP_TYPE (cond) != AOP_CRY)
10940 if (AOP(cond)->aopu.aop_dir)
10941 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10944 /* the result is now in the accumulator or a directly addressable bit */
10945 freeAsmop (cond, NULL, ic, TRUE);
10947 /* if there was something to be popped then do it */
10951 /* if the condition is a bit variable */
10953 genIfxJump(ic, dup, NULL, NULL, NULL);
10954 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10955 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10956 else if (isbit && !IS_ITEMP (cond))
10957 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10959 genIfxJump (ic, "a", NULL, NULL, NULL);
10964 /*-----------------------------------------------------------------*/
10965 /* genAddrOf - generates code for address of */
10966 /*-----------------------------------------------------------------*/
10968 genAddrOf (iCode * ic)
10970 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10973 D (emitcode (";", "genAddrOf"));
10975 aopOp (IC_RESULT (ic), ic, FALSE);
10977 /* if the operand is on the stack then we
10978 need to get the stack offset of this
10982 /* if it has an offset then we need to compute it */
10985 int stack_offset = ((sym->stack < 0) ?
10986 ((char) (sym->stack - _G.nRegsSaved)) :
10987 ((char) sym->stack)) & 0xff;
10988 if ((abs(stack_offset) == 1) &&
10989 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10990 !isOperandVolatile (IC_RESULT (ic), FALSE))
10992 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10993 if (stack_offset > 0)
10994 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10996 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11000 emitcode ("mov", "a,%s", SYM_BP (sym));
11001 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11002 aopPut (IC_RESULT (ic), "a", 0);
11007 /* we can just move _bp */
11008 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11010 /* fill the result with zero */
11011 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11016 aopPut (IC_RESULT (ic), zero, offset++);
11021 /* object not on stack then we need the name */
11022 size = AOP_SIZE (IC_RESULT (ic));
11027 char s[SDCC_NAME_MAX];
11029 sprintf (s, "#(%s >> %d)",
11033 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11034 aopPut (IC_RESULT (ic), s, offset++);
11038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11042 /*-----------------------------------------------------------------*/
11043 /* genFarFarAssign - assignment when both are in far space */
11044 /*-----------------------------------------------------------------*/
11046 genFarFarAssign (operand * result, operand * right, iCode * ic)
11048 int size = AOP_SIZE (right);
11052 D (emitcode (";", "genFarFarAssign"));
11054 /* first push the right side on to the stack */
11057 l = aopGet (right, offset++, FALSE, FALSE);
11059 emitcode ("push", "acc");
11062 freeAsmop (right, NULL, ic, FALSE);
11063 /* now assign DPTR to result */
11064 aopOp (result, ic, FALSE);
11065 size = AOP_SIZE (result);
11068 emitcode ("pop", "acc");
11069 aopPut (result, "a", --offset);
11071 freeAsmop (result, NULL, ic, FALSE);
11074 /*-----------------------------------------------------------------*/
11075 /* genAssign - generate code for assignment */
11076 /*-----------------------------------------------------------------*/
11078 genAssign (iCode * ic)
11080 operand *result, *right;
11082 unsigned long lit = 0L;
11084 D (emitcode (";", "genAssign"));
11086 result = IC_RESULT (ic);
11087 right = IC_RIGHT (ic);
11089 /* if they are the same */
11090 if (operandsEqu (result, right) &&
11091 !isOperandVolatile (result, FALSE) &&
11092 !isOperandVolatile (right, FALSE))
11095 aopOp (right, ic, FALSE);
11097 /* special case both in far space */
11098 if (AOP_TYPE (right) == AOP_DPTR &&
11099 IS_TRUE_SYMOP (result) &&
11100 isOperandInFarSpace (result))
11102 genFarFarAssign (result, right, ic);
11106 aopOp (result, ic, TRUE);
11108 /* if they are the same registers */
11109 if (sameRegs (AOP (right), AOP (result)) &&
11110 !isOperandVolatile (result, FALSE) &&
11111 !isOperandVolatile (right, FALSE))
11114 /* if the result is a bit */
11115 if (AOP_TYPE (result) == AOP_CRY)
11117 assignBit (result, right);
11121 /* bit variables done */
11123 size = AOP_SIZE (result);
11125 if (AOP_TYPE (right) == AOP_LIT)
11126 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11129 (AOP_TYPE (result) != AOP_REG) &&
11130 (AOP_TYPE (right) == AOP_LIT) &&
11131 !IS_FLOAT (operandType (right)) &&
11134 while ((size) && (lit))
11137 aopGet (right, offset, FALSE, FALSE),
11143 /* And now fill the rest with zeros. */
11146 emitcode ("clr", "a");
11150 aopPut (result, "a", offset);
11159 aopGet (right, offset, FALSE, FALSE),
11166 freeAsmop (result, NULL, ic, TRUE);
11167 freeAsmop (right, NULL, ic, TRUE);
11170 /*-----------------------------------------------------------------*/
11171 /* genJumpTab - generates code for jump table */
11172 /*-----------------------------------------------------------------*/
11174 genJumpTab (iCode * ic)
11176 symbol *jtab,*jtablo,*jtabhi;
11178 unsigned int count;
11180 D (emitcode (";", "genJumpTab"));
11182 count = elementsInSet( IC_JTLABELS (ic) );
11186 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11187 if the switch argument is in a register.
11188 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11189 /* Peephole may not convert ljmp to sjmp or ret
11190 labelIsReturnOnly & labelInRange must check
11191 currPl->ic->op != JUMPTABLE */
11192 aopOp (IC_JTCOND (ic), ic, FALSE);
11193 /* get the condition into accumulator */
11194 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11196 /* multiply by three */
11197 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11199 emitcode ("mov", "b,#3");
11200 emitcode ("mul", "ab");
11204 emitcode ("add", "a,acc");
11205 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11207 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11209 jtab = newiTempLabel (NULL);
11210 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11211 emitcode ("jmp", "@a+dptr");
11213 /* now generate the jump labels */
11214 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11215 jtab = setNextItem (IC_JTLABELS (ic)))
11216 emitcode ("ljmp", "%05d$", jtab->key + 100);
11220 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11221 if the switch argument is in a register.
11222 For n>6 this algorithm may be more compact */
11223 jtablo = newiTempLabel (NULL);
11224 jtabhi = newiTempLabel (NULL);
11226 /* get the condition into accumulator.
11227 Using b as temporary storage, if register push/pop is needed */
11228 aopOp (IC_JTCOND (ic), ic, FALSE);
11229 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11230 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11231 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11233 // (MB) what if B is in use???
11234 wassertl(!BINUSE, "B was in use");
11235 emitcode ("mov", "b,%s", l);
11238 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11242 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11243 emitcode ("movc", "a,@a+pc");
11244 emitcode ("push", "acc");
11247 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11248 emitcode ("movc", "a,@a+pc");
11249 emitcode ("push", "acc");
11253 /* this scales up to n<=255, but needs two more bytes
11254 and changes dptr */
11255 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11256 emitcode ("movc", "a,@a+dptr");
11257 emitcode ("push", "acc");
11260 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11261 emitcode ("movc", "a,@a+dptr");
11262 emitcode ("push", "acc");
11265 emitcode ("ret", "");
11267 /* now generate jump table, LSB */
11268 emitLabel (jtablo);
11269 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11270 jtab = setNextItem (IC_JTLABELS (ic)))
11271 emitcode (".db", "%05d$", jtab->key + 100);
11273 /* now generate jump table, MSB */
11274 emitLabel (jtabhi);
11275 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11276 jtab = setNextItem (IC_JTLABELS (ic)))
11277 emitcode (".db", "%05d$>>8", jtab->key + 100);
11281 /*-----------------------------------------------------------------*/
11282 /* genCast - gen code for casting */
11283 /*-----------------------------------------------------------------*/
11285 genCast (iCode * ic)
11287 operand *result = IC_RESULT (ic);
11288 sym_link *ctype = operandType (IC_LEFT (ic));
11289 sym_link *rtype = operandType (IC_RIGHT (ic));
11290 operand *right = IC_RIGHT (ic);
11293 D (emitcode (";", "genCast"));
11295 /* if they are equivalent then do nothing */
11296 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11299 aopOp (right, ic, FALSE);
11300 aopOp (result, ic, FALSE);
11302 /* if the result is a bit (and not a bitfield) */
11303 if (IS_BIT (OP_SYMBOL (result)->type))
11305 assignBit (result, right);
11309 /* if they are the same size : or less */
11310 if (AOP_SIZE (result) <= AOP_SIZE (right))
11313 /* if they are in the same place */
11314 if (sameRegs (AOP (right), AOP (result)))
11317 /* if they in different places then copy */
11318 size = AOP_SIZE (result);
11323 aopGet (right, offset, FALSE, FALSE),
11330 /* if the result is of type pointer */
11331 if (IS_PTR (ctype))
11335 sym_link *type = operandType (right);
11336 sym_link *etype = getSpec (type);
11338 /* pointer to generic pointer */
11339 if (IS_GENPTR (ctype))
11343 p_type = DCL_TYPE (type);
11347 if (SPEC_SCLS(etype)==S_REGISTER) {
11348 // let's assume it is a generic pointer
11351 /* we have to go by the storage class */
11352 p_type = PTR_TYPE (SPEC_OCLS (etype));
11356 /* the first two bytes are known */
11357 size = GPTRSIZE - 1;
11362 aopGet (right, offset, FALSE, FALSE),
11366 /* the last byte depending on type */
11368 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11373 // pointerTypeToGPByte will have bitched.
11377 sprintf(gpValStr, "#0x%x", gpVal);
11378 aopPut (result, gpValStr, GPTRSIZE - 1);
11383 /* just copy the pointers */
11384 size = AOP_SIZE (result);
11389 aopGet (right, offset, FALSE, FALSE),
11396 /* so we now know that the size of destination is greater
11397 than the size of the source */
11398 /* we move to result for the size of source */
11399 size = AOP_SIZE (right);
11404 aopGet (right, offset, FALSE, FALSE),
11409 /* now depending on the sign of the source && destination */
11410 size = AOP_SIZE (result) - AOP_SIZE (right);
11411 /* if unsigned or not an integral type */
11412 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11415 aopPut (result, zero, offset++);
11419 /* we need to extend the sign :{ */
11420 char *l = aopGet (right, AOP_SIZE (right) - 1,
11423 emitcode ("rlc", "a");
11424 emitcode ("subb", "a,acc");
11426 aopPut (result, "a", offset++);
11429 /* we are done hurray !!!! */
11432 freeAsmop (result, NULL, ic, TRUE);
11433 freeAsmop (right, NULL, ic, TRUE);
11436 /*-----------------------------------------------------------------*/
11437 /* genDjnz - generate decrement & jump if not zero instrucion */
11438 /*-----------------------------------------------------------------*/
11440 genDjnz (iCode * ic, iCode * ifx)
11442 symbol *lbl, *lbl1;
11446 /* if the if condition has a false label
11447 then we cannot save */
11448 if (IC_FALSE (ifx))
11451 /* if the minus is not of the form a = a - 1 */
11452 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11453 !IS_OP_LITERAL (IC_RIGHT (ic)))
11456 if (operandLitValue (IC_RIGHT (ic)) != 1)
11459 /* if the size of this greater than one then no
11461 if (getSize (operandType (IC_RESULT (ic))) > 1)
11464 /* otherwise we can save BIG */
11466 D (emitcode (";", "genDjnz"));
11468 lbl = newiTempLabel (NULL);
11469 lbl1 = newiTempLabel (NULL);
11471 aopOp (IC_RESULT (ic), ic, FALSE);
11473 if (AOP_NEEDSACC(IC_RESULT(ic)))
11475 /* If the result is accessed indirectly via
11476 * the accumulator, we must explicitly write
11477 * it back after the decrement.
11479 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11481 if (strcmp(rByte, "a"))
11483 /* Something is hopelessly wrong */
11484 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11485 __FILE__, __LINE__);
11486 /* We can just give up; the generated code will be inefficient,
11487 * but what the hey.
11489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11492 emitcode ("dec", "%s", rByte);
11493 aopPut (IC_RESULT (ic), rByte, 0);
11494 emitcode ("jnz", "%05d$", lbl->key + 100);
11496 else if (IS_AOP_PREG (IC_RESULT (ic)))
11498 emitcode ("dec", "%s",
11499 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11500 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11501 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11502 ifx->generated = 1;
11503 emitcode ("jnz", "%05d$", lbl->key + 100);
11507 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11510 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11512 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11515 if (!ifx->generated)
11516 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11517 ifx->generated = 1;
11521 /*-----------------------------------------------------------------*/
11522 /* genReceive - generate code for a receive iCode */
11523 /*-----------------------------------------------------------------*/
11525 genReceive (iCode * ic)
11527 int size = getSize (operandType (IC_RESULT (ic)));
11530 D (emitcode (";", "genReceive"));
11532 if (ic->argreg == 1)
11533 { /* first parameter */
11534 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11535 isOperandInPagedSpace (IC_RESULT (ic))) &&
11536 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11537 IS_TRUE_SYMOP (IC_RESULT (ic))))
11540 int receivingA = 0;
11543 for (offset = 0; offset<size; offset++)
11544 if (!strcmp (fReturn[offset], "a"))
11549 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11551 for (offset = size-1; offset>0; offset--)
11552 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11553 emitcode("mov","a,%s", fReturn[0]);
11555 aopOp (IC_RESULT (ic), ic, FALSE);
11557 aopPut (IC_RESULT (ic), "a", offset);
11558 for (offset = 1; offset<size; offset++)
11559 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11565 if (getTempRegs(tempRegs, size, ic))
11567 for (offset = 0; offset<size; offset++)
11568 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11569 aopOp (IC_RESULT (ic), ic, FALSE);
11570 for (offset = 0; offset<size; offset++)
11571 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11576 offset = fReturnSizeMCS51 - size;
11579 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11580 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11583 aopOp (IC_RESULT (ic), ic, FALSE);
11584 size = AOP_SIZE (IC_RESULT (ic));
11588 emitcode ("pop", "acc");
11589 aopPut (IC_RESULT (ic), "a", offset++);
11595 aopOp (IC_RESULT (ic), ic, FALSE);
11597 assignResultValue (IC_RESULT (ic), NULL);
11600 else if (ic->argreg > 12)
11601 { /* bit parameters */
11602 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11604 aopOp (IC_RESULT (ic), ic, FALSE);
11605 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11606 outBitC(IC_RESULT (ic));
11610 { /* other parameters */
11612 aopOp (IC_RESULT (ic), ic, FALSE);
11613 rb1off = ic->argreg;
11616 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11621 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11624 /*-----------------------------------------------------------------*/
11625 /* genDummyRead - generate code for dummy read of volatiles */
11626 /*-----------------------------------------------------------------*/
11628 genDummyRead (iCode * ic)
11633 D (emitcode(";", "genDummyRead"));
11635 op = IC_RIGHT (ic);
11636 if (op && IS_SYMOP (op))
11638 aopOp (op, ic, FALSE);
11640 /* if the result is a bit */
11641 if (AOP_TYPE (op) == AOP_CRY)
11642 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11645 /* bit variables done */
11647 size = AOP_SIZE (op);
11651 MOVA (aopGet (op, offset, FALSE, FALSE));
11656 freeAsmop (op, NULL, ic, TRUE);
11660 if (op && IS_SYMOP (op))
11662 aopOp (op, ic, FALSE);
11664 /* if the result is a bit */
11665 if (AOP_TYPE (op) == AOP_CRY)
11666 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11669 /* bit variables done */
11671 size = AOP_SIZE (op);
11675 MOVA (aopGet (op, offset, FALSE, FALSE));
11680 freeAsmop (op, NULL, ic, TRUE);
11684 /*-----------------------------------------------------------------*/
11685 /* genCritical - generate code for start of a critical sequence */
11686 /*-----------------------------------------------------------------*/
11688 genCritical (iCode *ic)
11690 symbol *tlbl = newiTempLabel (NULL);
11692 D (emitcode(";", "genCritical"));
11694 if (IC_RESULT (ic))
11696 aopOp (IC_RESULT (ic), ic, TRUE);
11697 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11698 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11699 aopPut (IC_RESULT (ic), zero, 0);
11701 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11705 emitcode ("setb", "c");
11706 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11707 emitcode ("clr", "c");
11709 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11713 /*-----------------------------------------------------------------*/
11714 /* genEndCritical - generate code for end of a critical sequence */
11715 /*-----------------------------------------------------------------*/
11717 genEndCritical (iCode *ic)
11719 D(emitcode(";", "genEndCritical"));
11723 aopOp (IC_RIGHT (ic), ic, FALSE);
11724 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11726 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11727 emitcode ("mov", "ea,c");
11731 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11732 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11733 emitcode ("rrc", "a");
11734 emitcode ("mov", "ea,c");
11736 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11740 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11741 emitcode ("mov", "ea,c");
11745 /*-----------------------------------------------------------------*/
11746 /* gen51Code - generate code for 8051 based controllers */
11747 /*-----------------------------------------------------------------*/
11749 gen51Code (iCode * lic)
11753 /* int cseq = 0; */
11755 _G.currentFunc = NULL;
11756 lineHead = lineCurr = NULL;
11758 /* print the allocation information */
11759 if (allocInfo && currFunc)
11760 printAllocInfo (currFunc, codeOutBuf);
11761 /* if debug information required */
11762 if (options.debug && currFunc)
11764 debugFile->writeFunction (currFunc, lic);
11766 /* stack pointer name */
11767 if (options.useXstack)
11773 for (ic = lic; ic; ic = ic->next)
11775 _G.current_iCode = ic;
11777 if (ic->lineno && cln != ic->lineno)
11781 debugFile->writeCLine (ic);
11783 if (!options.noCcodeInAsm) {
11784 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11785 printCLine(ic->filename, ic->lineno));
11790 if (ic->seqPoint && ic->seqPoint != cseq)
11792 emitcode (";", "sequence point %d", ic->seqPoint);
11793 cseq = ic->seqPoint;
11796 if (options.iCodeInAsm) {
11797 char regsInUse[80];
11802 for (i=0; i<8; i++) {
11803 sprintf (®sInUse[i],
11804 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11807 strcpy (regsInUse, "--------");
11808 for (i=0; i < 8; i++) {
11809 if (bitVectBitValue (ic->rMask, i))
11811 int offset = regs8051[i].offset;
11812 regsInUse[offset] = offset + '0'; /* show rMask */
11816 iLine = printILine(ic);
11817 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11820 /* if the result is marked as
11821 spilt and rematerializable or code for
11822 this has already been generated then
11824 if (resultRemat (ic) || ic->generated)
11827 /* depending on the operation */
11847 /* IPOP happens only when trying to restore a
11848 spilt live range, if there is an ifx statement
11849 following this pop then the if statement might
11850 be using some of the registers being popped which
11851 would destory the contents of the register so
11852 we need to check for this condition and handle it */
11854 ic->next->op == IFX &&
11855 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11856 genIfx (ic->next, ic);
11874 genEndFunction (ic);
11894 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11911 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11915 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11922 /* note these two are xlated by algebraic equivalence
11923 in decorateType() in SDCCast.c */
11924 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11925 "got '>=' or '<=' shouldn't have come here");
11929 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11941 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11945 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11949 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11985 genRightShift (ic);
11988 case GET_VALUE_AT_ADDRESS:
11990 hasInc (IC_LEFT (ic), ic,
11991 getSize (operandType (IC_RESULT (ic)))),
11992 ifxForOp (IC_RESULT (ic), ic) );
11996 if (POINTER_SET (ic))
11998 hasInc (IC_RESULT (ic), ic,
11999 getSize (operandType (IC_RIGHT (ic)))));
12025 addSet (&_G.sendSet, ic);
12028 case DUMMY_READ_VOLATILE:
12037 genEndCritical (ic);
12049 _G.current_iCode = NULL;
12051 /* now we are ready to call the
12052 peep hole optimizer */
12053 if (!options.nopeep)
12054 peepHole (&lineHead);
12056 /* now do the actual printing */
12057 printLine (lineHead, codeOutBuf);