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 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 #include "dbuf_string.h"
48 char *aopLiteral (value * val, int offset);
49 char *aopLiteralLong (value * val, int offset, int size);
52 /* this is the down and dirty file with all kinds of
53 kludgy & hacky stuff. This is what it is all about
54 CODE GENERATION for a specific MCU . some of the
55 routines may be reusable, will have to see */
57 static char *zero = "#0x00";
58 static char *one = "#0x01";
62 {"dpl", "dph", "b", "a"};
63 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
64 char **fReturn = fReturn8051;
65 static char *accUse[] =
68 static unsigned short rbank = -1;
70 #define REG_WITH_INDEX mcs51_regWithIdx
72 #define AOP(op) op->aop
73 #define AOP_TYPE(op) AOP(op)->type
74 #define AOP_SIZE(op) AOP(op)->size
75 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
76 AOP_TYPE(x) == AOP_R0))
78 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
79 AOP_TYPE(x) == AOP_DPTR || \
82 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
83 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
84 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
86 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
88 #define R0INB _G.bu.bs.r0InB
89 #define R1INB _G.bu.bs.r1InB
90 #define OPINB _G.bu.bs.OpInB
91 #define BINUSE _G.bu.BInUse
101 short r0InB : 2;//2 so we can see it overflow
102 short r1InB : 2;//2 so we can see it overflow
103 short OpInB : 2;//2 so we can see it overflow
112 iCode *current_iCode;
117 static char *rb1regs[] = {
118 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
119 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
122 extern struct dbuf_s *codeOutBuf;
123 static void saveRBank (int, iCode *, bool);
125 #define RESULTONSTACK(x) \
126 (IC_RESULT(x) && IC_RESULT(x)->aop && \
127 IC_RESULT(x)->aop->type == AOP_STK )
129 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
130 #define MOVB(x) movb(x)
132 #define CLRC emitcode("clr","c")
133 #define SETC emitcode("setb","c")
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
138 static unsigned char SLMask[] =
139 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
140 0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char SRMask[] =
142 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
143 0x07, 0x03, 0x01, 0x00};
150 /*-----------------------------------------------------------------*/
151 /* emitcode - writes the code into a file : for now it is simple */
152 /*-----------------------------------------------------------------*/
154 emitcode (const char *inst, const char *fmt,...)
158 const char *lbp, *lb;
160 dbuf_init (&dbuf, INITIAL_INLINEASM);
166 dbuf_append_str (&dbuf, inst);
170 dbuf_append_char (&dbuf, '\t');
171 dbuf_tvprintf (&dbuf, fmt, ap);
176 dbuf_tvprintf (&dbuf, fmt, ap);
179 lbp = lb = dbuf_c_str(&dbuf);
181 while (isspace ((unsigned char)*lbp))
190 lineCurr = (lineCurr ?
191 connectLine (lineCurr, newLineNode (lb)) :
192 (lineHead = newLineNode (lb)));
195 lineCurr->isInline = _G.inLine;
196 lineCurr->isDebug = _G.debugLine;
197 lineCurr->ic = _G.current_iCode;
198 lineCurr->isComment = (*lbp==';');
205 emitLabel (symbol *tlbl)
207 emitcode ("", "%05d$:", tlbl->key + 100);
208 lineCurr->isLabel = 1;
211 /*-----------------------------------------------------------------*/
212 /* mcs51_emitDebuggerSymbol - associate the current code location */
213 /* with a debugger symbol */
214 /*-----------------------------------------------------------------*/
216 mcs51_emitDebuggerSymbol (char * debugSym)
219 emitcode ("", "%s ==.", debugSym);
223 /*-----------------------------------------------------------------*/
224 /* mova - moves specified value into accumulator */
225 /*-----------------------------------------------------------------*/
229 /* do some early peephole optimization */
230 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
233 /* if it is a literal mov try to get it cheaper */
238 emitcode("mov", "a,%s", x);
241 /*-----------------------------------------------------------------*/
242 /* movb - moves specified value into register b */
243 /*-----------------------------------------------------------------*/
247 /* do some early peephole optimization */
248 if (!strncmp(x, "b", 2))
251 /* if it is a literal mov try to get it cheaper */
254 emitcode("mov","b,%s", rtrackGetLit(x));
258 emitcode("mov","b,%s", x);
261 /*-----------------------------------------------------------------*/
262 /* movc - moves specified value into the carry */
263 /*-----------------------------------------------------------------*/
267 if (!strcmp (s, zero))
269 else if (!strcmp (s, one))
271 else if (strcmp (s, "c"))
272 {/* it's not in carry already */
274 /* set C, if a >= 1 */
275 emitcode ("add", "a,#0xff");
279 /*-----------------------------------------------------------------*/
280 /* pushB - saves register B if necessary */
281 /*-----------------------------------------------------------------*/
285 bool pushedB = FALSE;
289 emitcode ("push", "b");
290 // printf("B was in use !\n");
300 /*-----------------------------------------------------------------*/
301 /* popB - restores value of register B if necessary */
302 /*-----------------------------------------------------------------*/
308 emitcode ("pop", "b");
316 /*-----------------------------------------------------------------*/
317 /* pushReg - saves register */
318 /*-----------------------------------------------------------------*/
320 pushReg (int index, bool bits_pushed)
322 regs * reg = REG_WITH_INDEX (index);
323 if (reg->type == REG_BIT)
326 emitcode ("push", "%s", reg->base);
330 emitcode ("push", "%s", reg->dname);
334 /*-----------------------------------------------------------------*/
335 /* popReg - restores register */
336 /*-----------------------------------------------------------------*/
338 popReg (int index, bool bits_popped)
340 regs * reg = REG_WITH_INDEX (index);
341 if (reg->type == REG_BIT)
344 emitcode ("pop", "%s", reg->base);
348 emitcode ("pop", "%s", reg->dname);
352 /*-----------------------------------------------------------------*/
353 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
354 /*-----------------------------------------------------------------*/
356 getFreePtr (iCode * ic, asmop ** aopp, bool result)
361 /* the logic: if r0 & r1 used in the instruction
362 then we are in trouble otherwise */
364 /* first check if r0 & r1 are used by this
365 instruction, in which case we are in trouble */
366 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
367 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
372 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
373 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
375 /* if no usage of r0 then return it */
378 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
379 (*aopp)->type = AOP_R0;
381 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
384 /* if no usage of r1 then return it */
387 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
388 (*aopp)->type = AOP_R1;
390 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
393 /* now we know they both have usage */
394 /* if r0 not used in this instruction */
397 /* push it if not already pushed */
400 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
403 else if (!_G.r0Pushed)
405 emitcode ("push", "%s",
406 REG_WITH_INDEX (R0_IDX)->dname);
410 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
411 (*aopp)->type = AOP_R0;
413 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
416 /* if r1 not used then */
420 /* push it if not already pushed */
423 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
426 else if (!_G.r1Pushed)
428 emitcode ("push", "%s",
429 REG_WITH_INDEX (R1_IDX)->dname);
433 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
434 (*aopp)->type = AOP_R1;
435 return REG_WITH_INDEX (R1_IDX);
439 /* I said end of world, but not quite end of world yet */
440 /* if this is a result then we can push it on the stack */
443 (*aopp)->type = AOP_STK;
446 /* in the case that result AND left AND right needs a pointer reg
447 we can safely use the result's */
448 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
450 (*aopp)->type = AOP_R0;
451 return REG_WITH_INDEX (R0_IDX);
453 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
455 (*aopp)->type = AOP_R1;
456 return REG_WITH_INDEX (R1_IDX);
459 /* now this is REALLY the end of the world */
460 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
461 "getFreePtr should never reach here");
466 /*-----------------------------------------------------------------*/
467 /* getTempRegs - initialize an array of pointers to GPR registers */
468 /* that are not in use. Returns 1 if the requested */
469 /* number of registers were available, 0 otherwise. */
470 /*-----------------------------------------------------------------*/
472 getTempRegs(regs **tempRegs, int size, iCode *ic)
479 ic = _G.current_iCode;
485 freeRegs = newBitVect(8);
486 bitVectSetBit (freeRegs, R2_IDX);
487 bitVectSetBit (freeRegs, R3_IDX);
488 bitVectSetBit (freeRegs, R4_IDX);
489 bitVectSetBit (freeRegs, R5_IDX);
490 bitVectSetBit (freeRegs, R6_IDX);
491 bitVectSetBit (freeRegs, R7_IDX);
493 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
495 bitVect * newfreeRegs;
496 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
497 freeBitVect(freeRegs);
498 freeRegs = newfreeRegs;
500 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
503 for (i=0; i<freeRegs->size; i++)
505 if (bitVectBitValue(freeRegs,i))
506 tempRegs[offset++] = REG_WITH_INDEX(i);
509 freeBitVect(freeRegs);
514 freeBitVect(freeRegs);
519 /*-----------------------------------------------------------------*/
520 /* newAsmop - creates a new asmOp */
521 /*-----------------------------------------------------------------*/
523 newAsmop (short type)
527 aop = Safe_calloc (1, sizeof (asmop));
533 /*-----------------------------------------------------------------*/
534 /* pointerCode - returns the code for a pointer type */
535 /*-----------------------------------------------------------------*/
537 pointerCode (sym_link * etype)
540 return PTR_TYPE (SPEC_OCLS (etype));
544 /*-----------------------------------------------------------------*/
545 /* leftRightUseAcc - returns size of accumulator use by operands */
546 /*-----------------------------------------------------------------*/
548 leftRightUseAcc(iCode *ic)
557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
558 "null iCode pointer");
565 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
568 size = getSize (OP_SYMBOL (op)->type);
573 else if (ic->op == JUMPTABLE)
576 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
579 size = getSize (OP_SYMBOL (op)->type);
587 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
590 size = getSize (OP_SYMBOL (op)->type);
595 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
598 size = getSize (OP_SYMBOL (op)->type);
610 /*-----------------------------------------------------------------*/
611 /* aopForSym - for a true symbol */
612 /*-----------------------------------------------------------------*/
614 aopForSym (iCode * ic, symbol * sym, bool result)
618 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
620 wassertl (ic != NULL, "Got a null iCode");
621 wassertl (sym != NULL, "Got a null symbol");
623 space = SPEC_OCLS (sym->etype);
625 /* if already has one */
628 sym->aop->allocated++;
632 /* assign depending on the storage class */
633 /* if it is on the stack or indirectly addressable */
634 /* space we need to assign either r0 or r1 to it */
635 if (sym->onStack || sym->iaccess)
637 sym->aop = aop = newAsmop (0);
638 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
639 aop->size = getSize (sym->type);
641 /* now assign the address of the variable to
642 the pointer register */
643 if (aop->type != AOP_STK)
647 signed char offset = ((sym->stack < 0) ?
648 ((signed char) (sym->stack - _G.nRegsSaved)) :
649 ((signed char) sym->stack)) & 0xff;
651 if ((abs(offset) <= 3) ||
652 (accuse && (abs(offset) <= 7)))
654 emitcode ("mov", "%s,%s",
655 aop->aopu.aop_ptr->name, SYM_BP (sym));
658 emitcode ("dec", aop->aopu.aop_ptr->name);
663 emitcode ("inc", aop->aopu.aop_ptr->name);
670 emitcode ("push", "acc");
671 emitcode ("mov", "a,%s", SYM_BP (sym));
672 emitcode ("add", "a,#0x%02x", offset & 0xff);
673 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
675 emitcode ("pop", "acc");
680 emitcode ("mov", "%s,#%s",
681 aop->aopu.aop_ptr->name,
684 aop->paged = space->paged;
687 aop->aopu.aop_stk = sym->stack;
691 /* if in bit space */
692 if (IN_BITSPACE (space))
694 sym->aop = aop = newAsmop (AOP_CRY);
695 aop->aopu.aop_dir = sym->rname;
696 aop->size = getSize (sym->type);
699 /* if it is in direct space */
700 if (IN_DIRSPACE (space))
702 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
703 //printTypeChainRaw(sym->type, NULL);
704 //printf("space = %s\n", space ? space->sname : "NULL");
705 sym->aop = aop = newAsmop (AOP_DIR);
706 aop->aopu.aop_dir = sym->rname;
707 aop->size = getSize (sym->type);
711 /* special case for a function */
712 if (IS_FUNC (sym->type))
714 sym->aop = aop = newAsmop (AOP_IMMD);
715 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
716 aop->size = getSize (sym->type);
720 /* only remaining is far space */
721 /* in which case DPTR gets the address */
722 sym->aop = aop = newAsmop (AOP_DPTR);
723 emitcode ("mov", "dptr,#%s", sym->rname);
724 aop->size = getSize (sym->type);
726 /* if it is in code space */
727 if (IN_CODESPACE (space))
733 /*-----------------------------------------------------------------*/
734 /* aopForRemat - rematerialzes an object */
735 /*-----------------------------------------------------------------*/
737 aopForRemat (symbol * sym)
739 iCode *ic = sym->rematiCode;
740 asmop *aop = newAsmop (AOP_IMMD);
747 val += (int) operandLitValue (IC_RIGHT (ic));
748 else if (ic->op == '-')
749 val -= (int) operandLitValue (IC_RIGHT (ic));
750 else if (IS_CAST_ICODE(ic)) {
751 sym_link *from_type = operandType(IC_RIGHT(ic));
752 aop->aopu.aop_immd.from_cast_remat = 1;
753 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
754 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
758 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
763 SNPRINTF (buffer, sizeof(buffer),
765 OP_SYMBOL (IC_LEFT (ic))->rname,
766 val >= 0 ? '+' : '-',
771 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
774 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
775 /* set immd2 field if required */
776 if (aop->aopu.aop_immd.from_cast_remat)
778 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
779 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
785 /*-----------------------------------------------------------------*/
786 /* regsInCommon - two operands have some registers in common */
787 /*-----------------------------------------------------------------*/
789 regsInCommon (operand * op1, operand * op2)
794 /* if they have registers in common */
795 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
798 sym1 = OP_SYMBOL (op1);
799 sym2 = OP_SYMBOL (op2);
801 if (sym1->nRegs == 0 || sym2->nRegs == 0)
804 for (i = 0; i < sym1->nRegs; i++)
810 for (j = 0; j < sym2->nRegs; j++)
815 if (sym2->regs[j] == sym1->regs[i])
823 /*-----------------------------------------------------------------*/
824 /* operandsEqu - equivalent */
825 /*-----------------------------------------------------------------*/
827 operandsEqu (operand * op1, operand * op2)
831 /* if they're not symbols */
832 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
835 sym1 = OP_SYMBOL (op1);
836 sym2 = OP_SYMBOL (op2);
838 /* if both are itemps & one is spilt
839 and the other is not then false */
840 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
841 sym1->isspilt != sym2->isspilt)
844 /* if they are the same */
848 /* if they have the same rname */
849 if (sym1->rname[0] && sym2->rname[0] &&
850 strcmp (sym1->rname, sym2->rname) == 0 &&
851 !(IS_PARM (op2) && IS_ITEMP (op1)))
854 /* if left is a tmp & right is not */
855 if (IS_ITEMP (op1) &&
858 (sym1->usl.spillLoc == sym2))
861 if (IS_ITEMP (op2) &&
865 (sym2->usl.spillLoc == sym1))
871 /*-----------------------------------------------------------------*/
872 /* sameByte - two asmops have the same address at given offsets */
873 /*-----------------------------------------------------------------*/
875 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
877 if (aop1 == aop2 && off1 == off2)
880 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
883 if (aop1->type != aop2->type)
886 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
892 /*-----------------------------------------------------------------*/
893 /* sameRegs - two asmops have the same registers */
894 /*-----------------------------------------------------------------*/
896 sameRegs (asmop * aop1, asmop * aop2)
903 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
906 if (aop1->type != aop2->type)
909 if (aop1->size != aop2->size)
912 for (i = 0; i < aop1->size; i++)
913 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
919 /*-----------------------------------------------------------------*/
920 /* aopOp - allocates an asmop for an operand : */
921 /*-----------------------------------------------------------------*/
923 aopOp (operand * op, iCode * ic, bool result)
932 /* if this a literal */
933 if (IS_OP_LITERAL (op))
935 op->aop = aop = newAsmop (AOP_LIT);
936 aop->aopu.aop_lit = op->operand.valOperand;
937 aop->size = getSize (operandType (op));
941 /* if already has a asmop then continue */
944 op->aop->allocated++;
948 /* if the underlying symbol has a aop */
949 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
951 op->aop = OP_SYMBOL (op)->aop;
952 op->aop->allocated++;
956 /* if this is a true symbol */
957 if (IS_TRUE_SYMOP (op))
959 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
963 /* this is a temporary : this has
969 e) can be a return use only */
971 sym = OP_SYMBOL (op);
973 /* if the type is a conditional */
974 if (sym->regType == REG_CND)
976 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
981 /* if it is spilt then two situations
983 b) has a spill location */
984 if (sym->isspilt || sym->nRegs == 0)
987 /* rematerialize it NOW */
990 sym->aop = op->aop = aop = aopForRemat (sym);
991 aop->size = getSize (sym->type);
998 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
999 aop->size = getSize (sym->type);
1000 for (i = 0; i < 2; i++)
1001 aop->aopu.aop_str[i] = accUse[i];
1009 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1010 aop->size = getSize (sym->type);
1011 for (i = 0; i < fReturnSizeMCS51; i++)
1012 aop->aopu.aop_str[i] = fReturn[i];
1016 if (sym->usl.spillLoc)
1018 asmop *oldAsmOp = NULL;
1020 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1022 /* force a new aop if sizes differ */
1023 oldAsmOp = sym->usl.spillLoc->aop;
1024 sym->usl.spillLoc->aop = NULL;
1026 sym->aop = op->aop = aop =
1027 aopForSym (ic, sym->usl.spillLoc, result);
1028 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1030 /* Don't reuse the new aop, go with the last one */
1031 sym->usl.spillLoc->aop = oldAsmOp;
1033 aop->size = getSize (sym->type);
1037 /* else must be a dummy iTemp */
1038 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1039 aop->size = getSize (sym->type);
1043 /* if the type is a bit register */
1044 if (sym->regType == REG_BIT)
1046 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1047 aop->size = sym->nRegs;//1???
1048 aop->aopu.aop_reg[0] = sym->regs[0];
1049 aop->aopu.aop_dir = sym->regs[0]->name;
1053 /* must be in a register */
1054 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1055 aop->size = sym->nRegs;
1056 for (i = 0; i < sym->nRegs; i++)
1057 aop->aopu.aop_reg[i] = sym->regs[i];
1060 /*-----------------------------------------------------------------*/
1061 /* freeAsmop - free up the asmop given to an operand */
1062 /*----------------------------------------------------------------*/
1064 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1081 /* depending on the asmop type only three cases need work
1082 AOP_R0, AOP_R1 & AOP_STK */
1088 emitcode ("mov", "r0,b");
1091 else if (_G.r0Pushed)
1095 emitcode ("pop", "ar0");
1099 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 emitcode ("mov", "r1,b");
1108 else if (_G.r1Pushed)
1112 emitcode ("pop", "ar1");
1116 bitVectUnSetBit (ic->rUsed, R1_IDX);
1122 int stk = aop->aopu.aop_stk + aop->size - 1;
1123 bitVectUnSetBit (ic->rUsed, R0_IDX);
1124 bitVectUnSetBit (ic->rUsed, R1_IDX);
1126 getFreePtr (ic, &aop, FALSE);
1130 emitcode ("mov", "a,_bp");
1131 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1132 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1136 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1141 emitcode ("pop", "acc");
1142 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1145 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1148 freeAsmop (op, NULL, ic, TRUE);
1151 emitcode ("pop", "ar1");
1156 emitcode ("pop", "ar0");
1164 /* all other cases just dealloc */
1170 OP_SYMBOL (op)->aop = NULL;
1171 /* if the symbol has a spill */
1173 SPIL_LOC (op)->aop = NULL;
1178 /*------------------------------------------------------------------*/
1179 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1180 /* pop r0 or r1 off stack if pushed */
1181 /*------------------------------------------------------------------*/
1183 freeForBranchAsmop (operand * op)
1195 if (!aop->allocated)
1203 emitcode ("mov", "r0,b");
1205 else if (_G.r0Pushed)
1207 emitcode ("pop", "ar0");
1214 emitcode ("mov", "r1,b");
1216 else if (_G.r1Pushed)
1218 emitcode ("pop", "ar1");
1225 int stk = aop->aopu.aop_stk + aop->size - 1;
1227 emitcode ("mov", "b,r0");
1230 emitcode ("mov", "a,_bp");
1231 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1232 emitcode ("mov", "r0,a");
1236 emitcode ("mov", "r0,_bp");
1241 emitcode ("pop", "acc");
1242 emitcode ("mov", "@r0,a");
1245 emitcode ("dec", "r0");
1247 emitcode ("mov", "r0,b");
1253 /*-----------------------------------------------------------------*/
1254 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1255 /* clobber the accumulator */
1256 /*-----------------------------------------------------------------*/
1258 aopGetUsesAcc (operand * oper, int offset)
1260 asmop * aop = AOP (oper);
1262 if (offset > (aop->size - 1))
1280 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1291 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1297 /* Error case --- will have been caught already */
1303 /*-------------------------------------------------------------------*/
1304 /* aopGet - for fetching value of the aop */
1305 /*-------------------------------------------------------------------*/
1307 aopGet (operand * oper, int offset, bool bit16, bool dname)
1309 asmop * aop = AOP (oper);
1311 /* offset is greater than
1313 if (offset > (aop->size - 1) &&
1314 aop->type != AOP_LIT)
1317 /* depending on type */
1325 /* if we need to increment it */
1326 while (offset > aop->coff)
1328 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1332 while (offset < aop->coff)
1334 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1341 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1342 return (dname ? "acc" : "a");
1344 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1345 return Safe_strdup(buffer);
1348 if (aop->code && aop->coff==0 && offset>=1) {
1349 emitcode ("mov", "a,#0x%02x", offset);
1350 emitcode ("movc", "a,@a+dptr");
1351 return (dname ? "acc" : "a");
1354 while (offset > aop->coff)
1356 emitcode ("inc", "dptr");
1360 while (offset < aop->coff)
1362 emitcode ("lcall", "__decdptr");
1369 emitcode ("clr", "a");
1370 emitcode ("movc", "a,@a+dptr");
1374 emitcode ("movx", "a,@dptr");
1376 return (dname ? "acc" : "a");
1379 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1381 SNPRINTF(buffer, sizeof(buffer),
1382 "%s",aop->aopu.aop_immd.aop_immd2);
1386 SNPRINTF(buffer, sizeof(buffer),
1387 "#%s", aop->aopu.aop_immd.aop_immd1);
1391 SNPRINTF (buffer, sizeof(buffer),
1393 aop->aopu.aop_immd.aop_immd1,
1398 SNPRINTF (buffer, sizeof(buffer),
1400 aop->aopu.aop_immd.aop_immd1);
1402 return Safe_strdup(buffer);
1405 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1407 SNPRINTF (buffer, sizeof(buffer),
1409 aop->aopu.aop_dir, offset * 8);
1413 SNPRINTF (buffer, sizeof(buffer),
1420 SNPRINTF (buffer, sizeof(buffer),
1425 return Safe_strdup(buffer);
1429 return aop->aopu.aop_reg[offset]->dname;
1431 return aop->aopu.aop_reg[offset]->name;
1434 emitcode ("clr", "a");
1435 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1436 emitcode ("rlc", "a");
1437 return (dname ? "acc" : "a");
1440 if (!offset && dname)
1442 return aop->aopu.aop_str[offset];
1445 return aopLiteral (aop->aopu.aop_lit, offset);
1449 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1453 return aop->aopu.aop_str[offset];
1457 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1458 "aopget got unsupported aop->type");
1462 /*-----------------------------------------------------------------*/
1463 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1464 /* clobber the accumulator */
1465 /*-----------------------------------------------------------------*/
1467 aopPutUsesAcc (operand * oper, const char *s, int offset)
1469 asmop * aop = AOP (oper);
1471 if (offset > (aop->size - 1))
1481 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1487 return ((aop->paged) || (*s == '@'));
1491 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1499 /* Error case --- will have been caught already */
1505 /*-----------------------------------------------------------------*/
1506 /* aopPut - puts a string for a aop and indicates if acc is in use */
1507 /*-----------------------------------------------------------------*/
1509 aopPut (operand * result, const char *s, int offset)
1511 bool bvolatile = isOperandVolatile (result, FALSE);
1512 bool accuse = FALSE;
1513 asmop * aop = AOP (result);
1515 if (aop->size && offset > (aop->size - 1))
1517 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1518 "aopPut got offset > aop->size");
1522 /* will assign value to value */
1523 /* depending on where it is ofcourse */
1527 MOVA (s); /* read s in case it was volatile */
1532 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1534 SNPRINTF (buffer, sizeof(buffer),
1536 aop->aopu.aop_dir, offset * 8);
1540 SNPRINTF (buffer, sizeof(buffer),
1542 aop->aopu.aop_dir, offset);
1546 SNPRINTF (buffer, sizeof(buffer),
1551 if (strcmp (buffer, s) || bvolatile)
1553 emitcode ("mov", "%s,%s", buffer, s);
1555 if (!strcmp (buffer, "acc"))
1562 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1563 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1566 strcmp (s, "r0") == 0 ||
1567 strcmp (s, "r1") == 0 ||
1568 strcmp (s, "r2") == 0 ||
1569 strcmp (s, "r3") == 0 ||
1570 strcmp (s, "r4") == 0 ||
1571 strcmp (s, "r5") == 0 ||
1572 strcmp (s, "r6") == 0 ||
1573 strcmp (s, "r7") == 0)
1575 emitcode ("mov", "%s,%s",
1576 aop->aopu.aop_reg[offset]->dname, s);
1580 emitcode ("mov", "%s,%s",
1581 aop->aopu.aop_reg[offset]->name, s);
1589 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1590 "aopPut writing to code space");
1594 while (offset > aop->coff)
1597 emitcode ("inc", "dptr");
1600 while (offset < aop->coff)
1603 emitcode ("lcall", "__decdptr");
1608 /* if not in accumulator */
1611 emitcode ("movx", "@dptr,a");
1616 while (offset > aop->coff)
1619 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1621 while (offset < aop->coff)
1624 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1631 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1636 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1638 else if (strcmp (s, "r0") == 0 ||
1639 strcmp (s, "r1") == 0 ||
1640 strcmp (s, "r2") == 0 ||
1641 strcmp (s, "r3") == 0 ||
1642 strcmp (s, "r4") == 0 ||
1643 strcmp (s, "r5") == 0 ||
1644 strcmp (s, "r6") == 0 ||
1645 strcmp (s, "r7") == 0)
1648 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1649 emitcode ("mov", "@%s,%s",
1650 aop->aopu.aop_ptr->name, buffer);
1654 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1659 if (strcmp (s, "a") == 0)
1661 emitcode ("push", "acc");
1666 emitcode ("push", "acc");
1668 else if (strcmp (s, "r0") == 0 ||
1669 strcmp (s, "r1") == 0 ||
1670 strcmp (s, "r2") == 0 ||
1671 strcmp (s, "r3") == 0 ||
1672 strcmp (s, "r4") == 0 ||
1673 strcmp (s, "r5") == 0 ||
1674 strcmp (s, "r6") == 0 ||
1675 strcmp (s, "r7") == 0)
1678 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1679 emitcode ("push", buffer);
1683 emitcode ("push", s);
1689 /* if not bit variable */
1690 if (!aop->aopu.aop_dir)
1692 /* inefficient: move carry into A and use jz/jnz */
1693 emitcode ("clr", "a");
1694 emitcode ("rlc", "a");
1700 emitcode ("clr", "%s", aop->aopu.aop_dir);
1702 emitcode ("setb", "%s", aop->aopu.aop_dir);
1703 else if (!strcmp (s, "c"))
1704 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1705 else if (strcmp (s, aop->aopu.aop_dir))
1708 /* set C, if a >= 1 */
1709 emitcode ("add", "a,#0xff");
1710 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1717 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1718 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1724 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1727 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1728 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1732 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1733 "aopPut got unsupported aop->type");
1742 /*-----------------------------------------------------------------*/
1743 /* pointToEnd :- points to the last byte of the operand */
1744 /*-----------------------------------------------------------------*/
1746 pointToEnd (asmop * aop)
1752 aop->coff = count = (aop->size - 1);
1758 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1762 emitcode ("inc", "dptr");
1769 /*-----------------------------------------------------------------*/
1770 /* reAdjustPreg - points a register back to where it should */
1771 /*-----------------------------------------------------------------*/
1773 reAdjustPreg (asmop * aop)
1775 if ((aop->coff==0) || (aop->size <= 1))
1783 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1788 emitcode ("lcall", "__decdptr");
1795 /*-----------------------------------------------------------------*/
1796 /* opIsGptr: returns non-zero if the passed operand is */
1797 /* a generic pointer type. */
1798 /*-----------------------------------------------------------------*/
1800 opIsGptr (operand * op)
1802 sym_link *type = operandType (op);
1804 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1811 /*-----------------------------------------------------------------*/
1812 /* getDataSize - get the operand data size */
1813 /*-----------------------------------------------------------------*/
1815 getDataSize (operand * op)
1818 size = AOP_SIZE (op);
1819 if (size == GPTRSIZE)
1821 sym_link *type = operandType (op);
1822 if (IS_GENPTR (type))
1824 /* generic pointer; arithmetic operations
1825 * should ignore the high byte (pointer type).
1833 /*-----------------------------------------------------------------*/
1834 /* outAcc - output Acc */
1835 /*-----------------------------------------------------------------*/
1837 outAcc (operand * result)
1840 size = getDataSize (result);
1843 aopPut (result, "a", 0);
1846 /* unsigned or positive */
1849 aopPut (result, zero, offset++);
1854 /*-----------------------------------------------------------------*/
1855 /* outBitC - output a bit C */
1856 /*-----------------------------------------------------------------*/
1858 outBitC (operand * result)
1860 /* if the result is bit */
1861 if (AOP_TYPE (result) == AOP_CRY)
1863 aopPut (result, "c", 0);
1867 emitcode ("clr", "a");
1868 emitcode ("rlc", "a");
1873 /*-----------------------------------------------------------------*/
1874 /* toBoolean - emit code for orl a,operator(sizeop) */
1875 /*-----------------------------------------------------------------*/
1877 toBoolean (operand * oper)
1879 int size = AOP_SIZE (oper) - 1;
1881 bool AccUsed = FALSE;
1884 while (!AccUsed && size--)
1886 AccUsed |= aopGetUsesAcc(oper, offset++);
1889 size = AOP_SIZE (oper) - 1;
1891 MOVA (aopGet (oper, 0, FALSE, FALSE));
1892 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1895 emitcode("mov", "b,a");
1898 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1899 emitcode ("orl", "b,a");
1901 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1902 emitcode ("orl", "a,b");
1909 emitcode ("orl", "a,%s",
1910 aopGet (oper, offset++, FALSE, FALSE));
1916 /*-------------------------------------------------------------------*/
1917 /* xch_a_aopGet - for exchanging acc with value of the aop */
1918 /*-------------------------------------------------------------------*/
1920 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1924 if (aopGetUsesAcc (oper, offset))
1926 emitcode("mov", "b,a");
1927 MOVA (aopGet (oper, offset, bit16, dname));
1928 emitcode("xch", "a,b");
1929 aopPut (oper, "a", offset);
1930 emitcode("xch", "a,b");
1935 l = aopGet (oper, offset, bit16, dname);
1936 emitcode("xch", "a,%s", l);
1942 /*-----------------------------------------------------------------*/
1943 /* genNot - generate code for ! operation */
1944 /*-----------------------------------------------------------------*/
1950 D (emitcode (";", "genNot"));
1952 /* assign asmOps to operand & result */
1953 aopOp (IC_LEFT (ic), ic, FALSE);
1954 aopOp (IC_RESULT (ic), ic, TRUE);
1956 /* if in bit space then a special case */
1957 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1959 /* if left==result then cpl bit */
1960 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1962 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1966 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1967 emitcode ("cpl", "c");
1968 outBitC (IC_RESULT (ic));
1973 toBoolean (IC_LEFT (ic));
1975 /* set C, if a == 0 */
1976 tlbl = newiTempLabel (NULL);
1977 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1979 outBitC (IC_RESULT (ic));
1982 /* release the aops */
1983 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1984 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1988 /*-----------------------------------------------------------------*/
1989 /* genCpl - generate code for complement */
1990 /*-----------------------------------------------------------------*/
1997 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1999 D(emitcode (";", "genCpl"));
2001 /* assign asmOps to operand & result */
2002 aopOp (IC_LEFT (ic), ic, FALSE);
2003 aopOp (IC_RESULT (ic), ic, TRUE);
2005 /* special case if in bit space */
2006 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2010 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2011 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2013 /* promotion rules are responsible for this strange result:
2014 bit -> int -> ~int -> bit
2015 uchar -> int -> ~int -> bit
2017 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2021 tlbl=newiTempLabel(NULL);
2022 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2023 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2024 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2025 IS_AOP_PREG (IC_LEFT (ic)))
2027 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2032 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2035 outBitC (IC_RESULT(ic));
2039 size = AOP_SIZE (IC_RESULT (ic));
2042 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2044 emitcode ("cpl", "a");
2045 aopPut (IC_RESULT (ic), "a", offset++);
2050 /* release the aops */
2051 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2052 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2055 /*-----------------------------------------------------------------*/
2056 /* genUminusFloat - unary minus for floating points */
2057 /*-----------------------------------------------------------------*/
2059 genUminusFloat (operand * op, operand * result)
2061 int size, offset = 0;
2064 D (emitcode (";", "genUminusFloat"));
2066 /* for this we just copy and then flip the bit */
2068 size = AOP_SIZE (op) - 1;
2073 aopGet (op, offset, FALSE, FALSE),
2078 l = aopGet (op, offset, FALSE, FALSE);
2081 emitcode ("cpl", "acc.7");
2082 aopPut (result, "a", offset);
2085 /*-----------------------------------------------------------------*/
2086 /* genUminus - unary minus code generation */
2087 /*-----------------------------------------------------------------*/
2089 genUminus (iCode * ic)
2094 D (emitcode (";", "genUminus"));
2097 aopOp (IC_LEFT (ic), ic, FALSE);
2098 aopOp (IC_RESULT (ic), ic, TRUE);
2100 /* if both in bit space then special
2102 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2103 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2106 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2107 emitcode ("cpl", "c");
2108 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2112 optype = operandType (IC_LEFT (ic));
2114 /* if float then do float stuff */
2115 if (IS_FLOAT (optype))
2117 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2121 /* otherwise subtract from zero */
2122 size = AOP_SIZE (IC_LEFT (ic));
2126 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2127 if (!strcmp (l, "a"))
2131 emitcode ("cpl", "a");
2132 emitcode ("addc", "a,#0");
2138 emitcode ("clr", "a");
2139 emitcode ("subb", "a,%s", l);
2141 aopPut (IC_RESULT (ic), "a", offset++);
2144 /* if any remaining bytes in the result */
2145 /* we just need to propagate the sign */
2146 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2148 emitcode ("rlc", "a");
2149 emitcode ("subb", "a,acc");
2151 aopPut (IC_RESULT (ic), "a", offset++);
2155 /* release the aops */
2156 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2157 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2160 /*-----------------------------------------------------------------*/
2161 /* saveRegisters - will look for a call and save the registers */
2162 /*-----------------------------------------------------------------*/
2164 saveRegisters (iCode * lic)
2171 for (ic = lic; ic; ic = ic->next)
2172 if (ic->op == CALL || ic->op == PCALL)
2177 fprintf (stderr, "found parameter push with no function call\n");
2181 /* if the registers have been saved already or don't need to be then
2185 if (IS_SYMOP(IC_LEFT(ic)) &&
2186 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2187 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2190 /* save the registers in use at this time but skip the
2191 ones for the result */
2192 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2193 mcs51_rUmaskForOp (IC_RESULT(ic)));
2196 if (options.useXstack)
2198 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2199 int nBits = bitVectnBitsOn (rsavebits);
2200 int count = bitVectnBitsOn (rsave);
2204 count = count - nBits + 1;
2205 /* remove all but the first bits as they are pushed all at once */
2206 rsave = bitVectCplAnd (rsave, rsavebits);
2207 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2212 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2213 if (reg->type == REG_BIT)
2215 emitcode ("mov", "a,%s", reg->base);
2219 emitcode ("mov", "a,%s", reg->name);
2221 emitcode ("mov", "r0,%s", spname);
2222 emitcode ("inc", "%s", spname);// allocate before use
2223 emitcode ("movx", "@r0,a");
2224 if (bitVectBitValue (rsave, R0_IDX))
2225 emitcode ("mov", "r0,a");
2227 else if (count != 0)
2229 if (bitVectBitValue (rsave, R0_IDX))
2231 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2233 emitcode ("mov", "r0,%s", spname);
2235 emitcode ("add", "a,#%d", count);
2236 emitcode ("mov", "%s,a", spname);
2237 for (i = 0; i < mcs51_nRegs; i++)
2239 if (bitVectBitValue (rsave, i))
2241 regs * reg = REG_WITH_INDEX (i);
2244 emitcode ("pop", "acc");
2245 emitcode ("push", "acc");
2247 else if (reg->type == REG_BIT)
2249 emitcode ("mov", "a,%s", reg->base);
2253 emitcode ("mov", "a,%s", reg->name);
2255 emitcode ("movx", "@r0,a");
2258 emitcode ("inc", "r0");
2262 if (bitVectBitValue (rsave, R0_IDX))
2264 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2270 bool bits_pushed = FALSE;
2271 for (i = 0; i < mcs51_nRegs; i++)
2273 if (bitVectBitValue (rsave, i))
2275 bits_pushed = pushReg (i, bits_pushed);
2281 /*-----------------------------------------------------------------*/
2282 /* unsaveRegisters - pop the pushed registers */
2283 /*-----------------------------------------------------------------*/
2285 unsaveRegisters (iCode * ic)
2290 /* restore the registers in use at this time but skip the
2291 ones for the result */
2292 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2293 mcs51_rUmaskForOp (IC_RESULT(ic)));
2295 if (options.useXstack)
2297 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2298 int nBits = bitVectnBitsOn (rsavebits);
2299 int count = bitVectnBitsOn (rsave);
2303 count = count - nBits + 1;
2304 /* remove all but the first bits as they are popped all at once */
2305 rsave = bitVectCplAnd (rsave, rsavebits);
2306 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2311 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2312 emitcode ("mov", "r0,%s", spname);
2313 emitcode ("dec", "r0");
2314 emitcode ("movx", "a,@r0");
2315 if (reg->type == REG_BIT)
2317 emitcode ("mov", "%s,a", reg->base);
2321 emitcode ("mov", "%s,a", reg->name);
2323 emitcode ("dec", "%s", spname);
2325 else if (count != 0)
2327 emitcode ("mov", "r0,%s", spname);
2328 for (i = mcs51_nRegs; i >= 0; i--)
2330 if (bitVectBitValue (rsave, i))
2332 regs * reg = REG_WITH_INDEX (i);
2333 emitcode ("dec", "r0");
2334 emitcode ("movx", "a,@r0");
2337 emitcode ("push", "acc");
2339 else if (reg->type == REG_BIT)
2341 emitcode ("mov", "%s,a", reg->base);
2345 emitcode ("mov", "%s,a", reg->name);
2349 emitcode ("mov", "%s,r0", spname);
2350 if (bitVectBitValue (rsave, R0_IDX))
2352 emitcode ("pop", "ar0");
2358 bool bits_popped = FALSE;
2359 for (i = mcs51_nRegs; i >= 0; i--)
2361 if (bitVectBitValue (rsave, i))
2363 bits_popped = popReg (i, bits_popped);
2370 /*-----------------------------------------------------------------*/
2372 /*-----------------------------------------------------------------*/
2374 pushSide (operand * oper, int size)
2379 char *l = aopGet (oper, offset++, FALSE, TRUE);
2380 if (AOP_TYPE (oper) != AOP_REG &&
2381 AOP_TYPE (oper) != AOP_DIR &&
2385 emitcode ("push", "acc");
2389 emitcode ("push", "%s", l);
2394 /*-----------------------------------------------------------------*/
2395 /* assignResultValue - also indicates if acc is in use afterwards */
2396 /*-----------------------------------------------------------------*/
2398 assignResultValue (operand * oper, operand * func)
2401 int size = AOP_SIZE (oper);
2402 bool accuse = FALSE;
2403 bool pushedA = FALSE;
2405 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2411 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2413 emitcode ("push", "acc");
2418 if ((offset == 3) && pushedA)
2419 emitcode ("pop", "acc");
2420 accuse |= aopPut (oper, fReturn[offset], offset);
2427 /*-----------------------------------------------------------------*/
2428 /* genXpush - pushes onto the external stack */
2429 /*-----------------------------------------------------------------*/
2431 genXpush (iCode * ic)
2433 asmop *aop = newAsmop (0);
2435 int size, offset = 0;
2437 D (emitcode (";", "genXpush"));
2439 aopOp (IC_LEFT (ic), ic, FALSE);
2440 r = getFreePtr (ic, &aop, FALSE);
2442 size = AOP_SIZE (IC_LEFT (ic));
2446 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2447 emitcode ("mov", "%s,%s", r->name, spname);
2448 emitcode ("inc", "%s", spname); // allocate space first
2449 emitcode ("movx", "@%s,a", r->name);
2453 // allocate space first
2454 emitcode ("mov", "%s,%s", r->name, spname);
2456 emitcode ("add", "a,#%d", size);
2457 emitcode ("mov", "%s,a", spname);
2461 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2462 emitcode ("movx", "@%s,a", r->name);
2463 emitcode ("inc", "%s", r->name);
2467 freeAsmop (NULL, aop, ic, TRUE);
2468 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2471 /*-----------------------------------------------------------------*/
2472 /* genIpush - generate code for pushing this gets a little complex */
2473 /*-----------------------------------------------------------------*/
2475 genIpush (iCode * ic)
2477 int size, offset = 0;
2481 D (emitcode (";", "genIpush"));
2483 /* if this is not a parm push : ie. it is spill push
2484 and spill push is always done on the local stack */
2488 /* and the item is spilt then do nothing */
2489 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2492 aopOp (IC_LEFT (ic), ic, FALSE);
2493 size = AOP_SIZE (IC_LEFT (ic));
2494 /* push it on the stack */
2497 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2503 emitcode ("push", "%s", l);
2508 /* this is a parameter push: in this case we call
2509 the routine to find the call and save those
2510 registers that need to be saved */
2513 /* if use external stack then call the external
2514 stack pushing routine */
2515 if (options.useXstack)
2521 /* then do the push */
2522 aopOp (IC_LEFT (ic), ic, FALSE);
2524 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2525 size = AOP_SIZE (IC_LEFT (ic));
2529 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2530 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2531 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2533 if (strcmp (l, prev) || *l == '@')
2535 emitcode ("push", "acc");
2539 emitcode ("push", "%s", l);
2544 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2547 /*-----------------------------------------------------------------*/
2548 /* genIpop - recover the registers: can happen only for spilling */
2549 /*-----------------------------------------------------------------*/
2551 genIpop (iCode * ic)
2555 D (emitcode (";", "genIpop"));
2557 /* if the temp was not pushed then */
2558 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2561 aopOp (IC_LEFT (ic), ic, FALSE);
2562 size = AOP_SIZE (IC_LEFT (ic));
2563 offset = (size - 1);
2566 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2570 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2573 /*-----------------------------------------------------------------*/
2574 /* saveRBank - saves an entire register bank on the stack */
2575 /*-----------------------------------------------------------------*/
2577 saveRBank (int bank, iCode * ic, bool pushPsw)
2580 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2584 if (options.useXstack)
2588 /* Assume r0 is available for use. */
2589 r = REG_WITH_INDEX (R0_IDX);;
2594 r = getFreePtr (ic, &aop, FALSE);
2596 // allocate space first
2597 emitcode ("mov", "%s,%s", r->name, spname);
2599 emitcode ("add", "a,#%d", count);
2600 emitcode ("mov", "%s,a", spname);
2603 for (i = 0; i < 8; i++)
2605 if (options.useXstack)
2607 emitcode ("mov", "a,(%s+%d)",
2608 regs8051[i].base, 8 * bank + regs8051[i].offset);
2609 emitcode ("movx", "@%s,a", r->name);
2611 emitcode ("inc", "%s", r->name);
2614 emitcode ("push", "(%s+%d)",
2615 regs8051[i].base, 8 * bank + regs8051[i].offset);
2618 if (mcs51_nRegs > 8)
2620 if (options.useXstack)
2622 emitcode ("mov", "a,bits");
2623 emitcode ("movx", "@%s,a", r->name);
2625 emitcode ("inc", "%s", r->name);
2629 emitcode ("push", "bits");
2636 if (options.useXstack)
2638 emitcode ("mov", "a,psw");
2639 emitcode ("movx", "@%s,a", r->name);
2643 emitcode ("push", "psw");
2646 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2651 freeAsmop (NULL, aop, ic, TRUE);
2660 /*-----------------------------------------------------------------*/
2661 /* unsaveRBank - restores the register bank from stack */
2662 /*-----------------------------------------------------------------*/
2664 unsaveRBank (int bank, iCode * ic, bool popPsw)
2670 if (options.useXstack)
2674 /* Assume r0 is available for use. */
2675 r = REG_WITH_INDEX (R0_IDX);;
2680 r = getFreePtr (ic, &aop, FALSE);
2682 emitcode ("mov", "%s,%s", r->name, spname);
2687 if (options.useXstack)
2689 emitcode ("dec", "%s", r->name);
2690 emitcode ("movx", "a,@%s", r->name);
2691 emitcode ("mov", "psw,a");
2695 emitcode ("pop", "psw");
2699 if (mcs51_nRegs > 8)
2701 if (options.useXstack)
2703 emitcode ("dec", "%s", r->name);
2704 emitcode ("movx", "a,@%s", r->name);
2705 emitcode ("mov", "bits,a");
2709 emitcode ("pop", "bits");
2713 for (i = 7; i >= 0; i--)
2715 if (options.useXstack)
2717 emitcode ("dec", "%s", r->name);
2718 emitcode ("movx", "a,@%s", r->name);
2719 emitcode ("mov", "(%s+%d),a",
2720 regs8051[i].base, 8 * bank + regs8051[i].offset);
2724 emitcode ("pop", "(%s+%d)",
2725 regs8051[i].base, 8 * bank + regs8051[i].offset);
2729 if (options.useXstack)
2731 emitcode ("mov", "%s,%s", spname, r->name);
2736 freeAsmop (NULL, aop, ic, TRUE);
2740 /*-----------------------------------------------------------------*/
2741 /* genSend - gen code for SEND */
2742 /*-----------------------------------------------------------------*/
2743 static void genSend(set *sendSet)
2748 /* first we do all bit parameters */
2749 for (sic = setFirstItem (sendSet); sic;
2750 sic = setNextItem (sendSet))
2752 if (sic->argreg > 12)
2754 int bit = sic->argreg-13;
2756 aopOp (IC_LEFT (sic), sic, FALSE);
2758 /* if left is a literal then
2759 we know what the value is */
2760 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2762 if (((int) operandLitValue (IC_LEFT (sic))))
2763 emitcode ("setb", "b[%d]", bit);
2765 emitcode ("clr", "b[%d]", bit);
2767 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2769 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2770 if (strcmp (l, "c"))
2771 emitcode ("mov", "c,%s", l);
2772 emitcode ("mov", "b[%d],c", bit);
2777 toBoolean (IC_LEFT (sic));
2778 /* set C, if a >= 1 */
2779 emitcode ("add", "a,#0xff");
2780 emitcode ("mov", "b[%d],c", bit);
2785 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2791 saveRegisters (setFirstItem (sendSet));
2792 emitcode ("mov", "bits,b");
2795 /* then we do all other parameters */
2796 for (sic = setFirstItem (sendSet); sic;
2797 sic = setNextItem (sendSet))
2799 if (sic->argreg <= 12)
2801 int size, offset = 0;
2802 aopOp (IC_LEFT (sic), sic, FALSE);
2803 size = AOP_SIZE (IC_LEFT (sic));
2805 if (sic->argreg == 1)
2809 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2810 if (strcmp (l, fReturn[offset]))
2812 emitcode ("mov", "%s,%s", fReturn[offset], l);
2821 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2822 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2826 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2831 /*-----------------------------------------------------------------*/
2832 /* selectRegBank - emit code to select the register bank */
2833 /*-----------------------------------------------------------------*/
2835 selectRegBank (short bank, bool keepFlags)
2837 /* if f.e. result is in carry */
2840 emitcode ("anl", "psw,#0xE7");
2842 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2846 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2850 /*-----------------------------------------------------------------*/
2851 /* genCall - generates a call statement */
2852 /*-----------------------------------------------------------------*/
2854 genCall (iCode * ic)
2858 // bool restoreBank = FALSE;
2859 bool swapBanks = FALSE;
2860 bool accuse = FALSE;
2861 bool accPushed = FALSE;
2862 bool resultInF0 = FALSE;
2863 bool assignResultGenerated = FALSE;
2865 D (emitcode (";", "genCall"));
2867 dtype = operandType (IC_LEFT (ic));
2868 etype = getSpec(dtype);
2869 /* if send set is not empty then assign */
2872 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2873 genSend(reverseSet(_G.sendSet));
2875 genSend(_G.sendSet);
2880 /* if we are calling a not _naked function that is not using
2881 the same register bank then we need to save the
2882 destination registers on the stack */
2883 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2884 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2885 !IFFUNC_ISISR (dtype))
2890 /* if caller saves & we have not saved then */
2896 emitcode ("mov", "psw,#0x%02x",
2897 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2901 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2903 if (IFFUNC_CALLEESAVES(dtype))
2905 werror (E_BANKED_WITH_CALLEESAVES);
2909 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2910 OP_SYMBOL (IC_LEFT (ic))->rname :
2911 OP_SYMBOL (IC_LEFT (ic))->name);
2913 emitcode ("mov", "r0,#%s", l);
2914 emitcode ("mov", "r1,#(%s >> 8)", l);
2915 emitcode ("mov", "r2,#(%s >> 16)", l);
2916 emitcode ("lcall", "__sdcc_banked_call");
2921 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2922 OP_SYMBOL (IC_LEFT (ic))->rname :
2923 OP_SYMBOL (IC_LEFT (ic))->name));
2928 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2931 /* if we need assign a result value */
2932 if ((IS_ITEMP (IC_RESULT (ic)) &&
2933 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2934 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2935 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2936 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2937 IS_TRUE_SYMOP (IC_RESULT (ic)))
2941 aopOp (IC_RESULT (ic), ic, FALSE);
2944 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2945 assignResultGenerated = TRUE;
2947 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2950 /* adjust the stack for parameters if required */
2954 if (ic->parmBytes > 3)
2958 emitcode ("push", "acc");
2961 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2962 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2963 !assignResultGenerated)
2965 emitcode ("mov", "F0,c");
2969 emitcode ("mov", "a,%s", spname);
2970 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2971 emitcode ("mov", "%s,a", spname);
2973 /* unsaveRegisters from xstack needs acc, but */
2974 /* unsaveRegisters from stack needs this popped */
2975 if (accPushed && !options.useXstack)
2977 emitcode ("pop", "acc");
2982 for (i = 0; i < ic->parmBytes; i++)
2983 emitcode ("dec", "%s", spname);
2986 /* if we had saved some registers then unsave them */
2987 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2989 if (accuse && !accPushed && options.useXstack)
2991 /* xstack needs acc, but doesn't touch normal stack */
2992 emitcode ("push", "acc");
2995 unsaveRegisters (ic);
2998 // /* if register bank was saved then pop them */
3000 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3002 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3005 emitcode ("mov", "c,F0");
3007 aopOp (IC_RESULT (ic), ic, FALSE);
3008 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3009 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3013 emitcode ("pop", "acc");
3016 /*-----------------------------------------------------------------*/
3017 /* genPcall - generates a call by pointer statement */
3018 /*-----------------------------------------------------------------*/
3020 genPcall (iCode * ic)
3024 symbol *rlbl = newiTempLabel (NULL);
3025 // bool restoreBank=FALSE;
3026 bool swapBanks = FALSE;
3027 bool resultInF0 = FALSE;
3029 D (emitcode (";", "genPcall"));
3031 dtype = operandType (IC_LEFT (ic))->next;
3032 etype = getSpec(dtype);
3033 /* if caller saves & we have not saved then */
3037 /* if we are calling a not _naked function that is not using
3038 the same register bank then we need to save the
3039 destination registers on the stack */
3040 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3041 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3042 !IFFUNC_ISISR (dtype))
3044 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3045 // restoreBank=TRUE;
3047 // need caution message to user here
3050 if (IS_LITERAL(etype))
3052 /* if send set is not empty then assign */
3055 genSend(reverseSet(_G.sendSet));
3061 emitcode ("mov", "psw,#0x%02x",
3062 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3065 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3067 if (IFFUNC_CALLEESAVES(dtype))
3069 werror (E_BANKED_WITH_CALLEESAVES);
3073 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3075 emitcode ("mov", "r0,#%s", l);
3076 emitcode ("mov", "r1,#(%s >> 8)", l);
3077 emitcode ("mov", "r2,#(%s >> 16)", l);
3078 emitcode ("lcall", "__sdcc_banked_call");
3083 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3088 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3090 if (IFFUNC_CALLEESAVES(dtype))
3092 werror (E_BANKED_WITH_CALLEESAVES);
3096 aopOp (IC_LEFT (ic), ic, FALSE);
3100 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3101 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3102 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3106 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3107 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3108 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3109 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3112 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3114 /* if send set is not empty then assign */
3117 genSend(reverseSet(_G.sendSet));
3123 emitcode ("mov", "psw,#0x%02x",
3124 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3128 emitcode ("lcall", "__sdcc_banked_call");
3133 /* push the return address on to the stack */
3134 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3135 emitcode ("push", "acc");
3136 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3137 emitcode ("push", "acc");
3139 /* now push the calling address */
3140 aopOp (IC_LEFT (ic), ic, FALSE);
3142 pushSide (IC_LEFT (ic), FPTRSIZE);
3144 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3146 /* if send set is not empty the assign */
3149 genSend(reverseSet(_G.sendSet));
3155 emitcode ("mov", "psw,#0x%02x",
3156 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3160 emitcode ("ret", "");
3166 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3169 /* if we need assign a result value */
3170 if ((IS_ITEMP (IC_RESULT (ic)) &&
3171 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3172 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3173 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3174 IS_TRUE_SYMOP (IC_RESULT (ic)))
3178 aopOp (IC_RESULT (ic), ic, FALSE);
3181 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3183 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3186 /* adjust the stack for parameters if required */
3190 if (ic->parmBytes > 3)
3192 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3193 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3195 emitcode ("mov", "F0,c");
3199 emitcode ("mov", "a,%s", spname);
3200 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3201 emitcode ("mov", "%s,a", spname);
3204 for (i = 0; i < ic->parmBytes; i++)
3205 emitcode ("dec", "%s", spname);
3208 // /* if register bank was saved then unsave them */
3210 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3212 /* if we had saved some registers then unsave them */
3213 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3214 unsaveRegisters (ic);
3216 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3219 emitcode ("mov", "c,F0");
3221 aopOp (IC_RESULT (ic), ic, FALSE);
3222 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3223 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3227 /*-----------------------------------------------------------------*/
3228 /* resultRemat - result is rematerializable */
3229 /*-----------------------------------------------------------------*/
3231 resultRemat (iCode * ic)
3233 if (SKIP_IC (ic) || ic->op == IFX)
3236 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3238 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3239 if (sym->remat && !POINTER_SET (ic))
3246 /*-----------------------------------------------------------------*/
3247 /* inExcludeList - return 1 if the string is in exclude Reg list */
3248 /*-----------------------------------------------------------------*/
3250 regsCmp(void *p1, void *p2)
3252 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3256 inExcludeList (char *s)
3258 const char *p = setFirstItem(options.excludeRegsSet);
3260 if (p == NULL || STRCASECMP(p, "none") == 0)
3264 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3267 /*-----------------------------------------------------------------*/
3268 /* genFunction - generated code for function entry */
3269 /*-----------------------------------------------------------------*/
3271 genFunction (iCode * ic)
3273 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3275 bool switchedPSW = FALSE;
3276 int calleesaves_saved_register = -1;
3277 int stackAdjust = sym->stack;
3278 int accIsFree = sym->recvSize < 4;
3279 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3280 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3283 /* create the function header */
3284 emitcode (";", "-----------------------------------------");
3285 emitcode (";", " function %s", sym->name);
3286 emitcode (";", "-----------------------------------------");
3288 emitcode ("", "%s:", sym->rname);
3289 lineCurr->isLabel = 1;
3290 ftype = operandType (IC_LEFT (ic));
3291 _G.currentFunc = sym;
3293 if (IFFUNC_ISNAKED(ftype))
3295 emitcode(";", "naked function: no prologue.");
3299 /* here we need to generate the equates for the
3300 register bank if required */
3301 if (FUNC_REGBANK (ftype) != rbank)
3305 rbank = FUNC_REGBANK (ftype);
3306 for (i = 0; i < mcs51_nRegs; i++)
3308 if (regs8051[i].type != REG_BIT)
3310 if (strcmp (regs8051[i].base, "0") == 0)
3311 emitcode ("", "%s = 0x%02x",
3313 8 * rbank + regs8051[i].offset);
3315 emitcode ("", "%s = %s + 0x%02x",
3318 8 * rbank + regs8051[i].offset);
3323 /* if this is an interrupt service routine then
3324 save acc, b, dpl, dph */
3325 if (IFFUNC_ISISR (sym->type))
3327 if (!inExcludeList ("acc"))
3328 emitcode ("push", "acc");
3329 if (!inExcludeList ("b"))
3330 emitcode ("push", "b");
3331 if (!inExcludeList ("dpl"))
3332 emitcode ("push", "dpl");
3333 if (!inExcludeList ("dph"))
3334 emitcode ("push", "dph");
3335 /* if this isr has no bank i.e. is going to
3336 run with bank 0 , then we need to save more
3338 if (!FUNC_REGBANK (sym->type))
3342 /* if this function does not call any other
3343 function then we can be economical and
3344 save only those registers that are used */
3345 if (!IFFUNC_HASFCALL(sym->type))
3347 /* if any registers used */
3350 bool bits_pushed = FALSE;
3351 /* save the registers used */
3352 for (i = 0; i < sym->regsUsed->size; i++)
3354 if (bitVectBitValue (sym->regsUsed, i))
3355 bits_pushed = pushReg (i, bits_pushed);
3361 /* this function has a function call. We cannot
3362 determine register usage so we will have to push the
3364 saveRBank (0, ic, FALSE);
3365 if (options.parms_in_bank1) {
3366 for (i=0; i < 8 ; i++ ) {
3367 emitcode ("push","%s",rb1regs[i]);
3374 /* This ISR uses a non-zero bank.
3376 * We assume that the bank is available for our
3379 * However, if this ISR calls a function which uses some
3380 * other bank, we must save that bank entirely.
3382 unsigned long banksToSave = 0;
3384 if (IFFUNC_HASFCALL(sym->type))
3387 #define MAX_REGISTER_BANKS 4
3392 for (i = ic; i; i = i->next)
3394 if (i->op == ENDFUNCTION)
3396 /* we got to the end OK. */
3404 dtype = operandType (IC_LEFT(i));
3406 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3408 /* Mark this bank for saving. */
3409 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3411 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3415 banksToSave |= (1 << FUNC_REGBANK(dtype));
3418 /* And note that we don't need to do it in
3426 /* This is a mess; we have no idea what
3427 * register bank the called function might
3430 * The only thing I can think of to do is
3431 * throw a warning and hope.
3433 werror(W_FUNCPTR_IN_USING_ISR);
3437 if (banksToSave && options.useXstack)
3439 /* Since we aren't passing it an ic,
3440 * saveRBank will assume r0 is available to abuse.
3442 * So switch to our (trashable) bank now, so
3443 * the caller's R0 isn't trashed.
3445 emitcode ("push", "psw");
3446 emitcode ("mov", "psw,#0x%02x",
3447 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3451 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3453 if (banksToSave & (1 << ix))
3455 saveRBank(ix, NULL, FALSE);
3459 // TODO: this needs a closer look
3460 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3463 /* Set the register bank to the desired value if nothing else */
3464 /* has done so yet. */
3467 emitcode ("push", "psw");
3468 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3473 /* This is a non-ISR function. The caller has already switched register */
3474 /* banks, if necessary, so just handle the callee-saves option. */
3476 /* if callee-save to be used for this function
3477 then save the registers being used in this function */
3478 if (IFFUNC_CALLEESAVES(sym->type))
3482 /* if any registers used */
3485 bool bits_pushed = FALSE;
3486 /* save the registers used */
3487 for (i = 0; i < sym->regsUsed->size; i++)
3489 if (bitVectBitValue (sym->regsUsed, i))
3491 /* remember one saved register for later usage */
3492 if (calleesaves_saved_register < 0)
3493 calleesaves_saved_register = i;
3494 bits_pushed = pushReg (i, bits_pushed);
3504 if (options.useXstack)
3506 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3508 emitcode ("mov", "r0,%s", spname);
3509 emitcode ("inc", "%s", spname);
3510 emitcode ("xch", "a,_bpx");
3511 emitcode ("movx", "@r0,a");
3512 emitcode ("inc", "r0");
3513 emitcode ("mov", "a,r0");
3514 emitcode ("xch", "a,_bpx");
3518 emitcode ("push", "_bp"); /* save the callers stack */
3519 emitcode ("mov", "_bp,sp");
3524 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3526 /* set up the stack */
3527 emitcode ("push", "_bp"); /* save the callers stack */
3528 emitcode ("mov", "_bp,sp");
3533 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3534 /* before setting up the stack frame completely. */
3535 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3537 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3541 if (rsym && rsym->regType == REG_CND)
3543 if (rsym && (rsym->accuse || rsym->ruonly))
3545 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3546 rsym = rsym->usl.spillLoc;
3549 /* If the RECEIVE operand immediately spills to the first entry on the */
3550 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3551 /* rather than the usual @r0/r1 machinations. */
3552 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3556 _G.current_iCode = ric;
3557 D(emitcode ("; genReceive",""));
3558 for (ofs=0; ofs < sym->recvSize; ofs++)
3560 if (!strcmp (fReturn[ofs], "a"))
3561 emitcode ("push", "acc");
3563 emitcode ("push", fReturn[ofs]);
3565 stackAdjust -= sym->recvSize;
3568 assert (stackAdjust>=0);
3571 _G.current_iCode = ic;
3575 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3576 /* to free up the accumulator. */
3577 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3581 _G.current_iCode = ric;
3582 D(emitcode ("; genReceive",""));
3583 for (ofs=0; ofs < sym->recvSize; ofs++)
3585 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3587 _G.current_iCode = ic;
3593 /* adjust the stack for the function */
3596 int i = stackAdjust;
3598 werror (W_STACK_OVERFLOW, sym->name);
3600 if (i > 3 && accIsFree)
3602 emitcode ("mov", "a,sp");
3603 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604 emitcode ("mov", "sp,a");
3608 /* The accumulator is not free, so we will need another register */
3609 /* to clobber. No need to worry about a possible conflict with */
3610 /* the above early RECEIVE optimizations since they would have */
3611 /* freed the accumulator if they were generated. */
3613 if (IFFUNC_CALLEESAVES(sym->type))
3615 /* if it's a callee-saves function we need a saved register */
3616 if (calleesaves_saved_register >= 0)
3618 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3619 emitcode ("mov", "a,sp");
3620 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3621 emitcode ("mov", "sp,a");
3622 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3625 /* do it the hard way */
3627 emitcode ("inc", "sp");
3631 /* not callee-saves, we can clobber r0 */
3632 emitcode ("mov", "r0,a");
3633 emitcode ("mov", "a,sp");
3634 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3635 emitcode ("mov", "sp,a");
3636 emitcode ("mov", "a,r0");
3641 emitcode ("inc", "sp");
3646 char i = ((char) sym->xstack & 0xff);
3648 if (i > 3 && accIsFree)
3650 emitcode ("mov", "a,_spx");
3651 emitcode ("add", "a,#0x%02x", i & 0xff);
3652 emitcode ("mov", "_spx,a");
3656 emitcode ("push", "acc");
3657 emitcode ("mov", "a,_spx");
3658 emitcode ("add", "a,#0x%02x", i & 0xff);
3659 emitcode ("mov", "_spx,a");
3660 emitcode ("pop", "acc");
3665 emitcode ("inc", "_spx");
3669 /* if critical function then turn interrupts off */
3670 if (IFFUNC_ISCRITICAL (ftype))
3672 symbol *tlbl = newiTempLabel (NULL);
3673 emitcode ("setb", "c");
3674 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3675 emitcode ("clr", "c");
3677 emitcode ("push", "psw"); /* save old ea via c in psw */
3681 /*-----------------------------------------------------------------*/
3682 /* genEndFunction - generates epilogue for functions */
3683 /*-----------------------------------------------------------------*/
3685 genEndFunction (iCode * ic)
3687 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3688 lineNode *lnp = lineCurr;
3690 bitVect *regsUsedPrologue;
3691 bitVect *regsUnneeded;
3694 _G.currentFunc = NULL;
3695 if (IFFUNC_ISNAKED(sym->type))
3697 emitcode(";", "naked function: no epilogue.");
3698 if (options.debug && currFunc)
3699 debugFile->writeEndFunction (currFunc, ic, 0);
3703 if (IFFUNC_ISCRITICAL (sym->type))
3705 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3707 emitcode ("rlc", "a"); /* save c in a */
3708 emitcode ("pop", "psw"); /* restore ea via c in psw */
3709 emitcode ("mov", "ea,c");
3710 emitcode ("rrc", "a"); /* restore c from a */
3714 emitcode ("pop", "psw"); /* restore ea via c in psw */
3715 emitcode ("mov", "ea,c");
3719 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3721 if (options.useXstack)
3725 emitcode ("mov", "sp,_bp");
3726 emitcode ("pop", "_bp");
3728 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3730 emitcode ("xch", "a,_bpx");
3731 emitcode ("mov", "r0,a");
3732 emitcode ("dec", "r0");
3733 emitcode ("movx", "a,@r0");
3734 emitcode ("xch", "a,_bpx");
3735 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3738 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3741 emitcode ("mov", "sp,_bp");
3742 emitcode ("pop", "_bp");
3746 /* restore the register bank */
3747 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3749 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3750 || !options.useXstack)
3752 /* Special case of ISR using non-zero bank with useXstack
3755 emitcode ("pop", "psw");
3759 if (IFFUNC_ISISR (sym->type))
3762 /* now we need to restore the registers */
3763 /* if this isr has no bank i.e. is going to
3764 run with bank 0 , then we need to save more
3766 if (!FUNC_REGBANK (sym->type))
3769 /* if this function does not call any other
3770 function then we can be economical and
3771 save only those registers that are used */
3772 if (!IFFUNC_HASFCALL(sym->type))
3774 /* if any registers used */
3777 bool bits_popped = FALSE;
3778 /* save the registers used */
3779 for (i = sym->regsUsed->size; i >= 0; i--)
3781 if (bitVectBitValue (sym->regsUsed, i))
3782 bits_popped = popReg (i, bits_popped);
3788 if (options.parms_in_bank1) {
3789 for (i = 7 ; i >= 0 ; i-- ) {
3790 emitcode ("pop","%s",rb1regs[i]);
3793 /* this function has a function call cannot
3794 determines register usage so we will have to pop the
3796 unsaveRBank (0, ic, FALSE);
3801 /* This ISR uses a non-zero bank.
3803 * Restore any register banks saved by genFunction
3806 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3809 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3811 if (savedBanks & (1 << ix))
3813 unsaveRBank(ix, NULL, FALSE);
3817 if (options.useXstack)
3819 /* Restore bank AFTER calling unsaveRBank,
3820 * since it can trash r0.
3822 emitcode ("pop", "psw");
3826 if (!inExcludeList ("dph"))
3827 emitcode ("pop", "dph");
3828 if (!inExcludeList ("dpl"))
3829 emitcode ("pop", "dpl");
3830 if (!inExcludeList ("b"))
3831 emitcode ("pop", "b");
3832 if (!inExcludeList ("acc"))
3833 emitcode ("pop", "acc");
3835 /* if debug then send end of function */
3836 if (options.debug && currFunc)
3838 debugFile->writeEndFunction (currFunc, ic, 1);
3841 emitcode ("reti", "");
3845 if (IFFUNC_CALLEESAVES(sym->type))
3849 /* if any registers used */
3852 /* save the registers used */
3853 for (i = sym->regsUsed->size; i >= 0; i--)
3855 if (bitVectBitValue (sym->regsUsed, i) ||
3856 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3857 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3860 else if (mcs51_ptrRegReq)
3862 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3863 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3868 /* if debug then send end of function */
3869 if (options.debug && currFunc)
3871 debugFile->writeEndFunction (currFunc, ic, 1);
3874 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3876 emitcode ("ljmp", "__sdcc_banked_ret");
3880 emitcode ("ret", "");
3884 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3887 /* If this was an interrupt handler using bank 0 that called another */
3888 /* function, then all registers must be saved; nothing to optimized. */
3889 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3890 && !FUNC_REGBANK(sym->type))
3893 /* There are no push/pops to optimize if not callee-saves or ISR */
3894 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3897 /* If there were stack parameters, we cannot optimize without also */
3898 /* fixing all of the stack offsets; this is too dificult to consider. */
3899 if (FUNC_HASSTACKPARM(sym->type))
3902 /* Compute the registers actually used */
3903 regsUsed = newBitVect (mcs51_nRegs);
3904 regsUsedPrologue = newBitVect (mcs51_nRegs);
3907 if (lnp->ic && lnp->ic->op == FUNCTION)
3908 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3910 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3912 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3913 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3920 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3921 && !bitVectBitValue (regsUsed, CND_IDX))
3923 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3924 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3925 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3926 bitVectUnSetBit (regsUsed, CND_IDX);
3929 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3931 /* If this was an interrupt handler that called another function */
3932 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3933 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3935 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3936 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3937 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3938 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3939 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3942 /* Remove the unneeded push/pops */
3943 regsUnneeded = newBitVect (mcs51_nRegs);
3946 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3948 if (!strncmp(lnp->line, "push", 4))
3950 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3951 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3953 connectLine (lnp->prev, lnp->next);
3954 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3957 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3959 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3960 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3962 connectLine (lnp->prev, lnp->next);
3963 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3970 for (idx = 0; idx < regsUnneeded->size; idx++)
3971 if (bitVectBitValue (regsUnneeded, idx))
3972 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3974 freeBitVect (regsUnneeded);
3975 freeBitVect (regsUsed);
3976 freeBitVect (regsUsedPrologue);
3979 /*-----------------------------------------------------------------*/
3980 /* genRet - generate code for return statement */
3981 /*-----------------------------------------------------------------*/
3985 int size, offset = 0, pushed = 0;
3987 D (emitcode (";", "genRet"));
3989 /* if we have no return value then
3990 just generate the "ret" */
3994 /* we have something to return then
3995 move the return value into place */
3996 aopOp (IC_LEFT (ic), ic, FALSE);
3997 size = AOP_SIZE (IC_LEFT (ic));
3999 if (IS_BIT(_G.currentFunc->etype))
4001 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
4002 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4004 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4011 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4014 l = aopGet (IC_LEFT (ic), offset++,
4016 emitcode ("push", "%s", l);
4021 l = aopGet (IC_LEFT (ic), offset,
4023 if (strcmp (fReturn[offset], l))
4024 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4031 if (strcmp (fReturn[pushed], "a"))
4032 emitcode ("pop", fReturn[pushed]);
4034 emitcode ("pop", "acc");
4037 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4040 /* generate a jump to the return label
4041 if the next is not the return statement */
4042 if (!(ic->next && ic->next->op == LABEL &&
4043 IC_LABEL (ic->next) == returnLabel))
4045 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4049 /*-----------------------------------------------------------------*/
4050 /* genLabel - generates a label */
4051 /*-----------------------------------------------------------------*/
4053 genLabel (iCode * ic)
4055 /* special case never generate */
4056 if (IC_LABEL (ic) == entryLabel)
4059 emitLabel (IC_LABEL (ic));
4062 /*-----------------------------------------------------------------*/
4063 /* genGoto - generates a ljmp */
4064 /*-----------------------------------------------------------------*/
4066 genGoto (iCode * ic)
4068 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4071 /*-----------------------------------------------------------------*/
4072 /* findLabelBackwards: walks back through the iCode chain looking */
4073 /* for the given label. Returns number of iCode instructions */
4074 /* between that label and given ic. */
4075 /* Returns zero if label not found. */
4076 /*-----------------------------------------------------------------*/
4078 findLabelBackwards (iCode * ic, int key)
4087 /* If we have any pushes or pops, we cannot predict the distance.
4088 I don't like this at all, this should be dealt with in the
4090 if (ic->op == IPUSH || ic->op == IPOP) {
4094 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4103 /*-----------------------------------------------------------------*/
4104 /* genPlusIncr :- does addition with increment if possible */
4105 /*-----------------------------------------------------------------*/
4107 genPlusIncr (iCode * ic)
4109 unsigned int icount;
4110 unsigned int size = getDataSize (IC_RESULT (ic));
4112 /* will try to generate an increment */
4113 /* if the right side is not a literal
4115 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4118 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4120 D(emitcode (";","genPlusIncr"));
4122 /* if increment >=16 bits in register or direct space */
4123 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4124 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4125 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4126 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4127 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4135 /* If the next instruction is a goto and the goto target
4136 * is < 10 instructions previous to this, we can generate
4137 * jumps straight to that target.
4139 if (ic->next && ic->next->op == GOTO
4140 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4141 && labelRange <= 10)
4143 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4144 tlbl = IC_LABEL (ic->next);
4149 tlbl = newiTempLabel (NULL);
4152 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4153 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4154 IS_AOP_PREG (IC_RESULT (ic)))
4155 emitcode ("cjne", "%s,#0x00,%05d$",
4156 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4160 emitcode ("clr", "a");
4161 emitcode ("cjne", "a,%s,%05d$",
4162 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4166 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4169 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4170 IS_AOP_PREG (IC_RESULT (ic)))
4171 emitcode ("cjne", "%s,#0x00,%05d$",
4172 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4175 emitcode ("cjne", "a,%s,%05d$",
4176 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4179 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4183 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4184 IS_AOP_PREG (IC_RESULT (ic)))
4185 emitcode ("cjne", "%s,#0x00,%05d$",
4186 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4190 emitcode ("cjne", "a,%s,%05d$",
4191 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4194 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4204 /* if result is dptr */
4205 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4206 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4207 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4208 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4210 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4216 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4219 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4220 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4222 emitcode ("inc", "dptr");
4227 /* if the literal value of the right hand side
4228 is greater than 4 then it is not worth it */
4232 /* if the sizes are greater than 1 then we cannot */
4233 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4234 AOP_SIZE (IC_LEFT (ic)) > 1)
4237 /* we can if the aops of the left & result match or
4238 if they are in registers and the registers are the
4240 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4244 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4245 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4246 aopPut (IC_RESULT (ic), "a", 0);
4252 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4261 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4262 emitcode ("inc", "a");
4263 aopPut (IC_RESULT (ic), "a", 0);
4270 /*-----------------------------------------------------------------*/
4271 /* outBitAcc - output a bit in acc */
4272 /*-----------------------------------------------------------------*/
4274 outBitAcc (operand * result)
4276 symbol *tlbl = newiTempLabel (NULL);
4277 /* if the result is a bit */
4278 if (AOP_TYPE (result) == AOP_CRY)
4280 aopPut (result, "a", 0);
4284 emitcode ("jz", "%05d$", tlbl->key + 100);
4285 emitcode ("mov", "a,%s", one);
4291 /*-----------------------------------------------------------------*/
4292 /* genPlusBits - generates code for addition of two bits */
4293 /*-----------------------------------------------------------------*/
4295 genPlusBits (iCode * ic)
4297 D (emitcode (";", "genPlusBits"));
4299 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4301 symbol *lbl = newiTempLabel (NULL);
4302 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4303 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4304 emitcode ("cpl", "c");
4306 outBitC (IC_RESULT (ic));
4310 emitcode ("clr", "a");
4311 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4312 emitcode ("rlc", "a");
4313 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4314 emitcode ("addc", "a,%s", zero);
4315 outAcc (IC_RESULT (ic));
4320 /* This is the original version of this code.
4322 * This is being kept around for reference,
4323 * because I am not entirely sure I got it right...
4326 adjustArithmeticResult (iCode * ic)
4328 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4329 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4330 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4331 aopPut (IC_RESULT (ic),
4332 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4335 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4336 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4338 aopPut (IC_RESULT (ic),
4339 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4342 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4343 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4344 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4345 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4346 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4349 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4350 aopPut (IC_RESULT (ic), buffer, 2);
4354 /* This is the pure and virtuous version of this code.
4355 * I'm pretty certain it's right, but not enough to toss the old
4359 adjustArithmeticResult (iCode * ic)
4361 if (opIsGptr (IC_RESULT (ic)) &&
4362 opIsGptr (IC_LEFT (ic)) &&
4363 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4365 aopPut (IC_RESULT (ic),
4366 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4370 if (opIsGptr (IC_RESULT (ic)) &&
4371 opIsGptr (IC_RIGHT (ic)) &&
4372 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4374 aopPut (IC_RESULT (ic),
4375 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4379 if (opIsGptr (IC_RESULT (ic)) &&
4380 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4381 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4383 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4386 SNPRINTF (buffer, sizeof(buffer),
4387 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4388 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4393 /*-----------------------------------------------------------------*/
4394 /* genPlus - generates code for addition */
4395 /*-----------------------------------------------------------------*/
4397 genPlus (iCode * ic)
4399 int size, offset = 0;
4402 bool swappedLR = FALSE;
4403 operand *leftOp, *rightOp;
4406 D (emitcode (";", "genPlus"));
4408 /* special cases :- */
4410 aopOp (IC_LEFT (ic), ic, FALSE);
4411 aopOp (IC_RIGHT (ic), ic, FALSE);
4412 aopOp (IC_RESULT (ic), ic, TRUE);
4414 /* if literal, literal on the right or
4415 if left requires ACC or right is already
4417 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4418 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4419 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4421 operand *t = IC_RIGHT (ic);
4422 IC_RIGHT (ic) = IC_LEFT (ic);
4427 /* if both left & right are in bit
4429 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4430 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4436 /* if left in bit space & right literal */
4437 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4438 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4440 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4441 /* if result in bit space */
4442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4444 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4445 emitcode ("cpl", "c");
4446 outBitC (IC_RESULT (ic));
4450 size = getDataSize (IC_RESULT (ic));
4453 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4454 emitcode ("addc", "a,%s", zero);
4455 aopPut (IC_RESULT (ic), "a", offset++);
4461 /* if I can do an increment instead
4462 of add then GOOD for ME */
4463 if (genPlusIncr (ic) == TRUE)
4466 size = getDataSize (IC_RESULT (ic));
4467 leftOp = IC_LEFT(ic);
4468 rightOp = IC_RIGHT(ic);
4471 /* if this is an add for an array access
4472 at a 256 byte boundary */
4474 && AOP_TYPE (op) == AOP_IMMD
4476 && IS_SPEC (OP_SYM_ETYPE (op))
4477 && SPEC_ABSA (OP_SYM_ETYPE (op))
4478 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4481 D(emitcode ("; genPlus aligned array",""));
4482 aopPut (IC_RESULT (ic),
4483 aopGet (rightOp, 0, FALSE, FALSE),
4486 if( 1 == getDataSize (IC_RIGHT (ic)) )
4488 aopPut (IC_RESULT (ic),
4489 aopGet (leftOp, 1, FALSE, FALSE),
4494 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4495 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4496 aopPut (IC_RESULT (ic), "a", 1);
4501 /* if the lower bytes of a literal are zero skip the addition */
4502 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4504 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4505 (skip_bytes+1 < size))
4510 D(emitcode ("; genPlus shortcut",""));
4515 if( offset >= skip_bytes )
4517 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4520 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4522 emitcode("xch", "a,b");
4523 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4524 emitcode (add, "a,b");
4527 else if (aopGetUsesAcc (leftOp, offset))
4529 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4530 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4534 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4535 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4537 aopPut (IC_RESULT (ic), "a", offset);
4538 add = "addc"; /* further adds must propagate carry */
4542 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4543 isOperandVolatile (IC_RESULT (ic), FALSE))
4546 aopPut (IC_RESULT (ic),
4547 aopGet (leftOp, offset, FALSE, FALSE),
4554 adjustArithmeticResult (ic);
4557 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4560 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4561 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4570 /*-----------------------------------------------------------------*/
4571 /* genMinusDec :- does subtraction with decrement if possible */
4572 /*-----------------------------------------------------------------*/
4574 genMinusDec (iCode * ic)
4576 unsigned int icount;
4577 unsigned int size = getDataSize (IC_RESULT (ic));
4579 /* will try to generate an increment */
4580 /* if the right side is not a literal
4582 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4585 /* if the literal value of the right hand side
4586 is greater than 4 then it is not worth it */
4587 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4590 D (emitcode (";", "genMinusDec"));
4592 /* if decrement >=16 bits in register or direct space */
4593 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4594 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4595 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4596 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4604 /* If the next instruction is a goto and the goto target
4605 * is <= 10 instructions previous to this, we can generate
4606 * jumps straight to that target.
4608 if (ic->next && ic->next->op == GOTO
4609 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4610 && labelRange <= 10)
4612 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4613 tlbl = IC_LABEL (ic->next);
4618 tlbl = newiTempLabel (NULL);
4622 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4623 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4624 IS_AOP_PREG (IC_RESULT (ic)))
4625 emitcode ("cjne", "%s,#0xff,%05d$"
4626 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4630 emitcode ("mov", "a,#0xff");
4631 emitcode ("cjne", "a,%s,%05d$"
4632 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4635 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4638 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4639 IS_AOP_PREG (IC_RESULT (ic)))
4640 emitcode ("cjne", "%s,#0xff,%05d$"
4641 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4645 emitcode ("cjne", "a,%s,%05d$"
4646 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4649 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4653 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4654 IS_AOP_PREG (IC_RESULT (ic)))
4655 emitcode ("cjne", "%s,#0xff,%05d$"
4656 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4660 emitcode ("cjne", "a,%s,%05d$"
4661 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4664 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4673 /* if the sizes are greater than 1 then we cannot */
4674 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4675 AOP_SIZE (IC_LEFT (ic)) > 1)
4678 /* we can if the aops of the left & result match or
4679 if they are in registers and the registers are the
4681 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4685 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4687 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4692 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4697 emitcode ("dec", "%s", l);
4700 if (AOP_NEEDSACC (IC_RESULT (ic)))
4701 aopPut (IC_RESULT (ic), "a", 0);
4708 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4709 emitcode ("dec", "a");
4710 aopPut (IC_RESULT (ic), "a", 0);
4717 /*-----------------------------------------------------------------*/
4718 /* addSign - complete with sign */
4719 /*-----------------------------------------------------------------*/
4721 addSign (operand * result, int offset, int sign)
4723 int size = (getDataSize (result) - offset);
4728 emitcode ("rlc", "a");
4729 emitcode ("subb", "a,acc");
4732 aopPut (result, "a", offset++);
4739 aopPut (result, zero, offset++);
4745 /*-----------------------------------------------------------------*/
4746 /* genMinusBits - generates code for subtraction of two bits */
4747 /*-----------------------------------------------------------------*/
4749 genMinusBits (iCode * ic)
4751 symbol *lbl = newiTempLabel (NULL);
4753 D (emitcode (";", "genMinusBits"));
4755 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4757 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4758 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4759 emitcode ("cpl", "c");
4761 outBitC (IC_RESULT (ic));
4765 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4766 emitcode ("subb", "a,acc");
4767 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4768 emitcode ("inc", "a");
4770 aopPut (IC_RESULT (ic), "a", 0);
4771 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4775 /*-----------------------------------------------------------------*/
4776 /* genMinus - generates code for subtraction */
4777 /*-----------------------------------------------------------------*/
4779 genMinus (iCode * ic)
4781 int size, offset = 0;
4783 D (emitcode (";", "genMinus"));
4785 aopOp (IC_LEFT (ic), ic, FALSE);
4786 aopOp (IC_RIGHT (ic), ic, FALSE);
4787 aopOp (IC_RESULT (ic), ic, TRUE);
4789 /* special cases :- */
4790 /* if both left & right are in bit space */
4791 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4792 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4798 /* if I can do an decrement instead
4799 of subtract then GOOD for ME */
4800 if (genMinusDec (ic) == TRUE)
4803 size = getDataSize (IC_RESULT (ic));
4805 /* if literal, add a,#-lit, else normal subb */
4806 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4808 unsigned long lit = 0L;
4809 bool useCarry = FALSE;
4811 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4816 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4818 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4819 if (!offset && !size && lit== (unsigned long) -1)
4821 emitcode ("dec", "a");
4825 /* first add without previous c */
4826 emitcode ("add", "a,#0x%02x",
4827 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4832 emitcode ("addc", "a,#0x%02x",
4833 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4835 aopPut (IC_RESULT (ic), "a", offset++);
4839 /* no need to add zeroes */
4840 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4842 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4851 operand *leftOp, *rightOp;
4853 leftOp = IC_LEFT(ic);
4854 rightOp = IC_RIGHT(ic);
4858 if (aopGetUsesAcc(rightOp, offset)) {
4859 if (aopGetUsesAcc(leftOp, offset)) {
4862 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4864 emitcode ("mov", "b,a");
4867 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4868 emitcode ("subb", "a,b");
4871 /* reverse subtraction with 2's complement */
4873 emitcode( "setb", "c");
4875 emitcode( "cpl", "c");
4876 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4877 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4878 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4879 emitcode("cpl", "a");
4880 if (size) /* skip if last byte */
4881 emitcode( "cpl", "c");
4884 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4887 emitcode ("subb", "a,%s",
4888 aopGet(rightOp, offset, FALSE, TRUE));
4891 aopPut (IC_RESULT (ic), "a", offset++);
4895 adjustArithmeticResult (ic);
4898 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4899 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4900 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4904 /*-----------------------------------------------------------------*/
4905 /* genMultbits :- multiplication of bits */
4906 /*-----------------------------------------------------------------*/
4908 genMultbits (operand * left,
4912 D (emitcode (";", "genMultbits"));
4914 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4915 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4919 /*-----------------------------------------------------------------*/
4920 /* genMultOneByte : 8*8=8/16 bit multiplication */
4921 /*-----------------------------------------------------------------*/
4923 genMultOneByte (operand * left,
4928 int size = AOP_SIZE (result);
4929 bool runtimeSign, compiletimeSign;
4930 bool lUnsigned, rUnsigned, pushedB;
4932 D (emitcode (";", "genMultOneByte"));
4934 if (size < 1 || size > 2)
4936 /* this should never happen */
4937 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4938 AOP_SIZE(result), __FILE__, lineno);
4942 /* (if two literals: the value is computed before) */
4943 /* if one literal, literal on the right */
4944 if (AOP_TYPE (left) == AOP_LIT)
4949 /* emitcode (";", "swapped left and right"); */
4951 /* if no literal, unsigned on the right: shorter code */
4952 if ( AOP_TYPE (right) != AOP_LIT
4953 && SPEC_USIGN (getSpec (operandType (left))))
4960 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4961 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4965 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4966 no need to take care about the signedness! */
4967 || (lUnsigned && rUnsigned))
4969 /* just an unsigned 8 * 8 = 8 multiply
4971 /* emitcode (";","unsigned"); */
4972 /* TODO: check for accumulator clash between left & right aops? */
4974 if (AOP_TYPE (right) == AOP_LIT)
4976 /* moving to accumulator first helps peepholes */
4977 MOVA (aopGet (left, 0, FALSE, FALSE));
4978 MOVB (aopGet (right, 0, FALSE, FALSE));
4982 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4983 MOVA (aopGet (left, 0, FALSE, FALSE));
4986 emitcode ("mul", "ab");
4987 aopPut (result, "a", 0);
4989 aopPut (result, "b", 1);
4995 /* we have to do a signed multiply */
4996 /* emitcode (";", "signed"); */
4998 /* now sign adjust for both left & right */
5000 /* let's see what's needed: */
5001 /* apply negative sign during runtime */
5002 runtimeSign = FALSE;
5003 /* negative sign from literals */
5004 compiletimeSign = FALSE;
5008 if (AOP_TYPE(left) == AOP_LIT)
5010 /* signed literal */
5011 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5013 compiletimeSign = TRUE;
5016 /* signed but not literal */
5022 if (AOP_TYPE(right) == AOP_LIT)
5024 /* signed literal */
5025 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5027 compiletimeSign ^= TRUE;
5030 /* signed but not literal */
5034 /* initialize F0, which stores the runtime sign */
5037 if (compiletimeSign)
5038 emitcode ("setb", "F0"); /* set sign flag */
5040 emitcode ("clr", "F0"); /* reset sign flag */
5043 /* save the signs of the operands */
5044 if (AOP_TYPE(right) == AOP_LIT)
5046 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5048 if (!rUnsigned && val < 0)
5049 emitcode ("mov", "b,#0x%02x", -val);
5051 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5053 else /* ! literal */
5055 if (rUnsigned) /* emitcode (";", "signed"); */
5056 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5059 MOVA (aopGet (right, 0, FALSE, FALSE));
5060 lbl = newiTempLabel (NULL);
5061 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5062 emitcode ("cpl", "F0"); /* complement sign flag */
5063 emitcode ("cpl", "a"); /* 2's complement */
5064 emitcode ("inc", "a");
5066 emitcode ("mov", "b,a");
5070 if (AOP_TYPE(left) == AOP_LIT)
5072 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5074 if (!lUnsigned && val < 0)
5075 emitcode ("mov", "a,#0x%02x", -val);
5077 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5079 else /* ! literal */
5081 MOVA (aopGet (left, 0, FALSE, FALSE));
5085 lbl = newiTempLabel (NULL);
5086 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5087 emitcode ("cpl", "F0"); /* complement sign flag */
5088 emitcode ("cpl", "a"); /* 2's complement */
5089 emitcode ("inc", "a");
5094 /* now the multiplication */
5095 emitcode ("mul", "ab");
5096 if (runtimeSign || compiletimeSign)
5098 lbl = newiTempLabel (NULL);
5100 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5101 emitcode ("cpl", "a"); /* lsb 2's complement */
5103 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5106 emitcode ("add", "a,#1"); /* this sets carry flag */
5107 emitcode ("xch", "a,b");
5108 emitcode ("cpl", "a"); /* msb 2's complement */
5109 emitcode ("addc", "a,#0");
5110 emitcode ("xch", "a,b");
5114 aopPut (result, "a", 0);
5116 aopPut (result, "b", 1);
5121 /*-----------------------------------------------------------------*/
5122 /* genMult - generates code for multiplication */
5123 /*-----------------------------------------------------------------*/
5125 genMult (iCode * ic)
5127 operand *left = IC_LEFT (ic);
5128 operand *right = IC_RIGHT (ic);
5129 operand *result = IC_RESULT (ic);
5131 D (emitcode (";", "genMult"));
5133 /* assign the asmops */
5134 aopOp (left, ic, FALSE);
5135 aopOp (right, ic, FALSE);
5136 aopOp (result, ic, TRUE);
5138 /* special cases first */
5140 if (AOP_TYPE (left) == AOP_CRY &&
5141 AOP_TYPE (right) == AOP_CRY)
5143 genMultbits (left, right, result);
5147 /* if both are of size == 1 */
5148 #if 0 // one of them can be a sloc shared with the result
5149 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5151 if (getSize(operandType(left)) == 1 &&
5152 getSize(operandType(right)) == 1)
5155 genMultOneByte (left, right, result);
5159 /* should have been converted to function call */
5160 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5161 getSize(OP_SYMBOL(right)->type));
5165 freeAsmop (result, NULL, ic, TRUE);
5166 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5167 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170 /*-----------------------------------------------------------------*/
5171 /* genDivbits :- division of bits */
5172 /*-----------------------------------------------------------------*/
5174 genDivbits (operand * left,
5181 D(emitcode ("; genDivbits",""));
5185 /* the result must be bit */
5186 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5187 l = aopGet (left, 0, FALSE, FALSE);
5191 emitcode ("div", "ab");
5192 emitcode ("rrc", "a");
5196 aopPut (result, "c", 0);
5199 /*-----------------------------------------------------------------*/
5200 /* genDivOneByte : 8 bit division */
5201 /*-----------------------------------------------------------------*/
5203 genDivOneByte (operand * left,
5207 bool lUnsigned, rUnsigned, pushedB;
5208 bool runtimeSign, compiletimeSign;
5209 bool accuse = FALSE;
5210 bool pushedA = FALSE;
5214 D(emitcode ("; genDivOneByte",""));
5216 /* Why is it necessary that genDivOneByte() can return an int result?
5219 volatile unsigned char uc;
5220 volatile signed char sc1, sc2;
5233 In all cases a one byte result would overflow, the following cast to int
5234 would return the wrong result.
5236 Two possible solution:
5237 a) cast operands to int, if ((unsigned) / (signed)) or
5238 ((signed) / (signed))
5239 b) return an 16 bit signed int; this is what we're doing here!
5242 size = AOP_SIZE (result) - 1;
5244 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5245 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5249 /* signed or unsigned */
5250 if (lUnsigned && rUnsigned)
5252 /* unsigned is easy */
5253 MOVB (aopGet (right, 0, FALSE, FALSE));
5254 MOVA (aopGet (left, 0, FALSE, FALSE));
5255 emitcode ("div", "ab");
5256 aopPut (result, "a", 0);
5258 aopPut (result, zero, offset++);
5264 /* signed is a little bit more difficult */
5266 /* now sign adjust for both left & right */
5268 /* let's see what's needed: */
5269 /* apply negative sign during runtime */
5270 runtimeSign = FALSE;
5271 /* negative sign from literals */
5272 compiletimeSign = FALSE;
5276 if (AOP_TYPE(left) == AOP_LIT)
5278 /* signed literal */
5279 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5281 compiletimeSign = TRUE;
5284 /* signed but not literal */
5290 if (AOP_TYPE(right) == AOP_LIT)
5292 /* signed literal */
5293 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5295 compiletimeSign ^= TRUE;
5298 /* signed but not literal */
5302 /* initialize F0, which stores the runtime sign */
5305 if (compiletimeSign)
5306 emitcode ("setb", "F0"); /* set sign flag */
5308 emitcode ("clr", "F0"); /* reset sign flag */
5311 /* save the signs of the operands */
5312 if (AOP_TYPE(right) == AOP_LIT)
5314 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5316 if (!rUnsigned && val < 0)
5317 emitcode ("mov", "b,#0x%02x", -val);
5319 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5321 else /* ! literal */
5324 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5327 MOVA (aopGet (right, 0, FALSE, FALSE));
5328 lbl = newiTempLabel (NULL);
5329 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5330 emitcode ("cpl", "F0"); /* complement sign flag */
5331 emitcode ("cpl", "a"); /* 2's complement */
5332 emitcode ("inc", "a");
5334 emitcode ("mov", "b,a");
5338 if (AOP_TYPE(left) == AOP_LIT)
5340 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5342 if (!lUnsigned && val < 0)
5343 emitcode ("mov", "a,#0x%02x", -val);
5345 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5347 else /* ! literal */
5349 MOVA (aopGet (left, 0, FALSE, FALSE));
5353 lbl = newiTempLabel (NULL);
5354 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5355 emitcode ("cpl", "F0"); /* complement sign flag */
5356 emitcode ("cpl", "a"); /* 2's complement */
5357 emitcode ("inc", "a");
5362 /* now the division */
5363 emitcode ("div", "ab");
5365 if (runtimeSign || compiletimeSign)
5367 lbl = newiTempLabel (NULL);
5369 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5370 emitcode ("cpl", "a"); /* lsb 2's complement */
5371 emitcode ("inc", "a");
5374 accuse = aopPut (result, "a", 0);
5377 /* msb is 0x00 or 0xff depending on the sign */
5382 emitcode ("push", "acc");
5385 emitcode ("mov", "c,F0");
5386 emitcode ("subb", "a,acc");
5388 aopPut (result, "a", offset++);
5390 else /* compiletimeSign */
5392 if (aopPutUsesAcc (result, "#0xFF", offset))
5394 emitcode ("push", "acc");
5398 aopPut (result, "#0xff", offset++);
5404 aopPut (result, "a", 0);
5406 aopPut (result, zero, offset++);
5410 emitcode ("pop", "acc");
5414 /*-----------------------------------------------------------------*/
5415 /* genDiv - generates code for division */
5416 /*-----------------------------------------------------------------*/
5420 operand *left = IC_LEFT (ic);
5421 operand *right = IC_RIGHT (ic);
5422 operand *result = IC_RESULT (ic);
5424 D (emitcode (";", "genDiv"));
5426 /* assign the amsops */
5427 aopOp (left, ic, FALSE);
5428 aopOp (right, ic, FALSE);
5429 aopOp (result, ic, TRUE);
5431 /* special cases first */
5433 if (AOP_TYPE (left) == AOP_CRY &&
5434 AOP_TYPE (right) == AOP_CRY)
5436 genDivbits (left, right, result);
5440 /* if both are of size == 1 */
5441 if (AOP_SIZE (left) == 1 &&
5442 AOP_SIZE (right) == 1)
5444 genDivOneByte (left, right, result);
5448 /* should have been converted to function call */
5451 freeAsmop (result, NULL, ic, TRUE);
5452 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5456 /*-----------------------------------------------------------------*/
5457 /* genModbits :- modulus of bits */
5458 /*-----------------------------------------------------------------*/
5460 genModbits (operand * left,
5467 D (emitcode (";", "genModbits"));
5471 /* the result must be bit */
5472 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5473 l = aopGet (left, 0, FALSE, FALSE);
5477 emitcode ("div", "ab");
5478 emitcode ("mov", "a,b");
5479 emitcode ("rrc", "a");
5483 aopPut (result, "c", 0);
5486 /*-----------------------------------------------------------------*/
5487 /* genModOneByte : 8 bit modulus */
5488 /*-----------------------------------------------------------------*/
5490 genModOneByte (operand * left,
5494 bool lUnsigned, rUnsigned, pushedB;
5495 bool runtimeSign, compiletimeSign;
5499 D (emitcode (";", "genModOneByte"));
5501 size = AOP_SIZE (result) - 1;
5503 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5504 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5506 /* if right is a literal, check it for 2^n */
5507 if (AOP_TYPE(right) == AOP_LIT)
5509 unsigned char val = abs((int) operandLitValue(right));
5510 symbol *lbl2 = NULL;
5514 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5523 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5524 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5525 /* because iCode should have been changed to genAnd */
5526 /* see file "SDCCopt.c", function "convertToFcall()" */
5528 MOVA (aopGet (left, 0, FALSE, FALSE));
5529 emitcode ("mov", "c,acc.7");
5530 emitcode ("anl", "a,#0x%02x", val - 1);
5531 lbl = newiTempLabel (NULL);
5532 emitcode ("jz", "%05d$", (lbl->key + 100));
5533 emitcode ("jnc", "%05d$", (lbl->key + 100));
5534 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5540 aopPut (result, "a", 0);
5542 aopPut (result, "#0xff", offs2++);
5543 lbl2 = newiTempLabel (NULL);
5544 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5547 aopPut (result, "a", 0);
5549 aopPut (result, zero, offset++);
5563 /* signed or unsigned */
5564 if (lUnsigned && rUnsigned)
5566 /* unsigned is easy */
5567 MOVB (aopGet (right, 0, FALSE, FALSE));
5568 MOVA (aopGet (left, 0, FALSE, FALSE));
5569 emitcode ("div", "ab");
5570 aopPut (result, "b", 0);
5572 aopPut (result, zero, offset++);
5578 /* signed is a little bit more difficult */
5580 /* now sign adjust for both left & right */
5582 /* modulus: sign of the right operand has no influence on the result! */
5583 if (AOP_TYPE(right) == AOP_LIT)
5585 signed char val = (char) operandLitValue(right);
5587 if (!rUnsigned && val < 0)
5588 emitcode ("mov", "b,#0x%02x", -val);
5590 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5592 else /* not literal */
5595 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5598 MOVA (aopGet (right, 0, FALSE, FALSE));
5599 lbl = newiTempLabel (NULL);
5600 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5601 emitcode ("cpl", "a"); /* 2's complement */
5602 emitcode ("inc", "a");
5604 emitcode ("mov", "b,a");
5608 /* let's see what's needed: */
5609 /* apply negative sign during runtime */
5610 runtimeSign = FALSE;
5611 /* negative sign from literals */
5612 compiletimeSign = FALSE;
5614 /* sign adjust left side */
5615 if (AOP_TYPE(left) == AOP_LIT)
5617 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5619 if (!lUnsigned && val < 0)
5621 compiletimeSign = TRUE; /* set sign flag */
5622 emitcode ("mov", "a,#0x%02x", -val);
5625 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5627 else /* ! literal */
5629 MOVA (aopGet (left, 0, FALSE, FALSE));
5634 emitcode ("clr", "F0"); /* clear sign flag */
5636 lbl = newiTempLabel (NULL);
5637 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5638 emitcode ("setb", "F0"); /* set sign flag */
5639 emitcode ("cpl", "a"); /* 2's complement */
5640 emitcode ("inc", "a");
5645 /* now the modulus */
5646 emitcode ("div", "ab");
5648 if (runtimeSign || compiletimeSign)
5650 emitcode ("mov", "a,b");
5651 lbl = newiTempLabel (NULL);
5653 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5654 emitcode ("cpl", "a"); /* 2's complement */
5655 emitcode ("inc", "a");
5658 aopPut (result, "a", 0);
5661 /* msb is 0x00 or 0xff depending on the sign */
5664 emitcode ("mov", "c,F0");
5665 emitcode ("subb", "a,acc");
5667 aopPut (result, "a", offset++);
5669 else /* compiletimeSign */
5671 aopPut (result, "#0xff", offset++);
5676 aopPut (result, "b", 0);
5678 aopPut (result, zero, offset++);
5684 /*-----------------------------------------------------------------*/
5685 /* genMod - generates code for division */
5686 /*-----------------------------------------------------------------*/
5690 operand *left = IC_LEFT (ic);
5691 operand *right = IC_RIGHT (ic);
5692 operand *result = IC_RESULT (ic);
5694 D (emitcode (";", "genMod"));
5696 /* assign the asmops */
5697 aopOp (left, ic, FALSE);
5698 aopOp (right, ic, FALSE);
5699 aopOp (result, ic, TRUE);
5701 /* special cases first */
5703 if (AOP_TYPE (left) == AOP_CRY &&
5704 AOP_TYPE (right) == AOP_CRY)
5706 genModbits (left, right, result);
5710 /* if both are of size == 1 */
5711 if (AOP_SIZE (left) == 1 &&
5712 AOP_SIZE (right) == 1)
5714 genModOneByte (left, right, result);
5718 /* should have been converted to function call */
5722 freeAsmop (result, NULL, ic, TRUE);
5723 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5724 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5727 /*-----------------------------------------------------------------*/
5728 /* genIfxJump :- will create a jump depending on the ifx */
5729 /*-----------------------------------------------------------------*/
5731 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5734 symbol *tlbl = newiTempLabel (NULL);
5737 D (emitcode (";", "genIfxJump"));
5739 /* if true label then we jump if condition
5743 jlbl = IC_TRUE (ic);
5744 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5745 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5749 /* false label is present */
5750 jlbl = IC_FALSE (ic);
5751 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5752 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5754 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5755 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5757 emitcode (inst, "%05d$", tlbl->key + 100);
5758 freeForBranchAsmop (result);
5759 freeForBranchAsmop (right);
5760 freeForBranchAsmop (left);
5761 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5764 /* mark the icode as generated */
5768 /*-----------------------------------------------------------------*/
5769 /* genCmp :- greater or less than comparison */
5770 /*-----------------------------------------------------------------*/
5772 genCmp (operand * left, operand * right,
5773 operand * result, iCode * ifx, int sign, iCode *ic)
5775 int size, offset = 0;
5776 unsigned long lit = 0L;
5779 D (emitcode (";", "genCmp"));
5781 /* if left & right are bit variables */
5782 if (AOP_TYPE (left) == AOP_CRY &&
5783 AOP_TYPE (right) == AOP_CRY)
5785 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5786 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5790 /* subtract right from left if at the
5791 end the carry flag is set then we know that
5792 left is greater than right */
5793 size = max (AOP_SIZE (left), AOP_SIZE (right));
5795 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5796 if ((size == 1) && !sign &&
5797 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5799 symbol *lbl = newiTempLabel (NULL);
5800 emitcode ("cjne", "%s,%s,%05d$",
5801 aopGet (left, offset, FALSE, FALSE),
5802 aopGet (right, offset, FALSE, FALSE),
5808 if (AOP_TYPE (right) == AOP_LIT)
5810 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5811 /* optimize if(x < 0) or if(x >= 0) */
5820 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5821 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5823 genIfxJump (ifx, "acc.7", left, right, result);
5824 freeAsmop (right, NULL, ic, TRUE);
5825 freeAsmop (left, NULL, ic, TRUE);
5831 emitcode ("rlc", "a");
5838 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5839 while (size && (bytelit == 0))
5842 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5848 MOVA (aopGet (left, offset, FALSE, FALSE));
5849 if (sign && size == 0)
5851 emitcode ("xrl", "a,#0x80");
5852 emitcode ("subb", "a,#0x%02x",
5853 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5857 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5867 bool pushedB = FALSE;
5868 rightInB = aopGetUsesAcc(right, offset);
5872 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5874 MOVA (aopGet (left, offset, FALSE, FALSE));
5875 if (sign && size == 0)
5877 emitcode ("xrl", "a,#0x80");
5882 MOVB (aopGet (right, offset, FALSE, FALSE));
5884 emitcode ("xrl", "b,#0x80");
5885 emitcode ("subb", "a,b");
5890 emitcode ("subb", "a,b");
5892 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5902 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5903 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5904 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5910 /* if the result is used in the next
5911 ifx conditional branch then generate
5912 code a little differently */
5915 genIfxJump (ifx, "c", NULL, NULL, result);
5921 /* leave the result in acc */
5925 /*-----------------------------------------------------------------*/
5926 /* genCmpGt :- greater than comparison */
5927 /*-----------------------------------------------------------------*/
5929 genCmpGt (iCode * ic, iCode * ifx)
5931 operand *left, *right, *result;
5932 sym_link *letype, *retype;
5935 D (emitcode (";", "genCmpGt"));
5937 left = IC_LEFT (ic);
5938 right = IC_RIGHT (ic);
5939 result = IC_RESULT (ic);
5941 letype = getSpec (operandType (left));
5942 retype = getSpec (operandType (right));
5943 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5944 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5945 /* assign the amsops */
5946 aopOp (result, ic, TRUE);
5947 aopOp (left, ic, FALSE);
5948 aopOp (right, ic, FALSE);
5950 genCmp (right, left, result, ifx, sign, ic);
5952 freeAsmop (result, NULL, ic, TRUE);
5955 /*-----------------------------------------------------------------*/
5956 /* genCmpLt - less than comparisons */
5957 /*-----------------------------------------------------------------*/
5959 genCmpLt (iCode * ic, iCode * ifx)
5961 operand *left, *right, *result;
5962 sym_link *letype, *retype;
5965 D (emitcode (";", "genCmpLt"));
5967 left = IC_LEFT (ic);
5968 right = IC_RIGHT (ic);
5969 result = IC_RESULT (ic);
5971 letype = getSpec (operandType (left));
5972 retype = getSpec (operandType (right));
5973 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5974 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5975 /* assign the amsops */
5976 aopOp (result, ic, TRUE);
5977 aopOp (left, ic, FALSE);
5978 aopOp (right, ic, FALSE);
5980 genCmp (left, right, result, ifx, sign, ic);
5982 freeAsmop (result, NULL, ic, TRUE);
5985 /*-----------------------------------------------------------------*/
5986 /* gencjneshort - compare and jump if not equal */
5987 /*-----------------------------------------------------------------*/
5989 gencjneshort (operand * left, operand * right, symbol * lbl)
5991 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5993 unsigned long lit = 0L;
5995 D (emitcode (";", "gencjneshort"));
5997 /* if the left side is a literal or
5998 if the right is in a pointer register and left
6000 if ((AOP_TYPE (left) == AOP_LIT) ||
6001 (AOP_TYPE (left) == AOP_IMMD) ||
6002 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6009 if (AOP_TYPE (right) == AOP_LIT)
6010 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6012 /* if the right side is a literal then anything goes */
6013 if (AOP_TYPE (right) == AOP_LIT &&
6014 AOP_TYPE (left) != AOP_DIR &&
6015 AOP_TYPE (left) != AOP_IMMD)
6019 emitcode ("cjne", "%s,%s,%05d$",
6020 aopGet (left, offset, FALSE, FALSE),
6021 aopGet (right, offset, FALSE, FALSE),
6027 /* if the right side is in a register or in direct space or
6028 if the left is a pointer register & right is not */
6029 else if (AOP_TYPE (right) == AOP_REG ||
6030 AOP_TYPE (right) == AOP_DIR ||
6031 AOP_TYPE (right) == AOP_LIT ||
6032 AOP_TYPE (right) == AOP_IMMD ||
6033 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6034 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6038 MOVA (aopGet (left, offset, FALSE, FALSE));
6039 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6040 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6041 emitcode ("jnz", "%05d$", lbl->key + 100);
6043 emitcode ("cjne", "a,%s,%05d$",
6044 aopGet (right, offset, FALSE, TRUE),
6051 /* right is a pointer reg need both a & b */
6054 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6055 wassertl(!BINUSE, "B was in use");
6056 MOVB (aopGet (left, offset, FALSE, FALSE));
6057 MOVA (aopGet (right, offset, FALSE, FALSE));
6058 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6064 /*-----------------------------------------------------------------*/
6065 /* gencjne - compare and jump if not equal */
6066 /*-----------------------------------------------------------------*/
6068 gencjne (operand * left, operand * right, symbol * lbl)
6070 symbol *tlbl = newiTempLabel (NULL);
6072 D (emitcode (";", "gencjne"));
6074 gencjneshort (left, right, lbl);
6076 emitcode ("mov", "a,%s", one);
6077 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6079 emitcode ("clr", "a");
6083 /*-----------------------------------------------------------------*/
6084 /* genCmpEq - generates code for equal to */
6085 /*-----------------------------------------------------------------*/
6087 genCmpEq (iCode * ic, iCode * ifx)
6089 bool swappedLR = FALSE;
6090 operand *left, *right, *result;
6092 D (emitcode (";", "genCmpEq"));
6094 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6095 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6096 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6098 /* if literal, literal on the right or
6099 if the right is in a pointer register and left
6101 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6102 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6104 operand *t = IC_RIGHT (ic);
6105 IC_RIGHT (ic) = IC_LEFT (ic);
6110 if (ifx && !AOP_SIZE (result))
6113 /* if they are both bit variables */
6114 if (AOP_TYPE (left) == AOP_CRY &&
6115 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6117 if (AOP_TYPE (right) == AOP_LIT)
6119 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6122 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6123 emitcode ("cpl", "c");
6127 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6131 emitcode ("clr", "c");
6133 /* AOP_TYPE(right) == AOP_CRY */
6137 symbol *lbl = newiTempLabel (NULL);
6138 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6139 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6140 emitcode ("cpl", "c");
6143 /* if true label then we jump if condition
6145 tlbl = newiTempLabel (NULL);
6148 emitcode ("jnc", "%05d$", tlbl->key + 100);
6149 freeForBranchAsmop (result);
6150 freeForBranchAsmop (right);
6151 freeForBranchAsmop (left);
6152 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6156 emitcode ("jc", "%05d$", tlbl->key + 100);
6157 freeForBranchAsmop (result);
6158 freeForBranchAsmop (right);
6159 freeForBranchAsmop (left);
6160 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6166 tlbl = newiTempLabel (NULL);
6167 gencjneshort (left, right, tlbl);
6170 freeForBranchAsmop (result);
6171 freeForBranchAsmop (right);
6172 freeForBranchAsmop (left);
6173 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6178 symbol *lbl = newiTempLabel (NULL);
6179 emitcode ("sjmp", "%05d$", lbl->key + 100);
6181 freeForBranchAsmop (result);
6182 freeForBranchAsmop (right);
6183 freeForBranchAsmop (left);
6184 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6188 /* mark the icode as generated */
6193 /* if they are both bit variables */
6194 if (AOP_TYPE (left) == AOP_CRY &&
6195 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6197 if (AOP_TYPE (right) == AOP_LIT)
6199 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6202 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6203 emitcode ("cpl", "c");
6207 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6211 emitcode ("clr", "c");
6213 /* AOP_TYPE(right) == AOP_CRY */
6217 symbol *lbl = newiTempLabel (NULL);
6218 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6219 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6220 emitcode ("cpl", "c");
6224 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6231 genIfxJump (ifx, "c", left, right, result);
6234 /* if the result is used in an arithmetic operation
6235 then put the result in place */
6240 gencjne (left, right, newiTempLabel (NULL));
6241 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6243 aopPut (result, "a", 0);
6248 genIfxJump (ifx, "a", left, right, result);
6251 /* if the result is used in an arithmetic operation
6252 then put the result in place */
6253 if (AOP_TYPE (result) != AOP_CRY)
6255 /* leave the result in acc */
6259 freeAsmop (result, NULL, ic, TRUE);
6262 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6263 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6272 /*-----------------------------------------------------------------*/
6273 /* ifxForOp - returns the icode containing the ifx for operand */
6274 /*-----------------------------------------------------------------*/
6276 ifxForOp (operand * op, iCode * ic)
6278 /* if true symbol then needs to be assigned */
6279 if (IS_TRUE_SYMOP (op))
6282 /* if this has register type condition and
6283 the next instruction is ifx with the same operand
6284 and live to of the operand is upto the ifx only then */
6286 ic->next->op == IFX &&
6287 IC_COND (ic->next)->key == op->key &&
6288 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6294 /*-----------------------------------------------------------------*/
6295 /* hasInc - operand is incremented before any other use */
6296 /*-----------------------------------------------------------------*/
6298 hasInc (operand *op, iCode *ic, int osize)
6300 sym_link *type = operandType(op);
6301 sym_link *retype = getSpec (type);
6302 iCode *lic = ic->next;
6305 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6306 if (!IS_SYMOP(op)) return NULL;
6308 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6309 if (IS_AGGREGATE(type->next)) return NULL;
6310 if (osize != (isize = getSize(type->next))) return NULL;
6313 /* if operand of the form op = op + <sizeof *op> */
6314 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6315 isOperandEqual(IC_RESULT(lic),op) &&
6316 isOperandLiteral(IC_RIGHT(lic)) &&
6317 operandLitValue(IC_RIGHT(lic)) == isize) {
6320 /* if the operand used or deffed */
6321 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6324 /* if GOTO or IFX */
6325 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6331 /*-----------------------------------------------------------------*/
6332 /* genAndOp - for && operation */
6333 /*-----------------------------------------------------------------*/
6335 genAndOp (iCode * ic)
6337 operand *left, *right, *result;
6340 D (emitcode (";", "genAndOp"));
6342 /* note here that && operations that are in an
6343 if statement are taken away by backPatchLabels
6344 only those used in arthmetic operations remain */
6345 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6346 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6347 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6349 /* if both are bit variables */
6350 if (AOP_TYPE (left) == AOP_CRY &&
6351 AOP_TYPE (right) == AOP_CRY)
6353 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6354 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6359 tlbl = newiTempLabel (NULL);
6361 emitcode ("jz", "%05d$", tlbl->key + 100);
6367 freeAsmop (result, NULL, ic, TRUE);
6368 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6369 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6373 /*-----------------------------------------------------------------*/
6374 /* genOrOp - for || operation */
6375 /*-----------------------------------------------------------------*/
6377 genOrOp (iCode * ic)
6379 operand *left, *right, *result;
6382 D (emitcode (";", "genOrOp"));
6384 /* note here that || operations that are in an
6385 if statement are taken away by backPatchLabels
6386 only those used in arthmetic operations remain */
6387 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6388 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6389 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6391 /* if both are bit variables */
6392 if (AOP_TYPE (left) == AOP_CRY &&
6393 AOP_TYPE (right) == AOP_CRY)
6395 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6396 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6401 tlbl = newiTempLabel (NULL);
6403 emitcode ("jnz", "%05d$", tlbl->key + 100);
6409 freeAsmop (result, NULL, ic, TRUE);
6410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6414 /*-----------------------------------------------------------------*/
6415 /* isLiteralBit - test if lit == 2^n */
6416 /*-----------------------------------------------------------------*/
6418 isLiteralBit (unsigned long lit)
6420 unsigned long pw[32] =
6421 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6422 0x100L, 0x200L, 0x400L, 0x800L,
6423 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6424 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6425 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6426 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6427 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6430 for (idx = 0; idx < 32; idx++)
6436 /*-----------------------------------------------------------------*/
6437 /* continueIfTrue - */
6438 /*-----------------------------------------------------------------*/
6440 continueIfTrue (iCode * ic)
6443 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6447 /*-----------------------------------------------------------------*/
6449 /*-----------------------------------------------------------------*/
6451 jumpIfTrue (iCode * ic)
6454 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6458 /*-----------------------------------------------------------------*/
6459 /* jmpTrueOrFalse - */
6460 /*-----------------------------------------------------------------*/
6462 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6464 // ugly but optimized by peephole
6467 symbol *nlbl = newiTempLabel (NULL);
6468 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6470 freeForBranchAsmop (result);
6471 freeForBranchAsmop (right);
6472 freeForBranchAsmop (left);
6473 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6478 freeForBranchAsmop (result);
6479 freeForBranchAsmop (right);
6480 freeForBranchAsmop (left);
6481 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6487 /*-----------------------------------------------------------------*/
6488 /* genAnd - code for and */
6489 /*-----------------------------------------------------------------*/
6491 genAnd (iCode * ic, iCode * ifx)
6493 operand *left, *right, *result;
6494 int size, offset = 0;
6495 unsigned long lit = 0L;
6499 D (emitcode (";", "genAnd"));
6501 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6502 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6503 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6506 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6508 AOP_TYPE (left), AOP_TYPE (right));
6509 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6511 AOP_SIZE (left), AOP_SIZE (right));
6514 /* if left is a literal & right is not then exchange them */
6515 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6516 AOP_NEEDSACC (left))
6518 operand *tmp = right;
6523 /* if result = right then exchange left and right */
6524 if (sameRegs (AOP (result), AOP (right)))
6526 operand *tmp = right;
6531 /* if right is bit then exchange them */
6532 if (AOP_TYPE (right) == AOP_CRY &&
6533 AOP_TYPE (left) != AOP_CRY)
6535 operand *tmp = right;
6539 if (AOP_TYPE (right) == AOP_LIT)
6540 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6542 size = AOP_SIZE (result);
6545 // result = bit & yy;
6546 if (AOP_TYPE (left) == AOP_CRY)
6548 // c = bit & literal;
6549 if (AOP_TYPE (right) == AOP_LIT)
6553 if (size && sameRegs (AOP (result), AOP (left)))
6556 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6561 if (size && (AOP_TYPE (result) == AOP_CRY))
6563 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6566 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6571 emitcode ("clr", "c");
6576 if (AOP_TYPE (right) == AOP_CRY)
6579 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6580 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6585 MOVA (aopGet (right, 0, FALSE, FALSE));
6587 emitcode ("rrc", "a");
6588 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6596 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6597 genIfxJump (ifx, "c", left, right, result);
6601 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6602 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6603 if ((AOP_TYPE (right) == AOP_LIT) &&
6604 (AOP_TYPE (result) == AOP_CRY) &&
6605 (AOP_TYPE (left) != AOP_CRY))
6607 int posbit = isLiteralBit (lit);
6612 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6616 switch (posbit & 0x07)
6618 case 0: emitcode ("rrc", "a");
6620 case 7: emitcode ("rlc", "a");
6622 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6631 SNPRINTF (buffer, sizeof(buffer),
6632 "acc.%d", posbit & 0x07);
6633 genIfxJump (ifx, buffer, left, right, result);
6636 {// what is this case? just found it in ds390/gen.c
6637 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6644 symbol *tlbl = newiTempLabel (NULL);
6645 int sizel = AOP_SIZE (left);
6647 emitcode ("setb", "c");
6650 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6652 MOVA (aopGet (left, offset, FALSE, FALSE));
6654 if ((posbit = isLiteralBit (bytelit)) != 0)
6655 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6658 if (bytelit != 0x0FFL)
6659 emitcode ("anl", "a,%s",
6660 aopGet (right, offset, FALSE, TRUE));
6661 emitcode ("jnz", "%05d$", tlbl->key + 100);
6666 // bit = left & literal
6669 emitcode ("clr", "c");
6672 // if(left & literal)
6676 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6686 /* if left is same as result */
6687 if (sameRegs (AOP (result), AOP (left)))
6689 for (; size--; offset++)
6691 if (AOP_TYPE (right) == AOP_LIT)
6693 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6694 if (bytelit == 0x0FF)
6696 /* dummy read of volatile operand */
6697 if (isOperandVolatile (left, FALSE))
6698 MOVA (aopGet (left, offset, FALSE, FALSE));
6702 else if (bytelit == 0)
6704 aopPut (result, zero, offset);
6706 else if (IS_AOP_PREG (result))
6708 MOVA (aopGet (left, offset, FALSE, TRUE));
6709 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6710 aopPut (result, "a", offset);
6713 emitcode ("anl", "%s,%s",
6714 aopGet (left, offset, FALSE, TRUE),
6715 aopGet (right, offset, FALSE, FALSE));
6719 if (AOP_TYPE (left) == AOP_ACC)
6722 emitcode("mov", "a,b");
6723 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6725 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6727 MOVB (aopGet (left, offset, FALSE, FALSE));
6728 MOVA (aopGet (right, offset, FALSE, FALSE));
6729 emitcode ("anl", "a,b");
6730 aopPut (result, "a", offset);
6732 else if (aopGetUsesAcc (left, offset))
6734 MOVA (aopGet (left, offset, FALSE, FALSE));
6735 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6736 aopPut (result, "a", offset);
6740 MOVA (aopGet (right, offset, FALSE, FALSE));
6741 if (IS_AOP_PREG (result))
6743 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6744 aopPut (result, "a", offset);
6747 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6754 // left & result in different registers
6755 if (AOP_TYPE (result) == AOP_CRY)
6758 // if(size), result in bit
6759 // if(!size && ifx), conditional oper: if(left & right)
6760 symbol *tlbl = newiTempLabel (NULL);
6761 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6763 emitcode ("setb", "c");
6766 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6767 && AOP_TYPE(left)==AOP_ACC)
6770 emitcode("mov", "a,b");
6771 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6773 else if (AOP_TYPE(left)==AOP_ACC)
6777 bool pushedB = pushB ();
6778 emitcode("mov", "b,a");
6779 MOVA (aopGet (right, offset, FALSE, FALSE));
6780 emitcode("anl", "a,b");
6785 MOVA (aopGet (right, offset, FALSE, FALSE));
6786 emitcode("anl", "a,b");
6789 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6791 MOVB (aopGet (left, offset, FALSE, FALSE));
6792 MOVA (aopGet (right, offset, FALSE, FALSE));
6793 emitcode ("anl", "a,b");
6795 else if (aopGetUsesAcc (left, offset))
6797 MOVA (aopGet (left, offset, FALSE, FALSE));
6798 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6802 MOVA (aopGet (right, offset, FALSE, FALSE));
6803 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6806 emitcode ("jnz", "%05d$", tlbl->key + 100);
6816 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6822 for (; (size--); offset++)
6825 // result = left & right
6826 if (AOP_TYPE (right) == AOP_LIT)
6828 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6829 if (bytelit == 0x0FF)
6832 aopGet (left, offset, FALSE, FALSE),
6836 else if (bytelit == 0)
6838 /* dummy read of volatile operand */
6839 if (isOperandVolatile (left, FALSE))
6840 MOVA (aopGet (left, offset, FALSE, FALSE));
6841 aopPut (result, zero, offset);
6844 else if (AOP_TYPE (left) == AOP_ACC)
6848 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6849 aopPut (result, "a", offset);
6854 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6855 aopPut (result, "b", offset);
6860 // faster than result <- left, anl result,right
6861 // and better if result is SFR
6862 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6863 && AOP_TYPE(left)==AOP_ACC)
6866 emitcode("mov", "a,b");
6867 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6869 else if (AOP_TYPE(left)==AOP_ACC)
6873 bool pushedB = pushB ();
6874 emitcode("mov", "b,a");
6875 MOVA (aopGet (right, offset, FALSE, FALSE));
6876 emitcode("anl", "a,b");
6881 MOVA (aopGet (right, offset, FALSE, FALSE));
6882 emitcode("anl", "a,b");
6885 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6887 MOVB (aopGet (left, offset, FALSE, FALSE));
6888 MOVA (aopGet (right, offset, FALSE, FALSE));
6889 emitcode ("anl", "a,b");
6891 else if (aopGetUsesAcc (left, offset))
6893 MOVA (aopGet (left, offset, FALSE, FALSE));
6894 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6898 MOVA (aopGet (right, offset, FALSE, FALSE));
6899 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6901 aopPut (result, "a", offset);
6907 freeAsmop (result, NULL, ic, TRUE);
6908 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6909 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6912 /*-----------------------------------------------------------------*/
6913 /* genOr - code for or */
6914 /*-----------------------------------------------------------------*/
6916 genOr (iCode * ic, iCode * ifx)
6918 operand *left, *right, *result;
6919 int size, offset = 0;
6920 unsigned long lit = 0L;
6923 D (emitcode (";", "genOr"));
6925 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6926 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6927 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6930 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6932 AOP_TYPE (left), AOP_TYPE (right));
6933 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6935 AOP_SIZE (left), AOP_SIZE (right));
6938 /* if left is a literal & right is not then exchange them */
6939 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6940 AOP_NEEDSACC (left))
6942 operand *tmp = right;
6947 /* if result = right then exchange them */
6948 if (sameRegs (AOP (result), AOP (right)))
6950 operand *tmp = right;
6955 /* if right is bit then exchange them */
6956 if (AOP_TYPE (right) == AOP_CRY &&
6957 AOP_TYPE (left) != AOP_CRY)
6959 operand *tmp = right;
6963 if (AOP_TYPE (right) == AOP_LIT)
6964 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6966 size = AOP_SIZE (result);
6970 if (AOP_TYPE (left) == AOP_CRY)
6972 if (AOP_TYPE (right) == AOP_LIT)
6974 // c = bit | literal;
6977 // lit != 0 => result = 1
6978 if (AOP_TYPE (result) == AOP_CRY)
6981 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6983 continueIfTrue (ifx);
6986 emitcode ("setb", "c");
6990 // lit == 0 => result = left
6991 if (size && sameRegs (AOP (result), AOP (left)))
6993 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6998 if (AOP_TYPE (right) == AOP_CRY)
7001 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7002 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7007 symbol *tlbl = newiTempLabel (NULL);
7008 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7009 emitcode ("setb", "c");
7010 emitcode ("jb", "%s,%05d$",
7011 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7013 emitcode ("jnz", "%05d$", tlbl->key + 100);
7014 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7016 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7031 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7032 genIfxJump (ifx, "c", left, right, result);
7036 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7037 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7038 if ((AOP_TYPE (right) == AOP_LIT) &&
7039 (AOP_TYPE (result) == AOP_CRY) &&
7040 (AOP_TYPE (left) != AOP_CRY))
7046 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7048 continueIfTrue (ifx);
7053 // lit = 0, result = boolean(left)
7055 emitcode ("setb", "c");
7059 symbol *tlbl = newiTempLabel (NULL);
7060 emitcode ("jnz", "%05d$", tlbl->key + 100);
7066 genIfxJump (ifx, "a", left, right, result);
7074 /* if left is same as result */
7075 if (sameRegs (AOP (result), AOP (left)))
7077 for (; size--; offset++)
7079 if (AOP_TYPE (right) == AOP_LIT)
7081 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7084 /* dummy read of volatile operand */
7085 if (isOperandVolatile (left, FALSE))
7086 MOVA (aopGet (left, offset, FALSE, FALSE));
7090 else if (bytelit == 0x0FF)
7092 aopPut (result, "#0xFF", offset);
7094 else if (IS_AOP_PREG (left))
7096 MOVA (aopGet (left, offset, FALSE, TRUE));
7097 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7098 aopPut (result, "a", offset);
7102 emitcode ("orl", "%s,%s",
7103 aopGet (left, offset, FALSE, TRUE),
7104 aopGet (right, offset, FALSE, FALSE));
7109 if (AOP_TYPE (left) == AOP_ACC)
7112 emitcode("mov", "a,b");
7113 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7115 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7117 MOVB (aopGet (left, offset, FALSE, FALSE));
7118 MOVA (aopGet (right, offset, FALSE, FALSE));
7119 emitcode ("orl", "a,b");
7120 aopPut (result, "a", offset);
7122 else if (aopGetUsesAcc (left, offset))
7124 MOVA (aopGet (left, offset, FALSE, FALSE));
7125 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7126 aopPut (result, "a", offset);
7130 MOVA (aopGet (right, offset, FALSE, FALSE));
7131 if (IS_AOP_PREG (left))
7133 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7134 aopPut (result, "a", offset);
7138 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7146 // left & result in different registers
7147 if (AOP_TYPE (result) == AOP_CRY)
7150 // if(size), result in bit
7151 // if(!size && ifx), conditional oper: if(left | right)
7152 symbol *tlbl = newiTempLabel (NULL);
7153 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7155 emitcode ("setb", "c");
7158 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7159 && AOP_TYPE(left)==AOP_ACC)
7162 emitcode("mov", "a,b");
7163 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7165 else if (AOP_TYPE(left)==AOP_ACC)
7169 bool pushedB = pushB ();
7170 emitcode("mov", "b,a");
7171 MOVA (aopGet (right, offset, FALSE, FALSE));
7172 emitcode("orl", "a,b");
7177 MOVA (aopGet (right, offset, FALSE, FALSE));
7178 emitcode("orl", "a,b");
7181 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7183 MOVB (aopGet (left, offset, FALSE, FALSE));
7184 MOVA (aopGet (right, offset, FALSE, FALSE));
7185 emitcode ("orl", "a,b");
7187 else if (aopGetUsesAcc (left, offset))
7189 MOVA (aopGet (left, offset, FALSE, FALSE));
7190 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7194 MOVA (aopGet (right, offset, FALSE, FALSE));
7195 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7198 emitcode ("jnz", "%05d$", tlbl->key + 100);
7208 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7214 for (; (size--); offset++)
7217 // result = left | right
7218 if (AOP_TYPE (right) == AOP_LIT)
7220 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7224 aopGet (left, offset, FALSE, FALSE),
7228 else if (bytelit == 0x0FF)
7230 /* dummy read of volatile operand */
7231 if (isOperandVolatile (left, FALSE))
7232 MOVA (aopGet (left, offset, FALSE, FALSE));
7233 aopPut (result, "#0xFF", offset);
7237 // faster than result <- left, orl result,right
7238 // and better if result is SFR
7239 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7240 && AOP_TYPE(left)==AOP_ACC)
7243 emitcode("mov", "a,b");
7244 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7246 else if (AOP_TYPE(left)==AOP_ACC)
7250 bool pushedB = pushB ();
7251 emitcode("mov", "b,a");
7252 MOVA (aopGet (right, offset, FALSE, FALSE));
7253 emitcode("orl", "a,b");
7258 MOVA (aopGet (right, offset, FALSE, FALSE));
7259 emitcode("orl", "a,b");
7262 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7264 MOVB (aopGet (left, offset, FALSE, FALSE));
7265 MOVA (aopGet (right, offset, FALSE, FALSE));
7266 emitcode ("orl", "a,b");
7268 else if (aopGetUsesAcc (left, offset))
7270 MOVA (aopGet (left, offset, FALSE, FALSE));
7271 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7275 MOVA (aopGet (right, offset, FALSE, FALSE));
7276 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7278 aopPut (result, "a", offset);
7284 freeAsmop (result, NULL, ic, TRUE);
7285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7286 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7289 /*-----------------------------------------------------------------*/
7290 /* genXor - code for xclusive or */
7291 /*-----------------------------------------------------------------*/
7293 genXor (iCode * ic, iCode * ifx)
7295 operand *left, *right, *result;
7296 int size, offset = 0;
7297 unsigned long lit = 0L;
7300 D (emitcode (";", "genXor"));
7302 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7303 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7304 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7307 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7309 AOP_TYPE (left), AOP_TYPE (right));
7310 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7312 AOP_SIZE (left), AOP_SIZE (right));
7315 /* if left is a literal & right is not ||
7316 if left needs acc & right does not */
7317 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7318 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7320 operand *tmp = right;
7325 /* if result = right then exchange them */
7326 if (sameRegs (AOP (result), AOP (right)))
7328 operand *tmp = right;
7333 /* if right is bit then exchange them */
7334 if (AOP_TYPE (right) == AOP_CRY &&
7335 AOP_TYPE (left) != AOP_CRY)
7337 operand *tmp = right;
7341 if (AOP_TYPE (right) == AOP_LIT)
7342 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7344 size = AOP_SIZE (result);
7348 if (AOP_TYPE (left) == AOP_CRY)
7350 if (AOP_TYPE (right) == AOP_LIT)
7352 // c = bit & literal;
7355 // lit>>1 != 0 => result = 1
7356 if (AOP_TYPE (result) == AOP_CRY)
7359 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7361 continueIfTrue (ifx);
7364 emitcode ("setb", "c");
7371 // lit == 0, result = left
7372 if (size && sameRegs (AOP (result), AOP (left)))
7374 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7378 // lit == 1, result = not(left)
7379 if (size && sameRegs (AOP (result), AOP (left)))
7381 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7386 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7387 emitcode ("cpl", "c");
7395 symbol *tlbl = newiTempLabel (NULL);
7396 if (AOP_TYPE (right) == AOP_CRY)
7399 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7403 int sizer = AOP_SIZE (right);
7405 // if val>>1 != 0, result = 1
7406 emitcode ("setb", "c");
7409 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7411 // test the msb of the lsb
7412 emitcode ("anl", "a,#0xfe");
7413 emitcode ("jnz", "%05d$", tlbl->key + 100);
7417 emitcode ("rrc", "a");
7419 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7420 emitcode ("cpl", "c");
7428 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7429 genIfxJump (ifx, "c", left, right, result);
7433 /* if left is same as result */
7434 if (sameRegs (AOP (result), AOP (left)))
7436 for (; size--; offset++)
7438 if (AOP_TYPE (right) == AOP_LIT)
7440 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7443 /* dummy read of volatile operand */
7444 if (isOperandVolatile (left, FALSE))
7445 MOVA (aopGet (left, offset, FALSE, FALSE));
7449 else if (IS_AOP_PREG (left))
7451 MOVA (aopGet (left, offset, FALSE, TRUE));
7452 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7453 aopPut (result, "a", offset);
7457 emitcode ("xrl", "%s,%s",
7458 aopGet (left, offset, FALSE, TRUE),
7459 aopGet (right, offset, FALSE, FALSE));
7464 if (AOP_TYPE (left) == AOP_ACC)
7467 emitcode("mov", "a,b");
7468 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7470 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7472 MOVB (aopGet (left, offset, FALSE, FALSE));
7473 MOVA (aopGet (right, offset, FALSE, FALSE));
7474 emitcode ("xrl", "a,b");
7475 aopPut (result, "a", offset);
7477 else if (aopGetUsesAcc (left, offset))
7479 MOVA (aopGet (left, offset, FALSE, FALSE));
7480 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7481 aopPut (result, "a", offset);
7485 MOVA (aopGet (right, offset, FALSE, FALSE));
7486 if (IS_AOP_PREG (left))
7488 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7489 aopPut (result, "a", offset);
7492 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7499 // left & result in different registers
7500 if (AOP_TYPE (result) == AOP_CRY)
7503 // if(size), result in bit
7504 // if(!size && ifx), conditional oper: if(left ^ right)
7505 symbol *tlbl = newiTempLabel (NULL);
7506 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7509 emitcode ("setb", "c");
7512 if ((AOP_TYPE (right) == AOP_LIT) &&
7513 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7515 MOVA (aopGet (left, offset, FALSE, FALSE));
7517 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7518 && AOP_TYPE(left)==AOP_ACC)
7521 emitcode("mov", "a,b");
7522 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7524 else if (AOP_TYPE(left)==AOP_ACC)
7528 bool pushedB = pushB ();
7529 emitcode("mov", "b,a");
7530 MOVA (aopGet (right, offset, FALSE, FALSE));
7531 emitcode("xrl", "a,b");
7536 MOVA (aopGet (right, offset, FALSE, FALSE));
7537 emitcode("xrl", "a,b");
7540 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7542 MOVB (aopGet (left, offset, FALSE, FALSE));
7543 MOVA (aopGet (right, offset, FALSE, FALSE));
7544 emitcode ("xrl", "a,b");
7546 else if (aopGetUsesAcc (left, offset))
7548 MOVA (aopGet (left, offset, FALSE, FALSE));
7549 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7553 MOVA (aopGet (right, offset, FALSE, FALSE));
7554 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7557 emitcode ("jnz", "%05d$", tlbl->key + 100);
7567 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7571 for (; (size--); offset++)
7574 // result = left ^ right
7575 if (AOP_TYPE (right) == AOP_LIT)
7577 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7581 aopGet (left, offset, FALSE, FALSE),
7586 // faster than result <- left, xrl result,right
7587 // and better if result is SFR
7588 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7589 && AOP_TYPE(left)==AOP_ACC)
7592 emitcode("mov", "a,b");
7593 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7595 else if (AOP_TYPE(left)==AOP_ACC)
7599 bool pushedB = pushB ();
7600 emitcode("mov", "b,a");
7601 MOVA (aopGet (right, offset, FALSE, FALSE));
7602 emitcode("xrl", "a,b");
7607 MOVA (aopGet (right, offset, FALSE, FALSE));
7608 emitcode("xrl", "a,b");
7611 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7613 MOVB (aopGet (left, offset, FALSE, FALSE));
7614 MOVA (aopGet (right, offset, FALSE, FALSE));
7615 emitcode ("xrl", "a,b");
7617 else if (aopGetUsesAcc (left, offset))
7619 MOVA (aopGet (left, offset, FALSE, FALSE));
7620 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7624 MOVA (aopGet (right, offset, FALSE, FALSE));
7625 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7627 aopPut (result, "a", offset);
7633 freeAsmop (result, NULL, ic, TRUE);
7634 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7635 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7638 /*-----------------------------------------------------------------*/
7639 /* genInline - write the inline code out */
7640 /*-----------------------------------------------------------------*/
7642 genInline (iCode * ic)
7644 char *buffer, *bp, *bp1;
7646 D (emitcode (";", "genInline"));
7648 _G.inLine += (!options.asmpeep);
7650 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7652 /* emit each line as a code */
7663 /* Add \n for labels, not dirs such as c:\mydir */
7664 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7678 /* emitcode("",buffer); */
7679 _G.inLine -= (!options.asmpeep);
7682 /*-----------------------------------------------------------------*/
7683 /* genRRC - rotate right with carry */
7684 /*-----------------------------------------------------------------*/
7688 operand *left, *result;
7692 D (emitcode (";", "genRRC"));
7694 /* rotate right with carry */
7695 left = IC_LEFT (ic);
7696 result = IC_RESULT (ic);
7697 aopOp (left, ic, FALSE);
7698 aopOp (result, ic, FALSE);
7700 /* move it to the result */
7701 size = AOP_SIZE (result);
7703 if (size == 1) { /* special case for 1 byte */
7704 l = aopGet (left, offset, FALSE, FALSE);
7706 emitcode ("rr", "a");
7709 /* no need to clear carry, bit7 will be written later */
7712 l = aopGet (left, offset, FALSE, FALSE);
7714 emitcode ("rrc", "a");
7715 if (AOP_SIZE (result) > 1)
7716 aopPut (result, "a", offset--);
7718 /* now we need to put the carry into the
7719 highest order byte of the result */
7720 if (AOP_SIZE (result) > 1)
7722 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7725 emitcode ("mov", "acc.7,c");
7727 aopPut (result, "a", AOP_SIZE (result) - 1);
7728 freeAsmop (result, NULL, ic, TRUE);
7729 freeAsmop (left, NULL, ic, TRUE);
7732 /*-----------------------------------------------------------------*/
7733 /* genRLC - generate code for rotate left with carry */
7734 /*-----------------------------------------------------------------*/
7738 operand *left, *result;
7742 D (emitcode (";", "genRLC"));
7744 /* rotate right with carry */
7745 left = IC_LEFT (ic);
7746 result = IC_RESULT (ic);
7747 aopOp (left, ic, FALSE);
7748 aopOp (result, ic, FALSE);
7750 /* move it to the result */
7751 size = AOP_SIZE (result);
7755 l = aopGet (left, offset, FALSE, FALSE);
7757 if (size == 0) { /* special case for 1 byte */
7761 emitcode("rlc","a"); /* bit0 will be written later */
7762 if (AOP_SIZE (result) > 1)
7764 aopPut (result, "a", offset++);
7769 l = aopGet (left, offset, FALSE, FALSE);
7771 emitcode ("rlc", "a");
7772 if (AOP_SIZE (result) > 1)
7773 aopPut (result, "a", offset++);
7776 /* now we need to put the carry into the
7777 highest order byte of the result */
7778 if (AOP_SIZE (result) > 1)
7780 l = aopGet (result, 0, FALSE, FALSE);
7783 emitcode ("mov", "acc.0,c");
7785 aopPut (result, "a", 0);
7786 freeAsmop (result, NULL, ic, TRUE);
7787 freeAsmop (left, NULL, ic, TRUE);
7790 /*-----------------------------------------------------------------*/
7791 /* genGetHbit - generates code get highest order bit */
7792 /*-----------------------------------------------------------------*/
7794 genGetHbit (iCode * ic)
7796 operand *left, *result;
7798 D (emitcode (";", "genGetHbit"));
7800 left = IC_LEFT (ic);
7801 result = IC_RESULT (ic);
7802 aopOp (left, ic, FALSE);
7803 aopOp (result, ic, FALSE);
7805 /* get the highest order byte into a */
7806 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7807 if (AOP_TYPE (result) == AOP_CRY)
7809 emitcode ("rlc", "a");
7814 emitcode ("rl", "a");
7815 emitcode ("anl", "a,#0x01");
7819 freeAsmop (result, NULL, ic, TRUE);
7820 freeAsmop (left, NULL, ic, TRUE);
7823 /*-----------------------------------------------------------------*/
7824 /* genGetAbit - generates code get a single bit */
7825 /*-----------------------------------------------------------------*/
7827 genGetAbit (iCode * ic)
7829 operand *left, *right, *result;
7832 D (emitcode (";", "genGetAbit"));
7834 left = IC_LEFT (ic);
7835 right = IC_RIGHT (ic);
7836 result = IC_RESULT (ic);
7837 aopOp (left, ic, FALSE);
7838 aopOp (right, ic, FALSE);
7839 aopOp (result, ic, FALSE);
7841 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7843 /* get the needed byte into a */
7844 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7846 if (AOP_TYPE (result) == AOP_CRY)
7849 emitcode ("rlc", "a");
7850 else if ((shCount) == 0)
7851 emitcode ("rrc", "a");
7853 emitcode ("mov", "c,acc[%d]", shCount);
7861 emitcode ("rr", "a");
7864 emitcode ("rr", "a");
7867 emitcode ("anl", "a,#0x01");
7871 emitcode ("mov", "c,acc[%d]", shCount);
7872 emitcode ("clr", "a");
7873 emitcode ("rlc", "a");
7876 emitcode ("swap", "a");
7877 emitcode ("anl", "a,#0x01");
7880 emitcode ("rl", "a");
7883 emitcode ("rl", "a");
7884 emitcode ("anl", "a,#0x01");
7890 freeAsmop (result, NULL, ic, TRUE);
7891 freeAsmop (right, NULL, ic, TRUE);
7892 freeAsmop (left, NULL, ic, TRUE);
7895 /*-----------------------------------------------------------------*/
7896 /* genGetByte - generates code get a single byte */
7897 /*-----------------------------------------------------------------*/
7899 genGetByte (iCode * ic)
7901 operand *left, *right, *result;
7904 D (emitcode (";", "genGetByte"));
7906 left = IC_LEFT (ic);
7907 right = IC_RIGHT (ic);
7908 result = IC_RESULT (ic);
7909 aopOp (left, ic, FALSE);
7910 aopOp (right, ic, FALSE);
7911 aopOp (result, ic, FALSE);
7913 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7915 aopGet (left, offset, FALSE, FALSE),
7918 freeAsmop (result, NULL, ic, TRUE);
7919 freeAsmop (right, NULL, ic, TRUE);
7920 freeAsmop (left, NULL, ic, TRUE);
7923 /*-----------------------------------------------------------------*/
7924 /* genGetWord - generates code get two bytes */
7925 /*-----------------------------------------------------------------*/
7927 genGetWord (iCode * ic)
7929 operand *left, *right, *result;
7932 D (emitcode (";", "genGetWord"));
7934 left = IC_LEFT (ic);
7935 right = IC_RIGHT (ic);
7936 result = IC_RESULT (ic);
7937 aopOp (left, ic, FALSE);
7938 aopOp (right, ic, FALSE);
7939 aopOp (result, ic, FALSE);
7941 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7943 aopGet (left, offset, FALSE, FALSE),
7946 aopGet (left, offset+1, FALSE, FALSE),
7949 freeAsmop (result, NULL, ic, TRUE);
7950 freeAsmop (right, NULL, ic, TRUE);
7951 freeAsmop (left, NULL, ic, TRUE);
7954 /*-----------------------------------------------------------------*/
7955 /* genSwap - generates code to swap nibbles or bytes */
7956 /*-----------------------------------------------------------------*/
7958 genSwap (iCode * ic)
7960 operand *left, *result;
7962 D(emitcode ("; genSwap",""));
7964 left = IC_LEFT (ic);
7965 result = IC_RESULT (ic);
7966 aopOp (left, ic, FALSE);
7967 aopOp (result, ic, FALSE);
7969 switch (AOP_SIZE (left))
7971 case 1: /* swap nibbles in byte */
7972 MOVA (aopGet (left, 0, FALSE, FALSE));
7973 emitcode ("swap", "a");
7974 aopPut (result, "a", 0);
7976 case 2: /* swap bytes in word */
7977 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7979 MOVA (aopGet (left, 0, FALSE, FALSE));
7980 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7981 aopPut (result, "a", 1);
7983 else if (operandsEqu (left, result))
7986 bool pushedB = FALSE, leftInB = FALSE;
7988 MOVA (aopGet (left, 0, FALSE, FALSE));
7989 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7992 emitcode ("mov", "b,a");
7996 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7997 aopPut (result, reg, 1);
8004 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8005 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8009 wassertl(FALSE, "unsupported SWAP operand size");
8012 freeAsmop (result, NULL, ic, TRUE);
8013 freeAsmop (left, NULL, ic, TRUE);
8016 /*-----------------------------------------------------------------*/
8017 /* AccRol - rotate left accumulator by known count */
8018 /*-----------------------------------------------------------------*/
8020 AccRol (int shCount)
8022 shCount &= 0x0007; // shCount : 0..7
8029 emitcode ("rl", "a");
8032 emitcode ("rl", "a");
8033 emitcode ("rl", "a");
8036 emitcode ("swap", "a");
8037 emitcode ("rr", "a");
8040 emitcode ("swap", "a");
8043 emitcode ("swap", "a");
8044 emitcode ("rl", "a");
8047 emitcode ("rr", "a");
8048 emitcode ("rr", "a");
8051 emitcode ("rr", "a");
8056 /*-----------------------------------------------------------------*/
8057 /* AccLsh - left shift accumulator by known count */
8058 /*-----------------------------------------------------------------*/
8060 AccLsh (int shCount)
8065 emitcode ("add", "a,acc");
8066 else if (shCount == 2)
8068 emitcode ("add", "a,acc");
8069 emitcode ("add", "a,acc");
8073 /* rotate left accumulator */
8075 /* and kill the lower order bits */
8076 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8081 /*-----------------------------------------------------------------*/
8082 /* AccRsh - right shift accumulator by known count */
8083 /*-----------------------------------------------------------------*/
8085 AccRsh (int shCount)
8092 emitcode ("rrc", "a");
8096 /* rotate right accumulator */
8097 AccRol (8 - shCount);
8098 /* and kill the higher order bits */
8099 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8104 /*-----------------------------------------------------------------*/
8105 /* AccSRsh - signed right shift accumulator by known count */
8106 /*-----------------------------------------------------------------*/
8108 AccSRsh (int shCount)
8115 emitcode ("mov", "c,acc.7");
8116 emitcode ("rrc", "a");
8118 else if (shCount == 2)
8120 emitcode ("mov", "c,acc.7");
8121 emitcode ("rrc", "a");
8122 emitcode ("mov", "c,acc.7");
8123 emitcode ("rrc", "a");
8127 tlbl = newiTempLabel (NULL);
8128 /* rotate right accumulator */
8129 AccRol (8 - shCount);
8130 /* and kill the higher order bits */
8131 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8132 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8133 emitcode ("orl", "a,#0x%02x",
8134 (unsigned char) ~SRMask[shCount]);
8140 /*-----------------------------------------------------------------*/
8141 /* shiftR1Left2Result - shift right one byte from left to result */
8142 /*-----------------------------------------------------------------*/
8144 shiftR1Left2Result (operand * left, int offl,
8145 operand * result, int offr,
8146 int shCount, int sign)
8148 MOVA (aopGet (left, offl, FALSE, FALSE));
8149 /* shift right accumulator */
8154 aopPut (result, "a", offr);
8157 /*-----------------------------------------------------------------*/
8158 /* shiftL1Left2Result - shift left one byte from left to result */
8159 /*-----------------------------------------------------------------*/
8161 shiftL1Left2Result (operand * left, int offl,
8162 operand * result, int offr, int shCount)
8165 l = aopGet (left, offl, FALSE, FALSE);
8167 /* shift left accumulator */
8169 aopPut (result, "a", offr);
8172 /*-----------------------------------------------------------------*/
8173 /* movLeft2Result - move byte from left to result */
8174 /*-----------------------------------------------------------------*/
8176 movLeft2Result (operand * left, int offl,
8177 operand * result, int offr, int sign)
8180 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8182 l = aopGet (left, offl, FALSE, FALSE);
8184 if (*l == '@' && (IS_AOP_PREG (result)))
8186 emitcode ("mov", "a,%s", l);
8187 aopPut (result, "a", offr);
8193 aopPut (result, l, offr);
8197 /* MSB sign in acc.7 ! */
8198 if (getDataSize (left) == offl + 1)
8201 aopPut (result, "a", offr);
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8210 /*-----------------------------------------------------------------*/
8214 emitcode ("rrc", "a");
8215 emitcode ("xch", "a,%s", x);
8216 emitcode ("rrc", "a");
8217 emitcode ("xch", "a,%s", x);
8220 /*-----------------------------------------------------------------*/
8221 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8222 /*-----------------------------------------------------------------*/
8226 emitcode ("xch", "a,%s", x);
8227 emitcode ("rlc", "a");
8228 emitcode ("xch", "a,%s", x);
8229 emitcode ("rlc", "a");
8232 /*-----------------------------------------------------------------*/
8233 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8234 /*-----------------------------------------------------------------*/
8238 emitcode ("xch", "a,%s", x);
8239 emitcode ("add", "a,acc");
8240 emitcode ("xch", "a,%s", x);
8241 emitcode ("rlc", "a");
8244 /*-----------------------------------------------------------------*/
8245 /* AccAXLsh - left shift a:x by known count (0..7) */
8246 /*-----------------------------------------------------------------*/
8248 AccAXLsh (char *x, int shCount)
8263 case 5: // AAAAABBB:CCCCCDDD
8265 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8267 emitcode ("anl", "a,#0x%02x",
8268 SLMask[shCount]); // BBB00000:CCCCCDDD
8270 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8272 AccRol (shCount); // DDDCCCCC:BBB00000
8274 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8276 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8278 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8280 emitcode ("anl", "a,#0x%02x",
8281 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8283 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8285 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8288 case 6: // AAAAAABB:CCCCCCDD
8289 emitcode ("anl", "a,#0x%02x",
8290 SRMask[shCount]); // 000000BB:CCCCCCDD
8291 emitcode ("mov", "c,acc.0"); // c = B
8292 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8294 AccAXRrl1 (x); // BCCCCCCD:D000000B
8295 AccAXRrl1 (x); // BBCCCCCC:DD000000
8297 emitcode("rrc","a");
8298 emitcode("xch","a,%s", x);
8299 emitcode("rrc","a");
8300 emitcode("mov","c,acc.0"); //<< get correct bit
8301 emitcode("xch","a,%s", x);
8303 emitcode("rrc","a");
8304 emitcode("xch","a,%s", x);
8305 emitcode("rrc","a");
8306 emitcode("xch","a,%s", x);
8309 case 7: // a:x <<= 7
8311 emitcode ("anl", "a,#0x%02x",
8312 SRMask[shCount]); // 0000000B:CCCCCCCD
8314 emitcode ("mov", "c,acc.0"); // c = B
8316 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8318 AccAXRrl1 (x); // BCCCCCCC:D0000000
8326 /*-----------------------------------------------------------------*/
8327 /* AccAXRsh - right shift a:x known count (0..7) */
8328 /*-----------------------------------------------------------------*/
8330 AccAXRsh (char *x, int shCount)
8338 AccAXRrl1 (x); // 0->a:x
8343 AccAXRrl1 (x); // 0->a:x
8346 AccAXRrl1 (x); // 0->a:x
8351 case 5: // AAAAABBB:CCCCCDDD = a:x
8353 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8355 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8357 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8359 emitcode ("anl", "a,#0x%02x",
8360 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8362 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8364 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8366 emitcode ("anl", "a,#0x%02x",
8367 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8369 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8371 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8373 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8376 case 6: // AABBBBBB:CCDDDDDD
8378 emitcode ("mov", "c,acc.7");
8379 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8381 emitcode ("mov", "c,acc.7");
8382 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8384 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8386 emitcode ("anl", "a,#0x%02x",
8387 SRMask[shCount]); // 000000AA:BBBBBBCC
8390 case 7: // ABBBBBBB:CDDDDDDD
8392 emitcode ("mov", "c,acc.7"); // c = A
8394 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8396 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8398 emitcode ("anl", "a,#0x%02x",
8399 SRMask[shCount]); // 0000000A:BBBBBBBC
8407 /*-----------------------------------------------------------------*/
8408 /* AccAXRshS - right shift signed a:x known count (0..7) */
8409 /*-----------------------------------------------------------------*/
8411 AccAXRshS (char *x, int shCount)
8419 emitcode ("mov", "c,acc.7");
8420 AccAXRrl1 (x); // s->a:x
8424 emitcode ("mov", "c,acc.7");
8425 AccAXRrl1 (x); // s->a:x
8427 emitcode ("mov", "c,acc.7");
8428 AccAXRrl1 (x); // s->a:x
8433 case 5: // AAAAABBB:CCCCCDDD = a:x
8435 tlbl = newiTempLabel (NULL);
8436 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8438 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8440 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8442 emitcode ("anl", "a,#0x%02x",
8443 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8445 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8447 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8449 emitcode ("anl", "a,#0x%02x",
8450 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8452 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8454 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8456 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8458 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8459 emitcode ("orl", "a,#0x%02x",
8460 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8463 break; // SSSSAAAA:BBBCCCCC
8465 case 6: // AABBBBBB:CCDDDDDD
8467 tlbl = newiTempLabel (NULL);
8468 emitcode ("mov", "c,acc.7");
8469 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8471 emitcode ("mov", "c,acc.7");
8472 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8474 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8476 emitcode ("anl", "a,#0x%02x",
8477 SRMask[shCount]); // 000000AA:BBBBBBCC
8479 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8480 emitcode ("orl", "a,#0x%02x",
8481 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8485 case 7: // ABBBBBBB:CDDDDDDD
8487 tlbl = newiTempLabel (NULL);
8488 emitcode ("mov", "c,acc.7"); // c = A
8490 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8492 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8494 emitcode ("anl", "a,#0x%02x",
8495 SRMask[shCount]); // 0000000A:BBBBBBBC
8497 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8498 emitcode ("orl", "a,#0x%02x",
8499 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8508 /*-----------------------------------------------------------------*/
8509 /* shiftL2Left2Result - shift left two bytes from left to result */
8510 /*-----------------------------------------------------------------*/
8512 shiftL2Left2Result (operand * left, int offl,
8513 operand * result, int offr, int shCount)
8516 bool pushedB = FALSE;
8519 if (sameRegs (AOP (result), AOP (left)) &&
8520 ((offl + MSB16) == offr))
8522 /* don't crash result[offr] */
8523 MOVA (aopGet (left, offl, FALSE, FALSE));
8524 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8525 usedB = !strncmp(x, "b", 1);
8527 else if (aopGetUsesAcc (result, offr))
8529 movLeft2Result (left, offl, result, offr, 0);
8532 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8533 MOVA (aopGet (result, offr, FALSE, FALSE));
8534 emitcode ("xch", "a,b");
8539 movLeft2Result (left, offl, result, offr, 0);
8540 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8541 x = aopGet (result, offr, FALSE, FALSE);
8543 /* ax << shCount (x = lsb(result)) */
8544 AccAXLsh (x, shCount);
8547 emitcode ("xch", "a,b");
8548 aopPut (result, "a", offr);
8549 aopPut (result, "b", offr + MSB16);
8554 aopPut (result, "a", offr + MSB16);
8559 /*-----------------------------------------------------------------*/
8560 /* shiftR2Left2Result - shift right two bytes from left to result */
8561 /*-----------------------------------------------------------------*/
8563 shiftR2Left2Result (operand * left, int offl,
8564 operand * result, int offr,
8565 int shCount, int sign)
8568 bool pushedB = FALSE;
8571 if (sameRegs (AOP (result), AOP (left)) &&
8572 ((offl + MSB16) == offr))
8574 /* don't crash result[offr] */
8575 MOVA (aopGet (left, offl, FALSE, FALSE));
8576 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8577 usedB = !strncmp(x, "b", 1);
8579 else if (aopGetUsesAcc (result, offr))
8581 movLeft2Result (left, offl, result, offr, 0);
8584 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8585 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8590 movLeft2Result (left, offl, result, offr, 0);
8591 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8592 x = aopGet (result, offr, FALSE, FALSE);
8594 /* a:x >> shCount (x = lsb(result)) */
8596 AccAXRshS (x, shCount);
8598 AccAXRsh (x, shCount);
8601 emitcode ("xch", "a,b");
8602 aopPut (result, "a", offr);
8603 emitcode ("xch", "a,b");
8606 if (getDataSize (result) > 1)
8607 aopPut (result, "a", offr + MSB16);
8610 /*-----------------------------------------------------------------*/
8611 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8612 /*-----------------------------------------------------------------*/
8614 shiftLLeftOrResult (operand * left, int offl,
8615 operand * result, int offr, int shCount)
8617 MOVA (aopGet (left, offl, FALSE, FALSE));
8618 /* shift left accumulator */
8620 /* or with result */
8621 if (aopGetUsesAcc (result, offr))
8623 emitcode ("xch", "a,b");
8624 MOVA (aopGet (result, offr, FALSE, FALSE));
8625 emitcode ("orl", "a,b");
8629 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8631 /* back to result */
8632 aopPut (result, "a", offr);
8635 /*-----------------------------------------------------------------*/
8636 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8637 /*-----------------------------------------------------------------*/
8639 shiftRLeftOrResult (operand * left, int offl,
8640 operand * result, int offr, int shCount)
8642 MOVA (aopGet (left, offl, FALSE, FALSE));
8643 /* shift right accumulator */
8645 /* or with result */
8646 if (aopGetUsesAcc(result, offr))
8648 emitcode ("xch", "a,b");
8649 MOVA (aopGet (result, offr, FALSE, FALSE));
8650 emitcode ("orl", "a,b");
8654 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8656 /* back to result */
8657 aopPut (result, "a", offr);
8660 /*-----------------------------------------------------------------*/
8661 /* genlshOne - left shift a one byte quantity by known count */
8662 /*-----------------------------------------------------------------*/
8664 genlshOne (operand * result, operand * left, int shCount)
8666 D (emitcode (";", "genlshOne"));
8668 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8671 /*-----------------------------------------------------------------*/
8672 /* genlshTwo - left shift two bytes by known amount != 0 */
8673 /*-----------------------------------------------------------------*/
8675 genlshTwo (operand * result, operand * left, int shCount)
8679 D (emitcode (";", "genlshTwo"));
8681 size = getDataSize (result);
8683 /* if shCount >= 8 */
8691 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8693 movLeft2Result (left, LSB, result, MSB16, 0);
8695 aopPut (result, zero, LSB);
8698 /* 1 <= shCount <= 7 */
8702 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8704 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8708 /*-----------------------------------------------------------------*/
8709 /* shiftLLong - shift left one long from left to result */
8710 /* offl = LSB or MSB16 */
8711 /*-----------------------------------------------------------------*/
8713 shiftLLong (operand * left, operand * result, int offr)
8716 int size = AOP_SIZE (result);
8718 if (size >= LSB + offr)
8720 l = aopGet (left, LSB, FALSE, FALSE);
8722 emitcode ("add", "a,acc");
8723 if (sameRegs (AOP (left), AOP (result)) &&
8724 size >= MSB16 + offr && offr != LSB)
8725 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8727 aopPut (result, "a", LSB + offr);
8730 if (size >= MSB16 + offr)
8732 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8734 l = aopGet (left, MSB16, FALSE, FALSE);
8737 emitcode ("rlc", "a");
8738 if (sameRegs (AOP (left), AOP (result)) &&
8739 size >= MSB24 + offr && offr != LSB)
8740 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8742 aopPut (result, "a", MSB16 + offr);
8745 if (size >= MSB24 + offr)
8747 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8749 l = aopGet (left, MSB24, FALSE, FALSE);
8752 emitcode ("rlc", "a");
8753 if (sameRegs (AOP (left), AOP (result)) &&
8754 size >= MSB32 + offr && offr != LSB)
8755 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8757 aopPut (result, "a", MSB24 + offr);
8760 if (size > MSB32 + offr)
8762 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8764 l = aopGet (left, MSB32, FALSE, FALSE);
8767 emitcode ("rlc", "a");
8768 aopPut (result, "a", MSB32 + offr);
8771 aopPut (result, zero, LSB);
8774 /*-----------------------------------------------------------------*/
8775 /* genlshFour - shift four byte by a known amount != 0 */
8776 /*-----------------------------------------------------------------*/
8778 genlshFour (operand * result, operand * left, int shCount)
8782 D (emitcode (";", "genlshFour"));
8784 size = AOP_SIZE (result);
8786 /* if shifting more that 3 bytes */
8791 /* lowest order of left goes to the highest
8792 order of the destination */
8793 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8795 movLeft2Result (left, LSB, result, MSB32, 0);
8796 aopPut (result, zero, LSB);
8797 aopPut (result, zero, MSB16);
8798 aopPut (result, zero, MSB24);
8802 /* more than two bytes */
8803 else if (shCount >= 16)
8805 /* lower order two bytes goes to higher order two bytes */
8807 /* if some more remaining */
8809 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8812 movLeft2Result (left, MSB16, result, MSB32, 0);
8813 movLeft2Result (left, LSB, result, MSB24, 0);
8815 aopPut (result, zero, MSB16);
8816 aopPut (result, zero, LSB);
8820 /* if more than 1 byte */
8821 else if (shCount >= 8)
8823 /* lower order three bytes goes to higher order three bytes */
8828 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8830 movLeft2Result (left, LSB, result, MSB16, 0);
8836 movLeft2Result (left, MSB24, result, MSB32, 0);
8837 movLeft2Result (left, MSB16, result, MSB24, 0);
8838 movLeft2Result (left, LSB, result, MSB16, 0);
8839 aopPut (result, zero, LSB);
8841 else if (shCount == 1)
8842 shiftLLong (left, result, MSB16);
8845 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8846 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8847 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8848 aopPut (result, zero, LSB);
8853 /* 1 <= shCount <= 7 */
8854 else if (shCount <= 2)
8856 shiftLLong (left, result, LSB);
8858 shiftLLong (result, result, LSB);
8860 /* 3 <= shCount <= 7, optimize */
8863 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8864 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8865 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8869 /*-----------------------------------------------------------------*/
8870 /* genLeftShiftLiteral - left shifting by known count */
8871 /*-----------------------------------------------------------------*/
8873 genLeftShiftLiteral (operand * left,
8878 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8881 D (emitcode (";", "genLeftShiftLiteral"));
8883 freeAsmop (right, NULL, ic, TRUE);
8885 aopOp (left, ic, FALSE);
8886 aopOp (result, ic, FALSE);
8888 size = getSize (operandType (result));
8891 emitcode ("; shift left ", "result %d, left %d", size,
8895 /* I suppose that the left size >= result size */
8900 movLeft2Result (left, size, result, size, 0);
8903 else if (shCount >= (size * 8))
8907 aopPut (result, zero, size);
8915 genlshOne (result, left, shCount);
8919 genlshTwo (result, left, shCount);
8923 genlshFour (result, left, shCount);
8926 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8927 "*** ack! mystery literal shift!\n");
8931 freeAsmop (result, NULL, ic, TRUE);
8932 freeAsmop (left, NULL, ic, TRUE);
8935 /*-----------------------------------------------------------------*/
8936 /* genLeftShift - generates code for left shifting */
8937 /*-----------------------------------------------------------------*/
8939 genLeftShift (iCode * ic)
8941 operand *left, *right, *result;
8944 symbol *tlbl, *tlbl1;
8947 D (emitcode (";", "genLeftShift"));
8949 right = IC_RIGHT (ic);
8950 left = IC_LEFT (ic);
8951 result = IC_RESULT (ic);
8953 aopOp (right, ic, FALSE);
8955 /* if the shift count is known then do it
8956 as efficiently as possible */
8957 if (AOP_TYPE (right) == AOP_LIT)
8959 genLeftShiftLiteral (left, right, result, ic);
8963 /* shift count is unknown then we have to form
8964 a loop get the loop count in B : Note: we take
8965 only the lower order byte since shifting
8966 more that 32 bits make no sense anyway, ( the
8967 largest size of an object can be only 32 bits ) */
8970 MOVB (aopGet (right, 0, FALSE, FALSE));
8971 emitcode ("inc", "b");
8972 freeAsmop (right, NULL, ic, TRUE);
8973 aopOp (left, ic, FALSE);
8974 aopOp (result, ic, FALSE);
8976 /* now move the left to the result if they are not the same */
8977 if (!sameRegs (AOP (left), AOP (result)) &&
8978 AOP_SIZE (result) > 1)
8981 size = AOP_SIZE (result);
8985 l = aopGet (left, offset, FALSE, TRUE);
8986 if (*l == '@' && (IS_AOP_PREG (result)))
8989 emitcode ("mov", "a,%s", l);
8990 aopPut (result, "a", offset);
8993 aopPut (result, l, offset);
8998 tlbl = newiTempLabel (NULL);
8999 size = AOP_SIZE (result);
9001 tlbl1 = newiTempLabel (NULL);
9003 /* if it is only one byte then */
9006 symbol *tlbl1 = newiTempLabel (NULL);
9008 l = aopGet (left, 0, FALSE, FALSE);
9010 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9012 emitcode ("add", "a,acc");
9014 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9016 aopPut (result, "a", 0);
9020 reAdjustPreg (AOP (result));
9022 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9024 l = aopGet (result, offset, FALSE, FALSE);
9026 emitcode ("add", "a,acc");
9027 aopPut (result, "a", offset++);
9030 l = aopGet (result, offset, FALSE, FALSE);
9032 emitcode ("rlc", "a");
9033 aopPut (result, "a", offset++);
9035 reAdjustPreg (AOP (result));
9038 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9041 freeAsmop (result, NULL, ic, TRUE);
9042 freeAsmop (left, NULL, ic, TRUE);
9045 /*-----------------------------------------------------------------*/
9046 /* genrshOne - right shift a one byte quantity by known count */
9047 /*-----------------------------------------------------------------*/
9049 genrshOne (operand * result, operand * left,
9050 int shCount, int sign)
9052 D (emitcode (";", "genrshOne"));
9054 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9057 /*-----------------------------------------------------------------*/
9058 /* genrshTwo - right shift two bytes by known amount != 0 */
9059 /*-----------------------------------------------------------------*/
9061 genrshTwo (operand * result, operand * left,
9062 int shCount, int sign)
9064 D (emitcode (";", "genrshTwo"));
9066 /* if shCount >= 8 */
9071 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9073 movLeft2Result (left, MSB16, result, LSB, sign);
9074 addSign (result, MSB16, sign);
9077 /* 1 <= shCount <= 7 */
9079 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9082 /*-----------------------------------------------------------------*/
9083 /* shiftRLong - shift right one long from left to result */
9084 /* offl = LSB or MSB16 */
9085 /*-----------------------------------------------------------------*/
9087 shiftRLong (operand * left, int offl,
9088 operand * result, int sign)
9090 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9092 if (overlapping && offl>1)
9094 // we are in big trouble, but this shouldn't happen
9095 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9098 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9105 emitcode ("rlc", "a");
9106 emitcode ("subb", "a,acc");
9107 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9109 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9113 aopPut (result, "a", MSB32);
9114 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9119 if (aopPutUsesAcc (result, zero, MSB32))
9121 emitcode("xch", "a,b");
9122 aopPut (result, zero, MSB32);
9123 emitcode("xch", "a,b");
9127 aopPut (result, zero, MSB32);
9134 emitcode ("clr", "c");
9138 emitcode ("mov", "c,acc.7");
9141 emitcode ("rrc", "a");
9143 if (overlapping && offl==MSB16 &&
9144 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9146 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9150 aopPut (result, "a", MSB32 - offl);
9151 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9154 emitcode ("rrc", "a");
9155 if (overlapping && offl==MSB16 &&
9156 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9158 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9162 aopPut (result, "a", MSB24 - offl);
9163 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9166 emitcode ("rrc", "a");
9169 aopPut (result, "a", MSB16 - offl);
9174 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9176 xch_a_aopGet (left, LSB, FALSE, FALSE);
9180 aopPut (result, "a", MSB16 - offl);
9181 MOVA (aopGet (left, LSB, FALSE, FALSE));
9183 emitcode ("rrc", "a");
9184 aopPut (result, "a", LSB);
9188 /*-----------------------------------------------------------------*/
9189 /* genrshFour - shift four byte by a known amount != 0 */
9190 /*-----------------------------------------------------------------*/
9192 genrshFour (operand * result, operand * left,
9193 int shCount, int sign)
9195 D (emitcode (";", "genrshFour"));
9197 /* if shifting more that 3 bytes */
9202 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9204 movLeft2Result (left, MSB32, result, LSB, sign);
9205 addSign (result, MSB16, sign);
9207 else if (shCount >= 16)
9211 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9214 movLeft2Result (left, MSB24, result, LSB, 0);
9215 movLeft2Result (left, MSB32, result, MSB16, sign);
9217 addSign (result, MSB24, sign);
9219 else if (shCount >= 8)
9224 shiftRLong (left, MSB16, result, sign);
9226 else if (shCount == 0)
9228 movLeft2Result (left, MSB16, result, LSB, 0);
9229 movLeft2Result (left, MSB24, result, MSB16, 0);
9230 movLeft2Result (left, MSB32, result, MSB24, sign);
9231 addSign (result, MSB32, sign);
9235 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9236 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9237 /* the last shift is signed */
9238 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9239 addSign (result, MSB32, sign);
9244 /* 1 <= shCount <= 7 */
9247 shiftRLong (left, LSB, result, sign);
9249 shiftRLong (result, LSB, result, sign);
9253 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9254 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9255 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9260 /*-----------------------------------------------------------------*/
9261 /* genRightShiftLiteral - right shifting by known count */
9262 /*-----------------------------------------------------------------*/
9264 genRightShiftLiteral (operand * left,
9270 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9273 D (emitcode (";", "genRightShiftLiteral"));
9275 freeAsmop (right, NULL, ic, TRUE);
9277 aopOp (left, ic, FALSE);
9278 aopOp (result, ic, FALSE);
9281 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9285 size = getDataSize (left);
9286 /* test the LEFT size !!! */
9288 /* I suppose that the left size >= result size */
9291 size = getDataSize (result);
9293 movLeft2Result (left, size, result, size, 0);
9296 else if (shCount >= (size * 8))
9300 /* get sign in acc.7 */
9301 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9303 addSign (result, LSB, sign);
9310 genrshOne (result, left, shCount, sign);
9314 genrshTwo (result, left, shCount, sign);
9318 genrshFour (result, left, shCount, sign);
9324 freeAsmop (result, NULL, ic, TRUE);
9325 freeAsmop (left, NULL, ic, TRUE);
9328 /*-----------------------------------------------------------------*/
9329 /* genSignedRightShift - right shift of signed number */
9330 /*-----------------------------------------------------------------*/
9332 genSignedRightShift (iCode * ic)
9334 operand *right, *left, *result;
9337 symbol *tlbl, *tlbl1;
9340 D (emitcode (";", "genSignedRightShift"));
9342 /* we do it the hard way put the shift count in b
9343 and loop thru preserving the sign */
9345 right = IC_RIGHT (ic);
9346 left = IC_LEFT (ic);
9347 result = IC_RESULT (ic);
9349 aopOp (right, ic, FALSE);
9352 if (AOP_TYPE (right) == AOP_LIT)
9354 genRightShiftLiteral (left, right, result, ic, 1);
9357 /* shift count is unknown then we have to form
9358 a loop get the loop count in B : Note: we take
9359 only the lower order byte since shifting
9360 more that 32 bits make no sense anyway, ( the
9361 largest size of an object can be only 32 bits ) */
9364 MOVB (aopGet (right, 0, FALSE, FALSE));
9365 emitcode ("inc", "b");
9366 freeAsmop (right, NULL, ic, TRUE);
9367 aopOp (left, ic, FALSE);
9368 aopOp (result, ic, FALSE);
9370 /* now move the left to the result if they are not the
9372 if (!sameRegs (AOP (left), AOP (result)) &&
9373 AOP_SIZE (result) > 1)
9376 size = AOP_SIZE (result);
9380 l = aopGet (left, offset, FALSE, TRUE);
9381 if (*l == '@' && IS_AOP_PREG (result))
9384 emitcode ("mov", "a,%s", l);
9385 aopPut (result, "a", offset);
9388 aopPut (result, l, offset);
9393 /* mov the highest order bit to OVR */
9394 tlbl = newiTempLabel (NULL);
9395 tlbl1 = newiTempLabel (NULL);
9397 size = AOP_SIZE (result);
9399 MOVA (aopGet (left, offset, FALSE, FALSE));
9400 emitcode ("rlc", "a");
9401 emitcode ("mov", "ov,c");
9402 /* if it is only one byte then */
9405 l = aopGet (left, 0, FALSE, FALSE);
9407 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9409 emitcode ("mov", "c,ov");
9410 emitcode ("rrc", "a");
9412 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9414 aopPut (result, "a", 0);
9418 reAdjustPreg (AOP (result));
9419 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9421 emitcode ("mov", "c,ov");
9424 l = aopGet (result, offset, FALSE, FALSE);
9426 emitcode ("rrc", "a");
9427 aopPut (result, "a", offset--);
9429 reAdjustPreg (AOP (result));
9431 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9435 freeAsmop (result, NULL, ic, TRUE);
9436 freeAsmop (left, NULL, ic, TRUE);
9439 /*-----------------------------------------------------------------*/
9440 /* genRightShift - generate code for right shifting */
9441 /*-----------------------------------------------------------------*/
9443 genRightShift (iCode * ic)
9445 operand *right, *left, *result;
9449 symbol *tlbl, *tlbl1;
9452 D (emitcode (";", "genRightShift"));
9454 /* if signed then we do it the hard way preserve the
9455 sign bit moving it inwards */
9456 letype = getSpec (operandType (IC_LEFT (ic)));
9458 if (!SPEC_USIGN (letype))
9460 genSignedRightShift (ic);
9464 /* signed & unsigned types are treated the same : i.e. the
9465 signed is NOT propagated inwards : quoting from the
9466 ANSI - standard : "for E1 >> E2, is equivalent to division
9467 by 2**E2 if unsigned or if it has a non-negative value,
9468 otherwise the result is implementation defined ", MY definition
9469 is that the sign does not get propagated */
9471 right = IC_RIGHT (ic);
9472 left = IC_LEFT (ic);
9473 result = IC_RESULT (ic);
9475 aopOp (right, ic, FALSE);
9477 /* if the shift count is known then do it
9478 as efficiently as possible */
9479 if (AOP_TYPE (right) == AOP_LIT)
9481 genRightShiftLiteral (left, right, result, ic, 0);
9485 /* shift count is unknown then we have to form
9486 a loop get the loop count in B : Note: we take
9487 only the lower order byte since shifting
9488 more that 32 bits make no sense anyway, ( the
9489 largest size of an object can be only 32 bits ) */
9492 MOVB (aopGet (right, 0, FALSE, FALSE));
9493 emitcode ("inc", "b");
9494 freeAsmop (right, NULL, ic, TRUE);
9495 aopOp (left, ic, FALSE);
9496 aopOp (result, ic, FALSE);
9498 /* now move the left to the result if they are not the
9500 if (!sameRegs (AOP (left), AOP (result)) &&
9501 AOP_SIZE (result) > 1)
9503 size = AOP_SIZE (result);
9507 l = aopGet (left, offset, FALSE, TRUE);
9508 if (*l == '@' && IS_AOP_PREG (result))
9511 emitcode ("mov", "a,%s", l);
9512 aopPut (result, "a", offset);
9515 aopPut (result, l, offset);
9520 tlbl = newiTempLabel (NULL);
9521 tlbl1 = newiTempLabel (NULL);
9522 size = AOP_SIZE (result);
9525 /* if it is only one byte then */
9528 l = aopGet (left, 0, FALSE, FALSE);
9530 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9533 emitcode ("rrc", "a");
9535 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9537 aopPut (result, "a", 0);
9541 reAdjustPreg (AOP (result));
9542 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9547 l = aopGet (result, offset, FALSE, FALSE);
9549 emitcode ("rrc", "a");
9550 aopPut (result, "a", offset--);
9552 reAdjustPreg (AOP (result));
9555 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9559 freeAsmop (result, NULL, ic, TRUE);
9560 freeAsmop (left, NULL, ic, TRUE);
9563 /*-----------------------------------------------------------------*/
9564 /* emitPtrByteGet - emits code to get a byte into A through a */
9565 /* pointer register (R0, R1, or DPTR). The */
9566 /* original value of A can be preserved in B. */
9567 /*-----------------------------------------------------------------*/
9569 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9576 emitcode ("mov", "b,a");
9577 emitcode ("mov", "a,@%s", rname);
9582 emitcode ("mov", "b,a");
9583 emitcode ("movx", "a,@%s", rname);
9588 emitcode ("mov", "b,a");
9589 emitcode ("movx", "a,@dptr");
9594 emitcode ("mov", "b,a");
9595 emitcode ("clr", "a");
9596 emitcode ("movc", "a,@a+dptr");
9602 emitcode ("push", "b");
9603 emitcode ("push", "acc");
9605 emitcode ("lcall", "__gptrget");
9607 emitcode ("pop", "b");
9612 /*-----------------------------------------------------------------*/
9613 /* emitPtrByteSet - emits code to set a byte from src through a */
9614 /* pointer register (R0, R1, or DPTR). */
9615 /*-----------------------------------------------------------------*/
9617 emitPtrByteSet (char *rname, int p_type, char *src)
9626 emitcode ("mov", "@%s,a", rname);
9629 emitcode ("mov", "@%s,%s", rname, src);
9634 emitcode ("movx", "@%s,a", rname);
9639 emitcode ("movx", "@dptr,a");
9644 emitcode ("lcall", "__gptrput");
9649 /*-----------------------------------------------------------------*/
9650 /* genUnpackBits - generates code for unpacking bits */
9651 /*-----------------------------------------------------------------*/
9653 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9655 int offset = 0; /* result byte offset */
9656 int rsize; /* result size */
9657 int rlen = 0; /* remaining bitfield length */
9658 sym_link *etype; /* bitfield type information */
9659 int blen; /* bitfield length */
9660 int bstr; /* bitfield starting bit within byte */
9663 D(emitcode ("; genUnpackBits",""));
9665 etype = getSpec (operandType (result));
9666 rsize = getSize (operandType (result));
9667 blen = SPEC_BLEN (etype);
9668 bstr = SPEC_BSTR (etype);
9670 if (ifx && blen <= 8)
9672 emitPtrByteGet (rname, ptype, FALSE);
9675 SNPRINTF (buffer, sizeof(buffer),
9677 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9682 emitcode ("anl", "a,#0x%02x",
9683 (((unsigned char) -1) >> (8 - blen)) << bstr);
9684 genIfxJump (ifx, "a", NULL, NULL, NULL);
9690 /* If the bitfield length is less than a byte */
9693 emitPtrByteGet (rname, ptype, FALSE);
9695 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9696 if (!SPEC_USIGN (etype))
9698 /* signed bitfield */
9699 symbol *tlbl = newiTempLabel (NULL);
9701 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9702 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9705 aopPut (result, "a", offset++);
9709 /* Bit field did not fit in a byte. Copy all
9710 but the partial byte at the end. */
9711 for (rlen=blen;rlen>=8;rlen-=8)
9713 emitPtrByteGet (rname, ptype, FALSE);
9714 aopPut (result, "a", offset++);
9716 emitcode ("inc", "%s", rname);
9719 /* Handle the partial byte at the end */
9722 emitPtrByteGet (rname, ptype, FALSE);
9723 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9724 if (!SPEC_USIGN (etype))
9726 /* signed bitfield */
9727 symbol *tlbl = newiTempLabel (NULL);
9729 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9730 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9733 aopPut (result, "a", offset++);
9741 if (SPEC_USIGN (etype))
9745 /* signed bitfield: sign extension with 0x00 or 0xff */
9746 emitcode ("rlc", "a");
9747 emitcode ("subb", "a,acc");
9753 aopPut (result, source, offset++);
9758 /*-----------------------------------------------------------------*/
9759 /* genDataPointerGet - generates code when ptr offset is known */
9760 /*-----------------------------------------------------------------*/
9762 genDataPointerGet (operand * left,
9768 int size, offset = 0;
9770 D (emitcode (";", "genDataPointerGet"));
9772 aopOp (result, ic, TRUE);
9774 /* get the string representation of the name */
9775 l = aopGet (left, 0, FALSE, TRUE);
9777 size = AOP_SIZE (result);
9782 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9786 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9788 aopPut (result, buffer, offset++);
9791 freeAsmop (result, NULL, ic, TRUE);
9792 freeAsmop (left, NULL, ic, TRUE);
9795 /*-----------------------------------------------------------------*/
9796 /* genNearPointerGet - emitcode for near pointer fetch */
9797 /*-----------------------------------------------------------------*/
9799 genNearPointerGet (operand * left,
9808 sym_link *rtype, *retype;
9809 sym_link *ltype = operandType (left);
9812 D (emitcode (";", "genNearPointerGet"));
9814 rtype = operandType (result);
9815 retype = getSpec (rtype);
9817 aopOp (left, ic, FALSE);
9819 /* if left is rematerialisable and
9820 result is not bitfield variable type and
9821 the left is pointer to data space i.e
9822 lower 128 bytes of space */
9823 if (AOP_TYPE (left) == AOP_IMMD &&
9824 !IS_BITFIELD (retype) &&
9825 DCL_TYPE (ltype) == POINTER)
9827 genDataPointerGet (left, result, ic);
9831 /* if the value is already in a pointer register
9832 then don't need anything more */
9833 if (!AOP_INPREG (AOP (left)))
9835 if (IS_AOP_PREG (left))
9837 // Aha, it is a pointer, just in disguise.
9838 rname = aopGet (left, 0, FALSE, FALSE);
9841 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9842 __FILE__, __LINE__);
9847 emitcode ("mov", "a%s,%s", rname + 1, rname);
9848 rname++; // skip the '@'.
9853 /* otherwise get a free pointer register */
9855 preg = getFreePtr (ic, &aop, FALSE);
9856 emitcode ("mov", "%s,%s",
9858 aopGet (left, 0, FALSE, TRUE));
9863 rname = aopGet (left, 0, FALSE, FALSE);
9865 //aopOp (result, ic, FALSE);
9866 aopOp (result, ic, result?TRUE:FALSE);
9868 /* if bitfield then unpack the bits */
9869 if (IS_BITFIELD (retype))
9870 genUnpackBits (result, rname, POINTER, ifx);
9873 /* we have can just get the values */
9874 int size = AOP_SIZE (result);
9879 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9882 emitcode ("mov", "a,@%s", rname);
9884 aopPut (result, "a", offset);
9888 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9889 aopPut (result, buffer, offset);
9893 emitcode ("inc", "%s", rname);
9897 /* now some housekeeping stuff */
9898 if (aop) /* we had to allocate for this iCode */
9900 if (pi) { /* post increment present */
9901 aopPut (left, rname, 0);
9903 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9907 /* we did not allocate which means left
9908 already in a pointer register, then
9909 if size > 0 && this could be used again
9910 we have to point it back to where it
9912 if ((AOP_SIZE (result) > 1 &&
9913 !OP_SYMBOL (left)->remat &&
9914 (OP_SYMBOL (left)->liveTo > ic->seq ||
9918 int size = AOP_SIZE (result) - 1;
9920 emitcode ("dec", "%s", rname);
9924 if (ifx && !ifx->generated)
9926 genIfxJump (ifx, "a", left, NULL, result);
9930 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9931 freeAsmop (left, NULL, ic, TRUE);
9932 if (pi) pi->generated = 1;
9935 /*-----------------------------------------------------------------*/
9936 /* genPagedPointerGet - emitcode for paged pointer fetch */
9937 /*-----------------------------------------------------------------*/
9939 genPagedPointerGet (operand * left,
9948 sym_link *rtype, *retype;
9950 D (emitcode (";", "genPagedPointerGet"));
9952 rtype = operandType (result);
9953 retype = getSpec (rtype);
9955 aopOp (left, ic, FALSE);
9957 /* if the value is already in a pointer register
9958 then don't need anything more */
9959 if (!AOP_INPREG (AOP (left)))
9961 /* otherwise get a free pointer register */
9963 preg = getFreePtr (ic, &aop, FALSE);
9964 emitcode ("mov", "%s,%s",
9966 aopGet (left, 0, FALSE, TRUE));
9970 rname = aopGet (left, 0, FALSE, FALSE);
9972 aopOp (result, ic, FALSE);
9974 /* if bitfield then unpack the bits */
9975 if (IS_BITFIELD (retype))
9976 genUnpackBits (result, rname, PPOINTER, ifx);
9979 /* we have can just get the values */
9980 int size = AOP_SIZE (result);
9986 emitcode ("movx", "a,@%s", rname);
9988 aopPut (result, "a", offset);
9993 emitcode ("inc", "%s", rname);
9997 /* now some housekeeping stuff */
9998 if (aop) /* we had to allocate for this iCode */
10001 aopPut (left, rname, 0);
10002 freeAsmop (NULL, aop, ic, TRUE);
10006 /* we did not allocate which means left
10007 already in a pointer register, then
10008 if size > 0 && this could be used again
10009 we have to point it back to where it
10011 if ((AOP_SIZE (result) > 1 &&
10012 !OP_SYMBOL (left)->remat &&
10013 (OP_SYMBOL (left)->liveTo > ic->seq ||
10017 int size = AOP_SIZE (result) - 1;
10019 emitcode ("dec", "%s", rname);
10023 if (ifx && !ifx->generated)
10025 genIfxJump (ifx, "a", left, NULL, result);
10029 freeAsmop (result, NULL, ic, TRUE);
10030 freeAsmop (left, NULL, ic, TRUE);
10031 if (pi) pi->generated = 1;
10034 /*--------------------------------------------------------------------*/
10035 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10036 /*--------------------------------------------------------------------*/
10038 loadDptrFromOperand (operand *op, bool loadBToo)
10040 if (AOP_TYPE (op) != AOP_STR)
10042 /* if this is rematerializable */
10043 if (AOP_TYPE (op) == AOP_IMMD)
10045 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10048 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10049 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10052 wassertl(FALSE, "need pointerCode");
10053 emitcode ("", "; mov b,???");
10054 /* genPointerGet and genPointerSet originally did different
10055 ** things for this case. Both seem wrong.
10056 ** from genPointerGet:
10057 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10058 ** from genPointerSet:
10059 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10064 else if (AOP_TYPE (op) == AOP_DPTR)
10068 MOVA (aopGet (op, 0, FALSE, FALSE));
10069 emitcode ("push", "acc");
10070 MOVA (aopGet (op, 1, FALSE, FALSE));
10071 emitcode ("push", "acc");
10072 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10073 emitcode ("pop", "dph");
10074 emitcode ("pop", "dpl");
10078 MOVA (aopGet (op, 0, FALSE, FALSE));
10079 emitcode ("push", "acc");
10080 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10081 emitcode ("pop", "dpl");
10085 { /* we need to get it byte by byte */
10086 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10087 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10089 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10094 /*-----------------------------------------------------------------*/
10095 /* genFarPointerGet - get value from far space */
10096 /*-----------------------------------------------------------------*/
10098 genFarPointerGet (operand * left,
10099 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10102 sym_link *retype = getSpec (operandType (result));
10104 D (emitcode (";", "genFarPointerGet"));
10106 aopOp (left, ic, FALSE);
10107 loadDptrFromOperand (left, FALSE);
10109 /* so dptr now contains the address */
10110 aopOp (result, ic, FALSE);
10112 /* if bit then unpack */
10113 if (IS_BITFIELD (retype))
10114 genUnpackBits (result, "dptr", FPOINTER, ifx);
10117 size = AOP_SIZE (result);
10122 emitcode ("movx", "a,@dptr");
10124 aopPut (result, "a", offset++);
10126 emitcode ("inc", "dptr");
10130 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10132 aopPut (left, "dpl", 0);
10133 aopPut (left, "dph", 1);
10137 if (ifx && !ifx->generated)
10139 genIfxJump (ifx, "a", left, NULL, result);
10142 freeAsmop (result, NULL, ic, TRUE);
10143 freeAsmop (left, NULL, ic, TRUE);
10146 /*-----------------------------------------------------------------*/
10147 /* genCodePointerGet - get value from code space */
10148 /*-----------------------------------------------------------------*/
10150 genCodePointerGet (operand * left,
10151 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10154 sym_link *retype = getSpec (operandType (result));
10156 D (emitcode (";", "genCodePointerGet"));
10158 aopOp (left, ic, FALSE);
10159 loadDptrFromOperand (left, FALSE);
10161 /* so dptr now contains the address */
10162 aopOp (result, ic, FALSE);
10164 /* if bit then unpack */
10165 if (IS_BITFIELD (retype))
10166 genUnpackBits (result, "dptr", CPOINTER, ifx);
10169 size = AOP_SIZE (result);
10174 emitcode ("clr", "a");
10175 emitcode ("movc", "a,@a+dptr");
10177 aopPut (result, "a", offset++);
10179 emitcode ("inc", "dptr");
10183 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10185 aopPut (left, "dpl", 0);
10186 aopPut (left, "dph", 1);
10190 if (ifx && !ifx->generated)
10192 genIfxJump (ifx, "a", left, NULL, result);
10195 freeAsmop (result, NULL, ic, TRUE);
10196 freeAsmop (left, NULL, ic, TRUE);
10199 /*-----------------------------------------------------------------*/
10200 /* genGenPointerGet - get value from generic pointer space */
10201 /*-----------------------------------------------------------------*/
10203 genGenPointerGet (operand * left,
10204 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10207 sym_link *retype = getSpec (operandType (result));
10209 D (emitcode (";", "genGenPointerGet"));
10211 aopOp (left, ic, FALSE);
10212 loadDptrFromOperand (left, TRUE);
10214 /* so dptr now contains the address */
10215 aopOp (result, ic, FALSE);
10217 /* if bit then unpack */
10218 if (IS_BITFIELD (retype))
10220 genUnpackBits (result, "dptr", GPOINTER, ifx);
10224 size = AOP_SIZE (result);
10229 emitcode ("lcall", "__gptrget");
10231 aopPut (result, "a", offset++);
10233 emitcode ("inc", "dptr");
10237 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10239 aopPut (left, "dpl", 0);
10240 aopPut (left, "dph", 1);
10244 if (ifx && !ifx->generated)
10246 genIfxJump (ifx, "a", left, NULL, result);
10249 freeAsmop (result, NULL, ic, TRUE);
10250 freeAsmop (left, NULL, ic, TRUE);
10253 /*-----------------------------------------------------------------*/
10254 /* genPointerGet - generate code for pointer get */
10255 /*-----------------------------------------------------------------*/
10257 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10259 operand *left, *result;
10260 sym_link *type, *etype;
10263 D (emitcode (";", "genPointerGet"));
10265 left = IC_LEFT (ic);
10266 result = IC_RESULT (ic);
10268 if (getSize (operandType (result))>1)
10271 /* depending on the type of pointer we need to
10272 move it to the correct pointer register */
10273 type = operandType (left);
10274 etype = getSpec (type);
10275 /* if left is of type of pointer then it is simple */
10276 if (IS_PTR (type) && !IS_FUNC (type->next))
10277 p_type = DCL_TYPE (type);
10280 /* we have to go by the storage class */
10281 p_type = PTR_TYPE (SPEC_OCLS (etype));
10284 /* special case when cast remat */
10285 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10286 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10288 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10289 type = operandType (left);
10290 p_type = DCL_TYPE (type);
10292 /* now that we have the pointer type we assign
10293 the pointer values */
10299 genNearPointerGet (left, result, ic, pi, ifx);
10303 genPagedPointerGet (left, result, ic, pi, ifx);
10307 genFarPointerGet (left, result, ic, pi, ifx);
10311 genCodePointerGet (left, result, ic, pi, ifx);
10315 genGenPointerGet (left, result, ic, pi, ifx);
10321 /*-----------------------------------------------------------------*/
10322 /* genPackBits - generates code for packed bit storage */
10323 /*-----------------------------------------------------------------*/
10325 genPackBits (sym_link * etype,
10327 char *rname, int p_type)
10329 int offset = 0; /* source byte offset */
10330 int rlen = 0; /* remaining bitfield length */
10331 int blen; /* bitfield length */
10332 int bstr; /* bitfield starting bit within byte */
10333 int litval; /* source literal value (if AOP_LIT) */
10334 unsigned char mask; /* bitmask within current byte */
10336 D(emitcode ("; genPackBits",""));
10338 blen = SPEC_BLEN (etype);
10339 bstr = SPEC_BSTR (etype);
10341 /* If the bitfield length is less than a byte */
10344 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10345 (unsigned char) (0xFF >> (8 - bstr)));
10347 if (AOP_TYPE (right) == AOP_LIT)
10349 /* Case with a bitfield length <8 and literal source
10351 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10353 litval &= (~mask) & 0xff;
10354 emitPtrByteGet (rname, p_type, FALSE);
10355 if ((mask|litval)!=0xff)
10356 emitcode ("anl","a,#0x%02x", mask);
10358 emitcode ("orl","a,#0x%02x", litval);
10362 if ((blen==1) && (p_type!=GPOINTER))
10364 /* Case with a bitfield length == 1 and no generic pointer
10366 if (AOP_TYPE (right) == AOP_CRY)
10367 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10370 MOVA (aopGet (right, 0, FALSE, FALSE));
10371 emitcode ("rrc","a");
10373 emitPtrByteGet (rname, p_type, FALSE);
10374 emitcode ("mov","acc.%d,c",bstr);
10379 /* Case with a bitfield length < 8 and arbitrary source
10381 MOVA (aopGet (right, 0, FALSE, FALSE));
10382 /* shift and mask source value */
10384 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10386 pushedB = pushB ();
10387 /* transfer A to B and get next byte */
10388 emitPtrByteGet (rname, p_type, TRUE);
10390 emitcode ("anl", "a,#0x%02x", mask);
10391 emitcode ("orl", "a,b");
10392 if (p_type == GPOINTER)
10393 emitcode ("pop", "b");
10399 emitPtrByteSet (rname, p_type, "a");
10403 /* Bit length is greater than 7 bits. In this case, copy */
10404 /* all except the partial byte at the end */
10405 for (rlen=blen;rlen>=8;rlen-=8)
10407 emitPtrByteSet (rname, p_type,
10408 aopGet (right, offset++, FALSE, TRUE) );
10410 emitcode ("inc", "%s", rname);
10413 /* If there was a partial byte at the end */
10416 mask = (((unsigned char) -1 << rlen) & 0xff);
10418 if (AOP_TYPE (right) == AOP_LIT)
10420 /* Case with partial byte and literal source
10422 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10423 litval >>= (blen-rlen);
10424 litval &= (~mask) & 0xff;
10425 emitPtrByteGet (rname, p_type, FALSE);
10426 if ((mask|litval)!=0xff)
10427 emitcode ("anl","a,#0x%02x", mask);
10429 emitcode ("orl","a,#0x%02x", litval);
10434 /* Case with partial byte and arbitrary source
10436 MOVA (aopGet (right, offset++, FALSE, FALSE));
10437 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10439 pushedB = pushB ();
10440 /* transfer A to B and get next byte */
10441 emitPtrByteGet (rname, p_type, TRUE);
10443 emitcode ("anl", "a,#0x%02x", mask);
10444 emitcode ("orl", "a,b");
10445 if (p_type == GPOINTER)
10446 emitcode ("pop", "b");
10450 emitPtrByteSet (rname, p_type, "a");
10455 /*-----------------------------------------------------------------*/
10456 /* genDataPointerSet - remat pointer to data space */
10457 /*-----------------------------------------------------------------*/
10459 genDataPointerSet (operand * right,
10463 int size, offset = 0;
10464 char *l, buffer[256];
10466 D (emitcode (";", "genDataPointerSet"));
10468 aopOp (right, ic, FALSE);
10470 l = aopGet (result, 0, FALSE, TRUE);
10472 size = AOP_SIZE (right);
10476 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10478 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10479 emitcode ("mov", "%s,%s", buffer,
10480 aopGet (right, offset++, FALSE, FALSE));
10483 freeAsmop (result, NULL, ic, TRUE);
10484 freeAsmop (right, NULL, ic, TRUE);
10487 /*-----------------------------------------------------------------*/
10488 /* genNearPointerSet - emitcode for near pointer put */
10489 /*-----------------------------------------------------------------*/
10491 genNearPointerSet (operand * right,
10499 sym_link *retype, *letype;
10500 sym_link *ptype = operandType (result);
10502 D (emitcode (";", "genNearPointerSet"));
10504 retype = getSpec (operandType (right));
10505 letype = getSpec (ptype);
10507 aopOp (result, ic, FALSE);
10509 /* if the result is rematerializable &
10510 in data space & not a bit variable */
10511 if (AOP_TYPE (result) == AOP_IMMD &&
10512 DCL_TYPE (ptype) == POINTER &&
10513 !IS_BITVAR (retype) &&
10514 !IS_BITVAR (letype))
10516 genDataPointerSet (right, result, ic);
10520 /* if the value is already in a pointer register
10521 then don't need anything more */
10522 if (!AOP_INPREG (AOP (result)))
10525 //AOP_TYPE (result) == AOP_STK
10526 IS_AOP_PREG(result)
10529 // Aha, it is a pointer, just in disguise.
10530 rname = aopGet (result, 0, FALSE, FALSE);
10533 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10534 __FILE__, __LINE__);
10539 emitcode ("mov", "a%s,%s", rname + 1, rname);
10540 rname++; // skip the '@'.
10545 /* otherwise get a free pointer register */
10546 aop = newAsmop (0);
10547 preg = getFreePtr (ic, &aop, FALSE);
10548 emitcode ("mov", "%s,%s",
10550 aopGet (result, 0, FALSE, TRUE));
10551 rname = preg->name;
10556 rname = aopGet (result, 0, FALSE, FALSE);
10559 aopOp (right, ic, FALSE);
10561 /* if bitfield then unpack the bits */
10562 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10563 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10566 /* we can just get the values */
10567 int size = AOP_SIZE (right);
10572 l = aopGet (right, offset, FALSE, TRUE);
10573 if ((*l == '@') || (strcmp (l, "acc") == 0))
10576 emitcode ("mov", "@%s,a", rname);
10579 emitcode ("mov", "@%s,%s", rname, l);
10581 emitcode ("inc", "%s", rname);
10586 /* now some housekeeping stuff */
10587 if (aop) /* we had to allocate for this iCode */
10590 aopPut (result, rname, 0);
10591 freeAsmop (NULL, aop, ic, TRUE);
10595 /* we did not allocate which means left
10596 already in a pointer register, then
10597 if size > 0 && this could be used again
10598 we have to point it back to where it
10600 if ((AOP_SIZE (right) > 1 &&
10601 !OP_SYMBOL (result)->remat &&
10602 (OP_SYMBOL (result)->liveTo > ic->seq ||
10606 int size = AOP_SIZE (right) - 1;
10608 emitcode ("dec", "%s", rname);
10613 if (pi) pi->generated = 1;
10614 freeAsmop (result, NULL, ic, TRUE);
10615 freeAsmop (right, NULL, ic, TRUE);
10618 /*-----------------------------------------------------------------*/
10619 /* genPagedPointerSet - emitcode for Paged pointer put */
10620 /*-----------------------------------------------------------------*/
10622 genPagedPointerSet (operand * right,
10630 sym_link *retype, *letype;
10632 D (emitcode (";", "genPagedPointerSet"));
10634 retype = getSpec (operandType (right));
10635 letype = getSpec (operandType (result));
10637 aopOp (result, ic, FALSE);
10639 /* if the value is already in a pointer register
10640 then don't need anything more */
10641 if (!AOP_INPREG (AOP (result)))
10643 /* otherwise get a free pointer register */
10644 aop = newAsmop (0);
10645 preg = getFreePtr (ic, &aop, FALSE);
10646 emitcode ("mov", "%s,%s",
10648 aopGet (result, 0, FALSE, TRUE));
10649 rname = preg->name;
10652 rname = aopGet (result, 0, FALSE, FALSE);
10654 aopOp (right, ic, FALSE);
10656 /* if bitfield then unpack the bits */
10657 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10658 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10661 /* we have can just get the values */
10662 int size = AOP_SIZE (right);
10667 l = aopGet (right, offset, FALSE, TRUE);
10669 emitcode ("movx", "@%s,a", rname);
10672 emitcode ("inc", "%s", rname);
10678 /* now some housekeeping stuff */
10679 if (aop) /* we had to allocate for this iCode */
10682 aopPut (result, rname, 0);
10683 freeAsmop (NULL, aop, ic, TRUE);
10687 /* we did not allocate which means left
10688 already in a pointer register, then
10689 if size > 0 && this could be used again
10690 we have to point it back to where it
10692 if (AOP_SIZE (right) > 1 &&
10693 !OP_SYMBOL (result)->remat &&
10694 (OP_SYMBOL (result)->liveTo > ic->seq ||
10697 int size = AOP_SIZE (right) - 1;
10699 emitcode ("dec", "%s", rname);
10704 if (pi) pi->generated = 1;
10705 freeAsmop (result, NULL, ic, TRUE);
10706 freeAsmop (right, NULL, ic, TRUE);
10709 /*-----------------------------------------------------------------*/
10710 /* genFarPointerSet - set value from far space */
10711 /*-----------------------------------------------------------------*/
10713 genFarPointerSet (operand * right,
10714 operand * result, iCode * ic, iCode * pi)
10717 sym_link *retype = getSpec (operandType (right));
10718 sym_link *letype = getSpec (operandType (result));
10720 D(emitcode ("; genFarPointerSet",""));
10722 aopOp (result, ic, FALSE);
10723 loadDptrFromOperand (result, FALSE);
10725 /* so dptr now contains the address */
10726 aopOp (right, ic, FALSE);
10728 /* if bit then unpack */
10729 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10730 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10733 size = AOP_SIZE (right);
10738 char *l = aopGet (right, offset++, FALSE, FALSE);
10740 emitcode ("movx", "@dptr,a");
10742 emitcode ("inc", "dptr");
10745 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10746 aopPut (result, "dpl", 0);
10747 aopPut (result, "dph", 1);
10750 freeAsmop (result, NULL, ic, TRUE);
10751 freeAsmop (right, NULL, ic, TRUE);
10754 /*-----------------------------------------------------------------*/
10755 /* genGenPointerSet - set value from generic pointer space */
10756 /*-----------------------------------------------------------------*/
10758 genGenPointerSet (operand * right,
10759 operand * result, iCode * ic, iCode * pi)
10762 sym_link *retype = getSpec (operandType (right));
10763 sym_link *letype = getSpec (operandType (result));
10765 D (emitcode (";", "genGenPointerSet"));
10767 aopOp (result, ic, FALSE);
10768 loadDptrFromOperand (result, TRUE);
10770 /* so dptr now contains the address */
10771 aopOp (right, ic, FALSE);
10773 /* if bit then unpack */
10774 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10776 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10780 size = AOP_SIZE (right);
10785 char *l = aopGet (right, offset++, FALSE, FALSE);
10787 emitcode ("lcall", "__gptrput");
10789 emitcode ("inc", "dptr");
10793 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10794 aopPut (result, "dpl", 0);
10795 aopPut (result, "dph", 1);
10798 freeAsmop (result, NULL, ic, TRUE);
10799 freeAsmop (right, NULL, ic, TRUE);
10802 /*-----------------------------------------------------------------*/
10803 /* genPointerSet - stores the value into a pointer location */
10804 /*-----------------------------------------------------------------*/
10806 genPointerSet (iCode * ic, iCode *pi)
10808 operand *right, *result;
10809 sym_link *type, *etype;
10812 D (emitcode (";", "genPointerSet"));
10814 right = IC_RIGHT (ic);
10815 result = IC_RESULT (ic);
10817 /* depending on the type of pointer we need to
10818 move it to the correct pointer register */
10819 type = operandType (result);
10820 etype = getSpec (type);
10821 /* if left is of type of pointer then it is simple */
10822 if (IS_PTR (type) && !IS_FUNC (type->next))
10824 p_type = DCL_TYPE (type);
10828 /* we have to go by the storage class */
10829 p_type = PTR_TYPE (SPEC_OCLS (etype));
10832 /* special case when cast remat */
10833 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10834 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10835 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10836 type = operandType (result);
10837 p_type = DCL_TYPE (type);
10840 /* now that we have the pointer type we assign
10841 the pointer values */
10847 genNearPointerSet (right, result, ic, pi);
10851 genPagedPointerSet (right, result, ic, pi);
10855 genFarPointerSet (right, result, ic, pi);
10859 genGenPointerSet (right, result, ic, pi);
10863 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10864 "genPointerSet: illegal pointer type");
10868 /*-----------------------------------------------------------------*/
10869 /* genIfx - generate code for Ifx statement */
10870 /*-----------------------------------------------------------------*/
10872 genIfx (iCode * ic, iCode * popIc)
10874 operand *cond = IC_COND (ic);
10878 D (emitcode (";", "genIfx"));
10880 aopOp (cond, ic, FALSE);
10882 /* get the value into acc */
10883 if (AOP_TYPE (cond) != AOP_CRY)
10890 if (AOP(cond)->aopu.aop_dir)
10891 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10894 /* the result is now in the accumulator or a directly addressable bit */
10895 freeAsmop (cond, NULL, ic, TRUE);
10897 /* if there was something to be popped then do it */
10901 /* if the condition is a bit variable */
10903 genIfxJump(ic, dup, NULL, NULL, NULL);
10904 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10905 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10906 else if (isbit && !IS_ITEMP (cond))
10907 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10909 genIfxJump (ic, "a", NULL, NULL, NULL);
10914 /*-----------------------------------------------------------------*/
10915 /* genAddrOf - generates code for address of */
10916 /*-----------------------------------------------------------------*/
10918 genAddrOf (iCode * ic)
10920 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10923 D (emitcode (";", "genAddrOf"));
10925 aopOp (IC_RESULT (ic), ic, FALSE);
10927 /* if the operand is on the stack then we
10928 need to get the stack offset of this
10932 /* if it has an offset then we need to compute it */
10935 int stack_offset = ((sym->stack < 0) ?
10936 ((char) (sym->stack - _G.nRegsSaved)) :
10937 ((char) sym->stack)) & 0xff;
10938 if ((abs(stack_offset) == 1) &&
10939 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10940 !isOperandVolatile (IC_RESULT (ic), FALSE))
10942 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10943 if (stack_offset > 0)
10944 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10946 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10950 emitcode ("mov", "a,%s", SYM_BP (sym));
10951 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10952 aopPut (IC_RESULT (ic), "a", 0);
10957 /* we can just move _bp */
10958 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10960 /* fill the result with zero */
10961 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10966 aopPut (IC_RESULT (ic), zero, offset++);
10971 /* object not on stack then we need the name */
10972 size = AOP_SIZE (IC_RESULT (ic));
10977 char s[SDCC_NAME_MAX];
10979 sprintf (s, "#(%s >> %d)",
10983 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10984 aopPut (IC_RESULT (ic), s, offset++);
10988 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10992 /*-----------------------------------------------------------------*/
10993 /* genFarFarAssign - assignment when both are in far space */
10994 /*-----------------------------------------------------------------*/
10996 genFarFarAssign (operand * result, operand * right, iCode * ic)
10998 int size = AOP_SIZE (right);
11002 D (emitcode (";", "genFarFarAssign"));
11004 /* first push the right side on to the stack */
11007 l = aopGet (right, offset++, FALSE, FALSE);
11009 emitcode ("push", "acc");
11012 freeAsmop (right, NULL, ic, FALSE);
11013 /* now assign DPTR to result */
11014 aopOp (result, ic, FALSE);
11015 size = AOP_SIZE (result);
11018 emitcode ("pop", "acc");
11019 aopPut (result, "a", --offset);
11021 freeAsmop (result, NULL, ic, FALSE);
11024 /*-----------------------------------------------------------------*/
11025 /* genAssign - generate code for assignment */
11026 /*-----------------------------------------------------------------*/
11028 genAssign (iCode * ic)
11030 operand *result, *right;
11032 unsigned long lit = 0L;
11034 D (emitcode (";", "genAssign"));
11036 result = IC_RESULT (ic);
11037 right = IC_RIGHT (ic);
11039 /* if they are the same */
11040 if (operandsEqu (result, right) &&
11041 !isOperandVolatile (result, FALSE) &&
11042 !isOperandVolatile (right, FALSE))
11045 aopOp (right, ic, FALSE);
11047 /* special case both in far space */
11048 if (AOP_TYPE (right) == AOP_DPTR &&
11049 IS_TRUE_SYMOP (result) &&
11050 isOperandInFarSpace (result))
11052 genFarFarAssign (result, right, ic);
11056 aopOp (result, ic, TRUE);
11058 /* if they are the same registers */
11059 if (sameRegs (AOP (right), AOP (result)) &&
11060 !isOperandVolatile (result, FALSE) &&
11061 !isOperandVolatile (right, FALSE))
11064 /* if the result is a bit */
11065 if (AOP_TYPE (result) == AOP_CRY)
11067 /* if the right size is a literal then
11068 we know what the value is */
11069 if (AOP_TYPE (right) == AOP_LIT)
11071 if (((int) operandLitValue (right)))
11072 aopPut (result, one, 0);
11074 aopPut (result, zero, 0);
11078 /* the right is also a bit variable */
11079 if (AOP_TYPE (right) == AOP_CRY)
11081 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11082 aopPut (result, "c", 0);
11086 /* we need to or */
11088 aopPut (result, "a", 0);
11092 /* bit variables done */
11094 size = AOP_SIZE (result);
11096 if (AOP_TYPE (right) == AOP_LIT)
11097 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11100 (AOP_TYPE (result) != AOP_REG) &&
11101 (AOP_TYPE (right) == AOP_LIT) &&
11102 !IS_FLOAT (operandType (right)) &&
11105 while ((size) && (lit))
11108 aopGet (right, offset, FALSE, FALSE),
11114 /* And now fill the rest with zeros. */
11117 emitcode ("clr", "a");
11121 aopPut (result, "a", offset);
11130 aopGet (right, offset, FALSE, FALSE),
11137 freeAsmop (result, NULL, ic, TRUE);
11138 freeAsmop (right, NULL, ic, TRUE);
11141 /*-----------------------------------------------------------------*/
11142 /* genJumpTab - generates code for jump table */
11143 /*-----------------------------------------------------------------*/
11145 genJumpTab (iCode * ic)
11147 symbol *jtab,*jtablo,*jtabhi;
11149 unsigned int count;
11151 D (emitcode (";", "genJumpTab"));
11153 count = elementsInSet( IC_JTLABELS (ic) );
11157 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11158 if the switch argument is in a register.
11159 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11160 /* Peephole may not convert ljmp to sjmp or ret
11161 labelIsReturnOnly & labelInRange must check
11162 currPl->ic->op != JUMPTABLE */
11163 aopOp (IC_JTCOND (ic), ic, FALSE);
11164 /* get the condition into accumulator */
11165 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11167 /* multiply by three */
11168 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11170 emitcode ("mov", "b,#3");
11171 emitcode ("mul", "ab");
11175 emitcode ("add", "a,acc");
11176 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11178 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11180 jtab = newiTempLabel (NULL);
11181 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11182 emitcode ("jmp", "@a+dptr");
11184 /* now generate the jump labels */
11185 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11186 jtab = setNextItem (IC_JTLABELS (ic)))
11187 emitcode ("ljmp", "%05d$", jtab->key + 100);
11191 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11192 if the switch argument is in a register.
11193 For n>6 this algorithm may be more compact */
11194 jtablo = newiTempLabel (NULL);
11195 jtabhi = newiTempLabel (NULL);
11197 /* get the condition into accumulator.
11198 Using b as temporary storage, if register push/pop is needed */
11199 aopOp (IC_JTCOND (ic), ic, FALSE);
11200 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11201 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11202 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11204 // (MB) what if B is in use???
11205 wassertl(!BINUSE, "B was in use");
11206 emitcode ("mov", "b,%s", l);
11209 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11213 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11214 emitcode ("movc", "a,@a+pc");
11215 emitcode ("push", "acc");
11218 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11219 emitcode ("movc", "a,@a+pc");
11220 emitcode ("push", "acc");
11224 /* this scales up to n<=255, but needs two more bytes
11225 and changes dptr */
11226 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11227 emitcode ("movc", "a,@a+dptr");
11228 emitcode ("push", "acc");
11231 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11232 emitcode ("movc", "a,@a+dptr");
11233 emitcode ("push", "acc");
11236 emitcode ("ret", "");
11238 /* now generate jump table, LSB */
11239 emitLabel (jtablo);
11240 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11241 jtab = setNextItem (IC_JTLABELS (ic)))
11242 emitcode (".db", "%05d$", jtab->key + 100);
11244 /* now generate jump table, MSB */
11245 emitLabel (jtabhi);
11246 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11247 jtab = setNextItem (IC_JTLABELS (ic)))
11248 emitcode (".db", "%05d$>>8", jtab->key + 100);
11252 /*-----------------------------------------------------------------*/
11253 /* genCast - gen code for casting */
11254 /*-----------------------------------------------------------------*/
11256 genCast (iCode * ic)
11258 operand *result = IC_RESULT (ic);
11259 sym_link *ctype = operandType (IC_LEFT (ic));
11260 sym_link *rtype = operandType (IC_RIGHT (ic));
11261 operand *right = IC_RIGHT (ic);
11264 D (emitcode (";", "genCast"));
11266 /* if they are equivalent then do nothing */
11267 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11270 aopOp (right, ic, FALSE);
11271 aopOp (result, ic, FALSE);
11273 /* if the result is a bit (and not a bitfield) */
11274 if (IS_BIT (OP_SYMBOL (result)->type))
11276 /* if the right size is a literal then
11277 we know what the value is */
11278 if (AOP_TYPE (right) == AOP_LIT)
11280 if (((int) operandLitValue (right)))
11281 aopPut (result, one, 0);
11283 aopPut (result, zero, 0);
11288 /* the right is also a bit variable */
11289 if (AOP_TYPE (right) == AOP_CRY)
11291 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11292 aopPut (result, "c", 0);
11296 /* we need to or */
11298 aopPut (result, "a", 0);
11302 /* if they are the same size : or less */
11303 if (AOP_SIZE (result) <= AOP_SIZE (right))
11306 /* if they are in the same place */
11307 if (sameRegs (AOP (right), AOP (result)))
11310 /* if they in different places then copy */
11311 size = AOP_SIZE (result);
11316 aopGet (right, offset, FALSE, FALSE),
11323 /* if the result is of type pointer */
11324 if (IS_PTR (ctype))
11328 sym_link *type = operandType (right);
11329 sym_link *etype = getSpec (type);
11331 /* pointer to generic pointer */
11332 if (IS_GENPTR (ctype))
11336 p_type = DCL_TYPE (type);
11340 if (SPEC_SCLS(etype)==S_REGISTER) {
11341 // let's assume it is a generic pointer
11344 /* we have to go by the storage class */
11345 p_type = PTR_TYPE (SPEC_OCLS (etype));
11349 /* the first two bytes are known */
11350 size = GPTRSIZE - 1;
11355 aopGet (right, offset, FALSE, FALSE),
11359 /* the last byte depending on type */
11361 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11366 // pointerTypeToGPByte will have bitched.
11370 sprintf(gpValStr, "#0x%x", gpVal);
11371 aopPut (result, gpValStr, GPTRSIZE - 1);
11376 /* just copy the pointers */
11377 size = AOP_SIZE (result);
11382 aopGet (right, offset, FALSE, FALSE),
11389 /* so we now know that the size of destination is greater
11390 than the size of the source */
11391 /* we move to result for the size of source */
11392 size = AOP_SIZE (right);
11397 aopGet (right, offset, FALSE, FALSE),
11402 /* now depending on the sign of the source && destination */
11403 size = AOP_SIZE (result) - AOP_SIZE (right);
11404 /* if unsigned or not an integral type */
11405 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11408 aopPut (result, zero, offset++);
11412 /* we need to extend the sign :{ */
11413 char *l = aopGet (right, AOP_SIZE (right) - 1,
11416 emitcode ("rlc", "a");
11417 emitcode ("subb", "a,acc");
11419 aopPut (result, "a", offset++);
11422 /* we are done hurray !!!! */
11425 freeAsmop (result, NULL, ic, TRUE);
11426 freeAsmop (right, NULL, ic, TRUE);
11429 /*-----------------------------------------------------------------*/
11430 /* genDjnz - generate decrement & jump if not zero instrucion */
11431 /*-----------------------------------------------------------------*/
11433 genDjnz (iCode * ic, iCode * ifx)
11435 symbol *lbl, *lbl1;
11439 /* if the if condition has a false label
11440 then we cannot save */
11441 if (IC_FALSE (ifx))
11444 /* if the minus is not of the form a = a - 1 */
11445 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11446 !IS_OP_LITERAL (IC_RIGHT (ic)))
11449 if (operandLitValue (IC_RIGHT (ic)) != 1)
11452 /* if the size of this greater than one then no
11454 if (getSize (operandType (IC_RESULT (ic))) > 1)
11457 /* otherwise we can save BIG */
11459 D (emitcode (";", "genDjnz"));
11461 lbl = newiTempLabel (NULL);
11462 lbl1 = newiTempLabel (NULL);
11464 aopOp (IC_RESULT (ic), ic, FALSE);
11466 if (AOP_NEEDSACC(IC_RESULT(ic)))
11468 /* If the result is accessed indirectly via
11469 * the accumulator, we must explicitly write
11470 * it back after the decrement.
11472 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11474 if (strcmp(rByte, "a"))
11476 /* Something is hopelessly wrong */
11477 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11478 __FILE__, __LINE__);
11479 /* We can just give up; the generated code will be inefficient,
11480 * but what the hey.
11482 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11485 emitcode ("dec", "%s", rByte);
11486 aopPut (IC_RESULT (ic), rByte, 0);
11487 emitcode ("jnz", "%05d$", lbl->key + 100);
11489 else if (IS_AOP_PREG (IC_RESULT (ic)))
11491 emitcode ("dec", "%s",
11492 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11493 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11494 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11495 ifx->generated = 1;
11496 emitcode ("jnz", "%05d$", lbl->key + 100);
11500 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11503 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11505 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11508 if (!ifx->generated)
11509 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11510 ifx->generated = 1;
11514 /*-----------------------------------------------------------------*/
11515 /* genReceive - generate code for a receive iCode */
11516 /*-----------------------------------------------------------------*/
11518 genReceive (iCode * ic)
11520 int size = getSize (operandType (IC_RESULT (ic)));
11523 D (emitcode (";", "genReceive"));
11525 if (ic->argreg == 1)
11526 { /* first parameter */
11527 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11528 isOperandInPagedSpace (IC_RESULT (ic))) &&
11529 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11530 IS_TRUE_SYMOP (IC_RESULT (ic))))
11533 int receivingA = 0;
11536 for (offset = 0; offset<size; offset++)
11537 if (!strcmp (fReturn[offset], "a"))
11542 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11544 for (offset = size-1; offset>0; offset--)
11545 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11546 emitcode("mov","a,%s", fReturn[0]);
11548 aopOp (IC_RESULT (ic), ic, FALSE);
11550 aopPut (IC_RESULT (ic), "a", offset);
11551 for (offset = 1; offset<size; offset++)
11552 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11558 if (getTempRegs(tempRegs, size, ic))
11560 for (offset = 0; offset<size; offset++)
11561 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11562 aopOp (IC_RESULT (ic), ic, FALSE);
11563 for (offset = 0; offset<size; offset++)
11564 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11569 offset = fReturnSizeMCS51 - size;
11572 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11573 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11576 aopOp (IC_RESULT (ic), ic, FALSE);
11577 size = AOP_SIZE (IC_RESULT (ic));
11581 emitcode ("pop", "acc");
11582 aopPut (IC_RESULT (ic), "a", offset++);
11588 aopOp (IC_RESULT (ic), ic, FALSE);
11590 assignResultValue (IC_RESULT (ic), NULL);
11593 else if (ic->argreg > 12)
11594 { /* bit parameters */
11595 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11597 aopOp (IC_RESULT (ic), ic, FALSE);
11598 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11599 outBitC(IC_RESULT (ic));
11603 { /* other parameters */
11605 aopOp (IC_RESULT (ic), ic, FALSE);
11606 rb1off = ic->argreg;
11609 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11617 /*-----------------------------------------------------------------*/
11618 /* genDummyRead - generate code for dummy read of volatiles */
11619 /*-----------------------------------------------------------------*/
11621 genDummyRead (iCode * ic)
11626 D (emitcode(";", "genDummyRead"));
11628 op = IC_RIGHT (ic);
11629 if (op && IS_SYMOP (op))
11631 aopOp (op, ic, FALSE);
11633 /* if the result is a bit */
11634 if (AOP_TYPE (op) == AOP_CRY)
11635 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11638 /* bit variables done */
11640 size = AOP_SIZE (op);
11644 MOVA (aopGet (op, offset, FALSE, FALSE));
11649 freeAsmop (op, NULL, ic, TRUE);
11653 if (op && IS_SYMOP (op))
11655 aopOp (op, ic, FALSE);
11657 /* if the result is a bit */
11658 if (AOP_TYPE (op) == AOP_CRY)
11659 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11662 /* bit variables done */
11664 size = AOP_SIZE (op);
11668 MOVA (aopGet (op, offset, FALSE, FALSE));
11673 freeAsmop (op, NULL, ic, TRUE);
11677 /*-----------------------------------------------------------------*/
11678 /* genCritical - generate code for start of a critical sequence */
11679 /*-----------------------------------------------------------------*/
11681 genCritical (iCode *ic)
11683 symbol *tlbl = newiTempLabel (NULL);
11685 D (emitcode(";", "genCritical"));
11687 if (IC_RESULT (ic))
11689 aopOp (IC_RESULT (ic), ic, TRUE);
11690 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11691 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11692 aopPut (IC_RESULT (ic), zero, 0);
11694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11698 emitcode ("setb", "c");
11699 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11700 emitcode ("clr", "c");
11702 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11706 /*-----------------------------------------------------------------*/
11707 /* genEndCritical - generate code for end of a critical sequence */
11708 /*-----------------------------------------------------------------*/
11710 genEndCritical (iCode *ic)
11712 D(emitcode("; genEndCritical",""));
11716 aopOp (IC_RIGHT (ic), ic, FALSE);
11717 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11719 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11720 emitcode ("mov", "ea,c");
11724 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11725 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11726 emitcode ("rrc", "a");
11727 emitcode ("mov", "ea,c");
11729 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11733 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11734 emitcode ("mov", "ea,c");
11738 /*-----------------------------------------------------------------*/
11739 /* gen51Code - generate code for 8051 based controllers */
11740 /*-----------------------------------------------------------------*/
11742 gen51Code (iCode * lic)
11746 /* int cseq = 0; */
11748 _G.currentFunc = NULL;
11749 lineHead = lineCurr = NULL;
11751 /* print the allocation information */
11752 if (allocInfo && currFunc)
11753 printAllocInfo (currFunc, codeOutBuf);
11754 /* if debug information required */
11755 if (options.debug && currFunc)
11757 debugFile->writeFunction (currFunc, lic);
11759 /* stack pointer name */
11760 if (options.useXstack)
11766 for (ic = lic; ic; ic = ic->next)
11768 _G.current_iCode = ic;
11770 if (ic->lineno && cln != ic->lineno)
11774 debugFile->writeCLine (ic);
11776 if (!options.noCcodeInAsm) {
11777 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11778 printCLine(ic->filename, ic->lineno));
11783 if (ic->seqPoint && ic->seqPoint != cseq)
11785 emitcode ("", "; sequence point %d", ic->seqPoint);
11786 cseq = ic->seqPoint;
11789 if (options.iCodeInAsm) {
11790 char regsInUse[80];
11795 for (i=0; i<8; i++) {
11796 sprintf (®sInUse[i],
11797 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11800 strcpy (regsInUse, "--------");
11801 for (i=0; i < 8; i++) {
11802 if (bitVectBitValue (ic->rMask, i))
11804 int offset = regs8051[i].offset;
11805 regsInUse[offset] = offset + '0'; /* show rMask */
11809 iLine = printILine(ic);
11810 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11813 /* if the result is marked as
11814 spilt and rematerializable or code for
11815 this has already been generated then
11817 if (resultRemat (ic) || ic->generated)
11820 /* depending on the operation */
11840 /* IPOP happens only when trying to restore a
11841 spilt live range, if there is an ifx statement
11842 following this pop then the if statement might
11843 be using some of the registers being popped which
11844 would destory the contents of the register so
11845 we need to check for this condition and handle it */
11847 ic->next->op == IFX &&
11848 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11849 genIfx (ic->next, ic);
11867 genEndFunction (ic);
11887 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11904 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11908 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11915 /* note these two are xlated by algebraic equivalence
11916 in decorateType() in SDCCast.c */
11917 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11918 "got '>=' or '<=' shouldn't have come here");
11922 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11934 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11938 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11942 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11978 genRightShift (ic);
11981 case GET_VALUE_AT_ADDRESS:
11983 hasInc (IC_LEFT (ic), ic,
11984 getSize (operandType (IC_RESULT (ic)))),
11985 ifxForOp (IC_RESULT (ic), ic) );
11989 if (POINTER_SET (ic))
11991 hasInc (IC_RESULT (ic), ic,
11992 getSize (operandType (IC_RIGHT (ic)))));
12018 addSet (&_G.sendSet, ic);
12021 case DUMMY_READ_VOLATILE:
12030 genEndCritical (ic);
12042 _G.current_iCode = NULL;
12044 /* now we are ready to call the
12045 peep hole optimizer */
12046 if (!options.nopeep)
12047 peepHole (&lineHead);
12049 /* now do the actual printing */
12050 printLine (lineHead, codeOutBuf);