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)
1645 emitcode ("push", "acc");
1649 emitcode ("push", "acc");
1651 emitcode ("push", s);
1657 /* if not bit variable */
1658 if (!aop->aopu.aop_dir)
1660 /* inefficient: move carry into A and use jz/jnz */
1661 emitcode ("clr", "a");
1662 emitcode ("rlc", "a");
1668 emitcode ("clr", "%s", aop->aopu.aop_dir);
1670 emitcode ("setb", "%s", aop->aopu.aop_dir);
1671 else if (!strcmp (s, "c"))
1672 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1673 else if (strcmp (s, aop->aopu.aop_dir))
1676 /* set C, if a >= 1 */
1677 emitcode ("add", "a,#0xff");
1678 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1685 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1686 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1692 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1695 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1696 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1700 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1701 "aopPut got unsupported aop->type");
1710 /*-----------------------------------------------------------------*/
1711 /* pointToEnd :- points to the last byte of the operand */
1712 /*-----------------------------------------------------------------*/
1714 pointToEnd (asmop * aop)
1720 aop->coff = count = (aop->size - 1);
1726 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1730 emitcode ("inc", "dptr");
1737 /*-----------------------------------------------------------------*/
1738 /* reAdjustPreg - points a register back to where it should */
1739 /*-----------------------------------------------------------------*/
1741 reAdjustPreg (asmop * aop)
1743 if ((aop->coff==0) || (aop->size <= 1))
1751 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1756 emitcode ("lcall", "__decdptr");
1763 /*-----------------------------------------------------------------*/
1764 /* opIsGptr: returns non-zero if the passed operand is */
1765 /* a generic pointer type. */
1766 /*-----------------------------------------------------------------*/
1768 opIsGptr (operand * op)
1770 sym_link *type = operandType (op);
1772 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1779 /*-----------------------------------------------------------------*/
1780 /* getDataSize - get the operand data size */
1781 /*-----------------------------------------------------------------*/
1783 getDataSize (operand * op)
1786 size = AOP_SIZE (op);
1787 if (size == GPTRSIZE)
1789 sym_link *type = operandType (op);
1790 if (IS_GENPTR (type))
1792 /* generic pointer; arithmetic operations
1793 * should ignore the high byte (pointer type).
1801 /*-----------------------------------------------------------------*/
1802 /* outAcc - output Acc */
1803 /*-----------------------------------------------------------------*/
1805 outAcc (operand * result)
1808 size = getDataSize (result);
1811 aopPut (result, "a", 0);
1814 /* unsigned or positive */
1817 aopPut (result, zero, offset++);
1822 /*-----------------------------------------------------------------*/
1823 /* outBitC - output a bit C */
1824 /*-----------------------------------------------------------------*/
1826 outBitC (operand * result)
1828 /* if the result is bit */
1829 if (AOP_TYPE (result) == AOP_CRY)
1831 aopPut (result, "c", 0);
1835 emitcode ("clr", "a");
1836 emitcode ("rlc", "a");
1841 /*-----------------------------------------------------------------*/
1842 /* toBoolean - emit code for orl a,operator(sizeop) */
1843 /*-----------------------------------------------------------------*/
1845 toBoolean (operand * oper)
1847 int size = AOP_SIZE (oper) - 1;
1849 bool AccUsed = FALSE;
1852 while (!AccUsed && size--)
1854 AccUsed |= aopGetUsesAcc(oper, offset++);
1857 size = AOP_SIZE (oper) - 1;
1859 MOVA (aopGet (oper, 0, FALSE, FALSE));
1860 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1863 emitcode("mov", "b,a");
1866 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1867 emitcode ("orl", "b,a");
1869 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1870 emitcode ("orl", "a,b");
1877 emitcode ("orl", "a,%s",
1878 aopGet (oper, offset++, FALSE, FALSE));
1884 /*-------------------------------------------------------------------*/
1885 /* xch_a_aopGet - for exchanging acc with value of the aop */
1886 /*-------------------------------------------------------------------*/
1888 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1892 if (aopGetUsesAcc (oper, offset))
1894 emitcode("mov", "b,a");
1895 MOVA (aopGet (oper, offset, bit16, dname));
1896 emitcode("xch", "a,b");
1897 aopPut (oper, "a", offset);
1898 emitcode("xch", "a,b");
1903 l = aopGet (oper, offset, bit16, dname);
1904 emitcode("xch", "a,%s", l);
1910 /*-----------------------------------------------------------------*/
1911 /* genNot - generate code for ! operation */
1912 /*-----------------------------------------------------------------*/
1918 D (emitcode (";", "genNot"));
1920 /* assign asmOps to operand & result */
1921 aopOp (IC_LEFT (ic), ic, FALSE);
1922 aopOp (IC_RESULT (ic), ic, TRUE);
1924 /* if in bit space then a special case */
1925 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1927 /* if left==result then cpl bit */
1928 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1930 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1934 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1935 emitcode ("cpl", "c");
1936 outBitC (IC_RESULT (ic));
1941 toBoolean (IC_LEFT (ic));
1943 /* set C, if a == 0 */
1944 tlbl = newiTempLabel (NULL);
1945 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1947 outBitC (IC_RESULT (ic));
1950 /* release the aops */
1951 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1952 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1956 /*-----------------------------------------------------------------*/
1957 /* genCpl - generate code for complement */
1958 /*-----------------------------------------------------------------*/
1965 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1967 D(emitcode (";", "genCpl"));
1969 /* assign asmOps to operand & result */
1970 aopOp (IC_LEFT (ic), ic, FALSE);
1971 aopOp (IC_RESULT (ic), ic, TRUE);
1973 /* special case if in bit space */
1974 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1978 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1979 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1981 /* promotion rules are responsible for this strange result:
1982 bit -> int -> ~int -> bit
1983 uchar -> int -> ~int -> bit
1985 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1989 tlbl=newiTempLabel(NULL);
1990 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1991 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1992 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1993 IS_AOP_PREG (IC_LEFT (ic)))
1995 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2000 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2003 outBitC (IC_RESULT(ic));
2007 size = AOP_SIZE (IC_RESULT (ic));
2010 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2012 emitcode ("cpl", "a");
2013 aopPut (IC_RESULT (ic), "a", offset++);
2018 /* release the aops */
2019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2020 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2023 /*-----------------------------------------------------------------*/
2024 /* genUminusFloat - unary minus for floating points */
2025 /*-----------------------------------------------------------------*/
2027 genUminusFloat (operand * op, operand * result)
2029 int size, offset = 0;
2032 D (emitcode (";", "genUminusFloat"));
2034 /* for this we just copy and then flip the bit */
2036 size = AOP_SIZE (op) - 1;
2041 aopGet (op, offset, FALSE, FALSE),
2046 l = aopGet (op, offset, FALSE, FALSE);
2049 emitcode ("cpl", "acc.7");
2050 aopPut (result, "a", offset);
2053 /*-----------------------------------------------------------------*/
2054 /* genUminus - unary minus code generation */
2055 /*-----------------------------------------------------------------*/
2057 genUminus (iCode * ic)
2062 D (emitcode (";", "genUminus"));
2065 aopOp (IC_LEFT (ic), ic, FALSE);
2066 aopOp (IC_RESULT (ic), ic, TRUE);
2068 /* if both in bit space then special
2070 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2071 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2074 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2075 emitcode ("cpl", "c");
2076 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2080 optype = operandType (IC_LEFT (ic));
2082 /* if float then do float stuff */
2083 if (IS_FLOAT (optype))
2085 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2089 /* otherwise subtract from zero */
2090 size = AOP_SIZE (IC_LEFT (ic));
2094 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2095 if (!strcmp (l, "a"))
2099 emitcode ("cpl", "a");
2100 emitcode ("addc", "a,#0");
2106 emitcode ("clr", "a");
2107 emitcode ("subb", "a,%s", l);
2109 aopPut (IC_RESULT (ic), "a", offset++);
2112 /* if any remaining bytes in the result */
2113 /* we just need to propagate the sign */
2114 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2116 emitcode ("rlc", "a");
2117 emitcode ("subb", "a,acc");
2119 aopPut (IC_RESULT (ic), "a", offset++);
2123 /* release the aops */
2124 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2125 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2128 /*-----------------------------------------------------------------*/
2129 /* saveRegisters - will look for a call and save the registers */
2130 /*-----------------------------------------------------------------*/
2132 saveRegisters (iCode * lic)
2139 for (ic = lic; ic; ic = ic->next)
2140 if (ic->op == CALL || ic->op == PCALL)
2145 fprintf (stderr, "found parameter push with no function call\n");
2149 /* if the registers have been saved already or don't need to be then
2153 if (IS_SYMOP(IC_LEFT(ic)) &&
2154 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2155 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2158 /* save the registers in use at this time but skip the
2159 ones for the result */
2160 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2161 mcs51_rUmaskForOp (IC_RESULT(ic)));
2164 if (options.useXstack)
2166 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2167 int nBits = bitVectnBitsOn (rsavebits);
2168 int count = bitVectnBitsOn (rsave);
2172 count = count - nBits + 1;
2173 /* remove all but the first bits as they are pushed all at once */
2174 rsave = bitVectCplAnd (rsave, rsavebits);
2175 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2180 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2181 if (reg->type == REG_BIT)
2183 emitcode ("mov", "a,%s", reg->base);
2187 emitcode ("mov", "a,%s", reg->name);
2189 emitcode ("mov", "r0,%s", spname);
2190 emitcode ("inc", "%s", spname);// allocate before use
2191 emitcode ("movx", "@r0,a");
2192 if (bitVectBitValue (rsave, R0_IDX))
2193 emitcode ("mov", "r0,a");
2195 else if (count != 0)
2197 if (bitVectBitValue (rsave, R0_IDX))
2199 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2201 emitcode ("mov", "r0,%s", spname);
2203 emitcode ("add", "a,#%d", count);
2204 emitcode ("mov", "%s,a", spname);
2205 for (i = 0; i < mcs51_nRegs; i++)
2207 if (bitVectBitValue (rsave, i))
2209 regs * reg = REG_WITH_INDEX (i);
2212 emitcode ("pop", "acc");
2213 emitcode ("push", "acc");
2215 else if (reg->type == REG_BIT)
2217 emitcode ("mov", "a,%s", reg->base);
2221 emitcode ("mov", "a,%s", reg->name);
2223 emitcode ("movx", "@r0,a");
2226 emitcode ("inc", "r0");
2230 if (bitVectBitValue (rsave, R0_IDX))
2232 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2238 bool bits_pushed = FALSE;
2239 for (i = 0; i < mcs51_nRegs; i++)
2241 if (bitVectBitValue (rsave, i))
2243 bits_pushed = pushReg (i, bits_pushed);
2249 /*-----------------------------------------------------------------*/
2250 /* unsaveRegisters - pop the pushed registers */
2251 /*-----------------------------------------------------------------*/
2253 unsaveRegisters (iCode * ic)
2258 /* restore the registers in use at this time but skip the
2259 ones for the result */
2260 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2261 mcs51_rUmaskForOp (IC_RESULT(ic)));
2263 if (options.useXstack)
2265 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2266 int nBits = bitVectnBitsOn (rsavebits);
2267 int count = bitVectnBitsOn (rsave);
2271 count = count - nBits + 1;
2272 /* remove all but the first bits as they are popped all at once */
2273 rsave = bitVectCplAnd (rsave, rsavebits);
2274 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2279 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2280 emitcode ("mov", "r0,%s", spname);
2281 emitcode ("dec", "r0");
2282 emitcode ("movx", "a,@r0");
2283 if (reg->type == REG_BIT)
2285 emitcode ("mov", "%s,a", reg->base);
2289 emitcode ("mov", "%s,a", reg->name);
2291 emitcode ("dec", "%s", spname);
2293 else if (count != 0)
2295 emitcode ("mov", "r0,%s", spname);
2296 for (i = mcs51_nRegs; i >= 0; i--)
2298 if (bitVectBitValue (rsave, i))
2300 regs * reg = REG_WITH_INDEX (i);
2301 emitcode ("dec", "r0");
2302 emitcode ("movx", "a,@r0");
2305 emitcode ("push", "acc");
2307 else if (reg->type == REG_BIT)
2309 emitcode ("mov", "%s,a", reg->base);
2313 emitcode ("mov", "%s,a", reg->name);
2317 emitcode ("mov", "%s,r0", spname);
2318 if (bitVectBitValue (rsave, R0_IDX))
2320 emitcode ("pop", "ar0");
2326 bool bits_popped = FALSE;
2327 for (i = mcs51_nRegs; i >= 0; i--)
2329 if (bitVectBitValue (rsave, i))
2331 bits_popped = popReg (i, bits_popped);
2338 /*-----------------------------------------------------------------*/
2340 /*-----------------------------------------------------------------*/
2342 pushSide (operand * oper, int size)
2347 char *l = aopGet (oper, offset++, FALSE, TRUE);
2348 if (AOP_TYPE (oper) != AOP_REG &&
2349 AOP_TYPE (oper) != AOP_DIR &&
2353 emitcode ("push", "acc");
2357 emitcode ("push", "%s", l);
2362 /*-----------------------------------------------------------------*/
2363 /* assignResultValue - also indicates if acc is in use afterwards */
2364 /*-----------------------------------------------------------------*/
2366 assignResultValue (operand * oper, operand * func)
2369 int size = AOP_SIZE (oper);
2370 bool accuse = FALSE;
2371 bool pushedA = FALSE;
2373 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2379 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2381 emitcode ("push", "acc");
2386 if ((offset == 3) && pushedA)
2387 emitcode ("pop", "acc");
2388 accuse |= aopPut (oper, fReturn[offset], offset);
2395 /*-----------------------------------------------------------------*/
2396 /* genXpush - pushes onto the external stack */
2397 /*-----------------------------------------------------------------*/
2399 genXpush (iCode * ic)
2401 asmop *aop = newAsmop (0);
2403 int size, offset = 0;
2405 D (emitcode (";", "genXpush"));
2407 aopOp (IC_LEFT (ic), ic, FALSE);
2408 r = getFreePtr (ic, &aop, FALSE);
2410 size = AOP_SIZE (IC_LEFT (ic));
2414 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2415 emitcode ("mov", "%s,%s", r->name, spname);
2416 emitcode ("inc", "%s", spname); // allocate space first
2417 emitcode ("movx", "@%s,a", r->name);
2421 // allocate space first
2422 emitcode ("mov", "%s,%s", r->name, spname);
2424 emitcode ("add", "a,#%d", size);
2425 emitcode ("mov", "%s,a", spname);
2429 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2430 emitcode ("movx", "@%s,a", r->name);
2431 emitcode ("inc", "%s", r->name);
2435 freeAsmop (NULL, aop, ic, TRUE);
2436 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2439 /*-----------------------------------------------------------------*/
2440 /* genIpush - generate code for pushing this gets a little complex */
2441 /*-----------------------------------------------------------------*/
2443 genIpush (iCode * ic)
2445 int size, offset = 0;
2449 D (emitcode (";", "genIpush"));
2451 /* if this is not a parm push : ie. it is spill push
2452 and spill push is always done on the local stack */
2456 /* and the item is spilt then do nothing */
2457 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2460 aopOp (IC_LEFT (ic), ic, FALSE);
2461 size = AOP_SIZE (IC_LEFT (ic));
2462 /* push it on the stack */
2465 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2471 emitcode ("push", "%s", l);
2476 /* this is a parameter push: in this case we call
2477 the routine to find the call and save those
2478 registers that need to be saved */
2481 /* if use external stack then call the external
2482 stack pushing routine */
2483 if (options.useXstack)
2489 /* then do the push */
2490 aopOp (IC_LEFT (ic), ic, FALSE);
2492 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2493 size = AOP_SIZE (IC_LEFT (ic));
2497 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2498 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2499 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2501 if (strcmp (l, prev) || *l == '@')
2503 emitcode ("push", "acc");
2507 emitcode ("push", "%s", l);
2512 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2515 /*-----------------------------------------------------------------*/
2516 /* genIpop - recover the registers: can happen only for spilling */
2517 /*-----------------------------------------------------------------*/
2519 genIpop (iCode * ic)
2523 D (emitcode (";", "genIpop"));
2525 /* if the temp was not pushed then */
2526 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2529 aopOp (IC_LEFT (ic), ic, FALSE);
2530 size = AOP_SIZE (IC_LEFT (ic));
2531 offset = (size - 1);
2534 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2541 /*-----------------------------------------------------------------*/
2542 /* saveRBank - saves an entire register bank on the stack */
2543 /*-----------------------------------------------------------------*/
2545 saveRBank (int bank, iCode * ic, bool pushPsw)
2548 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2552 if (options.useXstack)
2556 /* Assume r0 is available for use. */
2557 r = REG_WITH_INDEX (R0_IDX);;
2562 r = getFreePtr (ic, &aop, FALSE);
2564 // allocate space first
2565 emitcode ("mov", "%s,%s", r->name, spname);
2567 emitcode ("add", "a,#%d", count);
2568 emitcode ("mov", "%s,a", spname);
2571 for (i = 0; i < 8; i++)
2573 if (options.useXstack)
2575 emitcode ("mov", "a,(%s+%d)",
2576 regs8051[i].base, 8 * bank + regs8051[i].offset);
2577 emitcode ("movx", "@%s,a", r->name);
2579 emitcode ("inc", "%s", r->name);
2582 emitcode ("push", "(%s+%d)",
2583 regs8051[i].base, 8 * bank + regs8051[i].offset);
2586 if (mcs51_nRegs > 8)
2588 if (options.useXstack)
2590 emitcode ("mov", "a,bits");
2591 emitcode ("movx", "@%s,a", r->name);
2593 emitcode ("inc", "%s", r->name);
2597 emitcode ("push", "bits");
2604 if (options.useXstack)
2606 emitcode ("mov", "a,psw");
2607 emitcode ("movx", "@%s,a", r->name);
2611 emitcode ("push", "psw");
2614 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2619 freeAsmop (NULL, aop, ic, TRUE);
2628 /*-----------------------------------------------------------------*/
2629 /* unsaveRBank - restores the register bank from stack */
2630 /*-----------------------------------------------------------------*/
2632 unsaveRBank (int bank, iCode * ic, bool popPsw)
2638 if (options.useXstack)
2642 /* Assume r0 is available for use. */
2643 r = REG_WITH_INDEX (R0_IDX);;
2648 r = getFreePtr (ic, &aop, FALSE);
2650 emitcode ("mov", "%s,%s", r->name, spname);
2655 if (options.useXstack)
2657 emitcode ("dec", "%s", r->name);
2658 emitcode ("movx", "a,@%s", r->name);
2659 emitcode ("mov", "psw,a");
2663 emitcode ("pop", "psw");
2667 if (mcs51_nRegs > 8)
2669 if (options.useXstack)
2671 emitcode ("dec", "%s", r->name);
2672 emitcode ("movx", "a,@%s", r->name);
2673 emitcode ("mov", "bits,a");
2677 emitcode ("pop", "bits");
2681 for (i = 7; i >= 0; i--)
2683 if (options.useXstack)
2685 emitcode ("dec", "%s", r->name);
2686 emitcode ("movx", "a,@%s", r->name);
2687 emitcode ("mov", "(%s+%d),a",
2688 regs8051[i].base, 8 * bank + regs8051[i].offset);
2692 emitcode ("pop", "(%s+%d)",
2693 regs8051[i].base, 8 * bank + regs8051[i].offset);
2697 if (options.useXstack)
2699 emitcode ("mov", "%s,%s", spname, r->name);
2704 freeAsmop (NULL, aop, ic, TRUE);
2708 /*-----------------------------------------------------------------*/
2709 /* genSend - gen code for SEND */
2710 /*-----------------------------------------------------------------*/
2711 static void genSend(set *sendSet)
2716 /* first we do all bit parameters */
2717 for (sic = setFirstItem (sendSet); sic;
2718 sic = setNextItem (sendSet))
2720 if (sic->argreg > 12)
2722 int bit = sic->argreg-13;
2724 aopOp (IC_LEFT (sic), sic, FALSE);
2726 /* if left is a literal then
2727 we know what the value is */
2728 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2730 if (((int) operandLitValue (IC_LEFT (sic))))
2731 emitcode ("setb", "b[%d]", bit);
2733 emitcode ("clr", "b[%d]", bit);
2735 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2737 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2738 if (strcmp (l, "c"))
2739 emitcode ("mov", "c,%s", l);
2740 emitcode ("mov", "b[%d],c", bit);
2745 toBoolean (IC_LEFT (sic));
2746 /* set C, if a >= 1 */
2747 emitcode ("add", "a,#0xff");
2748 emitcode ("mov", "b[%d],c", bit);
2753 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2759 saveRegisters (setFirstItem (sendSet));
2760 emitcode ("mov", "bits,b");
2763 /* then we do all other parameters */
2764 for (sic = setFirstItem (sendSet); sic;
2765 sic = setNextItem (sendSet))
2767 if (sic->argreg <= 12)
2769 int size, offset = 0;
2770 aopOp (IC_LEFT (sic), sic, FALSE);
2771 size = AOP_SIZE (IC_LEFT (sic));
2773 if (sic->argreg == 1)
2777 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2778 if (strcmp (l, fReturn[offset]))
2780 emitcode ("mov", "%s,%s", fReturn[offset], l);
2789 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2790 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2794 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2799 /*-----------------------------------------------------------------*/
2800 /* selectRegBank - emit code to select the register bank */
2801 /*-----------------------------------------------------------------*/
2803 selectRegBank (short bank, bool keepFlags)
2805 /* if f.e. result is in carry */
2808 emitcode ("anl", "psw,#0xE7");
2810 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2814 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2818 /*-----------------------------------------------------------------*/
2819 /* genCall - generates a call statement */
2820 /*-----------------------------------------------------------------*/
2822 genCall (iCode * ic)
2826 // bool restoreBank = FALSE;
2827 bool swapBanks = FALSE;
2828 bool accuse = FALSE;
2829 bool accPushed = FALSE;
2830 bool resultInF0 = FALSE;
2831 bool assignResultGenerated = FALSE;
2833 D (emitcode (";", "genCall"));
2835 dtype = operandType (IC_LEFT (ic));
2836 etype = getSpec(dtype);
2837 /* if send set is not empty then assign */
2840 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2841 genSend(reverseSet(_G.sendSet));
2843 genSend(_G.sendSet);
2848 /* if we are calling a not _naked function that is not using
2849 the same register bank then we need to save the
2850 destination registers on the stack */
2851 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2852 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2853 !IFFUNC_ISISR (dtype))
2858 /* if caller saves & we have not saved then */
2864 emitcode ("mov", "psw,#0x%02x",
2865 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2869 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2871 if (IFFUNC_CALLEESAVES(dtype))
2873 werror (E_BANKED_WITH_CALLEESAVES);
2877 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2878 OP_SYMBOL (IC_LEFT (ic))->rname :
2879 OP_SYMBOL (IC_LEFT (ic))->name);
2881 emitcode ("mov", "r0,#%s", l);
2882 emitcode ("mov", "r1,#(%s >> 8)", l);
2883 emitcode ("mov", "r2,#(%s >> 16)", l);
2884 emitcode ("lcall", "__sdcc_banked_call");
2889 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2890 OP_SYMBOL (IC_LEFT (ic))->rname :
2891 OP_SYMBOL (IC_LEFT (ic))->name));
2896 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2899 /* if we need assign a result value */
2900 if ((IS_ITEMP (IC_RESULT (ic)) &&
2901 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2902 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2903 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2904 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2905 IS_TRUE_SYMOP (IC_RESULT (ic)))
2909 aopOp (IC_RESULT (ic), ic, FALSE);
2912 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2913 assignResultGenerated = TRUE;
2915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2918 /* adjust the stack for parameters if required */
2922 if (ic->parmBytes > 3)
2926 emitcode ("push", "acc");
2929 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2930 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2931 !assignResultGenerated)
2933 emitcode ("mov", "F0,c");
2937 emitcode ("mov", "a,%s", spname);
2938 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2939 emitcode ("mov", "%s,a", spname);
2941 /* unsaveRegisters from xstack needs acc, but */
2942 /* unsaveRegisters from stack needs this popped */
2943 if (accPushed && !options.useXstack)
2945 emitcode ("pop", "acc");
2950 for (i = 0; i < ic->parmBytes; i++)
2951 emitcode ("dec", "%s", spname);
2954 /* if we had saved some registers then unsave them */
2955 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2957 if (accuse && !accPushed && options.useXstack)
2959 /* xstack needs acc, but doesn't touch normal stack */
2960 emitcode ("push", "acc");
2963 unsaveRegisters (ic);
2966 // /* if register bank was saved then pop them */
2968 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2970 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2973 emitcode ("mov", "c,F0");
2975 aopOp (IC_RESULT (ic), ic, FALSE);
2976 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2977 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2981 emitcode ("pop", "acc");
2984 /*-----------------------------------------------------------------*/
2985 /* genPcall - generates a call by pointer statement */
2986 /*-----------------------------------------------------------------*/
2988 genPcall (iCode * ic)
2992 symbol *rlbl = newiTempLabel (NULL);
2993 // bool restoreBank=FALSE;
2994 bool swapBanks = FALSE;
2995 bool resultInF0 = FALSE;
2997 D (emitcode (";", "genPcall"));
2999 dtype = operandType (IC_LEFT (ic))->next;
3000 etype = getSpec(dtype);
3001 /* if caller saves & we have not saved then */
3005 /* if we are calling a not _naked function that is not using
3006 the same register bank then we need to save the
3007 destination registers on the stack */
3008 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3009 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3010 !IFFUNC_ISISR (dtype))
3012 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3013 // restoreBank=TRUE;
3015 // need caution message to user here
3018 if (IS_LITERAL(etype))
3020 /* if send set is not empty then assign */
3023 genSend(reverseSet(_G.sendSet));
3029 emitcode ("mov", "psw,#0x%02x",
3030 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3033 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3035 if (IFFUNC_CALLEESAVES(dtype))
3037 werror (E_BANKED_WITH_CALLEESAVES);
3041 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3043 emitcode ("mov", "r0,#%s", l);
3044 emitcode ("mov", "r1,#(%s >> 8)", l);
3045 emitcode ("mov", "r2,#(%s >> 16)", l);
3046 emitcode ("lcall", "__sdcc_banked_call");
3051 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3056 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3058 if (IFFUNC_CALLEESAVES(dtype))
3060 werror (E_BANKED_WITH_CALLEESAVES);
3064 aopOp (IC_LEFT (ic), ic, FALSE);
3068 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3069 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3070 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3074 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3075 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3076 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3077 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3080 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3082 /* if send set is not empty then assign */
3085 genSend(reverseSet(_G.sendSet));
3091 emitcode ("mov", "psw,#0x%02x",
3092 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3096 emitcode ("lcall", "__sdcc_banked_call");
3101 /* push the return address on to the stack */
3102 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3103 emitcode ("push", "acc");
3104 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3105 emitcode ("push", "acc");
3107 /* now push the calling address */
3108 aopOp (IC_LEFT (ic), ic, FALSE);
3110 pushSide (IC_LEFT (ic), FPTRSIZE);
3112 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3114 /* if send set is not empty the assign */
3117 genSend(reverseSet(_G.sendSet));
3123 emitcode ("mov", "psw,#0x%02x",
3124 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3128 emitcode ("ret", "");
3134 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3137 /* if we need assign a result value */
3138 if ((IS_ITEMP (IC_RESULT (ic)) &&
3139 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3140 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3141 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3142 IS_TRUE_SYMOP (IC_RESULT (ic)))
3146 aopOp (IC_RESULT (ic), ic, FALSE);
3149 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3151 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3154 /* adjust the stack for parameters if required */
3158 if (ic->parmBytes > 3)
3160 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3161 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3163 emitcode ("mov", "F0,c");
3167 emitcode ("mov", "a,%s", spname);
3168 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3169 emitcode ("mov", "%s,a", spname);
3172 for (i = 0; i < ic->parmBytes; i++)
3173 emitcode ("dec", "%s", spname);
3176 // /* if register bank was saved then unsave them */
3178 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3180 /* if we had saved some registers then unsave them */
3181 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3182 unsaveRegisters (ic);
3184 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3187 emitcode ("mov", "c,F0");
3189 aopOp (IC_RESULT (ic), ic, FALSE);
3190 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3195 /*-----------------------------------------------------------------*/
3196 /* resultRemat - result is rematerializable */
3197 /*-----------------------------------------------------------------*/
3199 resultRemat (iCode * ic)
3201 if (SKIP_IC (ic) || ic->op == IFX)
3204 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3206 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3207 if (sym->remat && !POINTER_SET (ic))
3214 #if defined(__BORLANDC__) || defined(_MSC_VER)
3215 #define STRCASECMP stricmp
3217 #define STRCASECMP strcasecmp
3220 /*-----------------------------------------------------------------*/
3221 /* inExcludeList - return 1 if the string is in exclude Reg list */
3222 /*-----------------------------------------------------------------*/
3224 regsCmp(void *p1, void *p2)
3226 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3230 inExcludeList (char *s)
3232 const char *p = setFirstItem(options.excludeRegsSet);
3234 if (p == NULL || STRCASECMP(p, "none") == 0)
3238 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3241 /*-----------------------------------------------------------------*/
3242 /* genFunction - generated code for function entry */
3243 /*-----------------------------------------------------------------*/
3245 genFunction (iCode * ic)
3247 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3249 bool switchedPSW = FALSE;
3250 int calleesaves_saved_register = -1;
3251 int stackAdjust = sym->stack;
3252 int accIsFree = sym->recvSize < 4;
3253 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3254 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3257 /* create the function header */
3258 emitcode (";", "-----------------------------------------");
3259 emitcode (";", " function %s", sym->name);
3260 emitcode (";", "-----------------------------------------");
3262 emitcode ("", "%s:", sym->rname);
3263 lineCurr->isLabel = 1;
3264 ftype = operandType (IC_LEFT (ic));
3265 _G.currentFunc = sym;
3267 if (IFFUNC_ISNAKED(ftype))
3269 emitcode(";", "naked function: no prologue.");
3273 /* here we need to generate the equates for the
3274 register bank if required */
3275 if (FUNC_REGBANK (ftype) != rbank)
3279 rbank = FUNC_REGBANK (ftype);
3280 for (i = 0; i < mcs51_nRegs; i++)
3282 if (regs8051[i].type != REG_BIT)
3284 if (strcmp (regs8051[i].base, "0") == 0)
3285 emitcode ("", "%s = 0x%02x",
3287 8 * rbank + regs8051[i].offset);
3289 emitcode ("", "%s = %s + 0x%02x",
3292 8 * rbank + regs8051[i].offset);
3297 /* if this is an interrupt service routine then
3298 save acc, b, dpl, dph */
3299 if (IFFUNC_ISISR (sym->type))
3301 if (!inExcludeList ("acc"))
3302 emitcode ("push", "acc");
3303 if (!inExcludeList ("b"))
3304 emitcode ("push", "b");
3305 if (!inExcludeList ("dpl"))
3306 emitcode ("push", "dpl");
3307 if (!inExcludeList ("dph"))
3308 emitcode ("push", "dph");
3309 /* if this isr has no bank i.e. is going to
3310 run with bank 0 , then we need to save more
3312 if (!FUNC_REGBANK (sym->type))
3316 /* if this function does not call any other
3317 function then we can be economical and
3318 save only those registers that are used */
3319 if (!IFFUNC_HASFCALL(sym->type))
3321 /* if any registers used */
3324 bool bits_pushed = FALSE;
3325 /* save the registers used */
3326 for (i = 0; i < sym->regsUsed->size; i++)
3328 if (bitVectBitValue (sym->regsUsed, i))
3329 bits_pushed = pushReg (i, bits_pushed);
3335 /* this function has a function call. We cannot
3336 determine register usage so we will have to push the
3338 saveRBank (0, ic, FALSE);
3339 if (options.parms_in_bank1) {
3340 for (i=0; i < 8 ; i++ ) {
3341 emitcode ("push","%s",rb1regs[i]);
3348 /* This ISR uses a non-zero bank.
3350 * We assume that the bank is available for our
3353 * However, if this ISR calls a function which uses some
3354 * other bank, we must save that bank entirely.
3356 unsigned long banksToSave = 0;
3358 if (IFFUNC_HASFCALL(sym->type))
3361 #define MAX_REGISTER_BANKS 4
3366 for (i = ic; i; i = i->next)
3368 if (i->op == ENDFUNCTION)
3370 /* we got to the end OK. */
3378 dtype = operandType (IC_LEFT(i));
3380 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3382 /* Mark this bank for saving. */
3383 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3385 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3389 banksToSave |= (1 << FUNC_REGBANK(dtype));
3392 /* And note that we don't need to do it in
3400 /* This is a mess; we have no idea what
3401 * register bank the called function might
3404 * The only thing I can think of to do is
3405 * throw a warning and hope.
3407 werror(W_FUNCPTR_IN_USING_ISR);
3411 if (banksToSave && options.useXstack)
3413 /* Since we aren't passing it an ic,
3414 * saveRBank will assume r0 is available to abuse.
3416 * So switch to our (trashable) bank now, so
3417 * the caller's R0 isn't trashed.
3419 emitcode ("push", "psw");
3420 emitcode ("mov", "psw,#0x%02x",
3421 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3425 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3427 if (banksToSave & (1 << ix))
3429 saveRBank(ix, NULL, FALSE);
3433 // TODO: this needs a closer look
3434 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3437 /* Set the register bank to the desired value if nothing else */
3438 /* has done so yet. */
3441 emitcode ("push", "psw");
3442 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3447 /* This is a non-ISR function. The caller has already switched register */
3448 /* banks, if necessary, so just handle the callee-saves option. */
3450 /* if callee-save to be used for this function
3451 then save the registers being used in this function */
3452 if (IFFUNC_CALLEESAVES(sym->type))
3456 /* if any registers used */
3459 bool bits_pushed = FALSE;
3460 /* save the registers used */
3461 for (i = 0; i < sym->regsUsed->size; i++)
3463 if (bitVectBitValue (sym->regsUsed, i))
3465 /* remember one saved register for later usage */
3466 if (calleesaves_saved_register < 0)
3467 calleesaves_saved_register = i;
3468 bits_pushed = pushReg (i, bits_pushed);
3478 if (options.useXstack)
3480 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3482 emitcode ("mov", "r0,%s", spname);
3483 emitcode ("inc", "%s", spname);
3484 emitcode ("xch", "a,_bpx");
3485 emitcode ("movx", "@r0,a");
3486 emitcode ("inc", "r0");
3487 emitcode ("mov", "a,r0");
3488 emitcode ("xch", "a,_bpx");
3492 emitcode ("push", "_bp"); /* save the callers stack */
3493 emitcode ("mov", "_bp,sp");
3498 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3500 /* set up the stack */
3501 emitcode ("push", "_bp"); /* save the callers stack */
3502 emitcode ("mov", "_bp,sp");
3507 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3508 /* before setting up the stack frame completely. */
3509 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3511 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3515 if (rsym && rsym->regType == REG_CND)
3517 if (rsym && (rsym->accuse || rsym->ruonly))
3519 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3520 rsym = rsym->usl.spillLoc;
3523 /* If the RECEIVE operand immediately spills to the first entry on the */
3524 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3525 /* rather than the usual @r0/r1 machinations. */
3526 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3530 _G.current_iCode = ric;
3531 D(emitcode ("; genReceive",""));
3532 for (ofs=0; ofs < sym->recvSize; ofs++)
3534 if (!strcmp (fReturn[ofs], "a"))
3535 emitcode ("push", "acc");
3537 emitcode ("push", fReturn[ofs]);
3539 stackAdjust -= sym->recvSize;
3542 assert (stackAdjust>=0);
3545 _G.current_iCode = ic;
3549 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3550 /* to free up the accumulator. */
3551 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3555 _G.current_iCode = ric;
3556 D(emitcode ("; genReceive",""));
3557 for (ofs=0; ofs < sym->recvSize; ofs++)
3559 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3561 _G.current_iCode = ic;
3567 /* adjust the stack for the function */
3570 int i = stackAdjust;
3572 werror (W_STACK_OVERFLOW, sym->name);
3574 if (i > 3 && accIsFree)
3576 emitcode ("mov", "a,sp");
3577 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3578 emitcode ("mov", "sp,a");
3582 /* The accumulator is not free, so we will need another register */
3583 /* to clobber. No need to worry about a possible conflict with */
3584 /* the above early RECEIVE optimizations since they would have */
3585 /* freed the accumulator if they were generated. */
3587 if (IFFUNC_CALLEESAVES(sym->type))
3589 /* if it's a callee-saves function we need a saved register */
3590 if (calleesaves_saved_register >= 0)
3592 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3593 emitcode ("mov", "a,sp");
3594 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3595 emitcode ("mov", "sp,a");
3596 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3599 /* do it the hard way */
3601 emitcode ("inc", "sp");
3605 /* not callee-saves, we can clobber r0 */
3606 emitcode ("mov", "r0,a");
3607 emitcode ("mov", "a,sp");
3608 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3609 emitcode ("mov", "sp,a");
3610 emitcode ("mov", "a,r0");
3615 emitcode ("inc", "sp");
3620 char i = ((char) sym->xstack & 0xff);
3622 if (i > 3 && accIsFree)
3624 emitcode ("mov", "a,_spx");
3625 emitcode ("add", "a,#0x%02x", i & 0xff);
3626 emitcode ("mov", "_spx,a");
3630 emitcode ("push", "acc");
3631 emitcode ("mov", "a,_spx");
3632 emitcode ("add", "a,#0x%02x", i & 0xff);
3633 emitcode ("mov", "_spx,a");
3634 emitcode ("pop", "acc");
3639 emitcode ("inc", "_spx");
3643 /* if critical function then turn interrupts off */
3644 if (IFFUNC_ISCRITICAL (ftype))
3646 symbol *tlbl = newiTempLabel (NULL);
3647 emitcode ("setb", "c");
3648 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3649 emitcode ("clr", "c");
3651 emitcode ("push", "psw"); /* save old ea via c in psw */
3655 /*-----------------------------------------------------------------*/
3656 /* genEndFunction - generates epilogue for functions */
3657 /*-----------------------------------------------------------------*/
3659 genEndFunction (iCode * ic)
3661 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3662 lineNode *lnp = lineCurr;
3664 bitVect *regsUsedPrologue;
3665 bitVect *regsUnneeded;
3668 _G.currentFunc = NULL;
3669 if (IFFUNC_ISNAKED(sym->type))
3671 emitcode(";", "naked function: no epilogue.");
3672 if (options.debug && currFunc)
3673 debugFile->writeEndFunction (currFunc, ic, 0);
3677 if (IFFUNC_ISCRITICAL (sym->type))
3679 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3681 emitcode ("rlc", "a"); /* save c in a */
3682 emitcode ("pop", "psw"); /* restore ea via c in psw */
3683 emitcode ("mov", "ea,c");
3684 emitcode ("rrc", "a"); /* restore c from a */
3688 emitcode ("pop", "psw"); /* restore ea via c in psw */
3689 emitcode ("mov", "ea,c");
3693 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3695 if (options.useXstack)
3699 emitcode ("mov", "sp,_bp");
3700 emitcode ("pop", "_bp");
3702 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3704 emitcode ("xch", "a,_bpx");
3705 emitcode ("mov", "r0,a");
3706 emitcode ("dec", "r0");
3707 emitcode ("movx", "a,@r0");
3708 emitcode ("xch", "a,_bpx");
3709 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3712 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3715 emitcode ("mov", "sp,_bp");
3716 emitcode ("pop", "_bp");
3720 /* restore the register bank */
3721 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3723 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3724 || !options.useXstack)
3726 /* Special case of ISR using non-zero bank with useXstack
3729 emitcode ("pop", "psw");
3733 if (IFFUNC_ISISR (sym->type))
3736 /* now we need to restore the registers */
3737 /* if this isr has no bank i.e. is going to
3738 run with bank 0 , then we need to save more
3740 if (!FUNC_REGBANK (sym->type))
3743 /* if this function does not call any other
3744 function then we can be economical and
3745 save only those registers that are used */
3746 if (!IFFUNC_HASFCALL(sym->type))
3748 /* if any registers used */
3751 bool bits_popped = FALSE;
3752 /* save the registers used */
3753 for (i = sym->regsUsed->size; i >= 0; i--)
3755 if (bitVectBitValue (sym->regsUsed, i))
3756 bits_popped = popReg (i, bits_popped);
3762 if (options.parms_in_bank1) {
3763 for (i = 7 ; i >= 0 ; i-- ) {
3764 emitcode ("pop","%s",rb1regs[i]);
3767 /* this function has a function call cannot
3768 determines register usage so we will have to pop the
3770 unsaveRBank (0, ic, FALSE);
3775 /* This ISR uses a non-zero bank.
3777 * Restore any register banks saved by genFunction
3780 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3783 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3785 if (savedBanks & (1 << ix))
3787 unsaveRBank(ix, NULL, FALSE);
3791 if (options.useXstack)
3793 /* Restore bank AFTER calling unsaveRBank,
3794 * since it can trash r0.
3796 emitcode ("pop", "psw");
3800 if (!inExcludeList ("dph"))
3801 emitcode ("pop", "dph");
3802 if (!inExcludeList ("dpl"))
3803 emitcode ("pop", "dpl");
3804 if (!inExcludeList ("b"))
3805 emitcode ("pop", "b");
3806 if (!inExcludeList ("acc"))
3807 emitcode ("pop", "acc");
3809 /* if debug then send end of function */
3810 if (options.debug && currFunc)
3812 debugFile->writeEndFunction (currFunc, ic, 1);
3815 emitcode ("reti", "");
3819 if (IFFUNC_CALLEESAVES(sym->type))
3823 /* if any registers used */
3826 /* save the registers used */
3827 for (i = sym->regsUsed->size; i >= 0; i--)
3829 if (bitVectBitValue (sym->regsUsed, i) ||
3830 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3831 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3834 else if (mcs51_ptrRegReq)
3836 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3837 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3842 /* if debug then send end of function */
3843 if (options.debug && currFunc)
3845 debugFile->writeEndFunction (currFunc, ic, 1);
3848 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3850 emitcode ("ljmp", "__sdcc_banked_ret");
3854 emitcode ("ret", "");
3858 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3861 /* If this was an interrupt handler using bank 0 that called another */
3862 /* function, then all registers must be saved; nothing to optimized. */
3863 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3864 && !FUNC_REGBANK(sym->type))
3867 /* There are no push/pops to optimize if not callee-saves or ISR */
3868 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3871 /* If there were stack parameters, we cannot optimize without also */
3872 /* fixing all of the stack offsets; this is too dificult to consider. */
3873 if (FUNC_HASSTACKPARM(sym->type))
3876 /* Compute the registers actually used */
3877 regsUsed = newBitVect (mcs51_nRegs);
3878 regsUsedPrologue = newBitVect (mcs51_nRegs);
3881 if (lnp->ic && lnp->ic->op == FUNCTION)
3882 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3884 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3886 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3887 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3894 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3895 && !bitVectBitValue (regsUsed, CND_IDX))
3897 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3898 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3899 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3900 bitVectUnSetBit (regsUsed, CND_IDX);
3903 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3905 /* If this was an interrupt handler that called another function */
3906 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3907 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3909 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3910 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3911 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3912 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3913 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3916 /* Remove the unneeded push/pops */
3917 regsUnneeded = newBitVect (mcs51_nRegs);
3920 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3922 if (!strncmp(lnp->line, "push", 4))
3924 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3925 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3927 connectLine (lnp->prev, lnp->next);
3928 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3931 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3933 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3934 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3936 connectLine (lnp->prev, lnp->next);
3937 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3944 for (idx = 0; idx < regsUnneeded->size; idx++)
3945 if (bitVectBitValue (regsUnneeded, idx))
3946 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3948 freeBitVect (regsUnneeded);
3949 freeBitVect (regsUsed);
3950 freeBitVect (regsUsedPrologue);
3953 /*-----------------------------------------------------------------*/
3954 /* genRet - generate code for return statement */
3955 /*-----------------------------------------------------------------*/
3959 int size, offset = 0, pushed = 0;
3961 D (emitcode (";", "genRet"));
3963 /* if we have no return value then
3964 just generate the "ret" */
3968 /* we have something to return then
3969 move the return value into place */
3970 aopOp (IC_LEFT (ic), ic, FALSE);
3971 size = AOP_SIZE (IC_LEFT (ic));
3973 if (IS_BIT(_G.currentFunc->etype))
3975 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3982 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3985 l = aopGet (IC_LEFT (ic), offset++,
3987 emitcode ("push", "%s", l);
3992 l = aopGet (IC_LEFT (ic), offset,
3994 if (strcmp (fReturn[offset], l))
3995 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4002 if (strcmp (fReturn[pushed], "a"))
4003 emitcode ("pop", fReturn[pushed]);
4005 emitcode ("pop", "acc");
4007 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4010 /* generate a jump to the return label
4011 if the next is not the return statement */
4012 if (!(ic->next && ic->next->op == LABEL &&
4013 IC_LABEL (ic->next) == returnLabel))
4015 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4019 /*-----------------------------------------------------------------*/
4020 /* genLabel - generates a label */
4021 /*-----------------------------------------------------------------*/
4023 genLabel (iCode * ic)
4025 /* special case never generate */
4026 if (IC_LABEL (ic) == entryLabel)
4029 emitLabel (IC_LABEL (ic));
4032 /*-----------------------------------------------------------------*/
4033 /* genGoto - generates a ljmp */
4034 /*-----------------------------------------------------------------*/
4036 genGoto (iCode * ic)
4038 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4041 /*-----------------------------------------------------------------*/
4042 /* findLabelBackwards: walks back through the iCode chain looking */
4043 /* for the given label. Returns number of iCode instructions */
4044 /* between that label and given ic. */
4045 /* Returns zero if label not found. */
4046 /*-----------------------------------------------------------------*/
4048 findLabelBackwards (iCode * ic, int key)
4057 /* If we have any pushes or pops, we cannot predict the distance.
4058 I don't like this at all, this should be dealt with in the
4060 if (ic->op == IPUSH || ic->op == IPOP) {
4064 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4073 /*-----------------------------------------------------------------*/
4074 /* genPlusIncr :- does addition with increment if possible */
4075 /*-----------------------------------------------------------------*/
4077 genPlusIncr (iCode * ic)
4079 unsigned int icount;
4080 unsigned int size = getDataSize (IC_RESULT (ic));
4082 /* will try to generate an increment */
4083 /* if the right side is not a literal
4085 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4088 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4090 D(emitcode (";","genPlusIncr"));
4092 /* if increment >=16 bits in register or direct space */
4093 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4094 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4095 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4096 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4097 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4105 /* If the next instruction is a goto and the goto target
4106 * is < 10 instructions previous to this, we can generate
4107 * jumps straight to that target.
4109 if (ic->next && ic->next->op == GOTO
4110 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4111 && labelRange <= 10)
4113 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4114 tlbl = IC_LABEL (ic->next);
4119 tlbl = newiTempLabel (NULL);
4122 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4123 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4124 IS_AOP_PREG (IC_RESULT (ic)))
4125 emitcode ("cjne", "%s,#0x00,%05d$",
4126 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4130 emitcode ("clr", "a");
4131 emitcode ("cjne", "a,%s,%05d$",
4132 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4136 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4139 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4140 IS_AOP_PREG (IC_RESULT (ic)))
4141 emitcode ("cjne", "%s,#0x00,%05d$",
4142 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4145 emitcode ("cjne", "a,%s,%05d$",
4146 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4149 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4153 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4154 IS_AOP_PREG (IC_RESULT (ic)))
4155 emitcode ("cjne", "%s,#0x00,%05d$",
4156 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4160 emitcode ("cjne", "a,%s,%05d$",
4161 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4164 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4174 /* if result is dptr */
4175 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4176 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4177 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4178 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4180 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4186 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4189 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4190 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4192 emitcode ("inc", "dptr");
4197 /* if the literal value of the right hand side
4198 is greater than 4 then it is not worth it */
4202 /* if the sizes are greater than 1 then we cannot */
4203 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4204 AOP_SIZE (IC_LEFT (ic)) > 1)
4207 /* we can if the aops of the left & result match or
4208 if they are in registers and the registers are the
4210 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4214 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4215 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4216 aopPut (IC_RESULT (ic), "a", 0);
4222 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4231 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4232 emitcode ("inc", "a");
4233 aopPut (IC_RESULT (ic), "a", 0);
4240 /*-----------------------------------------------------------------*/
4241 /* outBitAcc - output a bit in acc */
4242 /*-----------------------------------------------------------------*/
4244 outBitAcc (operand * result)
4246 symbol *tlbl = newiTempLabel (NULL);
4247 /* if the result is a bit */
4248 if (AOP_TYPE (result) == AOP_CRY)
4250 aopPut (result, "a", 0);
4254 emitcode ("jz", "%05d$", tlbl->key + 100);
4255 emitcode ("mov", "a,%s", one);
4261 /*-----------------------------------------------------------------*/
4262 /* genPlusBits - generates code for addition of two bits */
4263 /*-----------------------------------------------------------------*/
4265 genPlusBits (iCode * ic)
4267 D (emitcode (";", "genPlusBits"));
4269 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4271 symbol *lbl = newiTempLabel (NULL);
4272 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4273 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4274 emitcode ("cpl", "c");
4276 outBitC (IC_RESULT (ic));
4280 emitcode ("clr", "a");
4281 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4282 emitcode ("rlc", "a");
4283 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4284 emitcode ("addc", "a,%s", zero);
4285 outAcc (IC_RESULT (ic));
4290 /* This is the original version of this code.
4292 * This is being kept around for reference,
4293 * because I am not entirely sure I got it right...
4296 adjustArithmeticResult (iCode * ic)
4298 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4299 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4300 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4301 aopPut (IC_RESULT (ic),
4302 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4305 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4306 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4307 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4308 aopPut (IC_RESULT (ic),
4309 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4312 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4313 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4314 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4315 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4316 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4319 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4320 aopPut (IC_RESULT (ic), buffer, 2);
4324 /* This is the pure and virtuous version of this code.
4325 * I'm pretty certain it's right, but not enough to toss the old
4329 adjustArithmeticResult (iCode * ic)
4331 if (opIsGptr (IC_RESULT (ic)) &&
4332 opIsGptr (IC_LEFT (ic)) &&
4333 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4335 aopPut (IC_RESULT (ic),
4336 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4340 if (opIsGptr (IC_RESULT (ic)) &&
4341 opIsGptr (IC_RIGHT (ic)) &&
4342 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4344 aopPut (IC_RESULT (ic),
4345 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4349 if (opIsGptr (IC_RESULT (ic)) &&
4350 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4351 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4352 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4356 SNPRINTF (buffer, sizeof(buffer),
4357 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4358 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4363 /*-----------------------------------------------------------------*/
4364 /* genPlus - generates code for addition */
4365 /*-----------------------------------------------------------------*/
4367 genPlus (iCode * ic)
4369 int size, offset = 0;
4372 bool swappedLR = FALSE;
4373 operand *leftOp, *rightOp;
4376 D (emitcode (";", "genPlus"));
4378 /* special cases :- */
4380 aopOp (IC_LEFT (ic), ic, FALSE);
4381 aopOp (IC_RIGHT (ic), ic, FALSE);
4382 aopOp (IC_RESULT (ic), ic, TRUE);
4384 /* if literal, literal on the right or
4385 if left requires ACC or right is already
4387 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4388 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4389 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4391 operand *t = IC_RIGHT (ic);
4392 IC_RIGHT (ic) = IC_LEFT (ic);
4397 /* if both left & right are in bit
4399 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4400 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4406 /* if left in bit space & right literal */
4407 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4408 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4410 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4411 /* if result in bit space */
4412 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4414 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4415 emitcode ("cpl", "c");
4416 outBitC (IC_RESULT (ic));
4420 size = getDataSize (IC_RESULT (ic));
4423 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4424 emitcode ("addc", "a,%s", zero);
4425 aopPut (IC_RESULT (ic), "a", offset++);
4431 /* if I can do an increment instead
4432 of add then GOOD for ME */
4433 if (genPlusIncr (ic) == TRUE)
4436 size = getDataSize (IC_RESULT (ic));
4437 leftOp = IC_LEFT(ic);
4438 rightOp = IC_RIGHT(ic);
4441 /* if this is an add for an array access
4442 at a 256 byte boundary */
4444 && AOP_TYPE (op) == AOP_IMMD
4446 && IS_SPEC (OP_SYM_ETYPE (op))
4447 && SPEC_ABSA (OP_SYM_ETYPE (op))
4448 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4451 D(emitcode ("; genPlus aligned array",""));
4452 aopPut (IC_RESULT (ic),
4453 aopGet (rightOp, 0, FALSE, FALSE),
4456 if( 1 == getDataSize (IC_RIGHT (ic)) )
4458 aopPut (IC_RESULT (ic),
4459 aopGet (leftOp, 1, FALSE, FALSE),
4464 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4465 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4466 aopPut (IC_RESULT (ic), "a", 1);
4471 /* if the lower bytes of a literal are zero skip the addition */
4472 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4474 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4475 (skip_bytes+1 < size))
4480 D(emitcode ("; genPlus shortcut",""));
4485 if( offset >= skip_bytes )
4487 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4490 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4492 emitcode("xch", "a,b");
4493 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4494 emitcode (add, "a,b");
4497 else if (aopGetUsesAcc (leftOp, offset))
4499 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4500 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4504 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4505 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4507 aopPut (IC_RESULT (ic), "a", offset);
4508 add = "addc"; /* further adds must propagate carry */
4512 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4513 isOperandVolatile (IC_RESULT (ic), FALSE))
4516 aopPut (IC_RESULT (ic),
4517 aopGet (leftOp, offset, FALSE, FALSE),
4524 adjustArithmeticResult (ic);
4527 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4530 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4535 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540 /*-----------------------------------------------------------------*/
4541 /* genMinusDec :- does subtraction with decrement if possible */
4542 /*-----------------------------------------------------------------*/
4544 genMinusDec (iCode * ic)
4546 unsigned int icount;
4547 unsigned int size = getDataSize (IC_RESULT (ic));
4549 /* will try to generate an increment */
4550 /* if the right side is not a literal
4552 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4555 /* if the literal value of the right hand side
4556 is greater than 4 then it is not worth it */
4557 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4560 D (emitcode (";", "genMinusDec"));
4562 /* if decrement >=16 bits in register or direct space */
4563 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4564 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4565 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4566 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4574 /* If the next instruction is a goto and the goto target
4575 * is <= 10 instructions previous to this, we can generate
4576 * jumps straight to that target.
4578 if (ic->next && ic->next->op == GOTO
4579 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4580 && labelRange <= 10)
4582 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4583 tlbl = IC_LABEL (ic->next);
4588 tlbl = newiTempLabel (NULL);
4592 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4593 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4594 IS_AOP_PREG (IC_RESULT (ic)))
4595 emitcode ("cjne", "%s,#0xff,%05d$"
4596 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4600 emitcode ("mov", "a,#0xff");
4601 emitcode ("cjne", "a,%s,%05d$"
4602 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4605 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, 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), MSB16, FALSE, FALSE)
4615 emitcode ("cjne", "a,%s,%05d$"
4616 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4619 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, 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), MSB24, FALSE, FALSE)
4630 emitcode ("cjne", "a,%s,%05d$"
4631 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4634 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4643 /* if the sizes are greater than 1 then we cannot */
4644 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4645 AOP_SIZE (IC_LEFT (ic)) > 1)
4648 /* we can if the aops of the left & result match or
4649 if they are in registers and the registers are the
4651 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4655 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4657 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4662 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4667 emitcode ("dec", "%s", l);
4670 if (AOP_NEEDSACC (IC_RESULT (ic)))
4671 aopPut (IC_RESULT (ic), "a", 0);
4678 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4679 emitcode ("dec", "a");
4680 aopPut (IC_RESULT (ic), "a", 0);
4687 /*-----------------------------------------------------------------*/
4688 /* addSign - complete with sign */
4689 /*-----------------------------------------------------------------*/
4691 addSign (operand * result, int offset, int sign)
4693 int size = (getDataSize (result) - offset);
4698 emitcode ("rlc", "a");
4699 emitcode ("subb", "a,acc");
4702 aopPut (result, "a", offset++);
4709 aopPut (result, zero, offset++);
4715 /*-----------------------------------------------------------------*/
4716 /* genMinusBits - generates code for subtraction of two bits */
4717 /*-----------------------------------------------------------------*/
4719 genMinusBits (iCode * ic)
4721 symbol *lbl = newiTempLabel (NULL);
4723 D (emitcode (";", "genMinusBits"));
4725 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4727 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4728 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4729 emitcode ("cpl", "c");
4731 outBitC (IC_RESULT (ic));
4735 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4736 emitcode ("subb", "a,acc");
4737 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4738 emitcode ("inc", "a");
4740 aopPut (IC_RESULT (ic), "a", 0);
4741 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4745 /*-----------------------------------------------------------------*/
4746 /* genMinus - generates code for subtraction */
4747 /*-----------------------------------------------------------------*/
4749 genMinus (iCode * ic)
4751 int size, offset = 0;
4753 D (emitcode (";", "genMinus"));
4755 aopOp (IC_LEFT (ic), ic, FALSE);
4756 aopOp (IC_RIGHT (ic), ic, FALSE);
4757 aopOp (IC_RESULT (ic), ic, TRUE);
4759 /* special cases :- */
4760 /* if both left & right are in bit space */
4761 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4762 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4768 /* if I can do an decrement instead
4769 of subtract then GOOD for ME */
4770 if (genMinusDec (ic) == TRUE)
4773 size = getDataSize (IC_RESULT (ic));
4775 /* if literal, add a,#-lit, else normal subb */
4776 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4778 unsigned long lit = 0L;
4779 bool useCarry = FALSE;
4781 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4786 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4788 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4789 if (!offset && !size && lit== (unsigned long) -1)
4791 emitcode ("dec", "a");
4795 /* first add without previous c */
4796 emitcode ("add", "a,#0x%02x",
4797 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4802 emitcode ("addc", "a,#0x%02x",
4803 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4805 aopPut (IC_RESULT (ic), "a", offset++);
4809 /* no need to add zeroes */
4810 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4812 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4821 operand *leftOp, *rightOp;
4823 leftOp = IC_LEFT(ic);
4824 rightOp = IC_RIGHT(ic);
4828 if (aopGetUsesAcc(rightOp, offset)) {
4829 if (aopGetUsesAcc(leftOp, offset)) {
4832 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4834 emitcode ("mov", "b,a");
4837 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4838 emitcode ("subb", "a,b");
4841 /* reverse subtraction with 2's complement */
4843 emitcode( "setb", "c");
4845 emitcode( "cpl", "c");
4846 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4847 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4848 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4849 emitcode("cpl", "a");
4850 if (size) /* skip if last byte */
4851 emitcode( "cpl", "c");
4854 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4857 emitcode ("subb", "a,%s",
4858 aopGet(rightOp, offset, FALSE, TRUE));
4861 aopPut (IC_RESULT (ic), "a", offset++);
4865 adjustArithmeticResult (ic);
4868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4869 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4870 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874 /*-----------------------------------------------------------------*/
4875 /* genMultbits :- multiplication of bits */
4876 /*-----------------------------------------------------------------*/
4878 genMultbits (operand * left,
4882 D (emitcode (";", "genMultbits"));
4884 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4885 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4889 /*-----------------------------------------------------------------*/
4890 /* genMultOneByte : 8*8=8/16 bit multiplication */
4891 /*-----------------------------------------------------------------*/
4893 genMultOneByte (operand * left,
4898 int size = AOP_SIZE (result);
4899 bool runtimeSign, compiletimeSign;
4900 bool lUnsigned, rUnsigned, pushedB;
4902 D (emitcode (";", "genMultOneByte"));
4904 if (size < 1 || size > 2)
4906 /* this should never happen */
4907 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4908 AOP_SIZE(result), __FILE__, lineno);
4912 /* (if two literals: the value is computed before) */
4913 /* if one literal, literal on the right */
4914 if (AOP_TYPE (left) == AOP_LIT)
4919 /* emitcode (";", "swapped left and right"); */
4921 /* if no literal, unsigned on the right: shorter code */
4922 if ( AOP_TYPE (right) != AOP_LIT
4923 && SPEC_USIGN (getSpec (operandType (left))))
4930 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4931 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4935 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4936 no need to take care about the signedness! */
4937 || (lUnsigned && rUnsigned))
4939 /* just an unsigned 8 * 8 = 8 multiply
4941 /* emitcode (";","unsigned"); */
4942 /* TODO: check for accumulator clash between left & right aops? */
4944 if (AOP_TYPE (right) == AOP_LIT)
4946 /* moving to accumulator first helps peepholes */
4947 MOVA (aopGet (left, 0, FALSE, FALSE));
4948 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4952 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4953 MOVA (aopGet (left, 0, FALSE, FALSE));
4956 emitcode ("mul", "ab");
4957 aopPut (result, "a", 0);
4959 aopPut (result, "b", 1);
4965 /* we have to do a signed multiply */
4966 /* emitcode (";", "signed"); */
4968 /* now sign adjust for both left & right */
4970 /* let's see what's needed: */
4971 /* apply negative sign during runtime */
4972 runtimeSign = FALSE;
4973 /* negative sign from literals */
4974 compiletimeSign = FALSE;
4978 if (AOP_TYPE(left) == AOP_LIT)
4980 /* signed literal */
4981 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4983 compiletimeSign = TRUE;
4986 /* signed but not literal */
4992 if (AOP_TYPE(right) == AOP_LIT)
4994 /* signed literal */
4995 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4997 compiletimeSign ^= TRUE;
5000 /* signed but not literal */
5004 /* initialize F0, which stores the runtime sign */
5007 if (compiletimeSign)
5008 emitcode ("setb", "F0"); /* set sign flag */
5010 emitcode ("clr", "F0"); /* reset sign flag */
5013 /* save the signs of the operands */
5014 if (AOP_TYPE(right) == AOP_LIT)
5016 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5018 if (!rUnsigned && val < 0)
5019 emitcode ("mov", "b,#0x%02x", -val);
5021 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5023 else /* ! literal */
5025 if (rUnsigned) /* emitcode (";", "signed"); */
5026 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5029 MOVA (aopGet (right, 0, FALSE, FALSE));
5030 lbl = newiTempLabel (NULL);
5031 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032 emitcode ("cpl", "F0"); /* complement sign flag */
5033 emitcode ("cpl", "a"); /* 2's complement */
5034 emitcode ("inc", "a");
5036 emitcode ("mov", "b,a");
5040 if (AOP_TYPE(left) == AOP_LIT)
5042 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5044 if (!lUnsigned && val < 0)
5045 emitcode ("mov", "a,#0x%02x", -val);
5047 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5049 else /* ! literal */
5051 MOVA (aopGet (left, 0, FALSE, FALSE));
5055 lbl = newiTempLabel (NULL);
5056 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5057 emitcode ("cpl", "F0"); /* complement sign flag */
5058 emitcode ("cpl", "a"); /* 2's complement */
5059 emitcode ("inc", "a");
5064 /* now the multiplication */
5065 emitcode ("mul", "ab");
5066 if (runtimeSign || compiletimeSign)
5068 lbl = newiTempLabel (NULL);
5070 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5071 emitcode ("cpl", "a"); /* lsb 2's complement */
5073 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5076 emitcode ("add", "a,#1"); /* this sets carry flag */
5077 emitcode ("xch", "a,b");
5078 emitcode ("cpl", "a"); /* msb 2's complement */
5079 emitcode ("addc", "a,#0");
5080 emitcode ("xch", "a,b");
5084 aopPut (result, "a", 0);
5086 aopPut (result, "b", 1);
5091 /*-----------------------------------------------------------------*/
5092 /* genMult - generates code for multiplication */
5093 /*-----------------------------------------------------------------*/
5095 genMult (iCode * ic)
5097 operand *left = IC_LEFT (ic);
5098 operand *right = IC_RIGHT (ic);
5099 operand *result = IC_RESULT (ic);
5101 D (emitcode (";", "genMult"));
5103 /* assign the asmops */
5104 aopOp (left, ic, FALSE);
5105 aopOp (right, ic, FALSE);
5106 aopOp (result, ic, TRUE);
5108 /* special cases first */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 AOP_TYPE (right) == AOP_CRY)
5113 genMultbits (left, right, result);
5117 /* if both are of size == 1 */
5118 #if 0 // one of them can be a sloc shared with the result
5119 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5121 if (getSize(operandType(left)) == 1 &&
5122 getSize(operandType(right)) == 1)
5125 genMultOneByte (left, right, result);
5129 /* should have been converted to function call */
5130 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5131 getSize(OP_SYMBOL(right)->type));
5135 freeAsmop (result, NULL, ic, TRUE);
5136 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5140 /*-----------------------------------------------------------------*/
5141 /* genDivbits :- division of bits */
5142 /*-----------------------------------------------------------------*/
5144 genDivbits (operand * left,
5151 D(emitcode ("; genDivbits",""));
5155 /* the result must be bit */
5156 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5157 l = aopGet (left, 0, FALSE, FALSE);
5161 emitcode ("div", "ab");
5162 emitcode ("rrc", "a");
5166 aopPut (result, "c", 0);
5169 /*-----------------------------------------------------------------*/
5170 /* genDivOneByte : 8 bit division */
5171 /*-----------------------------------------------------------------*/
5173 genDivOneByte (operand * left,
5177 bool lUnsigned, rUnsigned, pushedB;
5178 bool runtimeSign, compiletimeSign;
5179 bool accuse = FALSE;
5180 bool pushedA = FALSE;
5184 D(emitcode ("; genDivOneByte",""));
5186 /* Why is it necessary that genDivOneByte() can return an int result?
5189 volatile unsigned char uc;
5190 volatile signed char sc1, sc2;
5203 In all cases a one byte result would overflow, the following cast to int
5204 would return the wrong result.
5206 Two possible solution:
5207 a) cast operands to int, if ((unsigned) / (signed)) or
5208 ((signed) / (signed))
5209 b) return an 16 bit signed int; this is what we're doing here!
5212 size = AOP_SIZE (result) - 1;
5214 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5215 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5219 /* signed or unsigned */
5220 if (lUnsigned && rUnsigned)
5222 /* unsigned is easy */
5223 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5224 MOVA (aopGet (left, 0, FALSE, FALSE));
5225 emitcode ("div", "ab");
5226 aopPut (result, "a", 0);
5228 aopPut (result, zero, offset++);
5234 /* signed is a little bit more difficult */
5236 /* now sign adjust for both left & right */
5238 /* let's see what's needed: */
5239 /* apply negative sign during runtime */
5240 runtimeSign = FALSE;
5241 /* negative sign from literals */
5242 compiletimeSign = FALSE;
5246 if (AOP_TYPE(left) == AOP_LIT)
5248 /* signed literal */
5249 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5251 compiletimeSign = TRUE;
5254 /* signed but not literal */
5260 if (AOP_TYPE(right) == AOP_LIT)
5262 /* signed literal */
5263 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5265 compiletimeSign ^= TRUE;
5268 /* signed but not literal */
5272 /* initialize F0, which stores the runtime sign */
5275 if (compiletimeSign)
5276 emitcode ("setb", "F0"); /* set sign flag */
5278 emitcode ("clr", "F0"); /* reset sign flag */
5281 /* save the signs of the operands */
5282 if (AOP_TYPE(right) == AOP_LIT)
5284 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5286 if (!rUnsigned && val < 0)
5287 emitcode ("mov", "b,#0x%02x", -val);
5289 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5291 else /* ! literal */
5294 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5297 MOVA (aopGet (right, 0, FALSE, FALSE));
5298 lbl = newiTempLabel (NULL);
5299 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300 emitcode ("cpl", "F0"); /* complement sign flag */
5301 emitcode ("cpl", "a"); /* 2's complement */
5302 emitcode ("inc", "a");
5304 emitcode ("mov", "b,a");
5308 if (AOP_TYPE(left) == AOP_LIT)
5310 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5312 if (!lUnsigned && val < 0)
5313 emitcode ("mov", "a,#0x%02x", -val);
5315 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5317 else /* ! literal */
5319 MOVA (aopGet (left, 0, FALSE, FALSE));
5323 lbl = newiTempLabel (NULL);
5324 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5325 emitcode ("cpl", "F0"); /* complement sign flag */
5326 emitcode ("cpl", "a"); /* 2's complement */
5327 emitcode ("inc", "a");
5332 /* now the division */
5333 emitcode ("div", "ab");
5335 if (runtimeSign || compiletimeSign)
5337 lbl = newiTempLabel (NULL);
5339 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5340 emitcode ("cpl", "a"); /* lsb 2's complement */
5341 emitcode ("inc", "a");
5344 accuse = aopPut (result, "a", 0);
5347 /* msb is 0x00 or 0xff depending on the sign */
5352 emitcode ("push", "acc");
5355 emitcode ("mov", "c,F0");
5356 emitcode ("subb", "a,acc");
5358 aopPut (result, "a", offset++);
5360 else /* compiletimeSign */
5362 if (aopPutUsesAcc (result, "#0xFF", offset))
5364 emitcode ("push", "acc");
5368 aopPut (result, "#0xff", offset++);
5374 aopPut (result, "a", 0);
5376 aopPut (result, zero, offset++);
5380 emitcode ("pop", "acc");
5384 /*-----------------------------------------------------------------*/
5385 /* genDiv - generates code for division */
5386 /*-----------------------------------------------------------------*/
5390 operand *left = IC_LEFT (ic);
5391 operand *right = IC_RIGHT (ic);
5392 operand *result = IC_RESULT (ic);
5394 D (emitcode (";", "genDiv"));
5396 /* assign the amsops */
5397 aopOp (left, ic, FALSE);
5398 aopOp (right, ic, FALSE);
5399 aopOp (result, ic, TRUE);
5401 /* special cases first */
5403 if (AOP_TYPE (left) == AOP_CRY &&
5404 AOP_TYPE (right) == AOP_CRY)
5406 genDivbits (left, right, result);
5410 /* if both are of size == 1 */
5411 if (AOP_SIZE (left) == 1 &&
5412 AOP_SIZE (right) == 1)
5414 genDivOneByte (left, right, result);
5418 /* should have been converted to function call */
5421 freeAsmop (result, NULL, ic, TRUE);
5422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5426 /*-----------------------------------------------------------------*/
5427 /* genModbits :- modulus of bits */
5428 /*-----------------------------------------------------------------*/
5430 genModbits (operand * left,
5437 D (emitcode (";", "genModbits"));
5441 /* the result must be bit */
5442 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5443 l = aopGet (left, 0, FALSE, FALSE);
5447 emitcode ("div", "ab");
5448 emitcode ("mov", "a,b");
5449 emitcode ("rrc", "a");
5453 aopPut (result, "c", 0);
5456 /*-----------------------------------------------------------------*/
5457 /* genModOneByte : 8 bit modulus */
5458 /*-----------------------------------------------------------------*/
5460 genModOneByte (operand * left,
5464 bool lUnsigned, rUnsigned, pushedB;
5465 bool runtimeSign, compiletimeSign;
5469 D (emitcode (";", "genModOneByte"));
5471 size = AOP_SIZE (result) - 1;
5473 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5474 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5476 /* if right is a literal, check it for 2^n */
5477 if (AOP_TYPE(right) == AOP_LIT)
5479 unsigned char val = abs((int) operandLitValue(right));
5480 symbol *lbl2 = NULL;
5484 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5493 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5494 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5495 /* because iCode should have been changed to genAnd */
5496 /* see file "SDCCopt.c", function "convertToFcall()" */
5498 MOVA (aopGet (left, 0, FALSE, FALSE));
5499 emitcode ("mov", "c,acc.7");
5500 emitcode ("anl", "a,#0x%02x", val - 1);
5501 lbl = newiTempLabel (NULL);
5502 emitcode ("jz", "%05d$", (lbl->key + 100));
5503 emitcode ("jnc", "%05d$", (lbl->key + 100));
5504 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5510 aopPut (result, "a", 0);
5512 aopPut (result, "#0xff", offs2++);
5513 lbl2 = newiTempLabel (NULL);
5514 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5517 aopPut (result, "a", 0);
5519 aopPut (result, zero, offset++);
5533 /* signed or unsigned */
5534 if (lUnsigned && rUnsigned)
5536 /* unsigned is easy */
5537 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5538 MOVA (aopGet (left, 0, FALSE, FALSE));
5539 emitcode ("div", "ab");
5540 aopPut (result, "b", 0);
5542 aopPut (result, zero, offset++);
5548 /* signed is a little bit more difficult */
5550 /* now sign adjust for both left & right */
5552 /* modulus: sign of the right operand has no influence on the result! */
5553 if (AOP_TYPE(right) == AOP_LIT)
5555 signed char val = (char) operandLitValue(right);
5557 if (!rUnsigned && val < 0)
5558 emitcode ("mov", "b,#0x%02x", -val);
5560 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5562 else /* not literal */
5565 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5568 MOVA (aopGet (right, 0, FALSE, FALSE));
5569 lbl = newiTempLabel (NULL);
5570 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5571 emitcode ("cpl", "a"); /* 2's complement */
5572 emitcode ("inc", "a");
5574 emitcode ("mov", "b,a");
5578 /* let's see what's needed: */
5579 /* apply negative sign during runtime */
5580 runtimeSign = FALSE;
5581 /* negative sign from literals */
5582 compiletimeSign = FALSE;
5584 /* sign adjust left side */
5585 if (AOP_TYPE(left) == AOP_LIT)
5587 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5589 if (!lUnsigned && val < 0)
5591 compiletimeSign = TRUE; /* set sign flag */
5592 emitcode ("mov", "a,#0x%02x", -val);
5595 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5597 else /* ! literal */
5599 MOVA (aopGet (left, 0, FALSE, FALSE));
5604 emitcode ("clr", "F0"); /* clear sign flag */
5606 lbl = newiTempLabel (NULL);
5607 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5608 emitcode ("setb", "F0"); /* set sign flag */
5609 emitcode ("cpl", "a"); /* 2's complement */
5610 emitcode ("inc", "a");
5615 /* now the modulus */
5616 emitcode ("div", "ab");
5618 if (runtimeSign || compiletimeSign)
5620 emitcode ("mov", "a,b");
5621 lbl = newiTempLabel (NULL);
5623 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5624 emitcode ("cpl", "a"); /* 2's complement */
5625 emitcode ("inc", "a");
5628 aopPut (result, "a", 0);
5631 /* msb is 0x00 or 0xff depending on the sign */
5634 emitcode ("mov", "c,F0");
5635 emitcode ("subb", "a,acc");
5637 aopPut (result, "a", offset++);
5639 else /* compiletimeSign */
5641 aopPut (result, "#0xff", offset++);
5646 aopPut (result, "b", 0);
5648 aopPut (result, zero, offset++);
5654 /*-----------------------------------------------------------------*/
5655 /* genMod - generates code for division */
5656 /*-----------------------------------------------------------------*/
5660 operand *left = IC_LEFT (ic);
5661 operand *right = IC_RIGHT (ic);
5662 operand *result = IC_RESULT (ic);
5664 D (emitcode (";", "genMod"));
5666 /* assign the asmops */
5667 aopOp (left, ic, FALSE);
5668 aopOp (right, ic, FALSE);
5669 aopOp (result, ic, TRUE);
5671 /* special cases first */
5673 if (AOP_TYPE (left) == AOP_CRY &&
5674 AOP_TYPE (right) == AOP_CRY)
5676 genModbits (left, right, result);
5680 /* if both are of size == 1 */
5681 if (AOP_SIZE (left) == 1 &&
5682 AOP_SIZE (right) == 1)
5684 genModOneByte (left, right, result);
5688 /* should have been converted to function call */
5692 freeAsmop (result, NULL, ic, TRUE);
5693 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5694 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5697 /*-----------------------------------------------------------------*/
5698 /* genIfxJump :- will create a jump depending on the ifx */
5699 /*-----------------------------------------------------------------*/
5701 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5704 symbol *tlbl = newiTempLabel (NULL);
5707 D (emitcode (";", "genIfxJump"));
5709 /* if true label then we jump if condition
5713 jlbl = IC_TRUE (ic);
5714 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5715 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5719 /* false label is present */
5720 jlbl = IC_FALSE (ic);
5721 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5722 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5724 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5725 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5727 emitcode (inst, "%05d$", tlbl->key + 100);
5728 freeForBranchAsmop (result);
5729 freeForBranchAsmop (right);
5730 freeForBranchAsmop (left);
5731 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5734 /* mark the icode as generated */
5738 /*-----------------------------------------------------------------*/
5739 /* genCmp :- greater or less than comparison */
5740 /*-----------------------------------------------------------------*/
5742 genCmp (operand * left, operand * right,
5743 operand * result, iCode * ifx, int sign, iCode *ic)
5745 int size, offset = 0;
5746 unsigned long lit = 0L;
5749 D (emitcode (";", "genCmp"));
5751 /* if left & right are bit variables */
5752 if (AOP_TYPE (left) == AOP_CRY &&
5753 AOP_TYPE (right) == AOP_CRY)
5755 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5756 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5760 /* subtract right from left if at the
5761 end the carry flag is set then we know that
5762 left is greater than right */
5763 size = max (AOP_SIZE (left), AOP_SIZE (right));
5765 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5766 if ((size == 1) && !sign &&
5767 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5769 symbol *lbl = newiTempLabel (NULL);
5770 emitcode ("cjne", "%s,%s,%05d$",
5771 aopGet (left, offset, FALSE, FALSE),
5772 aopGet (right, offset, FALSE, FALSE),
5778 if (AOP_TYPE (right) == AOP_LIT)
5780 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5781 /* optimize if(x < 0) or if(x >= 0) */
5790 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5791 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5793 genIfxJump (ifx, "acc.7", left, right, result);
5794 freeAsmop (right, NULL, ic, TRUE);
5795 freeAsmop (left, NULL, ic, TRUE);
5801 emitcode ("rlc", "a");
5808 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5809 while (size && (bytelit == 0))
5812 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5818 MOVA (aopGet (left, offset, FALSE, FALSE));
5819 if (sign && size == 0)
5821 emitcode ("xrl", "a,#0x80");
5822 emitcode ("subb", "a,#0x%02x",
5823 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5827 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5837 bool pushedB = FALSE;
5838 rightInB = aopGetUsesAcc(right, offset);
5842 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5844 MOVA (aopGet (left, offset, FALSE, FALSE));
5845 if (sign && size == 0)
5847 emitcode ("xrl", "a,#0x80");
5852 MOVB (aopGet (right, offset, FALSE, FALSE));
5854 emitcode ("xrl", "b,#0x80");
5855 emitcode ("subb", "a,b");
5860 emitcode ("subb", "a,b");
5862 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5872 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5880 /* if the result is used in the next
5881 ifx conditional branch then generate
5882 code a little differently */
5885 genIfxJump (ifx, "c", NULL, NULL, result);
5891 /* leave the result in acc */
5895 /*-----------------------------------------------------------------*/
5896 /* genCmpGt :- greater than comparison */
5897 /*-----------------------------------------------------------------*/
5899 genCmpGt (iCode * ic, iCode * ifx)
5901 operand *left, *right, *result;
5902 sym_link *letype, *retype;
5905 D (emitcode (";", "genCmpGt"));
5907 left = IC_LEFT (ic);
5908 right = IC_RIGHT (ic);
5909 result = IC_RESULT (ic);
5911 letype = getSpec (operandType (left));
5912 retype = getSpec (operandType (right));
5913 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5914 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5915 /* assign the amsops */
5916 aopOp (result, ic, TRUE);
5917 aopOp (left, ic, FALSE);
5918 aopOp (right, ic, FALSE);
5920 genCmp (right, left, result, ifx, sign, ic);
5922 freeAsmop (result, NULL, ic, TRUE);
5925 /*-----------------------------------------------------------------*/
5926 /* genCmpLt - less than comparisons */
5927 /*-----------------------------------------------------------------*/
5929 genCmpLt (iCode * ic, iCode * ifx)
5931 operand *left, *right, *result;
5932 sym_link *letype, *retype;
5935 D (emitcode (";", "genCmpLt"));
5937 left = IC_LEFT (ic);
5938 right = IC_RIGHT (ic);
5939 result = IC_RESULT (ic);
5941 letype = getSpec (operandType (left));
5942 retype = getSpec (operandType (right));
5943 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5944 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5945 /* assign the amsops */
5946 aopOp (result, ic, TRUE);
5947 aopOp (left, ic, FALSE);
5948 aopOp (right, ic, FALSE);
5950 genCmp (left, right, result, ifx, sign, ic);
5952 freeAsmop (result, NULL, ic, TRUE);
5955 /*-----------------------------------------------------------------*/
5956 /* gencjneshort - compare and jump if not equal */
5957 /*-----------------------------------------------------------------*/
5959 gencjneshort (operand * left, operand * right, symbol * lbl)
5961 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5963 unsigned long lit = 0L;
5965 D (emitcode (";", "gencjneshort"));
5967 /* if the left side is a literal or
5968 if the right is in a pointer register and left
5970 if ((AOP_TYPE (left) == AOP_LIT) ||
5971 (AOP_TYPE (left) == AOP_IMMD) ||
5972 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5979 if (AOP_TYPE (right) == AOP_LIT)
5980 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5982 /* if the right side is a literal then anything goes */
5983 if (AOP_TYPE (right) == AOP_LIT &&
5984 AOP_TYPE (left) != AOP_DIR &&
5985 AOP_TYPE (left) != AOP_IMMD)
5989 emitcode ("cjne", "%s,%s,%05d$",
5990 aopGet (left, offset, FALSE, FALSE),
5991 aopGet (right, offset, FALSE, FALSE),
5997 /* if the right side is in a register or in direct space or
5998 if the left is a pointer register & right is not */
5999 else if (AOP_TYPE (right) == AOP_REG ||
6000 AOP_TYPE (right) == AOP_DIR ||
6001 AOP_TYPE (right) == AOP_LIT ||
6002 AOP_TYPE (right) == AOP_IMMD ||
6003 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6004 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6008 MOVA (aopGet (left, offset, FALSE, FALSE));
6009 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6010 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6011 emitcode ("jnz", "%05d$", lbl->key + 100);
6013 emitcode ("cjne", "a,%s,%05d$",
6014 aopGet (right, offset, FALSE, TRUE),
6021 /* right is a pointer reg need both a & b */
6024 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6025 wassertl(!BINUSE, "B was in use");
6026 MOVB (aopGet (left, offset, FALSE, FALSE));
6027 MOVA (aopGet (right, offset, FALSE, FALSE));
6028 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6034 /*-----------------------------------------------------------------*/
6035 /* gencjne - compare and jump if not equal */
6036 /*-----------------------------------------------------------------*/
6038 gencjne (operand * left, operand * right, symbol * lbl)
6040 symbol *tlbl = newiTempLabel (NULL);
6042 D (emitcode (";", "gencjne"));
6044 gencjneshort (left, right, lbl);
6046 emitcode ("mov", "a,%s", one);
6047 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6049 emitcode ("clr", "a");
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpEq - generates code for equal to */
6055 /*-----------------------------------------------------------------*/
6057 genCmpEq (iCode * ic, iCode * ifx)
6059 bool swappedLR = FALSE;
6060 operand *left, *right, *result;
6062 D (emitcode (";", "genCmpEq"));
6064 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6065 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6066 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6068 /* if literal, literal on the right or
6069 if the right is in a pointer register and left
6071 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6072 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6074 operand *t = IC_RIGHT (ic);
6075 IC_RIGHT (ic) = IC_LEFT (ic);
6080 if (ifx && !AOP_SIZE (result))
6083 /* if they are both bit variables */
6084 if (AOP_TYPE (left) == AOP_CRY &&
6085 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6087 if (AOP_TYPE (right) == AOP_LIT)
6089 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6092 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6093 emitcode ("cpl", "c");
6097 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6101 emitcode ("clr", "c");
6103 /* AOP_TYPE(right) == AOP_CRY */
6107 symbol *lbl = newiTempLabel (NULL);
6108 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6109 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6110 emitcode ("cpl", "c");
6113 /* if true label then we jump if condition
6115 tlbl = newiTempLabel (NULL);
6118 emitcode ("jnc", "%05d$", tlbl->key + 100);
6119 freeForBranchAsmop (result);
6120 freeForBranchAsmop (right);
6121 freeForBranchAsmop (left);
6122 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6126 emitcode ("jc", "%05d$", tlbl->key + 100);
6127 freeForBranchAsmop (result);
6128 freeForBranchAsmop (right);
6129 freeForBranchAsmop (left);
6130 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6136 tlbl = newiTempLabel (NULL);
6137 gencjneshort (left, right, tlbl);
6140 freeForBranchAsmop (result);
6141 freeForBranchAsmop (right);
6142 freeForBranchAsmop (left);
6143 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6148 symbol *lbl = newiTempLabel (NULL);
6149 emitcode ("sjmp", "%05d$", lbl->key + 100);
6151 freeForBranchAsmop (result);
6152 freeForBranchAsmop (right);
6153 freeForBranchAsmop (left);
6154 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6158 /* mark the icode as generated */
6163 /* if they are both bit variables */
6164 if (AOP_TYPE (left) == AOP_CRY &&
6165 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6167 if (AOP_TYPE (right) == AOP_LIT)
6169 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6172 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6173 emitcode ("cpl", "c");
6177 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6181 emitcode ("clr", "c");
6183 /* AOP_TYPE(right) == AOP_CRY */
6187 symbol *lbl = newiTempLabel (NULL);
6188 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6189 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6190 emitcode ("cpl", "c");
6194 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6201 genIfxJump (ifx, "c", left, right, result);
6204 /* if the result is used in an arithmetic operation
6205 then put the result in place */
6210 gencjne (left, right, newiTempLabel (NULL));
6211 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6213 aopPut (result, "a", 0);
6218 genIfxJump (ifx, "a", left, right, result);
6221 /* if the result is used in an arithmetic operation
6222 then put the result in place */
6223 if (AOP_TYPE (result) != AOP_CRY)
6225 /* leave the result in acc */
6229 freeAsmop (result, NULL, ic, TRUE);
6232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6237 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6238 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6242 /*-----------------------------------------------------------------*/
6243 /* ifxForOp - returns the icode containing the ifx for operand */
6244 /*-----------------------------------------------------------------*/
6246 ifxForOp (operand * op, iCode * ic)
6248 /* if true symbol then needs to be assigned */
6249 if (IS_TRUE_SYMOP (op))
6252 /* if this has register type condition and
6253 the next instruction is ifx with the same operand
6254 and live to of the operand is upto the ifx only then */
6256 ic->next->op == IFX &&
6257 IC_COND (ic->next)->key == op->key &&
6258 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6264 /*-----------------------------------------------------------------*/
6265 /* hasInc - operand is incremented before any other use */
6266 /*-----------------------------------------------------------------*/
6268 hasInc (operand *op, iCode *ic, int osize)
6270 sym_link *type = operandType(op);
6271 sym_link *retype = getSpec (type);
6272 iCode *lic = ic->next;
6275 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6276 if (!IS_SYMOP(op)) return NULL;
6278 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6279 if (IS_AGGREGATE(type->next)) return NULL;
6280 if (osize != (isize = getSize(type->next))) return NULL;
6283 /* if operand of the form op = op + <sizeof *op> */
6284 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6285 isOperandEqual(IC_RESULT(lic),op) &&
6286 isOperandLiteral(IC_RIGHT(lic)) &&
6287 operandLitValue(IC_RIGHT(lic)) == isize) {
6290 /* if the operand used or deffed */
6291 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6294 /* if GOTO or IFX */
6295 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6301 /*-----------------------------------------------------------------*/
6302 /* genAndOp - for && operation */
6303 /*-----------------------------------------------------------------*/
6305 genAndOp (iCode * ic)
6307 operand *left, *right, *result;
6310 D (emitcode (";", "genAndOp"));
6312 /* note here that && operations that are in an
6313 if statement are taken away by backPatchLabels
6314 only those used in arthmetic operations remain */
6315 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6316 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6317 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6319 /* if both are bit variables */
6320 if (AOP_TYPE (left) == AOP_CRY &&
6321 AOP_TYPE (right) == AOP_CRY)
6323 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6324 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6329 tlbl = newiTempLabel (NULL);
6331 emitcode ("jz", "%05d$", tlbl->key + 100);
6337 freeAsmop (result, NULL, ic, TRUE);
6338 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343 /*-----------------------------------------------------------------*/
6344 /* genOrOp - for || operation */
6345 /*-----------------------------------------------------------------*/
6347 genOrOp (iCode * ic)
6349 operand *left, *right, *result;
6352 D (emitcode (";", "genOrOp"));
6354 /* note here that || operations that are in an
6355 if statement are taken away by backPatchLabels
6356 only those used in arthmetic operations remain */
6357 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6358 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6359 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6361 /* if both are bit variables */
6362 if (AOP_TYPE (left) == AOP_CRY &&
6363 AOP_TYPE (right) == AOP_CRY)
6365 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6371 tlbl = newiTempLabel (NULL);
6373 emitcode ("jnz", "%05d$", tlbl->key + 100);
6379 freeAsmop (result, NULL, ic, TRUE);
6380 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6381 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6384 /*-----------------------------------------------------------------*/
6385 /* isLiteralBit - test if lit == 2^n */
6386 /*-----------------------------------------------------------------*/
6388 isLiteralBit (unsigned long lit)
6390 unsigned long pw[32] =
6391 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6392 0x100L, 0x200L, 0x400L, 0x800L,
6393 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6394 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6395 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6396 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6397 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6400 for (idx = 0; idx < 32; idx++)
6406 /*-----------------------------------------------------------------*/
6407 /* continueIfTrue - */
6408 /*-----------------------------------------------------------------*/
6410 continueIfTrue (iCode * ic)
6413 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6417 /*-----------------------------------------------------------------*/
6419 /*-----------------------------------------------------------------*/
6421 jumpIfTrue (iCode * ic)
6424 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6428 /*-----------------------------------------------------------------*/
6429 /* jmpTrueOrFalse - */
6430 /*-----------------------------------------------------------------*/
6432 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6434 // ugly but optimized by peephole
6437 symbol *nlbl = newiTempLabel (NULL);
6438 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6440 freeForBranchAsmop (result);
6441 freeForBranchAsmop (right);
6442 freeForBranchAsmop (left);
6443 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6448 freeForBranchAsmop (result);
6449 freeForBranchAsmop (right);
6450 freeForBranchAsmop (left);
6451 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6457 /*-----------------------------------------------------------------*/
6458 /* genAnd - code for and */
6459 /*-----------------------------------------------------------------*/
6461 genAnd (iCode * ic, iCode * ifx)
6463 operand *left, *right, *result;
6464 int size, offset = 0;
6465 unsigned long lit = 0L;
6469 D (emitcode (";", "genAnd"));
6471 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6472 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6473 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6476 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6478 AOP_TYPE (left), AOP_TYPE (right));
6479 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6481 AOP_SIZE (left), AOP_SIZE (right));
6484 /* if left is a literal & right is not then exchange them */
6485 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6486 AOP_NEEDSACC (left))
6488 operand *tmp = right;
6493 /* if result = right then exchange left and right */
6494 if (sameRegs (AOP (result), AOP (right)))
6496 operand *tmp = right;
6501 /* if right is bit then exchange them */
6502 if (AOP_TYPE (right) == AOP_CRY &&
6503 AOP_TYPE (left) != AOP_CRY)
6505 operand *tmp = right;
6509 if (AOP_TYPE (right) == AOP_LIT)
6510 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6512 size = AOP_SIZE (result);
6515 // result = bit & yy;
6516 if (AOP_TYPE (left) == AOP_CRY)
6518 // c = bit & literal;
6519 if (AOP_TYPE (right) == AOP_LIT)
6523 if (size && sameRegs (AOP (result), AOP (left)))
6526 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6531 if (size && (AOP_TYPE (result) == AOP_CRY))
6533 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6536 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6541 emitcode ("clr", "c");
6546 if (AOP_TYPE (right) == AOP_CRY)
6549 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6550 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6555 MOVA (aopGet (right, 0, FALSE, FALSE));
6557 emitcode ("rrc", "a");
6558 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6566 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6567 genIfxJump (ifx, "c", left, right, result);
6571 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6572 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6573 if ((AOP_TYPE (right) == AOP_LIT) &&
6574 (AOP_TYPE (result) == AOP_CRY) &&
6575 (AOP_TYPE (left) != AOP_CRY))
6577 int posbit = isLiteralBit (lit);
6582 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6586 switch (posbit & 0x07)
6588 case 0: emitcode ("rrc", "a");
6590 case 7: emitcode ("rlc", "a");
6592 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6601 SNPRINTF (buffer, sizeof(buffer),
6602 "acc.%d", posbit & 0x07);
6603 genIfxJump (ifx, buffer, left, right, result);
6606 {// what is this case? just found it in ds390/gen.c
6607 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6614 symbol *tlbl = newiTempLabel (NULL);
6615 int sizel = AOP_SIZE (left);
6617 emitcode ("setb", "c");
6620 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6622 MOVA (aopGet (left, offset, FALSE, FALSE));
6624 if ((posbit = isLiteralBit (bytelit)) != 0)
6625 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6628 if (bytelit != 0x0FFL)
6629 emitcode ("anl", "a,%s",
6630 aopGet (right, offset, FALSE, TRUE));
6631 emitcode ("jnz", "%05d$", tlbl->key + 100);
6636 // bit = left & literal
6639 emitcode ("clr", "c");
6642 // if(left & literal)
6646 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6656 /* if left is same as result */
6657 if (sameRegs (AOP (result), AOP (left)))
6659 for (; size--; offset++)
6661 if (AOP_TYPE (right) == AOP_LIT)
6663 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6664 if (bytelit == 0x0FF)
6666 /* dummy read of volatile operand */
6667 if (isOperandVolatile (left, FALSE))
6668 MOVA (aopGet (left, offset, FALSE, FALSE));
6672 else if (bytelit == 0)
6674 aopPut (result, zero, offset);
6676 else if (IS_AOP_PREG (result))
6678 MOVA (aopGet (left, offset, FALSE, TRUE));
6679 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6680 aopPut (result, "a", offset);
6683 emitcode ("anl", "%s,%s",
6684 aopGet (left, offset, FALSE, TRUE),
6685 aopGet (right, offset, FALSE, FALSE));
6689 if (AOP_TYPE (left) == AOP_ACC)
6692 emitcode("mov", "a,b");
6693 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6695 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6697 MOVB (aopGet (left, offset, FALSE, FALSE));
6698 MOVA (aopGet (right, offset, FALSE, FALSE));
6699 emitcode ("anl", "a,b");
6700 aopPut (result, "a", offset);
6702 else if (aopGetUsesAcc (left, offset))
6704 MOVA (aopGet (left, offset, FALSE, FALSE));
6705 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6706 aopPut (result, "a", offset);
6710 MOVA (aopGet (right, offset, FALSE, FALSE));
6711 if (IS_AOP_PREG (result))
6713 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6714 aopPut (result, "a", offset);
6717 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6724 // left & result in different registers
6725 if (AOP_TYPE (result) == AOP_CRY)
6728 // if(size), result in bit
6729 // if(!size && ifx), conditional oper: if(left & right)
6730 symbol *tlbl = newiTempLabel (NULL);
6731 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6733 emitcode ("setb", "c");
6736 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6737 && AOP_TYPE(left)==AOP_ACC)
6740 emitcode("mov", "a,b");
6741 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6743 else if (AOP_TYPE(left)==AOP_ACC)
6747 bool pushedB = pushB ();
6748 emitcode("mov", "b,a");
6749 MOVA (aopGet (right, offset, FALSE, FALSE));
6750 emitcode("anl", "a,b");
6755 MOVA (aopGet (right, offset, FALSE, FALSE));
6756 emitcode("anl", "a,b");
6759 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6761 MOVB (aopGet (left, offset, FALSE, FALSE));
6762 MOVA (aopGet (right, offset, FALSE, FALSE));
6763 emitcode ("anl", "a,b");
6765 else if (aopGetUsesAcc (left, offset))
6767 MOVA (aopGet (left, offset, FALSE, FALSE));
6768 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772 MOVA (aopGet (right, offset, FALSE, FALSE));
6773 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6776 emitcode ("jnz", "%05d$", tlbl->key + 100);
6786 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6792 for (; (size--); offset++)
6795 // result = left & right
6796 if (AOP_TYPE (right) == AOP_LIT)
6798 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6799 if (bytelit == 0x0FF)
6802 aopGet (left, offset, FALSE, FALSE),
6806 else if (bytelit == 0)
6808 /* dummy read of volatile operand */
6809 if (isOperandVolatile (left, FALSE))
6810 MOVA (aopGet (left, offset, FALSE, FALSE));
6811 aopPut (result, zero, offset);
6814 else if (AOP_TYPE (left) == AOP_ACC)
6818 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6819 aopPut (result, "a", offset);
6824 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6825 aopPut (result, "b", offset);
6830 // faster than result <- left, anl result,right
6831 // and better if result is SFR
6832 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6833 && AOP_TYPE(left)==AOP_ACC)
6836 emitcode("mov", "a,b");
6837 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6839 else if (AOP_TYPE(left)==AOP_ACC)
6843 bool pushedB = pushB ();
6844 emitcode("mov", "b,a");
6845 MOVA (aopGet (right, offset, FALSE, FALSE));
6846 emitcode("anl", "a,b");
6851 MOVA (aopGet (right, offset, FALSE, FALSE));
6852 emitcode("anl", "a,b");
6855 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6857 MOVB (aopGet (left, offset, FALSE, FALSE));
6858 MOVA (aopGet (right, offset, FALSE, FALSE));
6859 emitcode ("anl", "a,b");
6861 else if (aopGetUsesAcc (left, offset))
6863 MOVA (aopGet (left, offset, FALSE, FALSE));
6864 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6868 MOVA (aopGet (right, offset, FALSE, FALSE));
6869 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6871 aopPut (result, "a", offset);
6877 freeAsmop (result, NULL, ic, TRUE);
6878 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6879 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6882 /*-----------------------------------------------------------------*/
6883 /* genOr - code for or */
6884 /*-----------------------------------------------------------------*/
6886 genOr (iCode * ic, iCode * ifx)
6888 operand *left, *right, *result;
6889 int size, offset = 0;
6890 unsigned long lit = 0L;
6893 D (emitcode (";", "genOr"));
6895 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6896 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6897 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6900 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6902 AOP_TYPE (left), AOP_TYPE (right));
6903 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6905 AOP_SIZE (left), AOP_SIZE (right));
6908 /* if left is a literal & right is not then exchange them */
6909 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6910 AOP_NEEDSACC (left))
6912 operand *tmp = right;
6917 /* if result = right then exchange them */
6918 if (sameRegs (AOP (result), AOP (right)))
6920 operand *tmp = right;
6925 /* if right is bit then exchange them */
6926 if (AOP_TYPE (right) == AOP_CRY &&
6927 AOP_TYPE (left) != AOP_CRY)
6929 operand *tmp = right;
6933 if (AOP_TYPE (right) == AOP_LIT)
6934 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6936 size = AOP_SIZE (result);
6940 if (AOP_TYPE (left) == AOP_CRY)
6942 if (AOP_TYPE (right) == AOP_LIT)
6944 // c = bit | literal;
6947 // lit != 0 => result = 1
6948 if (AOP_TYPE (result) == AOP_CRY)
6951 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6953 continueIfTrue (ifx);
6956 emitcode ("setb", "c");
6960 // lit == 0 => result = left
6961 if (size && sameRegs (AOP (result), AOP (left)))
6963 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6968 if (AOP_TYPE (right) == AOP_CRY)
6971 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6972 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6977 symbol *tlbl = newiTempLabel (NULL);
6978 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6979 emitcode ("setb", "c");
6980 emitcode ("jb", "%s,%05d$",
6981 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6983 emitcode ("jnz", "%05d$", tlbl->key + 100);
6984 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6986 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7001 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7002 genIfxJump (ifx, "c", left, right, result);
7006 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7007 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7008 if ((AOP_TYPE (right) == AOP_LIT) &&
7009 (AOP_TYPE (result) == AOP_CRY) &&
7010 (AOP_TYPE (left) != AOP_CRY))
7016 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7018 continueIfTrue (ifx);
7023 // lit = 0, result = boolean(left)
7025 emitcode ("setb", "c");
7029 symbol *tlbl = newiTempLabel (NULL);
7030 emitcode ("jnz", "%05d$", tlbl->key + 100);
7036 genIfxJump (ifx, "a", left, right, result);
7044 /* if left is same as result */
7045 if (sameRegs (AOP (result), AOP (left)))
7047 for (; size--; offset++)
7049 if (AOP_TYPE (right) == AOP_LIT)
7051 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7054 /* dummy read of volatile operand */
7055 if (isOperandVolatile (left, FALSE))
7056 MOVA (aopGet (left, offset, FALSE, FALSE));
7060 else if (bytelit == 0x0FF)
7062 aopPut (result, "#0xFF", offset);
7064 else if (IS_AOP_PREG (left))
7066 MOVA (aopGet (left, offset, FALSE, TRUE));
7067 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7068 aopPut (result, "a", offset);
7072 emitcode ("orl", "%s,%s",
7073 aopGet (left, offset, FALSE, TRUE),
7074 aopGet (right, offset, FALSE, FALSE));
7079 if (AOP_TYPE (left) == AOP_ACC)
7082 emitcode("mov", "a,b");
7083 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7085 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7087 MOVB (aopGet (left, offset, FALSE, FALSE));
7088 MOVA (aopGet (right, offset, FALSE, FALSE));
7089 emitcode ("orl", "a,b");
7090 aopPut (result, "a", offset);
7092 else if (aopGetUsesAcc (left, offset))
7094 MOVA (aopGet (left, offset, FALSE, FALSE));
7095 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7096 aopPut (result, "a", offset);
7100 MOVA (aopGet (right, offset, FALSE, FALSE));
7101 if (IS_AOP_PREG (left))
7103 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7104 aopPut (result, "a", offset);
7108 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7116 // left & result in different registers
7117 if (AOP_TYPE (result) == AOP_CRY)
7120 // if(size), result in bit
7121 // if(!size && ifx), conditional oper: if(left | right)
7122 symbol *tlbl = newiTempLabel (NULL);
7123 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7125 emitcode ("setb", "c");
7128 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7129 && AOP_TYPE(left)==AOP_ACC)
7132 emitcode("mov", "a,b");
7133 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7135 else if (AOP_TYPE(left)==AOP_ACC)
7139 bool pushedB = pushB ();
7140 emitcode("mov", "b,a");
7141 MOVA (aopGet (right, offset, FALSE, FALSE));
7142 emitcode("orl", "a,b");
7147 MOVA (aopGet (right, offset, FALSE, FALSE));
7148 emitcode("orl", "a,b");
7151 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7153 MOVB (aopGet (left, offset, FALSE, FALSE));
7154 MOVA (aopGet (right, offset, FALSE, FALSE));
7155 emitcode ("orl", "a,b");
7157 else if (aopGetUsesAcc (left, offset))
7159 MOVA (aopGet (left, offset, FALSE, FALSE));
7160 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7164 MOVA (aopGet (right, offset, FALSE, FALSE));
7165 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7168 emitcode ("jnz", "%05d$", tlbl->key + 100);
7178 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7184 for (; (size--); offset++)
7187 // result = left | right
7188 if (AOP_TYPE (right) == AOP_LIT)
7190 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7194 aopGet (left, offset, FALSE, FALSE),
7198 else if (bytelit == 0x0FF)
7200 /* dummy read of volatile operand */
7201 if (isOperandVolatile (left, FALSE))
7202 MOVA (aopGet (left, offset, FALSE, FALSE));
7203 aopPut (result, "#0xFF", offset);
7207 // faster than result <- left, orl result,right
7208 // and better if result is SFR
7209 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7210 && AOP_TYPE(left)==AOP_ACC)
7213 emitcode("mov", "a,b");
7214 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7216 else if (AOP_TYPE(left)==AOP_ACC)
7220 bool pushedB = pushB ();
7221 emitcode("mov", "b,a");
7222 MOVA (aopGet (right, offset, FALSE, FALSE));
7223 emitcode("orl", "a,b");
7228 MOVA (aopGet (right, offset, FALSE, FALSE));
7229 emitcode("orl", "a,b");
7232 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7234 MOVB (aopGet (left, offset, FALSE, FALSE));
7235 MOVA (aopGet (right, offset, FALSE, FALSE));
7236 emitcode ("orl", "a,b");
7238 else if (aopGetUsesAcc (left, offset))
7240 MOVA (aopGet (left, offset, FALSE, FALSE));
7241 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7245 MOVA (aopGet (right, offset, FALSE, FALSE));
7246 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7248 aopPut (result, "a", offset);
7254 freeAsmop (result, NULL, ic, TRUE);
7255 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7256 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7259 /*-----------------------------------------------------------------*/
7260 /* genXor - code for xclusive or */
7261 /*-----------------------------------------------------------------*/
7263 genXor (iCode * ic, iCode * ifx)
7265 operand *left, *right, *result;
7266 int size, offset = 0;
7267 unsigned long lit = 0L;
7270 D (emitcode (";", "genXor"));
7272 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7273 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7274 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7277 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7279 AOP_TYPE (left), AOP_TYPE (right));
7280 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7282 AOP_SIZE (left), AOP_SIZE (right));
7285 /* if left is a literal & right is not ||
7286 if left needs acc & right does not */
7287 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7288 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7290 operand *tmp = right;
7295 /* if result = right then exchange them */
7296 if (sameRegs (AOP (result), AOP (right)))
7298 operand *tmp = right;
7303 /* if right is bit then exchange them */
7304 if (AOP_TYPE (right) == AOP_CRY &&
7305 AOP_TYPE (left) != AOP_CRY)
7307 operand *tmp = right;
7311 if (AOP_TYPE (right) == AOP_LIT)
7312 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7314 size = AOP_SIZE (result);
7318 if (AOP_TYPE (left) == AOP_CRY)
7320 if (AOP_TYPE (right) == AOP_LIT)
7322 // c = bit & literal;
7325 // lit>>1 != 0 => result = 1
7326 if (AOP_TYPE (result) == AOP_CRY)
7329 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7331 continueIfTrue (ifx);
7334 emitcode ("setb", "c");
7341 // lit == 0, result = left
7342 if (size && sameRegs (AOP (result), AOP (left)))
7344 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7348 // lit == 1, result = not(left)
7349 if (size && sameRegs (AOP (result), AOP (left)))
7351 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7356 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7357 emitcode ("cpl", "c");
7365 symbol *tlbl = newiTempLabel (NULL);
7366 if (AOP_TYPE (right) == AOP_CRY)
7369 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7373 int sizer = AOP_SIZE (right);
7375 // if val>>1 != 0, result = 1
7376 emitcode ("setb", "c");
7379 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7381 // test the msb of the lsb
7382 emitcode ("anl", "a,#0xfe");
7383 emitcode ("jnz", "%05d$", tlbl->key + 100);
7387 emitcode ("rrc", "a");
7389 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7390 emitcode ("cpl", "c");
7398 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7399 genIfxJump (ifx, "c", left, right, result);
7403 /* if left is same as result */
7404 if (sameRegs (AOP (result), AOP (left)))
7406 for (; size--; offset++)
7408 if (AOP_TYPE (right) == AOP_LIT)
7410 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7413 /* dummy read of volatile operand */
7414 if (isOperandVolatile (left, FALSE))
7415 MOVA (aopGet (left, offset, FALSE, FALSE));
7419 else if (IS_AOP_PREG (left))
7421 MOVA (aopGet (left, offset, FALSE, TRUE));
7422 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7423 aopPut (result, "a", offset);
7427 emitcode ("xrl", "%s,%s",
7428 aopGet (left, offset, FALSE, TRUE),
7429 aopGet (right, offset, FALSE, FALSE));
7434 if (AOP_TYPE (left) == AOP_ACC)
7437 emitcode("mov", "a,b");
7438 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7440 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7442 MOVB (aopGet (left, offset, FALSE, FALSE));
7443 MOVA (aopGet (right, offset, FALSE, FALSE));
7444 emitcode ("xrl", "a,b");
7445 aopPut (result, "a", offset);
7447 else if (aopGetUsesAcc (left, offset))
7449 MOVA (aopGet (left, offset, FALSE, FALSE));
7450 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7451 aopPut (result, "a", offset);
7455 MOVA (aopGet (right, offset, FALSE, FALSE));
7456 if (IS_AOP_PREG (left))
7458 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7459 aopPut (result, "a", offset);
7462 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7469 // left & result in different registers
7470 if (AOP_TYPE (result) == AOP_CRY)
7473 // if(size), result in bit
7474 // if(!size && ifx), conditional oper: if(left ^ right)
7475 symbol *tlbl = newiTempLabel (NULL);
7476 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7479 emitcode ("setb", "c");
7482 if ((AOP_TYPE (right) == AOP_LIT) &&
7483 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7485 MOVA (aopGet (left, offset, FALSE, FALSE));
7487 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7488 && AOP_TYPE(left)==AOP_ACC)
7491 emitcode("mov", "a,b");
7492 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7494 else if (AOP_TYPE(left)==AOP_ACC)
7498 bool pushedB = pushB ();
7499 emitcode("mov", "b,a");
7500 MOVA (aopGet (right, offset, FALSE, FALSE));
7501 emitcode("xrl", "a,b");
7506 MOVA (aopGet (right, offset, FALSE, FALSE));
7507 emitcode("xrl", "a,b");
7510 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7512 MOVB (aopGet (left, offset, FALSE, FALSE));
7513 MOVA (aopGet (right, offset, FALSE, FALSE));
7514 emitcode ("xrl", "a,b");
7516 else if (aopGetUsesAcc (left, offset))
7518 MOVA (aopGet (left, offset, FALSE, FALSE));
7519 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7523 MOVA (aopGet (right, offset, FALSE, FALSE));
7524 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7527 emitcode ("jnz", "%05d$", tlbl->key + 100);
7537 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7541 for (; (size--); offset++)
7544 // result = left ^ right
7545 if (AOP_TYPE (right) == AOP_LIT)
7547 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7551 aopGet (left, offset, FALSE, FALSE),
7556 // faster than result <- left, xrl result,right
7557 // and better if result is SFR
7558 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7559 && AOP_TYPE(left)==AOP_ACC)
7562 emitcode("mov", "a,b");
7563 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7565 else if (AOP_TYPE(left)==AOP_ACC)
7569 bool pushedB = pushB ();
7570 emitcode("mov", "b,a");
7571 MOVA (aopGet (right, offset, FALSE, FALSE));
7572 emitcode("xrl", "a,b");
7577 MOVA (aopGet (right, offset, FALSE, FALSE));
7578 emitcode("xrl", "a,b");
7581 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7583 MOVB (aopGet (left, offset, FALSE, FALSE));
7584 MOVA (aopGet (right, offset, FALSE, FALSE));
7585 emitcode ("xrl", "a,b");
7587 else if (aopGetUsesAcc (left, offset))
7589 MOVA (aopGet (left, offset, FALSE, FALSE));
7590 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7594 MOVA (aopGet (right, offset, FALSE, FALSE));
7595 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7597 aopPut (result, "a", offset);
7603 freeAsmop (result, NULL, ic, TRUE);
7604 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7605 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7608 /*-----------------------------------------------------------------*/
7609 /* genInline - write the inline code out */
7610 /*-----------------------------------------------------------------*/
7612 genInline (iCode * ic)
7614 char *buffer, *bp, *bp1;
7616 D (emitcode (";", "genInline"));
7618 _G.inLine += (!options.asmpeep);
7620 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7622 /* emit each line as a code */
7633 /* Add \n for labels, not dirs such as c:\mydir */
7634 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7648 /* emitcode("",buffer); */
7649 _G.inLine -= (!options.asmpeep);
7652 /*-----------------------------------------------------------------*/
7653 /* genRRC - rotate right with carry */
7654 /*-----------------------------------------------------------------*/
7658 operand *left, *result;
7662 D (emitcode (";", "genRRC"));
7664 /* rotate right with carry */
7665 left = IC_LEFT (ic);
7666 result = IC_RESULT (ic);
7667 aopOp (left, ic, FALSE);
7668 aopOp (result, ic, FALSE);
7670 /* move it to the result */
7671 size = AOP_SIZE (result);
7673 if (size == 1) { /* special case for 1 byte */
7674 l = aopGet (left, offset, FALSE, FALSE);
7676 emitcode ("rr", "a");
7679 /* no need to clear carry, bit7 will be written later */
7682 l = aopGet (left, offset, FALSE, FALSE);
7684 emitcode ("rrc", "a");
7685 if (AOP_SIZE (result) > 1)
7686 aopPut (result, "a", offset--);
7688 /* now we need to put the carry into the
7689 highest order byte of the result */
7690 if (AOP_SIZE (result) > 1)
7692 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7695 emitcode ("mov", "acc.7,c");
7697 aopPut (result, "a", AOP_SIZE (result) - 1);
7698 freeAsmop (result, NULL, ic, TRUE);
7699 freeAsmop (left, NULL, ic, TRUE);
7702 /*-----------------------------------------------------------------*/
7703 /* genRLC - generate code for rotate left with carry */
7704 /*-----------------------------------------------------------------*/
7708 operand *left, *result;
7712 D (emitcode (";", "genRLC"));
7714 /* rotate right with carry */
7715 left = IC_LEFT (ic);
7716 result = IC_RESULT (ic);
7717 aopOp (left, ic, FALSE);
7718 aopOp (result, ic, FALSE);
7720 /* move it to the result */
7721 size = AOP_SIZE (result);
7725 l = aopGet (left, offset, FALSE, FALSE);
7727 if (size == 0) { /* special case for 1 byte */
7731 emitcode("rlc","a"); /* bit0 will be written later */
7732 if (AOP_SIZE (result) > 1)
7734 aopPut (result, "a", offset++);
7739 l = aopGet (left, offset, FALSE, FALSE);
7741 emitcode ("rlc", "a");
7742 if (AOP_SIZE (result) > 1)
7743 aopPut (result, "a", offset++);
7746 /* now we need to put the carry into the
7747 highest order byte of the result */
7748 if (AOP_SIZE (result) > 1)
7750 l = aopGet (result, 0, FALSE, FALSE);
7753 emitcode ("mov", "acc.0,c");
7755 aopPut (result, "a", 0);
7756 freeAsmop (result, NULL, ic, TRUE);
7757 freeAsmop (left, NULL, ic, TRUE);
7760 /*-----------------------------------------------------------------*/
7761 /* genGetHbit - generates code get highest order bit */
7762 /*-----------------------------------------------------------------*/
7764 genGetHbit (iCode * ic)
7766 operand *left, *result;
7768 D (emitcode (";", "genGetHbit"));
7770 left = IC_LEFT (ic);
7771 result = IC_RESULT (ic);
7772 aopOp (left, ic, FALSE);
7773 aopOp (result, ic, FALSE);
7775 /* get the highest order byte into a */
7776 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7777 if (AOP_TYPE (result) == AOP_CRY)
7779 emitcode ("rlc", "a");
7784 emitcode ("rl", "a");
7785 emitcode ("anl", "a,#0x01");
7789 freeAsmop (result, NULL, ic, TRUE);
7790 freeAsmop (left, NULL, ic, TRUE);
7793 /*-----------------------------------------------------------------*/
7794 /* genGetAbit - generates code get a single bit */
7795 /*-----------------------------------------------------------------*/
7797 genGetAbit (iCode * ic)
7799 operand *left, *right, *result;
7802 D (emitcode (";", "genGetAbit"));
7804 left = IC_LEFT (ic);
7805 right = IC_RIGHT (ic);
7806 result = IC_RESULT (ic);
7807 aopOp (left, ic, FALSE);
7808 aopOp (right, ic, FALSE);
7809 aopOp (result, ic, FALSE);
7811 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7813 /* get the needed byte into a */
7814 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7816 if (AOP_TYPE (result) == AOP_CRY)
7819 emitcode ("rlc", "a");
7820 else if ((shCount) == 0)
7821 emitcode ("rrc", "a");
7823 emitcode ("mov", "c,acc[%d]", shCount);
7831 emitcode ("rr", "a");
7834 emitcode ("rr", "a");
7837 emitcode ("anl", "a,#0x01");
7841 emitcode ("mov", "c,acc[%d]", shCount);
7842 emitcode ("clr", "a");
7843 emitcode ("rlc", "a");
7846 emitcode ("swap", "a");
7847 emitcode ("anl", "a,#0x01");
7850 emitcode ("rl", "a");
7853 emitcode ("rl", "a");
7854 emitcode ("anl", "a,#0x01");
7860 freeAsmop (result, NULL, ic, TRUE);
7861 freeAsmop (right, NULL, ic, TRUE);
7862 freeAsmop (left, NULL, ic, TRUE);
7865 /*-----------------------------------------------------------------*/
7866 /* genGetByte - generates code get a single byte */
7867 /*-----------------------------------------------------------------*/
7869 genGetByte (iCode * ic)
7871 operand *left, *right, *result;
7874 D (emitcode (";", "genGetByte"));
7876 left = IC_LEFT (ic);
7877 right = IC_RIGHT (ic);
7878 result = IC_RESULT (ic);
7879 aopOp (left, ic, FALSE);
7880 aopOp (right, ic, FALSE);
7881 aopOp (result, ic, FALSE);
7883 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7885 aopGet (left, offset, FALSE, FALSE),
7888 freeAsmop (result, NULL, ic, TRUE);
7889 freeAsmop (right, NULL, ic, TRUE);
7890 freeAsmop (left, NULL, ic, TRUE);
7893 /*-----------------------------------------------------------------*/
7894 /* genGetWord - generates code get two bytes */
7895 /*-----------------------------------------------------------------*/
7897 genGetWord (iCode * ic)
7899 operand *left, *right, *result;
7902 D (emitcode (";", "genGetWord"));
7904 left = IC_LEFT (ic);
7905 right = IC_RIGHT (ic);
7906 result = IC_RESULT (ic);
7907 aopOp (left, ic, FALSE);
7908 aopOp (right, ic, FALSE);
7909 aopOp (result, ic, FALSE);
7911 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7913 aopGet (left, offset, FALSE, FALSE),
7916 aopGet (left, offset+1, FALSE, FALSE),
7919 freeAsmop (result, NULL, ic, TRUE);
7920 freeAsmop (right, NULL, ic, TRUE);
7921 freeAsmop (left, NULL, ic, TRUE);
7924 /*-----------------------------------------------------------------*/
7925 /* genSwap - generates code to swap nibbles or bytes */
7926 /*-----------------------------------------------------------------*/
7928 genSwap (iCode * ic)
7930 operand *left, *result;
7932 D(emitcode ("; genSwap",""));
7934 left = IC_LEFT (ic);
7935 result = IC_RESULT (ic);
7936 aopOp (left, ic, FALSE);
7937 aopOp (result, ic, FALSE);
7939 switch (AOP_SIZE (left))
7941 case 1: /* swap nibbles in byte */
7942 MOVA (aopGet (left, 0, FALSE, FALSE));
7943 emitcode ("swap", "a");
7944 aopPut (result, "a", 0);
7946 case 2: /* swap bytes in word */
7947 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7949 MOVA (aopGet (left, 0, FALSE, FALSE));
7950 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7951 aopPut (result, "a", 1);
7953 else if (operandsEqu (left, result))
7956 bool pushedB = FALSE, leftInB = FALSE;
7958 MOVA (aopGet (left, 0, FALSE, FALSE));
7959 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7962 emitcode ("mov", "b,a");
7966 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7967 aopPut (result, reg, 1);
7974 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7975 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7979 wassertl(FALSE, "unsupported SWAP operand size");
7982 freeAsmop (result, NULL, ic, TRUE);
7983 freeAsmop (left, NULL, ic, TRUE);
7986 /*-----------------------------------------------------------------*/
7987 /* AccRol - rotate left accumulator by known count */
7988 /*-----------------------------------------------------------------*/
7990 AccRol (int shCount)
7992 shCount &= 0x0007; // shCount : 0..7
7999 emitcode ("rl", "a");
8002 emitcode ("rl", "a");
8003 emitcode ("rl", "a");
8006 emitcode ("swap", "a");
8007 emitcode ("rr", "a");
8010 emitcode ("swap", "a");
8013 emitcode ("swap", "a");
8014 emitcode ("rl", "a");
8017 emitcode ("rr", "a");
8018 emitcode ("rr", "a");
8021 emitcode ("rr", "a");
8026 /*-----------------------------------------------------------------*/
8027 /* AccLsh - left shift accumulator by known count */
8028 /*-----------------------------------------------------------------*/
8030 AccLsh (int shCount)
8035 emitcode ("add", "a,acc");
8036 else if (shCount == 2)
8038 emitcode ("add", "a,acc");
8039 emitcode ("add", "a,acc");
8043 /* rotate left accumulator */
8045 /* and kill the lower order bits */
8046 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8051 /*-----------------------------------------------------------------*/
8052 /* AccRsh - right shift accumulator by known count */
8053 /*-----------------------------------------------------------------*/
8055 AccRsh (int shCount)
8062 emitcode ("rrc", "a");
8066 /* rotate right accumulator */
8067 AccRol (8 - shCount);
8068 /* and kill the higher order bits */
8069 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8074 /*-----------------------------------------------------------------*/
8075 /* AccSRsh - signed right shift accumulator by known count */
8076 /*-----------------------------------------------------------------*/
8078 AccSRsh (int shCount)
8085 emitcode ("mov", "c,acc.7");
8086 emitcode ("rrc", "a");
8088 else if (shCount == 2)
8090 emitcode ("mov", "c,acc.7");
8091 emitcode ("rrc", "a");
8092 emitcode ("mov", "c,acc.7");
8093 emitcode ("rrc", "a");
8097 tlbl = newiTempLabel (NULL);
8098 /* rotate right accumulator */
8099 AccRol (8 - shCount);
8100 /* and kill the higher order bits */
8101 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8102 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8103 emitcode ("orl", "a,#0x%02x",
8104 (unsigned char) ~SRMask[shCount]);
8110 /*-----------------------------------------------------------------*/
8111 /* shiftR1Left2Result - shift right one byte from left to result */
8112 /*-----------------------------------------------------------------*/
8114 shiftR1Left2Result (operand * left, int offl,
8115 operand * result, int offr,
8116 int shCount, int sign)
8118 MOVA (aopGet (left, offl, FALSE, FALSE));
8119 /* shift right accumulator */
8124 aopPut (result, "a", offr);
8127 /*-----------------------------------------------------------------*/
8128 /* shiftL1Left2Result - shift left one byte from left to result */
8129 /*-----------------------------------------------------------------*/
8131 shiftL1Left2Result (operand * left, int offl,
8132 operand * result, int offr, int shCount)
8135 l = aopGet (left, offl, FALSE, FALSE);
8137 /* shift left accumulator */
8139 aopPut (result, "a", offr);
8142 /*-----------------------------------------------------------------*/
8143 /* movLeft2Result - move byte from left to result */
8144 /*-----------------------------------------------------------------*/
8146 movLeft2Result (operand * left, int offl,
8147 operand * result, int offr, int sign)
8150 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8152 l = aopGet (left, offl, FALSE, FALSE);
8154 if (*l == '@' && (IS_AOP_PREG (result)))
8156 emitcode ("mov", "a,%s", l);
8157 aopPut (result, "a", offr);
8163 aopPut (result, l, offr);
8167 /* MSB sign in acc.7 ! */
8168 if (getDataSize (left) == offl + 1)
8171 aopPut (result, "a", offr);
8178 /*-----------------------------------------------------------------*/
8179 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8180 /*-----------------------------------------------------------------*/
8184 emitcode ("rrc", "a");
8185 emitcode ("xch", "a,%s", x);
8186 emitcode ("rrc", "a");
8187 emitcode ("xch", "a,%s", x);
8190 /*-----------------------------------------------------------------*/
8191 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8192 /*-----------------------------------------------------------------*/
8196 emitcode ("xch", "a,%s", x);
8197 emitcode ("rlc", "a");
8198 emitcode ("xch", "a,%s", x);
8199 emitcode ("rlc", "a");
8202 /*-----------------------------------------------------------------*/
8203 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8204 /*-----------------------------------------------------------------*/
8208 emitcode ("xch", "a,%s", x);
8209 emitcode ("add", "a,acc");
8210 emitcode ("xch", "a,%s", x);
8211 emitcode ("rlc", "a");
8214 /*-----------------------------------------------------------------*/
8215 /* AccAXLsh - left shift a:x by known count (0..7) */
8216 /*-----------------------------------------------------------------*/
8218 AccAXLsh (char *x, int shCount)
8233 case 5: // AAAAABBB:CCCCCDDD
8235 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8237 emitcode ("anl", "a,#0x%02x",
8238 SLMask[shCount]); // BBB00000:CCCCCDDD
8240 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8242 AccRol (shCount); // DDDCCCCC:BBB00000
8244 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8246 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8248 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8250 emitcode ("anl", "a,#0x%02x",
8251 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8253 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8255 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8258 case 6: // AAAAAABB:CCCCCCDD
8259 emitcode ("anl", "a,#0x%02x",
8260 SRMask[shCount]); // 000000BB:CCCCCCDD
8261 emitcode ("mov", "c,acc.0"); // c = B
8262 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8264 AccAXRrl1 (x); // BCCCCCCD:D000000B
8265 AccAXRrl1 (x); // BBCCCCCC:DD000000
8267 emitcode("rrc","a");
8268 emitcode("xch","a,%s", x);
8269 emitcode("rrc","a");
8270 emitcode("mov","c,acc.0"); //<< get correct bit
8271 emitcode("xch","a,%s", x);
8273 emitcode("rrc","a");
8274 emitcode("xch","a,%s", x);
8275 emitcode("rrc","a");
8276 emitcode("xch","a,%s", x);
8279 case 7: // a:x <<= 7
8281 emitcode ("anl", "a,#0x%02x",
8282 SRMask[shCount]); // 0000000B:CCCCCCCD
8284 emitcode ("mov", "c,acc.0"); // c = B
8286 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8288 AccAXRrl1 (x); // BCCCCCCC:D0000000
8296 /*-----------------------------------------------------------------*/
8297 /* AccAXRsh - right shift a:x known count (0..7) */
8298 /*-----------------------------------------------------------------*/
8300 AccAXRsh (char *x, int shCount)
8308 AccAXRrl1 (x); // 0->a:x
8313 AccAXRrl1 (x); // 0->a:x
8316 AccAXRrl1 (x); // 0->a:x
8321 case 5: // AAAAABBB:CCCCCDDD = a:x
8323 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8325 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8327 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8329 emitcode ("anl", "a,#0x%02x",
8330 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8332 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8334 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8336 emitcode ("anl", "a,#0x%02x",
8337 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8339 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8341 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8343 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8346 case 6: // AABBBBBB:CCDDDDDD
8348 emitcode ("mov", "c,acc.7");
8349 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8351 emitcode ("mov", "c,acc.7");
8352 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8354 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8356 emitcode ("anl", "a,#0x%02x",
8357 SRMask[shCount]); // 000000AA:BBBBBBCC
8360 case 7: // ABBBBBBB:CDDDDDDD
8362 emitcode ("mov", "c,acc.7"); // c = A
8364 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8366 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8368 emitcode ("anl", "a,#0x%02x",
8369 SRMask[shCount]); // 0000000A:BBBBBBBC
8377 /*-----------------------------------------------------------------*/
8378 /* AccAXRshS - right shift signed a:x known count (0..7) */
8379 /*-----------------------------------------------------------------*/
8381 AccAXRshS (char *x, int shCount)
8389 emitcode ("mov", "c,acc.7");
8390 AccAXRrl1 (x); // s->a:x
8394 emitcode ("mov", "c,acc.7");
8395 AccAXRrl1 (x); // s->a:x
8397 emitcode ("mov", "c,acc.7");
8398 AccAXRrl1 (x); // s->a:x
8403 case 5: // AAAAABBB:CCCCCDDD = a:x
8405 tlbl = newiTempLabel (NULL);
8406 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8408 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8410 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8412 emitcode ("anl", "a,#0x%02x",
8413 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8415 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8417 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8419 emitcode ("anl", "a,#0x%02x",
8420 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8422 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8424 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8426 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8428 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8429 emitcode ("orl", "a,#0x%02x",
8430 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8433 break; // SSSSAAAA:BBBCCCCC
8435 case 6: // AABBBBBB:CCDDDDDD
8437 tlbl = newiTempLabel (NULL);
8438 emitcode ("mov", "c,acc.7");
8439 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8441 emitcode ("mov", "c,acc.7");
8442 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8444 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8446 emitcode ("anl", "a,#0x%02x",
8447 SRMask[shCount]); // 000000AA:BBBBBBCC
8449 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8450 emitcode ("orl", "a,#0x%02x",
8451 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8455 case 7: // ABBBBBBB:CDDDDDDD
8457 tlbl = newiTempLabel (NULL);
8458 emitcode ("mov", "c,acc.7"); // c = A
8460 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8462 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8464 emitcode ("anl", "a,#0x%02x",
8465 SRMask[shCount]); // 0000000A:BBBBBBBC
8467 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8468 emitcode ("orl", "a,#0x%02x",
8469 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8478 /*-----------------------------------------------------------------*/
8479 /* shiftL2Left2Result - shift left two bytes from left to result */
8480 /*-----------------------------------------------------------------*/
8482 shiftL2Left2Result (operand * left, int offl,
8483 operand * result, int offr, int shCount)
8486 bool pushedB = FALSE;
8489 if (sameRegs (AOP (result), AOP (left)) &&
8490 ((offl + MSB16) == offr))
8492 /* don't crash result[offr] */
8493 MOVA (aopGet (left, offl, FALSE, FALSE));
8494 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8495 usedB = !strncmp(x, "b", 1);
8497 else if (aopGetUsesAcc (result, offr))
8499 movLeft2Result (left, offl, result, offr, 0);
8502 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8503 MOVA (aopGet (result, offr, FALSE, FALSE));
8504 emitcode ("xch", "a,b");
8509 movLeft2Result (left, offl, result, offr, 0);
8510 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8511 x = aopGet (result, offr, FALSE, FALSE);
8513 /* ax << shCount (x = lsb(result)) */
8514 AccAXLsh (x, shCount);
8517 emitcode ("xch", "a,b");
8518 aopPut (result, "a", offr);
8519 aopPut (result, "b", offr + MSB16);
8524 aopPut (result, "a", offr + MSB16);
8529 /*-----------------------------------------------------------------*/
8530 /* shiftR2Left2Result - shift right two bytes from left to result */
8531 /*-----------------------------------------------------------------*/
8533 shiftR2Left2Result (operand * left, int offl,
8534 operand * result, int offr,
8535 int shCount, int sign)
8538 bool pushedB = FALSE;
8541 if (sameRegs (AOP (result), AOP (left)) &&
8542 ((offl + MSB16) == offr))
8544 /* don't crash result[offr] */
8545 MOVA (aopGet (left, offl, FALSE, FALSE));
8546 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8547 usedB = !strncmp(x, "b", 1);
8549 else if (aopGetUsesAcc (result, offr))
8551 movLeft2Result (left, offl, result, offr, 0);
8554 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8555 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8560 movLeft2Result (left, offl, result, offr, 0);
8561 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8562 x = aopGet (result, offr, FALSE, FALSE);
8564 /* a:x >> shCount (x = lsb(result)) */
8566 AccAXRshS (x, shCount);
8568 AccAXRsh (x, shCount);
8571 emitcode ("xch", "a,b");
8572 aopPut (result, "a", offr);
8573 emitcode ("xch", "a,b");
8576 if (getDataSize (result) > 1)
8577 aopPut (result, "a", offr + MSB16);
8580 /*-----------------------------------------------------------------*/
8581 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8582 /*-----------------------------------------------------------------*/
8584 shiftLLeftOrResult (operand * left, int offl,
8585 operand * result, int offr, int shCount)
8587 MOVA (aopGet (left, offl, FALSE, FALSE));
8588 /* shift left accumulator */
8590 /* or with result */
8591 if (aopGetUsesAcc (result, offr))
8593 emitcode ("xch", "a,b");
8594 MOVA (aopGet (result, offr, FALSE, FALSE));
8595 emitcode ("orl", "a,b");
8599 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8601 /* back to result */
8602 aopPut (result, "a", offr);
8605 /*-----------------------------------------------------------------*/
8606 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8607 /*-----------------------------------------------------------------*/
8609 shiftRLeftOrResult (operand * left, int offl,
8610 operand * result, int offr, int shCount)
8612 MOVA (aopGet (left, offl, FALSE, FALSE));
8613 /* shift right accumulator */
8615 /* or with result */
8616 if (aopGetUsesAcc(result, offr))
8618 emitcode ("xch", "a,b");
8619 MOVA (aopGet (result, offr, FALSE, FALSE));
8620 emitcode ("orl", "a,b");
8624 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8626 /* back to result */
8627 aopPut (result, "a", offr);
8630 /*-----------------------------------------------------------------*/
8631 /* genlshOne - left shift a one byte quantity by known count */
8632 /*-----------------------------------------------------------------*/
8634 genlshOne (operand * result, operand * left, int shCount)
8636 D (emitcode (";", "genlshOne"));
8638 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8641 /*-----------------------------------------------------------------*/
8642 /* genlshTwo - left shift two bytes by known amount != 0 */
8643 /*-----------------------------------------------------------------*/
8645 genlshTwo (operand * result, operand * left, int shCount)
8649 D (emitcode (";", "genlshTwo"));
8651 size = getDataSize (result);
8653 /* if shCount >= 8 */
8661 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8663 movLeft2Result (left, LSB, result, MSB16, 0);
8665 aopPut (result, zero, LSB);
8668 /* 1 <= shCount <= 7 */
8672 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8674 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8678 /*-----------------------------------------------------------------*/
8679 /* shiftLLong - shift left one long from left to result */
8680 /* offl = LSB or MSB16 */
8681 /*-----------------------------------------------------------------*/
8683 shiftLLong (operand * left, operand * result, int offr)
8686 int size = AOP_SIZE (result);
8688 if (size >= LSB + offr)
8690 l = aopGet (left, LSB, FALSE, FALSE);
8692 emitcode ("add", "a,acc");
8693 if (sameRegs (AOP (left), AOP (result)) &&
8694 size >= MSB16 + offr && offr != LSB)
8695 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8697 aopPut (result, "a", LSB + offr);
8700 if (size >= MSB16 + offr)
8702 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8704 l = aopGet (left, MSB16, FALSE, FALSE);
8707 emitcode ("rlc", "a");
8708 if (sameRegs (AOP (left), AOP (result)) &&
8709 size >= MSB24 + offr && offr != LSB)
8710 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8712 aopPut (result, "a", MSB16 + offr);
8715 if (size >= MSB24 + offr)
8717 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8719 l = aopGet (left, MSB24, FALSE, FALSE);
8722 emitcode ("rlc", "a");
8723 if (sameRegs (AOP (left), AOP (result)) &&
8724 size >= MSB32 + offr && offr != LSB)
8725 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8727 aopPut (result, "a", MSB24 + offr);
8730 if (size > MSB32 + offr)
8732 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8734 l = aopGet (left, MSB32, FALSE, FALSE);
8737 emitcode ("rlc", "a");
8738 aopPut (result, "a", MSB32 + offr);
8741 aopPut (result, zero, LSB);
8744 /*-----------------------------------------------------------------*/
8745 /* genlshFour - shift four byte by a known amount != 0 */
8746 /*-----------------------------------------------------------------*/
8748 genlshFour (operand * result, operand * left, int shCount)
8752 D (emitcode (";", "genlshFour"));
8754 size = AOP_SIZE (result);
8756 /* if shifting more that 3 bytes */
8761 /* lowest order of left goes to the highest
8762 order of the destination */
8763 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8765 movLeft2Result (left, LSB, result, MSB32, 0);
8766 aopPut (result, zero, LSB);
8767 aopPut (result, zero, MSB16);
8768 aopPut (result, zero, MSB24);
8772 /* more than two bytes */
8773 else if (shCount >= 16)
8775 /* lower order two bytes goes to higher order two bytes */
8777 /* if some more remaining */
8779 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8782 movLeft2Result (left, MSB16, result, MSB32, 0);
8783 movLeft2Result (left, LSB, result, MSB24, 0);
8785 aopPut (result, zero, MSB16);
8786 aopPut (result, zero, LSB);
8790 /* if more than 1 byte */
8791 else if (shCount >= 8)
8793 /* lower order three bytes goes to higher order three bytes */
8798 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8800 movLeft2Result (left, LSB, result, MSB16, 0);
8806 movLeft2Result (left, MSB24, result, MSB32, 0);
8807 movLeft2Result (left, MSB16, result, MSB24, 0);
8808 movLeft2Result (left, LSB, result, MSB16, 0);
8809 aopPut (result, zero, LSB);
8811 else if (shCount == 1)
8812 shiftLLong (left, result, MSB16);
8815 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8816 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8817 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8818 aopPut (result, zero, LSB);
8823 /* 1 <= shCount <= 7 */
8824 else if (shCount <= 2)
8826 shiftLLong (left, result, LSB);
8828 shiftLLong (result, result, LSB);
8830 /* 3 <= shCount <= 7, optimize */
8833 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8834 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8835 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8839 /*-----------------------------------------------------------------*/
8840 /* genLeftShiftLiteral - left shifting by known count */
8841 /*-----------------------------------------------------------------*/
8843 genLeftShiftLiteral (operand * left,
8848 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8851 D (emitcode (";", "genLeftShiftLiteral"));
8853 freeAsmop (right, NULL, ic, TRUE);
8855 aopOp (left, ic, FALSE);
8856 aopOp (result, ic, FALSE);
8858 size = getSize (operandType (result));
8861 emitcode ("; shift left ", "result %d, left %d", size,
8865 /* I suppose that the left size >= result size */
8870 movLeft2Result (left, size, result, size, 0);
8873 else if (shCount >= (size * 8))
8877 aopPut (result, zero, size);
8885 genlshOne (result, left, shCount);
8889 genlshTwo (result, left, shCount);
8893 genlshFour (result, left, shCount);
8896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8897 "*** ack! mystery literal shift!\n");
8901 freeAsmop (result, NULL, ic, TRUE);
8902 freeAsmop (left, NULL, ic, TRUE);
8905 /*-----------------------------------------------------------------*/
8906 /* genLeftShift - generates code for left shifting */
8907 /*-----------------------------------------------------------------*/
8909 genLeftShift (iCode * ic)
8911 operand *left, *right, *result;
8914 symbol *tlbl, *tlbl1;
8917 D (emitcode (";", "genLeftShift"));
8919 right = IC_RIGHT (ic);
8920 left = IC_LEFT (ic);
8921 result = IC_RESULT (ic);
8923 aopOp (right, ic, FALSE);
8925 /* if the shift count is known then do it
8926 as efficiently as possible */
8927 if (AOP_TYPE (right) == AOP_LIT)
8929 genLeftShiftLiteral (left, right, result, ic);
8933 /* shift count is unknown then we have to form
8934 a loop get the loop count in B : Note: we take
8935 only the lower order byte since shifting
8936 more that 32 bits make no sense anyway, ( the
8937 largest size of an object can be only 32 bits ) */
8940 MOVB (aopGet (right, 0, FALSE, FALSE));
8941 emitcode ("inc", "b");
8942 freeAsmop (right, NULL, ic, TRUE);
8943 aopOp (left, ic, FALSE);
8944 aopOp (result, ic, FALSE);
8946 /* now move the left to the result if they are not the same */
8947 if (!sameRegs (AOP (left), AOP (result)) &&
8948 AOP_SIZE (result) > 1)
8951 size = AOP_SIZE (result);
8955 l = aopGet (left, offset, FALSE, TRUE);
8956 if (*l == '@' && (IS_AOP_PREG (result)))
8959 emitcode ("mov", "a,%s", l);
8960 aopPut (result, "a", offset);
8963 aopPut (result, l, offset);
8968 tlbl = newiTempLabel (NULL);
8969 size = AOP_SIZE (result);
8971 tlbl1 = newiTempLabel (NULL);
8973 /* if it is only one byte then */
8976 symbol *tlbl1 = newiTempLabel (NULL);
8978 l = aopGet (left, 0, FALSE, FALSE);
8980 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8982 emitcode ("add", "a,acc");
8984 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8986 aopPut (result, "a", 0);
8990 reAdjustPreg (AOP (result));
8992 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8994 l = aopGet (result, offset, FALSE, FALSE);
8996 emitcode ("add", "a,acc");
8997 aopPut (result, "a", offset++);
9000 l = aopGet (result, offset, FALSE, FALSE);
9002 emitcode ("rlc", "a");
9003 aopPut (result, "a", offset++);
9005 reAdjustPreg (AOP (result));
9008 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9011 freeAsmop (result, NULL, ic, TRUE);
9012 freeAsmop (left, NULL, ic, TRUE);
9015 /*-----------------------------------------------------------------*/
9016 /* genrshOne - right shift a one byte quantity by known count */
9017 /*-----------------------------------------------------------------*/
9019 genrshOne (operand * result, operand * left,
9020 int shCount, int sign)
9022 D (emitcode (";", "genrshOne"));
9024 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9027 /*-----------------------------------------------------------------*/
9028 /* genrshTwo - right shift two bytes by known amount != 0 */
9029 /*-----------------------------------------------------------------*/
9031 genrshTwo (operand * result, operand * left,
9032 int shCount, int sign)
9034 D (emitcode (";", "genrshTwo"));
9036 /* if shCount >= 8 */
9041 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9043 movLeft2Result (left, MSB16, result, LSB, sign);
9044 addSign (result, MSB16, sign);
9047 /* 1 <= shCount <= 7 */
9049 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9052 /*-----------------------------------------------------------------*/
9053 /* shiftRLong - shift right one long from left to result */
9054 /* offl = LSB or MSB16 */
9055 /*-----------------------------------------------------------------*/
9057 shiftRLong (operand * left, int offl,
9058 operand * result, int sign)
9060 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9062 if (overlapping && offl>1)
9064 // we are in big trouble, but this shouldn't happen
9065 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9068 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9075 emitcode ("rlc", "a");
9076 emitcode ("subb", "a,acc");
9077 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9079 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9083 aopPut (result, "a", MSB32);
9084 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9089 if (aopPutUsesAcc (result, zero, MSB32))
9091 emitcode("xch", "a,b");
9092 aopPut (result, zero, MSB32);
9093 emitcode("xch", "a,b");
9097 aopPut (result, zero, MSB32);
9104 emitcode ("clr", "c");
9108 emitcode ("mov", "c,acc.7");
9111 emitcode ("rrc", "a");
9113 if (overlapping && offl==MSB16 &&
9114 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9116 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9120 aopPut (result, "a", MSB32 - offl);
9121 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9124 emitcode ("rrc", "a");
9125 if (overlapping && offl==MSB16 &&
9126 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9128 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9132 aopPut (result, "a", MSB24 - offl);
9133 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9136 emitcode ("rrc", "a");
9139 aopPut (result, "a", MSB16 - offl);
9144 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9146 xch_a_aopGet (left, LSB, FALSE, FALSE);
9150 aopPut (result, "a", MSB16 - offl);
9151 MOVA (aopGet (left, LSB, FALSE, FALSE));
9153 emitcode ("rrc", "a");
9154 aopPut (result, "a", LSB);
9158 /*-----------------------------------------------------------------*/
9159 /* genrshFour - shift four byte by a known amount != 0 */
9160 /*-----------------------------------------------------------------*/
9162 genrshFour (operand * result, operand * left,
9163 int shCount, int sign)
9165 D (emitcode (";", "genrshFour"));
9167 /* if shifting more that 3 bytes */
9172 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9174 movLeft2Result (left, MSB32, result, LSB, sign);
9175 addSign (result, MSB16, sign);
9177 else if (shCount >= 16)
9181 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9184 movLeft2Result (left, MSB24, result, LSB, 0);
9185 movLeft2Result (left, MSB32, result, MSB16, sign);
9187 addSign (result, MSB24, sign);
9189 else if (shCount >= 8)
9194 shiftRLong (left, MSB16, result, sign);
9196 else if (shCount == 0)
9198 movLeft2Result (left, MSB16, result, LSB, 0);
9199 movLeft2Result (left, MSB24, result, MSB16, 0);
9200 movLeft2Result (left, MSB32, result, MSB24, sign);
9201 addSign (result, MSB32, sign);
9205 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9206 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9207 /* the last shift is signed */
9208 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9209 addSign (result, MSB32, sign);
9214 /* 1 <= shCount <= 7 */
9217 shiftRLong (left, LSB, result, sign);
9219 shiftRLong (result, LSB, result, sign);
9223 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9224 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9225 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9230 /*-----------------------------------------------------------------*/
9231 /* genRightShiftLiteral - right shifting by known count */
9232 /*-----------------------------------------------------------------*/
9234 genRightShiftLiteral (operand * left,
9240 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9243 D (emitcode (";", "genRightShiftLiteral"));
9245 freeAsmop (right, NULL, ic, TRUE);
9247 aopOp (left, ic, FALSE);
9248 aopOp (result, ic, FALSE);
9251 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9255 size = getDataSize (left);
9256 /* test the LEFT size !!! */
9258 /* I suppose that the left size >= result size */
9261 size = getDataSize (result);
9263 movLeft2Result (left, size, result, size, 0);
9266 else if (shCount >= (size * 8))
9270 /* get sign in acc.7 */
9271 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9273 addSign (result, LSB, sign);
9280 genrshOne (result, left, shCount, sign);
9284 genrshTwo (result, left, shCount, sign);
9288 genrshFour (result, left, shCount, sign);
9294 freeAsmop (result, NULL, ic, TRUE);
9295 freeAsmop (left, NULL, ic, TRUE);
9298 /*-----------------------------------------------------------------*/
9299 /* genSignedRightShift - right shift of signed number */
9300 /*-----------------------------------------------------------------*/
9302 genSignedRightShift (iCode * ic)
9304 operand *right, *left, *result;
9307 symbol *tlbl, *tlbl1;
9310 D (emitcode (";", "genSignedRightShift"));
9312 /* we do it the hard way put the shift count in b
9313 and loop thru preserving the sign */
9315 right = IC_RIGHT (ic);
9316 left = IC_LEFT (ic);
9317 result = IC_RESULT (ic);
9319 aopOp (right, ic, FALSE);
9322 if (AOP_TYPE (right) == AOP_LIT)
9324 genRightShiftLiteral (left, right, result, ic, 1);
9327 /* shift count is unknown then we have to form
9328 a loop get the loop count in B : Note: we take
9329 only the lower order byte since shifting
9330 more that 32 bits make no sense anyway, ( the
9331 largest size of an object can be only 32 bits ) */
9334 MOVB (aopGet (right, 0, FALSE, FALSE));
9335 emitcode ("inc", "b");
9336 freeAsmop (right, NULL, ic, TRUE);
9337 aopOp (left, ic, FALSE);
9338 aopOp (result, ic, FALSE);
9340 /* now move the left to the result if they are not the
9342 if (!sameRegs (AOP (left), AOP (result)) &&
9343 AOP_SIZE (result) > 1)
9346 size = AOP_SIZE (result);
9350 l = aopGet (left, offset, FALSE, TRUE);
9351 if (*l == '@' && IS_AOP_PREG (result))
9354 emitcode ("mov", "a,%s", l);
9355 aopPut (result, "a", offset);
9358 aopPut (result, l, offset);
9363 /* mov the highest order bit to OVR */
9364 tlbl = newiTempLabel (NULL);
9365 tlbl1 = newiTempLabel (NULL);
9367 size = AOP_SIZE (result);
9369 MOVA (aopGet (left, offset, FALSE, FALSE));
9370 emitcode ("rlc", "a");
9371 emitcode ("mov", "ov,c");
9372 /* if it is only one byte then */
9375 l = aopGet (left, 0, FALSE, FALSE);
9377 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9379 emitcode ("mov", "c,ov");
9380 emitcode ("rrc", "a");
9382 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9384 aopPut (result, "a", 0);
9388 reAdjustPreg (AOP (result));
9389 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9391 emitcode ("mov", "c,ov");
9394 l = aopGet (result, offset, FALSE, FALSE);
9396 emitcode ("rrc", "a");
9397 aopPut (result, "a", offset--);
9399 reAdjustPreg (AOP (result));
9401 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9405 freeAsmop (result, NULL, ic, TRUE);
9406 freeAsmop (left, NULL, ic, TRUE);
9409 /*-----------------------------------------------------------------*/
9410 /* genRightShift - generate code for right shifting */
9411 /*-----------------------------------------------------------------*/
9413 genRightShift (iCode * ic)
9415 operand *right, *left, *result;
9419 symbol *tlbl, *tlbl1;
9422 D (emitcode (";", "genRightShift"));
9424 /* if signed then we do it the hard way preserve the
9425 sign bit moving it inwards */
9426 letype = getSpec (operandType (IC_LEFT (ic)));
9428 if (!SPEC_USIGN (letype))
9430 genSignedRightShift (ic);
9434 /* signed & unsigned types are treated the same : i.e. the
9435 signed is NOT propagated inwards : quoting from the
9436 ANSI - standard : "for E1 >> E2, is equivalent to division
9437 by 2**E2 if unsigned or if it has a non-negative value,
9438 otherwise the result is implementation defined ", MY definition
9439 is that the sign does not get propagated */
9441 right = IC_RIGHT (ic);
9442 left = IC_LEFT (ic);
9443 result = IC_RESULT (ic);
9445 aopOp (right, ic, FALSE);
9447 /* if the shift count is known then do it
9448 as efficiently as possible */
9449 if (AOP_TYPE (right) == AOP_LIT)
9451 genRightShiftLiteral (left, right, result, ic, 0);
9455 /* shift count is unknown then we have to form
9456 a loop get the loop count in B : Note: we take
9457 only the lower order byte since shifting
9458 more that 32 bits make no sense anyway, ( the
9459 largest size of an object can be only 32 bits ) */
9462 MOVB (aopGet (right, 0, FALSE, FALSE));
9463 emitcode ("inc", "b");
9464 freeAsmop (right, NULL, ic, TRUE);
9465 aopOp (left, ic, FALSE);
9466 aopOp (result, ic, FALSE);
9468 /* now move the left to the result if they are not the
9470 if (!sameRegs (AOP (left), AOP (result)) &&
9471 AOP_SIZE (result) > 1)
9473 size = AOP_SIZE (result);
9477 l = aopGet (left, offset, FALSE, TRUE);
9478 if (*l == '@' && IS_AOP_PREG (result))
9481 emitcode ("mov", "a,%s", l);
9482 aopPut (result, "a", offset);
9485 aopPut (result, l, offset);
9490 tlbl = newiTempLabel (NULL);
9491 tlbl1 = newiTempLabel (NULL);
9492 size = AOP_SIZE (result);
9495 /* if it is only one byte then */
9498 l = aopGet (left, 0, FALSE, FALSE);
9500 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9503 emitcode ("rrc", "a");
9505 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9507 aopPut (result, "a", 0);
9511 reAdjustPreg (AOP (result));
9512 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9517 l = aopGet (result, offset, FALSE, FALSE);
9519 emitcode ("rrc", "a");
9520 aopPut (result, "a", offset--);
9522 reAdjustPreg (AOP (result));
9525 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9529 freeAsmop (result, NULL, ic, TRUE);
9530 freeAsmop (left, NULL, ic, TRUE);
9533 /*-----------------------------------------------------------------*/
9534 /* emitPtrByteGet - emits code to get a byte into A through a */
9535 /* pointer register (R0, R1, or DPTR). The */
9536 /* original value of A can be preserved in B. */
9537 /*-----------------------------------------------------------------*/
9539 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9546 emitcode ("mov", "b,a");
9547 emitcode ("mov", "a,@%s", rname);
9552 emitcode ("mov", "b,a");
9553 emitcode ("movx", "a,@%s", rname);
9558 emitcode ("mov", "b,a");
9559 emitcode ("movx", "a,@dptr");
9564 emitcode ("mov", "b,a");
9565 emitcode ("clr", "a");
9566 emitcode ("movc", "a,@a+dptr");
9572 emitcode ("push", "b");
9573 emitcode ("push", "acc");
9575 emitcode ("lcall", "__gptrget");
9577 emitcode ("pop", "b");
9582 /*-----------------------------------------------------------------*/
9583 /* emitPtrByteSet - emits code to set a byte from src through a */
9584 /* pointer register (R0, R1, or DPTR). */
9585 /*-----------------------------------------------------------------*/
9587 emitPtrByteSet (char *rname, int p_type, char *src)
9596 emitcode ("mov", "@%s,a", rname);
9599 emitcode ("mov", "@%s,%s", rname, src);
9604 emitcode ("movx", "@%s,a", rname);
9609 emitcode ("movx", "@dptr,a");
9614 emitcode ("lcall", "__gptrput");
9619 /*-----------------------------------------------------------------*/
9620 /* genUnpackBits - generates code for unpacking bits */
9621 /*-----------------------------------------------------------------*/
9623 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9625 int offset = 0; /* result byte offset */
9626 int rsize; /* result size */
9627 int rlen = 0; /* remaining bitfield length */
9628 sym_link *etype; /* bitfield type information */
9629 int blen; /* bitfield length */
9630 int bstr; /* bitfield starting bit within byte */
9633 D(emitcode ("; genUnpackBits",""));
9635 etype = getSpec (operandType (result));
9636 rsize = getSize (operandType (result));
9637 blen = SPEC_BLEN (etype);
9638 bstr = SPEC_BSTR (etype);
9640 if (ifx && blen <= 8)
9642 emitPtrByteGet (rname, ptype, FALSE);
9645 SNPRINTF (buffer, sizeof(buffer),
9647 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9652 emitcode ("anl", "a,#0x%02x",
9653 (((unsigned char) -1) >> (8 - blen)) << bstr);
9654 genIfxJump (ifx, "a", NULL, NULL, NULL);
9660 /* If the bitfield length is less than a byte */
9663 emitPtrByteGet (rname, ptype, FALSE);
9665 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9666 if (!SPEC_USIGN (etype))
9668 /* signed bitfield */
9669 symbol *tlbl = newiTempLabel (NULL);
9671 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9672 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9675 aopPut (result, "a", offset++);
9679 /* Bit field did not fit in a byte. Copy all
9680 but the partial byte at the end. */
9681 for (rlen=blen;rlen>=8;rlen-=8)
9683 emitPtrByteGet (rname, ptype, FALSE);
9684 aopPut (result, "a", offset++);
9686 emitcode ("inc", "%s", rname);
9689 /* Handle the partial byte at the end */
9692 emitPtrByteGet (rname, ptype, FALSE);
9693 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9694 if (!SPEC_USIGN (etype))
9696 /* signed bitfield */
9697 symbol *tlbl = newiTempLabel (NULL);
9699 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9700 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9703 aopPut (result, "a", offset++);
9711 if (SPEC_USIGN (etype))
9715 /* signed bitfield: sign extension with 0x00 or 0xff */
9716 emitcode ("rlc", "a");
9717 emitcode ("subb", "a,acc");
9723 aopPut (result, source, offset++);
9728 /*-----------------------------------------------------------------*/
9729 /* genDataPointerGet - generates code when ptr offset is known */
9730 /*-----------------------------------------------------------------*/
9732 genDataPointerGet (operand * left,
9738 int size, offset = 0;
9740 D (emitcode (";", "genDataPointerGet"));
9742 aopOp (result, ic, TRUE);
9744 /* get the string representation of the name */
9745 l = aopGet (left, 0, FALSE, TRUE);
9747 size = AOP_SIZE (result);
9752 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9756 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9758 aopPut (result, buffer, offset++);
9761 freeAsmop (result, NULL, ic, TRUE);
9762 freeAsmop (left, NULL, ic, TRUE);
9765 /*-----------------------------------------------------------------*/
9766 /* genNearPointerGet - emitcode for near pointer fetch */
9767 /*-----------------------------------------------------------------*/
9769 genNearPointerGet (operand * left,
9778 sym_link *rtype, *retype;
9779 sym_link *ltype = operandType (left);
9782 D (emitcode (";", "genNearPointerGet"));
9784 rtype = operandType (result);
9785 retype = getSpec (rtype);
9787 aopOp (left, ic, FALSE);
9789 /* if left is rematerialisable and
9790 result is not bitfield variable type and
9791 the left is pointer to data space i.e
9792 lower 128 bytes of space */
9793 if (AOP_TYPE (left) == AOP_IMMD &&
9794 !IS_BITFIELD (retype) &&
9795 DCL_TYPE (ltype) == POINTER)
9797 genDataPointerGet (left, result, ic);
9801 /* if the value is already in a pointer register
9802 then don't need anything more */
9803 if (!AOP_INPREG (AOP (left)))
9805 if (IS_AOP_PREG (left))
9807 // Aha, it is a pointer, just in disguise.
9808 rname = aopGet (left, 0, FALSE, FALSE);
9811 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9812 __FILE__, __LINE__);
9817 emitcode ("mov", "a%s,%s", rname + 1, rname);
9818 rname++; // skip the '@'.
9823 /* otherwise get a free pointer register */
9825 preg = getFreePtr (ic, &aop, FALSE);
9826 emitcode ("mov", "%s,%s",
9828 aopGet (left, 0, FALSE, TRUE));
9833 rname = aopGet (left, 0, FALSE, FALSE);
9835 //aopOp (result, ic, FALSE);
9836 aopOp (result, ic, result?TRUE:FALSE);
9838 /* if bitfield then unpack the bits */
9839 if (IS_BITFIELD (retype))
9840 genUnpackBits (result, rname, POINTER, ifx);
9843 /* we have can just get the values */
9844 int size = AOP_SIZE (result);
9849 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9852 emitcode ("mov", "a,@%s", rname);
9854 aopPut (result, "a", offset);
9858 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9859 aopPut (result, buffer, offset);
9863 emitcode ("inc", "%s", rname);
9867 /* now some housekeeping stuff */
9868 if (aop) /* we had to allocate for this iCode */
9870 if (pi) { /* post increment present */
9871 aopPut (left, rname, 0);
9873 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9877 /* we did not allocate which means left
9878 already in a pointer register, then
9879 if size > 0 && this could be used again
9880 we have to point it back to where it
9882 if ((AOP_SIZE (result) > 1 &&
9883 !OP_SYMBOL (left)->remat &&
9884 (OP_SYMBOL (left)->liveTo > ic->seq ||
9888 int size = AOP_SIZE (result) - 1;
9890 emitcode ("dec", "%s", rname);
9894 if (ifx && !ifx->generated)
9896 genIfxJump (ifx, "a", left, NULL, result);
9900 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9901 freeAsmop (left, NULL, ic, TRUE);
9902 if (pi) pi->generated = 1;
9905 /*-----------------------------------------------------------------*/
9906 /* genPagedPointerGet - emitcode for paged pointer fetch */
9907 /*-----------------------------------------------------------------*/
9909 genPagedPointerGet (operand * left,
9918 sym_link *rtype, *retype;
9920 D (emitcode (";", "genPagedPointerGet"));
9922 rtype = operandType (result);
9923 retype = getSpec (rtype);
9925 aopOp (left, ic, FALSE);
9927 /* if the value is already in a pointer register
9928 then don't need anything more */
9929 if (!AOP_INPREG (AOP (left)))
9931 /* otherwise get a free pointer register */
9933 preg = getFreePtr (ic, &aop, FALSE);
9934 emitcode ("mov", "%s,%s",
9936 aopGet (left, 0, FALSE, TRUE));
9940 rname = aopGet (left, 0, FALSE, FALSE);
9942 aopOp (result, ic, FALSE);
9944 /* if bitfield then unpack the bits */
9945 if (IS_BITFIELD (retype))
9946 genUnpackBits (result, rname, PPOINTER, ifx);
9949 /* we have can just get the values */
9950 int size = AOP_SIZE (result);
9956 emitcode ("movx", "a,@%s", rname);
9958 aopPut (result, "a", offset);
9963 emitcode ("inc", "%s", rname);
9967 /* now some housekeeping stuff */
9968 if (aop) /* we had to allocate for this iCode */
9971 aopPut (left, rname, 0);
9972 freeAsmop (NULL, aop, ic, TRUE);
9976 /* we did not allocate which means left
9977 already in a pointer register, then
9978 if size > 0 && this could be used again
9979 we have to point it back to where it
9981 if ((AOP_SIZE (result) > 1 &&
9982 !OP_SYMBOL (left)->remat &&
9983 (OP_SYMBOL (left)->liveTo > ic->seq ||
9987 int size = AOP_SIZE (result) - 1;
9989 emitcode ("dec", "%s", rname);
9993 if (ifx && !ifx->generated)
9995 genIfxJump (ifx, "a", left, NULL, result);
9999 freeAsmop (result, NULL, ic, TRUE);
10000 freeAsmop (left, NULL, ic, TRUE);
10001 if (pi) pi->generated = 1;
10004 /*--------------------------------------------------------------------*/
10005 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10006 /*--------------------------------------------------------------------*/
10008 loadDptrFromOperand (operand *op, bool loadBToo)
10010 if (AOP_TYPE (op) != AOP_STR)
10012 /* if this is rematerializable */
10013 if (AOP_TYPE (op) == AOP_IMMD)
10015 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10018 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10019 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10022 wassertl(FALSE, "need pointerCode");
10023 emitcode ("", "; mov b,???");
10024 /* genPointerGet and genPointerSet originally did different
10025 ** things for this case. Both seem wrong.
10026 ** from genPointerGet:
10027 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10028 ** from genPointerSet:
10029 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10034 else if (AOP_TYPE (op) == AOP_DPTR)
10038 MOVA (aopGet (op, 0, FALSE, FALSE));
10039 emitcode ("push", "acc");
10040 MOVA (aopGet (op, 1, FALSE, FALSE));
10041 emitcode ("push", "acc");
10042 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10043 emitcode ("pop", "dph");
10044 emitcode ("pop", "dpl");
10048 MOVA (aopGet (op, 0, FALSE, FALSE));
10049 emitcode ("push", "acc");
10050 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10051 emitcode ("pop", "dpl");
10055 { /* we need to get it byte by byte */
10056 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10057 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10059 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10064 /*-----------------------------------------------------------------*/
10065 /* genFarPointerGet - get value from far space */
10066 /*-----------------------------------------------------------------*/
10068 genFarPointerGet (operand * left,
10069 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10072 sym_link *retype = getSpec (operandType (result));
10074 D (emitcode (";", "genFarPointerGet"));
10076 aopOp (left, ic, FALSE);
10077 loadDptrFromOperand (left, FALSE);
10079 /* so dptr now contains the address */
10080 aopOp (result, ic, FALSE);
10082 /* if bit then unpack */
10083 if (IS_BITFIELD (retype))
10084 genUnpackBits (result, "dptr", FPOINTER, ifx);
10087 size = AOP_SIZE (result);
10092 emitcode ("movx", "a,@dptr");
10094 aopPut (result, "a", offset++);
10096 emitcode ("inc", "dptr");
10100 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10102 aopPut (left, "dpl", 0);
10103 aopPut (left, "dph", 1);
10107 if (ifx && !ifx->generated)
10109 genIfxJump (ifx, "a", left, NULL, result);
10112 freeAsmop (result, NULL, ic, TRUE);
10113 freeAsmop (left, NULL, ic, TRUE);
10116 /*-----------------------------------------------------------------*/
10117 /* genCodePointerGet - get value from code space */
10118 /*-----------------------------------------------------------------*/
10120 genCodePointerGet (operand * left,
10121 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10124 sym_link *retype = getSpec (operandType (result));
10126 D (emitcode (";", "genCodePointerGet"));
10128 aopOp (left, ic, FALSE);
10129 loadDptrFromOperand (left, FALSE);
10131 /* so dptr now contains the address */
10132 aopOp (result, ic, FALSE);
10134 /* if bit then unpack */
10135 if (IS_BITFIELD (retype))
10136 genUnpackBits (result, "dptr", CPOINTER, ifx);
10139 size = AOP_SIZE (result);
10144 emitcode ("clr", "a");
10145 emitcode ("movc", "a,@a+dptr");
10147 aopPut (result, "a", offset++);
10149 emitcode ("inc", "dptr");
10153 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10155 aopPut (left, "dpl", 0);
10156 aopPut (left, "dph", 1);
10160 if (ifx && !ifx->generated)
10162 genIfxJump (ifx, "a", left, NULL, result);
10165 freeAsmop (result, NULL, ic, TRUE);
10166 freeAsmop (left, NULL, ic, TRUE);
10169 /*-----------------------------------------------------------------*/
10170 /* genGenPointerGet - get value from generic pointer space */
10171 /*-----------------------------------------------------------------*/
10173 genGenPointerGet (operand * left,
10174 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10177 sym_link *retype = getSpec (operandType (result));
10179 D (emitcode (";", "genGenPointerGet"));
10181 aopOp (left, ic, FALSE);
10182 loadDptrFromOperand (left, TRUE);
10184 /* so dptr now contains the address */
10185 aopOp (result, ic, FALSE);
10187 /* if bit then unpack */
10188 if (IS_BITFIELD (retype))
10190 genUnpackBits (result, "dptr", GPOINTER, ifx);
10194 size = AOP_SIZE (result);
10199 emitcode ("lcall", "__gptrget");
10201 aopPut (result, "a", offset++);
10203 emitcode ("inc", "dptr");
10207 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10209 aopPut (left, "dpl", 0);
10210 aopPut (left, "dph", 1);
10214 if (ifx && !ifx->generated)
10216 genIfxJump (ifx, "a", left, NULL, result);
10219 freeAsmop (result, NULL, ic, TRUE);
10220 freeAsmop (left, NULL, ic, TRUE);
10223 /*-----------------------------------------------------------------*/
10224 /* genPointerGet - generate code for pointer get */
10225 /*-----------------------------------------------------------------*/
10227 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10229 operand *left, *result;
10230 sym_link *type, *etype;
10233 D (emitcode (";", "genPointerGet"));
10235 left = IC_LEFT (ic);
10236 result = IC_RESULT (ic);
10238 if (getSize (operandType (result))>1)
10241 /* depending on the type of pointer we need to
10242 move it to the correct pointer register */
10243 type = operandType (left);
10244 etype = getSpec (type);
10245 /* if left is of type of pointer then it is simple */
10246 if (IS_PTR (type) && !IS_FUNC (type->next))
10247 p_type = DCL_TYPE (type);
10250 /* we have to go by the storage class */
10251 p_type = PTR_TYPE (SPEC_OCLS (etype));
10254 /* special case when cast remat */
10255 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10256 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10258 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10259 type = operandType (left);
10260 p_type = DCL_TYPE (type);
10262 /* now that we have the pointer type we assign
10263 the pointer values */
10269 genNearPointerGet (left, result, ic, pi, ifx);
10273 genPagedPointerGet (left, result, ic, pi, ifx);
10277 genFarPointerGet (left, result, ic, pi, ifx);
10281 genCodePointerGet (left, result, ic, pi, ifx);
10285 genGenPointerGet (left, result, ic, pi, ifx);
10291 /*-----------------------------------------------------------------*/
10292 /* genPackBits - generates code for packed bit storage */
10293 /*-----------------------------------------------------------------*/
10295 genPackBits (sym_link * etype,
10297 char *rname, int p_type)
10299 int offset = 0; /* source byte offset */
10300 int rlen = 0; /* remaining bitfield length */
10301 int blen; /* bitfield length */
10302 int bstr; /* bitfield starting bit within byte */
10303 int litval; /* source literal value (if AOP_LIT) */
10304 unsigned char mask; /* bitmask within current byte */
10306 D(emitcode ("; genPackBits",""));
10308 blen = SPEC_BLEN (etype);
10309 bstr = SPEC_BSTR (etype);
10311 /* If the bitfield length is less than a byte */
10314 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10315 (unsigned char) (0xFF >> (8 - bstr)));
10317 if (AOP_TYPE (right) == AOP_LIT)
10319 /* Case with a bitfield length <8 and literal source
10321 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10323 litval &= (~mask) & 0xff;
10324 emitPtrByteGet (rname, p_type, FALSE);
10325 if ((mask|litval)!=0xff)
10326 emitcode ("anl","a,#0x%02x", mask);
10328 emitcode ("orl","a,#0x%02x", litval);
10332 if ((blen==1) && (p_type!=GPOINTER))
10334 /* Case with a bitfield length == 1 and no generic pointer
10336 if (AOP_TYPE (right) == AOP_CRY)
10337 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10340 MOVA (aopGet (right, 0, FALSE, FALSE));
10341 emitcode ("rrc","a");
10343 emitPtrByteGet (rname, p_type, FALSE);
10344 emitcode ("mov","acc.%d,c",bstr);
10349 /* Case with a bitfield length < 8 and arbitrary source
10351 MOVA (aopGet (right, 0, FALSE, FALSE));
10352 /* shift and mask source value */
10354 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10356 pushedB = pushB ();
10357 /* transfer A to B and get next byte */
10358 emitPtrByteGet (rname, p_type, TRUE);
10360 emitcode ("anl", "a,#0x%02x", mask);
10361 emitcode ("orl", "a,b");
10362 if (p_type == GPOINTER)
10363 emitcode ("pop", "b");
10369 emitPtrByteSet (rname, p_type, "a");
10373 /* Bit length is greater than 7 bits. In this case, copy */
10374 /* all except the partial byte at the end */
10375 for (rlen=blen;rlen>=8;rlen-=8)
10377 emitPtrByteSet (rname, p_type,
10378 aopGet (right, offset++, FALSE, TRUE) );
10380 emitcode ("inc", "%s", rname);
10383 /* If there was a partial byte at the end */
10386 mask = (((unsigned char) -1 << rlen) & 0xff);
10388 if (AOP_TYPE (right) == AOP_LIT)
10390 /* Case with partial byte and literal source
10392 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10393 litval >>= (blen-rlen);
10394 litval &= (~mask) & 0xff;
10395 emitPtrByteGet (rname, p_type, FALSE);
10396 if ((mask|litval)!=0xff)
10397 emitcode ("anl","a,#0x%02x", mask);
10399 emitcode ("orl","a,#0x%02x", litval);
10404 /* Case with partial byte and arbitrary source
10406 MOVA (aopGet (right, offset++, FALSE, FALSE));
10407 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10409 pushedB = pushB ();
10410 /* transfer A to B and get next byte */
10411 emitPtrByteGet (rname, p_type, TRUE);
10413 emitcode ("anl", "a,#0x%02x", mask);
10414 emitcode ("orl", "a,b");
10415 if (p_type == GPOINTER)
10416 emitcode ("pop", "b");
10420 emitPtrByteSet (rname, p_type, "a");
10425 /*-----------------------------------------------------------------*/
10426 /* genDataPointerSet - remat pointer to data space */
10427 /*-----------------------------------------------------------------*/
10429 genDataPointerSet (operand * right,
10433 int size, offset = 0;
10434 char *l, buffer[256];
10436 D (emitcode (";", "genDataPointerSet"));
10438 aopOp (right, ic, FALSE);
10440 l = aopGet (result, 0, FALSE, TRUE);
10442 size = AOP_SIZE (right);
10446 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10448 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10449 emitcode ("mov", "%s,%s", buffer,
10450 aopGet (right, offset++, FALSE, FALSE));
10453 freeAsmop (result, NULL, ic, TRUE);
10454 freeAsmop (right, NULL, ic, TRUE);
10457 /*-----------------------------------------------------------------*/
10458 /* genNearPointerSet - emitcode for near pointer put */
10459 /*-----------------------------------------------------------------*/
10461 genNearPointerSet (operand * right,
10469 sym_link *retype, *letype;
10470 sym_link *ptype = operandType (result);
10472 D (emitcode (";", "genNearPointerSet"));
10474 retype = getSpec (operandType (right));
10475 letype = getSpec (ptype);
10477 aopOp (result, ic, FALSE);
10479 /* if the result is rematerializable &
10480 in data space & not a bit variable */
10481 if (AOP_TYPE (result) == AOP_IMMD &&
10482 DCL_TYPE (ptype) == POINTER &&
10483 !IS_BITVAR (retype) &&
10484 !IS_BITVAR (letype))
10486 genDataPointerSet (right, result, ic);
10490 /* if the value is already in a pointer register
10491 then don't need anything more */
10492 if (!AOP_INPREG (AOP (result)))
10495 //AOP_TYPE (result) == AOP_STK
10496 IS_AOP_PREG(result)
10499 // Aha, it is a pointer, just in disguise.
10500 rname = aopGet (result, 0, FALSE, FALSE);
10503 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10504 __FILE__, __LINE__);
10509 emitcode ("mov", "a%s,%s", rname + 1, rname);
10510 rname++; // skip the '@'.
10515 /* otherwise get a free pointer register */
10516 aop = newAsmop (0);
10517 preg = getFreePtr (ic, &aop, FALSE);
10518 emitcode ("mov", "%s,%s",
10520 aopGet (result, 0, FALSE, TRUE));
10521 rname = preg->name;
10526 rname = aopGet (result, 0, FALSE, FALSE);
10529 aopOp (right, ic, FALSE);
10531 /* if bitfield then unpack the bits */
10532 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10533 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10536 /* we can just get the values */
10537 int size = AOP_SIZE (right);
10542 l = aopGet (right, offset, FALSE, TRUE);
10543 if ((*l == '@') || (strcmp (l, "acc") == 0))
10546 emitcode ("mov", "@%s,a", rname);
10549 emitcode ("mov", "@%s,%s", rname, l);
10551 emitcode ("inc", "%s", rname);
10556 /* now some housekeeping stuff */
10557 if (aop) /* we had to allocate for this iCode */
10560 aopPut (result, rname, 0);
10561 freeAsmop (NULL, aop, ic, TRUE);
10565 /* we did not allocate which means left
10566 already in a pointer register, then
10567 if size > 0 && this could be used again
10568 we have to point it back to where it
10570 if ((AOP_SIZE (right) > 1 &&
10571 !OP_SYMBOL (result)->remat &&
10572 (OP_SYMBOL (result)->liveTo > ic->seq ||
10576 int size = AOP_SIZE (right) - 1;
10578 emitcode ("dec", "%s", rname);
10583 if (pi) pi->generated = 1;
10584 freeAsmop (result, NULL, ic, TRUE);
10585 freeAsmop (right, NULL, ic, TRUE);
10588 /*-----------------------------------------------------------------*/
10589 /* genPagedPointerSet - emitcode for Paged pointer put */
10590 /*-----------------------------------------------------------------*/
10592 genPagedPointerSet (operand * right,
10600 sym_link *retype, *letype;
10602 D (emitcode (";", "genPagedPointerSet"));
10604 retype = getSpec (operandType (right));
10605 letype = getSpec (operandType (result));
10607 aopOp (result, ic, FALSE);
10609 /* if the value is already in a pointer register
10610 then don't need anything more */
10611 if (!AOP_INPREG (AOP (result)))
10613 /* otherwise get a free pointer register */
10614 aop = newAsmop (0);
10615 preg = getFreePtr (ic, &aop, FALSE);
10616 emitcode ("mov", "%s,%s",
10618 aopGet (result, 0, FALSE, TRUE));
10619 rname = preg->name;
10622 rname = aopGet (result, 0, FALSE, FALSE);
10624 aopOp (right, ic, FALSE);
10626 /* if bitfield then unpack the bits */
10627 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10628 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10631 /* we have can just get the values */
10632 int size = AOP_SIZE (right);
10637 l = aopGet (right, offset, FALSE, TRUE);
10639 emitcode ("movx", "@%s,a", rname);
10642 emitcode ("inc", "%s", rname);
10648 /* now some housekeeping stuff */
10649 if (aop) /* we had to allocate for this iCode */
10652 aopPut (result, rname, 0);
10653 freeAsmop (NULL, aop, ic, TRUE);
10657 /* we did not allocate which means left
10658 already in a pointer register, then
10659 if size > 0 && this could be used again
10660 we have to point it back to where it
10662 if (AOP_SIZE (right) > 1 &&
10663 !OP_SYMBOL (result)->remat &&
10664 (OP_SYMBOL (result)->liveTo > ic->seq ||
10667 int size = AOP_SIZE (right) - 1;
10669 emitcode ("dec", "%s", rname);
10674 if (pi) pi->generated = 1;
10675 freeAsmop (result, NULL, ic, TRUE);
10676 freeAsmop (right, NULL, ic, TRUE);
10679 /*-----------------------------------------------------------------*/
10680 /* genFarPointerSet - set value from far space */
10681 /*-----------------------------------------------------------------*/
10683 genFarPointerSet (operand * right,
10684 operand * result, iCode * ic, iCode * pi)
10687 sym_link *retype = getSpec (operandType (right));
10688 sym_link *letype = getSpec (operandType (result));
10690 D(emitcode ("; genFarPointerSet",""));
10692 aopOp (result, ic, FALSE);
10693 loadDptrFromOperand (result, FALSE);
10695 /* so dptr now contains the address */
10696 aopOp (right, ic, FALSE);
10698 /* if bit then unpack */
10699 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10700 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10703 size = AOP_SIZE (right);
10708 char *l = aopGet (right, offset++, FALSE, FALSE);
10710 emitcode ("movx", "@dptr,a");
10712 emitcode ("inc", "dptr");
10715 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10716 aopPut (result, "dpl", 0);
10717 aopPut (result, "dph", 1);
10720 freeAsmop (result, NULL, ic, TRUE);
10721 freeAsmop (right, NULL, ic, TRUE);
10724 /*-----------------------------------------------------------------*/
10725 /* genGenPointerSet - set value from generic pointer space */
10726 /*-----------------------------------------------------------------*/
10728 genGenPointerSet (operand * right,
10729 operand * result, iCode * ic, iCode * pi)
10732 sym_link *retype = getSpec (operandType (right));
10733 sym_link *letype = getSpec (operandType (result));
10735 D (emitcode (";", "genGenPointerSet"));
10737 aopOp (result, ic, FALSE);
10738 loadDptrFromOperand (result, TRUE);
10740 /* so dptr now contains the address */
10741 aopOp (right, ic, FALSE);
10743 /* if bit then unpack */
10744 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10746 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10750 size = AOP_SIZE (right);
10755 char *l = aopGet (right, offset++, FALSE, FALSE);
10757 emitcode ("lcall", "__gptrput");
10759 emitcode ("inc", "dptr");
10763 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10764 aopPut (result, "dpl", 0);
10765 aopPut (result, "dph", 1);
10768 freeAsmop (result, NULL, ic, TRUE);
10769 freeAsmop (right, NULL, ic, TRUE);
10772 /*-----------------------------------------------------------------*/
10773 /* genPointerSet - stores the value into a pointer location */
10774 /*-----------------------------------------------------------------*/
10776 genPointerSet (iCode * ic, iCode *pi)
10778 operand *right, *result;
10779 sym_link *type, *etype;
10782 D (emitcode (";", "genPointerSet"));
10784 right = IC_RIGHT (ic);
10785 result = IC_RESULT (ic);
10787 /* depending on the type of pointer we need to
10788 move it to the correct pointer register */
10789 type = operandType (result);
10790 etype = getSpec (type);
10791 /* if left is of type of pointer then it is simple */
10792 if (IS_PTR (type) && !IS_FUNC (type->next))
10794 p_type = DCL_TYPE (type);
10798 /* we have to go by the storage class */
10799 p_type = PTR_TYPE (SPEC_OCLS (etype));
10802 /* special case when cast remat */
10803 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10804 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10805 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10806 type = operandType (result);
10807 p_type = DCL_TYPE (type);
10810 /* now that we have the pointer type we assign
10811 the pointer values */
10817 genNearPointerSet (right, result, ic, pi);
10821 genPagedPointerSet (right, result, ic, pi);
10825 genFarPointerSet (right, result, ic, pi);
10829 genGenPointerSet (right, result, ic, pi);
10833 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10834 "genPointerSet: illegal pointer type");
10838 /*-----------------------------------------------------------------*/
10839 /* genIfx - generate code for Ifx statement */
10840 /*-----------------------------------------------------------------*/
10842 genIfx (iCode * ic, iCode * popIc)
10844 operand *cond = IC_COND (ic);
10848 D (emitcode (";", "genIfx"));
10850 aopOp (cond, ic, FALSE);
10852 /* get the value into acc */
10853 if (AOP_TYPE (cond) != AOP_CRY)
10860 if (AOP(cond)->aopu.aop_dir)
10861 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10864 /* the result is now in the accumulator or a directly addressable bit */
10865 freeAsmop (cond, NULL, ic, TRUE);
10867 /* if there was something to be popped then do it */
10871 /* if the condition is a bit variable */
10873 genIfxJump(ic, dup, NULL, NULL, NULL);
10874 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10875 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10876 else if (isbit && !IS_ITEMP (cond))
10877 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10879 genIfxJump (ic, "a", NULL, NULL, NULL);
10884 /*-----------------------------------------------------------------*/
10885 /* genAddrOf - generates code for address of */
10886 /*-----------------------------------------------------------------*/
10888 genAddrOf (iCode * ic)
10890 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10893 D (emitcode (";", "genAddrOf"));
10895 aopOp (IC_RESULT (ic), ic, FALSE);
10897 /* if the operand is on the stack then we
10898 need to get the stack offset of this
10902 /* if it has an offset then we need to compute it */
10905 int stack_offset = ((sym->stack < 0) ?
10906 ((char) (sym->stack - _G.nRegsSaved)) :
10907 ((char) sym->stack)) & 0xff;
10908 if ((abs(stack_offset) == 1) &&
10909 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10910 !isOperandVolatile (IC_RESULT (ic), FALSE))
10912 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10913 if (stack_offset > 0)
10914 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10916 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10920 emitcode ("mov", "a,%s", SYM_BP (sym));
10921 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10922 aopPut (IC_RESULT (ic), "a", 0);
10927 /* we can just move _bp */
10928 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10930 /* fill the result with zero */
10931 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10936 aopPut (IC_RESULT (ic), zero, offset++);
10941 /* object not on stack then we need the name */
10942 size = AOP_SIZE (IC_RESULT (ic));
10947 char s[SDCC_NAME_MAX];
10949 sprintf (s, "#(%s >> %d)",
10953 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10954 aopPut (IC_RESULT (ic), s, offset++);
10958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10962 /*-----------------------------------------------------------------*/
10963 /* genFarFarAssign - assignment when both are in far space */
10964 /*-----------------------------------------------------------------*/
10966 genFarFarAssign (operand * result, operand * right, iCode * ic)
10968 int size = AOP_SIZE (right);
10972 D (emitcode (";", "genFarFarAssign"));
10974 /* first push the right side on to the stack */
10977 l = aopGet (right, offset++, FALSE, FALSE);
10979 emitcode ("push", "acc");
10982 freeAsmop (right, NULL, ic, FALSE);
10983 /* now assign DPTR to result */
10984 aopOp (result, ic, FALSE);
10985 size = AOP_SIZE (result);
10988 emitcode ("pop", "acc");
10989 aopPut (result, "a", --offset);
10991 freeAsmop (result, NULL, ic, FALSE);
10994 /*-----------------------------------------------------------------*/
10995 /* genAssign - generate code for assignment */
10996 /*-----------------------------------------------------------------*/
10998 genAssign (iCode * ic)
11000 operand *result, *right;
11002 unsigned long lit = 0L;
11004 D (emitcode (";", "genAssign"));
11006 result = IC_RESULT (ic);
11007 right = IC_RIGHT (ic);
11009 /* if they are the same */
11010 if (operandsEqu (result, right) &&
11011 !isOperandVolatile (result, FALSE) &&
11012 !isOperandVolatile (right, FALSE))
11015 aopOp (right, ic, FALSE);
11017 /* special case both in far space */
11018 if (AOP_TYPE (right) == AOP_DPTR &&
11019 IS_TRUE_SYMOP (result) &&
11020 isOperandInFarSpace (result))
11022 genFarFarAssign (result, right, ic);
11026 aopOp (result, ic, TRUE);
11028 /* if they are the same registers */
11029 if (sameRegs (AOP (right), AOP (result)) &&
11030 !isOperandVolatile (result, FALSE) &&
11031 !isOperandVolatile (right, FALSE))
11034 /* if the result is a bit */
11035 if (AOP_TYPE (result) == AOP_CRY)
11037 /* if the right size is a literal then
11038 we know what the value is */
11039 if (AOP_TYPE (right) == AOP_LIT)
11041 if (((int) operandLitValue (right)))
11042 aopPut (result, one, 0);
11044 aopPut (result, zero, 0);
11048 /* the right is also a bit variable */
11049 if (AOP_TYPE (right) == AOP_CRY)
11051 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11052 aopPut (result, "c", 0);
11056 /* we need to or */
11058 aopPut (result, "a", 0);
11062 /* bit variables done */
11064 size = AOP_SIZE (result);
11066 if (AOP_TYPE (right) == AOP_LIT)
11067 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11070 (AOP_TYPE (result) != AOP_REG) &&
11071 (AOP_TYPE (right) == AOP_LIT) &&
11072 !IS_FLOAT (operandType (right)) &&
11075 while ((size) && (lit))
11078 aopGet (right, offset, FALSE, FALSE),
11084 /* And now fill the rest with zeros. */
11087 emitcode ("clr", "a");
11091 aopPut (result, "a", offset);
11100 aopGet (right, offset, FALSE, FALSE),
11107 freeAsmop (result, NULL, ic, TRUE);
11108 freeAsmop (right, NULL, ic, TRUE);
11111 /*-----------------------------------------------------------------*/
11112 /* genJumpTab - generates code for jump table */
11113 /*-----------------------------------------------------------------*/
11115 genJumpTab (iCode * ic)
11117 symbol *jtab,*jtablo,*jtabhi;
11119 unsigned int count;
11121 D (emitcode (";", "genJumpTab"));
11123 count = elementsInSet( IC_JTLABELS (ic) );
11127 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11128 if the switch argument is in a register.
11129 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11130 /* Peephole may not convert ljmp to sjmp or ret
11131 labelIsReturnOnly & labelInRange must check
11132 currPl->ic->op != JUMPTABLE */
11133 aopOp (IC_JTCOND (ic), ic, FALSE);
11134 /* get the condition into accumulator */
11135 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11137 /* multiply by three */
11138 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11140 emitcode ("mov", "b,#3");
11141 emitcode ("mul", "ab");
11145 emitcode ("add", "a,acc");
11146 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11148 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11150 jtab = newiTempLabel (NULL);
11151 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11152 emitcode ("jmp", "@a+dptr");
11154 /* now generate the jump labels */
11155 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11156 jtab = setNextItem (IC_JTLABELS (ic)))
11157 emitcode ("ljmp", "%05d$", jtab->key + 100);
11161 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11162 if the switch argument is in a register.
11163 For n>6 this algorithm may be more compact */
11164 jtablo = newiTempLabel (NULL);
11165 jtabhi = newiTempLabel (NULL);
11167 /* get the condition into accumulator.
11168 Using b as temporary storage, if register push/pop is needed */
11169 aopOp (IC_JTCOND (ic), ic, FALSE);
11170 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11171 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11172 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11174 // (MB) what if B is in use???
11175 wassertl(!BINUSE, "B was in use");
11176 emitcode ("mov", "b,%s", l);
11179 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11183 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11184 emitcode ("movc", "a,@a+pc");
11185 emitcode ("push", "acc");
11188 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11189 emitcode ("movc", "a,@a+pc");
11190 emitcode ("push", "acc");
11194 /* this scales up to n<=255, but needs two more bytes
11195 and changes dptr */
11196 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11197 emitcode ("movc", "a,@a+dptr");
11198 emitcode ("push", "acc");
11201 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11202 emitcode ("movc", "a,@a+dptr");
11203 emitcode ("push", "acc");
11206 emitcode ("ret", "");
11208 /* now generate jump table, LSB */
11209 emitLabel (jtablo);
11210 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11211 jtab = setNextItem (IC_JTLABELS (ic)))
11212 emitcode (".db", "%05d$", jtab->key + 100);
11214 /* now generate jump table, MSB */
11215 emitLabel (jtabhi);
11216 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11217 jtab = setNextItem (IC_JTLABELS (ic)))
11218 emitcode (".db", "%05d$>>8", jtab->key + 100);
11222 /*-----------------------------------------------------------------*/
11223 /* genCast - gen code for casting */
11224 /*-----------------------------------------------------------------*/
11226 genCast (iCode * ic)
11228 operand *result = IC_RESULT (ic);
11229 sym_link *ctype = operandType (IC_LEFT (ic));
11230 sym_link *rtype = operandType (IC_RIGHT (ic));
11231 operand *right = IC_RIGHT (ic);
11234 D (emitcode (";", "genCast"));
11236 /* if they are equivalent then do nothing */
11237 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11240 aopOp (right, ic, FALSE);
11241 aopOp (result, ic, FALSE);
11243 /* if the result is a bit (and not a bitfield) */
11244 if (IS_BIT (OP_SYMBOL (result)->type))
11246 /* if the right size is a literal then
11247 we know what the value is */
11248 if (AOP_TYPE (right) == AOP_LIT)
11250 if (((int) operandLitValue (right)))
11251 aopPut (result, one, 0);
11253 aopPut (result, zero, 0);
11258 /* the right is also a bit variable */
11259 if (AOP_TYPE (right) == AOP_CRY)
11261 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11262 aopPut (result, "c", 0);
11266 /* we need to or */
11268 aopPut (result, "a", 0);
11272 /* if they are the same size : or less */
11273 if (AOP_SIZE (result) <= AOP_SIZE (right))
11276 /* if they are in the same place */
11277 if (sameRegs (AOP (right), AOP (result)))
11280 /* if they in different places then copy */
11281 size = AOP_SIZE (result);
11286 aopGet (right, offset, FALSE, FALSE),
11293 /* if the result is of type pointer */
11294 if (IS_PTR (ctype))
11298 sym_link *type = operandType (right);
11299 sym_link *etype = getSpec (type);
11301 /* pointer to generic pointer */
11302 if (IS_GENPTR (ctype))
11306 p_type = DCL_TYPE (type);
11310 if (SPEC_SCLS(etype)==S_REGISTER) {
11311 // let's assume it is a generic pointer
11314 /* we have to go by the storage class */
11315 p_type = PTR_TYPE (SPEC_OCLS (etype));
11319 /* the first two bytes are known */
11320 size = GPTRSIZE - 1;
11325 aopGet (right, offset, FALSE, FALSE),
11329 /* the last byte depending on type */
11331 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11336 // pointerTypeToGPByte will have bitched.
11340 sprintf(gpValStr, "#0x%x", gpVal);
11341 aopPut (result, gpValStr, GPTRSIZE - 1);
11346 /* just copy the pointers */
11347 size = AOP_SIZE (result);
11352 aopGet (right, offset, FALSE, FALSE),
11359 /* so we now know that the size of destination is greater
11360 than the size of the source */
11361 /* we move to result for the size of source */
11362 size = AOP_SIZE (right);
11367 aopGet (right, offset, FALSE, FALSE),
11372 /* now depending on the sign of the source && destination */
11373 size = AOP_SIZE (result) - AOP_SIZE (right);
11374 /* if unsigned or not an integral type */
11375 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11378 aopPut (result, zero, offset++);
11382 /* we need to extend the sign :{ */
11383 char *l = aopGet (right, AOP_SIZE (right) - 1,
11386 emitcode ("rlc", "a");
11387 emitcode ("subb", "a,acc");
11389 aopPut (result, "a", offset++);
11392 /* we are done hurray !!!! */
11395 freeAsmop (result, NULL, ic, TRUE);
11396 freeAsmop (right, NULL, ic, TRUE);
11399 /*-----------------------------------------------------------------*/
11400 /* genDjnz - generate decrement & jump if not zero instrucion */
11401 /*-----------------------------------------------------------------*/
11403 genDjnz (iCode * ic, iCode * ifx)
11405 symbol *lbl, *lbl1;
11409 /* if the if condition has a false label
11410 then we cannot save */
11411 if (IC_FALSE (ifx))
11414 /* if the minus is not of the form a = a - 1 */
11415 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11416 !IS_OP_LITERAL (IC_RIGHT (ic)))
11419 if (operandLitValue (IC_RIGHT (ic)) != 1)
11422 /* if the size of this greater than one then no
11424 if (getSize (operandType (IC_RESULT (ic))) > 1)
11427 /* otherwise we can save BIG */
11429 D (emitcode (";", "genDjnz"));
11431 lbl = newiTempLabel (NULL);
11432 lbl1 = newiTempLabel (NULL);
11434 aopOp (IC_RESULT (ic), ic, FALSE);
11436 if (AOP_NEEDSACC(IC_RESULT(ic)))
11438 /* If the result is accessed indirectly via
11439 * the accumulator, we must explicitly write
11440 * it back after the decrement.
11442 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11444 if (strcmp(rByte, "a"))
11446 /* Something is hopelessly wrong */
11447 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11448 __FILE__, __LINE__);
11449 /* We can just give up; the generated code will be inefficient,
11450 * but what the hey.
11452 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11455 emitcode ("dec", "%s", rByte);
11456 aopPut (IC_RESULT (ic), rByte, 0);
11457 emitcode ("jnz", "%05d$", lbl->key + 100);
11459 else if (IS_AOP_PREG (IC_RESULT (ic)))
11461 emitcode ("dec", "%s",
11462 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11463 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11464 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11465 ifx->generated = 1;
11466 emitcode ("jnz", "%05d$", lbl->key + 100);
11470 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11473 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11475 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11478 if (!ifx->generated)
11479 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11480 ifx->generated = 1;
11484 /*-----------------------------------------------------------------*/
11485 /* genReceive - generate code for a receive iCode */
11486 /*-----------------------------------------------------------------*/
11488 genReceive (iCode * ic)
11490 int size = getSize (operandType (IC_RESULT (ic)));
11493 D (emitcode (";", "genReceive"));
11495 if (ic->argreg == 1)
11496 { /* first parameter */
11497 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11498 isOperandInPagedSpace (IC_RESULT (ic))) &&
11499 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11500 IS_TRUE_SYMOP (IC_RESULT (ic))))
11503 int receivingA = 0;
11506 for (offset = 0; offset<size; offset++)
11507 if (!strcmp (fReturn[offset], "a"))
11512 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11514 for (offset = size-1; offset>0; offset--)
11515 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11516 emitcode("mov","a,%s", fReturn[0]);
11518 aopOp (IC_RESULT (ic), ic, FALSE);
11520 aopPut (IC_RESULT (ic), "a", offset);
11521 for (offset = 1; offset<size; offset++)
11522 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11528 if (getTempRegs(tempRegs, size, ic))
11530 for (offset = 0; offset<size; offset++)
11531 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11532 aopOp (IC_RESULT (ic), ic, FALSE);
11533 for (offset = 0; offset<size; offset++)
11534 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11539 offset = fReturnSizeMCS51 - size;
11542 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11543 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11546 aopOp (IC_RESULT (ic), ic, FALSE);
11547 size = AOP_SIZE (IC_RESULT (ic));
11551 emitcode ("pop", "acc");
11552 aopPut (IC_RESULT (ic), "a", offset++);
11558 aopOp (IC_RESULT (ic), ic, FALSE);
11560 assignResultValue (IC_RESULT (ic), NULL);
11563 else if (ic->argreg > 12)
11564 { /* bit parameters */
11565 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11567 aopOp (IC_RESULT (ic), ic, FALSE);
11568 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11569 outBitC(IC_RESULT (ic));
11573 { /* other parameters */
11575 aopOp (IC_RESULT (ic), ic, FALSE);
11576 rb1off = ic->argreg;
11579 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11584 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11587 /*-----------------------------------------------------------------*/
11588 /* genDummyRead - generate code for dummy read of volatiles */
11589 /*-----------------------------------------------------------------*/
11591 genDummyRead (iCode * ic)
11596 D (emitcode(";", "genDummyRead"));
11598 op = IC_RIGHT (ic);
11599 if (op && IS_SYMOP (op))
11601 aopOp (op, ic, FALSE);
11603 /* if the result is a bit */
11604 if (AOP_TYPE (op) == AOP_CRY)
11605 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11608 /* bit variables done */
11610 size = AOP_SIZE (op);
11614 MOVA (aopGet (op, offset, FALSE, FALSE));
11619 freeAsmop (op, NULL, ic, TRUE);
11623 if (op && IS_SYMOP (op))
11625 aopOp (op, ic, FALSE);
11627 /* if the result is a bit */
11628 if (AOP_TYPE (op) == AOP_CRY)
11629 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11632 /* bit variables done */
11634 size = AOP_SIZE (op);
11638 MOVA (aopGet (op, offset, FALSE, FALSE));
11643 freeAsmop (op, NULL, ic, TRUE);
11647 /*-----------------------------------------------------------------*/
11648 /* genCritical - generate code for start of a critical sequence */
11649 /*-----------------------------------------------------------------*/
11651 genCritical (iCode *ic)
11653 symbol *tlbl = newiTempLabel (NULL);
11655 D (emitcode(";", "genCritical"));
11657 if (IC_RESULT (ic))
11659 aopOp (IC_RESULT (ic), ic, TRUE);
11660 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11661 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11662 aopPut (IC_RESULT (ic), zero, 0);
11664 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11668 emitcode ("setb", "c");
11669 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11670 emitcode ("clr", "c");
11672 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11676 /*-----------------------------------------------------------------*/
11677 /* genEndCritical - generate code for end of a critical sequence */
11678 /*-----------------------------------------------------------------*/
11680 genEndCritical (iCode *ic)
11682 D(emitcode("; genEndCritical",""));
11686 aopOp (IC_RIGHT (ic), ic, FALSE);
11687 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11689 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11690 emitcode ("mov", "ea,c");
11694 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11695 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11696 emitcode ("rrc", "a");
11697 emitcode ("mov", "ea,c");
11699 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11703 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11704 emitcode ("mov", "ea,c");
11708 /*-----------------------------------------------------------------*/
11709 /* gen51Code - generate code for 8051 based controllers */
11710 /*-----------------------------------------------------------------*/
11712 gen51Code (iCode * lic)
11716 /* int cseq = 0; */
11718 _G.currentFunc = NULL;
11719 lineHead = lineCurr = NULL;
11721 /* print the allocation information */
11722 if (allocInfo && currFunc)
11723 printAllocInfo (currFunc, codeOutBuf);
11724 /* if debug information required */
11725 if (options.debug && currFunc)
11727 debugFile->writeFunction (currFunc, lic);
11729 /* stack pointer name */
11730 if (options.useXstack)
11736 for (ic = lic; ic; ic = ic->next)
11738 _G.current_iCode = ic;
11740 if (ic->lineno && cln != ic->lineno)
11744 debugFile->writeCLine (ic);
11746 if (!options.noCcodeInAsm) {
11747 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11748 printCLine(ic->filename, ic->lineno));
11753 if (ic->seqPoint && ic->seqPoint != cseq)
11755 emitcode ("", "; sequence point %d", ic->seqPoint);
11756 cseq = ic->seqPoint;
11759 if (options.iCodeInAsm) {
11760 char regsInUse[80];
11765 for (i=0; i<8; i++) {
11766 sprintf (®sInUse[i],
11767 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11770 strcpy (regsInUse, "--------");
11771 for (i=0; i < 8; i++) {
11772 if (bitVectBitValue (ic->rMask, i))
11774 int offset = regs8051[i].offset;
11775 regsInUse[offset] = offset + '0'; /* show rMask */
11779 iLine = printILine(ic);
11780 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11783 /* if the result is marked as
11784 spilt and rematerializable or code for
11785 this has already been generated then
11787 if (resultRemat (ic) || ic->generated)
11790 /* depending on the operation */
11810 /* IPOP happens only when trying to restore a
11811 spilt live range, if there is an ifx statement
11812 following this pop then the if statement might
11813 be using some of the registers being popped which
11814 would destory the contents of the register so
11815 we need to check for this condition and handle it */
11817 ic->next->op == IFX &&
11818 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11819 genIfx (ic->next, ic);
11837 genEndFunction (ic);
11857 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11874 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11878 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11885 /* note these two are xlated by algebraic equivalence
11886 in decorateType() in SDCCast.c */
11887 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11888 "got '>=' or '<=' shouldn't have come here");
11892 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11904 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11908 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11912 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11948 genRightShift (ic);
11951 case GET_VALUE_AT_ADDRESS:
11953 hasInc (IC_LEFT (ic), ic,
11954 getSize (operandType (IC_RESULT (ic)))),
11955 ifxForOp (IC_RESULT (ic), ic) );
11959 if (POINTER_SET (ic))
11961 hasInc (IC_RESULT (ic), ic,
11962 getSize (operandType (IC_RIGHT (ic)))));
11988 addSet (&_G.sendSet, ic);
11991 case DUMMY_READ_VOLATILE:
12000 genEndCritical (ic);
12012 _G.current_iCode = NULL;
12014 /* now we are ready to call the
12015 peep hole optimizer */
12016 if (!options.nopeep)
12017 peepHole (&lineHead);
12019 /* now do the actual printing */
12020 printLine (lineHead, codeOutBuf);