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;
7685 D (emitcode (";", "genInline"));
7687 _G.inLine += (!options.asmpeep);
7689 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7691 /* emit each line as a code */
7702 /* Add \n for labels, not dirs such as c:\mydir */
7703 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7717 /* emitcode("",buffer); */
7718 _G.inLine -= (!options.asmpeep);
7721 /*-----------------------------------------------------------------*/
7722 /* genRRC - rotate right with carry */
7723 /*-----------------------------------------------------------------*/
7727 operand *left, *result;
7731 D (emitcode (";", "genRRC"));
7733 /* rotate right with carry */
7734 left = IC_LEFT (ic);
7735 result = IC_RESULT (ic);
7736 aopOp (left, ic, FALSE);
7737 aopOp (result, ic, FALSE);
7739 /* move it to the result */
7740 size = AOP_SIZE (result);
7742 if (size == 1) { /* special case for 1 byte */
7743 l = aopGet (left, offset, FALSE, FALSE);
7745 emitcode ("rr", "a");
7748 /* no need to clear carry, bit7 will be written later */
7751 l = aopGet (left, offset, FALSE, FALSE);
7753 emitcode ("rrc", "a");
7754 if (AOP_SIZE (result) > 1)
7755 aopPut (result, "a", offset--);
7757 /* now we need to put the carry into the
7758 highest order byte of the result */
7759 if (AOP_SIZE (result) > 1)
7761 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7764 emitcode ("mov", "acc.7,c");
7766 aopPut (result, "a", AOP_SIZE (result) - 1);
7767 freeAsmop (result, NULL, ic, TRUE);
7768 freeAsmop (left, NULL, ic, TRUE);
7771 /*-----------------------------------------------------------------*/
7772 /* genRLC - generate code for rotate left with carry */
7773 /*-----------------------------------------------------------------*/
7777 operand *left, *result;
7781 D (emitcode (";", "genRLC"));
7783 /* rotate right with carry */
7784 left = IC_LEFT (ic);
7785 result = IC_RESULT (ic);
7786 aopOp (left, ic, FALSE);
7787 aopOp (result, ic, FALSE);
7789 /* move it to the result */
7790 size = AOP_SIZE (result);
7794 l = aopGet (left, offset, FALSE, FALSE);
7796 if (size == 0) { /* special case for 1 byte */
7800 emitcode("rlc","a"); /* bit0 will be written later */
7801 if (AOP_SIZE (result) > 1)
7803 aopPut (result, "a", offset++);
7808 l = aopGet (left, offset, FALSE, FALSE);
7810 emitcode ("rlc", "a");
7811 if (AOP_SIZE (result) > 1)
7812 aopPut (result, "a", offset++);
7815 /* now we need to put the carry into the
7816 highest order byte of the result */
7817 if (AOP_SIZE (result) > 1)
7819 l = aopGet (result, 0, FALSE, FALSE);
7822 emitcode ("mov", "acc.0,c");
7824 aopPut (result, "a", 0);
7825 freeAsmop (result, NULL, ic, TRUE);
7826 freeAsmop (left, NULL, ic, TRUE);
7829 /*-----------------------------------------------------------------*/
7830 /* genGetHbit - generates code get highest order bit */
7831 /*-----------------------------------------------------------------*/
7833 genGetHbit (iCode * ic)
7835 operand *left, *result;
7837 D (emitcode (";", "genGetHbit"));
7839 left = IC_LEFT (ic);
7840 result = IC_RESULT (ic);
7841 aopOp (left, ic, FALSE);
7842 aopOp (result, ic, FALSE);
7844 /* get the highest order byte into a */
7845 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7846 if (AOP_TYPE (result) == AOP_CRY)
7848 emitcode ("rlc", "a");
7853 emitcode ("rl", "a");
7854 emitcode ("anl", "a,#0x01");
7858 freeAsmop (result, NULL, ic, TRUE);
7859 freeAsmop (left, NULL, ic, TRUE);
7862 /*-----------------------------------------------------------------*/
7863 /* genGetAbit - generates code get a single bit */
7864 /*-----------------------------------------------------------------*/
7866 genGetAbit (iCode * ic)
7868 operand *left, *right, *result;
7871 D (emitcode (";", "genGetAbit"));
7873 left = IC_LEFT (ic);
7874 right = IC_RIGHT (ic);
7875 result = IC_RESULT (ic);
7876 aopOp (left, ic, FALSE);
7877 aopOp (right, ic, FALSE);
7878 aopOp (result, ic, FALSE);
7880 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7882 /* get the needed byte into a */
7883 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7885 if (AOP_TYPE (result) == AOP_CRY)
7888 emitcode ("rlc", "a");
7889 else if ((shCount) == 0)
7890 emitcode ("rrc", "a");
7892 emitcode ("mov", "c,acc[%d]", shCount);
7900 emitcode ("rr", "a");
7903 emitcode ("rr", "a");
7906 emitcode ("anl", "a,#0x01");
7910 emitcode ("mov", "c,acc[%d]", shCount);
7911 emitcode ("clr", "a");
7912 emitcode ("rlc", "a");
7915 emitcode ("swap", "a");
7916 emitcode ("anl", "a,#0x01");
7919 emitcode ("rl", "a");
7922 emitcode ("rl", "a");
7923 emitcode ("anl", "a,#0x01");
7929 freeAsmop (result, NULL, ic, TRUE);
7930 freeAsmop (right, NULL, ic, TRUE);
7931 freeAsmop (left, NULL, ic, TRUE);
7934 /*-----------------------------------------------------------------*/
7935 /* genGetByte - generates code get a single byte */
7936 /*-----------------------------------------------------------------*/
7938 genGetByte (iCode * ic)
7940 operand *left, *right, *result;
7943 D (emitcode (";", "genGetByte"));
7945 left = IC_LEFT (ic);
7946 right = IC_RIGHT (ic);
7947 result = IC_RESULT (ic);
7948 aopOp (left, ic, FALSE);
7949 aopOp (right, ic, FALSE);
7950 aopOp (result, ic, FALSE);
7952 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7954 aopGet (left, offset, FALSE, FALSE),
7957 freeAsmop (result, NULL, ic, TRUE);
7958 freeAsmop (right, NULL, ic, TRUE);
7959 freeAsmop (left, NULL, ic, TRUE);
7962 /*-----------------------------------------------------------------*/
7963 /* genGetWord - generates code get two bytes */
7964 /*-----------------------------------------------------------------*/
7966 genGetWord (iCode * ic)
7968 operand *left, *right, *result;
7971 D (emitcode (";", "genGetWord"));
7973 left = IC_LEFT (ic);
7974 right = IC_RIGHT (ic);
7975 result = IC_RESULT (ic);
7976 aopOp (left, ic, FALSE);
7977 aopOp (right, ic, FALSE);
7978 aopOp (result, ic, FALSE);
7980 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7982 aopGet (left, offset, FALSE, FALSE),
7985 aopGet (left, offset+1, FALSE, FALSE),
7988 freeAsmop (result, NULL, ic, TRUE);
7989 freeAsmop (right, NULL, ic, TRUE);
7990 freeAsmop (left, NULL, ic, TRUE);
7993 /*-----------------------------------------------------------------*/
7994 /* genSwap - generates code to swap nibbles or bytes */
7995 /*-----------------------------------------------------------------*/
7997 genSwap (iCode * ic)
7999 operand *left, *result;
8001 D(emitcode (";", "genSwap"));
8003 left = IC_LEFT (ic);
8004 result = IC_RESULT (ic);
8005 aopOp (left, ic, FALSE);
8006 aopOp (result, ic, FALSE);
8008 switch (AOP_SIZE (left))
8010 case 1: /* swap nibbles in byte */
8011 MOVA (aopGet (left, 0, FALSE, FALSE));
8012 emitcode ("swap", "a");
8013 aopPut (result, "a", 0);
8015 case 2: /* swap bytes in word */
8016 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8018 MOVA (aopGet (left, 0, FALSE, FALSE));
8019 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8020 aopPut (result, "a", 1);
8022 else if (operandsEqu (left, result))
8025 bool pushedB = FALSE, leftInB = FALSE;
8027 MOVA (aopGet (left, 0, FALSE, FALSE));
8028 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8031 emitcode ("mov", "b,a");
8035 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8036 aopPut (result, reg, 1);
8043 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8044 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8048 wassertl(FALSE, "unsupported SWAP operand size");
8051 freeAsmop (result, NULL, ic, TRUE);
8052 freeAsmop (left, NULL, ic, TRUE);
8055 /*-----------------------------------------------------------------*/
8056 /* AccRol - rotate left accumulator by known count */
8057 /*-----------------------------------------------------------------*/
8059 AccRol (int shCount)
8061 shCount &= 0x0007; // shCount : 0..7
8068 emitcode ("rl", "a");
8071 emitcode ("rl", "a");
8072 emitcode ("rl", "a");
8075 emitcode ("swap", "a");
8076 emitcode ("rr", "a");
8079 emitcode ("swap", "a");
8082 emitcode ("swap", "a");
8083 emitcode ("rl", "a");
8086 emitcode ("rr", "a");
8087 emitcode ("rr", "a");
8090 emitcode ("rr", "a");
8095 /*-----------------------------------------------------------------*/
8096 /* AccLsh - left shift accumulator by known count */
8097 /*-----------------------------------------------------------------*/
8099 AccLsh (int shCount)
8104 emitcode ("add", "a,acc");
8105 else if (shCount == 2)
8107 emitcode ("add", "a,acc");
8108 emitcode ("add", "a,acc");
8112 /* rotate left accumulator */
8114 /* and kill the lower order bits */
8115 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8120 /*-----------------------------------------------------------------*/
8121 /* AccRsh - right shift accumulator by known count */
8122 /*-----------------------------------------------------------------*/
8124 AccRsh (int shCount)
8131 emitcode ("rrc", "a");
8135 /* rotate right accumulator */
8136 AccRol (8 - shCount);
8137 /* and kill the higher order bits */
8138 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8143 /*-----------------------------------------------------------------*/
8144 /* AccSRsh - signed right shift accumulator by known count */
8145 /*-----------------------------------------------------------------*/
8147 AccSRsh (int shCount)
8154 emitcode ("mov", "c,acc.7");
8155 emitcode ("rrc", "a");
8157 else if (shCount == 2)
8159 emitcode ("mov", "c,acc.7");
8160 emitcode ("rrc", "a");
8161 emitcode ("mov", "c,acc.7");
8162 emitcode ("rrc", "a");
8166 tlbl = newiTempLabel (NULL);
8167 /* rotate right accumulator */
8168 AccRol (8 - shCount);
8169 /* and kill the higher order bits */
8170 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8171 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8172 emitcode ("orl", "a,#0x%02x",
8173 (unsigned char) ~SRMask[shCount]);
8179 /*-----------------------------------------------------------------*/
8180 /* shiftR1Left2Result - shift right one byte from left to result */
8181 /*-----------------------------------------------------------------*/
8183 shiftR1Left2Result (operand * left, int offl,
8184 operand * result, int offr,
8185 int shCount, int sign)
8187 MOVA (aopGet (left, offl, FALSE, FALSE));
8188 /* shift right accumulator */
8193 aopPut (result, "a", offr);
8196 /*-----------------------------------------------------------------*/
8197 /* shiftL1Left2Result - shift left one byte from left to result */
8198 /*-----------------------------------------------------------------*/
8200 shiftL1Left2Result (operand * left, int offl,
8201 operand * result, int offr, int shCount)
8204 l = aopGet (left, offl, FALSE, FALSE);
8206 /* shift left accumulator */
8208 aopPut (result, "a", offr);
8211 /*-----------------------------------------------------------------*/
8212 /* movLeft2Result - move byte from left to result */
8213 /*-----------------------------------------------------------------*/
8215 movLeft2Result (operand * left, int offl,
8216 operand * result, int offr, int sign)
8219 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8221 l = aopGet (left, offl, FALSE, FALSE);
8223 if (*l == '@' && (IS_AOP_PREG (result)))
8225 emitcode ("mov", "a,%s", l);
8226 aopPut (result, "a", offr);
8232 aopPut (result, l, offr);
8236 /* MSB sign in acc.7 ! */
8237 if (getDataSize (left) == offl + 1)
8240 aopPut (result, "a", offr);
8247 /*-----------------------------------------------------------------*/
8248 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8249 /*-----------------------------------------------------------------*/
8253 emitcode ("rrc", "a");
8254 emitcode ("xch", "a,%s", x);
8255 emitcode ("rrc", "a");
8256 emitcode ("xch", "a,%s", x);
8259 /*-----------------------------------------------------------------*/
8260 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8261 /*-----------------------------------------------------------------*/
8265 emitcode ("xch", "a,%s", x);
8266 emitcode ("rlc", "a");
8267 emitcode ("xch", "a,%s", x);
8268 emitcode ("rlc", "a");
8271 /*-----------------------------------------------------------------*/
8272 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8273 /*-----------------------------------------------------------------*/
8277 emitcode ("xch", "a,%s", x);
8278 emitcode ("add", "a,acc");
8279 emitcode ("xch", "a,%s", x);
8280 emitcode ("rlc", "a");
8283 /*-----------------------------------------------------------------*/
8284 /* AccAXLsh - left shift a:x by known count (0..7) */
8285 /*-----------------------------------------------------------------*/
8287 AccAXLsh (char *x, int shCount)
8302 case 5: // AAAAABBB:CCCCCDDD
8304 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8306 emitcode ("anl", "a,#0x%02x",
8307 SLMask[shCount]); // BBB00000:CCCCCDDD
8309 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8311 AccRol (shCount); // DDDCCCCC:BBB00000
8313 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8315 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8317 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8319 emitcode ("anl", "a,#0x%02x",
8320 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8322 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8324 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8327 case 6: // AAAAAABB:CCCCCCDD
8328 emitcode ("anl", "a,#0x%02x",
8329 SRMask[shCount]); // 000000BB:CCCCCCDD
8330 emitcode ("mov", "c,acc.0"); // c = B
8331 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8333 AccAXRrl1 (x); // BCCCCCCD:D000000B
8334 AccAXRrl1 (x); // BBCCCCCC:DD000000
8336 emitcode("rrc","a");
8337 emitcode("xch","a,%s", x);
8338 emitcode("rrc","a");
8339 emitcode("mov","c,acc.0"); //<< get correct bit
8340 emitcode("xch","a,%s", x);
8342 emitcode("rrc","a");
8343 emitcode("xch","a,%s", x);
8344 emitcode("rrc","a");
8345 emitcode("xch","a,%s", x);
8348 case 7: // a:x <<= 7
8350 emitcode ("anl", "a,#0x%02x",
8351 SRMask[shCount]); // 0000000B:CCCCCCCD
8353 emitcode ("mov", "c,acc.0"); // c = B
8355 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8357 AccAXRrl1 (x); // BCCCCCCC:D0000000
8365 /*-----------------------------------------------------------------*/
8366 /* AccAXRsh - right shift a:x known count (0..7) */
8367 /*-----------------------------------------------------------------*/
8369 AccAXRsh (char *x, int shCount)
8377 AccAXRrl1 (x); // 0->a:x
8382 AccAXRrl1 (x); // 0->a:x
8385 AccAXRrl1 (x); // 0->a:x
8390 case 5: // AAAAABBB:CCCCCDDD = a:x
8392 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8394 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8396 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8398 emitcode ("anl", "a,#0x%02x",
8399 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8401 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8403 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8405 emitcode ("anl", "a,#0x%02x",
8406 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8408 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8410 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8412 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8415 case 6: // AABBBBBB:CCDDDDDD
8417 emitcode ("mov", "c,acc.7");
8418 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8420 emitcode ("mov", "c,acc.7");
8421 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8423 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8425 emitcode ("anl", "a,#0x%02x",
8426 SRMask[shCount]); // 000000AA:BBBBBBCC
8429 case 7: // ABBBBBBB:CDDDDDDD
8431 emitcode ("mov", "c,acc.7"); // c = A
8433 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8435 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8437 emitcode ("anl", "a,#0x%02x",
8438 SRMask[shCount]); // 0000000A:BBBBBBBC
8446 /*-----------------------------------------------------------------*/
8447 /* AccAXRshS - right shift signed a:x known count (0..7) */
8448 /*-----------------------------------------------------------------*/
8450 AccAXRshS (char *x, int shCount)
8458 emitcode ("mov", "c,acc.7");
8459 AccAXRrl1 (x); // s->a:x
8463 emitcode ("mov", "c,acc.7");
8464 AccAXRrl1 (x); // s->a:x
8466 emitcode ("mov", "c,acc.7");
8467 AccAXRrl1 (x); // s->a:x
8472 case 5: // AAAAABBB:CCCCCDDD = a:x
8474 tlbl = newiTempLabel (NULL);
8475 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8477 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8479 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8481 emitcode ("anl", "a,#0x%02x",
8482 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8484 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8486 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8488 emitcode ("anl", "a,#0x%02x",
8489 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8491 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8493 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8495 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8497 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8498 emitcode ("orl", "a,#0x%02x",
8499 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8502 break; // SSSSAAAA:BBBCCCCC
8504 case 6: // AABBBBBB:CCDDDDDD
8506 tlbl = newiTempLabel (NULL);
8507 emitcode ("mov", "c,acc.7");
8508 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8510 emitcode ("mov", "c,acc.7");
8511 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8513 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8515 emitcode ("anl", "a,#0x%02x",
8516 SRMask[shCount]); // 000000AA:BBBBBBCC
8518 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8519 emitcode ("orl", "a,#0x%02x",
8520 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8524 case 7: // ABBBBBBB:CDDDDDDD
8526 tlbl = newiTempLabel (NULL);
8527 emitcode ("mov", "c,acc.7"); // c = A
8529 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8531 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8533 emitcode ("anl", "a,#0x%02x",
8534 SRMask[shCount]); // 0000000A:BBBBBBBC
8536 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8537 emitcode ("orl", "a,#0x%02x",
8538 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8547 /*-----------------------------------------------------------------*/
8548 /* shiftL2Left2Result - shift left two bytes from left to result */
8549 /*-----------------------------------------------------------------*/
8551 shiftL2Left2Result (operand * left, int offl,
8552 operand * result, int offr, int shCount)
8555 bool pushedB = FALSE;
8558 if (sameRegs (AOP (result), AOP (left)) &&
8559 ((offl + MSB16) == offr))
8561 /* don't crash result[offr] */
8562 MOVA (aopGet (left, offl, FALSE, FALSE));
8563 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8564 usedB = !strncmp(x, "b", 1);
8566 else if (aopGetUsesAcc (result, offr))
8568 movLeft2Result (left, offl, result, offr, 0);
8571 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8572 MOVA (aopGet (result, offr, FALSE, FALSE));
8573 emitcode ("xch", "a,b");
8578 movLeft2Result (left, offl, result, offr, 0);
8579 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8580 x = aopGet (result, offr, FALSE, FALSE);
8582 /* ax << shCount (x = lsb(result)) */
8583 AccAXLsh (x, shCount);
8586 emitcode ("xch", "a,b");
8587 aopPut (result, "a", offr);
8588 aopPut (result, "b", offr + MSB16);
8593 aopPut (result, "a", offr + MSB16);
8598 /*-----------------------------------------------------------------*/
8599 /* shiftR2Left2Result - shift right two bytes from left to result */
8600 /*-----------------------------------------------------------------*/
8602 shiftR2Left2Result (operand * left, int offl,
8603 operand * result, int offr,
8604 int shCount, int sign)
8607 bool pushedB = FALSE;
8610 if (sameRegs (AOP (result), AOP (left)) &&
8611 ((offl + MSB16) == offr))
8613 /* don't crash result[offr] */
8614 MOVA (aopGet (left, offl, FALSE, FALSE));
8615 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8616 usedB = !strncmp(x, "b", 1);
8618 else if (aopGetUsesAcc (result, offr))
8620 movLeft2Result (left, offl, result, offr, 0);
8623 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8624 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8629 movLeft2Result (left, offl, result, offr, 0);
8630 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8631 x = aopGet (result, offr, FALSE, FALSE);
8633 /* a:x >> shCount (x = lsb(result)) */
8635 AccAXRshS (x, shCount);
8637 AccAXRsh (x, shCount);
8640 emitcode ("xch", "a,b");
8641 aopPut (result, "a", offr);
8642 emitcode ("xch", "a,b");
8645 if (getDataSize (result) > 1)
8646 aopPut (result, "a", offr + MSB16);
8649 /*-----------------------------------------------------------------*/
8650 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8651 /*-----------------------------------------------------------------*/
8653 shiftLLeftOrResult (operand * left, int offl,
8654 operand * result, int offr, int shCount)
8656 MOVA (aopGet (left, offl, FALSE, FALSE));
8657 /* shift left accumulator */
8659 /* or with result */
8660 if (aopGetUsesAcc (result, offr))
8662 emitcode ("xch", "a,b");
8663 MOVA (aopGet (result, offr, FALSE, FALSE));
8664 emitcode ("orl", "a,b");
8668 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8670 /* back to result */
8671 aopPut (result, "a", offr);
8674 /*-----------------------------------------------------------------*/
8675 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8676 /*-----------------------------------------------------------------*/
8678 shiftRLeftOrResult (operand * left, int offl,
8679 operand * result, int offr, int shCount)
8681 MOVA (aopGet (left, offl, FALSE, FALSE));
8682 /* shift right accumulator */
8684 /* or with result */
8685 if (aopGetUsesAcc(result, offr))
8687 emitcode ("xch", "a,b");
8688 MOVA (aopGet (result, offr, FALSE, FALSE));
8689 emitcode ("orl", "a,b");
8693 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8695 /* back to result */
8696 aopPut (result, "a", offr);
8699 /*-----------------------------------------------------------------*/
8700 /* genlshOne - left shift a one byte quantity by known count */
8701 /*-----------------------------------------------------------------*/
8703 genlshOne (operand * result, operand * left, int shCount)
8705 D (emitcode (";", "genlshOne"));
8707 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8710 /*-----------------------------------------------------------------*/
8711 /* genlshTwo - left shift two bytes by known amount != 0 */
8712 /*-----------------------------------------------------------------*/
8714 genlshTwo (operand * result, operand * left, int shCount)
8718 D (emitcode (";", "genlshTwo"));
8720 size = getDataSize (result);
8722 /* if shCount >= 8 */
8730 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8732 movLeft2Result (left, LSB, result, MSB16, 0);
8734 aopPut (result, zero, LSB);
8737 /* 1 <= shCount <= 7 */
8741 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8743 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8747 /*-----------------------------------------------------------------*/
8748 /* shiftLLong - shift left one long from left to result */
8749 /* offl = LSB or MSB16 */
8750 /*-----------------------------------------------------------------*/
8752 shiftLLong (operand * left, operand * result, int offr)
8755 int size = AOP_SIZE (result);
8757 if (size >= LSB + offr)
8759 l = aopGet (left, LSB, FALSE, FALSE);
8761 emitcode ("add", "a,acc");
8762 if (sameRegs (AOP (left), AOP (result)) &&
8763 size >= MSB16 + offr && offr != LSB)
8764 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8766 aopPut (result, "a", LSB + offr);
8769 if (size >= MSB16 + offr)
8771 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8773 l = aopGet (left, MSB16, FALSE, FALSE);
8776 emitcode ("rlc", "a");
8777 if (sameRegs (AOP (left), AOP (result)) &&
8778 size >= MSB24 + offr && offr != LSB)
8779 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8781 aopPut (result, "a", MSB16 + offr);
8784 if (size >= MSB24 + offr)
8786 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8788 l = aopGet (left, MSB24, FALSE, FALSE);
8791 emitcode ("rlc", "a");
8792 if (sameRegs (AOP (left), AOP (result)) &&
8793 size >= MSB32 + offr && offr != LSB)
8794 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8796 aopPut (result, "a", MSB24 + offr);
8799 if (size > MSB32 + offr)
8801 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8803 l = aopGet (left, MSB32, FALSE, FALSE);
8806 emitcode ("rlc", "a");
8807 aopPut (result, "a", MSB32 + offr);
8810 aopPut (result, zero, LSB);
8813 /*-----------------------------------------------------------------*/
8814 /* genlshFour - shift four byte by a known amount != 0 */
8815 /*-----------------------------------------------------------------*/
8817 genlshFour (operand * result, operand * left, int shCount)
8821 D (emitcode (";", "genlshFour"));
8823 size = AOP_SIZE (result);
8825 /* if shifting more that 3 bytes */
8830 /* lowest order of left goes to the highest
8831 order of the destination */
8832 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8834 movLeft2Result (left, LSB, result, MSB32, 0);
8835 aopPut (result, zero, LSB);
8836 aopPut (result, zero, MSB16);
8837 aopPut (result, zero, MSB24);
8841 /* more than two bytes */
8842 else if (shCount >= 16)
8844 /* lower order two bytes goes to higher order two bytes */
8846 /* if some more remaining */
8848 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8851 movLeft2Result (left, MSB16, result, MSB32, 0);
8852 movLeft2Result (left, LSB, result, MSB24, 0);
8854 aopPut (result, zero, MSB16);
8855 aopPut (result, zero, LSB);
8859 /* if more than 1 byte */
8860 else if (shCount >= 8)
8862 /* lower order three bytes goes to higher order three bytes */
8867 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8869 movLeft2Result (left, LSB, result, MSB16, 0);
8875 movLeft2Result (left, MSB24, result, MSB32, 0);
8876 movLeft2Result (left, MSB16, result, MSB24, 0);
8877 movLeft2Result (left, LSB, result, MSB16, 0);
8878 aopPut (result, zero, LSB);
8880 else if (shCount == 1)
8881 shiftLLong (left, result, MSB16);
8884 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8885 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8886 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8887 aopPut (result, zero, LSB);
8892 /* 1 <= shCount <= 7 */
8893 else if (shCount <= 2)
8895 shiftLLong (left, result, LSB);
8897 shiftLLong (result, result, LSB);
8899 /* 3 <= shCount <= 7, optimize */
8902 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8903 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8904 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8908 /*-----------------------------------------------------------------*/
8909 /* genLeftShiftLiteral - left shifting by known count */
8910 /*-----------------------------------------------------------------*/
8912 genLeftShiftLiteral (operand * left,
8917 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8920 D (emitcode (";", "genLeftShiftLiteral"));
8922 freeAsmop (right, NULL, ic, TRUE);
8924 aopOp (left, ic, FALSE);
8925 aopOp (result, ic, FALSE);
8927 size = getSize (operandType (result));
8930 emitcode ("; shift left ", "result %d, left %d", size,
8934 /* I suppose that the left size >= result size */
8939 movLeft2Result (left, size, result, size, 0);
8942 else if (shCount >= (size * 8))
8946 aopPut (result, zero, size);
8954 genlshOne (result, left, shCount);
8958 genlshTwo (result, left, shCount);
8962 genlshFour (result, left, shCount);
8965 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8966 "*** ack! mystery literal shift!\n");
8970 freeAsmop (result, NULL, ic, TRUE);
8971 freeAsmop (left, NULL, ic, TRUE);
8974 /*-----------------------------------------------------------------*/
8975 /* genLeftShift - generates code for left shifting */
8976 /*-----------------------------------------------------------------*/
8978 genLeftShift (iCode * ic)
8980 operand *left, *right, *result;
8983 symbol *tlbl, *tlbl1;
8986 D (emitcode (";", "genLeftShift"));
8988 right = IC_RIGHT (ic);
8989 left = IC_LEFT (ic);
8990 result = IC_RESULT (ic);
8992 aopOp (right, ic, FALSE);
8994 /* if the shift count is known then do it
8995 as efficiently as possible */
8996 if (AOP_TYPE (right) == AOP_LIT)
8998 genLeftShiftLiteral (left, right, result, ic);
9002 /* shift count is unknown then we have to form
9003 a loop get the loop count in B : Note: we take
9004 only the lower order byte since shifting
9005 more that 32 bits make no sense anyway, ( the
9006 largest size of an object can be only 32 bits ) */
9009 MOVB (aopGet (right, 0, FALSE, FALSE));
9010 emitcode ("inc", "b");
9011 freeAsmop (right, NULL, ic, TRUE);
9012 aopOp (left, ic, FALSE);
9013 aopOp (result, ic, FALSE);
9015 /* now move the left to the result if they are not the same */
9016 if (!sameRegs (AOP (left), AOP (result)) &&
9017 AOP_SIZE (result) > 1)
9020 size = AOP_SIZE (result);
9024 l = aopGet (left, offset, FALSE, TRUE);
9025 if (*l == '@' && (IS_AOP_PREG (result)))
9028 emitcode ("mov", "a,%s", l);
9029 aopPut (result, "a", offset);
9032 aopPut (result, l, offset);
9037 tlbl = newiTempLabel (NULL);
9038 size = AOP_SIZE (result);
9040 tlbl1 = newiTempLabel (NULL);
9042 /* if it is only one byte then */
9045 symbol *tlbl1 = newiTempLabel (NULL);
9047 l = aopGet (left, 0, FALSE, FALSE);
9049 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9051 emitcode ("add", "a,acc");
9053 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9055 aopPut (result, "a", 0);
9059 reAdjustPreg (AOP (result));
9061 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9063 l = aopGet (result, offset, FALSE, FALSE);
9065 emitcode ("add", "a,acc");
9066 aopPut (result, "a", offset++);
9069 l = aopGet (result, offset, FALSE, FALSE);
9071 emitcode ("rlc", "a");
9072 aopPut (result, "a", offset++);
9074 reAdjustPreg (AOP (result));
9077 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9080 freeAsmop (result, NULL, ic, TRUE);
9081 freeAsmop (left, NULL, ic, TRUE);
9084 /*-----------------------------------------------------------------*/
9085 /* genrshOne - right shift a one byte quantity by known count */
9086 /*-----------------------------------------------------------------*/
9088 genrshOne (operand * result, operand * left,
9089 int shCount, int sign)
9091 D (emitcode (";", "genrshOne"));
9093 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9096 /*-----------------------------------------------------------------*/
9097 /* genrshTwo - right shift two bytes by known amount != 0 */
9098 /*-----------------------------------------------------------------*/
9100 genrshTwo (operand * result, operand * left,
9101 int shCount, int sign)
9103 D (emitcode (";", "genrshTwo"));
9105 /* if shCount >= 8 */
9110 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9112 movLeft2Result (left, MSB16, result, LSB, sign);
9113 addSign (result, MSB16, sign);
9116 /* 1 <= shCount <= 7 */
9118 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9121 /*-----------------------------------------------------------------*/
9122 /* shiftRLong - shift right one long from left to result */
9123 /* offl = LSB or MSB16 */
9124 /*-----------------------------------------------------------------*/
9126 shiftRLong (operand * left, int offl,
9127 operand * result, int sign)
9129 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9131 if (overlapping && offl>1)
9133 // we are in big trouble, but this shouldn't happen
9134 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9137 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9144 emitcode ("rlc", "a");
9145 emitcode ("subb", "a,acc");
9146 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9148 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9152 aopPut (result, "a", MSB32);
9153 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9158 if (aopPutUsesAcc (result, zero, MSB32))
9160 emitcode("xch", "a,b");
9161 aopPut (result, zero, MSB32);
9162 emitcode("xch", "a,b");
9166 aopPut (result, zero, MSB32);
9173 emitcode ("clr", "c");
9177 emitcode ("mov", "c,acc.7");
9180 emitcode ("rrc", "a");
9182 if (overlapping && offl==MSB16 &&
9183 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9185 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9189 aopPut (result, "a", MSB32 - offl);
9190 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9193 emitcode ("rrc", "a");
9194 if (overlapping && offl==MSB16 &&
9195 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9197 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9201 aopPut (result, "a", MSB24 - offl);
9202 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9205 emitcode ("rrc", "a");
9208 aopPut (result, "a", MSB16 - offl);
9213 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9215 xch_a_aopGet (left, LSB, FALSE, FALSE);
9219 aopPut (result, "a", MSB16 - offl);
9220 MOVA (aopGet (left, LSB, FALSE, FALSE));
9222 emitcode ("rrc", "a");
9223 aopPut (result, "a", LSB);
9227 /*-----------------------------------------------------------------*/
9228 /* genrshFour - shift four byte by a known amount != 0 */
9229 /*-----------------------------------------------------------------*/
9231 genrshFour (operand * result, operand * left,
9232 int shCount, int sign)
9234 D (emitcode (";", "genrshFour"));
9236 /* if shifting more that 3 bytes */
9241 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9243 movLeft2Result (left, MSB32, result, LSB, sign);
9244 addSign (result, MSB16, sign);
9246 else if (shCount >= 16)
9250 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9253 movLeft2Result (left, MSB24, result, LSB, 0);
9254 movLeft2Result (left, MSB32, result, MSB16, sign);
9256 addSign (result, MSB24, sign);
9258 else if (shCount >= 8)
9263 shiftRLong (left, MSB16, result, sign);
9265 else if (shCount == 0)
9267 movLeft2Result (left, MSB16, result, LSB, 0);
9268 movLeft2Result (left, MSB24, result, MSB16, 0);
9269 movLeft2Result (left, MSB32, result, MSB24, sign);
9270 addSign (result, MSB32, sign);
9274 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9275 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9276 /* the last shift is signed */
9277 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9278 addSign (result, MSB32, sign);
9283 /* 1 <= shCount <= 7 */
9286 shiftRLong (left, LSB, result, sign);
9288 shiftRLong (result, LSB, result, sign);
9292 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9293 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9294 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9299 /*-----------------------------------------------------------------*/
9300 /* genRightShiftLiteral - right shifting by known count */
9301 /*-----------------------------------------------------------------*/
9303 genRightShiftLiteral (operand * left,
9309 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9312 D (emitcode (";", "genRightShiftLiteral"));
9314 freeAsmop (right, NULL, ic, TRUE);
9316 aopOp (left, ic, FALSE);
9317 aopOp (result, ic, FALSE);
9320 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9324 size = getDataSize (left);
9325 /* test the LEFT size !!! */
9327 /* I suppose that the left size >= result size */
9330 size = getDataSize (result);
9332 movLeft2Result (left, size, result, size, 0);
9335 else if (shCount >= (size * 8))
9339 /* get sign in acc.7 */
9340 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9342 addSign (result, LSB, sign);
9349 genrshOne (result, left, shCount, sign);
9353 genrshTwo (result, left, shCount, sign);
9357 genrshFour (result, left, shCount, sign);
9363 freeAsmop (result, NULL, ic, TRUE);
9364 freeAsmop (left, NULL, ic, TRUE);
9367 /*-----------------------------------------------------------------*/
9368 /* genSignedRightShift - right shift of signed number */
9369 /*-----------------------------------------------------------------*/
9371 genSignedRightShift (iCode * ic)
9373 operand *right, *left, *result;
9376 symbol *tlbl, *tlbl1;
9379 D (emitcode (";", "genSignedRightShift"));
9381 /* we do it the hard way put the shift count in b
9382 and loop thru preserving the sign */
9384 right = IC_RIGHT (ic);
9385 left = IC_LEFT (ic);
9386 result = IC_RESULT (ic);
9388 aopOp (right, ic, FALSE);
9391 if (AOP_TYPE (right) == AOP_LIT)
9393 genRightShiftLiteral (left, right, result, ic, 1);
9396 /* shift count is unknown then we have to form
9397 a loop get the loop count in B : Note: we take
9398 only the lower order byte since shifting
9399 more that 32 bits make no sense anyway, ( the
9400 largest size of an object can be only 32 bits ) */
9403 MOVB (aopGet (right, 0, FALSE, FALSE));
9404 emitcode ("inc", "b");
9405 freeAsmop (right, NULL, ic, TRUE);
9406 aopOp (left, ic, FALSE);
9407 aopOp (result, ic, FALSE);
9409 /* now move the left to the result if they are not the
9411 if (!sameRegs (AOP (left), AOP (result)) &&
9412 AOP_SIZE (result) > 1)
9415 size = AOP_SIZE (result);
9419 l = aopGet (left, offset, FALSE, TRUE);
9420 if (*l == '@' && IS_AOP_PREG (result))
9423 emitcode ("mov", "a,%s", l);
9424 aopPut (result, "a", offset);
9427 aopPut (result, l, offset);
9432 /* mov the highest order bit to OVR */
9433 tlbl = newiTempLabel (NULL);
9434 tlbl1 = newiTempLabel (NULL);
9436 size = AOP_SIZE (result);
9438 MOVA (aopGet (left, offset, FALSE, FALSE));
9439 emitcode ("rlc", "a");
9440 emitcode ("mov", "ov,c");
9441 /* if it is only one byte then */
9444 l = aopGet (left, 0, FALSE, FALSE);
9446 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9448 emitcode ("mov", "c,ov");
9449 emitcode ("rrc", "a");
9451 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9453 aopPut (result, "a", 0);
9457 reAdjustPreg (AOP (result));
9458 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9460 emitcode ("mov", "c,ov");
9463 l = aopGet (result, offset, FALSE, FALSE);
9465 emitcode ("rrc", "a");
9466 aopPut (result, "a", offset--);
9468 reAdjustPreg (AOP (result));
9470 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9474 freeAsmop (result, NULL, ic, TRUE);
9475 freeAsmop (left, NULL, ic, TRUE);
9478 /*-----------------------------------------------------------------*/
9479 /* genRightShift - generate code for right shifting */
9480 /*-----------------------------------------------------------------*/
9482 genRightShift (iCode * ic)
9484 operand *right, *left, *result;
9488 symbol *tlbl, *tlbl1;
9491 D (emitcode (";", "genRightShift"));
9493 /* if signed then we do it the hard way preserve the
9494 sign bit moving it inwards */
9495 letype = getSpec (operandType (IC_LEFT (ic)));
9497 if (!SPEC_USIGN (letype))
9499 genSignedRightShift (ic);
9503 /* signed & unsigned types are treated the same : i.e. the
9504 signed is NOT propagated inwards : quoting from the
9505 ANSI - standard : "for E1 >> E2, is equivalent to division
9506 by 2**E2 if unsigned or if it has a non-negative value,
9507 otherwise the result is implementation defined ", MY definition
9508 is that the sign does not get propagated */
9510 right = IC_RIGHT (ic);
9511 left = IC_LEFT (ic);
9512 result = IC_RESULT (ic);
9514 aopOp (right, ic, FALSE);
9516 /* if the shift count is known then do it
9517 as efficiently as possible */
9518 if (AOP_TYPE (right) == AOP_LIT)
9520 genRightShiftLiteral (left, right, result, ic, 0);
9524 /* shift count is unknown then we have to form
9525 a loop get the loop count in B : Note: we take
9526 only the lower order byte since shifting
9527 more that 32 bits make no sense anyway, ( the
9528 largest size of an object can be only 32 bits ) */
9531 MOVB (aopGet (right, 0, FALSE, FALSE));
9532 emitcode ("inc", "b");
9533 freeAsmop (right, NULL, ic, TRUE);
9534 aopOp (left, ic, FALSE);
9535 aopOp (result, ic, FALSE);
9537 /* now move the left to the result if they are not the
9539 if (!sameRegs (AOP (left), AOP (result)) &&
9540 AOP_SIZE (result) > 1)
9542 size = AOP_SIZE (result);
9546 l = aopGet (left, offset, FALSE, TRUE);
9547 if (*l == '@' && IS_AOP_PREG (result))
9550 emitcode ("mov", "a,%s", l);
9551 aopPut (result, "a", offset);
9554 aopPut (result, l, offset);
9559 tlbl = newiTempLabel (NULL);
9560 tlbl1 = newiTempLabel (NULL);
9561 size = AOP_SIZE (result);
9564 /* if it is only one byte then */
9567 l = aopGet (left, 0, FALSE, FALSE);
9569 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9572 emitcode ("rrc", "a");
9574 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9576 aopPut (result, "a", 0);
9580 reAdjustPreg (AOP (result));
9581 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9586 l = aopGet (result, offset, FALSE, FALSE);
9588 emitcode ("rrc", "a");
9589 aopPut (result, "a", offset--);
9591 reAdjustPreg (AOP (result));
9594 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9598 freeAsmop (result, NULL, ic, TRUE);
9599 freeAsmop (left, NULL, ic, TRUE);
9602 /*-----------------------------------------------------------------*/
9603 /* emitPtrByteGet - emits code to get a byte into A through a */
9604 /* pointer register (R0, R1, or DPTR). The */
9605 /* original value of A can be preserved in B. */
9606 /*-----------------------------------------------------------------*/
9608 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9615 emitcode ("mov", "b,a");
9616 emitcode ("mov", "a,@%s", rname);
9621 emitcode ("mov", "b,a");
9622 emitcode ("movx", "a,@%s", rname);
9627 emitcode ("mov", "b,a");
9628 emitcode ("movx", "a,@dptr");
9633 emitcode ("mov", "b,a");
9634 emitcode ("clr", "a");
9635 emitcode ("movc", "a,@a+dptr");
9641 emitcode ("push", "b");
9642 emitcode ("push", "acc");
9644 emitcode ("lcall", "__gptrget");
9646 emitcode ("pop", "b");
9651 /*-----------------------------------------------------------------*/
9652 /* emitPtrByteSet - emits code to set a byte from src through a */
9653 /* pointer register (R0, R1, or DPTR). */
9654 /*-----------------------------------------------------------------*/
9656 emitPtrByteSet (char *rname, int p_type, char *src)
9665 emitcode ("mov", "@%s,a", rname);
9668 emitcode ("mov", "@%s,%s", rname, src);
9673 emitcode ("movx", "@%s,a", rname);
9678 emitcode ("movx", "@dptr,a");
9683 emitcode ("lcall", "__gptrput");
9688 /*-----------------------------------------------------------------*/
9689 /* genUnpackBits - generates code for unpacking bits */
9690 /*-----------------------------------------------------------------*/
9692 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9694 int offset = 0; /* result byte offset */
9695 int rsize; /* result size */
9696 int rlen = 0; /* remaining bitfield length */
9697 sym_link *etype; /* bitfield type information */
9698 int blen; /* bitfield length */
9699 int bstr; /* bitfield starting bit within byte */
9702 D(emitcode (";", "genUnpackBits"));
9704 etype = getSpec (operandType (result));
9705 rsize = getSize (operandType (result));
9706 blen = SPEC_BLEN (etype);
9707 bstr = SPEC_BSTR (etype);
9709 if (ifx && blen <= 8)
9711 emitPtrByteGet (rname, ptype, FALSE);
9714 SNPRINTF (buffer, sizeof(buffer),
9716 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9721 emitcode ("anl", "a,#0x%02x",
9722 (((unsigned char) -1) >> (8 - blen)) << bstr);
9723 genIfxJump (ifx, "a", NULL, NULL, NULL);
9729 /* If the bitfield length is less than a byte */
9732 emitPtrByteGet (rname, ptype, FALSE);
9734 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9735 if (!SPEC_USIGN (etype))
9737 /* signed bitfield */
9738 symbol *tlbl = newiTempLabel (NULL);
9740 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9741 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9744 aopPut (result, "a", offset++);
9748 /* Bit field did not fit in a byte. Copy all
9749 but the partial byte at the end. */
9750 for (rlen=blen;rlen>=8;rlen-=8)
9752 emitPtrByteGet (rname, ptype, FALSE);
9753 aopPut (result, "a", offset++);
9755 emitcode ("inc", "%s", rname);
9758 /* Handle the partial byte at the end */
9761 emitPtrByteGet (rname, ptype, FALSE);
9762 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9763 if (!SPEC_USIGN (etype))
9765 /* signed bitfield */
9766 symbol *tlbl = newiTempLabel (NULL);
9768 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9769 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9772 aopPut (result, "a", offset++);
9780 if (SPEC_USIGN (etype))
9784 /* signed bitfield: sign extension with 0x00 or 0xff */
9785 emitcode ("rlc", "a");
9786 emitcode ("subb", "a,acc");
9792 aopPut (result, source, offset++);
9797 /*-----------------------------------------------------------------*/
9798 /* genDataPointerGet - generates code when ptr offset is known */
9799 /*-----------------------------------------------------------------*/
9801 genDataPointerGet (operand * left,
9807 int size, offset = 0;
9809 D (emitcode (";", "genDataPointerGet"));
9811 aopOp (result, ic, TRUE);
9813 /* get the string representation of the name */
9814 l = aopGet (left, 0, FALSE, TRUE);
9816 size = AOP_SIZE (result);
9821 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9825 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9827 aopPut (result, buffer, offset++);
9830 freeAsmop (result, NULL, ic, TRUE);
9831 freeAsmop (left, NULL, ic, TRUE);
9834 /*-----------------------------------------------------------------*/
9835 /* genNearPointerGet - emitcode for near pointer fetch */
9836 /*-----------------------------------------------------------------*/
9838 genNearPointerGet (operand * left,
9847 sym_link *rtype, *retype;
9848 sym_link *ltype = operandType (left);
9851 D (emitcode (";", "genNearPointerGet"));
9853 rtype = operandType (result);
9854 retype = getSpec (rtype);
9856 aopOp (left, ic, FALSE);
9858 /* if left is rematerialisable and
9859 result is not bitfield variable type and
9860 the left is pointer to data space i.e
9861 lower 128 bytes of space */
9862 if (AOP_TYPE (left) == AOP_IMMD &&
9863 !IS_BITFIELD (retype) &&
9864 DCL_TYPE (ltype) == POINTER)
9866 genDataPointerGet (left, result, ic);
9870 /* if the value is already in a pointer register
9871 then don't need anything more */
9872 if (!AOP_INPREG (AOP (left)))
9874 if (IS_AOP_PREG (left))
9876 // Aha, it is a pointer, just in disguise.
9877 rname = aopGet (left, 0, FALSE, FALSE);
9880 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9881 __FILE__, __LINE__);
9886 emitcode ("mov", "a%s,%s", rname + 1, rname);
9887 rname++; // skip the '@'.
9892 /* otherwise get a free pointer register */
9894 preg = getFreePtr (ic, &aop, FALSE);
9895 emitcode ("mov", "%s,%s",
9897 aopGet (left, 0, FALSE, TRUE));
9902 rname = aopGet (left, 0, FALSE, FALSE);
9904 //aopOp (result, ic, FALSE);
9905 aopOp (result, ic, result?TRUE:FALSE);
9907 /* if bitfield then unpack the bits */
9908 if (IS_BITFIELD (retype))
9909 genUnpackBits (result, rname, POINTER, ifx);
9912 /* we have can just get the values */
9913 int size = AOP_SIZE (result);
9918 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9921 emitcode ("mov", "a,@%s", rname);
9923 aopPut (result, "a", offset);
9927 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9928 aopPut (result, buffer, offset);
9932 emitcode ("inc", "%s", rname);
9936 /* now some housekeeping stuff */
9937 if (aop) /* we had to allocate for this iCode */
9939 if (pi) { /* post increment present */
9940 aopPut (left, rname, 0);
9942 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9946 /* we did not allocate which means left
9947 already in a pointer register, then
9948 if size > 0 && this could be used again
9949 we have to point it back to where it
9951 if ((AOP_SIZE (result) > 1 &&
9952 !OP_SYMBOL (left)->remat &&
9953 (OP_SYMBOL (left)->liveTo > ic->seq ||
9957 int size = AOP_SIZE (result) - 1;
9959 emitcode ("dec", "%s", rname);
9963 if (ifx && !ifx->generated)
9965 genIfxJump (ifx, "a", left, NULL, result);
9969 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9970 freeAsmop (left, NULL, ic, TRUE);
9971 if (pi) pi->generated = 1;
9974 /*-----------------------------------------------------------------*/
9975 /* genPagedPointerGet - emitcode for paged pointer fetch */
9976 /*-----------------------------------------------------------------*/
9978 genPagedPointerGet (operand * left,
9987 sym_link *rtype, *retype;
9989 D (emitcode (";", "genPagedPointerGet"));
9991 rtype = operandType (result);
9992 retype = getSpec (rtype);
9994 aopOp (left, ic, FALSE);
9996 /* if the value is already in a pointer register
9997 then don't need anything more */
9998 if (!AOP_INPREG (AOP (left)))
10000 /* otherwise get a free pointer register */
10001 aop = newAsmop (0);
10002 preg = getFreePtr (ic, &aop, FALSE);
10003 emitcode ("mov", "%s,%s",
10005 aopGet (left, 0, FALSE, TRUE));
10006 rname = preg->name;
10009 rname = aopGet (left, 0, FALSE, FALSE);
10011 aopOp (result, ic, FALSE);
10013 /* if bitfield then unpack the bits */
10014 if (IS_BITFIELD (retype))
10015 genUnpackBits (result, rname, PPOINTER, ifx);
10018 /* we have can just get the values */
10019 int size = AOP_SIZE (result);
10025 emitcode ("movx", "a,@%s", rname);
10027 aopPut (result, "a", offset);
10032 emitcode ("inc", "%s", rname);
10036 /* now some housekeeping stuff */
10037 if (aop) /* we had to allocate for this iCode */
10040 aopPut (left, rname, 0);
10041 freeAsmop (NULL, aop, ic, TRUE);
10045 /* we did not allocate which means left
10046 already in a pointer register, then
10047 if size > 0 && this could be used again
10048 we have to point it back to where it
10050 if ((AOP_SIZE (result) > 1 &&
10051 !OP_SYMBOL (left)->remat &&
10052 (OP_SYMBOL (left)->liveTo > ic->seq ||
10056 int size = AOP_SIZE (result) - 1;
10058 emitcode ("dec", "%s", rname);
10062 if (ifx && !ifx->generated)
10064 genIfxJump (ifx, "a", left, NULL, result);
10068 freeAsmop (result, NULL, ic, TRUE);
10069 freeAsmop (left, NULL, ic, TRUE);
10070 if (pi) pi->generated = 1;
10073 /*--------------------------------------------------------------------*/
10074 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10075 /*--------------------------------------------------------------------*/
10077 loadDptrFromOperand (operand *op, bool loadBToo)
10079 if (AOP_TYPE (op) != AOP_STR)
10081 /* if this is rematerializable */
10082 if (AOP_TYPE (op) == AOP_IMMD)
10084 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10087 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10088 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10091 wassertl(FALSE, "need pointerCode");
10092 emitcode (";", "mov b,???");
10093 /* genPointerGet and genPointerSet originally did different
10094 ** things for this case. Both seem wrong.
10095 ** from genPointerGet:
10096 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10097 ** from genPointerSet:
10098 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10103 else if (AOP_TYPE (op) == AOP_DPTR)
10107 MOVA (aopGet (op, 0, FALSE, FALSE));
10108 emitcode ("push", "acc");
10109 MOVA (aopGet (op, 1, FALSE, FALSE));
10110 emitcode ("push", "acc");
10111 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10112 emitcode ("pop", "dph");
10113 emitcode ("pop", "dpl");
10117 MOVA (aopGet (op, 0, FALSE, FALSE));
10118 emitcode ("push", "acc");
10119 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10120 emitcode ("pop", "dpl");
10124 { /* we need to get it byte by byte */
10125 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10126 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10128 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10133 /*-----------------------------------------------------------------*/
10134 /* genFarPointerGet - get value from far space */
10135 /*-----------------------------------------------------------------*/
10137 genFarPointerGet (operand * left,
10138 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10141 sym_link *retype = getSpec (operandType (result));
10143 D (emitcode (";", "genFarPointerGet"));
10145 aopOp (left, ic, FALSE);
10146 loadDptrFromOperand (left, FALSE);
10148 /* so dptr now contains the address */
10149 aopOp (result, ic, FALSE);
10151 /* if bit then unpack */
10152 if (IS_BITFIELD (retype))
10153 genUnpackBits (result, "dptr", FPOINTER, ifx);
10156 size = AOP_SIZE (result);
10161 emitcode ("movx", "a,@dptr");
10163 aopPut (result, "a", offset++);
10165 emitcode ("inc", "dptr");
10169 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10171 aopPut (left, "dpl", 0);
10172 aopPut (left, "dph", 1);
10176 if (ifx && !ifx->generated)
10178 genIfxJump (ifx, "a", left, NULL, result);
10181 freeAsmop (result, NULL, ic, TRUE);
10182 freeAsmop (left, NULL, ic, TRUE);
10185 /*-----------------------------------------------------------------*/
10186 /* genCodePointerGet - get value from code space */
10187 /*-----------------------------------------------------------------*/
10189 genCodePointerGet (operand * left,
10190 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10193 sym_link *retype = getSpec (operandType (result));
10195 D (emitcode (";", "genCodePointerGet"));
10197 aopOp (left, ic, FALSE);
10198 loadDptrFromOperand (left, FALSE);
10200 /* so dptr now contains the address */
10201 aopOp (result, ic, FALSE);
10203 /* if bit then unpack */
10204 if (IS_BITFIELD (retype))
10205 genUnpackBits (result, "dptr", CPOINTER, ifx);
10208 size = AOP_SIZE (result);
10213 emitcode ("clr", "a");
10214 emitcode ("movc", "a,@a+dptr");
10216 aopPut (result, "a", offset++);
10218 emitcode ("inc", "dptr");
10222 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10224 aopPut (left, "dpl", 0);
10225 aopPut (left, "dph", 1);
10229 if (ifx && !ifx->generated)
10231 genIfxJump (ifx, "a", left, NULL, result);
10234 freeAsmop (result, NULL, ic, TRUE);
10235 freeAsmop (left, NULL, ic, TRUE);
10238 /*-----------------------------------------------------------------*/
10239 /* genGenPointerGet - get value from generic pointer space */
10240 /*-----------------------------------------------------------------*/
10242 genGenPointerGet (operand * left,
10243 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10246 sym_link *retype = getSpec (operandType (result));
10248 D (emitcode (";", "genGenPointerGet"));
10250 aopOp (left, ic, FALSE);
10251 loadDptrFromOperand (left, TRUE);
10253 /* so dptr now contains the address */
10254 aopOp (result, ic, FALSE);
10256 /* if bit then unpack */
10257 if (IS_BITFIELD (retype))
10259 genUnpackBits (result, "dptr", GPOINTER, ifx);
10263 size = AOP_SIZE (result);
10268 emitcode ("lcall", "__gptrget");
10270 aopPut (result, "a", offset++);
10272 emitcode ("inc", "dptr");
10276 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10278 aopPut (left, "dpl", 0);
10279 aopPut (left, "dph", 1);
10283 if (ifx && !ifx->generated)
10285 genIfxJump (ifx, "a", left, NULL, result);
10288 freeAsmop (result, NULL, ic, TRUE);
10289 freeAsmop (left, NULL, ic, TRUE);
10292 /*-----------------------------------------------------------------*/
10293 /* genPointerGet - generate code for pointer get */
10294 /*-----------------------------------------------------------------*/
10296 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10298 operand *left, *result;
10299 sym_link *type, *etype;
10302 D (emitcode (";", "genPointerGet"));
10304 left = IC_LEFT (ic);
10305 result = IC_RESULT (ic);
10307 if (getSize (operandType (result))>1)
10310 /* depending on the type of pointer we need to
10311 move it to the correct pointer register */
10312 type = operandType (left);
10313 etype = getSpec (type);
10314 /* if left is of type of pointer then it is simple */
10315 if (IS_PTR (type) && !IS_FUNC (type->next))
10316 p_type = DCL_TYPE (type);
10319 /* we have to go by the storage class */
10320 p_type = PTR_TYPE (SPEC_OCLS (etype));
10323 /* special case when cast remat */
10324 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10325 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10327 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10328 type = operandType (left);
10329 p_type = DCL_TYPE (type);
10331 /* now that we have the pointer type we assign
10332 the pointer values */
10338 genNearPointerGet (left, result, ic, pi, ifx);
10342 genPagedPointerGet (left, result, ic, pi, ifx);
10346 genFarPointerGet (left, result, ic, pi, ifx);
10350 genCodePointerGet (left, result, ic, pi, ifx);
10354 genGenPointerGet (left, result, ic, pi, ifx);
10360 /*-----------------------------------------------------------------*/
10361 /* genPackBits - generates code for packed bit storage */
10362 /*-----------------------------------------------------------------*/
10364 genPackBits (sym_link * etype,
10366 char *rname, int p_type)
10368 int offset = 0; /* source byte offset */
10369 int rlen = 0; /* remaining bitfield length */
10370 int blen; /* bitfield length */
10371 int bstr; /* bitfield starting bit within byte */
10372 int litval; /* source literal value (if AOP_LIT) */
10373 unsigned char mask; /* bitmask within current byte */
10375 D(emitcode (";", "genPackBits"));
10377 blen = SPEC_BLEN (etype);
10378 bstr = SPEC_BSTR (etype);
10380 /* If the bitfield length is less than a byte */
10383 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10384 (unsigned char) (0xFF >> (8 - bstr)));
10386 if (AOP_TYPE (right) == AOP_LIT)
10388 /* Case with a bitfield length <8 and literal source
10390 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10392 litval &= (~mask) & 0xff;
10393 emitPtrByteGet (rname, p_type, FALSE);
10394 if ((mask|litval)!=0xff)
10395 emitcode ("anl","a,#0x%02x", mask);
10397 emitcode ("orl","a,#0x%02x", litval);
10401 if ((blen==1) && (p_type!=GPOINTER))
10403 /* Case with a bitfield length == 1 and no generic pointer
10405 if (AOP_TYPE (right) == AOP_CRY)
10406 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10409 MOVA (aopGet (right, 0, FALSE, FALSE));
10410 emitcode ("rrc","a");
10412 emitPtrByteGet (rname, p_type, FALSE);
10413 emitcode ("mov","acc.%d,c",bstr);
10418 /* Case with a bitfield length < 8 and arbitrary source
10420 MOVA (aopGet (right, 0, FALSE, FALSE));
10421 /* shift and mask source value */
10423 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10425 pushedB = pushB ();
10426 /* transfer A to B and get next byte */
10427 emitPtrByteGet (rname, p_type, TRUE);
10429 emitcode ("anl", "a,#0x%02x", mask);
10430 emitcode ("orl", "a,b");
10431 if (p_type == GPOINTER)
10432 emitcode ("pop", "b");
10438 emitPtrByteSet (rname, p_type, "a");
10442 /* Bit length is greater than 7 bits. In this case, copy */
10443 /* all except the partial byte at the end */
10444 for (rlen=blen;rlen>=8;rlen-=8)
10446 emitPtrByteSet (rname, p_type,
10447 aopGet (right, offset++, FALSE, TRUE) );
10449 emitcode ("inc", "%s", rname);
10452 /* If there was a partial byte at the end */
10455 mask = (((unsigned char) -1 << rlen) & 0xff);
10457 if (AOP_TYPE (right) == AOP_LIT)
10459 /* Case with partial byte and literal source
10461 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10462 litval >>= (blen-rlen);
10463 litval &= (~mask) & 0xff;
10464 emitPtrByteGet (rname, p_type, FALSE);
10465 if ((mask|litval)!=0xff)
10466 emitcode ("anl","a,#0x%02x", mask);
10468 emitcode ("orl","a,#0x%02x", litval);
10473 /* Case with partial byte and arbitrary source
10475 MOVA (aopGet (right, offset++, FALSE, FALSE));
10476 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10478 pushedB = pushB ();
10479 /* transfer A to B and get next byte */
10480 emitPtrByteGet (rname, p_type, TRUE);
10482 emitcode ("anl", "a,#0x%02x", mask);
10483 emitcode ("orl", "a,b");
10484 if (p_type == GPOINTER)
10485 emitcode ("pop", "b");
10489 emitPtrByteSet (rname, p_type, "a");
10494 /*-----------------------------------------------------------------*/
10495 /* genDataPointerSet - remat pointer to data space */
10496 /*-----------------------------------------------------------------*/
10498 genDataPointerSet (operand * right,
10502 int size, offset = 0;
10503 char *l, buffer[256];
10505 D (emitcode (";", "genDataPointerSet"));
10507 aopOp (right, ic, FALSE);
10509 l = aopGet (result, 0, FALSE, TRUE);
10511 size = AOP_SIZE (right);
10515 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10517 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10518 emitcode ("mov", "%s,%s", buffer,
10519 aopGet (right, offset++, FALSE, FALSE));
10522 freeAsmop (result, NULL, ic, TRUE);
10523 freeAsmop (right, NULL, ic, TRUE);
10526 /*-----------------------------------------------------------------*/
10527 /* genNearPointerSet - emitcode for near pointer put */
10528 /*-----------------------------------------------------------------*/
10530 genNearPointerSet (operand * right,
10538 sym_link *retype, *letype;
10539 sym_link *ptype = operandType (result);
10541 D (emitcode (";", "genNearPointerSet"));
10543 retype = getSpec (operandType (right));
10544 letype = getSpec (ptype);
10546 aopOp (result, ic, FALSE);
10548 /* if the result is rematerializable &
10549 in data space & not a bit variable */
10550 if (AOP_TYPE (result) == AOP_IMMD &&
10551 DCL_TYPE (ptype) == POINTER &&
10552 !IS_BITVAR (retype) &&
10553 !IS_BITVAR (letype))
10555 genDataPointerSet (right, result, ic);
10559 /* if the value is already in a pointer register
10560 then don't need anything more */
10561 if (!AOP_INPREG (AOP (result)))
10564 //AOP_TYPE (result) == AOP_STK
10565 IS_AOP_PREG(result)
10568 // Aha, it is a pointer, just in disguise.
10569 rname = aopGet (result, 0, FALSE, FALSE);
10572 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10573 __FILE__, __LINE__);
10578 emitcode ("mov", "a%s,%s", rname + 1, rname);
10579 rname++; // skip the '@'.
10584 /* otherwise get a free pointer register */
10585 aop = newAsmop (0);
10586 preg = getFreePtr (ic, &aop, FALSE);
10587 emitcode ("mov", "%s,%s",
10589 aopGet (result, 0, FALSE, TRUE));
10590 rname = preg->name;
10595 rname = aopGet (result, 0, FALSE, FALSE);
10598 aopOp (right, ic, FALSE);
10600 /* if bitfield then unpack the bits */
10601 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10602 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10605 /* we can just get the values */
10606 int size = AOP_SIZE (right);
10611 l = aopGet (right, offset, FALSE, TRUE);
10612 if ((*l == '@') || (strcmp (l, "acc") == 0))
10615 emitcode ("mov", "@%s,a", rname);
10618 emitcode ("mov", "@%s,%s", rname, l);
10620 emitcode ("inc", "%s", rname);
10625 /* now some housekeeping stuff */
10626 if (aop) /* we had to allocate for this iCode */
10629 aopPut (result, rname, 0);
10630 freeAsmop (NULL, aop, ic, TRUE);
10634 /* we did not allocate which means left
10635 already in a pointer register, then
10636 if size > 0 && this could be used again
10637 we have to point it back to where it
10639 if ((AOP_SIZE (right) > 1 &&
10640 !OP_SYMBOL (result)->remat &&
10641 (OP_SYMBOL (result)->liveTo > ic->seq ||
10645 int size = AOP_SIZE (right) - 1;
10647 emitcode ("dec", "%s", rname);
10652 if (pi) pi->generated = 1;
10653 freeAsmop (result, NULL, ic, TRUE);
10654 freeAsmop (right, NULL, ic, TRUE);
10657 /*-----------------------------------------------------------------*/
10658 /* genPagedPointerSet - emitcode for Paged pointer put */
10659 /*-----------------------------------------------------------------*/
10661 genPagedPointerSet (operand * right,
10669 sym_link *retype, *letype;
10671 D (emitcode (";", "genPagedPointerSet"));
10673 retype = getSpec (operandType (right));
10674 letype = getSpec (operandType (result));
10676 aopOp (result, ic, FALSE);
10678 /* if the value is already in a pointer register
10679 then don't need anything more */
10680 if (!AOP_INPREG (AOP (result)))
10682 /* otherwise get a free pointer register */
10683 aop = newAsmop (0);
10684 preg = getFreePtr (ic, &aop, FALSE);
10685 emitcode ("mov", "%s,%s",
10687 aopGet (result, 0, FALSE, TRUE));
10688 rname = preg->name;
10691 rname = aopGet (result, 0, FALSE, FALSE);
10693 aopOp (right, ic, FALSE);
10695 /* if bitfield then unpack the bits */
10696 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10697 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10700 /* we have can just get the values */
10701 int size = AOP_SIZE (right);
10706 l = aopGet (right, offset, FALSE, TRUE);
10708 emitcode ("movx", "@%s,a", rname);
10711 emitcode ("inc", "%s", rname);
10717 /* now some housekeeping stuff */
10718 if (aop) /* we had to allocate for this iCode */
10721 aopPut (result, rname, 0);
10722 freeAsmop (NULL, aop, ic, TRUE);
10726 /* we did not allocate which means left
10727 already in a pointer register, then
10728 if size > 0 && this could be used again
10729 we have to point it back to where it
10731 if (AOP_SIZE (right) > 1 &&
10732 !OP_SYMBOL (result)->remat &&
10733 (OP_SYMBOL (result)->liveTo > ic->seq ||
10736 int size = AOP_SIZE (right) - 1;
10738 emitcode ("dec", "%s", rname);
10743 if (pi) pi->generated = 1;
10744 freeAsmop (result, NULL, ic, TRUE);
10745 freeAsmop (right, NULL, ic, TRUE);
10748 /*-----------------------------------------------------------------*/
10749 /* genFarPointerSet - set value from far space */
10750 /*-----------------------------------------------------------------*/
10752 genFarPointerSet (operand * right,
10753 operand * result, iCode * ic, iCode * pi)
10756 sym_link *retype = getSpec (operandType (right));
10757 sym_link *letype = getSpec (operandType (result));
10759 D(emitcode (";", "genFarPointerSet"));
10761 aopOp (result, ic, FALSE);
10762 loadDptrFromOperand (result, FALSE);
10764 /* so dptr now contains the address */
10765 aopOp (right, ic, FALSE);
10767 /* if bit then unpack */
10768 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10769 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10772 size = AOP_SIZE (right);
10777 char *l = aopGet (right, offset++, FALSE, FALSE);
10779 emitcode ("movx", "@dptr,a");
10781 emitcode ("inc", "dptr");
10784 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10785 aopPut (result, "dpl", 0);
10786 aopPut (result, "dph", 1);
10789 freeAsmop (result, NULL, ic, TRUE);
10790 freeAsmop (right, NULL, ic, TRUE);
10793 /*-----------------------------------------------------------------*/
10794 /* genGenPointerSet - set value from generic pointer space */
10795 /*-----------------------------------------------------------------*/
10797 genGenPointerSet (operand * right,
10798 operand * result, iCode * ic, iCode * pi)
10801 sym_link *retype = getSpec (operandType (right));
10802 sym_link *letype = getSpec (operandType (result));
10804 D (emitcode (";", "genGenPointerSet"));
10806 aopOp (result, ic, FALSE);
10807 loadDptrFromOperand (result, TRUE);
10809 /* so dptr now contains the address */
10810 aopOp (right, ic, FALSE);
10812 /* if bit then unpack */
10813 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10815 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10819 size = AOP_SIZE (right);
10824 char *l = aopGet (right, offset++, FALSE, FALSE);
10826 emitcode ("lcall", "__gptrput");
10828 emitcode ("inc", "dptr");
10832 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10833 aopPut (result, "dpl", 0);
10834 aopPut (result, "dph", 1);
10837 freeAsmop (result, NULL, ic, TRUE);
10838 freeAsmop (right, NULL, ic, TRUE);
10841 /*-----------------------------------------------------------------*/
10842 /* genPointerSet - stores the value into a pointer location */
10843 /*-----------------------------------------------------------------*/
10845 genPointerSet (iCode * ic, iCode *pi)
10847 operand *right, *result;
10848 sym_link *type, *etype;
10851 D (emitcode (";", "genPointerSet"));
10853 right = IC_RIGHT (ic);
10854 result = IC_RESULT (ic);
10856 /* depending on the type of pointer we need to
10857 move it to the correct pointer register */
10858 type = operandType (result);
10859 etype = getSpec (type);
10860 /* if left is of type of pointer then it is simple */
10861 if (IS_PTR (type) && !IS_FUNC (type->next))
10863 p_type = DCL_TYPE (type);
10867 /* we have to go by the storage class */
10868 p_type = PTR_TYPE (SPEC_OCLS (etype));
10871 /* special case when cast remat */
10872 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10873 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10874 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10875 type = operandType (result);
10876 p_type = DCL_TYPE (type);
10879 /* now that we have the pointer type we assign
10880 the pointer values */
10886 genNearPointerSet (right, result, ic, pi);
10890 genPagedPointerSet (right, result, ic, pi);
10894 genFarPointerSet (right, result, ic, pi);
10898 genGenPointerSet (right, result, ic, pi);
10902 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10903 "genPointerSet: illegal pointer type");
10907 /*-----------------------------------------------------------------*/
10908 /* genIfx - generate code for Ifx statement */
10909 /*-----------------------------------------------------------------*/
10911 genIfx (iCode * ic, iCode * popIc)
10913 operand *cond = IC_COND (ic);
10917 D (emitcode (";", "genIfx"));
10919 aopOp (cond, ic, FALSE);
10921 /* get the value into acc */
10922 if (AOP_TYPE (cond) != AOP_CRY)
10929 if (AOP(cond)->aopu.aop_dir)
10930 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10933 /* the result is now in the accumulator or a directly addressable bit */
10934 freeAsmop (cond, NULL, ic, TRUE);
10936 /* if there was something to be popped then do it */
10940 /* if the condition is a bit variable */
10942 genIfxJump(ic, dup, NULL, NULL, NULL);
10943 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10944 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10945 else if (isbit && !IS_ITEMP (cond))
10946 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10948 genIfxJump (ic, "a", NULL, NULL, NULL);
10953 /*-----------------------------------------------------------------*/
10954 /* genAddrOf - generates code for address of */
10955 /*-----------------------------------------------------------------*/
10957 genAddrOf (iCode * ic)
10959 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10962 D (emitcode (";", "genAddrOf"));
10964 aopOp (IC_RESULT (ic), ic, FALSE);
10966 /* if the operand is on the stack then we
10967 need to get the stack offset of this
10971 /* if it has an offset then we need to compute it */
10974 int stack_offset = ((sym->stack < 0) ?
10975 ((char) (sym->stack - _G.nRegsSaved)) :
10976 ((char) sym->stack)) & 0xff;
10977 if ((abs(stack_offset) == 1) &&
10978 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10979 !isOperandVolatile (IC_RESULT (ic), FALSE))
10981 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10982 if (stack_offset > 0)
10983 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10985 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10989 emitcode ("mov", "a,%s", SYM_BP (sym));
10990 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10991 aopPut (IC_RESULT (ic), "a", 0);
10996 /* we can just move _bp */
10997 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10999 /* fill the result with zero */
11000 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11005 aopPut (IC_RESULT (ic), zero, offset++);
11010 /* object not on stack then we need the name */
11011 size = AOP_SIZE (IC_RESULT (ic));
11016 char s[SDCC_NAME_MAX];
11018 sprintf (s, "#(%s >> %d)",
11022 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11023 aopPut (IC_RESULT (ic), s, offset++);
11027 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11031 /*-----------------------------------------------------------------*/
11032 /* genFarFarAssign - assignment when both are in far space */
11033 /*-----------------------------------------------------------------*/
11035 genFarFarAssign (operand * result, operand * right, iCode * ic)
11037 int size = AOP_SIZE (right);
11041 D (emitcode (";", "genFarFarAssign"));
11043 /* first push the right side on to the stack */
11046 l = aopGet (right, offset++, FALSE, FALSE);
11048 emitcode ("push", "acc");
11051 freeAsmop (right, NULL, ic, FALSE);
11052 /* now assign DPTR to result */
11053 aopOp (result, ic, FALSE);
11054 size = AOP_SIZE (result);
11057 emitcode ("pop", "acc");
11058 aopPut (result, "a", --offset);
11060 freeAsmop (result, NULL, ic, FALSE);
11063 /*-----------------------------------------------------------------*/
11064 /* genAssign - generate code for assignment */
11065 /*-----------------------------------------------------------------*/
11067 genAssign (iCode * ic)
11069 operand *result, *right;
11071 unsigned long lit = 0L;
11073 D (emitcode (";", "genAssign"));
11075 result = IC_RESULT (ic);
11076 right = IC_RIGHT (ic);
11078 /* if they are the same */
11079 if (operandsEqu (result, right) &&
11080 !isOperandVolatile (result, FALSE) &&
11081 !isOperandVolatile (right, FALSE))
11084 aopOp (right, ic, FALSE);
11086 /* special case both in far space */
11087 if (AOP_TYPE (right) == AOP_DPTR &&
11088 IS_TRUE_SYMOP (result) &&
11089 isOperandInFarSpace (result))
11091 genFarFarAssign (result, right, ic);
11095 aopOp (result, ic, TRUE);
11097 /* if they are the same registers */
11098 if (sameRegs (AOP (right), AOP (result)) &&
11099 !isOperandVolatile (result, FALSE) &&
11100 !isOperandVolatile (right, FALSE))
11103 /* if the result is a bit */
11104 if (AOP_TYPE (result) == AOP_CRY)
11106 assignBit (result, right);
11110 /* bit variables done */
11112 size = AOP_SIZE (result);
11114 if (AOP_TYPE (right) == AOP_LIT)
11115 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11118 (AOP_TYPE (result) != AOP_REG) &&
11119 (AOP_TYPE (right) == AOP_LIT) &&
11120 !IS_FLOAT (operandType (right)) &&
11123 while ((size) && (lit))
11126 aopGet (right, offset, FALSE, FALSE),
11132 /* And now fill the rest with zeros. */
11135 emitcode ("clr", "a");
11139 aopPut (result, "a", offset);
11148 aopGet (right, offset, FALSE, FALSE),
11155 freeAsmop (result, NULL, ic, TRUE);
11156 freeAsmop (right, NULL, ic, TRUE);
11159 /*-----------------------------------------------------------------*/
11160 /* genJumpTab - generates code for jump table */
11161 /*-----------------------------------------------------------------*/
11163 genJumpTab (iCode * ic)
11165 symbol *jtab,*jtablo,*jtabhi;
11167 unsigned int count;
11169 D (emitcode (";", "genJumpTab"));
11171 count = elementsInSet( IC_JTLABELS (ic) );
11175 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11176 if the switch argument is in a register.
11177 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11178 /* Peephole may not convert ljmp to sjmp or ret
11179 labelIsReturnOnly & labelInRange must check
11180 currPl->ic->op != JUMPTABLE */
11181 aopOp (IC_JTCOND (ic), ic, FALSE);
11182 /* get the condition into accumulator */
11183 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11185 /* multiply by three */
11186 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11188 emitcode ("mov", "b,#3");
11189 emitcode ("mul", "ab");
11193 emitcode ("add", "a,acc");
11194 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11196 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11198 jtab = newiTempLabel (NULL);
11199 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11200 emitcode ("jmp", "@a+dptr");
11202 /* now generate the jump labels */
11203 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11204 jtab = setNextItem (IC_JTLABELS (ic)))
11205 emitcode ("ljmp", "%05d$", jtab->key + 100);
11209 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11210 if the switch argument is in a register.
11211 For n>6 this algorithm may be more compact */
11212 jtablo = newiTempLabel (NULL);
11213 jtabhi = newiTempLabel (NULL);
11215 /* get the condition into accumulator.
11216 Using b as temporary storage, if register push/pop is needed */
11217 aopOp (IC_JTCOND (ic), ic, FALSE);
11218 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11219 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11220 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11222 // (MB) what if B is in use???
11223 wassertl(!BINUSE, "B was in use");
11224 emitcode ("mov", "b,%s", l);
11227 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11231 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11232 emitcode ("movc", "a,@a+pc");
11233 emitcode ("push", "acc");
11236 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11237 emitcode ("movc", "a,@a+pc");
11238 emitcode ("push", "acc");
11242 /* this scales up to n<=255, but needs two more bytes
11243 and changes dptr */
11244 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11245 emitcode ("movc", "a,@a+dptr");
11246 emitcode ("push", "acc");
11249 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11250 emitcode ("movc", "a,@a+dptr");
11251 emitcode ("push", "acc");
11254 emitcode ("ret", "");
11256 /* now generate jump table, LSB */
11257 emitLabel (jtablo);
11258 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11259 jtab = setNextItem (IC_JTLABELS (ic)))
11260 emitcode (".db", "%05d$", jtab->key + 100);
11262 /* now generate jump table, MSB */
11263 emitLabel (jtabhi);
11264 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11265 jtab = setNextItem (IC_JTLABELS (ic)))
11266 emitcode (".db", "%05d$>>8", jtab->key + 100);
11270 /*-----------------------------------------------------------------*/
11271 /* genCast - gen code for casting */
11272 /*-----------------------------------------------------------------*/
11274 genCast (iCode * ic)
11276 operand *result = IC_RESULT (ic);
11277 sym_link *ctype = operandType (IC_LEFT (ic));
11278 sym_link *rtype = operandType (IC_RIGHT (ic));
11279 operand *right = IC_RIGHT (ic);
11282 D (emitcode (";", "genCast"));
11284 /* if they are equivalent then do nothing */
11285 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11288 aopOp (right, ic, FALSE);
11289 aopOp (result, ic, FALSE);
11291 /* if the result is a bit (and not a bitfield) */
11292 if (IS_BIT (OP_SYMBOL (result)->type))
11294 assignBit (result, right);
11298 /* if they are the same size : or less */
11299 if (AOP_SIZE (result) <= AOP_SIZE (right))
11302 /* if they are in the same place */
11303 if (sameRegs (AOP (right), AOP (result)))
11306 /* if they in different places then copy */
11307 size = AOP_SIZE (result);
11312 aopGet (right, offset, FALSE, FALSE),
11319 /* if the result is of type pointer */
11320 if (IS_PTR (ctype))
11324 sym_link *type = operandType (right);
11325 sym_link *etype = getSpec (type);
11327 /* pointer to generic pointer */
11328 if (IS_GENPTR (ctype))
11332 p_type = DCL_TYPE (type);
11336 if (SPEC_SCLS(etype)==S_REGISTER) {
11337 // let's assume it is a generic pointer
11340 /* we have to go by the storage class */
11341 p_type = PTR_TYPE (SPEC_OCLS (etype));
11345 /* the first two bytes are known */
11346 size = GPTRSIZE - 1;
11351 aopGet (right, offset, FALSE, FALSE),
11355 /* the last byte depending on type */
11357 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11362 // pointerTypeToGPByte will have bitched.
11366 sprintf(gpValStr, "#0x%x", gpVal);
11367 aopPut (result, gpValStr, GPTRSIZE - 1);
11372 /* just copy the pointers */
11373 size = AOP_SIZE (result);
11378 aopGet (right, offset, FALSE, FALSE),
11385 /* so we now know that the size of destination is greater
11386 than the size of the source */
11387 /* we move to result for the size of source */
11388 size = AOP_SIZE (right);
11393 aopGet (right, offset, FALSE, FALSE),
11398 /* now depending on the sign of the source && destination */
11399 size = AOP_SIZE (result) - AOP_SIZE (right);
11400 /* if unsigned or not an integral type */
11401 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11404 aopPut (result, zero, offset++);
11408 /* we need to extend the sign :{ */
11409 char *l = aopGet (right, AOP_SIZE (right) - 1,
11412 emitcode ("rlc", "a");
11413 emitcode ("subb", "a,acc");
11415 aopPut (result, "a", offset++);
11418 /* we are done hurray !!!! */
11421 freeAsmop (result, NULL, ic, TRUE);
11422 freeAsmop (right, NULL, ic, TRUE);
11425 /*-----------------------------------------------------------------*/
11426 /* genDjnz - generate decrement & jump if not zero instrucion */
11427 /*-----------------------------------------------------------------*/
11429 genDjnz (iCode * ic, iCode * ifx)
11431 symbol *lbl, *lbl1;
11435 /* if the if condition has a false label
11436 then we cannot save */
11437 if (IC_FALSE (ifx))
11440 /* if the minus is not of the form a = a - 1 */
11441 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11442 !IS_OP_LITERAL (IC_RIGHT (ic)))
11445 if (operandLitValue (IC_RIGHT (ic)) != 1)
11448 /* if the size of this greater than one then no
11450 if (getSize (operandType (IC_RESULT (ic))) > 1)
11453 /* otherwise we can save BIG */
11455 D (emitcode (";", "genDjnz"));
11457 lbl = newiTempLabel (NULL);
11458 lbl1 = newiTempLabel (NULL);
11460 aopOp (IC_RESULT (ic), ic, FALSE);
11462 if (AOP_NEEDSACC(IC_RESULT(ic)))
11464 /* If the result is accessed indirectly via
11465 * the accumulator, we must explicitly write
11466 * it back after the decrement.
11468 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11470 if (strcmp(rByte, "a"))
11472 /* Something is hopelessly wrong */
11473 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11474 __FILE__, __LINE__);
11475 /* We can just give up; the generated code will be inefficient,
11476 * but what the hey.
11478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11481 emitcode ("dec", "%s", rByte);
11482 aopPut (IC_RESULT (ic), rByte, 0);
11483 emitcode ("jnz", "%05d$", lbl->key + 100);
11485 else if (IS_AOP_PREG (IC_RESULT (ic)))
11487 emitcode ("dec", "%s",
11488 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11489 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11490 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11491 ifx->generated = 1;
11492 emitcode ("jnz", "%05d$", lbl->key + 100);
11496 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11499 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11501 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11504 if (!ifx->generated)
11505 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11506 ifx->generated = 1;
11510 /*-----------------------------------------------------------------*/
11511 /* genReceive - generate code for a receive iCode */
11512 /*-----------------------------------------------------------------*/
11514 genReceive (iCode * ic)
11516 int size = getSize (operandType (IC_RESULT (ic)));
11519 D (emitcode (";", "genReceive"));
11521 if (ic->argreg == 1)
11522 { /* first parameter */
11523 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11524 isOperandInPagedSpace (IC_RESULT (ic))) &&
11525 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11526 IS_TRUE_SYMOP (IC_RESULT (ic))))
11529 int receivingA = 0;
11532 for (offset = 0; offset<size; offset++)
11533 if (!strcmp (fReturn[offset], "a"))
11538 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11540 for (offset = size-1; offset>0; offset--)
11541 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11542 emitcode("mov","a,%s", fReturn[0]);
11544 aopOp (IC_RESULT (ic), ic, FALSE);
11546 aopPut (IC_RESULT (ic), "a", offset);
11547 for (offset = 1; offset<size; offset++)
11548 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11554 if (getTempRegs(tempRegs, size, ic))
11556 for (offset = 0; offset<size; offset++)
11557 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11558 aopOp (IC_RESULT (ic), ic, FALSE);
11559 for (offset = 0; offset<size; offset++)
11560 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11565 offset = fReturnSizeMCS51 - size;
11568 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11569 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11572 aopOp (IC_RESULT (ic), ic, FALSE);
11573 size = AOP_SIZE (IC_RESULT (ic));
11577 emitcode ("pop", "acc");
11578 aopPut (IC_RESULT (ic), "a", offset++);
11584 aopOp (IC_RESULT (ic), ic, FALSE);
11586 assignResultValue (IC_RESULT (ic), NULL);
11589 else if (ic->argreg > 12)
11590 { /* bit parameters */
11591 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11593 aopOp (IC_RESULT (ic), ic, FALSE);
11594 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11595 outBitC(IC_RESULT (ic));
11599 { /* other parameters */
11601 aopOp (IC_RESULT (ic), ic, FALSE);
11602 rb1off = ic->argreg;
11605 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11613 /*-----------------------------------------------------------------*/
11614 /* genDummyRead - generate code for dummy read of volatiles */
11615 /*-----------------------------------------------------------------*/
11617 genDummyRead (iCode * ic)
11622 D (emitcode(";", "genDummyRead"));
11624 op = IC_RIGHT (ic);
11625 if (op && IS_SYMOP (op))
11627 aopOp (op, ic, FALSE);
11629 /* if the result is a bit */
11630 if (AOP_TYPE (op) == AOP_CRY)
11631 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11634 /* bit variables done */
11636 size = AOP_SIZE (op);
11640 MOVA (aopGet (op, offset, FALSE, FALSE));
11645 freeAsmop (op, NULL, ic, TRUE);
11649 if (op && IS_SYMOP (op))
11651 aopOp (op, ic, FALSE);
11653 /* if the result is a bit */
11654 if (AOP_TYPE (op) == AOP_CRY)
11655 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11658 /* bit variables done */
11660 size = AOP_SIZE (op);
11664 MOVA (aopGet (op, offset, FALSE, FALSE));
11669 freeAsmop (op, NULL, ic, TRUE);
11673 /*-----------------------------------------------------------------*/
11674 /* genCritical - generate code for start of a critical sequence */
11675 /*-----------------------------------------------------------------*/
11677 genCritical (iCode *ic)
11679 symbol *tlbl = newiTempLabel (NULL);
11681 D (emitcode(";", "genCritical"));
11683 if (IC_RESULT (ic))
11685 aopOp (IC_RESULT (ic), ic, TRUE);
11686 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11687 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11688 aopPut (IC_RESULT (ic), zero, 0);
11690 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11694 emitcode ("setb", "c");
11695 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11696 emitcode ("clr", "c");
11698 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11702 /*-----------------------------------------------------------------*/
11703 /* genEndCritical - generate code for end of a critical sequence */
11704 /*-----------------------------------------------------------------*/
11706 genEndCritical (iCode *ic)
11708 D(emitcode(";", "genEndCritical"));
11712 aopOp (IC_RIGHT (ic), ic, FALSE);
11713 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11715 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11716 emitcode ("mov", "ea,c");
11720 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11721 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11722 emitcode ("rrc", "a");
11723 emitcode ("mov", "ea,c");
11725 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11729 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11730 emitcode ("mov", "ea,c");
11734 /*-----------------------------------------------------------------*/
11735 /* gen51Code - generate code for 8051 based controllers */
11736 /*-----------------------------------------------------------------*/
11738 gen51Code (iCode * lic)
11742 /* int cseq = 0; */
11744 _G.currentFunc = NULL;
11745 lineHead = lineCurr = NULL;
11747 /* print the allocation information */
11748 if (allocInfo && currFunc)
11749 printAllocInfo (currFunc, codeOutBuf);
11750 /* if debug information required */
11751 if (options.debug && currFunc)
11753 debugFile->writeFunction (currFunc, lic);
11755 /* stack pointer name */
11756 if (options.useXstack)
11762 for (ic = lic; ic; ic = ic->next)
11764 _G.current_iCode = ic;
11766 if (ic->lineno && cln != ic->lineno)
11770 debugFile->writeCLine (ic);
11772 if (!options.noCcodeInAsm) {
11773 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11774 printCLine(ic->filename, ic->lineno));
11779 if (ic->seqPoint && ic->seqPoint != cseq)
11781 emitcode (";", "sequence point %d", ic->seqPoint);
11782 cseq = ic->seqPoint;
11785 if (options.iCodeInAsm) {
11786 char regsInUse[80];
11791 for (i=0; i<8; i++) {
11792 sprintf (®sInUse[i],
11793 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11796 strcpy (regsInUse, "--------");
11797 for (i=0; i < 8; i++) {
11798 if (bitVectBitValue (ic->rMask, i))
11800 int offset = regs8051[i].offset;
11801 regsInUse[offset] = offset + '0'; /* show rMask */
11805 iLine = printILine(ic);
11806 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11809 /* if the result is marked as
11810 spilt and rematerializable or code for
11811 this has already been generated then
11813 if (resultRemat (ic) || ic->generated)
11816 /* depending on the operation */
11836 /* IPOP happens only when trying to restore a
11837 spilt live range, if there is an ifx statement
11838 following this pop then the if statement might
11839 be using some of the registers being popped which
11840 would destory the contents of the register so
11841 we need to check for this condition and handle it */
11843 ic->next->op == IFX &&
11844 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11845 genIfx (ic->next, ic);
11863 genEndFunction (ic);
11883 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11900 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11904 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11911 /* note these two are xlated by algebraic equivalence
11912 in decorateType() in SDCCast.c */
11913 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11914 "got '>=' or '<=' shouldn't have come here");
11918 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11930 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11934 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11938 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11974 genRightShift (ic);
11977 case GET_VALUE_AT_ADDRESS:
11979 hasInc (IC_LEFT (ic), ic,
11980 getSize (operandType (IC_RESULT (ic)))),
11981 ifxForOp (IC_RESULT (ic), ic) );
11985 if (POINTER_SET (ic))
11987 hasInc (IC_RESULT (ic), ic,
11988 getSize (operandType (IC_RIGHT (ic)))));
12014 addSet (&_G.sendSet, ic);
12017 case DUMMY_READ_VOLATILE:
12026 genEndCritical (ic);
12038 _G.current_iCode = NULL;
12040 /* now we are ready to call the
12041 peep hole optimizer */
12042 if (!options.nopeep)
12043 peepHole (&lineHead);
12045 /* now do the actual printing */
12046 printLine (lineHead, codeOutBuf);