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"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
122 static void saveRBank (int, iCode *, bool);
124 #define RESULTONSTACK(x) \
125 (IC_RESULT(x) && IC_RESULT(x)->aop && \
126 IC_RESULT(x)->aop->type == AOP_STK )
128 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
129 #define MOVB(x) movb(x)
131 #define CLRC emitcode("clr","c")
132 #define SETC emitcode("setb","c")
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139 0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142 0x07, 0x03, 0x01, 0x00};
149 /*-----------------------------------------------------------------*/
150 /* emitcode - writes the code into a file : for now it is simple */
151 /*-----------------------------------------------------------------*/
153 emitcode (const char *inst, const char *fmt,...)
157 const char *lbp, *lb;
159 dbuf_init (&dbuf, INITIAL_INLINEASM);
165 dbuf_append_str (&dbuf, inst);
169 dbuf_append_char (&dbuf, '\t');
170 dbuf_tvprintf (&dbuf, fmt, ap);
175 dbuf_tvprintf (&dbuf, fmt, ap);
178 lbp = lb = dbuf_c_str(&dbuf);
180 while (isspace ((unsigned char)*lbp))
187 lineCurr = (lineCurr ?
188 connectLine (lineCurr, newLineNode (lb)) :
189 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
202 emitLabel (symbol *tlbl)
204 emitcode ("", "%05d$:", tlbl->key + 100);
205 lineCurr->isLabel = 1;
208 /*-----------------------------------------------------------------*/
209 /* mcs51_emitDebuggerSymbol - associate the current code location */
210 /* with a debugger symbol */
211 /*-----------------------------------------------------------------*/
213 mcs51_emitDebuggerSymbol (char * debugSym)
216 emitcode ("", "%s ==.", debugSym);
220 /*-----------------------------------------------------------------*/
221 /* mova - moves specified value into accumulator */
222 /*-----------------------------------------------------------------*/
226 /* do some early peephole optimization */
227 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
230 emitcode("mov", "a,%s", x);
233 /*-----------------------------------------------------------------*/
234 /* movb - moves specified value into register b */
235 /*-----------------------------------------------------------------*/
239 /* do some early peephole optimization */
240 if (!strncmp(x, "b", 2))
243 emitcode("mov","b,%s", x);
246 /*-----------------------------------------------------------------*/
247 /* movc - moves specified value into the carry */
248 /*-----------------------------------------------------------------*/
252 if (!strcmp (s, zero))
254 else if (!strcmp (s, one))
256 else if (strcmp (s, "c"))
257 {/* it's not in carry already */
259 /* set C, if a >= 1 */
260 emitcode ("add", "a,#0xff");
264 /*-----------------------------------------------------------------*/
265 /* pushB - saves register B if necessary */
266 /*-----------------------------------------------------------------*/
270 bool pushedB = FALSE;
274 emitcode ("push", "b");
275 // printf("B was in use !\n");
285 /*-----------------------------------------------------------------*/
286 /* popB - restores value of register B if necessary */
287 /*-----------------------------------------------------------------*/
293 emitcode ("pop", "b");
301 /*-----------------------------------------------------------------*/
302 /* pushReg - saves register */
303 /*-----------------------------------------------------------------*/
305 pushReg (int index, bool bits_pushed)
307 regs * reg = REG_WITH_INDEX (index);
308 if (reg->type == REG_BIT)
311 emitcode ("push", "%s", reg->base);
315 emitcode ("push", "%s", reg->dname);
319 /*-----------------------------------------------------------------*/
320 /* popReg - restores register */
321 /*-----------------------------------------------------------------*/
323 popReg (int index, bool bits_popped)
325 regs * reg = REG_WITH_INDEX (index);
326 if (reg->type == REG_BIT)
329 emitcode ("pop", "%s", reg->base);
333 emitcode ("pop", "%s", reg->dname);
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
339 /*-----------------------------------------------------------------*/
341 getFreePtr (iCode * ic, asmop ** aopp, bool result)
346 /* the logic: if r0 & r1 used in the instruction
347 then we are in trouble otherwise */
349 /* first check if r0 & r1 are used by this
350 instruction, in which case we are in trouble */
351 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
352 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
357 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
358 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
360 /* if no usage of r0 then return it */
363 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
364 (*aopp)->type = AOP_R0;
366 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
369 /* if no usage of r1 then return it */
372 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
373 (*aopp)->type = AOP_R1;
375 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
378 /* now we know they both have usage */
379 /* if r0 not used in this instruction */
382 /* push it if not already pushed */
385 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
388 else if (!_G.r0Pushed)
390 emitcode ("push", "%s",
391 REG_WITH_INDEX (R0_IDX)->dname);
395 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
396 (*aopp)->type = AOP_R0;
398 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
401 /* if r1 not used then */
405 /* push it if not already pushed */
408 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
411 else if (!_G.r1Pushed)
413 emitcode ("push", "%s",
414 REG_WITH_INDEX (R1_IDX)->dname);
418 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
419 (*aopp)->type = AOP_R1;
420 return REG_WITH_INDEX (R1_IDX);
424 /* I said end of world, but not quite end of world yet */
425 /* if this is a result then we can push it on the stack */
428 (*aopp)->type = AOP_STK;
431 /* in the case that result AND left AND right needs a pointer reg
432 we can safely use the result's */
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
435 (*aopp)->type = AOP_R0;
436 return REG_WITH_INDEX (R0_IDX);
438 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
440 (*aopp)->type = AOP_R1;
441 return REG_WITH_INDEX (R1_IDX);
444 /* now this is REALLY the end of the world */
445 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
446 "getFreePtr should never reach here");
451 /*-----------------------------------------------------------------*/
452 /* getTempRegs - initialize an array of pointers to GPR registers */
453 /* that are not in use. Returns 1 if the requested */
454 /* number of registers were available, 0 otherwise. */
455 /*-----------------------------------------------------------------*/
457 getTempRegs(regs **tempRegs, int size, iCode *ic)
464 ic = _G.current_iCode;
470 freeRegs = newBitVect(8);
471 bitVectSetBit (freeRegs, R2_IDX);
472 bitVectSetBit (freeRegs, R3_IDX);
473 bitVectSetBit (freeRegs, R4_IDX);
474 bitVectSetBit (freeRegs, R5_IDX);
475 bitVectSetBit (freeRegs, R6_IDX);
476 bitVectSetBit (freeRegs, R7_IDX);
478 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
480 bitVect * newfreeRegs;
481 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
482 freeBitVect(freeRegs);
483 freeRegs = newfreeRegs;
485 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
488 for (i=0; i<freeRegs->size; i++)
490 if (bitVectBitValue(freeRegs,i))
491 tempRegs[offset++] = REG_WITH_INDEX(i);
494 freeBitVect(freeRegs);
499 freeBitVect(freeRegs);
504 /*-----------------------------------------------------------------*/
505 /* newAsmop - creates a new asmOp */
506 /*-----------------------------------------------------------------*/
508 newAsmop (short type)
512 aop = Safe_calloc (1, sizeof (asmop));
518 /*-----------------------------------------------------------------*/
519 /* pointerCode - returns the code for a pointer type */
520 /*-----------------------------------------------------------------*/
522 pointerCode (sym_link * etype)
525 return PTR_TYPE (SPEC_OCLS (etype));
529 /*-----------------------------------------------------------------*/
530 /* leftRightUseAcc - returns size of accumulator use by operands */
531 /*-----------------------------------------------------------------*/
533 leftRightUseAcc(iCode *ic)
542 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
543 "null iCode pointer");
550 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
553 size = getSize (OP_SYMBOL (op)->type);
558 else if (ic->op == JUMPTABLE)
561 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
564 size = getSize (OP_SYMBOL (op)->type);
572 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
575 size = getSize (OP_SYMBOL (op)->type);
580 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
583 size = getSize (OP_SYMBOL (op)->type);
595 /*-----------------------------------------------------------------*/
596 /* aopForSym - for a true symbol */
597 /*-----------------------------------------------------------------*/
599 aopForSym (iCode * ic, symbol * sym, bool result)
603 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
605 wassertl (ic != NULL, "Got a null iCode");
606 wassertl (sym != NULL, "Got a null symbol");
608 space = SPEC_OCLS (sym->etype);
610 /* if already has one */
613 sym->aop->allocated++;
617 /* assign depending on the storage class */
618 /* if it is on the stack or indirectly addressable */
619 /* space we need to assign either r0 or r1 to it */
620 if (sym->onStack || sym->iaccess)
622 sym->aop = aop = newAsmop (0);
623 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
624 aop->size = getSize (sym->type);
626 /* now assign the address of the variable to
627 the pointer register */
628 if (aop->type != AOP_STK)
632 signed char offset = ((sym->stack < 0) ?
633 ((signed char) (sym->stack - _G.nRegsSaved)) :
634 ((signed char) sym->stack)) & 0xff;
636 if ((abs(offset) <= 3) ||
637 (accuse && (abs(offset) <= 7)))
639 emitcode ("mov", "%s,%s",
640 aop->aopu.aop_ptr->name, SYM_BP (sym));
643 emitcode ("dec", aop->aopu.aop_ptr->name);
648 emitcode ("inc", aop->aopu.aop_ptr->name);
655 emitcode ("push", "acc");
656 emitcode ("mov", "a,%s", SYM_BP (sym));
657 emitcode ("add", "a,#0x%02x", offset & 0xff);
658 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
660 emitcode ("pop", "acc");
665 emitcode ("mov", "%s,#%s",
666 aop->aopu.aop_ptr->name,
669 aop->paged = space->paged;
672 aop->aopu.aop_stk = sym->stack;
676 /* if in bit space */
677 if (IN_BITSPACE (space))
679 sym->aop = aop = newAsmop (AOP_CRY);
680 aop->aopu.aop_dir = sym->rname;
681 aop->size = getSize (sym->type);
684 /* if it is in direct space */
685 if (IN_DIRSPACE (space))
687 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
688 //printTypeChainRaw(sym->type, NULL);
689 //printf("space = %s\n", space ? space->sname : "NULL");
690 sym->aop = aop = newAsmop (AOP_DIR);
691 aop->aopu.aop_dir = sym->rname;
692 aop->size = getSize (sym->type);
696 /* special case for a function */
697 if (IS_FUNC (sym->type))
699 sym->aop = aop = newAsmop (AOP_IMMD);
700 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
701 aop->size = getSize (sym->type);
705 /* only remaining is far space */
706 /* in which case DPTR gets the address */
707 sym->aop = aop = newAsmop (AOP_DPTR);
708 emitcode ("mov", "dptr,#%s", sym->rname);
709 aop->size = getSize (sym->type);
711 /* if it is in code space */
712 if (IN_CODESPACE (space))
718 /*-----------------------------------------------------------------*/
719 /* aopForRemat - rematerialzes an object */
720 /*-----------------------------------------------------------------*/
722 aopForRemat (symbol * sym)
724 iCode *ic = sym->rematiCode;
725 asmop *aop = newAsmop (AOP_IMMD);
732 val += (int) operandLitValue (IC_RIGHT (ic));
733 else if (ic->op == '-')
734 val -= (int) operandLitValue (IC_RIGHT (ic));
735 else if (IS_CAST_ICODE(ic)) {
736 sym_link *from_type = operandType(IC_RIGHT(ic));
737 aop->aopu.aop_immd.from_cast_remat = 1;
738 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
739 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
743 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
748 SNPRINTF (buffer, sizeof(buffer),
750 OP_SYMBOL (IC_LEFT (ic))->rname,
751 val >= 0 ? '+' : '-',
756 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
759 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
760 /* set immd2 field if required */
761 if (aop->aopu.aop_immd.from_cast_remat)
763 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
764 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
770 /*-----------------------------------------------------------------*/
771 /* regsInCommon - two operands have some registers in common */
772 /*-----------------------------------------------------------------*/
774 regsInCommon (operand * op1, operand * op2)
779 /* if they have registers in common */
780 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
783 sym1 = OP_SYMBOL (op1);
784 sym2 = OP_SYMBOL (op2);
786 if (sym1->nRegs == 0 || sym2->nRegs == 0)
789 for (i = 0; i < sym1->nRegs; i++)
795 for (j = 0; j < sym2->nRegs; j++)
800 if (sym2->regs[j] == sym1->regs[i])
808 /*-----------------------------------------------------------------*/
809 /* operandsEqu - equivalent */
810 /*-----------------------------------------------------------------*/
812 operandsEqu (operand * op1, operand * op2)
816 /* if they're not symbols */
817 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
820 sym1 = OP_SYMBOL (op1);
821 sym2 = OP_SYMBOL (op2);
823 /* if both are itemps & one is spilt
824 and the other is not then false */
825 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
826 sym1->isspilt != sym2->isspilt)
829 /* if they are the same */
833 /* if they have the same rname */
834 if (sym1->rname[0] && sym2->rname[0] &&
835 strcmp (sym1->rname, sym2->rname) == 0 &&
836 !(IS_PARM (op2) && IS_ITEMP (op1)))
839 /* if left is a tmp & right is not */
840 if (IS_ITEMP (op1) &&
843 (sym1->usl.spillLoc == sym2))
846 if (IS_ITEMP (op2) &&
850 (sym2->usl.spillLoc == sym1))
856 /*-----------------------------------------------------------------*/
857 /* sameByte - two asmops have the same address at given offsets */
858 /*-----------------------------------------------------------------*/
860 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
862 if (aop1 == aop2 && off1 == off2)
865 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
868 if (aop1->type != aop2->type)
871 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
877 /*-----------------------------------------------------------------*/
878 /* sameRegs - two asmops have the same registers */
879 /*-----------------------------------------------------------------*/
881 sameRegs (asmop * aop1, asmop * aop2)
888 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
891 if (aop1->type != aop2->type)
894 if (aop1->size != aop2->size)
897 for (i = 0; i < aop1->size; i++)
898 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
904 /*-----------------------------------------------------------------*/
905 /* aopOp - allocates an asmop for an operand : */
906 /*-----------------------------------------------------------------*/
908 aopOp (operand * op, iCode * ic, bool result)
917 /* if this a literal */
918 if (IS_OP_LITERAL (op))
920 op->aop = aop = newAsmop (AOP_LIT);
921 aop->aopu.aop_lit = op->operand.valOperand;
922 aop->size = getSize (operandType (op));
926 /* if already has a asmop then continue */
929 op->aop->allocated++;
933 /* if the underlying symbol has a aop */
934 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
936 op->aop = OP_SYMBOL (op)->aop;
937 op->aop->allocated++;
941 /* if this is a true symbol */
942 if (IS_TRUE_SYMOP (op))
944 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
948 /* this is a temporary : this has
954 e) can be a return use only */
956 sym = OP_SYMBOL (op);
958 /* if the type is a conditional */
959 if (sym->regType == REG_CND)
961 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
966 /* if it is spilt then two situations
968 b) has a spill location */
969 if (sym->isspilt || sym->nRegs == 0)
972 /* rematerialize it NOW */
975 sym->aop = op->aop = aop = aopForRemat (sym);
976 aop->size = getSize (sym->type);
983 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
984 aop->size = getSize (sym->type);
985 for (i = 0; i < 2; i++)
986 aop->aopu.aop_str[i] = accUse[i];
994 aop = op->aop = sym->aop = newAsmop (AOP_STR);
995 aop->size = getSize (sym->type);
996 for (i = 0; i < fReturnSizeMCS51; i++)
997 aop->aopu.aop_str[i] = fReturn[i];
1001 if (sym->usl.spillLoc)
1003 asmop *oldAsmOp = NULL;
1005 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1007 /* force a new aop if sizes differ */
1008 oldAsmOp = sym->usl.spillLoc->aop;
1009 sym->usl.spillLoc->aop = NULL;
1011 sym->aop = op->aop = aop =
1012 aopForSym (ic, sym->usl.spillLoc, result);
1013 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1015 /* Don't reuse the new aop, go with the last one */
1016 sym->usl.spillLoc->aop = oldAsmOp;
1018 aop->size = getSize (sym->type);
1022 /* else must be a dummy iTemp */
1023 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1024 aop->size = getSize (sym->type);
1028 /* if the type is a bit register */
1029 if (sym->regType == REG_BIT)
1031 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1032 aop->size = sym->nRegs;//1???
1033 aop->aopu.aop_reg[0] = sym->regs[0];
1034 aop->aopu.aop_dir = sym->regs[0]->name;
1038 /* must be in a register */
1039 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1040 aop->size = sym->nRegs;
1041 for (i = 0; i < sym->nRegs; i++)
1042 aop->aopu.aop_reg[i] = sym->regs[i];
1045 /*-----------------------------------------------------------------*/
1046 /* freeAsmop - free up the asmop given to an operand */
1047 /*----------------------------------------------------------------*/
1049 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1066 /* depending on the asmop type only three cases need work
1067 AOP_R0, AOP_R1 & AOP_STK */
1073 emitcode ("mov", "r0,b");
1076 else if (_G.r0Pushed)
1080 emitcode ("pop", "ar0");
1084 bitVectUnSetBit (ic->rUsed, R0_IDX);
1090 emitcode ("mov", "r1,b");
1093 else if (_G.r1Pushed)
1097 emitcode ("pop", "ar1");
1101 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 int stk = aop->aopu.aop_stk + aop->size - 1;
1108 bitVectUnSetBit (ic->rUsed, R0_IDX);
1109 bitVectUnSetBit (ic->rUsed, R1_IDX);
1111 getFreePtr (ic, &aop, FALSE);
1115 emitcode ("mov", "a,_bp");
1116 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1117 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1121 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1126 emitcode ("pop", "acc");
1127 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1130 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 freeAsmop (op, NULL, ic, TRUE);
1136 emitcode ("pop", "ar1");
1141 emitcode ("pop", "ar0");
1149 /* all other cases just dealloc */
1155 OP_SYMBOL (op)->aop = NULL;
1156 /* if the symbol has a spill */
1158 SPIL_LOC (op)->aop = NULL;
1163 /*------------------------------------------------------------------*/
1164 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1165 /* pop r0 or r1 off stack if pushed */
1166 /*------------------------------------------------------------------*/
1168 freeForBranchAsmop (operand * op)
1180 if (!aop->allocated)
1188 emitcode ("mov", "r0,b");
1190 else if (_G.r0Pushed)
1192 emitcode ("pop", "ar0");
1199 emitcode ("mov", "r1,b");
1201 else if (_G.r1Pushed)
1203 emitcode ("pop", "ar1");
1210 int stk = aop->aopu.aop_stk + aop->size - 1;
1212 emitcode ("mov", "b,r0");
1215 emitcode ("mov", "a,_bp");
1216 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1217 emitcode ("mov", "r0,a");
1221 emitcode ("mov", "r0,_bp");
1226 emitcode ("pop", "acc");
1227 emitcode ("mov", "@r0,a");
1230 emitcode ("dec", "r0");
1232 emitcode ("mov", "r0,b");
1238 /*-----------------------------------------------------------------*/
1239 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1240 /* clobber the accumulator */
1241 /*-----------------------------------------------------------------*/
1243 aopGetUsesAcc (operand * oper, int offset)
1245 asmop * aop = AOP (oper);
1247 if (offset > (aop->size - 1))
1265 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1276 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1282 /* Error case --- will have been caught already */
1288 /*-------------------------------------------------------------------*/
1289 /* aopGet - for fetching value of the aop */
1290 /*-------------------------------------------------------------------*/
1292 aopGet (operand * oper, int offset, bool bit16, bool dname)
1294 asmop * aop = AOP (oper);
1296 /* offset is greater than
1298 if (offset > (aop->size - 1) &&
1299 aop->type != AOP_LIT)
1302 /* depending on type */
1310 /* if we need to increment it */
1311 while (offset > aop->coff)
1313 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1317 while (offset < aop->coff)
1319 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1326 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1327 return (dname ? "acc" : "a");
1329 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1330 return Safe_strdup(buffer);
1333 if (aop->code && aop->coff==0 && offset>=1) {
1334 emitcode ("mov", "a,#0x%02x", offset);
1335 emitcode ("movc", "a,@a+dptr");
1336 return (dname ? "acc" : "a");
1339 while (offset > aop->coff)
1341 emitcode ("inc", "dptr");
1345 while (offset < aop->coff)
1347 emitcode ("lcall", "__decdptr");
1354 emitcode ("clr", "a");
1355 emitcode ("movc", "a,@a+dptr");
1359 emitcode ("movx", "a,@dptr");
1361 return (dname ? "acc" : "a");
1364 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "%s",aop->aopu.aop_immd.aop_immd2);
1371 SNPRINTF(buffer, sizeof(buffer),
1372 "#%s", aop->aopu.aop_immd.aop_immd1);
1376 SNPRINTF (buffer, sizeof(buffer),
1378 aop->aopu.aop_immd.aop_immd1,
1383 SNPRINTF (buffer, sizeof(buffer),
1385 aop->aopu.aop_immd.aop_immd1);
1387 return Safe_strdup(buffer);
1390 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1392 SNPRINTF (buffer, sizeof(buffer),
1394 aop->aopu.aop_dir, offset * 8);
1398 SNPRINTF (buffer, sizeof(buffer),
1405 SNPRINTF (buffer, sizeof(buffer),
1410 return Safe_strdup(buffer);
1414 return aop->aopu.aop_reg[offset]->dname;
1416 return aop->aopu.aop_reg[offset]->name;
1419 emitcode ("clr", "a");
1420 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1421 emitcode ("rlc", "a");
1422 return (dname ? "acc" : "a");
1425 if (!offset && dname)
1427 return aop->aopu.aop_str[offset];
1430 return aopLiteral (aop->aopu.aop_lit, offset);
1434 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1438 return aop->aopu.aop_str[offset];
1442 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1443 "aopget got unsupported aop->type");
1447 /*-----------------------------------------------------------------*/
1448 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1449 /* clobber the accumulator */
1450 /*-----------------------------------------------------------------*/
1452 aopPutUsesAcc (operand * oper, const char *s, int offset)
1454 asmop * aop = AOP (oper);
1456 if (offset > (aop->size - 1))
1466 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1472 return ((aop->paged) || (*s == '@'));
1476 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1484 /* Error case --- will have been caught already */
1490 /*-----------------------------------------------------------------*/
1491 /* aopPut - puts a string for a aop and indicates if acc is in use */
1492 /*-----------------------------------------------------------------*/
1494 aopPut (operand * result, const char *s, int offset)
1496 bool bvolatile = isOperandVolatile (result, FALSE);
1497 bool accuse = FALSE;
1498 asmop * aop = AOP (result);
1500 if (aop->size && offset > (aop->size - 1))
1502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503 "aopPut got offset > aop->size");
1507 /* will assign value to value */
1508 /* depending on where it is ofcourse */
1512 MOVA (s); /* read s in case it was volatile */
1517 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1519 SNPRINTF (buffer, sizeof(buffer),
1521 aop->aopu.aop_dir, offset * 8);
1525 SNPRINTF (buffer, sizeof(buffer),
1527 aop->aopu.aop_dir, offset);
1531 SNPRINTF (buffer, sizeof(buffer),
1536 if (strcmp (buffer, s) || bvolatile)
1538 emitcode ("mov", "%s,%s", buffer, s);
1540 if (!strcmp (buffer, "acc"))
1547 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1548 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1551 strcmp (s, "r0") == 0 ||
1552 strcmp (s, "r1") == 0 ||
1553 strcmp (s, "r2") == 0 ||
1554 strcmp (s, "r3") == 0 ||
1555 strcmp (s, "r4") == 0 ||
1556 strcmp (s, "r5") == 0 ||
1557 strcmp (s, "r6") == 0 ||
1558 strcmp (s, "r7") == 0)
1560 emitcode ("mov", "%s,%s",
1561 aop->aopu.aop_reg[offset]->dname, s);
1565 emitcode ("mov", "%s,%s",
1566 aop->aopu.aop_reg[offset]->name, s);
1574 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1575 "aopPut writing to code space");
1579 while (offset > aop->coff)
1582 emitcode ("inc", "dptr");
1585 while (offset < aop->coff)
1588 emitcode ("lcall", "__decdptr");
1593 /* if not in accumulator */
1596 emitcode ("movx", "@dptr,a");
1601 while (offset > aop->coff)
1604 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1606 while (offset < aop->coff)
1609 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1616 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1621 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1623 else if (strcmp (s, "r0") == 0 ||
1624 strcmp (s, "r1") == 0 ||
1625 strcmp (s, "r2") == 0 ||
1626 strcmp (s, "r3") == 0 ||
1627 strcmp (s, "r4") == 0 ||
1628 strcmp (s, "r5") == 0 ||
1629 strcmp (s, "r6") == 0 ||
1630 strcmp (s, "r7") == 0)
1633 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1634 emitcode ("mov", "@%s,%s",
1635 aop->aopu.aop_ptr->name, buffer);
1639 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1644 if (strcmp (s, "a") == 0)
1646 emitcode ("push", "acc");
1651 emitcode ("push", "acc");
1653 else if (strcmp (s, "r0") == 0 ||
1654 strcmp (s, "r1") == 0 ||
1655 strcmp (s, "r2") == 0 ||
1656 strcmp (s, "r3") == 0 ||
1657 strcmp (s, "r4") == 0 ||
1658 strcmp (s, "r5") == 0 ||
1659 strcmp (s, "r6") == 0 ||
1660 strcmp (s, "r7") == 0)
1663 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1664 emitcode ("push", buffer);
1668 emitcode ("push", s);
1674 /* if not bit variable */
1675 if (!aop->aopu.aop_dir)
1677 /* inefficient: move carry into A and use jz/jnz */
1678 emitcode ("clr", "a");
1679 emitcode ("rlc", "a");
1685 emitcode ("clr", "%s", aop->aopu.aop_dir);
1687 emitcode ("setb", "%s", aop->aopu.aop_dir);
1688 else if (!strcmp (s, "c"))
1689 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1690 else if (strcmp (s, aop->aopu.aop_dir))
1693 /* set C, if a >= 1 */
1694 emitcode ("add", "a,#0xff");
1695 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1702 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1703 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1709 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1712 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1713 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1717 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1718 "aopPut got unsupported aop->type");
1727 /*-----------------------------------------------------------------*/
1728 /* pointToEnd :- points to the last byte of the operand */
1729 /*-----------------------------------------------------------------*/
1731 pointToEnd (asmop * aop)
1737 aop->coff = count = (aop->size - 1);
1743 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1747 emitcode ("inc", "dptr");
1754 /*-----------------------------------------------------------------*/
1755 /* reAdjustPreg - points a register back to where it should */
1756 /*-----------------------------------------------------------------*/
1758 reAdjustPreg (asmop * aop)
1760 if ((aop->coff==0) || (aop->size <= 1))
1768 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1773 emitcode ("lcall", "__decdptr");
1780 /*-----------------------------------------------------------------*/
1781 /* opIsGptr: returns non-zero if the passed operand is */
1782 /* a generic pointer type. */
1783 /*-----------------------------------------------------------------*/
1785 opIsGptr (operand * op)
1787 sym_link *type = operandType (op);
1789 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1796 /*-----------------------------------------------------------------*/
1797 /* getDataSize - get the operand data size */
1798 /*-----------------------------------------------------------------*/
1800 getDataSize (operand * op)
1803 size = AOP_SIZE (op);
1804 if (size == GPTRSIZE)
1806 sym_link *type = operandType (op);
1807 if (IS_GENPTR (type))
1809 /* generic pointer; arithmetic operations
1810 * should ignore the high byte (pointer type).
1818 /*-----------------------------------------------------------------*/
1819 /* outAcc - output Acc */
1820 /*-----------------------------------------------------------------*/
1822 outAcc (operand * result)
1825 size = getDataSize (result);
1828 aopPut (result, "a", 0);
1831 /* unsigned or positive */
1834 aopPut (result, zero, offset++);
1839 /*-----------------------------------------------------------------*/
1840 /* outBitC - output a bit C */
1841 /*-----------------------------------------------------------------*/
1843 outBitC (operand * result)
1845 /* if the result is bit */
1846 if (AOP_TYPE (result) == AOP_CRY)
1848 aopPut (result, "c", 0);
1852 emitcode ("clr", "a");
1853 emitcode ("rlc", "a");
1858 /*-----------------------------------------------------------------*/
1859 /* toBoolean - emit code for orl a,operator(sizeop) */
1860 /*-----------------------------------------------------------------*/
1862 toBoolean (operand * oper)
1864 int size = AOP_SIZE (oper) - 1;
1866 bool AccUsed = FALSE;
1869 while (!AccUsed && size--)
1871 AccUsed |= aopGetUsesAcc(oper, offset++);
1874 size = AOP_SIZE (oper) - 1;
1876 MOVA (aopGet (oper, 0, FALSE, FALSE));
1877 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1880 emitcode("mov", "b,a");
1883 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1884 emitcode ("orl", "b,a");
1886 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1887 emitcode ("orl", "a,b");
1894 emitcode ("orl", "a,%s",
1895 aopGet (oper, offset++, FALSE, FALSE));
1901 /*-------------------------------------------------------------------*/
1902 /* xch_a_aopGet - for exchanging acc with value of the aop */
1903 /*-------------------------------------------------------------------*/
1905 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1909 if (aopGetUsesAcc (oper, offset))
1911 emitcode("mov", "b,a");
1912 MOVA (aopGet (oper, offset, bit16, dname));
1913 emitcode("xch", "a,b");
1914 aopPut (oper, "a", offset);
1915 emitcode("xch", "a,b");
1920 l = aopGet (oper, offset, bit16, dname);
1921 emitcode("xch", "a,%s", l);
1927 /*-----------------------------------------------------------------*/
1928 /* genNot - generate code for ! operation */
1929 /*-----------------------------------------------------------------*/
1935 D (emitcode (";", "genNot"));
1937 /* assign asmOps to operand & result */
1938 aopOp (IC_LEFT (ic), ic, FALSE);
1939 aopOp (IC_RESULT (ic), ic, TRUE);
1941 /* if in bit space then a special case */
1942 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1944 /* if left==result then cpl bit */
1945 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1947 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1951 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1952 emitcode ("cpl", "c");
1953 outBitC (IC_RESULT (ic));
1958 toBoolean (IC_LEFT (ic));
1960 /* set C, if a == 0 */
1961 tlbl = newiTempLabel (NULL);
1962 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1964 outBitC (IC_RESULT (ic));
1967 /* release the aops */
1968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1969 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1973 /*-----------------------------------------------------------------*/
1974 /* genCpl - generate code for complement */
1975 /*-----------------------------------------------------------------*/
1982 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1984 D(emitcode (";", "genCpl"));
1986 /* assign asmOps to operand & result */
1987 aopOp (IC_LEFT (ic), ic, FALSE);
1988 aopOp (IC_RESULT (ic), ic, TRUE);
1990 /* special case if in bit space */
1991 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1995 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1996 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1998 /* promotion rules are responsible for this strange result:
1999 bit -> int -> ~int -> bit
2000 uchar -> int -> ~int -> bit
2002 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2006 tlbl=newiTempLabel(NULL);
2007 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2008 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2009 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2010 IS_AOP_PREG (IC_LEFT (ic)))
2012 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2017 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2020 outBitC (IC_RESULT(ic));
2024 size = AOP_SIZE (IC_RESULT (ic));
2027 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2029 emitcode ("cpl", "a");
2030 aopPut (IC_RESULT (ic), "a", offset++);
2035 /* release the aops */
2036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2037 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2040 /*-----------------------------------------------------------------*/
2041 /* genUminusFloat - unary minus for floating points */
2042 /*-----------------------------------------------------------------*/
2044 genUminusFloat (operand * op, operand * result)
2046 int size, offset = 0;
2049 D (emitcode (";", "genUminusFloat"));
2051 /* for this we just copy and then flip the bit */
2053 size = AOP_SIZE (op) - 1;
2058 aopGet (op, offset, FALSE, FALSE),
2063 l = aopGet (op, offset, FALSE, FALSE);
2066 emitcode ("cpl", "acc.7");
2067 aopPut (result, "a", offset);
2070 /*-----------------------------------------------------------------*/
2071 /* genUminus - unary minus code generation */
2072 /*-----------------------------------------------------------------*/
2074 genUminus (iCode * ic)
2079 D (emitcode (";", "genUminus"));
2082 aopOp (IC_LEFT (ic), ic, FALSE);
2083 aopOp (IC_RESULT (ic), ic, TRUE);
2085 /* if both in bit space then special
2087 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2088 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2091 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2092 emitcode ("cpl", "c");
2093 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2097 optype = operandType (IC_LEFT (ic));
2099 /* if float then do float stuff */
2100 if (IS_FLOAT (optype))
2102 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2106 /* otherwise subtract from zero */
2107 size = AOP_SIZE (IC_LEFT (ic));
2111 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2112 if (!strcmp (l, "a"))
2116 emitcode ("cpl", "a");
2117 emitcode ("addc", "a,#0");
2123 emitcode ("clr", "a");
2124 emitcode ("subb", "a,%s", l);
2126 aopPut (IC_RESULT (ic), "a", offset++);
2129 /* if any remaining bytes in the result */
2130 /* we just need to propagate the sign */
2131 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2133 emitcode ("rlc", "a");
2134 emitcode ("subb", "a,acc");
2136 aopPut (IC_RESULT (ic), "a", offset++);
2140 /* release the aops */
2141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2142 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2145 /*-----------------------------------------------------------------*/
2146 /* saveRegisters - will look for a call and save the registers */
2147 /*-----------------------------------------------------------------*/
2149 saveRegisters (iCode * lic)
2156 for (ic = lic; ic; ic = ic->next)
2157 if (ic->op == CALL || ic->op == PCALL)
2162 fprintf (stderr, "found parameter push with no function call\n");
2166 /* if the registers have been saved already or don't need to be then
2170 if (IS_SYMOP(IC_LEFT(ic)) &&
2171 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2172 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2175 /* save the registers in use at this time but skip the
2176 ones for the result */
2177 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2178 mcs51_rUmaskForOp (IC_RESULT(ic)));
2181 if (options.useXstack)
2183 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2184 int nBits = bitVectnBitsOn (rsavebits);
2185 int count = bitVectnBitsOn (rsave);
2189 count = count - nBits + 1;
2190 /* remove all but the first bits as they are pushed all at once */
2191 rsave = bitVectCplAnd (rsave, rsavebits);
2192 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2197 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2198 if (reg->type == REG_BIT)
2200 emitcode ("mov", "a,%s", reg->base);
2204 emitcode ("mov", "a,%s", reg->name);
2206 emitcode ("mov", "r0,%s", spname);
2207 emitcode ("inc", "%s", spname);// allocate before use
2208 emitcode ("movx", "@r0,a");
2209 if (bitVectBitValue (rsave, R0_IDX))
2210 emitcode ("mov", "r0,a");
2212 else if (count != 0)
2214 if (bitVectBitValue (rsave, R0_IDX))
2216 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2218 emitcode ("mov", "r0,%s", spname);
2220 emitcode ("add", "a,#%d", count);
2221 emitcode ("mov", "%s,a", spname);
2222 for (i = 0; i < mcs51_nRegs; i++)
2224 if (bitVectBitValue (rsave, i))
2226 regs * reg = REG_WITH_INDEX (i);
2229 emitcode ("pop", "acc");
2230 emitcode ("push", "acc");
2232 else if (reg->type == REG_BIT)
2234 emitcode ("mov", "a,%s", reg->base);
2238 emitcode ("mov", "a,%s", reg->name);
2240 emitcode ("movx", "@r0,a");
2243 emitcode ("inc", "r0");
2247 if (bitVectBitValue (rsave, R0_IDX))
2249 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2255 bool bits_pushed = FALSE;
2256 for (i = 0; i < mcs51_nRegs; i++)
2258 if (bitVectBitValue (rsave, i))
2260 bits_pushed = pushReg (i, bits_pushed);
2266 /*-----------------------------------------------------------------*/
2267 /* unsaveRegisters - pop the pushed registers */
2268 /*-----------------------------------------------------------------*/
2270 unsaveRegisters (iCode * ic)
2275 /* restore the registers in use at this time but skip the
2276 ones for the result */
2277 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2278 mcs51_rUmaskForOp (IC_RESULT(ic)));
2280 if (options.useXstack)
2282 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2283 int nBits = bitVectnBitsOn (rsavebits);
2284 int count = bitVectnBitsOn (rsave);
2288 count = count - nBits + 1;
2289 /* remove all but the first bits as they are popped all at once */
2290 rsave = bitVectCplAnd (rsave, rsavebits);
2291 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2296 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2297 emitcode ("mov", "r0,%s", spname);
2298 emitcode ("dec", "r0");
2299 emitcode ("movx", "a,@r0");
2300 if (reg->type == REG_BIT)
2302 emitcode ("mov", "%s,a", reg->base);
2306 emitcode ("mov", "%s,a", reg->name);
2308 emitcode ("dec", "%s", spname);
2310 else if (count != 0)
2312 emitcode ("mov", "r0,%s", spname);
2313 for (i = mcs51_nRegs; i >= 0; i--)
2315 if (bitVectBitValue (rsave, i))
2317 regs * reg = REG_WITH_INDEX (i);
2318 emitcode ("dec", "r0");
2319 emitcode ("movx", "a,@r0");
2322 emitcode ("push", "acc");
2324 else if (reg->type == REG_BIT)
2326 emitcode ("mov", "%s,a", reg->base);
2330 emitcode ("mov", "%s,a", reg->name);
2334 emitcode ("mov", "%s,r0", spname);
2335 if (bitVectBitValue (rsave, R0_IDX))
2337 emitcode ("pop", "ar0");
2343 bool bits_popped = FALSE;
2344 for (i = mcs51_nRegs; i >= 0; i--)
2346 if (bitVectBitValue (rsave, i))
2348 bits_popped = popReg (i, bits_popped);
2355 /*-----------------------------------------------------------------*/
2357 /*-----------------------------------------------------------------*/
2359 pushSide (operand * oper, int size)
2364 char *l = aopGet (oper, offset++, FALSE, TRUE);
2365 if (AOP_TYPE (oper) != AOP_REG &&
2366 AOP_TYPE (oper) != AOP_DIR &&
2370 emitcode ("push", "acc");
2374 emitcode ("push", "%s", l);
2379 /*-----------------------------------------------------------------*/
2380 /* assignResultValue - also indicates if acc is in use afterwards */
2381 /*-----------------------------------------------------------------*/
2383 assignResultValue (operand * oper, operand * func)
2386 int size = AOP_SIZE (oper);
2387 bool accuse = FALSE;
2388 bool pushedA = FALSE;
2390 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2396 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2398 emitcode ("push", "acc");
2403 if ((offset == 3) && pushedA)
2404 emitcode ("pop", "acc");
2405 accuse |= aopPut (oper, fReturn[offset], offset);
2412 /*-----------------------------------------------------------------*/
2413 /* genXpush - pushes onto the external stack */
2414 /*-----------------------------------------------------------------*/
2416 genXpush (iCode * ic)
2418 asmop *aop = newAsmop (0);
2420 int size, offset = 0;
2422 D (emitcode (";", "genXpush"));
2424 aopOp (IC_LEFT (ic), ic, FALSE);
2425 r = getFreePtr (ic, &aop, FALSE);
2427 size = AOP_SIZE (IC_LEFT (ic));
2431 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2432 emitcode ("mov", "%s,%s", r->name, spname);
2433 emitcode ("inc", "%s", spname); // allocate space first
2434 emitcode ("movx", "@%s,a", r->name);
2438 // allocate space first
2439 emitcode ("mov", "%s,%s", r->name, spname);
2441 emitcode ("add", "a,#%d", size);
2442 emitcode ("mov", "%s,a", spname);
2446 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2447 emitcode ("movx", "@%s,a", r->name);
2448 emitcode ("inc", "%s", r->name);
2452 freeAsmop (NULL, aop, ic, TRUE);
2453 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2456 /*-----------------------------------------------------------------*/
2457 /* genIpush - generate code for pushing this gets a little complex */
2458 /*-----------------------------------------------------------------*/
2460 genIpush (iCode * ic)
2462 int size, offset = 0;
2466 D (emitcode (";", "genIpush"));
2468 /* if this is not a parm push : ie. it is spill push
2469 and spill push is always done on the local stack */
2473 /* and the item is spilt then do nothing */
2474 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2477 aopOp (IC_LEFT (ic), ic, FALSE);
2478 size = AOP_SIZE (IC_LEFT (ic));
2479 /* push it on the stack */
2482 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2488 emitcode ("push", "%s", l);
2493 /* this is a parameter push: in this case we call
2494 the routine to find the call and save those
2495 registers that need to be saved */
2498 /* if use external stack then call the external
2499 stack pushing routine */
2500 if (options.useXstack)
2506 /* then do the push */
2507 aopOp (IC_LEFT (ic), ic, FALSE);
2509 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2515 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2516 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2518 if (strcmp (l, prev) || *l == '@')
2520 emitcode ("push", "acc");
2524 emitcode ("push", "%s", l);
2529 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2532 /*-----------------------------------------------------------------*/
2533 /* genIpop - recover the registers: can happen only for spilling */
2534 /*-----------------------------------------------------------------*/
2536 genIpop (iCode * ic)
2540 D (emitcode (";", "genIpop"));
2542 /* if the temp was not pushed then */
2543 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2546 aopOp (IC_LEFT (ic), ic, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2548 offset = (size - 1);
2551 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2555 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2558 /*-----------------------------------------------------------------*/
2559 /* saveRBank - saves an entire register bank on the stack */
2560 /*-----------------------------------------------------------------*/
2562 saveRBank (int bank, iCode * ic, bool pushPsw)
2565 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2569 if (options.useXstack)
2573 /* Assume r0 is available for use. */
2574 r = REG_WITH_INDEX (R0_IDX);;
2579 r = getFreePtr (ic, &aop, FALSE);
2581 // allocate space first
2582 emitcode ("mov", "%s,%s", r->name, spname);
2584 emitcode ("add", "a,#%d", count);
2585 emitcode ("mov", "%s,a", spname);
2588 for (i = 0; i < 8; i++)
2590 if (options.useXstack)
2592 emitcode ("mov", "a,(%s+%d)",
2593 regs8051[i].base, 8 * bank + regs8051[i].offset);
2594 emitcode ("movx", "@%s,a", r->name);
2596 emitcode ("inc", "%s", r->name);
2599 emitcode ("push", "(%s+%d)",
2600 regs8051[i].base, 8 * bank + regs8051[i].offset);
2603 if (mcs51_nRegs > 8)
2605 if (options.useXstack)
2607 emitcode ("mov", "a,bits");
2608 emitcode ("movx", "@%s,a", r->name);
2610 emitcode ("inc", "%s", r->name);
2614 emitcode ("push", "bits");
2621 if (options.useXstack)
2623 emitcode ("mov", "a,psw");
2624 emitcode ("movx", "@%s,a", r->name);
2628 emitcode ("push", "psw");
2631 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2636 freeAsmop (NULL, aop, ic, TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* unsaveRBank - restores the register bank from stack */
2647 /*-----------------------------------------------------------------*/
2649 unsaveRBank (int bank, iCode * ic, bool popPsw)
2655 if (options.useXstack)
2659 /* Assume r0 is available for use. */
2660 r = REG_WITH_INDEX (R0_IDX);;
2665 r = getFreePtr (ic, &aop, FALSE);
2667 emitcode ("mov", "%s,%s", r->name, spname);
2672 if (options.useXstack)
2674 emitcode ("dec", "%s", r->name);
2675 emitcode ("movx", "a,@%s", r->name);
2676 emitcode ("mov", "psw,a");
2680 emitcode ("pop", "psw");
2684 if (mcs51_nRegs > 8)
2686 if (options.useXstack)
2688 emitcode ("dec", "%s", r->name);
2689 emitcode ("movx", "a,@%s", r->name);
2690 emitcode ("mov", "bits,a");
2694 emitcode ("pop", "bits");
2698 for (i = 7; i >= 0; i--)
2700 if (options.useXstack)
2702 emitcode ("dec", "%s", r->name);
2703 emitcode ("movx", "a,@%s", r->name);
2704 emitcode ("mov", "(%s+%d),a",
2705 regs8051[i].base, 8 * bank + regs8051[i].offset);
2709 emitcode ("pop", "(%s+%d)",
2710 regs8051[i].base, 8 * bank + regs8051[i].offset);
2714 if (options.useXstack)
2716 emitcode ("mov", "%s,%s", spname, r->name);
2721 freeAsmop (NULL, aop, ic, TRUE);
2725 /*-----------------------------------------------------------------*/
2726 /* genSend - gen code for SEND */
2727 /*-----------------------------------------------------------------*/
2728 static void genSend(set *sendSet)
2733 /* first we do all bit parameters */
2734 for (sic = setFirstItem (sendSet); sic;
2735 sic = setNextItem (sendSet))
2737 if (sic->argreg > 12)
2739 int bit = sic->argreg-13;
2741 aopOp (IC_LEFT (sic), sic, FALSE);
2743 /* if left is a literal then
2744 we know what the value is */
2745 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2747 if (((int) operandLitValue (IC_LEFT (sic))))
2748 emitcode ("setb", "b[%d]", bit);
2750 emitcode ("clr", "b[%d]", bit);
2752 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2754 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2755 if (strcmp (l, "c"))
2756 emitcode ("mov", "c,%s", l);
2757 emitcode ("mov", "b[%d],c", bit);
2762 toBoolean (IC_LEFT (sic));
2763 /* set C, if a >= 1 */
2764 emitcode ("add", "a,#0xff");
2765 emitcode ("mov", "b[%d],c", bit);
2770 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2776 saveRegisters (setFirstItem (sendSet));
2777 emitcode ("mov", "bits,b");
2780 /* then we do all other parameters */
2781 for (sic = setFirstItem (sendSet); sic;
2782 sic = setNextItem (sendSet))
2784 if (sic->argreg <= 12)
2786 int size, offset = 0;
2787 aopOp (IC_LEFT (sic), sic, FALSE);
2788 size = AOP_SIZE (IC_LEFT (sic));
2790 if (sic->argreg == 1)
2794 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2795 if (strcmp (l, fReturn[offset]))
2797 emitcode ("mov", "%s,%s", fReturn[offset], l);
2806 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2807 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2811 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2816 /*-----------------------------------------------------------------*/
2817 /* selectRegBank - emit code to select the register bank */
2818 /*-----------------------------------------------------------------*/
2820 selectRegBank (short bank, bool keepFlags)
2822 /* if f.e. result is in carry */
2825 emitcode ("anl", "psw,#0xE7");
2827 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2831 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2835 /*-----------------------------------------------------------------*/
2836 /* genCall - generates a call statement */
2837 /*-----------------------------------------------------------------*/
2839 genCall (iCode * ic)
2843 // bool restoreBank = FALSE;
2844 bool swapBanks = FALSE;
2845 bool accuse = FALSE;
2846 bool accPushed = FALSE;
2847 bool resultInF0 = FALSE;
2848 bool assignResultGenerated = FALSE;
2850 D (emitcode (";", "genCall"));
2852 dtype = operandType (IC_LEFT (ic));
2853 etype = getSpec(dtype);
2854 /* if send set is not empty then assign */
2857 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2858 genSend(reverseSet(_G.sendSet));
2860 genSend(_G.sendSet);
2865 /* if we are calling a not _naked function that is not using
2866 the same register bank then we need to save the
2867 destination registers on the stack */
2868 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2869 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2870 !IFFUNC_ISISR (dtype))
2875 /* if caller saves & we have not saved then */
2881 emitcode ("mov", "psw,#0x%02x",
2882 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2886 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2888 if (IFFUNC_CALLEESAVES(dtype))
2890 werror (E_BANKED_WITH_CALLEESAVES);
2894 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2895 OP_SYMBOL (IC_LEFT (ic))->rname :
2896 OP_SYMBOL (IC_LEFT (ic))->name);
2898 emitcode ("mov", "r0,#%s", l);
2899 emitcode ("mov", "r1,#(%s >> 8)", l);
2900 emitcode ("mov", "r2,#(%s >> 16)", l);
2901 emitcode ("lcall", "__sdcc_banked_call");
2906 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2907 OP_SYMBOL (IC_LEFT (ic))->rname :
2908 OP_SYMBOL (IC_LEFT (ic))->name));
2913 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2916 /* if we need assign a result value */
2917 if ((IS_ITEMP (IC_RESULT (ic)) &&
2918 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2919 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2920 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2921 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2922 IS_TRUE_SYMOP (IC_RESULT (ic)))
2926 aopOp (IC_RESULT (ic), ic, FALSE);
2929 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2930 assignResultGenerated = TRUE;
2932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2935 /* adjust the stack for parameters if required */
2939 if (ic->parmBytes > 3)
2943 emitcode ("push", "acc");
2946 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2947 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2948 !assignResultGenerated)
2950 emitcode ("mov", "F0,c");
2954 emitcode ("mov", "a,%s", spname);
2955 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2956 emitcode ("mov", "%s,a", spname);
2958 /* unsaveRegisters from xstack needs acc, but */
2959 /* unsaveRegisters from stack needs this popped */
2960 if (accPushed && !options.useXstack)
2962 emitcode ("pop", "acc");
2967 for (i = 0; i < ic->parmBytes; i++)
2968 emitcode ("dec", "%s", spname);
2971 /* if we had saved some registers then unsave them */
2972 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2974 if (accuse && !accPushed && options.useXstack)
2976 /* xstack needs acc, but doesn't touch normal stack */
2977 emitcode ("push", "acc");
2980 unsaveRegisters (ic);
2983 // /* if register bank was saved then pop them */
2985 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2987 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2990 emitcode ("mov", "c,F0");
2992 aopOp (IC_RESULT (ic), ic, FALSE);
2993 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2994 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2998 emitcode ("pop", "acc");
3001 /*-----------------------------------------------------------------*/
3002 /* genPcall - generates a call by pointer statement */
3003 /*-----------------------------------------------------------------*/
3005 genPcall (iCode * ic)
3009 symbol *rlbl = newiTempLabel (NULL);
3010 // bool restoreBank=FALSE;
3011 bool swapBanks = FALSE;
3012 bool resultInF0 = FALSE;
3014 D (emitcode (";", "genPcall"));
3016 dtype = operandType (IC_LEFT (ic))->next;
3017 etype = getSpec(dtype);
3018 /* if caller saves & we have not saved then */
3022 /* if we are calling a not _naked function that is not using
3023 the same register bank then we need to save the
3024 destination registers on the stack */
3025 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3026 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3027 !IFFUNC_ISISR (dtype))
3029 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3030 // restoreBank=TRUE;
3032 // need caution message to user here
3035 if (IS_LITERAL(etype))
3037 /* if send set is not empty then assign */
3040 genSend(reverseSet(_G.sendSet));
3046 emitcode ("mov", "psw,#0x%02x",
3047 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3050 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3052 if (IFFUNC_CALLEESAVES(dtype))
3054 werror (E_BANKED_WITH_CALLEESAVES);
3058 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3060 emitcode ("mov", "r0,#%s", l);
3061 emitcode ("mov", "r1,#(%s >> 8)", l);
3062 emitcode ("mov", "r2,#(%s >> 16)", l);
3063 emitcode ("lcall", "__sdcc_banked_call");
3068 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3073 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3075 if (IFFUNC_CALLEESAVES(dtype))
3077 werror (E_BANKED_WITH_CALLEESAVES);
3081 aopOp (IC_LEFT (ic), ic, FALSE);
3085 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3086 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3087 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3091 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3092 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3093 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3094 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3097 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* if send set is not empty then assign */
3102 genSend(reverseSet(_G.sendSet));
3108 emitcode ("mov", "psw,#0x%02x",
3109 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3113 emitcode ("lcall", "__sdcc_banked_call");
3118 /* push the return address on to the stack */
3119 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3120 emitcode ("push", "acc");
3121 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3122 emitcode ("push", "acc");
3124 /* now push the calling address */
3125 aopOp (IC_LEFT (ic), ic, FALSE);
3127 pushSide (IC_LEFT (ic), FPTRSIZE);
3129 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3131 /* if send set is not empty the assign */
3134 genSend(reverseSet(_G.sendSet));
3140 emitcode ("mov", "psw,#0x%02x",
3141 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3145 emitcode ("ret", "");
3151 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3154 /* if we need assign a result value */
3155 if ((IS_ITEMP (IC_RESULT (ic)) &&
3156 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3157 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3158 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3159 IS_TRUE_SYMOP (IC_RESULT (ic)))
3163 aopOp (IC_RESULT (ic), ic, FALSE);
3166 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3171 /* adjust the stack for parameters if required */
3175 if (ic->parmBytes > 3)
3177 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3178 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3180 emitcode ("mov", "F0,c");
3184 emitcode ("mov", "a,%s", spname);
3185 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3186 emitcode ("mov", "%s,a", spname);
3189 for (i = 0; i < ic->parmBytes; i++)
3190 emitcode ("dec", "%s", spname);
3193 // /* if register bank was saved then unsave them */
3195 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3197 /* if we had saved some registers then unsave them */
3198 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3199 unsaveRegisters (ic);
3201 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3204 emitcode ("mov", "c,F0");
3206 aopOp (IC_RESULT (ic), ic, FALSE);
3207 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212 /*-----------------------------------------------------------------*/
3213 /* resultRemat - result is rematerializable */
3214 /*-----------------------------------------------------------------*/
3216 resultRemat (iCode * ic)
3218 if (SKIP_IC (ic) || ic->op == IFX)
3221 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3223 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3224 if (sym->remat && !POINTER_SET (ic))
3231 /*-----------------------------------------------------------------*/
3232 /* inExcludeList - return 1 if the string is in exclude Reg list */
3233 /*-----------------------------------------------------------------*/
3235 regsCmp(void *p1, void *p2)
3237 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3241 inExcludeList (char *s)
3243 const char *p = setFirstItem(options.excludeRegsSet);
3245 if (p == NULL || STRCASECMP(p, "none") == 0)
3249 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3252 /*-----------------------------------------------------------------*/
3253 /* genFunction - generated code for function entry */
3254 /*-----------------------------------------------------------------*/
3256 genFunction (iCode * ic)
3258 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3260 bool switchedPSW = FALSE;
3261 int calleesaves_saved_register = -1;
3262 int stackAdjust = sym->stack;
3263 int accIsFree = sym->recvSize < 4;
3264 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3265 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3268 /* create the function header */
3269 emitcode (";", "-----------------------------------------");
3270 emitcode (";", " function %s", sym->name);
3271 emitcode (";", "-----------------------------------------");
3273 emitcode ("", "%s:", sym->rname);
3274 lineCurr->isLabel = 1;
3275 ftype = operandType (IC_LEFT (ic));
3276 _G.currentFunc = sym;
3278 if (IFFUNC_ISNAKED(ftype))
3280 emitcode(";", "naked function: no prologue.");
3284 /* here we need to generate the equates for the
3285 register bank if required */
3286 if (FUNC_REGBANK (ftype) != rbank)
3290 rbank = FUNC_REGBANK (ftype);
3291 for (i = 0; i < mcs51_nRegs; i++)
3293 if (regs8051[i].type != REG_BIT)
3295 if (strcmp (regs8051[i].base, "0") == 0)
3296 emitcode ("", "%s = 0x%02x",
3298 8 * rbank + regs8051[i].offset);
3300 emitcode ("", "%s = %s + 0x%02x",
3303 8 * rbank + regs8051[i].offset);
3308 /* if this is an interrupt service routine then
3309 save acc, b, dpl, dph */
3310 if (IFFUNC_ISISR (sym->type))
3312 if (!inExcludeList ("acc"))
3313 emitcode ("push", "acc");
3314 if (!inExcludeList ("b"))
3315 emitcode ("push", "b");
3316 if (!inExcludeList ("dpl"))
3317 emitcode ("push", "dpl");
3318 if (!inExcludeList ("dph"))
3319 emitcode ("push", "dph");
3320 /* if this isr has no bank i.e. is going to
3321 run with bank 0 , then we need to save more
3323 if (!FUNC_REGBANK (sym->type))
3327 /* if this function does not call any other
3328 function then we can be economical and
3329 save only those registers that are used */
3330 if (!IFFUNC_HASFCALL(sym->type))
3332 /* if any registers used */
3335 bool bits_pushed = FALSE;
3336 /* save the registers used */
3337 for (i = 0; i < sym->regsUsed->size; i++)
3339 if (bitVectBitValue (sym->regsUsed, i))
3340 bits_pushed = pushReg (i, bits_pushed);
3346 /* this function has a function call. We cannot
3347 determine register usage so we will have to push the
3349 saveRBank (0, ic, FALSE);
3350 if (options.parms_in_bank1) {
3351 for (i=0; i < 8 ; i++ ) {
3352 emitcode ("push","%s",rb1regs[i]);
3359 /* This ISR uses a non-zero bank.
3361 * We assume that the bank is available for our
3364 * However, if this ISR calls a function which uses some
3365 * other bank, we must save that bank entirely.
3367 unsigned long banksToSave = 0;
3369 if (IFFUNC_HASFCALL(sym->type))
3372 #define MAX_REGISTER_BANKS 4
3377 for (i = ic; i; i = i->next)
3379 if (i->op == ENDFUNCTION)
3381 /* we got to the end OK. */
3389 dtype = operandType (IC_LEFT(i));
3391 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3393 /* Mark this bank for saving. */
3394 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3396 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3400 banksToSave |= (1 << FUNC_REGBANK(dtype));
3403 /* And note that we don't need to do it in
3411 /* This is a mess; we have no idea what
3412 * register bank the called function might
3415 * The only thing I can think of to do is
3416 * throw a warning and hope.
3418 werror(W_FUNCPTR_IN_USING_ISR);
3422 if (banksToSave && options.useXstack)
3424 /* Since we aren't passing it an ic,
3425 * saveRBank will assume r0 is available to abuse.
3427 * So switch to our (trashable) bank now, so
3428 * the caller's R0 isn't trashed.
3430 emitcode ("push", "psw");
3431 emitcode ("mov", "psw,#0x%02x",
3432 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3436 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3438 if (banksToSave & (1 << ix))
3440 saveRBank(ix, NULL, FALSE);
3444 // TODO: this needs a closer look
3445 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3448 /* Set the register bank to the desired value if nothing else */
3449 /* has done so yet. */
3452 emitcode ("push", "psw");
3453 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3458 /* This is a non-ISR function. The caller has already switched register */
3459 /* banks, if necessary, so just handle the callee-saves option. */
3461 /* if callee-save to be used for this function
3462 then save the registers being used in this function */
3463 if (IFFUNC_CALLEESAVES(sym->type))
3467 /* if any registers used */
3470 bool bits_pushed = FALSE;
3471 /* save the registers used */
3472 for (i = 0; i < sym->regsUsed->size; i++)
3474 if (bitVectBitValue (sym->regsUsed, i))
3476 /* remember one saved register for later usage */
3477 if (calleesaves_saved_register < 0)
3478 calleesaves_saved_register = i;
3479 bits_pushed = pushReg (i, bits_pushed);
3489 if (options.useXstack)
3491 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3493 emitcode ("mov", "r0,%s", spname);
3494 emitcode ("inc", "%s", spname);
3495 emitcode ("xch", "a,_bpx");
3496 emitcode ("movx", "@r0,a");
3497 emitcode ("inc", "r0");
3498 emitcode ("mov", "a,r0");
3499 emitcode ("xch", "a,_bpx");
3503 emitcode ("push", "_bp"); /* save the callers stack */
3504 emitcode ("mov", "_bp,sp");
3509 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3511 /* set up the stack */
3512 emitcode ("push", "_bp"); /* save the callers stack */
3513 emitcode ("mov", "_bp,sp");
3518 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3519 /* before setting up the stack frame completely. */
3520 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3522 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3526 if (rsym && rsym->regType == REG_CND)
3528 if (rsym && (rsym->accuse || rsym->ruonly))
3530 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3531 rsym = rsym->usl.spillLoc;
3534 /* If the RECEIVE operand immediately spills to the first entry on the */
3535 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3536 /* rather than the usual @r0/r1 machinations. */
3537 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3541 _G.current_iCode = ric;
3542 D(emitcode ("; genReceive",""));
3543 for (ofs=0; ofs < sym->recvSize; ofs++)
3545 if (!strcmp (fReturn[ofs], "a"))
3546 emitcode ("push", "acc");
3548 emitcode ("push", fReturn[ofs]);
3550 stackAdjust -= sym->recvSize;
3553 assert (stackAdjust>=0);
3556 _G.current_iCode = ic;
3560 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3561 /* to free up the accumulator. */
3562 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3566 _G.current_iCode = ric;
3567 D(emitcode ("; genReceive",""));
3568 for (ofs=0; ofs < sym->recvSize; ofs++)
3570 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3572 _G.current_iCode = ic;
3578 /* adjust the stack for the function */
3581 int i = stackAdjust;
3583 werror (W_STACK_OVERFLOW, sym->name);
3585 if (i > 3 && accIsFree)
3587 emitcode ("mov", "a,sp");
3588 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3589 emitcode ("mov", "sp,a");
3593 /* The accumulator is not free, so we will need another register */
3594 /* to clobber. No need to worry about a possible conflict with */
3595 /* the above early RECEIVE optimizations since they would have */
3596 /* freed the accumulator if they were generated. */
3598 if (IFFUNC_CALLEESAVES(sym->type))
3600 /* if it's a callee-saves function we need a saved register */
3601 if (calleesaves_saved_register >= 0)
3603 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3604 emitcode ("mov", "a,sp");
3605 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3606 emitcode ("mov", "sp,a");
3607 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3610 /* do it the hard way */
3612 emitcode ("inc", "sp");
3616 /* not callee-saves, we can clobber r0 */
3617 emitcode ("mov", "r0,a");
3618 emitcode ("mov", "a,sp");
3619 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3620 emitcode ("mov", "sp,a");
3621 emitcode ("mov", "a,r0");
3626 emitcode ("inc", "sp");
3631 char i = ((char) sym->xstack & 0xff);
3633 if (i > 3 && accIsFree)
3635 emitcode ("mov", "a,_spx");
3636 emitcode ("add", "a,#0x%02x", i & 0xff);
3637 emitcode ("mov", "_spx,a");
3641 emitcode ("push", "acc");
3642 emitcode ("mov", "a,_spx");
3643 emitcode ("add", "a,#0x%02x", i & 0xff);
3644 emitcode ("mov", "_spx,a");
3645 emitcode ("pop", "acc");
3650 emitcode ("inc", "_spx");
3654 /* if critical function then turn interrupts off */
3655 if (IFFUNC_ISCRITICAL (ftype))
3657 symbol *tlbl = newiTempLabel (NULL);
3658 emitcode ("setb", "c");
3659 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3660 emitcode ("clr", "c");
3662 emitcode ("push", "psw"); /* save old ea via c in psw */
3666 /*-----------------------------------------------------------------*/
3667 /* genEndFunction - generates epilogue for functions */
3668 /*-----------------------------------------------------------------*/
3670 genEndFunction (iCode * ic)
3672 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3673 lineNode *lnp = lineCurr;
3675 bitVect *regsUsedPrologue;
3676 bitVect *regsUnneeded;
3679 _G.currentFunc = NULL;
3680 if (IFFUNC_ISNAKED(sym->type))
3682 emitcode(";", "naked function: no epilogue.");
3683 if (options.debug && currFunc)
3684 debugFile->writeEndFunction (currFunc, ic, 0);
3688 if (IFFUNC_ISCRITICAL (sym->type))
3690 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3692 emitcode ("rlc", "a"); /* save c in a */
3693 emitcode ("pop", "psw"); /* restore ea via c in psw */
3694 emitcode ("mov", "ea,c");
3695 emitcode ("rrc", "a"); /* restore c from a */
3699 emitcode ("pop", "psw"); /* restore ea via c in psw */
3700 emitcode ("mov", "ea,c");
3704 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3706 if (options.useXstack)
3710 emitcode ("mov", "sp,_bp");
3711 emitcode ("pop", "_bp");
3713 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3715 emitcode ("xch", "a,_bpx");
3716 emitcode ("mov", "r0,a");
3717 emitcode ("dec", "r0");
3718 emitcode ("movx", "a,@r0");
3719 emitcode ("xch", "a,_bpx");
3720 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3723 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3726 emitcode ("mov", "sp,_bp");
3727 emitcode ("pop", "_bp");
3731 /* restore the register bank */
3732 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3734 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3735 || !options.useXstack)
3737 /* Special case of ISR using non-zero bank with useXstack
3740 emitcode ("pop", "psw");
3744 if (IFFUNC_ISISR (sym->type))
3747 /* now we need to restore the registers */
3748 /* if this isr has no bank i.e. is going to
3749 run with bank 0 , then we need to save more
3751 if (!FUNC_REGBANK (sym->type))
3754 /* if this function does not call any other
3755 function then we can be economical and
3756 save only those registers that are used */
3757 if (!IFFUNC_HASFCALL(sym->type))
3759 /* if any registers used */
3762 bool bits_popped = FALSE;
3763 /* save the registers used */
3764 for (i = sym->regsUsed->size; i >= 0; i--)
3766 if (bitVectBitValue (sym->regsUsed, i))
3767 bits_popped = popReg (i, bits_popped);
3773 if (options.parms_in_bank1) {
3774 for (i = 7 ; i >= 0 ; i-- ) {
3775 emitcode ("pop","%s",rb1regs[i]);
3778 /* this function has a function call cannot
3779 determines register usage so we will have to pop the
3781 unsaveRBank (0, ic, FALSE);
3786 /* This ISR uses a non-zero bank.
3788 * Restore any register banks saved by genFunction
3791 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3794 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3796 if (savedBanks & (1 << ix))
3798 unsaveRBank(ix, NULL, FALSE);
3802 if (options.useXstack)
3804 /* Restore bank AFTER calling unsaveRBank,
3805 * since it can trash r0.
3807 emitcode ("pop", "psw");
3811 if (!inExcludeList ("dph"))
3812 emitcode ("pop", "dph");
3813 if (!inExcludeList ("dpl"))
3814 emitcode ("pop", "dpl");
3815 if (!inExcludeList ("b"))
3816 emitcode ("pop", "b");
3817 if (!inExcludeList ("acc"))
3818 emitcode ("pop", "acc");
3820 /* if debug then send end of function */
3821 if (options.debug && currFunc)
3823 debugFile->writeEndFunction (currFunc, ic, 1);
3826 emitcode ("reti", "");
3830 if (IFFUNC_CALLEESAVES(sym->type))
3834 /* if any registers used */
3837 /* save the registers used */
3838 for (i = sym->regsUsed->size; i >= 0; i--)
3840 if (bitVectBitValue (sym->regsUsed, i) ||
3841 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3842 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3845 else if (mcs51_ptrRegReq)
3847 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3848 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3853 /* if debug then send end of function */
3854 if (options.debug && currFunc)
3856 debugFile->writeEndFunction (currFunc, ic, 1);
3859 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3861 emitcode ("ljmp", "__sdcc_banked_ret");
3865 emitcode ("ret", "");
3869 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3872 /* If this was an interrupt handler using bank 0 that called another */
3873 /* function, then all registers must be saved; nothing to optimized. */
3874 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3875 && !FUNC_REGBANK(sym->type))
3878 /* There are no push/pops to optimize if not callee-saves or ISR */
3879 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3882 /* If there were stack parameters, we cannot optimize without also */
3883 /* fixing all of the stack offsets; this is too dificult to consider. */
3884 if (FUNC_HASSTACKPARM(sym->type))
3887 /* Compute the registers actually used */
3888 regsUsed = newBitVect (mcs51_nRegs);
3889 regsUsedPrologue = newBitVect (mcs51_nRegs);
3892 if (lnp->ic && lnp->ic->op == FUNCTION)
3893 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3895 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3897 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3898 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3905 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3906 && !bitVectBitValue (regsUsed, CND_IDX))
3908 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3909 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3910 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3911 bitVectUnSetBit (regsUsed, CND_IDX);
3914 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3916 /* If this was an interrupt handler that called another function */
3917 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3918 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3920 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3921 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3922 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3923 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3924 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3927 /* Remove the unneeded push/pops */
3928 regsUnneeded = newBitVect (mcs51_nRegs);
3931 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3933 if (!strncmp(lnp->line, "push", 4))
3935 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3936 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3938 connectLine (lnp->prev, lnp->next);
3939 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3942 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3944 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3945 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3947 connectLine (lnp->prev, lnp->next);
3948 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3955 for (idx = 0; idx < regsUnneeded->size; idx++)
3956 if (bitVectBitValue (regsUnneeded, idx))
3957 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3959 freeBitVect (regsUnneeded);
3960 freeBitVect (regsUsed);
3961 freeBitVect (regsUsedPrologue);
3964 /*-----------------------------------------------------------------*/
3965 /* genRet - generate code for return statement */
3966 /*-----------------------------------------------------------------*/
3970 int size, offset = 0, pushed = 0;
3972 D (emitcode (";", "genRet"));
3974 /* if we have no return value then
3975 just generate the "ret" */
3979 /* we have something to return then
3980 move the return value into place */
3981 aopOp (IC_LEFT (ic), ic, FALSE);
3982 size = AOP_SIZE (IC_LEFT (ic));
3984 if (IS_BIT(_G.currentFunc->etype))
3986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
3987 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3989 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3996 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3999 l = aopGet (IC_LEFT (ic), offset++,
4001 emitcode ("push", "%s", l);
4006 l = aopGet (IC_LEFT (ic), offset,
4008 if (strcmp (fReturn[offset], l))
4009 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4016 if (strcmp (fReturn[pushed], "a"))
4017 emitcode ("pop", fReturn[pushed]);
4019 emitcode ("pop", "acc");
4022 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4025 /* generate a jump to the return label
4026 if the next is not the return statement */
4027 if (!(ic->next && ic->next->op == LABEL &&
4028 IC_LABEL (ic->next) == returnLabel))
4030 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4034 /*-----------------------------------------------------------------*/
4035 /* genLabel - generates a label */
4036 /*-----------------------------------------------------------------*/
4038 genLabel (iCode * ic)
4040 /* special case never generate */
4041 if (IC_LABEL (ic) == entryLabel)
4044 emitLabel (IC_LABEL (ic));
4047 /*-----------------------------------------------------------------*/
4048 /* genGoto - generates a ljmp */
4049 /*-----------------------------------------------------------------*/
4051 genGoto (iCode * ic)
4053 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4056 /*-----------------------------------------------------------------*/
4057 /* findLabelBackwards: walks back through the iCode chain looking */
4058 /* for the given label. Returns number of iCode instructions */
4059 /* between that label and given ic. */
4060 /* Returns zero if label not found. */
4061 /*-----------------------------------------------------------------*/
4063 findLabelBackwards (iCode * ic, int key)
4072 /* If we have any pushes or pops, we cannot predict the distance.
4073 I don't like this at all, this should be dealt with in the
4075 if (ic->op == IPUSH || ic->op == IPOP) {
4079 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4088 /*-----------------------------------------------------------------*/
4089 /* genPlusIncr :- does addition with increment if possible */
4090 /*-----------------------------------------------------------------*/
4092 genPlusIncr (iCode * ic)
4094 unsigned int icount;
4095 unsigned int size = getDataSize (IC_RESULT (ic));
4097 /* will try to generate an increment */
4098 /* if the right side is not a literal
4100 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4103 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4105 D(emitcode (";","genPlusIncr"));
4107 /* if increment >=16 bits in register or direct space */
4108 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4109 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4110 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4111 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4112 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4120 /* If the next instruction is a goto and the goto target
4121 * is < 10 instructions previous to this, we can generate
4122 * jumps straight to that target.
4124 if (ic->next && ic->next->op == GOTO
4125 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4126 && labelRange <= 10)
4128 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4129 tlbl = IC_LABEL (ic->next);
4134 tlbl = newiTempLabel (NULL);
4137 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4138 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4139 IS_AOP_PREG (IC_RESULT (ic)))
4140 emitcode ("cjne", "%s,#0x00,%05d$",
4141 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4145 emitcode ("clr", "a");
4146 emitcode ("cjne", "a,%s,%05d$",
4147 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4151 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4154 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4155 IS_AOP_PREG (IC_RESULT (ic)))
4156 emitcode ("cjne", "%s,#0x00,%05d$",
4157 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4160 emitcode ("cjne", "a,%s,%05d$",
4161 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4164 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4168 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4169 IS_AOP_PREG (IC_RESULT (ic)))
4170 emitcode ("cjne", "%s,#0x00,%05d$",
4171 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4175 emitcode ("cjne", "a,%s,%05d$",
4176 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4179 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4189 /* if result is dptr */
4190 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4191 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4192 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4193 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4195 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4201 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4204 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4205 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4207 emitcode ("inc", "dptr");
4212 /* if the literal value of the right hand side
4213 is greater than 4 then it is not worth it */
4217 /* if the sizes are greater than 1 then we cannot */
4218 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4219 AOP_SIZE (IC_LEFT (ic)) > 1)
4222 /* we can if the aops of the left & result match or
4223 if they are in registers and the registers are the
4225 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4229 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4230 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4231 aopPut (IC_RESULT (ic), "a", 0);
4237 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4246 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4247 emitcode ("inc", "a");
4248 aopPut (IC_RESULT (ic), "a", 0);
4255 /*-----------------------------------------------------------------*/
4256 /* outBitAcc - output a bit in acc */
4257 /*-----------------------------------------------------------------*/
4259 outBitAcc (operand * result)
4261 symbol *tlbl = newiTempLabel (NULL);
4262 /* if the result is a bit */
4263 if (AOP_TYPE (result) == AOP_CRY)
4265 aopPut (result, "a", 0);
4269 emitcode ("jz", "%05d$", tlbl->key + 100);
4270 emitcode ("mov", "a,%s", one);
4276 /*-----------------------------------------------------------------*/
4277 /* genPlusBits - generates code for addition of two bits */
4278 /*-----------------------------------------------------------------*/
4280 genPlusBits (iCode * ic)
4282 D (emitcode (";", "genPlusBits"));
4284 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4286 symbol *lbl = newiTempLabel (NULL);
4287 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4288 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4289 emitcode ("cpl", "c");
4291 outBitC (IC_RESULT (ic));
4295 emitcode ("clr", "a");
4296 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4297 emitcode ("rlc", "a");
4298 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4299 emitcode ("addc", "a,%s", zero);
4300 outAcc (IC_RESULT (ic));
4305 /* This is the original version of this code.
4307 * This is being kept around for reference,
4308 * because I am not entirely sure I got it right...
4311 adjustArithmeticResult (iCode * ic)
4313 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4314 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4315 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4316 aopPut (IC_RESULT (ic),
4317 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4320 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4321 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4322 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4323 aopPut (IC_RESULT (ic),
4324 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4327 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4328 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4329 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4330 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4331 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4334 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4335 aopPut (IC_RESULT (ic), buffer, 2);
4339 /* This is the pure and virtuous version of this code.
4340 * I'm pretty certain it's right, but not enough to toss the old
4344 adjustArithmeticResult (iCode * ic)
4346 if (opIsGptr (IC_RESULT (ic)) &&
4347 opIsGptr (IC_LEFT (ic)) &&
4348 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4350 aopPut (IC_RESULT (ic),
4351 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4355 if (opIsGptr (IC_RESULT (ic)) &&
4356 opIsGptr (IC_RIGHT (ic)) &&
4357 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4359 aopPut (IC_RESULT (ic),
4360 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4364 if (opIsGptr (IC_RESULT (ic)) &&
4365 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4366 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4367 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4368 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4371 SNPRINTF (buffer, sizeof(buffer),
4372 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4373 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4378 /*-----------------------------------------------------------------*/
4379 /* genPlus - generates code for addition */
4380 /*-----------------------------------------------------------------*/
4382 genPlus (iCode * ic)
4384 int size, offset = 0;
4387 bool swappedLR = FALSE;
4388 operand *leftOp, *rightOp;
4391 D (emitcode (";", "genPlus"));
4393 /* special cases :- */
4395 aopOp (IC_LEFT (ic), ic, FALSE);
4396 aopOp (IC_RIGHT (ic), ic, FALSE);
4397 aopOp (IC_RESULT (ic), ic, TRUE);
4399 /* if literal, literal on the right or
4400 if left requires ACC or right is already
4402 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4403 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4404 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4406 operand *t = IC_RIGHT (ic);
4407 IC_RIGHT (ic) = IC_LEFT (ic);
4412 /* if both left & right are in bit
4414 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4415 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4421 /* if left in bit space & right literal */
4422 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4423 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4425 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4426 /* if result in bit space */
4427 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4429 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4430 emitcode ("cpl", "c");
4431 outBitC (IC_RESULT (ic));
4435 size = getDataSize (IC_RESULT (ic));
4438 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4439 emitcode ("addc", "a,%s", zero);
4440 aopPut (IC_RESULT (ic), "a", offset++);
4446 /* if I can do an increment instead
4447 of add then GOOD for ME */
4448 if (genPlusIncr (ic) == TRUE)
4451 size = getDataSize (IC_RESULT (ic));
4452 leftOp = IC_LEFT(ic);
4453 rightOp = IC_RIGHT(ic);
4456 /* if this is an add for an array access
4457 at a 256 byte boundary */
4459 && AOP_TYPE (op) == AOP_IMMD
4461 && IS_SPEC (OP_SYM_ETYPE (op))
4462 && SPEC_ABSA (OP_SYM_ETYPE (op))
4463 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4466 D(emitcode ("; genPlus aligned array",""));
4467 aopPut (IC_RESULT (ic),
4468 aopGet (rightOp, 0, FALSE, FALSE),
4471 if( 1 == getDataSize (IC_RIGHT (ic)) )
4473 aopPut (IC_RESULT (ic),
4474 aopGet (leftOp, 1, FALSE, FALSE),
4479 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4480 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4481 aopPut (IC_RESULT (ic), "a", 1);
4486 /* if the lower bytes of a literal are zero skip the addition */
4487 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4489 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4490 (skip_bytes+1 < size))
4495 D(emitcode ("; genPlus shortcut",""));
4500 if( offset >= skip_bytes )
4502 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4505 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4507 emitcode("xch", "a,b");
4508 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4509 emitcode (add, "a,b");
4512 else if (aopGetUsesAcc (leftOp, offset))
4514 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4515 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4519 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4520 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4522 aopPut (IC_RESULT (ic), "a", offset);
4523 add = "addc"; /* further adds must propagate carry */
4527 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4528 isOperandVolatile (IC_RESULT (ic), FALSE))
4531 aopPut (IC_RESULT (ic),
4532 aopGet (leftOp, offset, FALSE, FALSE),
4539 adjustArithmeticResult (ic);
4542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4545 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4546 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4550 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4551 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4555 /*-----------------------------------------------------------------*/
4556 /* genMinusDec :- does subtraction with decrement if possible */
4557 /*-----------------------------------------------------------------*/
4559 genMinusDec (iCode * ic)
4561 unsigned int icount;
4562 unsigned int size = getDataSize (IC_RESULT (ic));
4564 /* will try to generate an increment */
4565 /* if the right side is not a literal
4567 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4570 /* if the literal value of the right hand side
4571 is greater than 4 then it is not worth it */
4572 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4575 D (emitcode (";", "genMinusDec"));
4577 /* if decrement >=16 bits in register or direct space */
4578 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4579 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4580 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4581 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4589 /* If the next instruction is a goto and the goto target
4590 * is <= 10 instructions previous to this, we can generate
4591 * jumps straight to that target.
4593 if (ic->next && ic->next->op == GOTO
4594 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4595 && labelRange <= 10)
4597 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4598 tlbl = IC_LABEL (ic->next);
4603 tlbl = newiTempLabel (NULL);
4607 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4608 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4609 IS_AOP_PREG (IC_RESULT (ic)))
4610 emitcode ("cjne", "%s,#0xff,%05d$"
4611 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4615 emitcode ("mov", "a,#0xff");
4616 emitcode ("cjne", "a,%s,%05d$"
4617 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4620 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, 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), MSB16, FALSE, FALSE)
4630 emitcode ("cjne", "a,%s,%05d$"
4631 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4634 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, 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), MSB24, FALSE, FALSE)
4645 emitcode ("cjne", "a,%s,%05d$"
4646 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4649 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4658 /* if the sizes are greater than 1 then we cannot */
4659 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4660 AOP_SIZE (IC_LEFT (ic)) > 1)
4663 /* we can if the aops of the left & result match or
4664 if they are in registers and the registers are the
4666 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4670 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4672 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4677 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4682 emitcode ("dec", "%s", l);
4685 if (AOP_NEEDSACC (IC_RESULT (ic)))
4686 aopPut (IC_RESULT (ic), "a", 0);
4693 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4694 emitcode ("dec", "a");
4695 aopPut (IC_RESULT (ic), "a", 0);
4702 /*-----------------------------------------------------------------*/
4703 /* addSign - complete with sign */
4704 /*-----------------------------------------------------------------*/
4706 addSign (operand * result, int offset, int sign)
4708 int size = (getDataSize (result) - offset);
4713 emitcode ("rlc", "a");
4714 emitcode ("subb", "a,acc");
4717 aopPut (result, "a", offset++);
4724 aopPut (result, zero, offset++);
4730 /*-----------------------------------------------------------------*/
4731 /* genMinusBits - generates code for subtraction of two bits */
4732 /*-----------------------------------------------------------------*/
4734 genMinusBits (iCode * ic)
4736 symbol *lbl = newiTempLabel (NULL);
4738 D (emitcode (";", "genMinusBits"));
4740 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4742 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4743 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4744 emitcode ("cpl", "c");
4746 outBitC (IC_RESULT (ic));
4750 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4751 emitcode ("subb", "a,acc");
4752 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4753 emitcode ("inc", "a");
4755 aopPut (IC_RESULT (ic), "a", 0);
4756 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4760 /*-----------------------------------------------------------------*/
4761 /* genMinus - generates code for subtraction */
4762 /*-----------------------------------------------------------------*/
4764 genMinus (iCode * ic)
4766 int size, offset = 0;
4768 D (emitcode (";", "genMinus"));
4770 aopOp (IC_LEFT (ic), ic, FALSE);
4771 aopOp (IC_RIGHT (ic), ic, FALSE);
4772 aopOp (IC_RESULT (ic), ic, TRUE);
4774 /* special cases :- */
4775 /* if both left & right are in bit space */
4776 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4777 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4783 /* if I can do an decrement instead
4784 of subtract then GOOD for ME */
4785 if (genMinusDec (ic) == TRUE)
4788 size = getDataSize (IC_RESULT (ic));
4790 /* if literal, add a,#-lit, else normal subb */
4791 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4793 unsigned long lit = 0L;
4794 bool useCarry = FALSE;
4796 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4801 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4803 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4804 if (!offset && !size && lit== (unsigned long) -1)
4806 emitcode ("dec", "a");
4810 /* first add without previous c */
4811 emitcode ("add", "a,#0x%02x",
4812 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4817 emitcode ("addc", "a,#0x%02x",
4818 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4820 aopPut (IC_RESULT (ic), "a", offset++);
4824 /* no need to add zeroes */
4825 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4827 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4836 operand *leftOp, *rightOp;
4838 leftOp = IC_LEFT(ic);
4839 rightOp = IC_RIGHT(ic);
4843 if (aopGetUsesAcc(rightOp, offset)) {
4844 if (aopGetUsesAcc(leftOp, offset)) {
4847 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4849 emitcode ("mov", "b,a");
4852 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4853 emitcode ("subb", "a,b");
4856 /* reverse subtraction with 2's complement */
4858 emitcode( "setb", "c");
4860 emitcode( "cpl", "c");
4861 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4862 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4863 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4864 emitcode("cpl", "a");
4865 if (size) /* skip if last byte */
4866 emitcode( "cpl", "c");
4869 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4872 emitcode ("subb", "a,%s",
4873 aopGet(rightOp, offset, FALSE, TRUE));
4876 aopPut (IC_RESULT (ic), "a", offset++);
4880 adjustArithmeticResult (ic);
4883 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4884 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889 /*-----------------------------------------------------------------*/
4890 /* genMultbits :- multiplication of bits */
4891 /*-----------------------------------------------------------------*/
4893 genMultbits (operand * left,
4897 D (emitcode (";", "genMultbits"));
4899 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4900 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4904 /*-----------------------------------------------------------------*/
4905 /* genMultOneByte : 8*8=8/16 bit multiplication */
4906 /*-----------------------------------------------------------------*/
4908 genMultOneByte (operand * left,
4913 int size = AOP_SIZE (result);
4914 bool runtimeSign, compiletimeSign;
4915 bool lUnsigned, rUnsigned, pushedB;
4917 D (emitcode (";", "genMultOneByte"));
4919 if (size < 1 || size > 2)
4921 /* this should never happen */
4922 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4923 AOP_SIZE(result), __FILE__, lineno);
4927 /* (if two literals: the value is computed before) */
4928 /* if one literal, literal on the right */
4929 if (AOP_TYPE (left) == AOP_LIT)
4934 /* emitcode (";", "swapped left and right"); */
4936 /* if no literal, unsigned on the right: shorter code */
4937 if ( AOP_TYPE (right) != AOP_LIT
4938 && SPEC_USIGN (getSpec (operandType (left))))
4945 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4946 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4950 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4951 no need to take care about the signedness! */
4952 || (lUnsigned && rUnsigned))
4954 /* just an unsigned 8 * 8 = 8 multiply
4956 /* emitcode (";","unsigned"); */
4957 /* TODO: check for accumulator clash between left & right aops? */
4959 if (AOP_TYPE (right) == AOP_LIT)
4961 /* moving to accumulator first helps peepholes */
4962 MOVA (aopGet (left, 0, FALSE, FALSE));
4963 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4967 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4968 MOVA (aopGet (left, 0, FALSE, FALSE));
4971 emitcode ("mul", "ab");
4972 aopPut (result, "a", 0);
4974 aopPut (result, "b", 1);
4980 /* we have to do a signed multiply */
4981 /* emitcode (";", "signed"); */
4983 /* now sign adjust for both left & right */
4985 /* let's see what's needed: */
4986 /* apply negative sign during runtime */
4987 runtimeSign = FALSE;
4988 /* negative sign from literals */
4989 compiletimeSign = FALSE;
4993 if (AOP_TYPE(left) == AOP_LIT)
4995 /* signed literal */
4996 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4998 compiletimeSign = TRUE;
5001 /* signed but not literal */
5007 if (AOP_TYPE(right) == AOP_LIT)
5009 /* signed literal */
5010 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5012 compiletimeSign ^= TRUE;
5015 /* signed but not literal */
5019 /* initialize F0, which stores the runtime sign */
5022 if (compiletimeSign)
5023 emitcode ("setb", "F0"); /* set sign flag */
5025 emitcode ("clr", "F0"); /* reset sign flag */
5028 /* save the signs of the operands */
5029 if (AOP_TYPE(right) == AOP_LIT)
5031 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5033 if (!rUnsigned && val < 0)
5034 emitcode ("mov", "b,#0x%02x", -val);
5036 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5038 else /* ! literal */
5040 if (rUnsigned) /* emitcode (";", "signed"); */
5041 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5044 MOVA (aopGet (right, 0, FALSE, FALSE));
5045 lbl = newiTempLabel (NULL);
5046 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5047 emitcode ("cpl", "F0"); /* complement sign flag */
5048 emitcode ("cpl", "a"); /* 2's complement */
5049 emitcode ("inc", "a");
5051 emitcode ("mov", "b,a");
5055 if (AOP_TYPE(left) == AOP_LIT)
5057 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5059 if (!lUnsigned && val < 0)
5060 emitcode ("mov", "a,#0x%02x", -val);
5062 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5064 else /* ! literal */
5066 MOVA (aopGet (left, 0, FALSE, FALSE));
5070 lbl = newiTempLabel (NULL);
5071 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5072 emitcode ("cpl", "F0"); /* complement sign flag */
5073 emitcode ("cpl", "a"); /* 2's complement */
5074 emitcode ("inc", "a");
5079 /* now the multiplication */
5080 emitcode ("mul", "ab");
5081 if (runtimeSign || compiletimeSign)
5083 lbl = newiTempLabel (NULL);
5085 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5086 emitcode ("cpl", "a"); /* lsb 2's complement */
5088 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5091 emitcode ("add", "a,#1"); /* this sets carry flag */
5092 emitcode ("xch", "a,b");
5093 emitcode ("cpl", "a"); /* msb 2's complement */
5094 emitcode ("addc", "a,#0");
5095 emitcode ("xch", "a,b");
5099 aopPut (result, "a", 0);
5101 aopPut (result, "b", 1);
5106 /*-----------------------------------------------------------------*/
5107 /* genMult - generates code for multiplication */
5108 /*-----------------------------------------------------------------*/
5110 genMult (iCode * ic)
5112 operand *left = IC_LEFT (ic);
5113 operand *right = IC_RIGHT (ic);
5114 operand *result = IC_RESULT (ic);
5116 D (emitcode (";", "genMult"));
5118 /* assign the asmops */
5119 aopOp (left, ic, FALSE);
5120 aopOp (right, ic, FALSE);
5121 aopOp (result, ic, TRUE);
5123 /* special cases first */
5125 if (AOP_TYPE (left) == AOP_CRY &&
5126 AOP_TYPE (right) == AOP_CRY)
5128 genMultbits (left, right, result);
5132 /* if both are of size == 1 */
5133 #if 0 // one of them can be a sloc shared with the result
5134 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5136 if (getSize(operandType(left)) == 1 &&
5137 getSize(operandType(right)) == 1)
5140 genMultOneByte (left, right, result);
5144 /* should have been converted to function call */
5145 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5146 getSize(OP_SYMBOL(right)->type));
5150 freeAsmop (result, NULL, ic, TRUE);
5151 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155 /*-----------------------------------------------------------------*/
5156 /* genDivbits :- division of bits */
5157 /*-----------------------------------------------------------------*/
5159 genDivbits (operand * left,
5166 D(emitcode ("; genDivbits",""));
5170 /* the result must be bit */
5171 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5172 l = aopGet (left, 0, FALSE, FALSE);
5176 emitcode ("div", "ab");
5177 emitcode ("rrc", "a");
5181 aopPut (result, "c", 0);
5184 /*-----------------------------------------------------------------*/
5185 /* genDivOneByte : 8 bit division */
5186 /*-----------------------------------------------------------------*/
5188 genDivOneByte (operand * left,
5192 bool lUnsigned, rUnsigned, pushedB;
5193 bool runtimeSign, compiletimeSign;
5194 bool accuse = FALSE;
5195 bool pushedA = FALSE;
5199 D(emitcode ("; genDivOneByte",""));
5201 /* Why is it necessary that genDivOneByte() can return an int result?
5204 volatile unsigned char uc;
5205 volatile signed char sc1, sc2;
5218 In all cases a one byte result would overflow, the following cast to int
5219 would return the wrong result.
5221 Two possible solution:
5222 a) cast operands to int, if ((unsigned) / (signed)) or
5223 ((signed) / (signed))
5224 b) return an 16 bit signed int; this is what we're doing here!
5227 size = AOP_SIZE (result) - 1;
5229 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5230 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5234 /* signed or unsigned */
5235 if (lUnsigned && rUnsigned)
5237 /* unsigned is easy */
5238 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5239 MOVA (aopGet (left, 0, FALSE, FALSE));
5240 emitcode ("div", "ab");
5241 aopPut (result, "a", 0);
5243 aopPut (result, zero, offset++);
5249 /* signed is a little bit more difficult */
5251 /* now sign adjust for both left & right */
5253 /* let's see what's needed: */
5254 /* apply negative sign during runtime */
5255 runtimeSign = FALSE;
5256 /* negative sign from literals */
5257 compiletimeSign = FALSE;
5261 if (AOP_TYPE(left) == AOP_LIT)
5263 /* signed literal */
5264 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5266 compiletimeSign = TRUE;
5269 /* signed but not literal */
5275 if (AOP_TYPE(right) == AOP_LIT)
5277 /* signed literal */
5278 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5280 compiletimeSign ^= TRUE;
5283 /* signed but not literal */
5287 /* initialize F0, which stores the runtime sign */
5290 if (compiletimeSign)
5291 emitcode ("setb", "F0"); /* set sign flag */
5293 emitcode ("clr", "F0"); /* reset sign flag */
5296 /* save the signs of the operands */
5297 if (AOP_TYPE(right) == AOP_LIT)
5299 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5301 if (!rUnsigned && val < 0)
5302 emitcode ("mov", "b,#0x%02x", -val);
5304 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5306 else /* ! literal */
5309 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5312 MOVA (aopGet (right, 0, FALSE, FALSE));
5313 lbl = newiTempLabel (NULL);
5314 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5315 emitcode ("cpl", "F0"); /* complement sign flag */
5316 emitcode ("cpl", "a"); /* 2's complement */
5317 emitcode ("inc", "a");
5319 emitcode ("mov", "b,a");
5323 if (AOP_TYPE(left) == AOP_LIT)
5325 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5327 if (!lUnsigned && val < 0)
5328 emitcode ("mov", "a,#0x%02x", -val);
5330 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5332 else /* ! literal */
5334 MOVA (aopGet (left, 0, FALSE, FALSE));
5338 lbl = newiTempLabel (NULL);
5339 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5340 emitcode ("cpl", "F0"); /* complement sign flag */
5341 emitcode ("cpl", "a"); /* 2's complement */
5342 emitcode ("inc", "a");
5347 /* now the division */
5348 emitcode ("div", "ab");
5350 if (runtimeSign || compiletimeSign)
5352 lbl = newiTempLabel (NULL);
5354 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5355 emitcode ("cpl", "a"); /* lsb 2's complement */
5356 emitcode ("inc", "a");
5359 accuse = aopPut (result, "a", 0);
5362 /* msb is 0x00 or 0xff depending on the sign */
5367 emitcode ("push", "acc");
5370 emitcode ("mov", "c,F0");
5371 emitcode ("subb", "a,acc");
5373 aopPut (result, "a", offset++);
5375 else /* compiletimeSign */
5377 if (aopPutUsesAcc (result, "#0xFF", offset))
5379 emitcode ("push", "acc");
5383 aopPut (result, "#0xff", offset++);
5389 aopPut (result, "a", 0);
5391 aopPut (result, zero, offset++);
5395 emitcode ("pop", "acc");
5399 /*-----------------------------------------------------------------*/
5400 /* genDiv - generates code for division */
5401 /*-----------------------------------------------------------------*/
5405 operand *left = IC_LEFT (ic);
5406 operand *right = IC_RIGHT (ic);
5407 operand *result = IC_RESULT (ic);
5409 D (emitcode (";", "genDiv"));
5411 /* assign the amsops */
5412 aopOp (left, ic, FALSE);
5413 aopOp (right, ic, FALSE);
5414 aopOp (result, ic, TRUE);
5416 /* special cases first */
5418 if (AOP_TYPE (left) == AOP_CRY &&
5419 AOP_TYPE (right) == AOP_CRY)
5421 genDivbits (left, right, result);
5425 /* if both are of size == 1 */
5426 if (AOP_SIZE (left) == 1 &&
5427 AOP_SIZE (right) == 1)
5429 genDivOneByte (left, right, result);
5433 /* should have been converted to function call */
5436 freeAsmop (result, NULL, ic, TRUE);
5437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441 /*-----------------------------------------------------------------*/
5442 /* genModbits :- modulus of bits */
5443 /*-----------------------------------------------------------------*/
5445 genModbits (operand * left,
5452 D (emitcode (";", "genModbits"));
5456 /* the result must be bit */
5457 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5458 l = aopGet (left, 0, FALSE, FALSE);
5462 emitcode ("div", "ab");
5463 emitcode ("mov", "a,b");
5464 emitcode ("rrc", "a");
5468 aopPut (result, "c", 0);
5471 /*-----------------------------------------------------------------*/
5472 /* genModOneByte : 8 bit modulus */
5473 /*-----------------------------------------------------------------*/
5475 genModOneByte (operand * left,
5479 bool lUnsigned, rUnsigned, pushedB;
5480 bool runtimeSign, compiletimeSign;
5484 D (emitcode (";", "genModOneByte"));
5486 size = AOP_SIZE (result) - 1;
5488 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5489 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5491 /* if right is a literal, check it for 2^n */
5492 if (AOP_TYPE(right) == AOP_LIT)
5494 unsigned char val = abs((int) operandLitValue(right));
5495 symbol *lbl2 = NULL;
5499 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5508 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5509 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5510 /* because iCode should have been changed to genAnd */
5511 /* see file "SDCCopt.c", function "convertToFcall()" */
5513 MOVA (aopGet (left, 0, FALSE, FALSE));
5514 emitcode ("mov", "c,acc.7");
5515 emitcode ("anl", "a,#0x%02x", val - 1);
5516 lbl = newiTempLabel (NULL);
5517 emitcode ("jz", "%05d$", (lbl->key + 100));
5518 emitcode ("jnc", "%05d$", (lbl->key + 100));
5519 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5525 aopPut (result, "a", 0);
5527 aopPut (result, "#0xff", offs2++);
5528 lbl2 = newiTempLabel (NULL);
5529 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5532 aopPut (result, "a", 0);
5534 aopPut (result, zero, offset++);
5548 /* signed or unsigned */
5549 if (lUnsigned && rUnsigned)
5551 /* unsigned is easy */
5552 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5553 MOVA (aopGet (left, 0, FALSE, FALSE));
5554 emitcode ("div", "ab");
5555 aopPut (result, "b", 0);
5557 aopPut (result, zero, offset++);
5563 /* signed is a little bit more difficult */
5565 /* now sign adjust for both left & right */
5567 /* modulus: sign of the right operand has no influence on the result! */
5568 if (AOP_TYPE(right) == AOP_LIT)
5570 signed char val = (char) operandLitValue(right);
5572 if (!rUnsigned && val < 0)
5573 emitcode ("mov", "b,#0x%02x", -val);
5575 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5577 else /* not literal */
5580 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5583 MOVA (aopGet (right, 0, FALSE, FALSE));
5584 lbl = newiTempLabel (NULL);
5585 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5586 emitcode ("cpl", "a"); /* 2's complement */
5587 emitcode ("inc", "a");
5589 emitcode ("mov", "b,a");
5593 /* let's see what's needed: */
5594 /* apply negative sign during runtime */
5595 runtimeSign = FALSE;
5596 /* negative sign from literals */
5597 compiletimeSign = FALSE;
5599 /* sign adjust left side */
5600 if (AOP_TYPE(left) == AOP_LIT)
5602 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5604 if (!lUnsigned && val < 0)
5606 compiletimeSign = TRUE; /* set sign flag */
5607 emitcode ("mov", "a,#0x%02x", -val);
5610 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5612 else /* ! literal */
5614 MOVA (aopGet (left, 0, FALSE, FALSE));
5619 emitcode ("clr", "F0"); /* clear sign flag */
5621 lbl = newiTempLabel (NULL);
5622 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5623 emitcode ("setb", "F0"); /* set sign flag */
5624 emitcode ("cpl", "a"); /* 2's complement */
5625 emitcode ("inc", "a");
5630 /* now the modulus */
5631 emitcode ("div", "ab");
5633 if (runtimeSign || compiletimeSign)
5635 emitcode ("mov", "a,b");
5636 lbl = newiTempLabel (NULL);
5638 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5639 emitcode ("cpl", "a"); /* 2's complement */
5640 emitcode ("inc", "a");
5643 aopPut (result, "a", 0);
5646 /* msb is 0x00 or 0xff depending on the sign */
5649 emitcode ("mov", "c,F0");
5650 emitcode ("subb", "a,acc");
5652 aopPut (result, "a", offset++);
5654 else /* compiletimeSign */
5656 aopPut (result, "#0xff", offset++);
5661 aopPut (result, "b", 0);
5663 aopPut (result, zero, offset++);
5669 /*-----------------------------------------------------------------*/
5670 /* genMod - generates code for division */
5671 /*-----------------------------------------------------------------*/
5675 operand *left = IC_LEFT (ic);
5676 operand *right = IC_RIGHT (ic);
5677 operand *result = IC_RESULT (ic);
5679 D (emitcode (";", "genMod"));
5681 /* assign the asmops */
5682 aopOp (left, ic, FALSE);
5683 aopOp (right, ic, FALSE);
5684 aopOp (result, ic, TRUE);
5686 /* special cases first */
5688 if (AOP_TYPE (left) == AOP_CRY &&
5689 AOP_TYPE (right) == AOP_CRY)
5691 genModbits (left, right, result);
5695 /* if both are of size == 1 */
5696 if (AOP_SIZE (left) == 1 &&
5697 AOP_SIZE (right) == 1)
5699 genModOneByte (left, right, result);
5703 /* should have been converted to function call */
5707 freeAsmop (result, NULL, ic, TRUE);
5708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5712 /*-----------------------------------------------------------------*/
5713 /* genIfxJump :- will create a jump depending on the ifx */
5714 /*-----------------------------------------------------------------*/
5716 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5719 symbol *tlbl = newiTempLabel (NULL);
5722 D (emitcode (";", "genIfxJump"));
5724 /* if true label then we jump if condition
5728 jlbl = IC_TRUE (ic);
5729 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5730 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5734 /* false label is present */
5735 jlbl = IC_FALSE (ic);
5736 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5737 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5739 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5740 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5742 emitcode (inst, "%05d$", tlbl->key + 100);
5743 freeForBranchAsmop (result);
5744 freeForBranchAsmop (right);
5745 freeForBranchAsmop (left);
5746 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5749 /* mark the icode as generated */
5753 /*-----------------------------------------------------------------*/
5754 /* genCmp :- greater or less than comparison */
5755 /*-----------------------------------------------------------------*/
5757 genCmp (operand * left, operand * right,
5758 operand * result, iCode * ifx, int sign, iCode *ic)
5760 int size, offset = 0;
5761 unsigned long lit = 0L;
5764 D (emitcode (";", "genCmp"));
5766 /* if left & right are bit variables */
5767 if (AOP_TYPE (left) == AOP_CRY &&
5768 AOP_TYPE (right) == AOP_CRY)
5770 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5771 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5775 /* subtract right from left if at the
5776 end the carry flag is set then we know that
5777 left is greater than right */
5778 size = max (AOP_SIZE (left), AOP_SIZE (right));
5780 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5781 if ((size == 1) && !sign &&
5782 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5784 symbol *lbl = newiTempLabel (NULL);
5785 emitcode ("cjne", "%s,%s,%05d$",
5786 aopGet (left, offset, FALSE, FALSE),
5787 aopGet (right, offset, FALSE, FALSE),
5793 if (AOP_TYPE (right) == AOP_LIT)
5795 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5796 /* optimize if(x < 0) or if(x >= 0) */
5805 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5806 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5808 genIfxJump (ifx, "acc.7", left, right, result);
5809 freeAsmop (right, NULL, ic, TRUE);
5810 freeAsmop (left, NULL, ic, TRUE);
5816 emitcode ("rlc", "a");
5823 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5824 while (size && (bytelit == 0))
5827 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5833 MOVA (aopGet (left, offset, FALSE, FALSE));
5834 if (sign && size == 0)
5836 emitcode ("xrl", "a,#0x80");
5837 emitcode ("subb", "a,#0x%02x",
5838 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5842 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5852 bool pushedB = FALSE;
5853 rightInB = aopGetUsesAcc(right, offset);
5857 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5859 MOVA (aopGet (left, offset, FALSE, FALSE));
5860 if (sign && size == 0)
5862 emitcode ("xrl", "a,#0x80");
5867 MOVB (aopGet (right, offset, FALSE, FALSE));
5869 emitcode ("xrl", "b,#0x80");
5870 emitcode ("subb", "a,b");
5875 emitcode ("subb", "a,b");
5877 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5887 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5889 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5895 /* if the result is used in the next
5896 ifx conditional branch then generate
5897 code a little differently */
5900 genIfxJump (ifx, "c", NULL, NULL, result);
5906 /* leave the result in acc */
5910 /*-----------------------------------------------------------------*/
5911 /* genCmpGt :- greater than comparison */
5912 /*-----------------------------------------------------------------*/
5914 genCmpGt (iCode * ic, iCode * ifx)
5916 operand *left, *right, *result;
5917 sym_link *letype, *retype;
5920 D (emitcode (";", "genCmpGt"));
5922 left = IC_LEFT (ic);
5923 right = IC_RIGHT (ic);
5924 result = IC_RESULT (ic);
5926 letype = getSpec (operandType (left));
5927 retype = getSpec (operandType (right));
5928 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5929 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5930 /* assign the amsops */
5931 aopOp (result, ic, TRUE);
5932 aopOp (left, ic, FALSE);
5933 aopOp (right, ic, FALSE);
5935 genCmp (right, left, result, ifx, sign, ic);
5937 freeAsmop (result, NULL, ic, TRUE);
5940 /*-----------------------------------------------------------------*/
5941 /* genCmpLt - less than comparisons */
5942 /*-----------------------------------------------------------------*/
5944 genCmpLt (iCode * ic, iCode * ifx)
5946 operand *left, *right, *result;
5947 sym_link *letype, *retype;
5950 D (emitcode (";", "genCmpLt"));
5952 left = IC_LEFT (ic);
5953 right = IC_RIGHT (ic);
5954 result = IC_RESULT (ic);
5956 letype = getSpec (operandType (left));
5957 retype = getSpec (operandType (right));
5958 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5959 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5960 /* assign the amsops */
5961 aopOp (result, ic, TRUE);
5962 aopOp (left, ic, FALSE);
5963 aopOp (right, ic, FALSE);
5965 genCmp (left, right, result, ifx, sign, ic);
5967 freeAsmop (result, NULL, ic, TRUE);
5970 /*-----------------------------------------------------------------*/
5971 /* gencjneshort - compare and jump if not equal */
5972 /*-----------------------------------------------------------------*/
5974 gencjneshort (operand * left, operand * right, symbol * lbl)
5976 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5978 unsigned long lit = 0L;
5980 D (emitcode (";", "gencjneshort"));
5982 /* if the left side is a literal or
5983 if the right is in a pointer register and left
5985 if ((AOP_TYPE (left) == AOP_LIT) ||
5986 (AOP_TYPE (left) == AOP_IMMD) ||
5987 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5994 if (AOP_TYPE (right) == AOP_LIT)
5995 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5997 /* if the right side is a literal then anything goes */
5998 if (AOP_TYPE (right) == AOP_LIT &&
5999 AOP_TYPE (left) != AOP_DIR &&
6000 AOP_TYPE (left) != AOP_IMMD)
6004 emitcode ("cjne", "%s,%s,%05d$",
6005 aopGet (left, offset, FALSE, FALSE),
6006 aopGet (right, offset, FALSE, FALSE),
6012 /* if the right side is in a register or in direct space or
6013 if the left is a pointer register & right is not */
6014 else if (AOP_TYPE (right) == AOP_REG ||
6015 AOP_TYPE (right) == AOP_DIR ||
6016 AOP_TYPE (right) == AOP_LIT ||
6017 AOP_TYPE (right) == AOP_IMMD ||
6018 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6019 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6023 MOVA (aopGet (left, offset, FALSE, FALSE));
6024 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6025 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6026 emitcode ("jnz", "%05d$", lbl->key + 100);
6028 emitcode ("cjne", "a,%s,%05d$",
6029 aopGet (right, offset, FALSE, TRUE),
6036 /* right is a pointer reg need both a & b */
6039 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6040 wassertl(!BINUSE, "B was in use");
6041 MOVB (aopGet (left, offset, FALSE, FALSE));
6042 MOVA (aopGet (right, offset, FALSE, FALSE));
6043 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6049 /*-----------------------------------------------------------------*/
6050 /* gencjne - compare and jump if not equal */
6051 /*-----------------------------------------------------------------*/
6053 gencjne (operand * left, operand * right, symbol * lbl)
6055 symbol *tlbl = newiTempLabel (NULL);
6057 D (emitcode (";", "gencjne"));
6059 gencjneshort (left, right, lbl);
6061 emitcode ("mov", "a,%s", one);
6062 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6064 emitcode ("clr", "a");
6068 /*-----------------------------------------------------------------*/
6069 /* genCmpEq - generates code for equal to */
6070 /*-----------------------------------------------------------------*/
6072 genCmpEq (iCode * ic, iCode * ifx)
6074 bool swappedLR = FALSE;
6075 operand *left, *right, *result;
6077 D (emitcode (";", "genCmpEq"));
6079 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6080 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6081 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6083 /* if literal, literal on the right or
6084 if the right is in a pointer register and left
6086 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6087 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6089 operand *t = IC_RIGHT (ic);
6090 IC_RIGHT (ic) = IC_LEFT (ic);
6095 if (ifx && !AOP_SIZE (result))
6098 /* if they are both bit variables */
6099 if (AOP_TYPE (left) == AOP_CRY &&
6100 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6102 if (AOP_TYPE (right) == AOP_LIT)
6104 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6107 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6108 emitcode ("cpl", "c");
6112 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6116 emitcode ("clr", "c");
6118 /* AOP_TYPE(right) == AOP_CRY */
6122 symbol *lbl = newiTempLabel (NULL);
6123 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6124 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6125 emitcode ("cpl", "c");
6128 /* if true label then we jump if condition
6130 tlbl = newiTempLabel (NULL);
6133 emitcode ("jnc", "%05d$", tlbl->key + 100);
6134 freeForBranchAsmop (result);
6135 freeForBranchAsmop (right);
6136 freeForBranchAsmop (left);
6137 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6141 emitcode ("jc", "%05d$", tlbl->key + 100);
6142 freeForBranchAsmop (result);
6143 freeForBranchAsmop (right);
6144 freeForBranchAsmop (left);
6145 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6151 tlbl = newiTempLabel (NULL);
6152 gencjneshort (left, right, tlbl);
6155 freeForBranchAsmop (result);
6156 freeForBranchAsmop (right);
6157 freeForBranchAsmop (left);
6158 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6163 symbol *lbl = newiTempLabel (NULL);
6164 emitcode ("sjmp", "%05d$", lbl->key + 100);
6166 freeForBranchAsmop (result);
6167 freeForBranchAsmop (right);
6168 freeForBranchAsmop (left);
6169 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6173 /* mark the icode as generated */
6178 /* if they are both bit variables */
6179 if (AOP_TYPE (left) == AOP_CRY &&
6180 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6182 if (AOP_TYPE (right) == AOP_LIT)
6184 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6187 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6188 emitcode ("cpl", "c");
6192 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6196 emitcode ("clr", "c");
6198 /* AOP_TYPE(right) == AOP_CRY */
6202 symbol *lbl = newiTempLabel (NULL);
6203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6204 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6205 emitcode ("cpl", "c");
6209 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6216 genIfxJump (ifx, "c", left, right, result);
6219 /* if the result is used in an arithmetic operation
6220 then put the result in place */
6225 gencjne (left, right, newiTempLabel (NULL));
6226 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6228 aopPut (result, "a", 0);
6233 genIfxJump (ifx, "a", left, right, result);
6236 /* if the result is used in an arithmetic operation
6237 then put the result in place */
6238 if (AOP_TYPE (result) != AOP_CRY)
6240 /* leave the result in acc */
6244 freeAsmop (result, NULL, ic, TRUE);
6247 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6248 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6252 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6253 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6257 /*-----------------------------------------------------------------*/
6258 /* ifxForOp - returns the icode containing the ifx for operand */
6259 /*-----------------------------------------------------------------*/
6261 ifxForOp (operand * op, iCode * ic)
6263 /* if true symbol then needs to be assigned */
6264 if (IS_TRUE_SYMOP (op))
6267 /* if this has register type condition and
6268 the next instruction is ifx with the same operand
6269 and live to of the operand is upto the ifx only then */
6271 ic->next->op == IFX &&
6272 IC_COND (ic->next)->key == op->key &&
6273 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6279 /*-----------------------------------------------------------------*/
6280 /* hasInc - operand is incremented before any other use */
6281 /*-----------------------------------------------------------------*/
6283 hasInc (operand *op, iCode *ic, int osize)
6285 sym_link *type = operandType(op);
6286 sym_link *retype = getSpec (type);
6287 iCode *lic = ic->next;
6290 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6291 if (!IS_SYMOP(op)) return NULL;
6293 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6294 if (IS_AGGREGATE(type->next)) return NULL;
6295 if (osize != (isize = getSize(type->next))) return NULL;
6298 /* if operand of the form op = op + <sizeof *op> */
6299 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6300 isOperandEqual(IC_RESULT(lic),op) &&
6301 isOperandLiteral(IC_RIGHT(lic)) &&
6302 operandLitValue(IC_RIGHT(lic)) == isize) {
6305 /* if the operand used or deffed */
6306 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6309 /* if GOTO or IFX */
6310 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6316 /*-----------------------------------------------------------------*/
6317 /* genAndOp - for && operation */
6318 /*-----------------------------------------------------------------*/
6320 genAndOp (iCode * ic)
6322 operand *left, *right, *result;
6325 D (emitcode (";", "genAndOp"));
6327 /* note here that && operations that are in an
6328 if statement are taken away by backPatchLabels
6329 only those used in arthmetic operations remain */
6330 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6331 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6332 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6334 /* if both are bit variables */
6335 if (AOP_TYPE (left) == AOP_CRY &&
6336 AOP_TYPE (right) == AOP_CRY)
6338 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6339 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6344 tlbl = newiTempLabel (NULL);
6346 emitcode ("jz", "%05d$", tlbl->key + 100);
6352 freeAsmop (result, NULL, ic, TRUE);
6353 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6354 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6358 /*-----------------------------------------------------------------*/
6359 /* genOrOp - for || operation */
6360 /*-----------------------------------------------------------------*/
6362 genOrOp (iCode * ic)
6364 operand *left, *right, *result;
6367 D (emitcode (";", "genOrOp"));
6369 /* note here that || operations that are in an
6370 if statement are taken away by backPatchLabels
6371 only those used in arthmetic operations remain */
6372 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6373 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6374 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6376 /* if both are bit variables */
6377 if (AOP_TYPE (left) == AOP_CRY &&
6378 AOP_TYPE (right) == AOP_CRY)
6380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6381 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6386 tlbl = newiTempLabel (NULL);
6388 emitcode ("jnz", "%05d$", tlbl->key + 100);
6394 freeAsmop (result, NULL, ic, TRUE);
6395 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6396 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6399 /*-----------------------------------------------------------------*/
6400 /* isLiteralBit - test if lit == 2^n */
6401 /*-----------------------------------------------------------------*/
6403 isLiteralBit (unsigned long lit)
6405 unsigned long pw[32] =
6406 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6407 0x100L, 0x200L, 0x400L, 0x800L,
6408 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6409 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6410 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6411 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6412 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6415 for (idx = 0; idx < 32; idx++)
6421 /*-----------------------------------------------------------------*/
6422 /* continueIfTrue - */
6423 /*-----------------------------------------------------------------*/
6425 continueIfTrue (iCode * ic)
6428 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6432 /*-----------------------------------------------------------------*/
6434 /*-----------------------------------------------------------------*/
6436 jumpIfTrue (iCode * ic)
6439 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6443 /*-----------------------------------------------------------------*/
6444 /* jmpTrueOrFalse - */
6445 /*-----------------------------------------------------------------*/
6447 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6449 // ugly but optimized by peephole
6452 symbol *nlbl = newiTempLabel (NULL);
6453 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6455 freeForBranchAsmop (result);
6456 freeForBranchAsmop (right);
6457 freeForBranchAsmop (left);
6458 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6463 freeForBranchAsmop (result);
6464 freeForBranchAsmop (right);
6465 freeForBranchAsmop (left);
6466 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6472 /*-----------------------------------------------------------------*/
6473 /* genAnd - code for and */
6474 /*-----------------------------------------------------------------*/
6476 genAnd (iCode * ic, iCode * ifx)
6478 operand *left, *right, *result;
6479 int size, offset = 0;
6480 unsigned long lit = 0L;
6484 D (emitcode (";", "genAnd"));
6486 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6487 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6488 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6491 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6493 AOP_TYPE (left), AOP_TYPE (right));
6494 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6496 AOP_SIZE (left), AOP_SIZE (right));
6499 /* if left is a literal & right is not then exchange them */
6500 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6501 AOP_NEEDSACC (left))
6503 operand *tmp = right;
6508 /* if result = right then exchange left and right */
6509 if (sameRegs (AOP (result), AOP (right)))
6511 operand *tmp = right;
6516 /* if right is bit then exchange them */
6517 if (AOP_TYPE (right) == AOP_CRY &&
6518 AOP_TYPE (left) != AOP_CRY)
6520 operand *tmp = right;
6524 if (AOP_TYPE (right) == AOP_LIT)
6525 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6527 size = AOP_SIZE (result);
6530 // result = bit & yy;
6531 if (AOP_TYPE (left) == AOP_CRY)
6533 // c = bit & literal;
6534 if (AOP_TYPE (right) == AOP_LIT)
6538 if (size && sameRegs (AOP (result), AOP (left)))
6541 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6546 if (size && (AOP_TYPE (result) == AOP_CRY))
6548 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6551 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6556 emitcode ("clr", "c");
6561 if (AOP_TYPE (right) == AOP_CRY)
6564 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6565 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6570 MOVA (aopGet (right, 0, FALSE, FALSE));
6572 emitcode ("rrc", "a");
6573 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6581 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6582 genIfxJump (ifx, "c", left, right, result);
6586 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6587 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6588 if ((AOP_TYPE (right) == AOP_LIT) &&
6589 (AOP_TYPE (result) == AOP_CRY) &&
6590 (AOP_TYPE (left) != AOP_CRY))
6592 int posbit = isLiteralBit (lit);
6597 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6601 switch (posbit & 0x07)
6603 case 0: emitcode ("rrc", "a");
6605 case 7: emitcode ("rlc", "a");
6607 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6616 SNPRINTF (buffer, sizeof(buffer),
6617 "acc.%d", posbit & 0x07);
6618 genIfxJump (ifx, buffer, left, right, result);
6621 {// what is this case? just found it in ds390/gen.c
6622 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6629 symbol *tlbl = newiTempLabel (NULL);
6630 int sizel = AOP_SIZE (left);
6632 emitcode ("setb", "c");
6635 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6637 MOVA (aopGet (left, offset, FALSE, FALSE));
6639 if ((posbit = isLiteralBit (bytelit)) != 0)
6640 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6643 if (bytelit != 0x0FFL)
6644 emitcode ("anl", "a,%s",
6645 aopGet (right, offset, FALSE, TRUE));
6646 emitcode ("jnz", "%05d$", tlbl->key + 100);
6651 // bit = left & literal
6654 emitcode ("clr", "c");
6657 // if(left & literal)
6661 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6671 /* if left is same as result */
6672 if (sameRegs (AOP (result), AOP (left)))
6674 for (; size--; offset++)
6676 if (AOP_TYPE (right) == AOP_LIT)
6678 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6679 if (bytelit == 0x0FF)
6681 /* dummy read of volatile operand */
6682 if (isOperandVolatile (left, FALSE))
6683 MOVA (aopGet (left, offset, FALSE, FALSE));
6687 else if (bytelit == 0)
6689 aopPut (result, zero, offset);
6691 else if (IS_AOP_PREG (result))
6693 MOVA (aopGet (left, offset, FALSE, TRUE));
6694 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6695 aopPut (result, "a", offset);
6698 emitcode ("anl", "%s,%s",
6699 aopGet (left, offset, FALSE, TRUE),
6700 aopGet (right, offset, FALSE, FALSE));
6704 if (AOP_TYPE (left) == AOP_ACC)
6707 emitcode("mov", "a,b");
6708 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6710 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6712 MOVB (aopGet (left, offset, FALSE, FALSE));
6713 MOVA (aopGet (right, offset, FALSE, FALSE));
6714 emitcode ("anl", "a,b");
6715 aopPut (result, "a", offset);
6717 else if (aopGetUsesAcc (left, offset))
6719 MOVA (aopGet (left, offset, FALSE, FALSE));
6720 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6721 aopPut (result, "a", offset);
6725 MOVA (aopGet (right, offset, FALSE, FALSE));
6726 if (IS_AOP_PREG (result))
6728 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6729 aopPut (result, "a", offset);
6732 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6739 // left & result in different registers
6740 if (AOP_TYPE (result) == AOP_CRY)
6743 // if(size), result in bit
6744 // if(!size && ifx), conditional oper: if(left & right)
6745 symbol *tlbl = newiTempLabel (NULL);
6746 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6748 emitcode ("setb", "c");
6751 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6752 && AOP_TYPE(left)==AOP_ACC)
6755 emitcode("mov", "a,b");
6756 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6758 else if (AOP_TYPE(left)==AOP_ACC)
6762 bool pushedB = pushB ();
6763 emitcode("mov", "b,a");
6764 MOVA (aopGet (right, offset, FALSE, FALSE));
6765 emitcode("anl", "a,b");
6770 MOVA (aopGet (right, offset, FALSE, FALSE));
6771 emitcode("anl", "a,b");
6774 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6776 MOVB (aopGet (left, offset, FALSE, FALSE));
6777 MOVA (aopGet (right, offset, FALSE, FALSE));
6778 emitcode ("anl", "a,b");
6780 else if (aopGetUsesAcc (left, offset))
6782 MOVA (aopGet (left, offset, FALSE, FALSE));
6783 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6787 MOVA (aopGet (right, offset, FALSE, FALSE));
6788 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6791 emitcode ("jnz", "%05d$", tlbl->key + 100);
6801 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6807 for (; (size--); offset++)
6810 // result = left & right
6811 if (AOP_TYPE (right) == AOP_LIT)
6813 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6814 if (bytelit == 0x0FF)
6817 aopGet (left, offset, FALSE, FALSE),
6821 else if (bytelit == 0)
6823 /* dummy read of volatile operand */
6824 if (isOperandVolatile (left, FALSE))
6825 MOVA (aopGet (left, offset, FALSE, FALSE));
6826 aopPut (result, zero, offset);
6829 else if (AOP_TYPE (left) == AOP_ACC)
6833 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6834 aopPut (result, "a", offset);
6839 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6840 aopPut (result, "b", offset);
6845 // faster than result <- left, anl result,right
6846 // and better if result is SFR
6847 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6848 && AOP_TYPE(left)==AOP_ACC)
6851 emitcode("mov", "a,b");
6852 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6854 else if (AOP_TYPE(left)==AOP_ACC)
6858 bool pushedB = pushB ();
6859 emitcode("mov", "b,a");
6860 MOVA (aopGet (right, offset, FALSE, FALSE));
6861 emitcode("anl", "a,b");
6866 MOVA (aopGet (right, offset, FALSE, FALSE));
6867 emitcode("anl", "a,b");
6870 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6872 MOVB (aopGet (left, offset, FALSE, FALSE));
6873 MOVA (aopGet (right, offset, FALSE, FALSE));
6874 emitcode ("anl", "a,b");
6876 else if (aopGetUsesAcc (left, offset))
6878 MOVA (aopGet (left, offset, FALSE, FALSE));
6879 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6883 MOVA (aopGet (right, offset, FALSE, FALSE));
6884 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6886 aopPut (result, "a", offset);
6892 freeAsmop (result, NULL, ic, TRUE);
6893 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6894 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6897 /*-----------------------------------------------------------------*/
6898 /* genOr - code for or */
6899 /*-----------------------------------------------------------------*/
6901 genOr (iCode * ic, iCode * ifx)
6903 operand *left, *right, *result;
6904 int size, offset = 0;
6905 unsigned long lit = 0L;
6908 D (emitcode (";", "genOr"));
6910 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6911 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6912 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6915 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6917 AOP_TYPE (left), AOP_TYPE (right));
6918 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6920 AOP_SIZE (left), AOP_SIZE (right));
6923 /* if left is a literal & right is not then exchange them */
6924 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6925 AOP_NEEDSACC (left))
6927 operand *tmp = right;
6932 /* if result = right then exchange them */
6933 if (sameRegs (AOP (result), AOP (right)))
6935 operand *tmp = right;
6940 /* if right is bit then exchange them */
6941 if (AOP_TYPE (right) == AOP_CRY &&
6942 AOP_TYPE (left) != AOP_CRY)
6944 operand *tmp = right;
6948 if (AOP_TYPE (right) == AOP_LIT)
6949 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6951 size = AOP_SIZE (result);
6955 if (AOP_TYPE (left) == AOP_CRY)
6957 if (AOP_TYPE (right) == AOP_LIT)
6959 // c = bit | literal;
6962 // lit != 0 => result = 1
6963 if (AOP_TYPE (result) == AOP_CRY)
6966 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6968 continueIfTrue (ifx);
6971 emitcode ("setb", "c");
6975 // lit == 0 => result = left
6976 if (size && sameRegs (AOP (result), AOP (left)))
6978 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6983 if (AOP_TYPE (right) == AOP_CRY)
6986 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6987 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6992 symbol *tlbl = newiTempLabel (NULL);
6993 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6994 emitcode ("setb", "c");
6995 emitcode ("jb", "%s,%05d$",
6996 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6998 emitcode ("jnz", "%05d$", tlbl->key + 100);
6999 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7001 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7016 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7017 genIfxJump (ifx, "c", left, right, result);
7021 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7022 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7023 if ((AOP_TYPE (right) == AOP_LIT) &&
7024 (AOP_TYPE (result) == AOP_CRY) &&
7025 (AOP_TYPE (left) != AOP_CRY))
7031 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7033 continueIfTrue (ifx);
7038 // lit = 0, result = boolean(left)
7040 emitcode ("setb", "c");
7044 symbol *tlbl = newiTempLabel (NULL);
7045 emitcode ("jnz", "%05d$", tlbl->key + 100);
7051 genIfxJump (ifx, "a", left, right, result);
7059 /* if left is same as result */
7060 if (sameRegs (AOP (result), AOP (left)))
7062 for (; size--; offset++)
7064 if (AOP_TYPE (right) == AOP_LIT)
7066 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7069 /* dummy read of volatile operand */
7070 if (isOperandVolatile (left, FALSE))
7071 MOVA (aopGet (left, offset, FALSE, FALSE));
7075 else if (bytelit == 0x0FF)
7077 aopPut (result, "#0xFF", offset);
7079 else if (IS_AOP_PREG (left))
7081 MOVA (aopGet (left, offset, FALSE, TRUE));
7082 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7083 aopPut (result, "a", offset);
7087 emitcode ("orl", "%s,%s",
7088 aopGet (left, offset, FALSE, TRUE),
7089 aopGet (right, offset, FALSE, FALSE));
7094 if (AOP_TYPE (left) == AOP_ACC)
7097 emitcode("mov", "a,b");
7098 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7100 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7102 MOVB (aopGet (left, offset, FALSE, FALSE));
7103 MOVA (aopGet (right, offset, FALSE, FALSE));
7104 emitcode ("orl", "a,b");
7105 aopPut (result, "a", offset);
7107 else if (aopGetUsesAcc (left, offset))
7109 MOVA (aopGet (left, offset, FALSE, FALSE));
7110 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7111 aopPut (result, "a", offset);
7115 MOVA (aopGet (right, offset, FALSE, FALSE));
7116 if (IS_AOP_PREG (left))
7118 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7119 aopPut (result, "a", offset);
7123 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7131 // left & result in different registers
7132 if (AOP_TYPE (result) == AOP_CRY)
7135 // if(size), result in bit
7136 // if(!size && ifx), conditional oper: if(left | right)
7137 symbol *tlbl = newiTempLabel (NULL);
7138 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7140 emitcode ("setb", "c");
7143 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7144 && AOP_TYPE(left)==AOP_ACC)
7147 emitcode("mov", "a,b");
7148 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7150 else if (AOP_TYPE(left)==AOP_ACC)
7154 bool pushedB = pushB ();
7155 emitcode("mov", "b,a");
7156 MOVA (aopGet (right, offset, FALSE, FALSE));
7157 emitcode("orl", "a,b");
7162 MOVA (aopGet (right, offset, FALSE, FALSE));
7163 emitcode("orl", "a,b");
7166 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7168 MOVB (aopGet (left, offset, FALSE, FALSE));
7169 MOVA (aopGet (right, offset, FALSE, FALSE));
7170 emitcode ("orl", "a,b");
7172 else if (aopGetUsesAcc (left, offset))
7174 MOVA (aopGet (left, offset, FALSE, FALSE));
7175 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7179 MOVA (aopGet (right, offset, FALSE, FALSE));
7180 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7183 emitcode ("jnz", "%05d$", tlbl->key + 100);
7193 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7199 for (; (size--); offset++)
7202 // result = left | right
7203 if (AOP_TYPE (right) == AOP_LIT)
7205 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7209 aopGet (left, offset, FALSE, FALSE),
7213 else if (bytelit == 0x0FF)
7215 /* dummy read of volatile operand */
7216 if (isOperandVolatile (left, FALSE))
7217 MOVA (aopGet (left, offset, FALSE, FALSE));
7218 aopPut (result, "#0xFF", offset);
7222 // faster than result <- left, orl result,right
7223 // and better if result is SFR
7224 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7225 && AOP_TYPE(left)==AOP_ACC)
7228 emitcode("mov", "a,b");
7229 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7231 else if (AOP_TYPE(left)==AOP_ACC)
7235 bool pushedB = pushB ();
7236 emitcode("mov", "b,a");
7237 MOVA (aopGet (right, offset, FALSE, FALSE));
7238 emitcode("orl", "a,b");
7243 MOVA (aopGet (right, offset, FALSE, FALSE));
7244 emitcode("orl", "a,b");
7247 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7249 MOVB (aopGet (left, offset, FALSE, FALSE));
7250 MOVA (aopGet (right, offset, FALSE, FALSE));
7251 emitcode ("orl", "a,b");
7253 else if (aopGetUsesAcc (left, offset))
7255 MOVA (aopGet (left, offset, FALSE, FALSE));
7256 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7260 MOVA (aopGet (right, offset, FALSE, FALSE));
7261 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7263 aopPut (result, "a", offset);
7269 freeAsmop (result, NULL, ic, TRUE);
7270 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7271 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7274 /*-----------------------------------------------------------------*/
7275 /* genXor - code for xclusive or */
7276 /*-----------------------------------------------------------------*/
7278 genXor (iCode * ic, iCode * ifx)
7280 operand *left, *right, *result;
7281 int size, offset = 0;
7282 unsigned long lit = 0L;
7285 D (emitcode (";", "genXor"));
7287 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7288 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7289 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7292 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7294 AOP_TYPE (left), AOP_TYPE (right));
7295 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7297 AOP_SIZE (left), AOP_SIZE (right));
7300 /* if left is a literal & right is not ||
7301 if left needs acc & right does not */
7302 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7303 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7305 operand *tmp = right;
7310 /* if result = right then exchange them */
7311 if (sameRegs (AOP (result), AOP (right)))
7313 operand *tmp = right;
7318 /* if right is bit then exchange them */
7319 if (AOP_TYPE (right) == AOP_CRY &&
7320 AOP_TYPE (left) != AOP_CRY)
7322 operand *tmp = right;
7326 if (AOP_TYPE (right) == AOP_LIT)
7327 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7329 size = AOP_SIZE (result);
7333 if (AOP_TYPE (left) == AOP_CRY)
7335 if (AOP_TYPE (right) == AOP_LIT)
7337 // c = bit & literal;
7340 // lit>>1 != 0 => result = 1
7341 if (AOP_TYPE (result) == AOP_CRY)
7344 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7346 continueIfTrue (ifx);
7349 emitcode ("setb", "c");
7356 // lit == 0, result = left
7357 if (size && sameRegs (AOP (result), AOP (left)))
7359 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7363 // lit == 1, result = not(left)
7364 if (size && sameRegs (AOP (result), AOP (left)))
7366 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7372 emitcode ("cpl", "c");
7380 symbol *tlbl = newiTempLabel (NULL);
7381 if (AOP_TYPE (right) == AOP_CRY)
7384 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7388 int sizer = AOP_SIZE (right);
7390 // if val>>1 != 0, result = 1
7391 emitcode ("setb", "c");
7394 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7396 // test the msb of the lsb
7397 emitcode ("anl", "a,#0xfe");
7398 emitcode ("jnz", "%05d$", tlbl->key + 100);
7402 emitcode ("rrc", "a");
7404 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7405 emitcode ("cpl", "c");
7413 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7414 genIfxJump (ifx, "c", left, right, result);
7418 /* if left is same as result */
7419 if (sameRegs (AOP (result), AOP (left)))
7421 for (; size--; offset++)
7423 if (AOP_TYPE (right) == AOP_LIT)
7425 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7428 /* dummy read of volatile operand */
7429 if (isOperandVolatile (left, FALSE))
7430 MOVA (aopGet (left, offset, FALSE, FALSE));
7434 else if (IS_AOP_PREG (left))
7436 MOVA (aopGet (left, offset, FALSE, TRUE));
7437 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7438 aopPut (result, "a", offset);
7442 emitcode ("xrl", "%s,%s",
7443 aopGet (left, offset, FALSE, TRUE),
7444 aopGet (right, offset, FALSE, FALSE));
7449 if (AOP_TYPE (left) == AOP_ACC)
7452 emitcode("mov", "a,b");
7453 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7455 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7457 MOVB (aopGet (left, offset, FALSE, FALSE));
7458 MOVA (aopGet (right, offset, FALSE, FALSE));
7459 emitcode ("xrl", "a,b");
7460 aopPut (result, "a", offset);
7462 else if (aopGetUsesAcc (left, offset))
7464 MOVA (aopGet (left, offset, FALSE, FALSE));
7465 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7466 aopPut (result, "a", offset);
7470 MOVA (aopGet (right, offset, FALSE, FALSE));
7471 if (IS_AOP_PREG (left))
7473 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7474 aopPut (result, "a", offset);
7477 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7484 // left & result in different registers
7485 if (AOP_TYPE (result) == AOP_CRY)
7488 // if(size), result in bit
7489 // if(!size && ifx), conditional oper: if(left ^ right)
7490 symbol *tlbl = newiTempLabel (NULL);
7491 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7494 emitcode ("setb", "c");
7497 if ((AOP_TYPE (right) == AOP_LIT) &&
7498 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7500 MOVA (aopGet (left, offset, FALSE, FALSE));
7502 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7503 && AOP_TYPE(left)==AOP_ACC)
7506 emitcode("mov", "a,b");
7507 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7509 else if (AOP_TYPE(left)==AOP_ACC)
7513 bool pushedB = pushB ();
7514 emitcode("mov", "b,a");
7515 MOVA (aopGet (right, offset, FALSE, FALSE));
7516 emitcode("xrl", "a,b");
7521 MOVA (aopGet (right, offset, FALSE, FALSE));
7522 emitcode("xrl", "a,b");
7525 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7527 MOVB (aopGet (left, offset, FALSE, FALSE));
7528 MOVA (aopGet (right, offset, FALSE, FALSE));
7529 emitcode ("xrl", "a,b");
7531 else if (aopGetUsesAcc (left, offset))
7533 MOVA (aopGet (left, offset, FALSE, FALSE));
7534 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7538 MOVA (aopGet (right, offset, FALSE, FALSE));
7539 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7542 emitcode ("jnz", "%05d$", tlbl->key + 100);
7552 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7556 for (; (size--); offset++)
7559 // result = left ^ right
7560 if (AOP_TYPE (right) == AOP_LIT)
7562 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7566 aopGet (left, offset, FALSE, FALSE),
7571 // faster than result <- left, xrl result,right
7572 // and better if result is SFR
7573 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7574 && AOP_TYPE(left)==AOP_ACC)
7577 emitcode("mov", "a,b");
7578 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7580 else if (AOP_TYPE(left)==AOP_ACC)
7584 bool pushedB = pushB ();
7585 emitcode("mov", "b,a");
7586 MOVA (aopGet (right, offset, FALSE, FALSE));
7587 emitcode("xrl", "a,b");
7592 MOVA (aopGet (right, offset, FALSE, FALSE));
7593 emitcode("xrl", "a,b");
7596 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7598 MOVB (aopGet (left, offset, FALSE, FALSE));
7599 MOVA (aopGet (right, offset, FALSE, FALSE));
7600 emitcode ("xrl", "a,b");
7602 else if (aopGetUsesAcc (left, offset))
7604 MOVA (aopGet (left, offset, FALSE, FALSE));
7605 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7609 MOVA (aopGet (right, offset, FALSE, FALSE));
7610 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7612 aopPut (result, "a", offset);
7618 freeAsmop (result, NULL, ic, TRUE);
7619 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7620 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7623 /*-----------------------------------------------------------------*/
7624 /* genInline - write the inline code out */
7625 /*-----------------------------------------------------------------*/
7627 genInline (iCode * ic)
7629 char *buffer, *bp, *bp1;
7631 D (emitcode (";", "genInline"));
7633 _G.inLine += (!options.asmpeep);
7635 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7637 /* emit each line as a code */
7648 /* Add \n for labels, not dirs such as c:\mydir */
7649 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7663 /* emitcode("",buffer); */
7664 _G.inLine -= (!options.asmpeep);
7667 /*-----------------------------------------------------------------*/
7668 /* genRRC - rotate right with carry */
7669 /*-----------------------------------------------------------------*/
7673 operand *left, *result;
7677 D (emitcode (";", "genRRC"));
7679 /* rotate right with carry */
7680 left = IC_LEFT (ic);
7681 result = IC_RESULT (ic);
7682 aopOp (left, ic, FALSE);
7683 aopOp (result, ic, FALSE);
7685 /* move it to the result */
7686 size = AOP_SIZE (result);
7688 if (size == 1) { /* special case for 1 byte */
7689 l = aopGet (left, offset, FALSE, FALSE);
7691 emitcode ("rr", "a");
7694 /* no need to clear carry, bit7 will be written later */
7697 l = aopGet (left, offset, FALSE, FALSE);
7699 emitcode ("rrc", "a");
7700 if (AOP_SIZE (result) > 1)
7701 aopPut (result, "a", offset--);
7703 /* now we need to put the carry into the
7704 highest order byte of the result */
7705 if (AOP_SIZE (result) > 1)
7707 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7710 emitcode ("mov", "acc.7,c");
7712 aopPut (result, "a", AOP_SIZE (result) - 1);
7713 freeAsmop (result, NULL, ic, TRUE);
7714 freeAsmop (left, NULL, ic, TRUE);
7717 /*-----------------------------------------------------------------*/
7718 /* genRLC - generate code for rotate left with carry */
7719 /*-----------------------------------------------------------------*/
7723 operand *left, *result;
7727 D (emitcode (";", "genRLC"));
7729 /* rotate right with carry */
7730 left = IC_LEFT (ic);
7731 result = IC_RESULT (ic);
7732 aopOp (left, ic, FALSE);
7733 aopOp (result, ic, FALSE);
7735 /* move it to the result */
7736 size = AOP_SIZE (result);
7740 l = aopGet (left, offset, FALSE, FALSE);
7742 if (size == 0) { /* special case for 1 byte */
7746 emitcode("rlc","a"); /* bit0 will be written later */
7747 if (AOP_SIZE (result) > 1)
7749 aopPut (result, "a", offset++);
7754 l = aopGet (left, offset, FALSE, FALSE);
7756 emitcode ("rlc", "a");
7757 if (AOP_SIZE (result) > 1)
7758 aopPut (result, "a", offset++);
7761 /* now we need to put the carry into the
7762 highest order byte of the result */
7763 if (AOP_SIZE (result) > 1)
7765 l = aopGet (result, 0, FALSE, FALSE);
7768 emitcode ("mov", "acc.0,c");
7770 aopPut (result, "a", 0);
7771 freeAsmop (result, NULL, ic, TRUE);
7772 freeAsmop (left, NULL, ic, TRUE);
7775 /*-----------------------------------------------------------------*/
7776 /* genGetHbit - generates code get highest order bit */
7777 /*-----------------------------------------------------------------*/
7779 genGetHbit (iCode * ic)
7781 operand *left, *result;
7783 D (emitcode (";", "genGetHbit"));
7785 left = IC_LEFT (ic);
7786 result = IC_RESULT (ic);
7787 aopOp (left, ic, FALSE);
7788 aopOp (result, ic, FALSE);
7790 /* get the highest order byte into a */
7791 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7792 if (AOP_TYPE (result) == AOP_CRY)
7794 emitcode ("rlc", "a");
7799 emitcode ("rl", "a");
7800 emitcode ("anl", "a,#0x01");
7804 freeAsmop (result, NULL, ic, TRUE);
7805 freeAsmop (left, NULL, ic, TRUE);
7808 /*-----------------------------------------------------------------*/
7809 /* genGetAbit - generates code get a single bit */
7810 /*-----------------------------------------------------------------*/
7812 genGetAbit (iCode * ic)
7814 operand *left, *right, *result;
7817 D (emitcode (";", "genGetAbit"));
7819 left = IC_LEFT (ic);
7820 right = IC_RIGHT (ic);
7821 result = IC_RESULT (ic);
7822 aopOp (left, ic, FALSE);
7823 aopOp (right, ic, FALSE);
7824 aopOp (result, ic, FALSE);
7826 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7828 /* get the needed byte into a */
7829 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7831 if (AOP_TYPE (result) == AOP_CRY)
7834 emitcode ("rlc", "a");
7835 else if ((shCount) == 0)
7836 emitcode ("rrc", "a");
7838 emitcode ("mov", "c,acc[%d]", shCount);
7846 emitcode ("rr", "a");
7849 emitcode ("rr", "a");
7852 emitcode ("anl", "a,#0x01");
7856 emitcode ("mov", "c,acc[%d]", shCount);
7857 emitcode ("clr", "a");
7858 emitcode ("rlc", "a");
7861 emitcode ("swap", "a");
7862 emitcode ("anl", "a,#0x01");
7865 emitcode ("rl", "a");
7868 emitcode ("rl", "a");
7869 emitcode ("anl", "a,#0x01");
7875 freeAsmop (result, NULL, ic, TRUE);
7876 freeAsmop (right, NULL, ic, TRUE);
7877 freeAsmop (left, NULL, ic, TRUE);
7880 /*-----------------------------------------------------------------*/
7881 /* genGetByte - generates code get a single byte */
7882 /*-----------------------------------------------------------------*/
7884 genGetByte (iCode * ic)
7886 operand *left, *right, *result;
7889 D (emitcode (";", "genGetByte"));
7891 left = IC_LEFT (ic);
7892 right = IC_RIGHT (ic);
7893 result = IC_RESULT (ic);
7894 aopOp (left, ic, FALSE);
7895 aopOp (right, ic, FALSE);
7896 aopOp (result, ic, FALSE);
7898 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7900 aopGet (left, offset, FALSE, FALSE),
7903 freeAsmop (result, NULL, ic, TRUE);
7904 freeAsmop (right, NULL, ic, TRUE);
7905 freeAsmop (left, NULL, ic, TRUE);
7908 /*-----------------------------------------------------------------*/
7909 /* genGetWord - generates code get two bytes */
7910 /*-----------------------------------------------------------------*/
7912 genGetWord (iCode * ic)
7914 operand *left, *right, *result;
7917 D (emitcode (";", "genGetWord"));
7919 left = IC_LEFT (ic);
7920 right = IC_RIGHT (ic);
7921 result = IC_RESULT (ic);
7922 aopOp (left, ic, FALSE);
7923 aopOp (right, ic, FALSE);
7924 aopOp (result, ic, FALSE);
7926 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7928 aopGet (left, offset, FALSE, FALSE),
7931 aopGet (left, offset+1, FALSE, FALSE),
7934 freeAsmop (result, NULL, ic, TRUE);
7935 freeAsmop (right, NULL, ic, TRUE);
7936 freeAsmop (left, NULL, ic, TRUE);
7939 /*-----------------------------------------------------------------*/
7940 /* genSwap - generates code to swap nibbles or bytes */
7941 /*-----------------------------------------------------------------*/
7943 genSwap (iCode * ic)
7945 operand *left, *result;
7947 D(emitcode ("; genSwap",""));
7949 left = IC_LEFT (ic);
7950 result = IC_RESULT (ic);
7951 aopOp (left, ic, FALSE);
7952 aopOp (result, ic, FALSE);
7954 switch (AOP_SIZE (left))
7956 case 1: /* swap nibbles in byte */
7957 MOVA (aopGet (left, 0, FALSE, FALSE));
7958 emitcode ("swap", "a");
7959 aopPut (result, "a", 0);
7961 case 2: /* swap bytes in word */
7962 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7964 MOVA (aopGet (left, 0, FALSE, FALSE));
7965 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7966 aopPut (result, "a", 1);
7968 else if (operandsEqu (left, result))
7971 bool pushedB = FALSE, leftInB = FALSE;
7973 MOVA (aopGet (left, 0, FALSE, FALSE));
7974 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7977 emitcode ("mov", "b,a");
7981 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7982 aopPut (result, reg, 1);
7989 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7990 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7994 wassertl(FALSE, "unsupported SWAP operand size");
7997 freeAsmop (result, NULL, ic, TRUE);
7998 freeAsmop (left, NULL, ic, TRUE);
8001 /*-----------------------------------------------------------------*/
8002 /* AccRol - rotate left accumulator by known count */
8003 /*-----------------------------------------------------------------*/
8005 AccRol (int shCount)
8007 shCount &= 0x0007; // shCount : 0..7
8014 emitcode ("rl", "a");
8017 emitcode ("rl", "a");
8018 emitcode ("rl", "a");
8021 emitcode ("swap", "a");
8022 emitcode ("rr", "a");
8025 emitcode ("swap", "a");
8028 emitcode ("swap", "a");
8029 emitcode ("rl", "a");
8032 emitcode ("rr", "a");
8033 emitcode ("rr", "a");
8036 emitcode ("rr", "a");
8041 /*-----------------------------------------------------------------*/
8042 /* AccLsh - left shift accumulator by known count */
8043 /*-----------------------------------------------------------------*/
8045 AccLsh (int shCount)
8050 emitcode ("add", "a,acc");
8051 else if (shCount == 2)
8053 emitcode ("add", "a,acc");
8054 emitcode ("add", "a,acc");
8058 /* rotate left accumulator */
8060 /* and kill the lower order bits */
8061 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8066 /*-----------------------------------------------------------------*/
8067 /* AccRsh - right shift accumulator by known count */
8068 /*-----------------------------------------------------------------*/
8070 AccRsh (int shCount)
8077 emitcode ("rrc", "a");
8081 /* rotate right accumulator */
8082 AccRol (8 - shCount);
8083 /* and kill the higher order bits */
8084 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8089 /*-----------------------------------------------------------------*/
8090 /* AccSRsh - signed right shift accumulator by known count */
8091 /*-----------------------------------------------------------------*/
8093 AccSRsh (int shCount)
8100 emitcode ("mov", "c,acc.7");
8101 emitcode ("rrc", "a");
8103 else if (shCount == 2)
8105 emitcode ("mov", "c,acc.7");
8106 emitcode ("rrc", "a");
8107 emitcode ("mov", "c,acc.7");
8108 emitcode ("rrc", "a");
8112 tlbl = newiTempLabel (NULL);
8113 /* rotate right accumulator */
8114 AccRol (8 - shCount);
8115 /* and kill the higher order bits */
8116 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8117 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8118 emitcode ("orl", "a,#0x%02x",
8119 (unsigned char) ~SRMask[shCount]);
8125 /*-----------------------------------------------------------------*/
8126 /* shiftR1Left2Result - shift right one byte from left to result */
8127 /*-----------------------------------------------------------------*/
8129 shiftR1Left2Result (operand * left, int offl,
8130 operand * result, int offr,
8131 int shCount, int sign)
8133 MOVA (aopGet (left, offl, FALSE, FALSE));
8134 /* shift right accumulator */
8139 aopPut (result, "a", offr);
8142 /*-----------------------------------------------------------------*/
8143 /* shiftL1Left2Result - shift left one byte from left to result */
8144 /*-----------------------------------------------------------------*/
8146 shiftL1Left2Result (operand * left, int offl,
8147 operand * result, int offr, int shCount)
8150 l = aopGet (left, offl, FALSE, FALSE);
8152 /* shift left accumulator */
8154 aopPut (result, "a", offr);
8157 /*-----------------------------------------------------------------*/
8158 /* movLeft2Result - move byte from left to result */
8159 /*-----------------------------------------------------------------*/
8161 movLeft2Result (operand * left, int offl,
8162 operand * result, int offr, int sign)
8165 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8167 l = aopGet (left, offl, FALSE, FALSE);
8169 if (*l == '@' && (IS_AOP_PREG (result)))
8171 emitcode ("mov", "a,%s", l);
8172 aopPut (result, "a", offr);
8178 aopPut (result, l, offr);
8182 /* MSB sign in acc.7 ! */
8183 if (getDataSize (left) == offl + 1)
8186 aopPut (result, "a", offr);
8193 /*-----------------------------------------------------------------*/
8194 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8195 /*-----------------------------------------------------------------*/
8199 emitcode ("rrc", "a");
8200 emitcode ("xch", "a,%s", x);
8201 emitcode ("rrc", "a");
8202 emitcode ("xch", "a,%s", x);
8205 /*-----------------------------------------------------------------*/
8206 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8207 /*-----------------------------------------------------------------*/
8211 emitcode ("xch", "a,%s", x);
8212 emitcode ("rlc", "a");
8213 emitcode ("xch", "a,%s", x);
8214 emitcode ("rlc", "a");
8217 /*-----------------------------------------------------------------*/
8218 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8219 /*-----------------------------------------------------------------*/
8223 emitcode ("xch", "a,%s", x);
8224 emitcode ("add", "a,acc");
8225 emitcode ("xch", "a,%s", x);
8226 emitcode ("rlc", "a");
8229 /*-----------------------------------------------------------------*/
8230 /* AccAXLsh - left shift a:x by known count (0..7) */
8231 /*-----------------------------------------------------------------*/
8233 AccAXLsh (char *x, int shCount)
8248 case 5: // AAAAABBB:CCCCCDDD
8250 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8252 emitcode ("anl", "a,#0x%02x",
8253 SLMask[shCount]); // BBB00000:CCCCCDDD
8255 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8257 AccRol (shCount); // DDDCCCCC:BBB00000
8259 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8261 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8263 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8265 emitcode ("anl", "a,#0x%02x",
8266 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8268 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8270 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8273 case 6: // AAAAAABB:CCCCCCDD
8274 emitcode ("anl", "a,#0x%02x",
8275 SRMask[shCount]); // 000000BB:CCCCCCDD
8276 emitcode ("mov", "c,acc.0"); // c = B
8277 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8279 AccAXRrl1 (x); // BCCCCCCD:D000000B
8280 AccAXRrl1 (x); // BBCCCCCC:DD000000
8282 emitcode("rrc","a");
8283 emitcode("xch","a,%s", x);
8284 emitcode("rrc","a");
8285 emitcode("mov","c,acc.0"); //<< get correct bit
8286 emitcode("xch","a,%s", x);
8288 emitcode("rrc","a");
8289 emitcode("xch","a,%s", x);
8290 emitcode("rrc","a");
8291 emitcode("xch","a,%s", x);
8294 case 7: // a:x <<= 7
8296 emitcode ("anl", "a,#0x%02x",
8297 SRMask[shCount]); // 0000000B:CCCCCCCD
8299 emitcode ("mov", "c,acc.0"); // c = B
8301 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8303 AccAXRrl1 (x); // BCCCCCCC:D0000000
8311 /*-----------------------------------------------------------------*/
8312 /* AccAXRsh - right shift a:x known count (0..7) */
8313 /*-----------------------------------------------------------------*/
8315 AccAXRsh (char *x, int shCount)
8323 AccAXRrl1 (x); // 0->a:x
8328 AccAXRrl1 (x); // 0->a:x
8331 AccAXRrl1 (x); // 0->a:x
8336 case 5: // AAAAABBB:CCCCCDDD = a:x
8338 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8340 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8342 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8344 emitcode ("anl", "a,#0x%02x",
8345 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8347 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8349 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8351 emitcode ("anl", "a,#0x%02x",
8352 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8354 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8356 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8358 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8361 case 6: // AABBBBBB:CCDDDDDD
8363 emitcode ("mov", "c,acc.7");
8364 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8366 emitcode ("mov", "c,acc.7");
8367 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8369 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8371 emitcode ("anl", "a,#0x%02x",
8372 SRMask[shCount]); // 000000AA:BBBBBBCC
8375 case 7: // ABBBBBBB:CDDDDDDD
8377 emitcode ("mov", "c,acc.7"); // c = A
8379 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8381 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8383 emitcode ("anl", "a,#0x%02x",
8384 SRMask[shCount]); // 0000000A:BBBBBBBC
8392 /*-----------------------------------------------------------------*/
8393 /* AccAXRshS - right shift signed a:x known count (0..7) */
8394 /*-----------------------------------------------------------------*/
8396 AccAXRshS (char *x, int shCount)
8404 emitcode ("mov", "c,acc.7");
8405 AccAXRrl1 (x); // s->a:x
8409 emitcode ("mov", "c,acc.7");
8410 AccAXRrl1 (x); // s->a:x
8412 emitcode ("mov", "c,acc.7");
8413 AccAXRrl1 (x); // s->a:x
8418 case 5: // AAAAABBB:CCCCCDDD = a:x
8420 tlbl = newiTempLabel (NULL);
8421 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8423 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8425 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8427 emitcode ("anl", "a,#0x%02x",
8428 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8430 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8432 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8434 emitcode ("anl", "a,#0x%02x",
8435 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8437 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8439 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8441 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8443 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8444 emitcode ("orl", "a,#0x%02x",
8445 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8448 break; // SSSSAAAA:BBBCCCCC
8450 case 6: // AABBBBBB:CCDDDDDD
8452 tlbl = newiTempLabel (NULL);
8453 emitcode ("mov", "c,acc.7");
8454 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8456 emitcode ("mov", "c,acc.7");
8457 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8459 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8461 emitcode ("anl", "a,#0x%02x",
8462 SRMask[shCount]); // 000000AA:BBBBBBCC
8464 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8465 emitcode ("orl", "a,#0x%02x",
8466 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8470 case 7: // ABBBBBBB:CDDDDDDD
8472 tlbl = newiTempLabel (NULL);
8473 emitcode ("mov", "c,acc.7"); // c = A
8475 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8477 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8479 emitcode ("anl", "a,#0x%02x",
8480 SRMask[shCount]); // 0000000A:BBBBBBBC
8482 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8483 emitcode ("orl", "a,#0x%02x",
8484 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8493 /*-----------------------------------------------------------------*/
8494 /* shiftL2Left2Result - shift left two bytes from left to result */
8495 /*-----------------------------------------------------------------*/
8497 shiftL2Left2Result (operand * left, int offl,
8498 operand * result, int offr, int shCount)
8501 bool pushedB = FALSE;
8504 if (sameRegs (AOP (result), AOP (left)) &&
8505 ((offl + MSB16) == offr))
8507 /* don't crash result[offr] */
8508 MOVA (aopGet (left, offl, FALSE, FALSE));
8509 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8510 usedB = !strncmp(x, "b", 1);
8512 else if (aopGetUsesAcc (result, offr))
8514 movLeft2Result (left, offl, result, offr, 0);
8517 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8518 MOVA (aopGet (result, offr, FALSE, FALSE));
8519 emitcode ("xch", "a,b");
8524 movLeft2Result (left, offl, result, offr, 0);
8525 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8526 x = aopGet (result, offr, FALSE, FALSE);
8528 /* ax << shCount (x = lsb(result)) */
8529 AccAXLsh (x, shCount);
8532 emitcode ("xch", "a,b");
8533 aopPut (result, "a", offr);
8534 aopPut (result, "b", offr + MSB16);
8539 aopPut (result, "a", offr + MSB16);
8544 /*-----------------------------------------------------------------*/
8545 /* shiftR2Left2Result - shift right two bytes from left to result */
8546 /*-----------------------------------------------------------------*/
8548 shiftR2Left2Result (operand * left, int offl,
8549 operand * result, int offr,
8550 int shCount, int sign)
8553 bool pushedB = FALSE;
8556 if (sameRegs (AOP (result), AOP (left)) &&
8557 ((offl + MSB16) == offr))
8559 /* don't crash result[offr] */
8560 MOVA (aopGet (left, offl, FALSE, FALSE));
8561 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8562 usedB = !strncmp(x, "b", 1);
8564 else if (aopGetUsesAcc (result, offr))
8566 movLeft2Result (left, offl, result, offr, 0);
8569 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8570 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8575 movLeft2Result (left, offl, result, offr, 0);
8576 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8577 x = aopGet (result, offr, FALSE, FALSE);
8579 /* a:x >> shCount (x = lsb(result)) */
8581 AccAXRshS (x, shCount);
8583 AccAXRsh (x, shCount);
8586 emitcode ("xch", "a,b");
8587 aopPut (result, "a", offr);
8588 emitcode ("xch", "a,b");
8591 if (getDataSize (result) > 1)
8592 aopPut (result, "a", offr + MSB16);
8595 /*-----------------------------------------------------------------*/
8596 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8597 /*-----------------------------------------------------------------*/
8599 shiftLLeftOrResult (operand * left, int offl,
8600 operand * result, int offr, int shCount)
8602 MOVA (aopGet (left, offl, FALSE, FALSE));
8603 /* shift left accumulator */
8605 /* or with result */
8606 if (aopGetUsesAcc (result, offr))
8608 emitcode ("xch", "a,b");
8609 MOVA (aopGet (result, offr, FALSE, FALSE));
8610 emitcode ("orl", "a,b");
8614 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8616 /* back to result */
8617 aopPut (result, "a", offr);
8620 /*-----------------------------------------------------------------*/
8621 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8622 /*-----------------------------------------------------------------*/
8624 shiftRLeftOrResult (operand * left, int offl,
8625 operand * result, int offr, int shCount)
8627 MOVA (aopGet (left, offl, FALSE, FALSE));
8628 /* shift right accumulator */
8630 /* or with result */
8631 if (aopGetUsesAcc(result, offr))
8633 emitcode ("xch", "a,b");
8634 MOVA (aopGet (result, offr, FALSE, FALSE));
8635 emitcode ("orl", "a,b");
8639 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8641 /* back to result */
8642 aopPut (result, "a", offr);
8645 /*-----------------------------------------------------------------*/
8646 /* genlshOne - left shift a one byte quantity by known count */
8647 /*-----------------------------------------------------------------*/
8649 genlshOne (operand * result, operand * left, int shCount)
8651 D (emitcode (";", "genlshOne"));
8653 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8656 /*-----------------------------------------------------------------*/
8657 /* genlshTwo - left shift two bytes by known amount != 0 */
8658 /*-----------------------------------------------------------------*/
8660 genlshTwo (operand * result, operand * left, int shCount)
8664 D (emitcode (";", "genlshTwo"));
8666 size = getDataSize (result);
8668 /* if shCount >= 8 */
8676 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8678 movLeft2Result (left, LSB, result, MSB16, 0);
8680 aopPut (result, zero, LSB);
8683 /* 1 <= shCount <= 7 */
8687 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8689 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8693 /*-----------------------------------------------------------------*/
8694 /* shiftLLong - shift left one long from left to result */
8695 /* offl = LSB or MSB16 */
8696 /*-----------------------------------------------------------------*/
8698 shiftLLong (operand * left, operand * result, int offr)
8701 int size = AOP_SIZE (result);
8703 if (size >= LSB + offr)
8705 l = aopGet (left, LSB, FALSE, FALSE);
8707 emitcode ("add", "a,acc");
8708 if (sameRegs (AOP (left), AOP (result)) &&
8709 size >= MSB16 + offr && offr != LSB)
8710 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8712 aopPut (result, "a", LSB + offr);
8715 if (size >= MSB16 + offr)
8717 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8719 l = aopGet (left, MSB16, FALSE, FALSE);
8722 emitcode ("rlc", "a");
8723 if (sameRegs (AOP (left), AOP (result)) &&
8724 size >= MSB24 + offr && offr != LSB)
8725 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8727 aopPut (result, "a", MSB16 + offr);
8730 if (size >= MSB24 + offr)
8732 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8734 l = aopGet (left, MSB24, FALSE, FALSE);
8737 emitcode ("rlc", "a");
8738 if (sameRegs (AOP (left), AOP (result)) &&
8739 size >= MSB32 + offr && offr != LSB)
8740 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8742 aopPut (result, "a", MSB24 + offr);
8745 if (size > MSB32 + offr)
8747 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8749 l = aopGet (left, MSB32, FALSE, FALSE);
8752 emitcode ("rlc", "a");
8753 aopPut (result, "a", MSB32 + offr);
8756 aopPut (result, zero, LSB);
8759 /*-----------------------------------------------------------------*/
8760 /* genlshFour - shift four byte by a known amount != 0 */
8761 /*-----------------------------------------------------------------*/
8763 genlshFour (operand * result, operand * left, int shCount)
8767 D (emitcode (";", "genlshFour"));
8769 size = AOP_SIZE (result);
8771 /* if shifting more that 3 bytes */
8776 /* lowest order of left goes to the highest
8777 order of the destination */
8778 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8780 movLeft2Result (left, LSB, result, MSB32, 0);
8781 aopPut (result, zero, LSB);
8782 aopPut (result, zero, MSB16);
8783 aopPut (result, zero, MSB24);
8787 /* more than two bytes */
8788 else if (shCount >= 16)
8790 /* lower order two bytes goes to higher order two bytes */
8792 /* if some more remaining */
8794 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8797 movLeft2Result (left, MSB16, result, MSB32, 0);
8798 movLeft2Result (left, LSB, result, MSB24, 0);
8800 aopPut (result, zero, MSB16);
8801 aopPut (result, zero, LSB);
8805 /* if more than 1 byte */
8806 else if (shCount >= 8)
8808 /* lower order three bytes goes to higher order three bytes */
8813 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8815 movLeft2Result (left, LSB, result, MSB16, 0);
8821 movLeft2Result (left, MSB24, result, MSB32, 0);
8822 movLeft2Result (left, MSB16, result, MSB24, 0);
8823 movLeft2Result (left, LSB, result, MSB16, 0);
8824 aopPut (result, zero, LSB);
8826 else if (shCount == 1)
8827 shiftLLong (left, result, MSB16);
8830 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8831 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8832 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8833 aopPut (result, zero, LSB);
8838 /* 1 <= shCount <= 7 */
8839 else if (shCount <= 2)
8841 shiftLLong (left, result, LSB);
8843 shiftLLong (result, result, LSB);
8845 /* 3 <= shCount <= 7, optimize */
8848 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8849 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8850 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8854 /*-----------------------------------------------------------------*/
8855 /* genLeftShiftLiteral - left shifting by known count */
8856 /*-----------------------------------------------------------------*/
8858 genLeftShiftLiteral (operand * left,
8863 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8866 D (emitcode (";", "genLeftShiftLiteral"));
8868 freeAsmop (right, NULL, ic, TRUE);
8870 aopOp (left, ic, FALSE);
8871 aopOp (result, ic, FALSE);
8873 size = getSize (operandType (result));
8876 emitcode ("; shift left ", "result %d, left %d", size,
8880 /* I suppose that the left size >= result size */
8885 movLeft2Result (left, size, result, size, 0);
8888 else if (shCount >= (size * 8))
8892 aopPut (result, zero, size);
8900 genlshOne (result, left, shCount);
8904 genlshTwo (result, left, shCount);
8908 genlshFour (result, left, shCount);
8911 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8912 "*** ack! mystery literal shift!\n");
8916 freeAsmop (result, NULL, ic, TRUE);
8917 freeAsmop (left, NULL, ic, TRUE);
8920 /*-----------------------------------------------------------------*/
8921 /* genLeftShift - generates code for left shifting */
8922 /*-----------------------------------------------------------------*/
8924 genLeftShift (iCode * ic)
8926 operand *left, *right, *result;
8929 symbol *tlbl, *tlbl1;
8932 D (emitcode (";", "genLeftShift"));
8934 right = IC_RIGHT (ic);
8935 left = IC_LEFT (ic);
8936 result = IC_RESULT (ic);
8938 aopOp (right, ic, FALSE);
8940 /* if the shift count is known then do it
8941 as efficiently as possible */
8942 if (AOP_TYPE (right) == AOP_LIT)
8944 genLeftShiftLiteral (left, right, result, ic);
8948 /* shift count is unknown then we have to form
8949 a loop get the loop count in B : Note: we take
8950 only the lower order byte since shifting
8951 more that 32 bits make no sense anyway, ( the
8952 largest size of an object can be only 32 bits ) */
8955 MOVB (aopGet (right, 0, FALSE, FALSE));
8956 emitcode ("inc", "b");
8957 freeAsmop (right, NULL, ic, TRUE);
8958 aopOp (left, ic, FALSE);
8959 aopOp (result, ic, FALSE);
8961 /* now move the left to the result if they are not the same */
8962 if (!sameRegs (AOP (left), AOP (result)) &&
8963 AOP_SIZE (result) > 1)
8966 size = AOP_SIZE (result);
8970 l = aopGet (left, offset, FALSE, TRUE);
8971 if (*l == '@' && (IS_AOP_PREG (result)))
8974 emitcode ("mov", "a,%s", l);
8975 aopPut (result, "a", offset);
8978 aopPut (result, l, offset);
8983 tlbl = newiTempLabel (NULL);
8984 size = AOP_SIZE (result);
8986 tlbl1 = newiTempLabel (NULL);
8988 /* if it is only one byte then */
8991 symbol *tlbl1 = newiTempLabel (NULL);
8993 l = aopGet (left, 0, FALSE, FALSE);
8995 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8997 emitcode ("add", "a,acc");
8999 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9001 aopPut (result, "a", 0);
9005 reAdjustPreg (AOP (result));
9007 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9009 l = aopGet (result, offset, FALSE, FALSE);
9011 emitcode ("add", "a,acc");
9012 aopPut (result, "a", offset++);
9015 l = aopGet (result, offset, FALSE, FALSE);
9017 emitcode ("rlc", "a");
9018 aopPut (result, "a", offset++);
9020 reAdjustPreg (AOP (result));
9023 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9026 freeAsmop (result, NULL, ic, TRUE);
9027 freeAsmop (left, NULL, ic, TRUE);
9030 /*-----------------------------------------------------------------*/
9031 /* genrshOne - right shift a one byte quantity by known count */
9032 /*-----------------------------------------------------------------*/
9034 genrshOne (operand * result, operand * left,
9035 int shCount, int sign)
9037 D (emitcode (";", "genrshOne"));
9039 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9042 /*-----------------------------------------------------------------*/
9043 /* genrshTwo - right shift two bytes by known amount != 0 */
9044 /*-----------------------------------------------------------------*/
9046 genrshTwo (operand * result, operand * left,
9047 int shCount, int sign)
9049 D (emitcode (";", "genrshTwo"));
9051 /* if shCount >= 8 */
9056 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9058 movLeft2Result (left, MSB16, result, LSB, sign);
9059 addSign (result, MSB16, sign);
9062 /* 1 <= shCount <= 7 */
9064 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9067 /*-----------------------------------------------------------------*/
9068 /* shiftRLong - shift right one long from left to result */
9069 /* offl = LSB or MSB16 */
9070 /*-----------------------------------------------------------------*/
9072 shiftRLong (operand * left, int offl,
9073 operand * result, int sign)
9075 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9077 if (overlapping && offl>1)
9079 // we are in big trouble, but this shouldn't happen
9080 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9083 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9090 emitcode ("rlc", "a");
9091 emitcode ("subb", "a,acc");
9092 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9094 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9098 aopPut (result, "a", MSB32);
9099 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9104 if (aopPutUsesAcc (result, zero, MSB32))
9106 emitcode("xch", "a,b");
9107 aopPut (result, zero, MSB32);
9108 emitcode("xch", "a,b");
9112 aopPut (result, zero, MSB32);
9119 emitcode ("clr", "c");
9123 emitcode ("mov", "c,acc.7");
9126 emitcode ("rrc", "a");
9128 if (overlapping && offl==MSB16 &&
9129 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9131 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9135 aopPut (result, "a", MSB32 - offl);
9136 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9139 emitcode ("rrc", "a");
9140 if (overlapping && offl==MSB16 &&
9141 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9143 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9147 aopPut (result, "a", MSB24 - offl);
9148 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9151 emitcode ("rrc", "a");
9154 aopPut (result, "a", MSB16 - offl);
9159 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9161 xch_a_aopGet (left, LSB, FALSE, FALSE);
9165 aopPut (result, "a", MSB16 - offl);
9166 MOVA (aopGet (left, LSB, FALSE, FALSE));
9168 emitcode ("rrc", "a");
9169 aopPut (result, "a", LSB);
9173 /*-----------------------------------------------------------------*/
9174 /* genrshFour - shift four byte by a known amount != 0 */
9175 /*-----------------------------------------------------------------*/
9177 genrshFour (operand * result, operand * left,
9178 int shCount, int sign)
9180 D (emitcode (";", "genrshFour"));
9182 /* if shifting more that 3 bytes */
9187 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9189 movLeft2Result (left, MSB32, result, LSB, sign);
9190 addSign (result, MSB16, sign);
9192 else if (shCount >= 16)
9196 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9199 movLeft2Result (left, MSB24, result, LSB, 0);
9200 movLeft2Result (left, MSB32, result, MSB16, sign);
9202 addSign (result, MSB24, sign);
9204 else if (shCount >= 8)
9209 shiftRLong (left, MSB16, result, sign);
9211 else if (shCount == 0)
9213 movLeft2Result (left, MSB16, result, LSB, 0);
9214 movLeft2Result (left, MSB24, result, MSB16, 0);
9215 movLeft2Result (left, MSB32, result, MSB24, sign);
9216 addSign (result, MSB32, sign);
9220 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9221 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9222 /* the last shift is signed */
9223 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9224 addSign (result, MSB32, sign);
9229 /* 1 <= shCount <= 7 */
9232 shiftRLong (left, LSB, result, sign);
9234 shiftRLong (result, LSB, result, sign);
9238 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9239 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9240 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9245 /*-----------------------------------------------------------------*/
9246 /* genRightShiftLiteral - right shifting by known count */
9247 /*-----------------------------------------------------------------*/
9249 genRightShiftLiteral (operand * left,
9255 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9258 D (emitcode (";", "genRightShiftLiteral"));
9260 freeAsmop (right, NULL, ic, TRUE);
9262 aopOp (left, ic, FALSE);
9263 aopOp (result, ic, FALSE);
9266 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9270 size = getDataSize (left);
9271 /* test the LEFT size !!! */
9273 /* I suppose that the left size >= result size */
9276 size = getDataSize (result);
9278 movLeft2Result (left, size, result, size, 0);
9281 else if (shCount >= (size * 8))
9285 /* get sign in acc.7 */
9286 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9288 addSign (result, LSB, sign);
9295 genrshOne (result, left, shCount, sign);
9299 genrshTwo (result, left, shCount, sign);
9303 genrshFour (result, left, shCount, sign);
9309 freeAsmop (result, NULL, ic, TRUE);
9310 freeAsmop (left, NULL, ic, TRUE);
9313 /*-----------------------------------------------------------------*/
9314 /* genSignedRightShift - right shift of signed number */
9315 /*-----------------------------------------------------------------*/
9317 genSignedRightShift (iCode * ic)
9319 operand *right, *left, *result;
9322 symbol *tlbl, *tlbl1;
9325 D (emitcode (";", "genSignedRightShift"));
9327 /* we do it the hard way put the shift count in b
9328 and loop thru preserving the sign */
9330 right = IC_RIGHT (ic);
9331 left = IC_LEFT (ic);
9332 result = IC_RESULT (ic);
9334 aopOp (right, ic, FALSE);
9337 if (AOP_TYPE (right) == AOP_LIT)
9339 genRightShiftLiteral (left, right, result, ic, 1);
9342 /* shift count is unknown then we have to form
9343 a loop get the loop count in B : Note: we take
9344 only the lower order byte since shifting
9345 more that 32 bits make no sense anyway, ( the
9346 largest size of an object can be only 32 bits ) */
9349 MOVB (aopGet (right, 0, FALSE, FALSE));
9350 emitcode ("inc", "b");
9351 freeAsmop (right, NULL, ic, TRUE);
9352 aopOp (left, ic, FALSE);
9353 aopOp (result, ic, FALSE);
9355 /* now move the left to the result if they are not the
9357 if (!sameRegs (AOP (left), AOP (result)) &&
9358 AOP_SIZE (result) > 1)
9361 size = AOP_SIZE (result);
9365 l = aopGet (left, offset, FALSE, TRUE);
9366 if (*l == '@' && IS_AOP_PREG (result))
9369 emitcode ("mov", "a,%s", l);
9370 aopPut (result, "a", offset);
9373 aopPut (result, l, offset);
9378 /* mov the highest order bit to OVR */
9379 tlbl = newiTempLabel (NULL);
9380 tlbl1 = newiTempLabel (NULL);
9382 size = AOP_SIZE (result);
9384 MOVA (aopGet (left, offset, FALSE, FALSE));
9385 emitcode ("rlc", "a");
9386 emitcode ("mov", "ov,c");
9387 /* if it is only one byte then */
9390 l = aopGet (left, 0, FALSE, FALSE);
9392 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9394 emitcode ("mov", "c,ov");
9395 emitcode ("rrc", "a");
9397 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9399 aopPut (result, "a", 0);
9403 reAdjustPreg (AOP (result));
9404 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9406 emitcode ("mov", "c,ov");
9409 l = aopGet (result, offset, FALSE, FALSE);
9411 emitcode ("rrc", "a");
9412 aopPut (result, "a", offset--);
9414 reAdjustPreg (AOP (result));
9416 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9420 freeAsmop (result, NULL, ic, TRUE);
9421 freeAsmop (left, NULL, ic, TRUE);
9424 /*-----------------------------------------------------------------*/
9425 /* genRightShift - generate code for right shifting */
9426 /*-----------------------------------------------------------------*/
9428 genRightShift (iCode * ic)
9430 operand *right, *left, *result;
9434 symbol *tlbl, *tlbl1;
9437 D (emitcode (";", "genRightShift"));
9439 /* if signed then we do it the hard way preserve the
9440 sign bit moving it inwards */
9441 letype = getSpec (operandType (IC_LEFT (ic)));
9443 if (!SPEC_USIGN (letype))
9445 genSignedRightShift (ic);
9449 /* signed & unsigned types are treated the same : i.e. the
9450 signed is NOT propagated inwards : quoting from the
9451 ANSI - standard : "for E1 >> E2, is equivalent to division
9452 by 2**E2 if unsigned or if it has a non-negative value,
9453 otherwise the result is implementation defined ", MY definition
9454 is that the sign does not get propagated */
9456 right = IC_RIGHT (ic);
9457 left = IC_LEFT (ic);
9458 result = IC_RESULT (ic);
9460 aopOp (right, ic, FALSE);
9462 /* if the shift count is known then do it
9463 as efficiently as possible */
9464 if (AOP_TYPE (right) == AOP_LIT)
9466 genRightShiftLiteral (left, right, result, ic, 0);
9470 /* shift count is unknown then we have to form
9471 a loop get the loop count in B : Note: we take
9472 only the lower order byte since shifting
9473 more that 32 bits make no sense anyway, ( the
9474 largest size of an object can be only 32 bits ) */
9477 MOVB (aopGet (right, 0, FALSE, FALSE));
9478 emitcode ("inc", "b");
9479 freeAsmop (right, NULL, ic, TRUE);
9480 aopOp (left, ic, FALSE);
9481 aopOp (result, ic, FALSE);
9483 /* now move the left to the result if they are not the
9485 if (!sameRegs (AOP (left), AOP (result)) &&
9486 AOP_SIZE (result) > 1)
9488 size = AOP_SIZE (result);
9492 l = aopGet (left, offset, FALSE, TRUE);
9493 if (*l == '@' && IS_AOP_PREG (result))
9496 emitcode ("mov", "a,%s", l);
9497 aopPut (result, "a", offset);
9500 aopPut (result, l, offset);
9505 tlbl = newiTempLabel (NULL);
9506 tlbl1 = newiTempLabel (NULL);
9507 size = AOP_SIZE (result);
9510 /* if it is only one byte then */
9513 l = aopGet (left, 0, FALSE, FALSE);
9515 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9518 emitcode ("rrc", "a");
9520 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9522 aopPut (result, "a", 0);
9526 reAdjustPreg (AOP (result));
9527 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9532 l = aopGet (result, offset, FALSE, FALSE);
9534 emitcode ("rrc", "a");
9535 aopPut (result, "a", offset--);
9537 reAdjustPreg (AOP (result));
9540 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9544 freeAsmop (result, NULL, ic, TRUE);
9545 freeAsmop (left, NULL, ic, TRUE);
9548 /*-----------------------------------------------------------------*/
9549 /* emitPtrByteGet - emits code to get a byte into A through a */
9550 /* pointer register (R0, R1, or DPTR). The */
9551 /* original value of A can be preserved in B. */
9552 /*-----------------------------------------------------------------*/
9554 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9561 emitcode ("mov", "b,a");
9562 emitcode ("mov", "a,@%s", rname);
9567 emitcode ("mov", "b,a");
9568 emitcode ("movx", "a,@%s", rname);
9573 emitcode ("mov", "b,a");
9574 emitcode ("movx", "a,@dptr");
9579 emitcode ("mov", "b,a");
9580 emitcode ("clr", "a");
9581 emitcode ("movc", "a,@a+dptr");
9587 emitcode ("push", "b");
9588 emitcode ("push", "acc");
9590 emitcode ("lcall", "__gptrget");
9592 emitcode ("pop", "b");
9597 /*-----------------------------------------------------------------*/
9598 /* emitPtrByteSet - emits code to set a byte from src through a */
9599 /* pointer register (R0, R1, or DPTR). */
9600 /*-----------------------------------------------------------------*/
9602 emitPtrByteSet (char *rname, int p_type, char *src)
9611 emitcode ("mov", "@%s,a", rname);
9614 emitcode ("mov", "@%s,%s", rname, src);
9619 emitcode ("movx", "@%s,a", rname);
9624 emitcode ("movx", "@dptr,a");
9629 emitcode ("lcall", "__gptrput");
9634 /*-----------------------------------------------------------------*/
9635 /* genUnpackBits - generates code for unpacking bits */
9636 /*-----------------------------------------------------------------*/
9638 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9640 int offset = 0; /* result byte offset */
9641 int rsize; /* result size */
9642 int rlen = 0; /* remaining bitfield length */
9643 sym_link *etype; /* bitfield type information */
9644 int blen; /* bitfield length */
9645 int bstr; /* bitfield starting bit within byte */
9648 D(emitcode ("; genUnpackBits",""));
9650 etype = getSpec (operandType (result));
9651 rsize = getSize (operandType (result));
9652 blen = SPEC_BLEN (etype);
9653 bstr = SPEC_BSTR (etype);
9655 if (ifx && blen <= 8)
9657 emitPtrByteGet (rname, ptype, FALSE);
9660 SNPRINTF (buffer, sizeof(buffer),
9662 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9667 emitcode ("anl", "a,#0x%02x",
9668 (((unsigned char) -1) >> (8 - blen)) << bstr);
9669 genIfxJump (ifx, "a", NULL, NULL, NULL);
9675 /* If the bitfield length is less than a byte */
9678 emitPtrByteGet (rname, ptype, FALSE);
9680 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9681 if (!SPEC_USIGN (etype))
9683 /* signed bitfield */
9684 symbol *tlbl = newiTempLabel (NULL);
9686 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9687 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9690 aopPut (result, "a", offset++);
9694 /* Bit field did not fit in a byte. Copy all
9695 but the partial byte at the end. */
9696 for (rlen=blen;rlen>=8;rlen-=8)
9698 emitPtrByteGet (rname, ptype, FALSE);
9699 aopPut (result, "a", offset++);
9701 emitcode ("inc", "%s", rname);
9704 /* Handle the partial byte at the end */
9707 emitPtrByteGet (rname, ptype, FALSE);
9708 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9709 if (!SPEC_USIGN (etype))
9711 /* signed bitfield */
9712 symbol *tlbl = newiTempLabel (NULL);
9714 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9715 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9718 aopPut (result, "a", offset++);
9726 if (SPEC_USIGN (etype))
9730 /* signed bitfield: sign extension with 0x00 or 0xff */
9731 emitcode ("rlc", "a");
9732 emitcode ("subb", "a,acc");
9738 aopPut (result, source, offset++);
9743 /*-----------------------------------------------------------------*/
9744 /* genDataPointerGet - generates code when ptr offset is known */
9745 /*-----------------------------------------------------------------*/
9747 genDataPointerGet (operand * left,
9753 int size, offset = 0;
9755 D (emitcode (";", "genDataPointerGet"));
9757 aopOp (result, ic, TRUE);
9759 /* get the string representation of the name */
9760 l = aopGet (left, 0, FALSE, TRUE);
9762 size = AOP_SIZE (result);
9767 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9771 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9773 aopPut (result, buffer, offset++);
9776 freeAsmop (result, NULL, ic, TRUE);
9777 freeAsmop (left, NULL, ic, TRUE);
9780 /*-----------------------------------------------------------------*/
9781 /* genNearPointerGet - emitcode for near pointer fetch */
9782 /*-----------------------------------------------------------------*/
9784 genNearPointerGet (operand * left,
9793 sym_link *rtype, *retype;
9794 sym_link *ltype = operandType (left);
9797 D (emitcode (";", "genNearPointerGet"));
9799 rtype = operandType (result);
9800 retype = getSpec (rtype);
9802 aopOp (left, ic, FALSE);
9804 /* if left is rematerialisable and
9805 result is not bitfield variable type and
9806 the left is pointer to data space i.e
9807 lower 128 bytes of space */
9808 if (AOP_TYPE (left) == AOP_IMMD &&
9809 !IS_BITFIELD (retype) &&
9810 DCL_TYPE (ltype) == POINTER)
9812 genDataPointerGet (left, result, ic);
9816 /* if the value is already in a pointer register
9817 then don't need anything more */
9818 if (!AOP_INPREG (AOP (left)))
9820 if (IS_AOP_PREG (left))
9822 // Aha, it is a pointer, just in disguise.
9823 rname = aopGet (left, 0, FALSE, FALSE);
9826 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9827 __FILE__, __LINE__);
9832 emitcode ("mov", "a%s,%s", rname + 1, rname);
9833 rname++; // skip the '@'.
9838 /* otherwise get a free pointer register */
9840 preg = getFreePtr (ic, &aop, FALSE);
9841 emitcode ("mov", "%s,%s",
9843 aopGet (left, 0, FALSE, TRUE));
9848 rname = aopGet (left, 0, FALSE, FALSE);
9850 //aopOp (result, ic, FALSE);
9851 aopOp (result, ic, result?TRUE:FALSE);
9853 /* if bitfield then unpack the bits */
9854 if (IS_BITFIELD (retype))
9855 genUnpackBits (result, rname, POINTER, ifx);
9858 /* we have can just get the values */
9859 int size = AOP_SIZE (result);
9864 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9867 emitcode ("mov", "a,@%s", rname);
9869 aopPut (result, "a", offset);
9873 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9874 aopPut (result, buffer, offset);
9878 emitcode ("inc", "%s", rname);
9882 /* now some housekeeping stuff */
9883 if (aop) /* we had to allocate for this iCode */
9885 if (pi) { /* post increment present */
9886 aopPut (left, rname, 0);
9888 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9892 /* we did not allocate which means left
9893 already in a pointer register, then
9894 if size > 0 && this could be used again
9895 we have to point it back to where it
9897 if ((AOP_SIZE (result) > 1 &&
9898 !OP_SYMBOL (left)->remat &&
9899 (OP_SYMBOL (left)->liveTo > ic->seq ||
9903 int size = AOP_SIZE (result) - 1;
9905 emitcode ("dec", "%s", rname);
9909 if (ifx && !ifx->generated)
9911 genIfxJump (ifx, "a", left, NULL, result);
9915 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9916 freeAsmop (left, NULL, ic, TRUE);
9917 if (pi) pi->generated = 1;
9920 /*-----------------------------------------------------------------*/
9921 /* genPagedPointerGet - emitcode for paged pointer fetch */
9922 /*-----------------------------------------------------------------*/
9924 genPagedPointerGet (operand * left,
9933 sym_link *rtype, *retype;
9935 D (emitcode (";", "genPagedPointerGet"));
9937 rtype = operandType (result);
9938 retype = getSpec (rtype);
9940 aopOp (left, ic, FALSE);
9942 /* if the value is already in a pointer register
9943 then don't need anything more */
9944 if (!AOP_INPREG (AOP (left)))
9946 /* otherwise get a free pointer register */
9948 preg = getFreePtr (ic, &aop, FALSE);
9949 emitcode ("mov", "%s,%s",
9951 aopGet (left, 0, FALSE, TRUE));
9955 rname = aopGet (left, 0, FALSE, FALSE);
9957 aopOp (result, ic, FALSE);
9959 /* if bitfield then unpack the bits */
9960 if (IS_BITFIELD (retype))
9961 genUnpackBits (result, rname, PPOINTER, ifx);
9964 /* we have can just get the values */
9965 int size = AOP_SIZE (result);
9971 emitcode ("movx", "a,@%s", rname);
9973 aopPut (result, "a", offset);
9978 emitcode ("inc", "%s", rname);
9982 /* now some housekeeping stuff */
9983 if (aop) /* we had to allocate for this iCode */
9986 aopPut (left, rname, 0);
9987 freeAsmop (NULL, aop, ic, TRUE);
9991 /* we did not allocate which means left
9992 already in a pointer register, then
9993 if size > 0 && this could be used again
9994 we have to point it back to where it
9996 if ((AOP_SIZE (result) > 1 &&
9997 !OP_SYMBOL (left)->remat &&
9998 (OP_SYMBOL (left)->liveTo > ic->seq ||
10002 int size = AOP_SIZE (result) - 1;
10004 emitcode ("dec", "%s", rname);
10008 if (ifx && !ifx->generated)
10010 genIfxJump (ifx, "a", left, NULL, result);
10014 freeAsmop (result, NULL, ic, TRUE);
10015 freeAsmop (left, NULL, ic, TRUE);
10016 if (pi) pi->generated = 1;
10019 /*--------------------------------------------------------------------*/
10020 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10021 /*--------------------------------------------------------------------*/
10023 loadDptrFromOperand (operand *op, bool loadBToo)
10025 if (AOP_TYPE (op) != AOP_STR)
10027 /* if this is rematerializable */
10028 if (AOP_TYPE (op) == AOP_IMMD)
10030 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10033 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10034 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10037 wassertl(FALSE, "need pointerCode");
10038 emitcode ("", "; mov b,???");
10039 /* genPointerGet and genPointerSet originally did different
10040 ** things for this case. Both seem wrong.
10041 ** from genPointerGet:
10042 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10043 ** from genPointerSet:
10044 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10049 else if (AOP_TYPE (op) == AOP_DPTR)
10053 MOVA (aopGet (op, 0, FALSE, FALSE));
10054 emitcode ("push", "acc");
10055 MOVA (aopGet (op, 1, FALSE, FALSE));
10056 emitcode ("push", "acc");
10057 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10058 emitcode ("pop", "dph");
10059 emitcode ("pop", "dpl");
10063 MOVA (aopGet (op, 0, FALSE, FALSE));
10064 emitcode ("push", "acc");
10065 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10066 emitcode ("pop", "dpl");
10070 { /* we need to get it byte by byte */
10071 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10072 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10074 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10079 /*-----------------------------------------------------------------*/
10080 /* genFarPointerGet - get value from far space */
10081 /*-----------------------------------------------------------------*/
10083 genFarPointerGet (operand * left,
10084 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10087 sym_link *retype = getSpec (operandType (result));
10089 D (emitcode (";", "genFarPointerGet"));
10091 aopOp (left, ic, FALSE);
10092 loadDptrFromOperand (left, FALSE);
10094 /* so dptr now contains the address */
10095 aopOp (result, ic, FALSE);
10097 /* if bit then unpack */
10098 if (IS_BITFIELD (retype))
10099 genUnpackBits (result, "dptr", FPOINTER, ifx);
10102 size = AOP_SIZE (result);
10107 emitcode ("movx", "a,@dptr");
10109 aopPut (result, "a", offset++);
10111 emitcode ("inc", "dptr");
10115 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10117 aopPut (left, "dpl", 0);
10118 aopPut (left, "dph", 1);
10122 if (ifx && !ifx->generated)
10124 genIfxJump (ifx, "a", left, NULL, result);
10127 freeAsmop (result, NULL, ic, TRUE);
10128 freeAsmop (left, NULL, ic, TRUE);
10131 /*-----------------------------------------------------------------*/
10132 /* genCodePointerGet - get value from code space */
10133 /*-----------------------------------------------------------------*/
10135 genCodePointerGet (operand * left,
10136 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10139 sym_link *retype = getSpec (operandType (result));
10141 D (emitcode (";", "genCodePointerGet"));
10143 aopOp (left, ic, FALSE);
10144 loadDptrFromOperand (left, FALSE);
10146 /* so dptr now contains the address */
10147 aopOp (result, ic, FALSE);
10149 /* if bit then unpack */
10150 if (IS_BITFIELD (retype))
10151 genUnpackBits (result, "dptr", CPOINTER, ifx);
10154 size = AOP_SIZE (result);
10159 emitcode ("clr", "a");
10160 emitcode ("movc", "a,@a+dptr");
10162 aopPut (result, "a", offset++);
10164 emitcode ("inc", "dptr");
10168 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10170 aopPut (left, "dpl", 0);
10171 aopPut (left, "dph", 1);
10175 if (ifx && !ifx->generated)
10177 genIfxJump (ifx, "a", left, NULL, result);
10180 freeAsmop (result, NULL, ic, TRUE);
10181 freeAsmop (left, NULL, ic, TRUE);
10184 /*-----------------------------------------------------------------*/
10185 /* genGenPointerGet - get value from generic pointer space */
10186 /*-----------------------------------------------------------------*/
10188 genGenPointerGet (operand * left,
10189 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10192 sym_link *retype = getSpec (operandType (result));
10194 D (emitcode (";", "genGenPointerGet"));
10196 aopOp (left, ic, FALSE);
10197 loadDptrFromOperand (left, TRUE);
10199 /* so dptr now contains the address */
10200 aopOp (result, ic, FALSE);
10202 /* if bit then unpack */
10203 if (IS_BITFIELD (retype))
10205 genUnpackBits (result, "dptr", GPOINTER, ifx);
10209 size = AOP_SIZE (result);
10214 emitcode ("lcall", "__gptrget");
10216 aopPut (result, "a", offset++);
10218 emitcode ("inc", "dptr");
10222 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10224 aopPut (left, "dpl", 0);
10225 aopPut (left, "dph", 1);
10229 if (ifx && !ifx->generated)
10231 genIfxJump (ifx, "a", left, NULL, result);
10234 freeAsmop (result, NULL, ic, TRUE);
10235 freeAsmop (left, NULL, ic, TRUE);
10238 /*-----------------------------------------------------------------*/
10239 /* genPointerGet - generate code for pointer get */
10240 /*-----------------------------------------------------------------*/
10242 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10244 operand *left, *result;
10245 sym_link *type, *etype;
10248 D (emitcode (";", "genPointerGet"));
10250 left = IC_LEFT (ic);
10251 result = IC_RESULT (ic);
10253 if (getSize (operandType (result))>1)
10256 /* depending on the type of pointer we need to
10257 move it to the correct pointer register */
10258 type = operandType (left);
10259 etype = getSpec (type);
10260 /* if left is of type of pointer then it is simple */
10261 if (IS_PTR (type) && !IS_FUNC (type->next))
10262 p_type = DCL_TYPE (type);
10265 /* we have to go by the storage class */
10266 p_type = PTR_TYPE (SPEC_OCLS (etype));
10269 /* special case when cast remat */
10270 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10271 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10273 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10274 type = operandType (left);
10275 p_type = DCL_TYPE (type);
10277 /* now that we have the pointer type we assign
10278 the pointer values */
10284 genNearPointerGet (left, result, ic, pi, ifx);
10288 genPagedPointerGet (left, result, ic, pi, ifx);
10292 genFarPointerGet (left, result, ic, pi, ifx);
10296 genCodePointerGet (left, result, ic, pi, ifx);
10300 genGenPointerGet (left, result, ic, pi, ifx);
10306 /*-----------------------------------------------------------------*/
10307 /* genPackBits - generates code for packed bit storage */
10308 /*-----------------------------------------------------------------*/
10310 genPackBits (sym_link * etype,
10312 char *rname, int p_type)
10314 int offset = 0; /* source byte offset */
10315 int rlen = 0; /* remaining bitfield length */
10316 int blen; /* bitfield length */
10317 int bstr; /* bitfield starting bit within byte */
10318 int litval; /* source literal value (if AOP_LIT) */
10319 unsigned char mask; /* bitmask within current byte */
10321 D(emitcode ("; genPackBits",""));
10323 blen = SPEC_BLEN (etype);
10324 bstr = SPEC_BSTR (etype);
10326 /* If the bitfield length is less than a byte */
10329 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10330 (unsigned char) (0xFF >> (8 - bstr)));
10332 if (AOP_TYPE (right) == AOP_LIT)
10334 /* Case with a bitfield length <8 and literal source
10336 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10338 litval &= (~mask) & 0xff;
10339 emitPtrByteGet (rname, p_type, FALSE);
10340 if ((mask|litval)!=0xff)
10341 emitcode ("anl","a,#0x%02x", mask);
10343 emitcode ("orl","a,#0x%02x", litval);
10347 if ((blen==1) && (p_type!=GPOINTER))
10349 /* Case with a bitfield length == 1 and no generic pointer
10351 if (AOP_TYPE (right) == AOP_CRY)
10352 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10355 MOVA (aopGet (right, 0, FALSE, FALSE));
10356 emitcode ("rrc","a");
10358 emitPtrByteGet (rname, p_type, FALSE);
10359 emitcode ("mov","acc.%d,c",bstr);
10364 /* Case with a bitfield length < 8 and arbitrary source
10366 MOVA (aopGet (right, 0, FALSE, FALSE));
10367 /* shift and mask source value */
10369 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10371 pushedB = pushB ();
10372 /* transfer A to B and get next byte */
10373 emitPtrByteGet (rname, p_type, TRUE);
10375 emitcode ("anl", "a,#0x%02x", mask);
10376 emitcode ("orl", "a,b");
10377 if (p_type == GPOINTER)
10378 emitcode ("pop", "b");
10384 emitPtrByteSet (rname, p_type, "a");
10388 /* Bit length is greater than 7 bits. In this case, copy */
10389 /* all except the partial byte at the end */
10390 for (rlen=blen;rlen>=8;rlen-=8)
10392 emitPtrByteSet (rname, p_type,
10393 aopGet (right, offset++, FALSE, TRUE) );
10395 emitcode ("inc", "%s", rname);
10398 /* If there was a partial byte at the end */
10401 mask = (((unsigned char) -1 << rlen) & 0xff);
10403 if (AOP_TYPE (right) == AOP_LIT)
10405 /* Case with partial byte and literal source
10407 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10408 litval >>= (blen-rlen);
10409 litval &= (~mask) & 0xff;
10410 emitPtrByteGet (rname, p_type, FALSE);
10411 if ((mask|litval)!=0xff)
10412 emitcode ("anl","a,#0x%02x", mask);
10414 emitcode ("orl","a,#0x%02x", litval);
10419 /* Case with partial byte and arbitrary source
10421 MOVA (aopGet (right, offset++, FALSE, FALSE));
10422 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10424 pushedB = pushB ();
10425 /* transfer A to B and get next byte */
10426 emitPtrByteGet (rname, p_type, TRUE);
10428 emitcode ("anl", "a,#0x%02x", mask);
10429 emitcode ("orl", "a,b");
10430 if (p_type == GPOINTER)
10431 emitcode ("pop", "b");
10435 emitPtrByteSet (rname, p_type, "a");
10440 /*-----------------------------------------------------------------*/
10441 /* genDataPointerSet - remat pointer to data space */
10442 /*-----------------------------------------------------------------*/
10444 genDataPointerSet (operand * right,
10448 int size, offset = 0;
10449 char *l, buffer[256];
10451 D (emitcode (";", "genDataPointerSet"));
10453 aopOp (right, ic, FALSE);
10455 l = aopGet (result, 0, FALSE, TRUE);
10457 size = AOP_SIZE (right);
10461 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10463 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10464 emitcode ("mov", "%s,%s", buffer,
10465 aopGet (right, offset++, FALSE, FALSE));
10468 freeAsmop (result, NULL, ic, TRUE);
10469 freeAsmop (right, NULL, ic, TRUE);
10472 /*-----------------------------------------------------------------*/
10473 /* genNearPointerSet - emitcode for near pointer put */
10474 /*-----------------------------------------------------------------*/
10476 genNearPointerSet (operand * right,
10484 sym_link *retype, *letype;
10485 sym_link *ptype = operandType (result);
10487 D (emitcode (";", "genNearPointerSet"));
10489 retype = getSpec (operandType (right));
10490 letype = getSpec (ptype);
10492 aopOp (result, ic, FALSE);
10494 /* if the result is rematerializable &
10495 in data space & not a bit variable */
10496 if (AOP_TYPE (result) == AOP_IMMD &&
10497 DCL_TYPE (ptype) == POINTER &&
10498 !IS_BITVAR (retype) &&
10499 !IS_BITVAR (letype))
10501 genDataPointerSet (right, result, ic);
10505 /* if the value is already in a pointer register
10506 then don't need anything more */
10507 if (!AOP_INPREG (AOP (result)))
10510 //AOP_TYPE (result) == AOP_STK
10511 IS_AOP_PREG(result)
10514 // Aha, it is a pointer, just in disguise.
10515 rname = aopGet (result, 0, FALSE, FALSE);
10518 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10519 __FILE__, __LINE__);
10524 emitcode ("mov", "a%s,%s", rname + 1, rname);
10525 rname++; // skip the '@'.
10530 /* otherwise get a free pointer register */
10531 aop = newAsmop (0);
10532 preg = getFreePtr (ic, &aop, FALSE);
10533 emitcode ("mov", "%s,%s",
10535 aopGet (result, 0, FALSE, TRUE));
10536 rname = preg->name;
10541 rname = aopGet (result, 0, FALSE, FALSE);
10544 aopOp (right, ic, FALSE);
10546 /* if bitfield then unpack the bits */
10547 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10548 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10551 /* we can just get the values */
10552 int size = AOP_SIZE (right);
10557 l = aopGet (right, offset, FALSE, TRUE);
10558 if ((*l == '@') || (strcmp (l, "acc") == 0))
10561 emitcode ("mov", "@%s,a", rname);
10564 emitcode ("mov", "@%s,%s", rname, l);
10566 emitcode ("inc", "%s", rname);
10571 /* now some housekeeping stuff */
10572 if (aop) /* we had to allocate for this iCode */
10575 aopPut (result, rname, 0);
10576 freeAsmop (NULL, aop, ic, TRUE);
10580 /* we did not allocate which means left
10581 already in a pointer register, then
10582 if size > 0 && this could be used again
10583 we have to point it back to where it
10585 if ((AOP_SIZE (right) > 1 &&
10586 !OP_SYMBOL (result)->remat &&
10587 (OP_SYMBOL (result)->liveTo > ic->seq ||
10591 int size = AOP_SIZE (right) - 1;
10593 emitcode ("dec", "%s", rname);
10598 if (pi) pi->generated = 1;
10599 freeAsmop (result, NULL, ic, TRUE);
10600 freeAsmop (right, NULL, ic, TRUE);
10603 /*-----------------------------------------------------------------*/
10604 /* genPagedPointerSet - emitcode for Paged pointer put */
10605 /*-----------------------------------------------------------------*/
10607 genPagedPointerSet (operand * right,
10615 sym_link *retype, *letype;
10617 D (emitcode (";", "genPagedPointerSet"));
10619 retype = getSpec (operandType (right));
10620 letype = getSpec (operandType (result));
10622 aopOp (result, ic, FALSE);
10624 /* if the value is already in a pointer register
10625 then don't need anything more */
10626 if (!AOP_INPREG (AOP (result)))
10628 /* otherwise get a free pointer register */
10629 aop = newAsmop (0);
10630 preg = getFreePtr (ic, &aop, FALSE);
10631 emitcode ("mov", "%s,%s",
10633 aopGet (result, 0, FALSE, TRUE));
10634 rname = preg->name;
10637 rname = aopGet (result, 0, FALSE, FALSE);
10639 aopOp (right, ic, FALSE);
10641 /* if bitfield then unpack the bits */
10642 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10643 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10646 /* we have can just get the values */
10647 int size = AOP_SIZE (right);
10652 l = aopGet (right, offset, FALSE, TRUE);
10654 emitcode ("movx", "@%s,a", rname);
10657 emitcode ("inc", "%s", rname);
10663 /* now some housekeeping stuff */
10664 if (aop) /* we had to allocate for this iCode */
10667 aopPut (result, rname, 0);
10668 freeAsmop (NULL, aop, ic, TRUE);
10672 /* we did not allocate which means left
10673 already in a pointer register, then
10674 if size > 0 && this could be used again
10675 we have to point it back to where it
10677 if (AOP_SIZE (right) > 1 &&
10678 !OP_SYMBOL (result)->remat &&
10679 (OP_SYMBOL (result)->liveTo > ic->seq ||
10682 int size = AOP_SIZE (right) - 1;
10684 emitcode ("dec", "%s", rname);
10689 if (pi) pi->generated = 1;
10690 freeAsmop (result, NULL, ic, TRUE);
10691 freeAsmop (right, NULL, ic, TRUE);
10694 /*-----------------------------------------------------------------*/
10695 /* genFarPointerSet - set value from far space */
10696 /*-----------------------------------------------------------------*/
10698 genFarPointerSet (operand * right,
10699 operand * result, iCode * ic, iCode * pi)
10702 sym_link *retype = getSpec (operandType (right));
10703 sym_link *letype = getSpec (operandType (result));
10705 D(emitcode ("; genFarPointerSet",""));
10707 aopOp (result, ic, FALSE);
10708 loadDptrFromOperand (result, FALSE);
10710 /* so dptr now contains the address */
10711 aopOp (right, ic, FALSE);
10713 /* if bit then unpack */
10714 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10715 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10718 size = AOP_SIZE (right);
10723 char *l = aopGet (right, offset++, FALSE, FALSE);
10725 emitcode ("movx", "@dptr,a");
10727 emitcode ("inc", "dptr");
10730 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10731 aopPut (result, "dpl", 0);
10732 aopPut (result, "dph", 1);
10735 freeAsmop (result, NULL, ic, TRUE);
10736 freeAsmop (right, NULL, ic, TRUE);
10739 /*-----------------------------------------------------------------*/
10740 /* genGenPointerSet - set value from generic pointer space */
10741 /*-----------------------------------------------------------------*/
10743 genGenPointerSet (operand * right,
10744 operand * result, iCode * ic, iCode * pi)
10747 sym_link *retype = getSpec (operandType (right));
10748 sym_link *letype = getSpec (operandType (result));
10750 D (emitcode (";", "genGenPointerSet"));
10752 aopOp (result, ic, FALSE);
10753 loadDptrFromOperand (result, TRUE);
10755 /* so dptr now contains the address */
10756 aopOp (right, ic, FALSE);
10758 /* if bit then unpack */
10759 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10761 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10765 size = AOP_SIZE (right);
10770 char *l = aopGet (right, offset++, FALSE, FALSE);
10772 emitcode ("lcall", "__gptrput");
10774 emitcode ("inc", "dptr");
10778 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10779 aopPut (result, "dpl", 0);
10780 aopPut (result, "dph", 1);
10783 freeAsmop (result, NULL, ic, TRUE);
10784 freeAsmop (right, NULL, ic, TRUE);
10787 /*-----------------------------------------------------------------*/
10788 /* genPointerSet - stores the value into a pointer location */
10789 /*-----------------------------------------------------------------*/
10791 genPointerSet (iCode * ic, iCode *pi)
10793 operand *right, *result;
10794 sym_link *type, *etype;
10797 D (emitcode (";", "genPointerSet"));
10799 right = IC_RIGHT (ic);
10800 result = IC_RESULT (ic);
10802 /* depending on the type of pointer we need to
10803 move it to the correct pointer register */
10804 type = operandType (result);
10805 etype = getSpec (type);
10806 /* if left is of type of pointer then it is simple */
10807 if (IS_PTR (type) && !IS_FUNC (type->next))
10809 p_type = DCL_TYPE (type);
10813 /* we have to go by the storage class */
10814 p_type = PTR_TYPE (SPEC_OCLS (etype));
10817 /* special case when cast remat */
10818 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10819 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10820 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10821 type = operandType (result);
10822 p_type = DCL_TYPE (type);
10825 /* now that we have the pointer type we assign
10826 the pointer values */
10832 genNearPointerSet (right, result, ic, pi);
10836 genPagedPointerSet (right, result, ic, pi);
10840 genFarPointerSet (right, result, ic, pi);
10844 genGenPointerSet (right, result, ic, pi);
10848 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10849 "genPointerSet: illegal pointer type");
10853 /*-----------------------------------------------------------------*/
10854 /* genIfx - generate code for Ifx statement */
10855 /*-----------------------------------------------------------------*/
10857 genIfx (iCode * ic, iCode * popIc)
10859 operand *cond = IC_COND (ic);
10863 D (emitcode (";", "genIfx"));
10865 aopOp (cond, ic, FALSE);
10867 /* get the value into acc */
10868 if (AOP_TYPE (cond) != AOP_CRY)
10875 if (AOP(cond)->aopu.aop_dir)
10876 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10879 /* the result is now in the accumulator or a directly addressable bit */
10880 freeAsmop (cond, NULL, ic, TRUE);
10882 /* if there was something to be popped then do it */
10886 /* if the condition is a bit variable */
10888 genIfxJump(ic, dup, NULL, NULL, NULL);
10889 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10890 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10891 else if (isbit && !IS_ITEMP (cond))
10892 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10894 genIfxJump (ic, "a", NULL, NULL, NULL);
10899 /*-----------------------------------------------------------------*/
10900 /* genAddrOf - generates code for address of */
10901 /*-----------------------------------------------------------------*/
10903 genAddrOf (iCode * ic)
10905 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10908 D (emitcode (";", "genAddrOf"));
10910 aopOp (IC_RESULT (ic), ic, FALSE);
10912 /* if the operand is on the stack then we
10913 need to get the stack offset of this
10917 /* if it has an offset then we need to compute it */
10920 int stack_offset = ((sym->stack < 0) ?
10921 ((char) (sym->stack - _G.nRegsSaved)) :
10922 ((char) sym->stack)) & 0xff;
10923 if ((abs(stack_offset) == 1) &&
10924 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10925 !isOperandVolatile (IC_RESULT (ic), FALSE))
10927 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10928 if (stack_offset > 0)
10929 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10931 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10935 emitcode ("mov", "a,%s", SYM_BP (sym));
10936 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10937 aopPut (IC_RESULT (ic), "a", 0);
10942 /* we can just move _bp */
10943 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10945 /* fill the result with zero */
10946 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10951 aopPut (IC_RESULT (ic), zero, offset++);
10956 /* object not on stack then we need the name */
10957 size = AOP_SIZE (IC_RESULT (ic));
10962 char s[SDCC_NAME_MAX];
10964 sprintf (s, "#(%s >> %d)",
10968 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10969 aopPut (IC_RESULT (ic), s, offset++);
10973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10977 /*-----------------------------------------------------------------*/
10978 /* genFarFarAssign - assignment when both are in far space */
10979 /*-----------------------------------------------------------------*/
10981 genFarFarAssign (operand * result, operand * right, iCode * ic)
10983 int size = AOP_SIZE (right);
10987 D (emitcode (";", "genFarFarAssign"));
10989 /* first push the right side on to the stack */
10992 l = aopGet (right, offset++, FALSE, FALSE);
10994 emitcode ("push", "acc");
10997 freeAsmop (right, NULL, ic, FALSE);
10998 /* now assign DPTR to result */
10999 aopOp (result, ic, FALSE);
11000 size = AOP_SIZE (result);
11003 emitcode ("pop", "acc");
11004 aopPut (result, "a", --offset);
11006 freeAsmop (result, NULL, ic, FALSE);
11009 /*-----------------------------------------------------------------*/
11010 /* genAssign - generate code for assignment */
11011 /*-----------------------------------------------------------------*/
11013 genAssign (iCode * ic)
11015 operand *result, *right;
11017 unsigned long lit = 0L;
11019 D (emitcode (";", "genAssign"));
11021 result = IC_RESULT (ic);
11022 right = IC_RIGHT (ic);
11024 /* if they are the same */
11025 if (operandsEqu (result, right) &&
11026 !isOperandVolatile (result, FALSE) &&
11027 !isOperandVolatile (right, FALSE))
11030 aopOp (right, ic, FALSE);
11032 /* special case both in far space */
11033 if (AOP_TYPE (right) == AOP_DPTR &&
11034 IS_TRUE_SYMOP (result) &&
11035 isOperandInFarSpace (result))
11037 genFarFarAssign (result, right, ic);
11041 aopOp (result, ic, TRUE);
11043 /* if they are the same registers */
11044 if (sameRegs (AOP (right), AOP (result)) &&
11045 !isOperandVolatile (result, FALSE) &&
11046 !isOperandVolatile (right, FALSE))
11049 /* if the result is a bit */
11050 if (AOP_TYPE (result) == AOP_CRY)
11052 /* if the right size is a literal then
11053 we know what the value is */
11054 if (AOP_TYPE (right) == AOP_LIT)
11056 if (((int) operandLitValue (right)))
11057 aopPut (result, one, 0);
11059 aopPut (result, zero, 0);
11063 /* the right is also a bit variable */
11064 if (AOP_TYPE (right) == AOP_CRY)
11066 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11067 aopPut (result, "c", 0);
11071 /* we need to or */
11073 aopPut (result, "a", 0);
11077 /* bit variables done */
11079 size = AOP_SIZE (result);
11081 if (AOP_TYPE (right) == AOP_LIT)
11082 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11085 (AOP_TYPE (result) != AOP_REG) &&
11086 (AOP_TYPE (right) == AOP_LIT) &&
11087 !IS_FLOAT (operandType (right)) &&
11090 while ((size) && (lit))
11093 aopGet (right, offset, FALSE, FALSE),
11099 /* And now fill the rest with zeros. */
11102 emitcode ("clr", "a");
11106 aopPut (result, "a", offset);
11115 aopGet (right, offset, FALSE, FALSE),
11122 freeAsmop (result, NULL, ic, TRUE);
11123 freeAsmop (right, NULL, ic, TRUE);
11126 /*-----------------------------------------------------------------*/
11127 /* genJumpTab - generates code for jump table */
11128 /*-----------------------------------------------------------------*/
11130 genJumpTab (iCode * ic)
11132 symbol *jtab,*jtablo,*jtabhi;
11134 unsigned int count;
11136 D (emitcode (";", "genJumpTab"));
11138 count = elementsInSet( IC_JTLABELS (ic) );
11142 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11143 if the switch argument is in a register.
11144 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11145 /* Peephole may not convert ljmp to sjmp or ret
11146 labelIsReturnOnly & labelInRange must check
11147 currPl->ic->op != JUMPTABLE */
11148 aopOp (IC_JTCOND (ic), ic, FALSE);
11149 /* get the condition into accumulator */
11150 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11152 /* multiply by three */
11153 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11155 emitcode ("mov", "b,#3");
11156 emitcode ("mul", "ab");
11160 emitcode ("add", "a,acc");
11161 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11163 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11165 jtab = newiTempLabel (NULL);
11166 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11167 emitcode ("jmp", "@a+dptr");
11169 /* now generate the jump labels */
11170 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11171 jtab = setNextItem (IC_JTLABELS (ic)))
11172 emitcode ("ljmp", "%05d$", jtab->key + 100);
11176 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11177 if the switch argument is in a register.
11178 For n>6 this algorithm may be more compact */
11179 jtablo = newiTempLabel (NULL);
11180 jtabhi = newiTempLabel (NULL);
11182 /* get the condition into accumulator.
11183 Using b as temporary storage, if register push/pop is needed */
11184 aopOp (IC_JTCOND (ic), ic, FALSE);
11185 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11186 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11187 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11189 // (MB) what if B is in use???
11190 wassertl(!BINUSE, "B was in use");
11191 emitcode ("mov", "b,%s", l);
11194 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11198 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11199 emitcode ("movc", "a,@a+pc");
11200 emitcode ("push", "acc");
11203 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11204 emitcode ("movc", "a,@a+pc");
11205 emitcode ("push", "acc");
11209 /* this scales up to n<=255, but needs two more bytes
11210 and changes dptr */
11211 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11212 emitcode ("movc", "a,@a+dptr");
11213 emitcode ("push", "acc");
11216 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11217 emitcode ("movc", "a,@a+dptr");
11218 emitcode ("push", "acc");
11221 emitcode ("ret", "");
11223 /* now generate jump table, LSB */
11224 emitLabel (jtablo);
11225 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11226 jtab = setNextItem (IC_JTLABELS (ic)))
11227 emitcode (".db", "%05d$", jtab->key + 100);
11229 /* now generate jump table, MSB */
11230 emitLabel (jtabhi);
11231 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11232 jtab = setNextItem (IC_JTLABELS (ic)))
11233 emitcode (".db", "%05d$>>8", jtab->key + 100);
11237 /*-----------------------------------------------------------------*/
11238 /* genCast - gen code for casting */
11239 /*-----------------------------------------------------------------*/
11241 genCast (iCode * ic)
11243 operand *result = IC_RESULT (ic);
11244 sym_link *ctype = operandType (IC_LEFT (ic));
11245 sym_link *rtype = operandType (IC_RIGHT (ic));
11246 operand *right = IC_RIGHT (ic);
11249 D (emitcode (";", "genCast"));
11251 /* if they are equivalent then do nothing */
11252 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11255 aopOp (right, ic, FALSE);
11256 aopOp (result, ic, FALSE);
11258 /* if the result is a bit (and not a bitfield) */
11259 if (IS_BIT (OP_SYMBOL (result)->type))
11261 /* if the right size is a literal then
11262 we know what the value is */
11263 if (AOP_TYPE (right) == AOP_LIT)
11265 if (((int) operandLitValue (right)))
11266 aopPut (result, one, 0);
11268 aopPut (result, zero, 0);
11273 /* the right is also a bit variable */
11274 if (AOP_TYPE (right) == AOP_CRY)
11276 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11277 aopPut (result, "c", 0);
11281 /* we need to or */
11283 aopPut (result, "a", 0);
11287 /* if they are the same size : or less */
11288 if (AOP_SIZE (result) <= AOP_SIZE (right))
11291 /* if they are in the same place */
11292 if (sameRegs (AOP (right), AOP (result)))
11295 /* if they in different places then copy */
11296 size = AOP_SIZE (result);
11301 aopGet (right, offset, FALSE, FALSE),
11308 /* if the result is of type pointer */
11309 if (IS_PTR (ctype))
11313 sym_link *type = operandType (right);
11314 sym_link *etype = getSpec (type);
11316 /* pointer to generic pointer */
11317 if (IS_GENPTR (ctype))
11321 p_type = DCL_TYPE (type);
11325 if (SPEC_SCLS(etype)==S_REGISTER) {
11326 // let's assume it is a generic pointer
11329 /* we have to go by the storage class */
11330 p_type = PTR_TYPE (SPEC_OCLS (etype));
11334 /* the first two bytes are known */
11335 size = GPTRSIZE - 1;
11340 aopGet (right, offset, FALSE, FALSE),
11344 /* the last byte depending on type */
11346 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11351 // pointerTypeToGPByte will have bitched.
11355 sprintf(gpValStr, "#0x%x", gpVal);
11356 aopPut (result, gpValStr, GPTRSIZE - 1);
11361 /* just copy the pointers */
11362 size = AOP_SIZE (result);
11367 aopGet (right, offset, FALSE, FALSE),
11374 /* so we now know that the size of destination is greater
11375 than the size of the source */
11376 /* we move to result for the size of source */
11377 size = AOP_SIZE (right);
11382 aopGet (right, offset, FALSE, FALSE),
11387 /* now depending on the sign of the source && destination */
11388 size = AOP_SIZE (result) - AOP_SIZE (right);
11389 /* if unsigned or not an integral type */
11390 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11393 aopPut (result, zero, offset++);
11397 /* we need to extend the sign :{ */
11398 char *l = aopGet (right, AOP_SIZE (right) - 1,
11401 emitcode ("rlc", "a");
11402 emitcode ("subb", "a,acc");
11404 aopPut (result, "a", offset++);
11407 /* we are done hurray !!!! */
11410 freeAsmop (result, NULL, ic, TRUE);
11411 freeAsmop (right, NULL, ic, TRUE);
11414 /*-----------------------------------------------------------------*/
11415 /* genDjnz - generate decrement & jump if not zero instrucion */
11416 /*-----------------------------------------------------------------*/
11418 genDjnz (iCode * ic, iCode * ifx)
11420 symbol *lbl, *lbl1;
11424 /* if the if condition has a false label
11425 then we cannot save */
11426 if (IC_FALSE (ifx))
11429 /* if the minus is not of the form a = a - 1 */
11430 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11431 !IS_OP_LITERAL (IC_RIGHT (ic)))
11434 if (operandLitValue (IC_RIGHT (ic)) != 1)
11437 /* if the size of this greater than one then no
11439 if (getSize (operandType (IC_RESULT (ic))) > 1)
11442 /* otherwise we can save BIG */
11444 D (emitcode (";", "genDjnz"));
11446 lbl = newiTempLabel (NULL);
11447 lbl1 = newiTempLabel (NULL);
11449 aopOp (IC_RESULT (ic), ic, FALSE);
11451 if (AOP_NEEDSACC(IC_RESULT(ic)))
11453 /* If the result is accessed indirectly via
11454 * the accumulator, we must explicitly write
11455 * it back after the decrement.
11457 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11459 if (strcmp(rByte, "a"))
11461 /* Something is hopelessly wrong */
11462 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11463 __FILE__, __LINE__);
11464 /* We can just give up; the generated code will be inefficient,
11465 * but what the hey.
11467 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11470 emitcode ("dec", "%s", rByte);
11471 aopPut (IC_RESULT (ic), rByte, 0);
11472 emitcode ("jnz", "%05d$", lbl->key + 100);
11474 else if (IS_AOP_PREG (IC_RESULT (ic)))
11476 emitcode ("dec", "%s",
11477 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11478 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11480 ifx->generated = 1;
11481 emitcode ("jnz", "%05d$", lbl->key + 100);
11485 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11488 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11490 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11493 if (!ifx->generated)
11494 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11495 ifx->generated = 1;
11499 /*-----------------------------------------------------------------*/
11500 /* genReceive - generate code for a receive iCode */
11501 /*-----------------------------------------------------------------*/
11503 genReceive (iCode * ic)
11505 int size = getSize (operandType (IC_RESULT (ic)));
11508 D (emitcode (";", "genReceive"));
11510 if (ic->argreg == 1)
11511 { /* first parameter */
11512 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11513 isOperandInPagedSpace (IC_RESULT (ic))) &&
11514 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11515 IS_TRUE_SYMOP (IC_RESULT (ic))))
11518 int receivingA = 0;
11521 for (offset = 0; offset<size; offset++)
11522 if (!strcmp (fReturn[offset], "a"))
11527 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11529 for (offset = size-1; offset>0; offset--)
11530 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11531 emitcode("mov","a,%s", fReturn[0]);
11533 aopOp (IC_RESULT (ic), ic, FALSE);
11535 aopPut (IC_RESULT (ic), "a", offset);
11536 for (offset = 1; offset<size; offset++)
11537 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11543 if (getTempRegs(tempRegs, size, ic))
11545 for (offset = 0; offset<size; offset++)
11546 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11547 aopOp (IC_RESULT (ic), ic, FALSE);
11548 for (offset = 0; offset<size; offset++)
11549 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11554 offset = fReturnSizeMCS51 - size;
11557 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11558 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11561 aopOp (IC_RESULT (ic), ic, FALSE);
11562 size = AOP_SIZE (IC_RESULT (ic));
11566 emitcode ("pop", "acc");
11567 aopPut (IC_RESULT (ic), "a", offset++);
11573 aopOp (IC_RESULT (ic), ic, FALSE);
11575 assignResultValue (IC_RESULT (ic), NULL);
11578 else if (ic->argreg > 12)
11579 { /* bit parameters */
11580 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11582 aopOp (IC_RESULT (ic), ic, FALSE);
11583 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11584 outBitC(IC_RESULT (ic));
11588 { /* other parameters */
11590 aopOp (IC_RESULT (ic), ic, FALSE);
11591 rb1off = ic->argreg;
11594 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11599 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11602 /*-----------------------------------------------------------------*/
11603 /* genDummyRead - generate code for dummy read of volatiles */
11604 /*-----------------------------------------------------------------*/
11606 genDummyRead (iCode * ic)
11611 D (emitcode(";", "genDummyRead"));
11613 op = IC_RIGHT (ic);
11614 if (op && IS_SYMOP (op))
11616 aopOp (op, ic, FALSE);
11618 /* if the result is a bit */
11619 if (AOP_TYPE (op) == AOP_CRY)
11620 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11623 /* bit variables done */
11625 size = AOP_SIZE (op);
11629 MOVA (aopGet (op, offset, FALSE, FALSE));
11634 freeAsmop (op, NULL, ic, TRUE);
11638 if (op && IS_SYMOP (op))
11640 aopOp (op, ic, FALSE);
11642 /* if the result is a bit */
11643 if (AOP_TYPE (op) == AOP_CRY)
11644 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11647 /* bit variables done */
11649 size = AOP_SIZE (op);
11653 MOVA (aopGet (op, offset, FALSE, FALSE));
11658 freeAsmop (op, NULL, ic, TRUE);
11662 /*-----------------------------------------------------------------*/
11663 /* genCritical - generate code for start of a critical sequence */
11664 /*-----------------------------------------------------------------*/
11666 genCritical (iCode *ic)
11668 symbol *tlbl = newiTempLabel (NULL);
11670 D (emitcode(";", "genCritical"));
11672 if (IC_RESULT (ic))
11674 aopOp (IC_RESULT (ic), ic, TRUE);
11675 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11676 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11677 aopPut (IC_RESULT (ic), zero, 0);
11679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11683 emitcode ("setb", "c");
11684 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11685 emitcode ("clr", "c");
11687 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11691 /*-----------------------------------------------------------------*/
11692 /* genEndCritical - generate code for end of a critical sequence */
11693 /*-----------------------------------------------------------------*/
11695 genEndCritical (iCode *ic)
11697 D(emitcode("; genEndCritical",""));
11701 aopOp (IC_RIGHT (ic), ic, FALSE);
11702 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11704 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11705 emitcode ("mov", "ea,c");
11709 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11710 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11711 emitcode ("rrc", "a");
11712 emitcode ("mov", "ea,c");
11714 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11718 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11719 emitcode ("mov", "ea,c");
11723 /*-----------------------------------------------------------------*/
11724 /* gen51Code - generate code for 8051 based controllers */
11725 /*-----------------------------------------------------------------*/
11727 gen51Code (iCode * lic)
11731 /* int cseq = 0; */
11733 _G.currentFunc = NULL;
11734 lineHead = lineCurr = NULL;
11736 /* print the allocation information */
11737 if (allocInfo && currFunc)
11738 printAllocInfo (currFunc, codeOutBuf);
11739 /* if debug information required */
11740 if (options.debug && currFunc)
11742 debugFile->writeFunction (currFunc, lic);
11744 /* stack pointer name */
11745 if (options.useXstack)
11751 for (ic = lic; ic; ic = ic->next)
11753 _G.current_iCode = ic;
11755 if (ic->lineno && cln != ic->lineno)
11759 debugFile->writeCLine (ic);
11761 if (!options.noCcodeInAsm) {
11762 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11763 printCLine(ic->filename, ic->lineno));
11768 if (ic->seqPoint && ic->seqPoint != cseq)
11770 emitcode ("", "; sequence point %d", ic->seqPoint);
11771 cseq = ic->seqPoint;
11774 if (options.iCodeInAsm) {
11775 char regsInUse[80];
11780 for (i=0; i<8; i++) {
11781 sprintf (®sInUse[i],
11782 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11785 strcpy (regsInUse, "--------");
11786 for (i=0; i < 8; i++) {
11787 if (bitVectBitValue (ic->rMask, i))
11789 int offset = regs8051[i].offset;
11790 regsInUse[offset] = offset + '0'; /* show rMask */
11794 iLine = printILine(ic);
11795 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11798 /* if the result is marked as
11799 spilt and rematerializable or code for
11800 this has already been generated then
11802 if (resultRemat (ic) || ic->generated)
11805 /* depending on the operation */
11825 /* IPOP happens only when trying to restore a
11826 spilt live range, if there is an ifx statement
11827 following this pop then the if statement might
11828 be using some of the registers being popped which
11829 would destory the contents of the register so
11830 we need to check for this condition and handle it */
11832 ic->next->op == IFX &&
11833 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11834 genIfx (ic->next, ic);
11852 genEndFunction (ic);
11872 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11889 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11893 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11900 /* note these two are xlated by algebraic equivalence
11901 in decorateType() in SDCCast.c */
11902 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11903 "got '>=' or '<=' shouldn't have come here");
11907 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11919 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11923 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11927 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11963 genRightShift (ic);
11966 case GET_VALUE_AT_ADDRESS:
11968 hasInc (IC_LEFT (ic), ic,
11969 getSize (operandType (IC_RESULT (ic)))),
11970 ifxForOp (IC_RESULT (ic), ic) );
11974 if (POINTER_SET (ic))
11976 hasInc (IC_RESULT (ic), ic,
11977 getSize (operandType (IC_RIGHT (ic)))));
12003 addSet (&_G.sendSet, ic);
12006 case DUMMY_READ_VOLATILE:
12015 genEndCritical (ic);
12027 _G.current_iCode = NULL;
12029 /* now we are ready to call the
12030 peep hole optimizer */
12031 if (!options.nopeep)
12032 peepHole (&lineHead);
12034 /* now do the actual printing */
12035 printLine (lineHead, codeOutBuf);