1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
122 static void saveRBank (int, iCode *, bool);
124 #define RESULTONSTACK(x) \
125 (IC_RESULT(x) && IC_RESULT(x)->aop && \
126 IC_RESULT(x)->aop->type == AOP_STK )
128 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
129 #define MOVB(x) movb(x)
131 #define CLRC emitcode("clr","c")
132 #define SETC emitcode("setb","c")
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139 0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142 0x07, 0x03, 0x01, 0x00};
149 /*-----------------------------------------------------------------*/
150 /* emitcode - writes the code into a file : for now it is simple */
151 /*-----------------------------------------------------------------*/
153 emitcode (const char *inst, const char *fmt,...)
157 const char *lbp, *lb;
159 dbuf_init (&dbuf, INITIAL_INLINEASM);
165 dbuf_append_str (&dbuf, inst);
169 dbuf_append_char (&dbuf, '\t');
170 dbuf_tvprintf (&dbuf, fmt, ap);
175 dbuf_tvprintf (&dbuf, fmt, ap);
178 lbp = lb = dbuf_c_str(&dbuf);
180 while (isspace ((unsigned char)*lbp))
187 lineCurr = (lineCurr ?
188 connectLine (lineCurr, newLineNode (lb)) :
189 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
202 emitLabel (symbol *tlbl)
204 emitcode ("", "%05d$:", tlbl->key + 100);
205 lineCurr->isLabel = 1;
208 /*-----------------------------------------------------------------*/
209 /* mcs51_emitDebuggerSymbol - associate the current code location */
210 /* with a debugger symbol */
211 /*-----------------------------------------------------------------*/
213 mcs51_emitDebuggerSymbol (char * debugSym)
216 emitcode ("", "%s ==.", debugSym);
220 /*-----------------------------------------------------------------*/
221 /* mova - moves specified value into accumulator */
222 /*-----------------------------------------------------------------*/
226 /* do some early peephole optimization */
227 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
230 emitcode("mov", "a,%s", x);
233 /*-----------------------------------------------------------------*/
234 /* movb - moves specified value into register b */
235 /*-----------------------------------------------------------------*/
239 /* do some early peephole optimization */
240 if (!strncmp(x, "b", 2))
243 emitcode("mov","b,%s", x);
246 /*-----------------------------------------------------------------*/
247 /* movc - moves specified value into the carry */
248 /*-----------------------------------------------------------------*/
252 if (!strcmp (s, zero))
254 else if (!strcmp (s, one))
256 else if (strcmp (s, "c"))
257 {/* it's not in carry already */
259 /* set C, if a >= 1 */
260 emitcode ("add", "a,#0xff");
264 /*-----------------------------------------------------------------*/
265 /* pushB - saves register B if necessary */
266 /*-----------------------------------------------------------------*/
270 bool pushedB = FALSE;
274 emitcode ("push", "b");
275 // printf("B was in use !\n");
285 /*-----------------------------------------------------------------*/
286 /* popB - restores value of register B if necessary */
287 /*-----------------------------------------------------------------*/
293 emitcode ("pop", "b");
301 /*-----------------------------------------------------------------*/
302 /* pushReg - saves register */
303 /*-----------------------------------------------------------------*/
305 pushReg (int index, bool bits_pushed)
307 regs * reg = REG_WITH_INDEX (index);
308 if (reg->type == REG_BIT)
311 emitcode ("push", "%s", reg->base);
315 emitcode ("push", "%s", reg->dname);
319 /*-----------------------------------------------------------------*/
320 /* popReg - restores register */
321 /*-----------------------------------------------------------------*/
323 popReg (int index, bool bits_popped)
325 regs * reg = REG_WITH_INDEX (index);
326 if (reg->type == REG_BIT)
329 emitcode ("pop", "%s", reg->base);
333 emitcode ("pop", "%s", reg->dname);
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
339 /*-----------------------------------------------------------------*/
341 getFreePtr (iCode * ic, asmop ** aopp, bool result)
346 /* the logic: if r0 & r1 used in the instruction
347 then we are in trouble otherwise */
349 /* first check if r0 & r1 are used by this
350 instruction, in which case we are in trouble */
351 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
352 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
357 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
358 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
360 /* if no usage of r0 then return it */
363 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
364 (*aopp)->type = AOP_R0;
366 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
369 /* if no usage of r1 then return it */
372 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
373 (*aopp)->type = AOP_R1;
375 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
378 /* now we know they both have usage */
379 /* if r0 not used in this instruction */
382 /* push it if not already pushed */
385 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
388 else if (!_G.r0Pushed)
390 emitcode ("push", "%s",
391 REG_WITH_INDEX (R0_IDX)->dname);
395 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
396 (*aopp)->type = AOP_R0;
398 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
401 /* if r1 not used then */
405 /* push it if not already pushed */
408 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
411 else if (!_G.r1Pushed)
413 emitcode ("push", "%s",
414 REG_WITH_INDEX (R1_IDX)->dname);
418 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
419 (*aopp)->type = AOP_R1;
420 return REG_WITH_INDEX (R1_IDX);
424 /* I said end of world, but not quite end of world yet */
425 /* if this is a result then we can push it on the stack */
428 (*aopp)->type = AOP_STK;
431 /* in the case that result AND left AND right needs a pointer reg
432 we can safely use the result's */
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
435 (*aopp)->type = AOP_R0;
436 return REG_WITH_INDEX (R0_IDX);
438 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
440 (*aopp)->type = AOP_R1;
441 return REG_WITH_INDEX (R1_IDX);
444 /* now this is REALLY the end of the world */
445 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
446 "getFreePtr should never reach here");
451 /*-----------------------------------------------------------------*/
452 /* getTempRegs - initialize an array of pointers to GPR registers */
453 /* that are not in use. Returns 1 if the requested */
454 /* number of registers were available, 0 otherwise. */
455 /*-----------------------------------------------------------------*/
457 getTempRegs(regs **tempRegs, int size, iCode *ic)
464 ic = _G.current_iCode;
470 freeRegs = newBitVect(8);
471 bitVectSetBit (freeRegs, R2_IDX);
472 bitVectSetBit (freeRegs, R3_IDX);
473 bitVectSetBit (freeRegs, R4_IDX);
474 bitVectSetBit (freeRegs, R5_IDX);
475 bitVectSetBit (freeRegs, R6_IDX);
476 bitVectSetBit (freeRegs, R7_IDX);
478 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
480 bitVect * newfreeRegs;
481 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
482 freeBitVect(freeRegs);
483 freeRegs = newfreeRegs;
485 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
488 for (i=0; i<freeRegs->size; i++)
490 if (bitVectBitValue(freeRegs,i))
491 tempRegs[offset++] = REG_WITH_INDEX(i);
494 freeBitVect(freeRegs);
499 freeBitVect(freeRegs);
504 /*-----------------------------------------------------------------*/
505 /* newAsmop - creates a new asmOp */
506 /*-----------------------------------------------------------------*/
508 newAsmop (short type)
512 aop = Safe_calloc (1, sizeof (asmop));
518 /*-----------------------------------------------------------------*/
519 /* pointerCode - returns the code for a pointer type */
520 /*-----------------------------------------------------------------*/
522 pointerCode (sym_link * etype)
525 return PTR_TYPE (SPEC_OCLS (etype));
529 /*-----------------------------------------------------------------*/
530 /* leftRightUseAcc - returns size of accumulator use by operands */
531 /*-----------------------------------------------------------------*/
533 leftRightUseAcc(iCode *ic)
542 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
543 "null iCode pointer");
550 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
553 size = getSize (OP_SYMBOL (op)->type);
558 else if (ic->op == JUMPTABLE)
561 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
564 size = getSize (OP_SYMBOL (op)->type);
572 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
575 size = getSize (OP_SYMBOL (op)->type);
580 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
583 size = getSize (OP_SYMBOL (op)->type);
595 /*-----------------------------------------------------------------*/
596 /* aopForSym - for a true symbol */
597 /*-----------------------------------------------------------------*/
599 aopForSym (iCode * ic, symbol * sym, bool result)
603 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
605 wassertl (ic != NULL, "Got a null iCode");
606 wassertl (sym != NULL, "Got a null symbol");
608 space = SPEC_OCLS (sym->etype);
610 /* if already has one */
613 sym->aop->allocated++;
617 /* assign depending on the storage class */
618 /* if it is on the stack or indirectly addressable */
619 /* space we need to assign either r0 or r1 to it */
620 if (sym->onStack || sym->iaccess)
622 sym->aop = aop = newAsmop (0);
623 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
624 aop->size = getSize (sym->type);
626 /* now assign the address of the variable to
627 the pointer register */
628 if (aop->type != AOP_STK)
632 signed char offset = ((sym->stack < 0) ?
633 ((signed char) (sym->stack - _G.nRegsSaved)) :
634 ((signed char) sym->stack)) & 0xff;
636 if ((abs(offset) <= 3) ||
637 (accuse && (abs(offset) <= 7)))
639 emitcode ("mov", "%s,%s",
640 aop->aopu.aop_ptr->name, SYM_BP (sym));
643 emitcode ("dec", aop->aopu.aop_ptr->name);
648 emitcode ("inc", aop->aopu.aop_ptr->name);
655 emitcode ("push", "acc");
656 emitcode ("mov", "a,%s", SYM_BP (sym));
657 emitcode ("add", "a,#0x%02x", offset & 0xff);
658 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
660 emitcode ("pop", "acc");
665 emitcode ("mov", "%s,#%s",
666 aop->aopu.aop_ptr->name,
669 aop->paged = space->paged;
672 aop->aopu.aop_stk = sym->stack;
676 /* if in bit space */
677 if (IN_BITSPACE (space))
679 sym->aop = aop = newAsmop (AOP_CRY);
680 aop->aopu.aop_dir = sym->rname;
681 aop->size = getSize (sym->type);
684 /* if it is in direct space */
685 if (IN_DIRSPACE (space))
687 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
688 //printTypeChainRaw(sym->type, NULL);
689 //printf("space = %s\n", space ? space->sname : "NULL");
690 sym->aop = aop = newAsmop (AOP_DIR);
691 aop->aopu.aop_dir = sym->rname;
692 aop->size = getSize (sym->type);
696 /* special case for a function */
697 if (IS_FUNC (sym->type))
699 sym->aop = aop = newAsmop (AOP_IMMD);
700 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
701 aop->size = getSize (sym->type);
705 /* only remaining is far space */
706 /* in which case DPTR gets the address */
707 sym->aop = aop = newAsmop (AOP_DPTR);
708 emitcode ("mov", "dptr,#%s", sym->rname);
709 aop->size = getSize (sym->type);
711 /* if it is in code space */
712 if (IN_CODESPACE (space))
718 /*-----------------------------------------------------------------*/
719 /* aopForRemat - rematerialzes an object */
720 /*-----------------------------------------------------------------*/
722 aopForRemat (symbol * sym)
724 iCode *ic = sym->rematiCode;
725 asmop *aop = newAsmop (AOP_IMMD);
732 val += (int) operandLitValue (IC_RIGHT (ic));
733 else if (ic->op == '-')
734 val -= (int) operandLitValue (IC_RIGHT (ic));
735 else if (IS_CAST_ICODE(ic)) {
736 sym_link *from_type = operandType(IC_RIGHT(ic));
737 aop->aopu.aop_immd.from_cast_remat = 1;
738 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
739 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
743 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
748 SNPRINTF (buffer, sizeof(buffer),
750 OP_SYMBOL (IC_LEFT (ic))->rname,
751 val >= 0 ? '+' : '-',
756 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
759 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
760 /* set immd2 field if required */
761 if (aop->aopu.aop_immd.from_cast_remat)
763 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
764 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
770 /*-----------------------------------------------------------------*/
771 /* regsInCommon - two operands have some registers in common */
772 /*-----------------------------------------------------------------*/
774 regsInCommon (operand * op1, operand * op2)
779 /* if they have registers in common */
780 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
783 sym1 = OP_SYMBOL (op1);
784 sym2 = OP_SYMBOL (op2);
786 if (sym1->nRegs == 0 || sym2->nRegs == 0)
789 for (i = 0; i < sym1->nRegs; i++)
795 for (j = 0; j < sym2->nRegs; j++)
800 if (sym2->regs[j] == sym1->regs[i])
808 /*-----------------------------------------------------------------*/
809 /* operandsEqu - equivalent */
810 /*-----------------------------------------------------------------*/
812 operandsEqu (operand * op1, operand * op2)
816 /* if they're not symbols */
817 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
820 sym1 = OP_SYMBOL (op1);
821 sym2 = OP_SYMBOL (op2);
823 /* if both are itemps & one is spilt
824 and the other is not then false */
825 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
826 sym1->isspilt != sym2->isspilt)
829 /* if they are the same */
833 /* if they have the same rname */
834 if (sym1->rname[0] && sym2->rname[0] &&
835 strcmp (sym1->rname, sym2->rname) == 0 &&
836 !(IS_PARM (op2) && IS_ITEMP (op1)))
839 /* if left is a tmp & right is not */
840 if (IS_ITEMP (op1) &&
843 (sym1->usl.spillLoc == sym2))
846 if (IS_ITEMP (op2) &&
850 (sym2->usl.spillLoc == sym1))
856 /*-----------------------------------------------------------------*/
857 /* sameByte - two asmops have the same address at given offsets */
858 /*-----------------------------------------------------------------*/
860 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
862 if (aop1 == aop2 && off1 == off2)
865 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
868 if (aop1->type != aop2->type)
871 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
877 /*-----------------------------------------------------------------*/
878 /* sameRegs - two asmops have the same registers */
879 /*-----------------------------------------------------------------*/
881 sameRegs (asmop * aop1, asmop * aop2)
888 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
891 if (aop1->type != aop2->type)
894 if (aop1->size != aop2->size)
897 for (i = 0; i < aop1->size; i++)
898 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
904 /*-----------------------------------------------------------------*/
905 /* aopOp - allocates an asmop for an operand : */
906 /*-----------------------------------------------------------------*/
908 aopOp (operand * op, iCode * ic, bool result)
917 /* if this a literal */
918 if (IS_OP_LITERAL (op))
920 op->aop = aop = newAsmop (AOP_LIT);
921 aop->aopu.aop_lit = op->operand.valOperand;
922 aop->size = getSize (operandType (op));
926 /* if already has a asmop then continue */
929 op->aop->allocated++;
933 /* if the underlying symbol has a aop */
934 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
936 op->aop = OP_SYMBOL (op)->aop;
937 op->aop->allocated++;
941 /* if this is a true symbol */
942 if (IS_TRUE_SYMOP (op))
944 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
948 /* this is a temporary : this has
954 e) can be a return use only */
956 sym = OP_SYMBOL (op);
958 /* if the type is a conditional */
959 if (sym->regType == REG_CND)
961 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
966 /* if it is spilt then two situations
968 b) has a spill location */
969 if (sym->isspilt || sym->nRegs == 0)
972 /* rematerialize it NOW */
975 sym->aop = op->aop = aop = aopForRemat (sym);
976 aop->size = getSize (sym->type);
983 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
984 aop->size = getSize (sym->type);
985 for (i = 0; i < 2; i++)
986 aop->aopu.aop_str[i] = accUse[i];
994 aop = op->aop = sym->aop = newAsmop (AOP_STR);
995 aop->size = getSize (sym->type);
996 for (i = 0; i < fReturnSizeMCS51; i++)
997 aop->aopu.aop_str[i] = fReturn[i];
1001 if (sym->usl.spillLoc)
1003 asmop *oldAsmOp = NULL;
1005 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1007 /* force a new aop if sizes differ */
1008 oldAsmOp = sym->usl.spillLoc->aop;
1009 sym->usl.spillLoc->aop = NULL;
1011 sym->aop = op->aop = aop =
1012 aopForSym (ic, sym->usl.spillLoc, result);
1013 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1015 /* Don't reuse the new aop, go with the last one */
1016 sym->usl.spillLoc->aop = oldAsmOp;
1018 aop->size = getSize (sym->type);
1022 /* else must be a dummy iTemp */
1023 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1024 aop->size = getSize (sym->type);
1028 /* if the type is a bit register */
1029 if (sym->regType == REG_BIT)
1031 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1032 aop->size = sym->nRegs;//1???
1033 aop->aopu.aop_reg[0] = sym->regs[0];
1034 aop->aopu.aop_dir = sym->regs[0]->name;
1038 /* must be in a register */
1039 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1040 aop->size = sym->nRegs;
1041 for (i = 0; i < sym->nRegs; i++)
1042 aop->aopu.aop_reg[i] = sym->regs[i];
1045 /*-----------------------------------------------------------------*/
1046 /* freeAsmop - free up the asmop given to an operand */
1047 /*----------------------------------------------------------------*/
1049 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1066 /* depending on the asmop type only three cases need work
1067 AOP_R0, AOP_R1 & AOP_STK */
1073 emitcode ("mov", "r0,b");
1076 else if (_G.r0Pushed)
1080 emitcode ("pop", "ar0");
1084 bitVectUnSetBit (ic->rUsed, R0_IDX);
1090 emitcode ("mov", "r1,b");
1093 else if (_G.r1Pushed)
1097 emitcode ("pop", "ar1");
1101 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 int stk = aop->aopu.aop_stk + aop->size - 1;
1108 bitVectUnSetBit (ic->rUsed, R0_IDX);
1109 bitVectUnSetBit (ic->rUsed, R1_IDX);
1111 getFreePtr (ic, &aop, FALSE);
1115 emitcode ("mov", "a,_bp");
1116 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1117 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1121 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1126 emitcode ("pop", "acc");
1127 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1130 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 freeAsmop (op, NULL, ic, TRUE);
1136 emitcode ("pop", "ar1");
1141 emitcode ("pop", "ar0");
1149 /* all other cases just dealloc */
1155 OP_SYMBOL (op)->aop = NULL;
1156 /* if the symbol has a spill */
1158 SPIL_LOC (op)->aop = NULL;
1163 /*------------------------------------------------------------------*/
1164 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1165 /* pop r0 or r1 off stack if pushed */
1166 /*------------------------------------------------------------------*/
1168 freeForBranchAsmop (operand * op)
1180 if (!aop->allocated)
1188 emitcode ("mov", "r0,b");
1190 else if (_G.r0Pushed)
1192 emitcode ("pop", "ar0");
1199 emitcode ("mov", "r1,b");
1201 else if (_G.r1Pushed)
1203 emitcode ("pop", "ar1");
1210 int stk = aop->aopu.aop_stk + aop->size - 1;
1212 emitcode ("mov", "b,r0");
1215 emitcode ("mov", "a,_bp");
1216 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1217 emitcode ("mov", "r0,a");
1221 emitcode ("mov", "r0,_bp");
1226 emitcode ("pop", "acc");
1227 emitcode ("mov", "@r0,a");
1230 emitcode ("dec", "r0");
1232 emitcode ("mov", "r0,b");
1238 /*-----------------------------------------------------------------*/
1239 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1240 /* clobber the accumulator */
1241 /*-----------------------------------------------------------------*/
1243 aopGetUsesAcc (operand * oper, int offset)
1245 asmop * aop = AOP (oper);
1247 if (offset > (aop->size - 1))
1265 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1276 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1282 /* Error case --- will have been caught already */
1288 /*-------------------------------------------------------------------*/
1289 /* aopGet - for fetching value of the aop */
1290 /*-------------------------------------------------------------------*/
1292 aopGet (operand * oper, int offset, bool bit16, bool dname)
1294 asmop * aop = AOP (oper);
1296 /* offset is greater than
1298 if (offset > (aop->size - 1) &&
1299 aop->type != AOP_LIT)
1302 /* depending on type */
1310 /* if we need to increment it */
1311 while (offset > aop->coff)
1313 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1317 while (offset < aop->coff)
1319 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1326 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1327 return (dname ? "acc" : "a");
1329 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1330 return Safe_strdup(buffer);
1333 if (aop->code && aop->coff==0 && offset>=1) {
1334 emitcode ("mov", "a,#0x%02x", offset);
1335 emitcode ("movc", "a,@a+dptr");
1336 return (dname ? "acc" : "a");
1339 while (offset > aop->coff)
1341 emitcode ("inc", "dptr");
1345 while (offset < aop->coff)
1347 emitcode ("lcall", "__decdptr");
1354 emitcode ("clr", "a");
1355 emitcode ("movc", "a,@a+dptr");
1359 emitcode ("movx", "a,@dptr");
1361 return (dname ? "acc" : "a");
1364 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "%s",aop->aopu.aop_immd.aop_immd2);
1371 SNPRINTF(buffer, sizeof(buffer),
1372 "#%s", aop->aopu.aop_immd.aop_immd1);
1376 SNPRINTF (buffer, sizeof(buffer),
1378 aop->aopu.aop_immd.aop_immd1,
1383 SNPRINTF (buffer, sizeof(buffer),
1385 aop->aopu.aop_immd.aop_immd1);
1387 return Safe_strdup(buffer);
1390 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1392 SNPRINTF (buffer, sizeof(buffer),
1394 aop->aopu.aop_dir, offset * 8);
1398 SNPRINTF (buffer, sizeof(buffer),
1405 SNPRINTF (buffer, sizeof(buffer),
1410 return Safe_strdup(buffer);
1414 return aop->aopu.aop_reg[offset]->dname;
1416 return aop->aopu.aop_reg[offset]->name;
1419 emitcode ("clr", "a");
1420 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1421 emitcode ("rlc", "a");
1422 return (dname ? "acc" : "a");
1425 if (!offset && dname)
1427 return aop->aopu.aop_str[offset];
1430 return aopLiteral (aop->aopu.aop_lit, offset);
1434 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1438 return aop->aopu.aop_str[offset];
1442 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1443 "aopget got unsupported aop->type");
1447 /*-----------------------------------------------------------------*/
1448 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1449 /* clobber the accumulator */
1450 /*-----------------------------------------------------------------*/
1452 aopPutUsesAcc (operand * oper, const char *s, int offset)
1454 asmop * aop = AOP (oper);
1456 if (offset > (aop->size - 1))
1466 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1472 return ((aop->paged) || (*s == '@'));
1476 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1484 /* Error case --- will have been caught already */
1490 /*-----------------------------------------------------------------*/
1491 /* aopPut - puts a string for a aop and indicates if acc is in use */
1492 /*-----------------------------------------------------------------*/
1494 aopPut (operand * result, const char *s, int offset)
1496 bool bvolatile = isOperandVolatile (result, FALSE);
1497 bool accuse = FALSE;
1498 asmop * aop = AOP (result);
1500 if (aop->size && offset > (aop->size - 1))
1502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503 "aopPut got offset > aop->size");
1507 /* will assign value to value */
1508 /* depending on where it is ofcourse */
1512 MOVA (s); /* read s in case it was volatile */
1517 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1519 SNPRINTF (buffer, sizeof(buffer),
1521 aop->aopu.aop_dir, offset * 8);
1525 SNPRINTF (buffer, sizeof(buffer),
1527 aop->aopu.aop_dir, offset);
1531 SNPRINTF (buffer, sizeof(buffer),
1536 if (strcmp (buffer, s) || bvolatile)
1538 emitcode ("mov", "%s,%s", buffer, s);
1540 if (!strcmp (buffer, "acc"))
1547 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1548 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1551 strcmp (s, "r0") == 0 ||
1552 strcmp (s, "r1") == 0 ||
1553 strcmp (s, "r2") == 0 ||
1554 strcmp (s, "r3") == 0 ||
1555 strcmp (s, "r4") == 0 ||
1556 strcmp (s, "r5") == 0 ||
1557 strcmp (s, "r6") == 0 ||
1558 strcmp (s, "r7") == 0)
1560 emitcode ("mov", "%s,%s",
1561 aop->aopu.aop_reg[offset]->dname, s);
1565 emitcode ("mov", "%s,%s",
1566 aop->aopu.aop_reg[offset]->name, s);
1574 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1575 "aopPut writing to code space");
1579 while (offset > aop->coff)
1582 emitcode ("inc", "dptr");
1585 while (offset < aop->coff)
1588 emitcode ("lcall", "__decdptr");
1593 /* if not in accumulator */
1596 emitcode ("movx", "@dptr,a");
1601 while (offset > aop->coff)
1604 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1606 while (offset < aop->coff)
1609 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1616 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1621 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1623 else if (strcmp (s, "r0") == 0 ||
1624 strcmp (s, "r1") == 0 ||
1625 strcmp (s, "r2") == 0 ||
1626 strcmp (s, "r3") == 0 ||
1627 strcmp (s, "r4") == 0 ||
1628 strcmp (s, "r5") == 0 ||
1629 strcmp (s, "r6") == 0 ||
1630 strcmp (s, "r7") == 0)
1633 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1634 emitcode ("mov", "@%s,%s",
1635 aop->aopu.aop_ptr->name, buffer);
1639 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1644 if (strcmp (s, "a") == 0)
1646 emitcode ("push", "acc");
1651 emitcode ("push", "acc");
1653 else if (strcmp (s, "r0") == 0 ||
1654 strcmp (s, "r1") == 0 ||
1655 strcmp (s, "r2") == 0 ||
1656 strcmp (s, "r3") == 0 ||
1657 strcmp (s, "r4") == 0 ||
1658 strcmp (s, "r5") == 0 ||
1659 strcmp (s, "r6") == 0 ||
1660 strcmp (s, "r7") == 0)
1663 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1664 emitcode ("push", buffer);
1668 emitcode ("push", s);
1674 /* if not bit variable */
1675 if (!aop->aopu.aop_dir)
1677 /* inefficient: move carry into A and use jz/jnz */
1678 emitcode ("clr", "a");
1679 emitcode ("rlc", "a");
1685 emitcode ("clr", "%s", aop->aopu.aop_dir);
1687 emitcode ("setb", "%s", aop->aopu.aop_dir);
1688 else if (!strcmp (s, "c"))
1689 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1690 else if (strcmp (s, aop->aopu.aop_dir))
1693 /* set C, if a >= 1 */
1694 emitcode ("add", "a,#0xff");
1695 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1702 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1703 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1709 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1712 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1713 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1717 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1718 "aopPut got unsupported aop->type");
1727 /*-----------------------------------------------------------------*/
1728 /* pointToEnd :- points to the last byte of the operand */
1729 /*-----------------------------------------------------------------*/
1731 pointToEnd (asmop * aop)
1737 aop->coff = count = (aop->size - 1);
1743 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1747 emitcode ("inc", "dptr");
1754 /*-----------------------------------------------------------------*/
1755 /* reAdjustPreg - points a register back to where it should */
1756 /*-----------------------------------------------------------------*/
1758 reAdjustPreg (asmop * aop)
1760 if ((aop->coff==0) || (aop->size <= 1))
1768 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1773 emitcode ("lcall", "__decdptr");
1780 /*-----------------------------------------------------------------*/
1781 /* opIsGptr: returns non-zero if the passed operand is */
1782 /* a generic pointer type. */
1783 /*-----------------------------------------------------------------*/
1785 opIsGptr (operand * op)
1787 sym_link *type = operandType (op);
1789 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1796 /*-----------------------------------------------------------------*/
1797 /* getDataSize - get the operand data size */
1798 /*-----------------------------------------------------------------*/
1800 getDataSize (operand * op)
1803 size = AOP_SIZE (op);
1804 if (size == GPTRSIZE)
1806 sym_link *type = operandType (op);
1807 if (IS_GENPTR (type))
1809 /* generic pointer; arithmetic operations
1810 * should ignore the high byte (pointer type).
1818 /*-----------------------------------------------------------------*/
1819 /* outAcc - output Acc */
1820 /*-----------------------------------------------------------------*/
1822 outAcc (operand * result)
1825 size = getDataSize (result);
1828 aopPut (result, "a", 0);
1831 /* unsigned or positive */
1834 aopPut (result, zero, offset++);
1839 /*-----------------------------------------------------------------*/
1840 /* outBitC - output a bit C */
1841 /*-----------------------------------------------------------------*/
1843 outBitC (operand * result)
1845 /* if the result is bit */
1846 if (AOP_TYPE (result) == AOP_CRY)
1848 aopPut (result, "c", 0);
1852 emitcode ("clr", "a");
1853 emitcode ("rlc", "a");
1858 /*-----------------------------------------------------------------*/
1859 /* toBoolean - emit code for orl a,operator(sizeop) */
1860 /*-----------------------------------------------------------------*/
1862 toBoolean (operand * oper)
1864 int size = AOP_SIZE (oper) - 1;
1866 bool AccUsed = FALSE;
1869 while (!AccUsed && size--)
1871 AccUsed |= aopGetUsesAcc(oper, offset++);
1874 size = AOP_SIZE (oper) - 1;
1876 MOVA (aopGet (oper, 0, FALSE, FALSE));
1877 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1880 emitcode("mov", "b,a");
1883 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1884 emitcode ("orl", "b,a");
1886 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1887 emitcode ("orl", "a,b");
1894 emitcode ("orl", "a,%s",
1895 aopGet (oper, offset++, FALSE, FALSE));
1901 /*-------------------------------------------------------------------*/
1902 /* xch_a_aopGet - for exchanging acc with value of the aop */
1903 /*-------------------------------------------------------------------*/
1905 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1909 if (aopGetUsesAcc (oper, offset))
1911 emitcode("mov", "b,a");
1912 MOVA (aopGet (oper, offset, bit16, dname));
1913 emitcode("xch", "a,b");
1914 aopPut (oper, "a", offset);
1915 emitcode("xch", "a,b");
1920 l = aopGet (oper, offset, bit16, dname);
1921 emitcode("xch", "a,%s", l);
1927 /*-----------------------------------------------------------------*/
1928 /* genNot - generate code for ! operation */
1929 /*-----------------------------------------------------------------*/
1935 D (emitcode (";", "genNot"));
1937 /* assign asmOps to operand & result */
1938 aopOp (IC_LEFT (ic), ic, FALSE);
1939 aopOp (IC_RESULT (ic), ic, TRUE);
1941 /* if in bit space then a special case */
1942 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1944 /* if left==result then cpl bit */
1945 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1947 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1951 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1952 emitcode ("cpl", "c");
1953 outBitC (IC_RESULT (ic));
1958 toBoolean (IC_LEFT (ic));
1960 /* set C, if a == 0 */
1961 tlbl = newiTempLabel (NULL);
1962 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1964 outBitC (IC_RESULT (ic));
1967 /* release the aops */
1968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1969 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1973 /*-----------------------------------------------------------------*/
1974 /* genCpl - generate code for complement */
1975 /*-----------------------------------------------------------------*/
1982 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1984 D(emitcode (";", "genCpl"));
1986 /* assign asmOps to operand & result */
1987 aopOp (IC_LEFT (ic), ic, FALSE);
1988 aopOp (IC_RESULT (ic), ic, TRUE);
1990 /* special case if in bit space */
1991 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1995 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1996 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1998 /* promotion rules are responsible for this strange result:
1999 bit -> int -> ~int -> bit
2000 uchar -> int -> ~int -> bit
2002 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2006 tlbl=newiTempLabel(NULL);
2007 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2008 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2009 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2010 IS_AOP_PREG (IC_LEFT (ic)))
2012 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2017 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2020 outBitC (IC_RESULT(ic));
2024 size = AOP_SIZE (IC_RESULT (ic));
2027 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2029 emitcode ("cpl", "a");
2030 aopPut (IC_RESULT (ic), "a", offset++);
2035 /* release the aops */
2036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2037 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2040 /*-----------------------------------------------------------------*/
2041 /* genUminusFloat - unary minus for floating points */
2042 /*-----------------------------------------------------------------*/
2044 genUminusFloat (operand * op, operand * result)
2046 int size, offset = 0;
2049 D (emitcode (";", "genUminusFloat"));
2051 /* for this we just copy and then flip the bit */
2053 size = AOP_SIZE (op) - 1;
2058 aopGet (op, offset, FALSE, FALSE),
2063 l = aopGet (op, offset, FALSE, FALSE);
2066 emitcode ("cpl", "acc.7");
2067 aopPut (result, "a", offset);
2070 /*-----------------------------------------------------------------*/
2071 /* genUminus - unary minus code generation */
2072 /*-----------------------------------------------------------------*/
2074 genUminus (iCode * ic)
2079 D (emitcode (";", "genUminus"));
2082 aopOp (IC_LEFT (ic), ic, FALSE);
2083 aopOp (IC_RESULT (ic), ic, TRUE);
2085 /* if both in bit space then special
2087 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2088 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2091 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2092 emitcode ("cpl", "c");
2093 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2097 optype = operandType (IC_LEFT (ic));
2099 /* if float then do float stuff */
2100 if (IS_FLOAT (optype))
2102 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2106 /* otherwise subtract from zero */
2107 size = AOP_SIZE (IC_LEFT (ic));
2111 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2112 if (!strcmp (l, "a"))
2116 emitcode ("cpl", "a");
2117 emitcode ("addc", "a,#0");
2123 emitcode ("clr", "a");
2124 emitcode ("subb", "a,%s", l);
2126 aopPut (IC_RESULT (ic), "a", offset++);
2129 /* if any remaining bytes in the result */
2130 /* we just need to propagate the sign */
2131 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2133 emitcode ("rlc", "a");
2134 emitcode ("subb", "a,acc");
2136 aopPut (IC_RESULT (ic), "a", offset++);
2140 /* release the aops */
2141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2142 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2145 /*-----------------------------------------------------------------*/
2146 /* saveRegisters - will look for a call and save the registers */
2147 /*-----------------------------------------------------------------*/
2149 saveRegisters (iCode * lic)
2156 for (ic = lic; ic; ic = ic->next)
2157 if (ic->op == CALL || ic->op == PCALL)
2162 fprintf (stderr, "found parameter push with no function call\n");
2166 /* if the registers have been saved already or don't need to be then
2170 if (IS_SYMOP(IC_LEFT(ic)) &&
2171 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2172 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2175 /* save the registers in use at this time but skip the
2176 ones for the result */
2177 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2178 mcs51_rUmaskForOp (IC_RESULT(ic)));
2181 if (options.useXstack)
2183 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2184 int nBits = bitVectnBitsOn (rsavebits);
2185 int count = bitVectnBitsOn (rsave);
2189 count = count - nBits + 1;
2190 /* remove all but the first bits as they are pushed all at once */
2191 rsave = bitVectCplAnd (rsave, rsavebits);
2192 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2197 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2198 if (reg->type == REG_BIT)
2200 emitcode ("mov", "a,%s", reg->base);
2204 emitcode ("mov", "a,%s", reg->name);
2206 emitcode ("mov", "r0,%s", spname);
2207 emitcode ("inc", "%s", spname);// allocate before use
2208 emitcode ("movx", "@r0,a");
2209 if (bitVectBitValue (rsave, R0_IDX))
2210 emitcode ("mov", "r0,a");
2212 else if (count != 0)
2214 if (bitVectBitValue (rsave, R0_IDX))
2216 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2218 emitcode ("mov", "r0,%s", spname);
2220 emitcode ("add", "a,#%d", count);
2221 emitcode ("mov", "%s,a", spname);
2222 for (i = 0; i < mcs51_nRegs; i++)
2224 if (bitVectBitValue (rsave, i))
2226 regs * reg = REG_WITH_INDEX (i);
2229 emitcode ("pop", "acc");
2230 emitcode ("push", "acc");
2232 else if (reg->type == REG_BIT)
2234 emitcode ("mov", "a,%s", reg->base);
2238 emitcode ("mov", "a,%s", reg->name);
2240 emitcode ("movx", "@r0,a");
2243 emitcode ("inc", "r0");
2247 if (bitVectBitValue (rsave, R0_IDX))
2249 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2255 bool bits_pushed = FALSE;
2256 for (i = 0; i < mcs51_nRegs; i++)
2258 if (bitVectBitValue (rsave, i))
2260 bits_pushed = pushReg (i, bits_pushed);
2266 /*-----------------------------------------------------------------*/
2267 /* unsaveRegisters - pop the pushed registers */
2268 /*-----------------------------------------------------------------*/
2270 unsaveRegisters (iCode * ic)
2275 /* restore the registers in use at this time but skip the
2276 ones for the result */
2277 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2278 mcs51_rUmaskForOp (IC_RESULT(ic)));
2280 if (options.useXstack)
2282 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2283 int nBits = bitVectnBitsOn (rsavebits);
2284 int count = bitVectnBitsOn (rsave);
2288 count = count - nBits + 1;
2289 /* remove all but the first bits as they are popped all at once */
2290 rsave = bitVectCplAnd (rsave, rsavebits);
2291 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2296 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2297 emitcode ("mov", "r0,%s", spname);
2298 emitcode ("dec", "r0");
2299 emitcode ("movx", "a,@r0");
2300 if (reg->type == REG_BIT)
2302 emitcode ("mov", "%s,a", reg->base);
2306 emitcode ("mov", "%s,a", reg->name);
2308 emitcode ("dec", "%s", spname);
2310 else if (count != 0)
2312 emitcode ("mov", "r0,%s", spname);
2313 for (i = mcs51_nRegs; i >= 0; i--)
2315 if (bitVectBitValue (rsave, i))
2317 regs * reg = REG_WITH_INDEX (i);
2318 emitcode ("dec", "r0");
2319 emitcode ("movx", "a,@r0");
2322 emitcode ("push", "acc");
2324 else if (reg->type == REG_BIT)
2326 emitcode ("mov", "%s,a", reg->base);
2330 emitcode ("mov", "%s,a", reg->name);
2334 emitcode ("mov", "%s,r0", spname);
2335 if (bitVectBitValue (rsave, R0_IDX))
2337 emitcode ("pop", "ar0");
2343 bool bits_popped = FALSE;
2344 for (i = mcs51_nRegs; i >= 0; i--)
2346 if (bitVectBitValue (rsave, i))
2348 bits_popped = popReg (i, bits_popped);
2355 /*-----------------------------------------------------------------*/
2357 /*-----------------------------------------------------------------*/
2359 pushSide (operand * oper, int size)
2364 char *l = aopGet (oper, offset++, FALSE, TRUE);
2365 if (AOP_TYPE (oper) != AOP_REG &&
2366 AOP_TYPE (oper) != AOP_DIR &&
2370 emitcode ("push", "acc");
2374 emitcode ("push", "%s", l);
2379 /*-----------------------------------------------------------------*/
2380 /* assignResultValue - also indicates if acc is in use afterwards */
2381 /*-----------------------------------------------------------------*/
2383 assignResultValue (operand * oper, operand * func)
2386 int size = AOP_SIZE (oper);
2387 bool accuse = FALSE;
2388 bool pushedA = FALSE;
2390 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2396 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2398 emitcode ("push", "acc");
2403 if ((offset == 3) && pushedA)
2404 emitcode ("pop", "acc");
2405 accuse |= aopPut (oper, fReturn[offset], offset);
2412 /*-----------------------------------------------------------------*/
2413 /* genXpush - pushes onto the external stack */
2414 /*-----------------------------------------------------------------*/
2416 genXpush (iCode * ic)
2418 asmop *aop = newAsmop (0);
2420 int size, offset = 0;
2422 D (emitcode (";", "genXpush"));
2424 aopOp (IC_LEFT (ic), ic, FALSE);
2425 r = getFreePtr (ic, &aop, FALSE);
2427 size = AOP_SIZE (IC_LEFT (ic));
2431 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2432 emitcode ("mov", "%s,%s", r->name, spname);
2433 emitcode ("inc", "%s", spname); // allocate space first
2434 emitcode ("movx", "@%s,a", r->name);
2438 // allocate space first
2439 emitcode ("mov", "%s,%s", r->name, spname);
2441 emitcode ("add", "a,#%d", size);
2442 emitcode ("mov", "%s,a", spname);
2446 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2447 emitcode ("movx", "@%s,a", r->name);
2448 emitcode ("inc", "%s", r->name);
2452 freeAsmop (NULL, aop, ic, TRUE);
2453 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2456 /*-----------------------------------------------------------------*/
2457 /* genIpush - generate code for pushing this gets a little complex */
2458 /*-----------------------------------------------------------------*/
2460 genIpush (iCode * ic)
2462 int size, offset = 0;
2466 D (emitcode (";", "genIpush"));
2468 /* if this is not a parm push : ie. it is spill push
2469 and spill push is always done on the local stack */
2473 /* and the item is spilt then do nothing */
2474 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2477 aopOp (IC_LEFT (ic), ic, FALSE);
2478 size = AOP_SIZE (IC_LEFT (ic));
2479 /* push it on the stack */
2482 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2488 emitcode ("push", "%s", l);
2493 /* this is a parameter push: in this case we call
2494 the routine to find the call and save those
2495 registers that need to be saved */
2498 /* if use external stack then call the external
2499 stack pushing routine */
2500 if (options.useXstack)
2506 /* then do the push */
2507 aopOp (IC_LEFT (ic), ic, FALSE);
2509 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2515 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2516 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2518 if (strcmp (l, prev) || *l == '@')
2520 emitcode ("push", "acc");
2524 emitcode ("push", "%s", l);
2529 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2532 /*-----------------------------------------------------------------*/
2533 /* genIpop - recover the registers: can happen only for spilling */
2534 /*-----------------------------------------------------------------*/
2536 genIpop (iCode * ic)
2540 D (emitcode (";", "genIpop"));
2542 /* if the temp was not pushed then */
2543 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2546 aopOp (IC_LEFT (ic), ic, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2548 offset = (size - 1);
2551 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2555 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2558 /*-----------------------------------------------------------------*/
2559 /* saveRBank - saves an entire register bank on the stack */
2560 /*-----------------------------------------------------------------*/
2562 saveRBank (int bank, iCode * ic, bool pushPsw)
2565 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2569 if (options.useXstack)
2573 /* Assume r0 is available for use. */
2574 r = REG_WITH_INDEX (R0_IDX);;
2579 r = getFreePtr (ic, &aop, FALSE);
2581 // allocate space first
2582 emitcode ("mov", "%s,%s", r->name, spname);
2584 emitcode ("add", "a,#%d", count);
2585 emitcode ("mov", "%s,a", spname);
2588 for (i = 0; i < 8; i++)
2590 if (options.useXstack)
2592 emitcode ("mov", "a,(%s+%d)",
2593 regs8051[i].base, 8 * bank + regs8051[i].offset);
2594 emitcode ("movx", "@%s,a", r->name);
2596 emitcode ("inc", "%s", r->name);
2599 emitcode ("push", "(%s+%d)",
2600 regs8051[i].base, 8 * bank + regs8051[i].offset);
2603 if (mcs51_nRegs > 8)
2605 if (options.useXstack)
2607 emitcode ("mov", "a,bits");
2608 emitcode ("movx", "@%s,a", r->name);
2610 emitcode ("inc", "%s", r->name);
2614 emitcode ("push", "bits");
2621 if (options.useXstack)
2623 emitcode ("mov", "a,psw");
2624 emitcode ("movx", "@%s,a", r->name);
2628 emitcode ("push", "psw");
2631 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2636 freeAsmop (NULL, aop, ic, TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* unsaveRBank - restores the register bank from stack */
2647 /*-----------------------------------------------------------------*/
2649 unsaveRBank (int bank, iCode * ic, bool popPsw)
2655 if (options.useXstack)
2659 /* Assume r0 is available for use. */
2660 r = REG_WITH_INDEX (R0_IDX);;
2665 r = getFreePtr (ic, &aop, FALSE);
2667 emitcode ("mov", "%s,%s", r->name, spname);
2672 if (options.useXstack)
2674 emitcode ("dec", "%s", r->name);
2675 emitcode ("movx", "a,@%s", r->name);
2676 emitcode ("mov", "psw,a");
2680 emitcode ("pop", "psw");
2684 if (mcs51_nRegs > 8)
2686 if (options.useXstack)
2688 emitcode ("dec", "%s", r->name);
2689 emitcode ("movx", "a,@%s", r->name);
2690 emitcode ("mov", "bits,a");
2694 emitcode ("pop", "bits");
2698 for (i = 7; i >= 0; i--)
2700 if (options.useXstack)
2702 emitcode ("dec", "%s", r->name);
2703 emitcode ("movx", "a,@%s", r->name);
2704 emitcode ("mov", "(%s+%d),a",
2705 regs8051[i].base, 8 * bank + regs8051[i].offset);
2709 emitcode ("pop", "(%s+%d)",
2710 regs8051[i].base, 8 * bank + regs8051[i].offset);
2714 if (options.useXstack)
2716 emitcode ("mov", "%s,%s", spname, r->name);
2721 freeAsmop (NULL, aop, ic, TRUE);
2725 /*-----------------------------------------------------------------*/
2726 /* genSend - gen code for SEND */
2727 /*-----------------------------------------------------------------*/
2728 static void genSend(set *sendSet)
2733 /* first we do all bit parameters */
2734 for (sic = setFirstItem (sendSet); sic;
2735 sic = setNextItem (sendSet))
2737 if (sic->argreg > 12)
2739 int bit = sic->argreg-13;
2741 aopOp (IC_LEFT (sic), sic, FALSE);
2743 /* if left is a literal then
2744 we know what the value is */
2745 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2747 if (((int) operandLitValue (IC_LEFT (sic))))
2748 emitcode ("setb", "b[%d]", bit);
2750 emitcode ("clr", "b[%d]", bit);
2752 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2754 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2755 if (strcmp (l, "c"))
2756 emitcode ("mov", "c,%s", l);
2757 emitcode ("mov", "b[%d],c", bit);
2762 toBoolean (IC_LEFT (sic));
2763 /* set C, if a >= 1 */
2764 emitcode ("add", "a,#0xff");
2765 emitcode ("mov", "b[%d],c", bit);
2770 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2776 saveRegisters (setFirstItem (sendSet));
2777 emitcode ("mov", "bits,b");
2780 /* then we do all other parameters */
2781 for (sic = setFirstItem (sendSet); sic;
2782 sic = setNextItem (sendSet))
2784 if (sic->argreg <= 12)
2786 int size, offset = 0;
2787 aopOp (IC_LEFT (sic), sic, FALSE);
2788 size = AOP_SIZE (IC_LEFT (sic));
2790 if (sic->argreg == 1)
2794 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2795 if (strcmp (l, fReturn[offset]))
2797 emitcode ("mov", "%s,%s", fReturn[offset], l);
2806 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2807 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2811 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2816 /*-----------------------------------------------------------------*/
2817 /* selectRegBank - emit code to select the register bank */
2818 /*-----------------------------------------------------------------*/
2820 selectRegBank (short bank, bool keepFlags)
2822 /* if f.e. result is in carry */
2825 emitcode ("anl", "psw,#0xE7");
2827 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2831 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2835 /*-----------------------------------------------------------------*/
2836 /* genCall - generates a call statement */
2837 /*-----------------------------------------------------------------*/
2839 genCall (iCode * ic)
2843 // bool restoreBank = FALSE;
2844 bool swapBanks = FALSE;
2845 bool accuse = FALSE;
2846 bool accPushed = FALSE;
2847 bool resultInF0 = FALSE;
2848 bool assignResultGenerated = FALSE;
2850 D (emitcode (";", "genCall"));
2852 dtype = operandType (IC_LEFT (ic));
2853 etype = getSpec(dtype);
2854 /* if send set is not empty then assign */
2857 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2858 genSend(reverseSet(_G.sendSet));
2860 genSend(_G.sendSet);
2865 /* if we are calling a not _naked function that is not using
2866 the same register bank then we need to save the
2867 destination registers on the stack */
2868 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2869 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2870 !IFFUNC_ISISR (dtype))
2875 /* if caller saves & we have not saved then */
2881 emitcode ("mov", "psw,#0x%02x",
2882 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2886 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2888 if (IFFUNC_CALLEESAVES(dtype))
2890 werror (E_BANKED_WITH_CALLEESAVES);
2894 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2895 OP_SYMBOL (IC_LEFT (ic))->rname :
2896 OP_SYMBOL (IC_LEFT (ic))->name);
2898 emitcode ("mov", "r0,#%s", l);
2899 emitcode ("mov", "r1,#(%s >> 8)", l);
2900 emitcode ("mov", "r2,#(%s >> 16)", l);
2901 emitcode ("lcall", "__sdcc_banked_call");
2906 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2907 OP_SYMBOL (IC_LEFT (ic))->rname :
2908 OP_SYMBOL (IC_LEFT (ic))->name));
2913 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2916 /* if we need assign a result value */
2917 if ((IS_ITEMP (IC_RESULT (ic)) &&
2918 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2919 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2920 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2921 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2922 IS_TRUE_SYMOP (IC_RESULT (ic)))
2926 aopOp (IC_RESULT (ic), ic, FALSE);
2929 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2930 assignResultGenerated = TRUE;
2932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2935 /* adjust the stack for parameters if required */
2939 if (ic->parmBytes > 3)
2943 emitcode ("push", "acc");
2946 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2947 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2948 !assignResultGenerated)
2950 emitcode ("mov", "F0,c");
2954 emitcode ("mov", "a,%s", spname);
2955 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2956 emitcode ("mov", "%s,a", spname);
2958 /* unsaveRegisters from xstack needs acc, but */
2959 /* unsaveRegisters from stack needs this popped */
2960 if (accPushed && !options.useXstack)
2962 emitcode ("pop", "acc");
2967 for (i = 0; i < ic->parmBytes; i++)
2968 emitcode ("dec", "%s", spname);
2971 /* if we had saved some registers then unsave them */
2972 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2974 if (accuse && !accPushed && options.useXstack)
2976 /* xstack needs acc, but doesn't touch normal stack */
2977 emitcode ("push", "acc");
2980 unsaveRegisters (ic);
2983 // /* if register bank was saved then pop them */
2985 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2987 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2990 emitcode ("mov", "c,F0");
2992 aopOp (IC_RESULT (ic), ic, FALSE);
2993 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2994 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2998 emitcode ("pop", "acc");
3001 /*-----------------------------------------------------------------*/
3002 /* genPcall - generates a call by pointer statement */
3003 /*-----------------------------------------------------------------*/
3005 genPcall (iCode * ic)
3009 symbol *rlbl = newiTempLabel (NULL);
3010 // bool restoreBank=FALSE;
3011 bool swapBanks = FALSE;
3012 bool resultInF0 = FALSE;
3014 D (emitcode (";", "genPcall"));
3016 dtype = operandType (IC_LEFT (ic))->next;
3017 etype = getSpec(dtype);
3018 /* if caller saves & we have not saved then */
3022 /* if we are calling a not _naked function that is not using
3023 the same register bank then we need to save the
3024 destination registers on the stack */
3025 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3026 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3027 !IFFUNC_ISISR (dtype))
3029 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3030 // restoreBank=TRUE;
3032 // need caution message to user here
3035 if (IS_LITERAL(etype))
3037 /* if send set is not empty then assign */
3040 genSend(reverseSet(_G.sendSet));
3046 emitcode ("mov", "psw,#0x%02x",
3047 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3050 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3052 if (IFFUNC_CALLEESAVES(dtype))
3054 werror (E_BANKED_WITH_CALLEESAVES);
3058 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3060 emitcode ("mov", "r0,#%s", l);
3061 emitcode ("mov", "r1,#(%s >> 8)", l);
3062 emitcode ("mov", "r2,#(%s >> 16)", l);
3063 emitcode ("lcall", "__sdcc_banked_call");
3068 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3073 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3075 if (IFFUNC_CALLEESAVES(dtype))
3077 werror (E_BANKED_WITH_CALLEESAVES);
3081 aopOp (IC_LEFT (ic), ic, FALSE);
3085 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3086 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3087 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3091 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3092 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3093 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3094 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3097 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* if send set is not empty then assign */
3102 genSend(reverseSet(_G.sendSet));
3108 emitcode ("mov", "psw,#0x%02x",
3109 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3113 emitcode ("lcall", "__sdcc_banked_call");
3118 /* push the return address on to the stack */
3119 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3120 emitcode ("push", "acc");
3121 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3122 emitcode ("push", "acc");
3124 /* now push the calling address */
3125 aopOp (IC_LEFT (ic), ic, FALSE);
3127 pushSide (IC_LEFT (ic), FPTRSIZE);
3129 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3131 /* if send set is not empty the assign */
3134 genSend(reverseSet(_G.sendSet));
3140 emitcode ("mov", "psw,#0x%02x",
3141 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3145 emitcode ("ret", "");
3151 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3154 /* if we need assign a result value */
3155 if ((IS_ITEMP (IC_RESULT (ic)) &&
3156 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3157 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3158 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3159 IS_TRUE_SYMOP (IC_RESULT (ic)))
3163 aopOp (IC_RESULT (ic), ic, FALSE);
3166 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3171 /* adjust the stack for parameters if required */
3175 if (ic->parmBytes > 3)
3177 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3178 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3180 emitcode ("mov", "F0,c");
3184 emitcode ("mov", "a,%s", spname);
3185 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3186 emitcode ("mov", "%s,a", spname);
3189 for (i = 0; i < ic->parmBytes; i++)
3190 emitcode ("dec", "%s", spname);
3193 // /* if register bank was saved then unsave them */
3195 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3197 /* if we had saved some registers then unsave them */
3198 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3199 unsaveRegisters (ic);
3201 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3204 emitcode ("mov", "c,F0");
3206 aopOp (IC_RESULT (ic), ic, FALSE);
3207 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212 /*-----------------------------------------------------------------*/
3213 /* resultRemat - result is rematerializable */
3214 /*-----------------------------------------------------------------*/
3216 resultRemat (iCode * ic)
3218 if (SKIP_IC (ic) || ic->op == IFX)
3221 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3223 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3224 if (sym->remat && !POINTER_SET (ic))
3231 /*-----------------------------------------------------------------*/
3232 /* inExcludeList - return 1 if the string is in exclude Reg list */
3233 /*-----------------------------------------------------------------*/
3235 regsCmp(void *p1, void *p2)
3237 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3241 inExcludeList (char *s)
3243 const char *p = setFirstItem(options.excludeRegsSet);
3245 if (p == NULL || STRCASECMP(p, "none") == 0)
3249 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3252 /*-----------------------------------------------------------------*/
3253 /* genFunction - generated code for function entry */
3254 /*-----------------------------------------------------------------*/
3256 genFunction (iCode * ic)
3258 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3260 bool switchedPSW = FALSE;
3261 int calleesaves_saved_register = -1;
3262 int stackAdjust = sym->stack;
3263 int accIsFree = sym->recvSize < 4;
3264 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3265 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3268 /* create the function header */
3269 emitcode (";", "-----------------------------------------");
3270 emitcode (";", " function %s", sym->name);
3271 emitcode (";", "-----------------------------------------");
3273 emitcode ("", "%s:", sym->rname);
3274 lineCurr->isLabel = 1;
3275 ftype = operandType (IC_LEFT (ic));
3276 _G.currentFunc = sym;
3278 if (IFFUNC_ISNAKED(ftype))
3280 emitcode(";", "naked function: no prologue.");
3284 /* here we need to generate the equates for the
3285 register bank if required */
3286 if (FUNC_REGBANK (ftype) != rbank)
3290 rbank = FUNC_REGBANK (ftype);
3291 for (i = 0; i < mcs51_nRegs; i++)
3293 if (regs8051[i].type != REG_BIT)
3295 if (strcmp (regs8051[i].base, "0") == 0)
3296 emitcode ("", "%s = 0x%02x",
3298 8 * rbank + regs8051[i].offset);
3300 emitcode ("", "%s = %s + 0x%02x",
3303 8 * rbank + regs8051[i].offset);
3308 /* if this is an interrupt service routine then
3309 save acc, b, dpl, dph */
3310 if (IFFUNC_ISISR (sym->type))
3312 if (!inExcludeList ("acc"))
3313 emitcode ("push", "acc");
3314 if (!inExcludeList ("b"))
3315 emitcode ("push", "b");
3316 if (!inExcludeList ("dpl"))
3317 emitcode ("push", "dpl");
3318 if (!inExcludeList ("dph"))
3319 emitcode ("push", "dph");
3320 /* if this isr has no bank i.e. is going to
3321 run with bank 0 , then we need to save more
3323 if (!FUNC_REGBANK (sym->type))
3327 /* if this function does not call any other
3328 function then we can be economical and
3329 save only those registers that are used */
3330 if (!IFFUNC_HASFCALL(sym->type))
3332 /* if any registers used */
3335 bool bits_pushed = FALSE;
3336 /* save the registers used */
3337 for (i = 0; i < sym->regsUsed->size; i++)
3339 if (bitVectBitValue (sym->regsUsed, i))
3340 bits_pushed = pushReg (i, bits_pushed);
3346 /* this function has a function call. We cannot
3347 determine register usage so we will have to push the
3349 saveRBank (0, ic, FALSE);
3350 if (options.parms_in_bank1) {
3351 for (i=0; i < 8 ; i++ ) {
3352 emitcode ("push","%s",rb1regs[i]);
3359 /* This ISR uses a non-zero bank.
3361 * We assume that the bank is available for our
3364 * However, if this ISR calls a function which uses some
3365 * other bank, we must save that bank entirely.
3367 unsigned long banksToSave = 0;
3369 if (IFFUNC_HASFCALL(sym->type))
3372 #define MAX_REGISTER_BANKS 4
3377 for (i = ic; i; i = i->next)
3379 if (i->op == ENDFUNCTION)
3381 /* we got to the end OK. */
3389 dtype = operandType (IC_LEFT(i));
3391 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3393 /* Mark this bank for saving. */
3394 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3396 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3400 banksToSave |= (1 << FUNC_REGBANK(dtype));
3403 /* And note that we don't need to do it in
3411 /* This is a mess; we have no idea what
3412 * register bank the called function might
3415 * The only thing I can think of to do is
3416 * throw a warning and hope.
3418 werror(W_FUNCPTR_IN_USING_ISR);
3422 if (banksToSave && options.useXstack)
3424 /* Since we aren't passing it an ic,
3425 * saveRBank will assume r0 is available to abuse.
3427 * So switch to our (trashable) bank now, so
3428 * the caller's R0 isn't trashed.
3430 emitcode ("push", "psw");
3431 emitcode ("mov", "psw,#0x%02x",
3432 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3436 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3438 if (banksToSave & (1 << ix))
3440 saveRBank(ix, NULL, FALSE);
3444 // TODO: this needs a closer look
3445 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3448 /* Set the register bank to the desired value if nothing else */
3449 /* has done so yet. */
3452 emitcode ("push", "psw");
3453 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3458 /* This is a non-ISR function. The caller has already switched register */
3459 /* banks, if necessary, so just handle the callee-saves option. */
3461 /* if callee-save to be used for this function
3462 then save the registers being used in this function */
3463 if (IFFUNC_CALLEESAVES(sym->type))
3467 /* if any registers used */
3470 bool bits_pushed = FALSE;
3471 /* save the registers used */
3472 for (i = 0; i < sym->regsUsed->size; i++)
3474 if (bitVectBitValue (sym->regsUsed, i))
3476 /* remember one saved register for later usage */
3477 if (calleesaves_saved_register < 0)
3478 calleesaves_saved_register = i;
3479 bits_pushed = pushReg (i, bits_pushed);
3489 if (options.useXstack)
3491 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3493 emitcode ("mov", "r0,%s", spname);
3494 emitcode ("inc", "%s", spname);
3495 emitcode ("xch", "a,_bpx");
3496 emitcode ("movx", "@r0,a");
3497 emitcode ("inc", "r0");
3498 emitcode ("mov", "a,r0");
3499 emitcode ("xch", "a,_bpx");
3503 emitcode ("push", "_bp"); /* save the callers stack */
3504 emitcode ("mov", "_bp,sp");
3509 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3511 /* set up the stack */
3512 emitcode ("push", "_bp"); /* save the callers stack */
3513 emitcode ("mov", "_bp,sp");
3518 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3519 /* before setting up the stack frame completely. */
3520 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3522 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3526 if (rsym && rsym->regType == REG_CND)
3528 if (rsym && (rsym->accuse || rsym->ruonly))
3530 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3531 rsym = rsym->usl.spillLoc;
3534 /* If the RECEIVE operand immediately spills to the first entry on the */
3535 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3536 /* rather than the usual @r0/r1 machinations. */
3537 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3541 _G.current_iCode = ric;
3542 D(emitcode ("; genReceive",""));
3543 for (ofs=0; ofs < sym->recvSize; ofs++)
3545 if (!strcmp (fReturn[ofs], "a"))
3546 emitcode ("push", "acc");
3548 emitcode ("push", fReturn[ofs]);
3550 stackAdjust -= sym->recvSize;
3553 assert (stackAdjust>=0);
3556 _G.current_iCode = ic;
3560 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3561 /* to free up the accumulator. */
3562 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3566 _G.current_iCode = ric;
3567 D(emitcode ("; genReceive",""));
3568 for (ofs=0; ofs < sym->recvSize; ofs++)
3570 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3572 _G.current_iCode = ic;
3578 /* adjust the stack for the function */
3581 int i = stackAdjust;
3583 werror (W_STACK_OVERFLOW, sym->name);
3585 if (i > 3 && accIsFree)
3587 emitcode ("mov", "a,sp");
3588 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3589 emitcode ("mov", "sp,a");
3593 /* The accumulator is not free, so we will need another register */
3594 /* to clobber. No need to worry about a possible conflict with */
3595 /* the above early RECEIVE optimizations since they would have */
3596 /* freed the accumulator if they were generated. */
3598 if (IFFUNC_CALLEESAVES(sym->type))
3600 /* if it's a callee-saves function we need a saved register */
3601 if (calleesaves_saved_register >= 0)
3603 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3604 emitcode ("mov", "a,sp");
3605 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3606 emitcode ("mov", "sp,a");
3607 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3610 /* do it the hard way */
3612 emitcode ("inc", "sp");
3616 /* not callee-saves, we can clobber r0 */
3617 emitcode ("mov", "r0,a");
3618 emitcode ("mov", "a,sp");
3619 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3620 emitcode ("mov", "sp,a");
3621 emitcode ("mov", "a,r0");
3626 emitcode ("inc", "sp");
3631 char i = ((char) sym->xstack & 0xff);
3633 if (i > 3 && accIsFree)
3635 emitcode ("mov", "a,_spx");
3636 emitcode ("add", "a,#0x%02x", i & 0xff);
3637 emitcode ("mov", "_spx,a");
3641 emitcode ("push", "acc");
3642 emitcode ("mov", "a,_spx");
3643 emitcode ("add", "a,#0x%02x", i & 0xff);
3644 emitcode ("mov", "_spx,a");
3645 emitcode ("pop", "acc");
3650 emitcode ("inc", "_spx");
3654 /* if critical function then turn interrupts off */
3655 if (IFFUNC_ISCRITICAL (ftype))
3657 symbol *tlbl = newiTempLabel (NULL);
3658 emitcode ("setb", "c");
3659 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3660 emitcode ("clr", "c");
3662 emitcode ("push", "psw"); /* save old ea via c in psw */
3666 /*-----------------------------------------------------------------*/
3667 /* genEndFunction - generates epilogue for functions */
3668 /*-----------------------------------------------------------------*/
3670 genEndFunction (iCode * ic)
3672 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3673 lineNode *lnp = lineCurr;
3675 bitVect *regsUsedPrologue;
3676 bitVect *regsUnneeded;
3679 _G.currentFunc = NULL;
3680 if (IFFUNC_ISNAKED(sym->type))
3682 emitcode(";", "naked function: no epilogue.");
3683 if (options.debug && currFunc)
3684 debugFile->writeEndFunction (currFunc, ic, 0);
3688 if (IFFUNC_ISCRITICAL (sym->type))
3690 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3692 emitcode ("rlc", "a"); /* save c in a */
3693 emitcode ("pop", "psw"); /* restore ea via c in psw */
3694 emitcode ("mov", "ea,c");
3695 emitcode ("rrc", "a"); /* restore c from a */
3699 emitcode ("pop", "psw"); /* restore ea via c in psw */
3700 emitcode ("mov", "ea,c");
3704 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3706 if (options.useXstack)
3710 emitcode ("mov", "sp,_bp");
3711 emitcode ("pop", "_bp");
3713 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3715 emitcode ("xch", "a,_bpx");
3716 emitcode ("mov", "r0,a");
3717 emitcode ("dec", "r0");
3718 emitcode ("movx", "a,@r0");
3719 emitcode ("xch", "a,_bpx");
3720 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3723 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3726 emitcode ("mov", "sp,_bp");
3727 emitcode ("pop", "_bp");
3731 /* restore the register bank */
3732 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3734 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3735 || !options.useXstack)
3737 /* Special case of ISR using non-zero bank with useXstack
3740 emitcode ("pop", "psw");
3744 if (IFFUNC_ISISR (sym->type))
3747 /* now we need to restore the registers */
3748 /* if this isr has no bank i.e. is going to
3749 run with bank 0 , then we need to save more
3751 if (!FUNC_REGBANK (sym->type))
3754 /* if this function does not call any other
3755 function then we can be economical and
3756 save only those registers that are used */
3757 if (!IFFUNC_HASFCALL(sym->type))
3759 /* if any registers used */
3762 bool bits_popped = FALSE;
3763 /* save the registers used */
3764 for (i = sym->regsUsed->size; i >= 0; i--)
3766 if (bitVectBitValue (sym->regsUsed, i))
3767 bits_popped = popReg (i, bits_popped);
3773 if (options.parms_in_bank1) {
3774 for (i = 7 ; i >= 0 ; i-- ) {
3775 emitcode ("pop","%s",rb1regs[i]);
3778 /* this function has a function call cannot
3779 determines register usage so we will have to pop the
3781 unsaveRBank (0, ic, FALSE);
3786 /* This ISR uses a non-zero bank.
3788 * Restore any register banks saved by genFunction
3791 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3794 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3796 if (savedBanks & (1 << ix))
3798 unsaveRBank(ix, NULL, FALSE);
3802 if (options.useXstack)
3804 /* Restore bank AFTER calling unsaveRBank,
3805 * since it can trash r0.
3807 emitcode ("pop", "psw");
3811 if (!inExcludeList ("dph"))
3812 emitcode ("pop", "dph");
3813 if (!inExcludeList ("dpl"))
3814 emitcode ("pop", "dpl");
3815 if (!inExcludeList ("b"))
3816 emitcode ("pop", "b");
3817 if (!inExcludeList ("acc"))
3818 emitcode ("pop", "acc");
3820 /* if debug then send end of function */
3821 if (options.debug && currFunc)
3823 debugFile->writeEndFunction (currFunc, ic, 1);
3826 emitcode ("reti", "");
3830 if (IFFUNC_CALLEESAVES(sym->type))
3834 /* if any registers used */
3837 /* save the registers used */
3838 for (i = sym->regsUsed->size; i >= 0; i--)
3840 if (bitVectBitValue (sym->regsUsed, i) ||
3841 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3842 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3845 else if (mcs51_ptrRegReq)
3847 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3848 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3853 /* if debug then send end of function */
3854 if (options.debug && currFunc)
3856 debugFile->writeEndFunction (currFunc, ic, 1);
3859 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3861 emitcode ("ljmp", "__sdcc_banked_ret");
3865 emitcode ("ret", "");
3869 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3872 /* If this was an interrupt handler using bank 0 that called another */
3873 /* function, then all registers must be saved; nothing to optimized. */
3874 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3875 && !FUNC_REGBANK(sym->type))
3878 /* There are no push/pops to optimize if not callee-saves or ISR */
3879 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3882 /* If there were stack parameters, we cannot optimize without also */
3883 /* fixing all of the stack offsets; this is too dificult to consider. */
3884 if (FUNC_HASSTACKPARM(sym->type))
3887 /* Compute the registers actually used */
3888 regsUsed = newBitVect (mcs51_nRegs);
3889 regsUsedPrologue = newBitVect (mcs51_nRegs);
3892 if (lnp->ic && lnp->ic->op == FUNCTION)
3893 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3895 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3897 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3898 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3905 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3906 && !bitVectBitValue (regsUsed, CND_IDX))
3908 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3909 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3910 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3911 bitVectUnSetBit (regsUsed, CND_IDX);
3914 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3916 /* If this was an interrupt handler that called another function */
3917 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3918 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3920 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3921 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3922 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3923 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3924 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3927 /* Remove the unneeded push/pops */
3928 regsUnneeded = newBitVect (mcs51_nRegs);
3931 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3933 if (!strncmp(lnp->line, "push", 4))
3935 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3936 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3938 connectLine (lnp->prev, lnp->next);
3939 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3942 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3944 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3945 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3947 connectLine (lnp->prev, lnp->next);
3948 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3955 for (idx = 0; idx < regsUnneeded->size; idx++)
3956 if (bitVectBitValue (regsUnneeded, idx))
3957 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3959 freeBitVect (regsUnneeded);
3960 freeBitVect (regsUsed);
3961 freeBitVect (regsUsedPrologue);
3964 /*-----------------------------------------------------------------*/
3965 /* genRet - generate code for return statement */
3966 /*-----------------------------------------------------------------*/
3970 int size, offset = 0, pushed = 0;
3972 D (emitcode (";", "genRet"));
3974 /* if we have no return value then
3975 just generate the "ret" */
3979 /* we have something to return then
3980 move the return value into place */
3981 aopOp (IC_LEFT (ic), ic, FALSE);
3982 size = AOP_SIZE (IC_LEFT (ic));
3984 if (IS_BIT(_G.currentFunc->etype))
3986 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3993 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3996 l = aopGet (IC_LEFT (ic), offset++,
3998 emitcode ("push", "%s", l);
4003 l = aopGet (IC_LEFT (ic), offset,
4005 if (strcmp (fReturn[offset], l))
4006 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4013 if (strcmp (fReturn[pushed], "a"))
4014 emitcode ("pop", fReturn[pushed]);
4016 emitcode ("pop", "acc");
4018 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4021 /* generate a jump to the return label
4022 if the next is not the return statement */
4023 if (!(ic->next && ic->next->op == LABEL &&
4024 IC_LABEL (ic->next) == returnLabel))
4026 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4030 /*-----------------------------------------------------------------*/
4031 /* genLabel - generates a label */
4032 /*-----------------------------------------------------------------*/
4034 genLabel (iCode * ic)
4036 /* special case never generate */
4037 if (IC_LABEL (ic) == entryLabel)
4040 emitLabel (IC_LABEL (ic));
4043 /*-----------------------------------------------------------------*/
4044 /* genGoto - generates a ljmp */
4045 /*-----------------------------------------------------------------*/
4047 genGoto (iCode * ic)
4049 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4052 /*-----------------------------------------------------------------*/
4053 /* findLabelBackwards: walks back through the iCode chain looking */
4054 /* for the given label. Returns number of iCode instructions */
4055 /* between that label and given ic. */
4056 /* Returns zero if label not found. */
4057 /*-----------------------------------------------------------------*/
4059 findLabelBackwards (iCode * ic, int key)
4068 /* If we have any pushes or pops, we cannot predict the distance.
4069 I don't like this at all, this should be dealt with in the
4071 if (ic->op == IPUSH || ic->op == IPOP) {
4075 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4084 /*-----------------------------------------------------------------*/
4085 /* genPlusIncr :- does addition with increment if possible */
4086 /*-----------------------------------------------------------------*/
4088 genPlusIncr (iCode * ic)
4090 unsigned int icount;
4091 unsigned int size = getDataSize (IC_RESULT (ic));
4093 /* will try to generate an increment */
4094 /* if the right side is not a literal
4096 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4099 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4101 D(emitcode (";","genPlusIncr"));
4103 /* if increment >=16 bits in register or direct space */
4104 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4105 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4106 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4107 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4108 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4116 /* If the next instruction is a goto and the goto target
4117 * is < 10 instructions previous to this, we can generate
4118 * jumps straight to that target.
4120 if (ic->next && ic->next->op == GOTO
4121 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4122 && labelRange <= 10)
4124 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4125 tlbl = IC_LABEL (ic->next);
4130 tlbl = newiTempLabel (NULL);
4133 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4134 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4135 IS_AOP_PREG (IC_RESULT (ic)))
4136 emitcode ("cjne", "%s,#0x00,%05d$",
4137 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4141 emitcode ("clr", "a");
4142 emitcode ("cjne", "a,%s,%05d$",
4143 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4147 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4151 IS_AOP_PREG (IC_RESULT (ic)))
4152 emitcode ("cjne", "%s,#0x00,%05d$",
4153 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4156 emitcode ("cjne", "a,%s,%05d$",
4157 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4160 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4164 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4165 IS_AOP_PREG (IC_RESULT (ic)))
4166 emitcode ("cjne", "%s,#0x00,%05d$",
4167 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4171 emitcode ("cjne", "a,%s,%05d$",
4172 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4175 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4185 /* if result is dptr */
4186 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4187 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4188 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4189 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4191 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4197 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4200 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4201 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4203 emitcode ("inc", "dptr");
4208 /* if the literal value of the right hand side
4209 is greater than 4 then it is not worth it */
4213 /* if the sizes are greater than 1 then we cannot */
4214 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4215 AOP_SIZE (IC_LEFT (ic)) > 1)
4218 /* we can if the aops of the left & result match or
4219 if they are in registers and the registers are the
4221 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4225 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4226 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4227 aopPut (IC_RESULT (ic), "a", 0);
4233 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4242 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4243 emitcode ("inc", "a");
4244 aopPut (IC_RESULT (ic), "a", 0);
4251 /*-----------------------------------------------------------------*/
4252 /* outBitAcc - output a bit in acc */
4253 /*-----------------------------------------------------------------*/
4255 outBitAcc (operand * result)
4257 symbol *tlbl = newiTempLabel (NULL);
4258 /* if the result is a bit */
4259 if (AOP_TYPE (result) == AOP_CRY)
4261 aopPut (result, "a", 0);
4265 emitcode ("jz", "%05d$", tlbl->key + 100);
4266 emitcode ("mov", "a,%s", one);
4272 /*-----------------------------------------------------------------*/
4273 /* genPlusBits - generates code for addition of two bits */
4274 /*-----------------------------------------------------------------*/
4276 genPlusBits (iCode * ic)
4278 D (emitcode (";", "genPlusBits"));
4280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4282 symbol *lbl = newiTempLabel (NULL);
4283 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4284 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4285 emitcode ("cpl", "c");
4287 outBitC (IC_RESULT (ic));
4291 emitcode ("clr", "a");
4292 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4293 emitcode ("rlc", "a");
4294 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4295 emitcode ("addc", "a,%s", zero);
4296 outAcc (IC_RESULT (ic));
4301 /* This is the original version of this code.
4303 * This is being kept around for reference,
4304 * because I am not entirely sure I got it right...
4307 adjustArithmeticResult (iCode * ic)
4309 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4310 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4311 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4312 aopPut (IC_RESULT (ic),
4313 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4316 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4317 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4318 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4319 aopPut (IC_RESULT (ic),
4320 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4323 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4324 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4325 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4326 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4327 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4330 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4331 aopPut (IC_RESULT (ic), buffer, 2);
4335 /* This is the pure and virtuous version of this code.
4336 * I'm pretty certain it's right, but not enough to toss the old
4340 adjustArithmeticResult (iCode * ic)
4342 if (opIsGptr (IC_RESULT (ic)) &&
4343 opIsGptr (IC_LEFT (ic)) &&
4344 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4346 aopPut (IC_RESULT (ic),
4347 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4351 if (opIsGptr (IC_RESULT (ic)) &&
4352 opIsGptr (IC_RIGHT (ic)) &&
4353 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4355 aopPut (IC_RESULT (ic),
4356 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4360 if (opIsGptr (IC_RESULT (ic)) &&
4361 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4362 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4363 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4364 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4367 SNPRINTF (buffer, sizeof(buffer),
4368 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4369 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4374 /*-----------------------------------------------------------------*/
4375 /* genPlus - generates code for addition */
4376 /*-----------------------------------------------------------------*/
4378 genPlus (iCode * ic)
4380 int size, offset = 0;
4383 bool swappedLR = FALSE;
4384 operand *leftOp, *rightOp;
4387 D (emitcode (";", "genPlus"));
4389 /* special cases :- */
4391 aopOp (IC_LEFT (ic), ic, FALSE);
4392 aopOp (IC_RIGHT (ic), ic, FALSE);
4393 aopOp (IC_RESULT (ic), ic, TRUE);
4395 /* if literal, literal on the right or
4396 if left requires ACC or right is already
4398 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4399 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4400 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4402 operand *t = IC_RIGHT (ic);
4403 IC_RIGHT (ic) = IC_LEFT (ic);
4408 /* if both left & right are in bit
4410 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4411 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4417 /* if left in bit space & right literal */
4418 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4419 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4421 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4422 /* if result in bit space */
4423 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4425 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4426 emitcode ("cpl", "c");
4427 outBitC (IC_RESULT (ic));
4431 size = getDataSize (IC_RESULT (ic));
4434 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4435 emitcode ("addc", "a,%s", zero);
4436 aopPut (IC_RESULT (ic), "a", offset++);
4442 /* if I can do an increment instead
4443 of add then GOOD for ME */
4444 if (genPlusIncr (ic) == TRUE)
4447 size = getDataSize (IC_RESULT (ic));
4448 leftOp = IC_LEFT(ic);
4449 rightOp = IC_RIGHT(ic);
4452 /* if this is an add for an array access
4453 at a 256 byte boundary */
4455 && AOP_TYPE (op) == AOP_IMMD
4457 && IS_SPEC (OP_SYM_ETYPE (op))
4458 && SPEC_ABSA (OP_SYM_ETYPE (op))
4459 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4462 D(emitcode ("; genPlus aligned array",""));
4463 aopPut (IC_RESULT (ic),
4464 aopGet (rightOp, 0, FALSE, FALSE),
4467 if( 1 == getDataSize (IC_RIGHT (ic)) )
4469 aopPut (IC_RESULT (ic),
4470 aopGet (leftOp, 1, FALSE, FALSE),
4475 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4476 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4477 aopPut (IC_RESULT (ic), "a", 1);
4482 /* if the lower bytes of a literal are zero skip the addition */
4483 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4485 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4486 (skip_bytes+1 < size))
4491 D(emitcode ("; genPlus shortcut",""));
4496 if( offset >= skip_bytes )
4498 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4501 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4503 emitcode("xch", "a,b");
4504 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4505 emitcode (add, "a,b");
4508 else if (aopGetUsesAcc (leftOp, offset))
4510 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4511 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4515 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4516 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4518 aopPut (IC_RESULT (ic), "a", offset);
4519 add = "addc"; /* further adds must propagate carry */
4523 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4524 isOperandVolatile (IC_RESULT (ic), FALSE))
4527 aopPut (IC_RESULT (ic),
4528 aopGet (leftOp, offset, FALSE, FALSE),
4535 adjustArithmeticResult (ic);
4538 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4541 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4542 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4546 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4547 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4551 /*-----------------------------------------------------------------*/
4552 /* genMinusDec :- does subtraction with decrement if possible */
4553 /*-----------------------------------------------------------------*/
4555 genMinusDec (iCode * ic)
4557 unsigned int icount;
4558 unsigned int size = getDataSize (IC_RESULT (ic));
4560 /* will try to generate an increment */
4561 /* if the right side is not a literal
4563 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4566 /* if the literal value of the right hand side
4567 is greater than 4 then it is not worth it */
4568 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4571 D (emitcode (";", "genMinusDec"));
4573 /* if decrement >=16 bits in register or direct space */
4574 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4575 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4576 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4577 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4585 /* If the next instruction is a goto and the goto target
4586 * is <= 10 instructions previous to this, we can generate
4587 * jumps straight to that target.
4589 if (ic->next && ic->next->op == GOTO
4590 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4591 && labelRange <= 10)
4593 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4594 tlbl = IC_LABEL (ic->next);
4599 tlbl = newiTempLabel (NULL);
4603 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4604 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4605 IS_AOP_PREG (IC_RESULT (ic)))
4606 emitcode ("cjne", "%s,#0xff,%05d$"
4607 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4611 emitcode ("mov", "a,#0xff");
4612 emitcode ("cjne", "a,%s,%05d$"
4613 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4616 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4619 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4620 IS_AOP_PREG (IC_RESULT (ic)))
4621 emitcode ("cjne", "%s,#0xff,%05d$"
4622 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4626 emitcode ("cjne", "a,%s,%05d$"
4627 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4630 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4635 IS_AOP_PREG (IC_RESULT (ic)))
4636 emitcode ("cjne", "%s,#0xff,%05d$"
4637 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4641 emitcode ("cjne", "a,%s,%05d$"
4642 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4645 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4654 /* if the sizes are greater than 1 then we cannot */
4655 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4656 AOP_SIZE (IC_LEFT (ic)) > 1)
4659 /* we can if the aops of the left & result match or
4660 if they are in registers and the registers are the
4662 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4666 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4668 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4673 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4678 emitcode ("dec", "%s", l);
4681 if (AOP_NEEDSACC (IC_RESULT (ic)))
4682 aopPut (IC_RESULT (ic), "a", 0);
4689 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4690 emitcode ("dec", "a");
4691 aopPut (IC_RESULT (ic), "a", 0);
4698 /*-----------------------------------------------------------------*/
4699 /* addSign - complete with sign */
4700 /*-----------------------------------------------------------------*/
4702 addSign (operand * result, int offset, int sign)
4704 int size = (getDataSize (result) - offset);
4709 emitcode ("rlc", "a");
4710 emitcode ("subb", "a,acc");
4713 aopPut (result, "a", offset++);
4720 aopPut (result, zero, offset++);
4726 /*-----------------------------------------------------------------*/
4727 /* genMinusBits - generates code for subtraction of two bits */
4728 /*-----------------------------------------------------------------*/
4730 genMinusBits (iCode * ic)
4732 symbol *lbl = newiTempLabel (NULL);
4734 D (emitcode (";", "genMinusBits"));
4736 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4738 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4739 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4740 emitcode ("cpl", "c");
4742 outBitC (IC_RESULT (ic));
4746 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4747 emitcode ("subb", "a,acc");
4748 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4749 emitcode ("inc", "a");
4751 aopPut (IC_RESULT (ic), "a", 0);
4752 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4756 /*-----------------------------------------------------------------*/
4757 /* genMinus - generates code for subtraction */
4758 /*-----------------------------------------------------------------*/
4760 genMinus (iCode * ic)
4762 int size, offset = 0;
4764 D (emitcode (";", "genMinus"));
4766 aopOp (IC_LEFT (ic), ic, FALSE);
4767 aopOp (IC_RIGHT (ic), ic, FALSE);
4768 aopOp (IC_RESULT (ic), ic, TRUE);
4770 /* special cases :- */
4771 /* if both left & right are in bit space */
4772 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4773 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4779 /* if I can do an decrement instead
4780 of subtract then GOOD for ME */
4781 if (genMinusDec (ic) == TRUE)
4784 size = getDataSize (IC_RESULT (ic));
4786 /* if literal, add a,#-lit, else normal subb */
4787 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4789 unsigned long lit = 0L;
4790 bool useCarry = FALSE;
4792 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4797 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4799 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4800 if (!offset && !size && lit== (unsigned long) -1)
4802 emitcode ("dec", "a");
4806 /* first add without previous c */
4807 emitcode ("add", "a,#0x%02x",
4808 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4813 emitcode ("addc", "a,#0x%02x",
4814 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4816 aopPut (IC_RESULT (ic), "a", offset++);
4820 /* no need to add zeroes */
4821 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4823 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4832 operand *leftOp, *rightOp;
4834 leftOp = IC_LEFT(ic);
4835 rightOp = IC_RIGHT(ic);
4839 if (aopGetUsesAcc(rightOp, offset)) {
4840 if (aopGetUsesAcc(leftOp, offset)) {
4843 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4845 emitcode ("mov", "b,a");
4848 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4849 emitcode ("subb", "a,b");
4852 /* reverse subtraction with 2's complement */
4854 emitcode( "setb", "c");
4856 emitcode( "cpl", "c");
4857 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4858 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4859 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4860 emitcode("cpl", "a");
4861 if (size) /* skip if last byte */
4862 emitcode( "cpl", "c");
4865 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4868 emitcode ("subb", "a,%s",
4869 aopGet(rightOp, offset, FALSE, TRUE));
4872 aopPut (IC_RESULT (ic), "a", offset++);
4876 adjustArithmeticResult (ic);
4879 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4880 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4881 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885 /*-----------------------------------------------------------------*/
4886 /* genMultbits :- multiplication of bits */
4887 /*-----------------------------------------------------------------*/
4889 genMultbits (operand * left,
4893 D (emitcode (";", "genMultbits"));
4895 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4896 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4900 /*-----------------------------------------------------------------*/
4901 /* genMultOneByte : 8*8=8/16 bit multiplication */
4902 /*-----------------------------------------------------------------*/
4904 genMultOneByte (operand * left,
4909 int size = AOP_SIZE (result);
4910 bool runtimeSign, compiletimeSign;
4911 bool lUnsigned, rUnsigned, pushedB;
4913 D (emitcode (";", "genMultOneByte"));
4915 if (size < 1 || size > 2)
4917 /* this should never happen */
4918 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4919 AOP_SIZE(result), __FILE__, lineno);
4923 /* (if two literals: the value is computed before) */
4924 /* if one literal, literal on the right */
4925 if (AOP_TYPE (left) == AOP_LIT)
4930 /* emitcode (";", "swapped left and right"); */
4932 /* if no literal, unsigned on the right: shorter code */
4933 if ( AOP_TYPE (right) != AOP_LIT
4934 && SPEC_USIGN (getSpec (operandType (left))))
4941 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4942 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4946 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4947 no need to take care about the signedness! */
4948 || (lUnsigned && rUnsigned))
4950 /* just an unsigned 8 * 8 = 8 multiply
4952 /* emitcode (";","unsigned"); */
4953 /* TODO: check for accumulator clash between left & right aops? */
4955 if (AOP_TYPE (right) == AOP_LIT)
4957 /* moving to accumulator first helps peepholes */
4958 MOVA (aopGet (left, 0, FALSE, FALSE));
4959 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4963 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964 MOVA (aopGet (left, 0, FALSE, FALSE));
4967 emitcode ("mul", "ab");
4968 aopPut (result, "a", 0);
4970 aopPut (result, "b", 1);
4976 /* we have to do a signed multiply */
4977 /* emitcode (";", "signed"); */
4979 /* now sign adjust for both left & right */
4981 /* let's see what's needed: */
4982 /* apply negative sign during runtime */
4983 runtimeSign = FALSE;
4984 /* negative sign from literals */
4985 compiletimeSign = FALSE;
4989 if (AOP_TYPE(left) == AOP_LIT)
4991 /* signed literal */
4992 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4994 compiletimeSign = TRUE;
4997 /* signed but not literal */
5003 if (AOP_TYPE(right) == AOP_LIT)
5005 /* signed literal */
5006 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5008 compiletimeSign ^= TRUE;
5011 /* signed but not literal */
5015 /* initialize F0, which stores the runtime sign */
5018 if (compiletimeSign)
5019 emitcode ("setb", "F0"); /* set sign flag */
5021 emitcode ("clr", "F0"); /* reset sign flag */
5024 /* save the signs of the operands */
5025 if (AOP_TYPE(right) == AOP_LIT)
5027 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5029 if (!rUnsigned && val < 0)
5030 emitcode ("mov", "b,#0x%02x", -val);
5032 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5034 else /* ! literal */
5036 if (rUnsigned) /* emitcode (";", "signed"); */
5037 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5040 MOVA (aopGet (right, 0, FALSE, FALSE));
5041 lbl = newiTempLabel (NULL);
5042 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5043 emitcode ("cpl", "F0"); /* complement sign flag */
5044 emitcode ("cpl", "a"); /* 2's complement */
5045 emitcode ("inc", "a");
5047 emitcode ("mov", "b,a");
5051 if (AOP_TYPE(left) == AOP_LIT)
5053 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5055 if (!lUnsigned && val < 0)
5056 emitcode ("mov", "a,#0x%02x", -val);
5058 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5060 else /* ! literal */
5062 MOVA (aopGet (left, 0, FALSE, FALSE));
5066 lbl = newiTempLabel (NULL);
5067 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5068 emitcode ("cpl", "F0"); /* complement sign flag */
5069 emitcode ("cpl", "a"); /* 2's complement */
5070 emitcode ("inc", "a");
5075 /* now the multiplication */
5076 emitcode ("mul", "ab");
5077 if (runtimeSign || compiletimeSign)
5079 lbl = newiTempLabel (NULL);
5081 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5082 emitcode ("cpl", "a"); /* lsb 2's complement */
5084 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5087 emitcode ("add", "a,#1"); /* this sets carry flag */
5088 emitcode ("xch", "a,b");
5089 emitcode ("cpl", "a"); /* msb 2's complement */
5090 emitcode ("addc", "a,#0");
5091 emitcode ("xch", "a,b");
5095 aopPut (result, "a", 0);
5097 aopPut (result, "b", 1);
5102 /*-----------------------------------------------------------------*/
5103 /* genMult - generates code for multiplication */
5104 /*-----------------------------------------------------------------*/
5106 genMult (iCode * ic)
5108 operand *left = IC_LEFT (ic);
5109 operand *right = IC_RIGHT (ic);
5110 operand *result = IC_RESULT (ic);
5112 D (emitcode (";", "genMult"));
5114 /* assign the asmops */
5115 aopOp (left, ic, FALSE);
5116 aopOp (right, ic, FALSE);
5117 aopOp (result, ic, TRUE);
5119 /* special cases first */
5121 if (AOP_TYPE (left) == AOP_CRY &&
5122 AOP_TYPE (right) == AOP_CRY)
5124 genMultbits (left, right, result);
5128 /* if both are of size == 1 */
5129 #if 0 // one of them can be a sloc shared with the result
5130 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5132 if (getSize(operandType(left)) == 1 &&
5133 getSize(operandType(right)) == 1)
5136 genMultOneByte (left, right, result);
5140 /* should have been converted to function call */
5141 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5142 getSize(OP_SYMBOL(right)->type));
5146 freeAsmop (result, NULL, ic, TRUE);
5147 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151 /*-----------------------------------------------------------------*/
5152 /* genDivbits :- division of bits */
5153 /*-----------------------------------------------------------------*/
5155 genDivbits (operand * left,
5162 D(emitcode ("; genDivbits",""));
5166 /* the result must be bit */
5167 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5168 l = aopGet (left, 0, FALSE, FALSE);
5172 emitcode ("div", "ab");
5173 emitcode ("rrc", "a");
5177 aopPut (result, "c", 0);
5180 /*-----------------------------------------------------------------*/
5181 /* genDivOneByte : 8 bit division */
5182 /*-----------------------------------------------------------------*/
5184 genDivOneByte (operand * left,
5188 bool lUnsigned, rUnsigned, pushedB;
5189 bool runtimeSign, compiletimeSign;
5190 bool accuse = FALSE;
5191 bool pushedA = FALSE;
5195 D(emitcode ("; genDivOneByte",""));
5197 /* Why is it necessary that genDivOneByte() can return an int result?
5200 volatile unsigned char uc;
5201 volatile signed char sc1, sc2;
5214 In all cases a one byte result would overflow, the following cast to int
5215 would return the wrong result.
5217 Two possible solution:
5218 a) cast operands to int, if ((unsigned) / (signed)) or
5219 ((signed) / (signed))
5220 b) return an 16 bit signed int; this is what we're doing here!
5223 size = AOP_SIZE (result) - 1;
5225 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5226 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5230 /* signed or unsigned */
5231 if (lUnsigned && rUnsigned)
5233 /* unsigned is easy */
5234 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5235 MOVA (aopGet (left, 0, FALSE, FALSE));
5236 emitcode ("div", "ab");
5237 aopPut (result, "a", 0);
5239 aopPut (result, zero, offset++);
5245 /* signed is a little bit more difficult */
5247 /* now sign adjust for both left & right */
5249 /* let's see what's needed: */
5250 /* apply negative sign during runtime */
5251 runtimeSign = FALSE;
5252 /* negative sign from literals */
5253 compiletimeSign = FALSE;
5257 if (AOP_TYPE(left) == AOP_LIT)
5259 /* signed literal */
5260 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5262 compiletimeSign = TRUE;
5265 /* signed but not literal */
5271 if (AOP_TYPE(right) == AOP_LIT)
5273 /* signed literal */
5274 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5276 compiletimeSign ^= TRUE;
5279 /* signed but not literal */
5283 /* initialize F0, which stores the runtime sign */
5286 if (compiletimeSign)
5287 emitcode ("setb", "F0"); /* set sign flag */
5289 emitcode ("clr", "F0"); /* reset sign flag */
5292 /* save the signs of the operands */
5293 if (AOP_TYPE(right) == AOP_LIT)
5295 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5297 if (!rUnsigned && val < 0)
5298 emitcode ("mov", "b,#0x%02x", -val);
5300 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5302 else /* ! literal */
5305 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5308 MOVA (aopGet (right, 0, FALSE, FALSE));
5309 lbl = newiTempLabel (NULL);
5310 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5311 emitcode ("cpl", "F0"); /* complement sign flag */
5312 emitcode ("cpl", "a"); /* 2's complement */
5313 emitcode ("inc", "a");
5315 emitcode ("mov", "b,a");
5319 if (AOP_TYPE(left) == AOP_LIT)
5321 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5323 if (!lUnsigned && val < 0)
5324 emitcode ("mov", "a,#0x%02x", -val);
5326 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5328 else /* ! literal */
5330 MOVA (aopGet (left, 0, FALSE, FALSE));
5334 lbl = newiTempLabel (NULL);
5335 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5336 emitcode ("cpl", "F0"); /* complement sign flag */
5337 emitcode ("cpl", "a"); /* 2's complement */
5338 emitcode ("inc", "a");
5343 /* now the division */
5344 emitcode ("div", "ab");
5346 if (runtimeSign || compiletimeSign)
5348 lbl = newiTempLabel (NULL);
5350 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5351 emitcode ("cpl", "a"); /* lsb 2's complement */
5352 emitcode ("inc", "a");
5355 accuse = aopPut (result, "a", 0);
5358 /* msb is 0x00 or 0xff depending on the sign */
5363 emitcode ("push", "acc");
5366 emitcode ("mov", "c,F0");
5367 emitcode ("subb", "a,acc");
5369 aopPut (result, "a", offset++);
5371 else /* compiletimeSign */
5373 if (aopPutUsesAcc (result, "#0xFF", offset))
5375 emitcode ("push", "acc");
5379 aopPut (result, "#0xff", offset++);
5385 aopPut (result, "a", 0);
5387 aopPut (result, zero, offset++);
5391 emitcode ("pop", "acc");
5395 /*-----------------------------------------------------------------*/
5396 /* genDiv - generates code for division */
5397 /*-----------------------------------------------------------------*/
5401 operand *left = IC_LEFT (ic);
5402 operand *right = IC_RIGHT (ic);
5403 operand *result = IC_RESULT (ic);
5405 D (emitcode (";", "genDiv"));
5407 /* assign the amsops */
5408 aopOp (left, ic, FALSE);
5409 aopOp (right, ic, FALSE);
5410 aopOp (result, ic, TRUE);
5412 /* special cases first */
5414 if (AOP_TYPE (left) == AOP_CRY &&
5415 AOP_TYPE (right) == AOP_CRY)
5417 genDivbits (left, right, result);
5421 /* if both are of size == 1 */
5422 if (AOP_SIZE (left) == 1 &&
5423 AOP_SIZE (right) == 1)
5425 genDivOneByte (left, right, result);
5429 /* should have been converted to function call */
5432 freeAsmop (result, NULL, ic, TRUE);
5433 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5434 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5437 /*-----------------------------------------------------------------*/
5438 /* genModbits :- modulus of bits */
5439 /*-----------------------------------------------------------------*/
5441 genModbits (operand * left,
5448 D (emitcode (";", "genModbits"));
5452 /* the result must be bit */
5453 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5454 l = aopGet (left, 0, FALSE, FALSE);
5458 emitcode ("div", "ab");
5459 emitcode ("mov", "a,b");
5460 emitcode ("rrc", "a");
5464 aopPut (result, "c", 0);
5467 /*-----------------------------------------------------------------*/
5468 /* genModOneByte : 8 bit modulus */
5469 /*-----------------------------------------------------------------*/
5471 genModOneByte (operand * left,
5475 bool lUnsigned, rUnsigned, pushedB;
5476 bool runtimeSign, compiletimeSign;
5480 D (emitcode (";", "genModOneByte"));
5482 size = AOP_SIZE (result) - 1;
5484 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5485 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5487 /* if right is a literal, check it for 2^n */
5488 if (AOP_TYPE(right) == AOP_LIT)
5490 unsigned char val = abs((int) operandLitValue(right));
5491 symbol *lbl2 = NULL;
5495 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5504 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5505 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5506 /* because iCode should have been changed to genAnd */
5507 /* see file "SDCCopt.c", function "convertToFcall()" */
5509 MOVA (aopGet (left, 0, FALSE, FALSE));
5510 emitcode ("mov", "c,acc.7");
5511 emitcode ("anl", "a,#0x%02x", val - 1);
5512 lbl = newiTempLabel (NULL);
5513 emitcode ("jz", "%05d$", (lbl->key + 100));
5514 emitcode ("jnc", "%05d$", (lbl->key + 100));
5515 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5521 aopPut (result, "a", 0);
5523 aopPut (result, "#0xff", offs2++);
5524 lbl2 = newiTempLabel (NULL);
5525 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5528 aopPut (result, "a", 0);
5530 aopPut (result, zero, offset++);
5544 /* signed or unsigned */
5545 if (lUnsigned && rUnsigned)
5547 /* unsigned is easy */
5548 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5549 MOVA (aopGet (left, 0, FALSE, FALSE));
5550 emitcode ("div", "ab");
5551 aopPut (result, "b", 0);
5553 aopPut (result, zero, offset++);
5559 /* signed is a little bit more difficult */
5561 /* now sign adjust for both left & right */
5563 /* modulus: sign of the right operand has no influence on the result! */
5564 if (AOP_TYPE(right) == AOP_LIT)
5566 signed char val = (char) operandLitValue(right);
5568 if (!rUnsigned && val < 0)
5569 emitcode ("mov", "b,#0x%02x", -val);
5571 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5573 else /* not literal */
5576 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5579 MOVA (aopGet (right, 0, FALSE, FALSE));
5580 lbl = newiTempLabel (NULL);
5581 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5582 emitcode ("cpl", "a"); /* 2's complement */
5583 emitcode ("inc", "a");
5585 emitcode ("mov", "b,a");
5589 /* let's see what's needed: */
5590 /* apply negative sign during runtime */
5591 runtimeSign = FALSE;
5592 /* negative sign from literals */
5593 compiletimeSign = FALSE;
5595 /* sign adjust left side */
5596 if (AOP_TYPE(left) == AOP_LIT)
5598 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5600 if (!lUnsigned && val < 0)
5602 compiletimeSign = TRUE; /* set sign flag */
5603 emitcode ("mov", "a,#0x%02x", -val);
5606 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5608 else /* ! literal */
5610 MOVA (aopGet (left, 0, FALSE, FALSE));
5615 emitcode ("clr", "F0"); /* clear sign flag */
5617 lbl = newiTempLabel (NULL);
5618 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5619 emitcode ("setb", "F0"); /* set sign flag */
5620 emitcode ("cpl", "a"); /* 2's complement */
5621 emitcode ("inc", "a");
5626 /* now the modulus */
5627 emitcode ("div", "ab");
5629 if (runtimeSign || compiletimeSign)
5631 emitcode ("mov", "a,b");
5632 lbl = newiTempLabel (NULL);
5634 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5635 emitcode ("cpl", "a"); /* 2's complement */
5636 emitcode ("inc", "a");
5639 aopPut (result, "a", 0);
5642 /* msb is 0x00 or 0xff depending on the sign */
5645 emitcode ("mov", "c,F0");
5646 emitcode ("subb", "a,acc");
5648 aopPut (result, "a", offset++);
5650 else /* compiletimeSign */
5652 aopPut (result, "#0xff", offset++);
5657 aopPut (result, "b", 0);
5659 aopPut (result, zero, offset++);
5665 /*-----------------------------------------------------------------*/
5666 /* genMod - generates code for division */
5667 /*-----------------------------------------------------------------*/
5671 operand *left = IC_LEFT (ic);
5672 operand *right = IC_RIGHT (ic);
5673 operand *result = IC_RESULT (ic);
5675 D (emitcode (";", "genMod"));
5677 /* assign the asmops */
5678 aopOp (left, ic, FALSE);
5679 aopOp (right, ic, FALSE);
5680 aopOp (result, ic, TRUE);
5682 /* special cases first */
5684 if (AOP_TYPE (left) == AOP_CRY &&
5685 AOP_TYPE (right) == AOP_CRY)
5687 genModbits (left, right, result);
5691 /* if both are of size == 1 */
5692 if (AOP_SIZE (left) == 1 &&
5693 AOP_SIZE (right) == 1)
5695 genModOneByte (left, right, result);
5699 /* should have been converted to function call */
5703 freeAsmop (result, NULL, ic, TRUE);
5704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 /*-----------------------------------------------------------------*/
5709 /* genIfxJump :- will create a jump depending on the ifx */
5710 /*-----------------------------------------------------------------*/
5712 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5715 symbol *tlbl = newiTempLabel (NULL);
5718 D (emitcode (";", "genIfxJump"));
5720 /* if true label then we jump if condition
5724 jlbl = IC_TRUE (ic);
5725 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5726 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5730 /* false label is present */
5731 jlbl = IC_FALSE (ic);
5732 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5733 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5735 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5736 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5738 emitcode (inst, "%05d$", tlbl->key + 100);
5739 freeForBranchAsmop (result);
5740 freeForBranchAsmop (right);
5741 freeForBranchAsmop (left);
5742 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5745 /* mark the icode as generated */
5749 /*-----------------------------------------------------------------*/
5750 /* genCmp :- greater or less than comparison */
5751 /*-----------------------------------------------------------------*/
5753 genCmp (operand * left, operand * right,
5754 operand * result, iCode * ifx, int sign, iCode *ic)
5756 int size, offset = 0;
5757 unsigned long lit = 0L;
5760 D (emitcode (";", "genCmp"));
5762 /* if left & right are bit variables */
5763 if (AOP_TYPE (left) == AOP_CRY &&
5764 AOP_TYPE (right) == AOP_CRY)
5766 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5767 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5771 /* subtract right from left if at the
5772 end the carry flag is set then we know that
5773 left is greater than right */
5774 size = max (AOP_SIZE (left), AOP_SIZE (right));
5776 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5777 if ((size == 1) && !sign &&
5778 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5780 symbol *lbl = newiTempLabel (NULL);
5781 emitcode ("cjne", "%s,%s,%05d$",
5782 aopGet (left, offset, FALSE, FALSE),
5783 aopGet (right, offset, FALSE, FALSE),
5789 if (AOP_TYPE (right) == AOP_LIT)
5791 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5792 /* optimize if(x < 0) or if(x >= 0) */
5801 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5802 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5804 genIfxJump (ifx, "acc.7", left, right, result);
5805 freeAsmop (right, NULL, ic, TRUE);
5806 freeAsmop (left, NULL, ic, TRUE);
5812 emitcode ("rlc", "a");
5819 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5820 while (size && (bytelit == 0))
5823 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5829 MOVA (aopGet (left, offset, FALSE, FALSE));
5830 if (sign && size == 0)
5832 emitcode ("xrl", "a,#0x80");
5833 emitcode ("subb", "a,#0x%02x",
5834 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5838 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5848 bool pushedB = FALSE;
5849 rightInB = aopGetUsesAcc(right, offset);
5853 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5855 MOVA (aopGet (left, offset, FALSE, FALSE));
5856 if (sign && size == 0)
5858 emitcode ("xrl", "a,#0x80");
5863 MOVB (aopGet (right, offset, FALSE, FALSE));
5865 emitcode ("xrl", "b,#0x80");
5866 emitcode ("subb", "a,b");
5871 emitcode ("subb", "a,b");
5873 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5885 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5891 /* if the result is used in the next
5892 ifx conditional branch then generate
5893 code a little differently */
5896 genIfxJump (ifx, "c", NULL, NULL, result);
5902 /* leave the result in acc */
5906 /*-----------------------------------------------------------------*/
5907 /* genCmpGt :- greater than comparison */
5908 /*-----------------------------------------------------------------*/
5910 genCmpGt (iCode * ic, iCode * ifx)
5912 operand *left, *right, *result;
5913 sym_link *letype, *retype;
5916 D (emitcode (";", "genCmpGt"));
5918 left = IC_LEFT (ic);
5919 right = IC_RIGHT (ic);
5920 result = IC_RESULT (ic);
5922 letype = getSpec (operandType (left));
5923 retype = getSpec (operandType (right));
5924 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5925 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5926 /* assign the amsops */
5927 aopOp (result, ic, TRUE);
5928 aopOp (left, ic, FALSE);
5929 aopOp (right, ic, FALSE);
5931 genCmp (right, left, result, ifx, sign, ic);
5933 freeAsmop (result, NULL, ic, TRUE);
5936 /*-----------------------------------------------------------------*/
5937 /* genCmpLt - less than comparisons */
5938 /*-----------------------------------------------------------------*/
5940 genCmpLt (iCode * ic, iCode * ifx)
5942 operand *left, *right, *result;
5943 sym_link *letype, *retype;
5946 D (emitcode (";", "genCmpLt"));
5948 left = IC_LEFT (ic);
5949 right = IC_RIGHT (ic);
5950 result = IC_RESULT (ic);
5952 letype = getSpec (operandType (left));
5953 retype = getSpec (operandType (right));
5954 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5955 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5956 /* assign the amsops */
5957 aopOp (result, ic, TRUE);
5958 aopOp (left, ic, FALSE);
5959 aopOp (right, ic, FALSE);
5961 genCmp (left, right, result, ifx, sign, ic);
5963 freeAsmop (result, NULL, ic, TRUE);
5966 /*-----------------------------------------------------------------*/
5967 /* gencjneshort - compare and jump if not equal */
5968 /*-----------------------------------------------------------------*/
5970 gencjneshort (operand * left, operand * right, symbol * lbl)
5972 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5974 unsigned long lit = 0L;
5976 D (emitcode (";", "gencjneshort"));
5978 /* if the left side is a literal or
5979 if the right is in a pointer register and left
5981 if ((AOP_TYPE (left) == AOP_LIT) ||
5982 (AOP_TYPE (left) == AOP_IMMD) ||
5983 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5990 if (AOP_TYPE (right) == AOP_LIT)
5991 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5993 /* if the right side is a literal then anything goes */
5994 if (AOP_TYPE (right) == AOP_LIT &&
5995 AOP_TYPE (left) != AOP_DIR &&
5996 AOP_TYPE (left) != AOP_IMMD)
6000 emitcode ("cjne", "%s,%s,%05d$",
6001 aopGet (left, offset, FALSE, FALSE),
6002 aopGet (right, offset, FALSE, FALSE),
6008 /* if the right side is in a register or in direct space or
6009 if the left is a pointer register & right is not */
6010 else if (AOP_TYPE (right) == AOP_REG ||
6011 AOP_TYPE (right) == AOP_DIR ||
6012 AOP_TYPE (right) == AOP_LIT ||
6013 AOP_TYPE (right) == AOP_IMMD ||
6014 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6015 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6019 MOVA (aopGet (left, offset, FALSE, FALSE));
6020 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6021 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6022 emitcode ("jnz", "%05d$", lbl->key + 100);
6024 emitcode ("cjne", "a,%s,%05d$",
6025 aopGet (right, offset, FALSE, TRUE),
6032 /* right is a pointer reg need both a & b */
6035 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6036 wassertl(!BINUSE, "B was in use");
6037 MOVB (aopGet (left, offset, FALSE, FALSE));
6038 MOVA (aopGet (right, offset, FALSE, FALSE));
6039 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6045 /*-----------------------------------------------------------------*/
6046 /* gencjne - compare and jump if not equal */
6047 /*-----------------------------------------------------------------*/
6049 gencjne (operand * left, operand * right, symbol * lbl)
6051 symbol *tlbl = newiTempLabel (NULL);
6053 D (emitcode (";", "gencjne"));
6055 gencjneshort (left, right, lbl);
6057 emitcode ("mov", "a,%s", one);
6058 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6060 emitcode ("clr", "a");
6064 /*-----------------------------------------------------------------*/
6065 /* genCmpEq - generates code for equal to */
6066 /*-----------------------------------------------------------------*/
6068 genCmpEq (iCode * ic, iCode * ifx)
6070 bool swappedLR = FALSE;
6071 operand *left, *right, *result;
6073 D (emitcode (";", "genCmpEq"));
6075 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6076 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6077 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6079 /* if literal, literal on the right or
6080 if the right is in a pointer register and left
6082 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6083 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6085 operand *t = IC_RIGHT (ic);
6086 IC_RIGHT (ic) = IC_LEFT (ic);
6091 if (ifx && !AOP_SIZE (result))
6094 /* if they are both bit variables */
6095 if (AOP_TYPE (left) == AOP_CRY &&
6096 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6098 if (AOP_TYPE (right) == AOP_LIT)
6100 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6103 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6104 emitcode ("cpl", "c");
6108 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6112 emitcode ("clr", "c");
6114 /* AOP_TYPE(right) == AOP_CRY */
6118 symbol *lbl = newiTempLabel (NULL);
6119 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6120 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6121 emitcode ("cpl", "c");
6124 /* if true label then we jump if condition
6126 tlbl = newiTempLabel (NULL);
6129 emitcode ("jnc", "%05d$", tlbl->key + 100);
6130 freeForBranchAsmop (result);
6131 freeForBranchAsmop (right);
6132 freeForBranchAsmop (left);
6133 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6137 emitcode ("jc", "%05d$", tlbl->key + 100);
6138 freeForBranchAsmop (result);
6139 freeForBranchAsmop (right);
6140 freeForBranchAsmop (left);
6141 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6147 tlbl = newiTempLabel (NULL);
6148 gencjneshort (left, right, tlbl);
6151 freeForBranchAsmop (result);
6152 freeForBranchAsmop (right);
6153 freeForBranchAsmop (left);
6154 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6159 symbol *lbl = newiTempLabel (NULL);
6160 emitcode ("sjmp", "%05d$", lbl->key + 100);
6162 freeForBranchAsmop (result);
6163 freeForBranchAsmop (right);
6164 freeForBranchAsmop (left);
6165 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6169 /* mark the icode as generated */
6174 /* if they are both bit variables */
6175 if (AOP_TYPE (left) == AOP_CRY &&
6176 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6178 if (AOP_TYPE (right) == AOP_LIT)
6180 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6184 emitcode ("cpl", "c");
6188 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6192 emitcode ("clr", "c");
6194 /* AOP_TYPE(right) == AOP_CRY */
6198 symbol *lbl = newiTempLabel (NULL);
6199 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6200 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6201 emitcode ("cpl", "c");
6205 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6212 genIfxJump (ifx, "c", left, right, result);
6215 /* if the result is used in an arithmetic operation
6216 then put the result in place */
6221 gencjne (left, right, newiTempLabel (NULL));
6222 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6224 aopPut (result, "a", 0);
6229 genIfxJump (ifx, "a", left, right, result);
6232 /* if the result is used in an arithmetic operation
6233 then put the result in place */
6234 if (AOP_TYPE (result) != AOP_CRY)
6236 /* leave the result in acc */
6240 freeAsmop (result, NULL, ic, TRUE);
6243 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6248 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6249 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6253 /*-----------------------------------------------------------------*/
6254 /* ifxForOp - returns the icode containing the ifx for operand */
6255 /*-----------------------------------------------------------------*/
6257 ifxForOp (operand * op, iCode * ic)
6259 /* if true symbol then needs to be assigned */
6260 if (IS_TRUE_SYMOP (op))
6263 /* if this has register type condition and
6264 the next instruction is ifx with the same operand
6265 and live to of the operand is upto the ifx only then */
6267 ic->next->op == IFX &&
6268 IC_COND (ic->next)->key == op->key &&
6269 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6275 /*-----------------------------------------------------------------*/
6276 /* hasInc - operand is incremented before any other use */
6277 /*-----------------------------------------------------------------*/
6279 hasInc (operand *op, iCode *ic, int osize)
6281 sym_link *type = operandType(op);
6282 sym_link *retype = getSpec (type);
6283 iCode *lic = ic->next;
6286 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6287 if (!IS_SYMOP(op)) return NULL;
6289 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6290 if (IS_AGGREGATE(type->next)) return NULL;
6291 if (osize != (isize = getSize(type->next))) return NULL;
6294 /* if operand of the form op = op + <sizeof *op> */
6295 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6296 isOperandEqual(IC_RESULT(lic),op) &&
6297 isOperandLiteral(IC_RIGHT(lic)) &&
6298 operandLitValue(IC_RIGHT(lic)) == isize) {
6301 /* if the operand used or deffed */
6302 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6305 /* if GOTO or IFX */
6306 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6312 /*-----------------------------------------------------------------*/
6313 /* genAndOp - for && operation */
6314 /*-----------------------------------------------------------------*/
6316 genAndOp (iCode * ic)
6318 operand *left, *right, *result;
6321 D (emitcode (";", "genAndOp"));
6323 /* note here that && operations that are in an
6324 if statement are taken away by backPatchLabels
6325 only those used in arthmetic operations remain */
6326 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6327 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6328 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6330 /* if both are bit variables */
6331 if (AOP_TYPE (left) == AOP_CRY &&
6332 AOP_TYPE (right) == AOP_CRY)
6334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6335 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6340 tlbl = newiTempLabel (NULL);
6342 emitcode ("jz", "%05d$", tlbl->key + 100);
6348 freeAsmop (result, NULL, ic, TRUE);
6349 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6350 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6354 /*-----------------------------------------------------------------*/
6355 /* genOrOp - for || operation */
6356 /*-----------------------------------------------------------------*/
6358 genOrOp (iCode * ic)
6360 operand *left, *right, *result;
6363 D (emitcode (";", "genOrOp"));
6365 /* note here that || operations that are in an
6366 if statement are taken away by backPatchLabels
6367 only those used in arthmetic operations remain */
6368 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6369 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6370 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6372 /* if both are bit variables */
6373 if (AOP_TYPE (left) == AOP_CRY &&
6374 AOP_TYPE (right) == AOP_CRY)
6376 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6377 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6382 tlbl = newiTempLabel (NULL);
6384 emitcode ("jnz", "%05d$", tlbl->key + 100);
6390 freeAsmop (result, NULL, ic, TRUE);
6391 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6392 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6395 /*-----------------------------------------------------------------*/
6396 /* isLiteralBit - test if lit == 2^n */
6397 /*-----------------------------------------------------------------*/
6399 isLiteralBit (unsigned long lit)
6401 unsigned long pw[32] =
6402 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6403 0x100L, 0x200L, 0x400L, 0x800L,
6404 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6405 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6406 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6407 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6408 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6411 for (idx = 0; idx < 32; idx++)
6417 /*-----------------------------------------------------------------*/
6418 /* continueIfTrue - */
6419 /*-----------------------------------------------------------------*/
6421 continueIfTrue (iCode * ic)
6424 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6428 /*-----------------------------------------------------------------*/
6430 /*-----------------------------------------------------------------*/
6432 jumpIfTrue (iCode * ic)
6435 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6439 /*-----------------------------------------------------------------*/
6440 /* jmpTrueOrFalse - */
6441 /*-----------------------------------------------------------------*/
6443 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6445 // ugly but optimized by peephole
6448 symbol *nlbl = newiTempLabel (NULL);
6449 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6451 freeForBranchAsmop (result);
6452 freeForBranchAsmop (right);
6453 freeForBranchAsmop (left);
6454 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6459 freeForBranchAsmop (result);
6460 freeForBranchAsmop (right);
6461 freeForBranchAsmop (left);
6462 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6468 /*-----------------------------------------------------------------*/
6469 /* genAnd - code for and */
6470 /*-----------------------------------------------------------------*/
6472 genAnd (iCode * ic, iCode * ifx)
6474 operand *left, *right, *result;
6475 int size, offset = 0;
6476 unsigned long lit = 0L;
6480 D (emitcode (";", "genAnd"));
6482 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6483 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6484 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6487 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6489 AOP_TYPE (left), AOP_TYPE (right));
6490 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6492 AOP_SIZE (left), AOP_SIZE (right));
6495 /* if left is a literal & right is not then exchange them */
6496 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6497 AOP_NEEDSACC (left))
6499 operand *tmp = right;
6504 /* if result = right then exchange left and right */
6505 if (sameRegs (AOP (result), AOP (right)))
6507 operand *tmp = right;
6512 /* if right is bit then exchange them */
6513 if (AOP_TYPE (right) == AOP_CRY &&
6514 AOP_TYPE (left) != AOP_CRY)
6516 operand *tmp = right;
6520 if (AOP_TYPE (right) == AOP_LIT)
6521 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6523 size = AOP_SIZE (result);
6526 // result = bit & yy;
6527 if (AOP_TYPE (left) == AOP_CRY)
6529 // c = bit & literal;
6530 if (AOP_TYPE (right) == AOP_LIT)
6534 if (size && sameRegs (AOP (result), AOP (left)))
6537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6542 if (size && (AOP_TYPE (result) == AOP_CRY))
6544 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6547 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6552 emitcode ("clr", "c");
6557 if (AOP_TYPE (right) == AOP_CRY)
6560 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6561 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6566 MOVA (aopGet (right, 0, FALSE, FALSE));
6568 emitcode ("rrc", "a");
6569 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6577 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6578 genIfxJump (ifx, "c", left, right, result);
6582 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6583 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6584 if ((AOP_TYPE (right) == AOP_LIT) &&
6585 (AOP_TYPE (result) == AOP_CRY) &&
6586 (AOP_TYPE (left) != AOP_CRY))
6588 int posbit = isLiteralBit (lit);
6593 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6597 switch (posbit & 0x07)
6599 case 0: emitcode ("rrc", "a");
6601 case 7: emitcode ("rlc", "a");
6603 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6612 SNPRINTF (buffer, sizeof(buffer),
6613 "acc.%d", posbit & 0x07);
6614 genIfxJump (ifx, buffer, left, right, result);
6617 {// what is this case? just found it in ds390/gen.c
6618 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6625 symbol *tlbl = newiTempLabel (NULL);
6626 int sizel = AOP_SIZE (left);
6628 emitcode ("setb", "c");
6631 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6633 MOVA (aopGet (left, offset, FALSE, FALSE));
6635 if ((posbit = isLiteralBit (bytelit)) != 0)
6636 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6639 if (bytelit != 0x0FFL)
6640 emitcode ("anl", "a,%s",
6641 aopGet (right, offset, FALSE, TRUE));
6642 emitcode ("jnz", "%05d$", tlbl->key + 100);
6647 // bit = left & literal
6650 emitcode ("clr", "c");
6653 // if(left & literal)
6657 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6667 /* if left is same as result */
6668 if (sameRegs (AOP (result), AOP (left)))
6670 for (; size--; offset++)
6672 if (AOP_TYPE (right) == AOP_LIT)
6674 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6675 if (bytelit == 0x0FF)
6677 /* dummy read of volatile operand */
6678 if (isOperandVolatile (left, FALSE))
6679 MOVA (aopGet (left, offset, FALSE, FALSE));
6683 else if (bytelit == 0)
6685 aopPut (result, zero, offset);
6687 else if (IS_AOP_PREG (result))
6689 MOVA (aopGet (left, offset, FALSE, TRUE));
6690 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6691 aopPut (result, "a", offset);
6694 emitcode ("anl", "%s,%s",
6695 aopGet (left, offset, FALSE, TRUE),
6696 aopGet (right, offset, FALSE, FALSE));
6700 if (AOP_TYPE (left) == AOP_ACC)
6703 emitcode("mov", "a,b");
6704 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6706 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6708 MOVB (aopGet (left, offset, FALSE, FALSE));
6709 MOVA (aopGet (right, offset, FALSE, FALSE));
6710 emitcode ("anl", "a,b");
6711 aopPut (result, "a", offset);
6713 else if (aopGetUsesAcc (left, offset))
6715 MOVA (aopGet (left, offset, FALSE, FALSE));
6716 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6717 aopPut (result, "a", offset);
6721 MOVA (aopGet (right, offset, FALSE, FALSE));
6722 if (IS_AOP_PREG (result))
6724 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6725 aopPut (result, "a", offset);
6728 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6735 // left & result in different registers
6736 if (AOP_TYPE (result) == AOP_CRY)
6739 // if(size), result in bit
6740 // if(!size && ifx), conditional oper: if(left & right)
6741 symbol *tlbl = newiTempLabel (NULL);
6742 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6744 emitcode ("setb", "c");
6747 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6748 && AOP_TYPE(left)==AOP_ACC)
6751 emitcode("mov", "a,b");
6752 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6754 else if (AOP_TYPE(left)==AOP_ACC)
6758 bool pushedB = pushB ();
6759 emitcode("mov", "b,a");
6760 MOVA (aopGet (right, offset, FALSE, FALSE));
6761 emitcode("anl", "a,b");
6766 MOVA (aopGet (right, offset, FALSE, FALSE));
6767 emitcode("anl", "a,b");
6770 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6772 MOVB (aopGet (left, offset, FALSE, FALSE));
6773 MOVA (aopGet (right, offset, FALSE, FALSE));
6774 emitcode ("anl", "a,b");
6776 else if (aopGetUsesAcc (left, offset))
6778 MOVA (aopGet (left, offset, FALSE, FALSE));
6779 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6783 MOVA (aopGet (right, offset, FALSE, FALSE));
6784 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6787 emitcode ("jnz", "%05d$", tlbl->key + 100);
6797 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6803 for (; (size--); offset++)
6806 // result = left & right
6807 if (AOP_TYPE (right) == AOP_LIT)
6809 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6810 if (bytelit == 0x0FF)
6813 aopGet (left, offset, FALSE, FALSE),
6817 else if (bytelit == 0)
6819 /* dummy read of volatile operand */
6820 if (isOperandVolatile (left, FALSE))
6821 MOVA (aopGet (left, offset, FALSE, FALSE));
6822 aopPut (result, zero, offset);
6825 else if (AOP_TYPE (left) == AOP_ACC)
6829 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6830 aopPut (result, "a", offset);
6835 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6836 aopPut (result, "b", offset);
6841 // faster than result <- left, anl result,right
6842 // and better if result is SFR
6843 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6844 && AOP_TYPE(left)==AOP_ACC)
6847 emitcode("mov", "a,b");
6848 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6850 else if (AOP_TYPE(left)==AOP_ACC)
6854 bool pushedB = pushB ();
6855 emitcode("mov", "b,a");
6856 MOVA (aopGet (right, offset, FALSE, FALSE));
6857 emitcode("anl", "a,b");
6862 MOVA (aopGet (right, offset, FALSE, FALSE));
6863 emitcode("anl", "a,b");
6866 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6868 MOVB (aopGet (left, offset, FALSE, FALSE));
6869 MOVA (aopGet (right, offset, FALSE, FALSE));
6870 emitcode ("anl", "a,b");
6872 else if (aopGetUsesAcc (left, offset))
6874 MOVA (aopGet (left, offset, FALSE, FALSE));
6875 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6879 MOVA (aopGet (right, offset, FALSE, FALSE));
6880 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6882 aopPut (result, "a", offset);
6888 freeAsmop (result, NULL, ic, TRUE);
6889 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6890 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6893 /*-----------------------------------------------------------------*/
6894 /* genOr - code for or */
6895 /*-----------------------------------------------------------------*/
6897 genOr (iCode * ic, iCode * ifx)
6899 operand *left, *right, *result;
6900 int size, offset = 0;
6901 unsigned long lit = 0L;
6904 D (emitcode (";", "genOr"));
6906 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6907 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6908 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6911 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6913 AOP_TYPE (left), AOP_TYPE (right));
6914 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6916 AOP_SIZE (left), AOP_SIZE (right));
6919 /* if left is a literal & right is not then exchange them */
6920 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6921 AOP_NEEDSACC (left))
6923 operand *tmp = right;
6928 /* if result = right then exchange them */
6929 if (sameRegs (AOP (result), AOP (right)))
6931 operand *tmp = right;
6936 /* if right is bit then exchange them */
6937 if (AOP_TYPE (right) == AOP_CRY &&
6938 AOP_TYPE (left) != AOP_CRY)
6940 operand *tmp = right;
6944 if (AOP_TYPE (right) == AOP_LIT)
6945 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6947 size = AOP_SIZE (result);
6951 if (AOP_TYPE (left) == AOP_CRY)
6953 if (AOP_TYPE (right) == AOP_LIT)
6955 // c = bit | literal;
6958 // lit != 0 => result = 1
6959 if (AOP_TYPE (result) == AOP_CRY)
6962 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6964 continueIfTrue (ifx);
6967 emitcode ("setb", "c");
6971 // lit == 0 => result = left
6972 if (size && sameRegs (AOP (result), AOP (left)))
6974 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6979 if (AOP_TYPE (right) == AOP_CRY)
6982 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6983 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6988 symbol *tlbl = newiTempLabel (NULL);
6989 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6990 emitcode ("setb", "c");
6991 emitcode ("jb", "%s,%05d$",
6992 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6994 emitcode ("jnz", "%05d$", tlbl->key + 100);
6995 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6997 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7012 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7013 genIfxJump (ifx, "c", left, right, result);
7017 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7018 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7019 if ((AOP_TYPE (right) == AOP_LIT) &&
7020 (AOP_TYPE (result) == AOP_CRY) &&
7021 (AOP_TYPE (left) != AOP_CRY))
7027 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7029 continueIfTrue (ifx);
7034 // lit = 0, result = boolean(left)
7036 emitcode ("setb", "c");
7040 symbol *tlbl = newiTempLabel (NULL);
7041 emitcode ("jnz", "%05d$", tlbl->key + 100);
7047 genIfxJump (ifx, "a", left, right, result);
7055 /* if left is same as result */
7056 if (sameRegs (AOP (result), AOP (left)))
7058 for (; size--; offset++)
7060 if (AOP_TYPE (right) == AOP_LIT)
7062 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7065 /* dummy read of volatile operand */
7066 if (isOperandVolatile (left, FALSE))
7067 MOVA (aopGet (left, offset, FALSE, FALSE));
7071 else if (bytelit == 0x0FF)
7073 aopPut (result, "#0xFF", offset);
7075 else if (IS_AOP_PREG (left))
7077 MOVA (aopGet (left, offset, FALSE, TRUE));
7078 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7079 aopPut (result, "a", offset);
7083 emitcode ("orl", "%s,%s",
7084 aopGet (left, offset, FALSE, TRUE),
7085 aopGet (right, offset, FALSE, FALSE));
7090 if (AOP_TYPE (left) == AOP_ACC)
7093 emitcode("mov", "a,b");
7094 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7096 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7098 MOVB (aopGet (left, offset, FALSE, FALSE));
7099 MOVA (aopGet (right, offset, FALSE, FALSE));
7100 emitcode ("orl", "a,b");
7101 aopPut (result, "a", offset);
7103 else if (aopGetUsesAcc (left, offset))
7105 MOVA (aopGet (left, offset, FALSE, FALSE));
7106 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7107 aopPut (result, "a", offset);
7111 MOVA (aopGet (right, offset, FALSE, FALSE));
7112 if (IS_AOP_PREG (left))
7114 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7115 aopPut (result, "a", offset);
7119 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7127 // left & result in different registers
7128 if (AOP_TYPE (result) == AOP_CRY)
7131 // if(size), result in bit
7132 // if(!size && ifx), conditional oper: if(left | right)
7133 symbol *tlbl = newiTempLabel (NULL);
7134 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7136 emitcode ("setb", "c");
7139 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7140 && AOP_TYPE(left)==AOP_ACC)
7143 emitcode("mov", "a,b");
7144 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7146 else if (AOP_TYPE(left)==AOP_ACC)
7150 bool pushedB = pushB ();
7151 emitcode("mov", "b,a");
7152 MOVA (aopGet (right, offset, FALSE, FALSE));
7153 emitcode("orl", "a,b");
7158 MOVA (aopGet (right, offset, FALSE, FALSE));
7159 emitcode("orl", "a,b");
7162 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7164 MOVB (aopGet (left, offset, FALSE, FALSE));
7165 MOVA (aopGet (right, offset, FALSE, FALSE));
7166 emitcode ("orl", "a,b");
7168 else if (aopGetUsesAcc (left, offset))
7170 MOVA (aopGet (left, offset, FALSE, FALSE));
7171 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7175 MOVA (aopGet (right, offset, FALSE, FALSE));
7176 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7179 emitcode ("jnz", "%05d$", tlbl->key + 100);
7189 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7195 for (; (size--); offset++)
7198 // result = left | right
7199 if (AOP_TYPE (right) == AOP_LIT)
7201 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7205 aopGet (left, offset, FALSE, FALSE),
7209 else if (bytelit == 0x0FF)
7211 /* dummy read of volatile operand */
7212 if (isOperandVolatile (left, FALSE))
7213 MOVA (aopGet (left, offset, FALSE, FALSE));
7214 aopPut (result, "#0xFF", offset);
7218 // faster than result <- left, orl result,right
7219 // and better if result is SFR
7220 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7221 && AOP_TYPE(left)==AOP_ACC)
7224 emitcode("mov", "a,b");
7225 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7227 else if (AOP_TYPE(left)==AOP_ACC)
7231 bool pushedB = pushB ();
7232 emitcode("mov", "b,a");
7233 MOVA (aopGet (right, offset, FALSE, FALSE));
7234 emitcode("orl", "a,b");
7239 MOVA (aopGet (right, offset, FALSE, FALSE));
7240 emitcode("orl", "a,b");
7243 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7245 MOVB (aopGet (left, offset, FALSE, FALSE));
7246 MOVA (aopGet (right, offset, FALSE, FALSE));
7247 emitcode ("orl", "a,b");
7249 else if (aopGetUsesAcc (left, offset))
7251 MOVA (aopGet (left, offset, FALSE, FALSE));
7252 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7256 MOVA (aopGet (right, offset, FALSE, FALSE));
7257 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7259 aopPut (result, "a", offset);
7265 freeAsmop (result, NULL, ic, TRUE);
7266 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7270 /*-----------------------------------------------------------------*/
7271 /* genXor - code for xclusive or */
7272 /*-----------------------------------------------------------------*/
7274 genXor (iCode * ic, iCode * ifx)
7276 operand *left, *right, *result;
7277 int size, offset = 0;
7278 unsigned long lit = 0L;
7281 D (emitcode (";", "genXor"));
7283 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7284 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7285 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7288 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7290 AOP_TYPE (left), AOP_TYPE (right));
7291 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7293 AOP_SIZE (left), AOP_SIZE (right));
7296 /* if left is a literal & right is not ||
7297 if left needs acc & right does not */
7298 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7299 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7301 operand *tmp = right;
7306 /* if result = right then exchange them */
7307 if (sameRegs (AOP (result), AOP (right)))
7309 operand *tmp = right;
7314 /* if right is bit then exchange them */
7315 if (AOP_TYPE (right) == AOP_CRY &&
7316 AOP_TYPE (left) != AOP_CRY)
7318 operand *tmp = right;
7322 if (AOP_TYPE (right) == AOP_LIT)
7323 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7325 size = AOP_SIZE (result);
7329 if (AOP_TYPE (left) == AOP_CRY)
7331 if (AOP_TYPE (right) == AOP_LIT)
7333 // c = bit & literal;
7336 // lit>>1 != 0 => result = 1
7337 if (AOP_TYPE (result) == AOP_CRY)
7340 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7342 continueIfTrue (ifx);
7345 emitcode ("setb", "c");
7352 // lit == 0, result = left
7353 if (size && sameRegs (AOP (result), AOP (left)))
7355 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7359 // lit == 1, result = not(left)
7360 if (size && sameRegs (AOP (result), AOP (left)))
7362 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7368 emitcode ("cpl", "c");
7376 symbol *tlbl = newiTempLabel (NULL);
7377 if (AOP_TYPE (right) == AOP_CRY)
7380 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7384 int sizer = AOP_SIZE (right);
7386 // if val>>1 != 0, result = 1
7387 emitcode ("setb", "c");
7390 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7392 // test the msb of the lsb
7393 emitcode ("anl", "a,#0xfe");
7394 emitcode ("jnz", "%05d$", tlbl->key + 100);
7398 emitcode ("rrc", "a");
7400 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7401 emitcode ("cpl", "c");
7409 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7410 genIfxJump (ifx, "c", left, right, result);
7414 /* if left is same as result */
7415 if (sameRegs (AOP (result), AOP (left)))
7417 for (; size--; offset++)
7419 if (AOP_TYPE (right) == AOP_LIT)
7421 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7424 /* dummy read of volatile operand */
7425 if (isOperandVolatile (left, FALSE))
7426 MOVA (aopGet (left, offset, FALSE, FALSE));
7430 else if (IS_AOP_PREG (left))
7432 MOVA (aopGet (left, offset, FALSE, TRUE));
7433 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7434 aopPut (result, "a", offset);
7438 emitcode ("xrl", "%s,%s",
7439 aopGet (left, offset, FALSE, TRUE),
7440 aopGet (right, offset, FALSE, FALSE));
7445 if (AOP_TYPE (left) == AOP_ACC)
7448 emitcode("mov", "a,b");
7449 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7451 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7453 MOVB (aopGet (left, offset, FALSE, FALSE));
7454 MOVA (aopGet (right, offset, FALSE, FALSE));
7455 emitcode ("xrl", "a,b");
7456 aopPut (result, "a", offset);
7458 else if (aopGetUsesAcc (left, offset))
7460 MOVA (aopGet (left, offset, FALSE, FALSE));
7461 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7462 aopPut (result, "a", offset);
7466 MOVA (aopGet (right, offset, FALSE, FALSE));
7467 if (IS_AOP_PREG (left))
7469 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7470 aopPut (result, "a", offset);
7473 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7480 // left & result in different registers
7481 if (AOP_TYPE (result) == AOP_CRY)
7484 // if(size), result in bit
7485 // if(!size && ifx), conditional oper: if(left ^ right)
7486 symbol *tlbl = newiTempLabel (NULL);
7487 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7490 emitcode ("setb", "c");
7493 if ((AOP_TYPE (right) == AOP_LIT) &&
7494 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7496 MOVA (aopGet (left, offset, FALSE, FALSE));
7498 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7499 && AOP_TYPE(left)==AOP_ACC)
7502 emitcode("mov", "a,b");
7503 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7505 else if (AOP_TYPE(left)==AOP_ACC)
7509 bool pushedB = pushB ();
7510 emitcode("mov", "b,a");
7511 MOVA (aopGet (right, offset, FALSE, FALSE));
7512 emitcode("xrl", "a,b");
7517 MOVA (aopGet (right, offset, FALSE, FALSE));
7518 emitcode("xrl", "a,b");
7521 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7523 MOVB (aopGet (left, offset, FALSE, FALSE));
7524 MOVA (aopGet (right, offset, FALSE, FALSE));
7525 emitcode ("xrl", "a,b");
7527 else if (aopGetUsesAcc (left, offset))
7529 MOVA (aopGet (left, offset, FALSE, FALSE));
7530 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7534 MOVA (aopGet (right, offset, FALSE, FALSE));
7535 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7538 emitcode ("jnz", "%05d$", tlbl->key + 100);
7548 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7552 for (; (size--); offset++)
7555 // result = left ^ right
7556 if (AOP_TYPE (right) == AOP_LIT)
7558 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7562 aopGet (left, offset, FALSE, FALSE),
7567 // faster than result <- left, xrl result,right
7568 // and better if result is SFR
7569 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7570 && AOP_TYPE(left)==AOP_ACC)
7573 emitcode("mov", "a,b");
7574 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7576 else if (AOP_TYPE(left)==AOP_ACC)
7580 bool pushedB = pushB ();
7581 emitcode("mov", "b,a");
7582 MOVA (aopGet (right, offset, FALSE, FALSE));
7583 emitcode("xrl", "a,b");
7588 MOVA (aopGet (right, offset, FALSE, FALSE));
7589 emitcode("xrl", "a,b");
7592 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7594 MOVB (aopGet (left, offset, FALSE, FALSE));
7595 MOVA (aopGet (right, offset, FALSE, FALSE));
7596 emitcode ("xrl", "a,b");
7598 else if (aopGetUsesAcc (left, offset))
7600 MOVA (aopGet (left, offset, FALSE, FALSE));
7601 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7605 MOVA (aopGet (right, offset, FALSE, FALSE));
7606 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7608 aopPut (result, "a", offset);
7614 freeAsmop (result, NULL, ic, TRUE);
7615 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7616 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7619 /*-----------------------------------------------------------------*/
7620 /* genInline - write the inline code out */
7621 /*-----------------------------------------------------------------*/
7623 genInline (iCode * ic)
7625 char *buffer, *bp, *bp1;
7627 D (emitcode (";", "genInline"));
7629 _G.inLine += (!options.asmpeep);
7631 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7633 /* emit each line as a code */
7644 /* Add \n for labels, not dirs such as c:\mydir */
7645 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7659 /* emitcode("",buffer); */
7660 _G.inLine -= (!options.asmpeep);
7663 /*-----------------------------------------------------------------*/
7664 /* genRRC - rotate right with carry */
7665 /*-----------------------------------------------------------------*/
7669 operand *left, *result;
7673 D (emitcode (";", "genRRC"));
7675 /* rotate right with carry */
7676 left = IC_LEFT (ic);
7677 result = IC_RESULT (ic);
7678 aopOp (left, ic, FALSE);
7679 aopOp (result, ic, FALSE);
7681 /* move it to the result */
7682 size = AOP_SIZE (result);
7684 if (size == 1) { /* special case for 1 byte */
7685 l = aopGet (left, offset, FALSE, FALSE);
7687 emitcode ("rr", "a");
7690 /* no need to clear carry, bit7 will be written later */
7693 l = aopGet (left, offset, FALSE, FALSE);
7695 emitcode ("rrc", "a");
7696 if (AOP_SIZE (result) > 1)
7697 aopPut (result, "a", offset--);
7699 /* now we need to put the carry into the
7700 highest order byte of the result */
7701 if (AOP_SIZE (result) > 1)
7703 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7706 emitcode ("mov", "acc.7,c");
7708 aopPut (result, "a", AOP_SIZE (result) - 1);
7709 freeAsmop (result, NULL, ic, TRUE);
7710 freeAsmop (left, NULL, ic, TRUE);
7713 /*-----------------------------------------------------------------*/
7714 /* genRLC - generate code for rotate left with carry */
7715 /*-----------------------------------------------------------------*/
7719 operand *left, *result;
7723 D (emitcode (";", "genRLC"));
7725 /* rotate right with carry */
7726 left = IC_LEFT (ic);
7727 result = IC_RESULT (ic);
7728 aopOp (left, ic, FALSE);
7729 aopOp (result, ic, FALSE);
7731 /* move it to the result */
7732 size = AOP_SIZE (result);
7736 l = aopGet (left, offset, FALSE, FALSE);
7738 if (size == 0) { /* special case for 1 byte */
7742 emitcode("rlc","a"); /* bit0 will be written later */
7743 if (AOP_SIZE (result) > 1)
7745 aopPut (result, "a", offset++);
7750 l = aopGet (left, offset, FALSE, FALSE);
7752 emitcode ("rlc", "a");
7753 if (AOP_SIZE (result) > 1)
7754 aopPut (result, "a", offset++);
7757 /* now we need to put the carry into the
7758 highest order byte of the result */
7759 if (AOP_SIZE (result) > 1)
7761 l = aopGet (result, 0, FALSE, FALSE);
7764 emitcode ("mov", "acc.0,c");
7766 aopPut (result, "a", 0);
7767 freeAsmop (result, NULL, ic, TRUE);
7768 freeAsmop (left, NULL, ic, TRUE);
7771 /*-----------------------------------------------------------------*/
7772 /* genGetHbit - generates code get highest order bit */
7773 /*-----------------------------------------------------------------*/
7775 genGetHbit (iCode * ic)
7777 operand *left, *result;
7779 D (emitcode (";", "genGetHbit"));
7781 left = IC_LEFT (ic);
7782 result = IC_RESULT (ic);
7783 aopOp (left, ic, FALSE);
7784 aopOp (result, ic, FALSE);
7786 /* get the highest order byte into a */
7787 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7788 if (AOP_TYPE (result) == AOP_CRY)
7790 emitcode ("rlc", "a");
7795 emitcode ("rl", "a");
7796 emitcode ("anl", "a,#0x01");
7800 freeAsmop (result, NULL, ic, TRUE);
7801 freeAsmop (left, NULL, ic, TRUE);
7804 /*-----------------------------------------------------------------*/
7805 /* genGetAbit - generates code get a single bit */
7806 /*-----------------------------------------------------------------*/
7808 genGetAbit (iCode * ic)
7810 operand *left, *right, *result;
7813 D (emitcode (";", "genGetAbit"));
7815 left = IC_LEFT (ic);
7816 right = IC_RIGHT (ic);
7817 result = IC_RESULT (ic);
7818 aopOp (left, ic, FALSE);
7819 aopOp (right, ic, FALSE);
7820 aopOp (result, ic, FALSE);
7822 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7824 /* get the needed byte into a */
7825 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7827 if (AOP_TYPE (result) == AOP_CRY)
7830 emitcode ("rlc", "a");
7831 else if ((shCount) == 0)
7832 emitcode ("rrc", "a");
7834 emitcode ("mov", "c,acc[%d]", shCount);
7842 emitcode ("rr", "a");
7845 emitcode ("rr", "a");
7848 emitcode ("anl", "a,#0x01");
7852 emitcode ("mov", "c,acc[%d]", shCount);
7853 emitcode ("clr", "a");
7854 emitcode ("rlc", "a");
7857 emitcode ("swap", "a");
7858 emitcode ("anl", "a,#0x01");
7861 emitcode ("rl", "a");
7864 emitcode ("rl", "a");
7865 emitcode ("anl", "a,#0x01");
7871 freeAsmop (result, NULL, ic, TRUE);
7872 freeAsmop (right, NULL, ic, TRUE);
7873 freeAsmop (left, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genGetByte - generates code get a single byte */
7878 /*-----------------------------------------------------------------*/
7880 genGetByte (iCode * ic)
7882 operand *left, *right, *result;
7885 D (emitcode (";", "genGetByte"));
7887 left = IC_LEFT (ic);
7888 right = IC_RIGHT (ic);
7889 result = IC_RESULT (ic);
7890 aopOp (left, ic, FALSE);
7891 aopOp (right, ic, FALSE);
7892 aopOp (result, ic, FALSE);
7894 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7896 aopGet (left, offset, FALSE, FALSE),
7899 freeAsmop (result, NULL, ic, TRUE);
7900 freeAsmop (right, NULL, ic, TRUE);
7901 freeAsmop (left, NULL, ic, TRUE);
7904 /*-----------------------------------------------------------------*/
7905 /* genGetWord - generates code get two bytes */
7906 /*-----------------------------------------------------------------*/
7908 genGetWord (iCode * ic)
7910 operand *left, *right, *result;
7913 D (emitcode (";", "genGetWord"));
7915 left = IC_LEFT (ic);
7916 right = IC_RIGHT (ic);
7917 result = IC_RESULT (ic);
7918 aopOp (left, ic, FALSE);
7919 aopOp (right, ic, FALSE);
7920 aopOp (result, ic, FALSE);
7922 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7924 aopGet (left, offset, FALSE, FALSE),
7927 aopGet (left, offset+1, FALSE, FALSE),
7930 freeAsmop (result, NULL, ic, TRUE);
7931 freeAsmop (right, NULL, ic, TRUE);
7932 freeAsmop (left, NULL, ic, TRUE);
7935 /*-----------------------------------------------------------------*/
7936 /* genSwap - generates code to swap nibbles or bytes */
7937 /*-----------------------------------------------------------------*/
7939 genSwap (iCode * ic)
7941 operand *left, *result;
7943 D(emitcode ("; genSwap",""));
7945 left = IC_LEFT (ic);
7946 result = IC_RESULT (ic);
7947 aopOp (left, ic, FALSE);
7948 aopOp (result, ic, FALSE);
7950 switch (AOP_SIZE (left))
7952 case 1: /* swap nibbles in byte */
7953 MOVA (aopGet (left, 0, FALSE, FALSE));
7954 emitcode ("swap", "a");
7955 aopPut (result, "a", 0);
7957 case 2: /* swap bytes in word */
7958 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7960 MOVA (aopGet (left, 0, FALSE, FALSE));
7961 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7962 aopPut (result, "a", 1);
7964 else if (operandsEqu (left, result))
7967 bool pushedB = FALSE, leftInB = FALSE;
7969 MOVA (aopGet (left, 0, FALSE, FALSE));
7970 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7973 emitcode ("mov", "b,a");
7977 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7978 aopPut (result, reg, 1);
7985 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7986 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7990 wassertl(FALSE, "unsupported SWAP operand size");
7993 freeAsmop (result, NULL, ic, TRUE);
7994 freeAsmop (left, NULL, ic, TRUE);
7997 /*-----------------------------------------------------------------*/
7998 /* AccRol - rotate left accumulator by known count */
7999 /*-----------------------------------------------------------------*/
8001 AccRol (int shCount)
8003 shCount &= 0x0007; // shCount : 0..7
8010 emitcode ("rl", "a");
8013 emitcode ("rl", "a");
8014 emitcode ("rl", "a");
8017 emitcode ("swap", "a");
8018 emitcode ("rr", "a");
8021 emitcode ("swap", "a");
8024 emitcode ("swap", "a");
8025 emitcode ("rl", "a");
8028 emitcode ("rr", "a");
8029 emitcode ("rr", "a");
8032 emitcode ("rr", "a");
8037 /*-----------------------------------------------------------------*/
8038 /* AccLsh - left shift accumulator by known count */
8039 /*-----------------------------------------------------------------*/
8041 AccLsh (int shCount)
8046 emitcode ("add", "a,acc");
8047 else if (shCount == 2)
8049 emitcode ("add", "a,acc");
8050 emitcode ("add", "a,acc");
8054 /* rotate left accumulator */
8056 /* and kill the lower order bits */
8057 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8062 /*-----------------------------------------------------------------*/
8063 /* AccRsh - right shift accumulator by known count */
8064 /*-----------------------------------------------------------------*/
8066 AccRsh (int shCount)
8073 emitcode ("rrc", "a");
8077 /* rotate right accumulator */
8078 AccRol (8 - shCount);
8079 /* and kill the higher order bits */
8080 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8085 /*-----------------------------------------------------------------*/
8086 /* AccSRsh - signed right shift accumulator by known count */
8087 /*-----------------------------------------------------------------*/
8089 AccSRsh (int shCount)
8096 emitcode ("mov", "c,acc.7");
8097 emitcode ("rrc", "a");
8099 else if (shCount == 2)
8101 emitcode ("mov", "c,acc.7");
8102 emitcode ("rrc", "a");
8103 emitcode ("mov", "c,acc.7");
8104 emitcode ("rrc", "a");
8108 tlbl = newiTempLabel (NULL);
8109 /* rotate right accumulator */
8110 AccRol (8 - shCount);
8111 /* and kill the higher order bits */
8112 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8113 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8114 emitcode ("orl", "a,#0x%02x",
8115 (unsigned char) ~SRMask[shCount]);
8121 /*-----------------------------------------------------------------*/
8122 /* shiftR1Left2Result - shift right one byte from left to result */
8123 /*-----------------------------------------------------------------*/
8125 shiftR1Left2Result (operand * left, int offl,
8126 operand * result, int offr,
8127 int shCount, int sign)
8129 MOVA (aopGet (left, offl, FALSE, FALSE));
8130 /* shift right accumulator */
8135 aopPut (result, "a", offr);
8138 /*-----------------------------------------------------------------*/
8139 /* shiftL1Left2Result - shift left one byte from left to result */
8140 /*-----------------------------------------------------------------*/
8142 shiftL1Left2Result (operand * left, int offl,
8143 operand * result, int offr, int shCount)
8146 l = aopGet (left, offl, FALSE, FALSE);
8148 /* shift left accumulator */
8150 aopPut (result, "a", offr);
8153 /*-----------------------------------------------------------------*/
8154 /* movLeft2Result - move byte from left to result */
8155 /*-----------------------------------------------------------------*/
8157 movLeft2Result (operand * left, int offl,
8158 operand * result, int offr, int sign)
8161 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8163 l = aopGet (left, offl, FALSE, FALSE);
8165 if (*l == '@' && (IS_AOP_PREG (result)))
8167 emitcode ("mov", "a,%s", l);
8168 aopPut (result, "a", offr);
8174 aopPut (result, l, offr);
8178 /* MSB sign in acc.7 ! */
8179 if (getDataSize (left) == offl + 1)
8182 aopPut (result, "a", offr);
8189 /*-----------------------------------------------------------------*/
8190 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8191 /*-----------------------------------------------------------------*/
8195 emitcode ("rrc", "a");
8196 emitcode ("xch", "a,%s", x);
8197 emitcode ("rrc", "a");
8198 emitcode ("xch", "a,%s", x);
8201 /*-----------------------------------------------------------------*/
8202 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8203 /*-----------------------------------------------------------------*/
8207 emitcode ("xch", "a,%s", x);
8208 emitcode ("rlc", "a");
8209 emitcode ("xch", "a,%s", x);
8210 emitcode ("rlc", "a");
8213 /*-----------------------------------------------------------------*/
8214 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8215 /*-----------------------------------------------------------------*/
8219 emitcode ("xch", "a,%s", x);
8220 emitcode ("add", "a,acc");
8221 emitcode ("xch", "a,%s", x);
8222 emitcode ("rlc", "a");
8225 /*-----------------------------------------------------------------*/
8226 /* AccAXLsh - left shift a:x by known count (0..7) */
8227 /*-----------------------------------------------------------------*/
8229 AccAXLsh (char *x, int shCount)
8244 case 5: // AAAAABBB:CCCCCDDD
8246 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8248 emitcode ("anl", "a,#0x%02x",
8249 SLMask[shCount]); // BBB00000:CCCCCDDD
8251 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8253 AccRol (shCount); // DDDCCCCC:BBB00000
8255 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8257 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8259 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8261 emitcode ("anl", "a,#0x%02x",
8262 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8264 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8266 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8269 case 6: // AAAAAABB:CCCCCCDD
8270 emitcode ("anl", "a,#0x%02x",
8271 SRMask[shCount]); // 000000BB:CCCCCCDD
8272 emitcode ("mov", "c,acc.0"); // c = B
8273 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8275 AccAXRrl1 (x); // BCCCCCCD:D000000B
8276 AccAXRrl1 (x); // BBCCCCCC:DD000000
8278 emitcode("rrc","a");
8279 emitcode("xch","a,%s", x);
8280 emitcode("rrc","a");
8281 emitcode("mov","c,acc.0"); //<< get correct bit
8282 emitcode("xch","a,%s", x);
8284 emitcode("rrc","a");
8285 emitcode("xch","a,%s", x);
8286 emitcode("rrc","a");
8287 emitcode("xch","a,%s", x);
8290 case 7: // a:x <<= 7
8292 emitcode ("anl", "a,#0x%02x",
8293 SRMask[shCount]); // 0000000B:CCCCCCCD
8295 emitcode ("mov", "c,acc.0"); // c = B
8297 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8299 AccAXRrl1 (x); // BCCCCCCC:D0000000
8307 /*-----------------------------------------------------------------*/
8308 /* AccAXRsh - right shift a:x known count (0..7) */
8309 /*-----------------------------------------------------------------*/
8311 AccAXRsh (char *x, int shCount)
8319 AccAXRrl1 (x); // 0->a:x
8324 AccAXRrl1 (x); // 0->a:x
8327 AccAXRrl1 (x); // 0->a:x
8332 case 5: // AAAAABBB:CCCCCDDD = a:x
8334 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8336 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8338 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8340 emitcode ("anl", "a,#0x%02x",
8341 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8343 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8345 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8347 emitcode ("anl", "a,#0x%02x",
8348 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8350 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8352 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8354 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8357 case 6: // AABBBBBB:CCDDDDDD
8359 emitcode ("mov", "c,acc.7");
8360 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8362 emitcode ("mov", "c,acc.7");
8363 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8365 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8367 emitcode ("anl", "a,#0x%02x",
8368 SRMask[shCount]); // 000000AA:BBBBBBCC
8371 case 7: // ABBBBBBB:CDDDDDDD
8373 emitcode ("mov", "c,acc.7"); // c = A
8375 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8377 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8379 emitcode ("anl", "a,#0x%02x",
8380 SRMask[shCount]); // 0000000A:BBBBBBBC
8388 /*-----------------------------------------------------------------*/
8389 /* AccAXRshS - right shift signed a:x known count (0..7) */
8390 /*-----------------------------------------------------------------*/
8392 AccAXRshS (char *x, int shCount)
8400 emitcode ("mov", "c,acc.7");
8401 AccAXRrl1 (x); // s->a:x
8405 emitcode ("mov", "c,acc.7");
8406 AccAXRrl1 (x); // s->a:x
8408 emitcode ("mov", "c,acc.7");
8409 AccAXRrl1 (x); // s->a:x
8414 case 5: // AAAAABBB:CCCCCDDD = a:x
8416 tlbl = newiTempLabel (NULL);
8417 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8419 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8421 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8423 emitcode ("anl", "a,#0x%02x",
8424 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8426 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8428 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8430 emitcode ("anl", "a,#0x%02x",
8431 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8433 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8435 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8437 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8439 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8440 emitcode ("orl", "a,#0x%02x",
8441 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8444 break; // SSSSAAAA:BBBCCCCC
8446 case 6: // AABBBBBB:CCDDDDDD
8448 tlbl = newiTempLabel (NULL);
8449 emitcode ("mov", "c,acc.7");
8450 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8452 emitcode ("mov", "c,acc.7");
8453 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8455 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8457 emitcode ("anl", "a,#0x%02x",
8458 SRMask[shCount]); // 000000AA:BBBBBBCC
8460 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8461 emitcode ("orl", "a,#0x%02x",
8462 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8466 case 7: // ABBBBBBB:CDDDDDDD
8468 tlbl = newiTempLabel (NULL);
8469 emitcode ("mov", "c,acc.7"); // c = A
8471 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8473 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8475 emitcode ("anl", "a,#0x%02x",
8476 SRMask[shCount]); // 0000000A:BBBBBBBC
8478 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8479 emitcode ("orl", "a,#0x%02x",
8480 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8489 /*-----------------------------------------------------------------*/
8490 /* shiftL2Left2Result - shift left two bytes from left to result */
8491 /*-----------------------------------------------------------------*/
8493 shiftL2Left2Result (operand * left, int offl,
8494 operand * result, int offr, int shCount)
8497 bool pushedB = FALSE;
8500 if (sameRegs (AOP (result), AOP (left)) &&
8501 ((offl + MSB16) == offr))
8503 /* don't crash result[offr] */
8504 MOVA (aopGet (left, offl, FALSE, FALSE));
8505 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8506 usedB = !strncmp(x, "b", 1);
8508 else if (aopGetUsesAcc (result, offr))
8510 movLeft2Result (left, offl, result, offr, 0);
8513 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8514 MOVA (aopGet (result, offr, FALSE, FALSE));
8515 emitcode ("xch", "a,b");
8520 movLeft2Result (left, offl, result, offr, 0);
8521 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8522 x = aopGet (result, offr, FALSE, FALSE);
8524 /* ax << shCount (x = lsb(result)) */
8525 AccAXLsh (x, shCount);
8528 emitcode ("xch", "a,b");
8529 aopPut (result, "a", offr);
8530 aopPut (result, "b", offr + MSB16);
8535 aopPut (result, "a", offr + MSB16);
8540 /*-----------------------------------------------------------------*/
8541 /* shiftR2Left2Result - shift right two bytes from left to result */
8542 /*-----------------------------------------------------------------*/
8544 shiftR2Left2Result (operand * left, int offl,
8545 operand * result, int offr,
8546 int shCount, int sign)
8549 bool pushedB = FALSE;
8552 if (sameRegs (AOP (result), AOP (left)) &&
8553 ((offl + MSB16) == offr))
8555 /* don't crash result[offr] */
8556 MOVA (aopGet (left, offl, FALSE, FALSE));
8557 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8558 usedB = !strncmp(x, "b", 1);
8560 else if (aopGetUsesAcc (result, offr))
8562 movLeft2Result (left, offl, result, offr, 0);
8565 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8566 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8571 movLeft2Result (left, offl, result, offr, 0);
8572 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8573 x = aopGet (result, offr, FALSE, FALSE);
8575 /* a:x >> shCount (x = lsb(result)) */
8577 AccAXRshS (x, shCount);
8579 AccAXRsh (x, shCount);
8582 emitcode ("xch", "a,b");
8583 aopPut (result, "a", offr);
8584 emitcode ("xch", "a,b");
8587 if (getDataSize (result) > 1)
8588 aopPut (result, "a", offr + MSB16);
8591 /*-----------------------------------------------------------------*/
8592 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8593 /*-----------------------------------------------------------------*/
8595 shiftLLeftOrResult (operand * left, int offl,
8596 operand * result, int offr, int shCount)
8598 MOVA (aopGet (left, offl, FALSE, FALSE));
8599 /* shift left accumulator */
8601 /* or with result */
8602 if (aopGetUsesAcc (result, offr))
8604 emitcode ("xch", "a,b");
8605 MOVA (aopGet (result, offr, FALSE, FALSE));
8606 emitcode ("orl", "a,b");
8610 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8612 /* back to result */
8613 aopPut (result, "a", offr);
8616 /*-----------------------------------------------------------------*/
8617 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8618 /*-----------------------------------------------------------------*/
8620 shiftRLeftOrResult (operand * left, int offl,
8621 operand * result, int offr, int shCount)
8623 MOVA (aopGet (left, offl, FALSE, FALSE));
8624 /* shift right accumulator */
8626 /* or with result */
8627 if (aopGetUsesAcc(result, offr))
8629 emitcode ("xch", "a,b");
8630 MOVA (aopGet (result, offr, FALSE, FALSE));
8631 emitcode ("orl", "a,b");
8635 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8637 /* back to result */
8638 aopPut (result, "a", offr);
8641 /*-----------------------------------------------------------------*/
8642 /* genlshOne - left shift a one byte quantity by known count */
8643 /*-----------------------------------------------------------------*/
8645 genlshOne (operand * result, operand * left, int shCount)
8647 D (emitcode (";", "genlshOne"));
8649 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8652 /*-----------------------------------------------------------------*/
8653 /* genlshTwo - left shift two bytes by known amount != 0 */
8654 /*-----------------------------------------------------------------*/
8656 genlshTwo (operand * result, operand * left, int shCount)
8660 D (emitcode (";", "genlshTwo"));
8662 size = getDataSize (result);
8664 /* if shCount >= 8 */
8672 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8674 movLeft2Result (left, LSB, result, MSB16, 0);
8676 aopPut (result, zero, LSB);
8679 /* 1 <= shCount <= 7 */
8683 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8685 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8689 /*-----------------------------------------------------------------*/
8690 /* shiftLLong - shift left one long from left to result */
8691 /* offl = LSB or MSB16 */
8692 /*-----------------------------------------------------------------*/
8694 shiftLLong (operand * left, operand * result, int offr)
8697 int size = AOP_SIZE (result);
8699 if (size >= LSB + offr)
8701 l = aopGet (left, LSB, FALSE, FALSE);
8703 emitcode ("add", "a,acc");
8704 if (sameRegs (AOP (left), AOP (result)) &&
8705 size >= MSB16 + offr && offr != LSB)
8706 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8708 aopPut (result, "a", LSB + offr);
8711 if (size >= MSB16 + offr)
8713 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8715 l = aopGet (left, MSB16, FALSE, FALSE);
8718 emitcode ("rlc", "a");
8719 if (sameRegs (AOP (left), AOP (result)) &&
8720 size >= MSB24 + offr && offr != LSB)
8721 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8723 aopPut (result, "a", MSB16 + offr);
8726 if (size >= MSB24 + offr)
8728 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8730 l = aopGet (left, MSB24, FALSE, FALSE);
8733 emitcode ("rlc", "a");
8734 if (sameRegs (AOP (left), AOP (result)) &&
8735 size >= MSB32 + offr && offr != LSB)
8736 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8738 aopPut (result, "a", MSB24 + offr);
8741 if (size > MSB32 + offr)
8743 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8745 l = aopGet (left, MSB32, FALSE, FALSE);
8748 emitcode ("rlc", "a");
8749 aopPut (result, "a", MSB32 + offr);
8752 aopPut (result, zero, LSB);
8755 /*-----------------------------------------------------------------*/
8756 /* genlshFour - shift four byte by a known amount != 0 */
8757 /*-----------------------------------------------------------------*/
8759 genlshFour (operand * result, operand * left, int shCount)
8763 D (emitcode (";", "genlshFour"));
8765 size = AOP_SIZE (result);
8767 /* if shifting more that 3 bytes */
8772 /* lowest order of left goes to the highest
8773 order of the destination */
8774 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8776 movLeft2Result (left, LSB, result, MSB32, 0);
8777 aopPut (result, zero, LSB);
8778 aopPut (result, zero, MSB16);
8779 aopPut (result, zero, MSB24);
8783 /* more than two bytes */
8784 else if (shCount >= 16)
8786 /* lower order two bytes goes to higher order two bytes */
8788 /* if some more remaining */
8790 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8793 movLeft2Result (left, MSB16, result, MSB32, 0);
8794 movLeft2Result (left, LSB, result, MSB24, 0);
8796 aopPut (result, zero, MSB16);
8797 aopPut (result, zero, LSB);
8801 /* if more than 1 byte */
8802 else if (shCount >= 8)
8804 /* lower order three bytes goes to higher order three bytes */
8809 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8811 movLeft2Result (left, LSB, result, MSB16, 0);
8817 movLeft2Result (left, MSB24, result, MSB32, 0);
8818 movLeft2Result (left, MSB16, result, MSB24, 0);
8819 movLeft2Result (left, LSB, result, MSB16, 0);
8820 aopPut (result, zero, LSB);
8822 else if (shCount == 1)
8823 shiftLLong (left, result, MSB16);
8826 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8827 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8828 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8829 aopPut (result, zero, LSB);
8834 /* 1 <= shCount <= 7 */
8835 else if (shCount <= 2)
8837 shiftLLong (left, result, LSB);
8839 shiftLLong (result, result, LSB);
8841 /* 3 <= shCount <= 7, optimize */
8844 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8845 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8846 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8850 /*-----------------------------------------------------------------*/
8851 /* genLeftShiftLiteral - left shifting by known count */
8852 /*-----------------------------------------------------------------*/
8854 genLeftShiftLiteral (operand * left,
8859 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8862 D (emitcode (";", "genLeftShiftLiteral"));
8864 freeAsmop (right, NULL, ic, TRUE);
8866 aopOp (left, ic, FALSE);
8867 aopOp (result, ic, FALSE);
8869 size = getSize (operandType (result));
8872 emitcode ("; shift left ", "result %d, left %d", size,
8876 /* I suppose that the left size >= result size */
8881 movLeft2Result (left, size, result, size, 0);
8884 else if (shCount >= (size * 8))
8888 aopPut (result, zero, size);
8896 genlshOne (result, left, shCount);
8900 genlshTwo (result, left, shCount);
8904 genlshFour (result, left, shCount);
8907 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8908 "*** ack! mystery literal shift!\n");
8912 freeAsmop (result, NULL, ic, TRUE);
8913 freeAsmop (left, NULL, ic, TRUE);
8916 /*-----------------------------------------------------------------*/
8917 /* genLeftShift - generates code for left shifting */
8918 /*-----------------------------------------------------------------*/
8920 genLeftShift (iCode * ic)
8922 operand *left, *right, *result;
8925 symbol *tlbl, *tlbl1;
8928 D (emitcode (";", "genLeftShift"));
8930 right = IC_RIGHT (ic);
8931 left = IC_LEFT (ic);
8932 result = IC_RESULT (ic);
8934 aopOp (right, ic, FALSE);
8936 /* if the shift count is known then do it
8937 as efficiently as possible */
8938 if (AOP_TYPE (right) == AOP_LIT)
8940 genLeftShiftLiteral (left, right, result, ic);
8944 /* shift count is unknown then we have to form
8945 a loop get the loop count in B : Note: we take
8946 only the lower order byte since shifting
8947 more that 32 bits make no sense anyway, ( the
8948 largest size of an object can be only 32 bits ) */
8951 MOVB (aopGet (right, 0, FALSE, FALSE));
8952 emitcode ("inc", "b");
8953 freeAsmop (right, NULL, ic, TRUE);
8954 aopOp (left, ic, FALSE);
8955 aopOp (result, ic, FALSE);
8957 /* now move the left to the result if they are not the same */
8958 if (!sameRegs (AOP (left), AOP (result)) &&
8959 AOP_SIZE (result) > 1)
8962 size = AOP_SIZE (result);
8966 l = aopGet (left, offset, FALSE, TRUE);
8967 if (*l == '@' && (IS_AOP_PREG (result)))
8970 emitcode ("mov", "a,%s", l);
8971 aopPut (result, "a", offset);
8974 aopPut (result, l, offset);
8979 tlbl = newiTempLabel (NULL);
8980 size = AOP_SIZE (result);
8982 tlbl1 = newiTempLabel (NULL);
8984 /* if it is only one byte then */
8987 symbol *tlbl1 = newiTempLabel (NULL);
8989 l = aopGet (left, 0, FALSE, FALSE);
8991 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8993 emitcode ("add", "a,acc");
8995 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8997 aopPut (result, "a", 0);
9001 reAdjustPreg (AOP (result));
9003 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9005 l = aopGet (result, offset, FALSE, FALSE);
9007 emitcode ("add", "a,acc");
9008 aopPut (result, "a", offset++);
9011 l = aopGet (result, offset, FALSE, FALSE);
9013 emitcode ("rlc", "a");
9014 aopPut (result, "a", offset++);
9016 reAdjustPreg (AOP (result));
9019 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9022 freeAsmop (result, NULL, ic, TRUE);
9023 freeAsmop (left, NULL, ic, TRUE);
9026 /*-----------------------------------------------------------------*/
9027 /* genrshOne - right shift a one byte quantity by known count */
9028 /*-----------------------------------------------------------------*/
9030 genrshOne (operand * result, operand * left,
9031 int shCount, int sign)
9033 D (emitcode (";", "genrshOne"));
9035 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9038 /*-----------------------------------------------------------------*/
9039 /* genrshTwo - right shift two bytes by known amount != 0 */
9040 /*-----------------------------------------------------------------*/
9042 genrshTwo (operand * result, operand * left,
9043 int shCount, int sign)
9045 D (emitcode (";", "genrshTwo"));
9047 /* if shCount >= 8 */
9052 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9054 movLeft2Result (left, MSB16, result, LSB, sign);
9055 addSign (result, MSB16, sign);
9058 /* 1 <= shCount <= 7 */
9060 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9063 /*-----------------------------------------------------------------*/
9064 /* shiftRLong - shift right one long from left to result */
9065 /* offl = LSB or MSB16 */
9066 /*-----------------------------------------------------------------*/
9068 shiftRLong (operand * left, int offl,
9069 operand * result, int sign)
9071 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9073 if (overlapping && offl>1)
9075 // we are in big trouble, but this shouldn't happen
9076 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9079 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9086 emitcode ("rlc", "a");
9087 emitcode ("subb", "a,acc");
9088 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9090 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9094 aopPut (result, "a", MSB32);
9095 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9100 if (aopPutUsesAcc (result, zero, MSB32))
9102 emitcode("xch", "a,b");
9103 aopPut (result, zero, MSB32);
9104 emitcode("xch", "a,b");
9108 aopPut (result, zero, MSB32);
9115 emitcode ("clr", "c");
9119 emitcode ("mov", "c,acc.7");
9122 emitcode ("rrc", "a");
9124 if (overlapping && offl==MSB16 &&
9125 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9127 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9131 aopPut (result, "a", MSB32 - offl);
9132 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9135 emitcode ("rrc", "a");
9136 if (overlapping && offl==MSB16 &&
9137 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9139 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9143 aopPut (result, "a", MSB24 - offl);
9144 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9147 emitcode ("rrc", "a");
9150 aopPut (result, "a", MSB16 - offl);
9155 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9157 xch_a_aopGet (left, LSB, FALSE, FALSE);
9161 aopPut (result, "a", MSB16 - offl);
9162 MOVA (aopGet (left, LSB, FALSE, FALSE));
9164 emitcode ("rrc", "a");
9165 aopPut (result, "a", LSB);
9169 /*-----------------------------------------------------------------*/
9170 /* genrshFour - shift four byte by a known amount != 0 */
9171 /*-----------------------------------------------------------------*/
9173 genrshFour (operand * result, operand * left,
9174 int shCount, int sign)
9176 D (emitcode (";", "genrshFour"));
9178 /* if shifting more that 3 bytes */
9183 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9185 movLeft2Result (left, MSB32, result, LSB, sign);
9186 addSign (result, MSB16, sign);
9188 else if (shCount >= 16)
9192 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9195 movLeft2Result (left, MSB24, result, LSB, 0);
9196 movLeft2Result (left, MSB32, result, MSB16, sign);
9198 addSign (result, MSB24, sign);
9200 else if (shCount >= 8)
9205 shiftRLong (left, MSB16, result, sign);
9207 else if (shCount == 0)
9209 movLeft2Result (left, MSB16, result, LSB, 0);
9210 movLeft2Result (left, MSB24, result, MSB16, 0);
9211 movLeft2Result (left, MSB32, result, MSB24, sign);
9212 addSign (result, MSB32, sign);
9216 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9217 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9218 /* the last shift is signed */
9219 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9220 addSign (result, MSB32, sign);
9225 /* 1 <= shCount <= 7 */
9228 shiftRLong (left, LSB, result, sign);
9230 shiftRLong (result, LSB, result, sign);
9234 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9235 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9236 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9241 /*-----------------------------------------------------------------*/
9242 /* genRightShiftLiteral - right shifting by known count */
9243 /*-----------------------------------------------------------------*/
9245 genRightShiftLiteral (operand * left,
9251 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9254 D (emitcode (";", "genRightShiftLiteral"));
9256 freeAsmop (right, NULL, ic, TRUE);
9258 aopOp (left, ic, FALSE);
9259 aopOp (result, ic, FALSE);
9262 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9266 size = getDataSize (left);
9267 /* test the LEFT size !!! */
9269 /* I suppose that the left size >= result size */
9272 size = getDataSize (result);
9274 movLeft2Result (left, size, result, size, 0);
9277 else if (shCount >= (size * 8))
9281 /* get sign in acc.7 */
9282 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9284 addSign (result, LSB, sign);
9291 genrshOne (result, left, shCount, sign);
9295 genrshTwo (result, left, shCount, sign);
9299 genrshFour (result, left, shCount, sign);
9305 freeAsmop (result, NULL, ic, TRUE);
9306 freeAsmop (left, NULL, ic, TRUE);
9309 /*-----------------------------------------------------------------*/
9310 /* genSignedRightShift - right shift of signed number */
9311 /*-----------------------------------------------------------------*/
9313 genSignedRightShift (iCode * ic)
9315 operand *right, *left, *result;
9318 symbol *tlbl, *tlbl1;
9321 D (emitcode (";", "genSignedRightShift"));
9323 /* we do it the hard way put the shift count in b
9324 and loop thru preserving the sign */
9326 right = IC_RIGHT (ic);
9327 left = IC_LEFT (ic);
9328 result = IC_RESULT (ic);
9330 aopOp (right, ic, FALSE);
9333 if (AOP_TYPE (right) == AOP_LIT)
9335 genRightShiftLiteral (left, right, result, ic, 1);
9338 /* shift count is unknown then we have to form
9339 a loop get the loop count in B : Note: we take
9340 only the lower order byte since shifting
9341 more that 32 bits make no sense anyway, ( the
9342 largest size of an object can be only 32 bits ) */
9345 MOVB (aopGet (right, 0, FALSE, FALSE));
9346 emitcode ("inc", "b");
9347 freeAsmop (right, NULL, ic, TRUE);
9348 aopOp (left, ic, FALSE);
9349 aopOp (result, ic, FALSE);
9351 /* now move the left to the result if they are not the
9353 if (!sameRegs (AOP (left), AOP (result)) &&
9354 AOP_SIZE (result) > 1)
9357 size = AOP_SIZE (result);
9361 l = aopGet (left, offset, FALSE, TRUE);
9362 if (*l == '@' && IS_AOP_PREG (result))
9365 emitcode ("mov", "a,%s", l);
9366 aopPut (result, "a", offset);
9369 aopPut (result, l, offset);
9374 /* mov the highest order bit to OVR */
9375 tlbl = newiTempLabel (NULL);
9376 tlbl1 = newiTempLabel (NULL);
9378 size = AOP_SIZE (result);
9380 MOVA (aopGet (left, offset, FALSE, FALSE));
9381 emitcode ("rlc", "a");
9382 emitcode ("mov", "ov,c");
9383 /* if it is only one byte then */
9386 l = aopGet (left, 0, FALSE, FALSE);
9388 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9390 emitcode ("mov", "c,ov");
9391 emitcode ("rrc", "a");
9393 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9395 aopPut (result, "a", 0);
9399 reAdjustPreg (AOP (result));
9400 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9402 emitcode ("mov", "c,ov");
9405 l = aopGet (result, offset, FALSE, FALSE);
9407 emitcode ("rrc", "a");
9408 aopPut (result, "a", offset--);
9410 reAdjustPreg (AOP (result));
9412 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9416 freeAsmop (result, NULL, ic, TRUE);
9417 freeAsmop (left, NULL, ic, TRUE);
9420 /*-----------------------------------------------------------------*/
9421 /* genRightShift - generate code for right shifting */
9422 /*-----------------------------------------------------------------*/
9424 genRightShift (iCode * ic)
9426 operand *right, *left, *result;
9430 symbol *tlbl, *tlbl1;
9433 D (emitcode (";", "genRightShift"));
9435 /* if signed then we do it the hard way preserve the
9436 sign bit moving it inwards */
9437 letype = getSpec (operandType (IC_LEFT (ic)));
9439 if (!SPEC_USIGN (letype))
9441 genSignedRightShift (ic);
9445 /* signed & unsigned types are treated the same : i.e. the
9446 signed is NOT propagated inwards : quoting from the
9447 ANSI - standard : "for E1 >> E2, is equivalent to division
9448 by 2**E2 if unsigned or if it has a non-negative value,
9449 otherwise the result is implementation defined ", MY definition
9450 is that the sign does not get propagated */
9452 right = IC_RIGHT (ic);
9453 left = IC_LEFT (ic);
9454 result = IC_RESULT (ic);
9456 aopOp (right, ic, FALSE);
9458 /* if the shift count is known then do it
9459 as efficiently as possible */
9460 if (AOP_TYPE (right) == AOP_LIT)
9462 genRightShiftLiteral (left, right, result, ic, 0);
9466 /* shift count is unknown then we have to form
9467 a loop get the loop count in B : Note: we take
9468 only the lower order byte since shifting
9469 more that 32 bits make no sense anyway, ( the
9470 largest size of an object can be only 32 bits ) */
9473 MOVB (aopGet (right, 0, FALSE, FALSE));
9474 emitcode ("inc", "b");
9475 freeAsmop (right, NULL, ic, TRUE);
9476 aopOp (left, ic, FALSE);
9477 aopOp (result, ic, FALSE);
9479 /* now move the left to the result if they are not the
9481 if (!sameRegs (AOP (left), AOP (result)) &&
9482 AOP_SIZE (result) > 1)
9484 size = AOP_SIZE (result);
9488 l = aopGet (left, offset, FALSE, TRUE);
9489 if (*l == '@' && IS_AOP_PREG (result))
9492 emitcode ("mov", "a,%s", l);
9493 aopPut (result, "a", offset);
9496 aopPut (result, l, offset);
9501 tlbl = newiTempLabel (NULL);
9502 tlbl1 = newiTempLabel (NULL);
9503 size = AOP_SIZE (result);
9506 /* if it is only one byte then */
9509 l = aopGet (left, 0, FALSE, FALSE);
9511 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9514 emitcode ("rrc", "a");
9516 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9518 aopPut (result, "a", 0);
9522 reAdjustPreg (AOP (result));
9523 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9528 l = aopGet (result, offset, FALSE, FALSE);
9530 emitcode ("rrc", "a");
9531 aopPut (result, "a", offset--);
9533 reAdjustPreg (AOP (result));
9536 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9540 freeAsmop (result, NULL, ic, TRUE);
9541 freeAsmop (left, NULL, ic, TRUE);
9544 /*-----------------------------------------------------------------*/
9545 /* emitPtrByteGet - emits code to get a byte into A through a */
9546 /* pointer register (R0, R1, or DPTR). The */
9547 /* original value of A can be preserved in B. */
9548 /*-----------------------------------------------------------------*/
9550 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9557 emitcode ("mov", "b,a");
9558 emitcode ("mov", "a,@%s", rname);
9563 emitcode ("mov", "b,a");
9564 emitcode ("movx", "a,@%s", rname);
9569 emitcode ("mov", "b,a");
9570 emitcode ("movx", "a,@dptr");
9575 emitcode ("mov", "b,a");
9576 emitcode ("clr", "a");
9577 emitcode ("movc", "a,@a+dptr");
9583 emitcode ("push", "b");
9584 emitcode ("push", "acc");
9586 emitcode ("lcall", "__gptrget");
9588 emitcode ("pop", "b");
9593 /*-----------------------------------------------------------------*/
9594 /* emitPtrByteSet - emits code to set a byte from src through a */
9595 /* pointer register (R0, R1, or DPTR). */
9596 /*-----------------------------------------------------------------*/
9598 emitPtrByteSet (char *rname, int p_type, char *src)
9607 emitcode ("mov", "@%s,a", rname);
9610 emitcode ("mov", "@%s,%s", rname, src);
9615 emitcode ("movx", "@%s,a", rname);
9620 emitcode ("movx", "@dptr,a");
9625 emitcode ("lcall", "__gptrput");
9630 /*-----------------------------------------------------------------*/
9631 /* genUnpackBits - generates code for unpacking bits */
9632 /*-----------------------------------------------------------------*/
9634 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9636 int offset = 0; /* result byte offset */
9637 int rsize; /* result size */
9638 int rlen = 0; /* remaining bitfield length */
9639 sym_link *etype; /* bitfield type information */
9640 int blen; /* bitfield length */
9641 int bstr; /* bitfield starting bit within byte */
9644 D(emitcode ("; genUnpackBits",""));
9646 etype = getSpec (operandType (result));
9647 rsize = getSize (operandType (result));
9648 blen = SPEC_BLEN (etype);
9649 bstr = SPEC_BSTR (etype);
9651 if (ifx && blen <= 8)
9653 emitPtrByteGet (rname, ptype, FALSE);
9656 SNPRINTF (buffer, sizeof(buffer),
9658 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9663 emitcode ("anl", "a,#0x%02x",
9664 (((unsigned char) -1) >> (8 - blen)) << bstr);
9665 genIfxJump (ifx, "a", NULL, NULL, NULL);
9671 /* If the bitfield length is less than a byte */
9674 emitPtrByteGet (rname, ptype, FALSE);
9676 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9677 if (!SPEC_USIGN (etype))
9679 /* signed bitfield */
9680 symbol *tlbl = newiTempLabel (NULL);
9682 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9683 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9686 aopPut (result, "a", offset++);
9690 /* Bit field did not fit in a byte. Copy all
9691 but the partial byte at the end. */
9692 for (rlen=blen;rlen>=8;rlen-=8)
9694 emitPtrByteGet (rname, ptype, FALSE);
9695 aopPut (result, "a", offset++);
9697 emitcode ("inc", "%s", rname);
9700 /* Handle the partial byte at the end */
9703 emitPtrByteGet (rname, ptype, FALSE);
9704 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9705 if (!SPEC_USIGN (etype))
9707 /* signed bitfield */
9708 symbol *tlbl = newiTempLabel (NULL);
9710 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9711 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9714 aopPut (result, "a", offset++);
9722 if (SPEC_USIGN (etype))
9726 /* signed bitfield: sign extension with 0x00 or 0xff */
9727 emitcode ("rlc", "a");
9728 emitcode ("subb", "a,acc");
9734 aopPut (result, source, offset++);
9739 /*-----------------------------------------------------------------*/
9740 /* genDataPointerGet - generates code when ptr offset is known */
9741 /*-----------------------------------------------------------------*/
9743 genDataPointerGet (operand * left,
9749 int size, offset = 0;
9751 D (emitcode (";", "genDataPointerGet"));
9753 aopOp (result, ic, TRUE);
9755 /* get the string representation of the name */
9756 l = aopGet (left, 0, FALSE, TRUE);
9758 size = AOP_SIZE (result);
9763 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9767 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9769 aopPut (result, buffer, offset++);
9772 freeAsmop (result, NULL, ic, TRUE);
9773 freeAsmop (left, NULL, ic, TRUE);
9776 /*-----------------------------------------------------------------*/
9777 /* genNearPointerGet - emitcode for near pointer fetch */
9778 /*-----------------------------------------------------------------*/
9780 genNearPointerGet (operand * left,
9789 sym_link *rtype, *retype;
9790 sym_link *ltype = operandType (left);
9793 D (emitcode (";", "genNearPointerGet"));
9795 rtype = operandType (result);
9796 retype = getSpec (rtype);
9798 aopOp (left, ic, FALSE);
9800 /* if left is rematerialisable and
9801 result is not bitfield variable type and
9802 the left is pointer to data space i.e
9803 lower 128 bytes of space */
9804 if (AOP_TYPE (left) == AOP_IMMD &&
9805 !IS_BITFIELD (retype) &&
9806 DCL_TYPE (ltype) == POINTER)
9808 genDataPointerGet (left, result, ic);
9812 /* if the value is already in a pointer register
9813 then don't need anything more */
9814 if (!AOP_INPREG (AOP (left)))
9816 if (IS_AOP_PREG (left))
9818 // Aha, it is a pointer, just in disguise.
9819 rname = aopGet (left, 0, FALSE, FALSE);
9822 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9823 __FILE__, __LINE__);
9828 emitcode ("mov", "a%s,%s", rname + 1, rname);
9829 rname++; // skip the '@'.
9834 /* otherwise get a free pointer register */
9836 preg = getFreePtr (ic, &aop, FALSE);
9837 emitcode ("mov", "%s,%s",
9839 aopGet (left, 0, FALSE, TRUE));
9844 rname = aopGet (left, 0, FALSE, FALSE);
9846 //aopOp (result, ic, FALSE);
9847 aopOp (result, ic, result?TRUE:FALSE);
9849 /* if bitfield then unpack the bits */
9850 if (IS_BITFIELD (retype))
9851 genUnpackBits (result, rname, POINTER, ifx);
9854 /* we have can just get the values */
9855 int size = AOP_SIZE (result);
9860 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9863 emitcode ("mov", "a,@%s", rname);
9865 aopPut (result, "a", offset);
9869 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9870 aopPut (result, buffer, offset);
9874 emitcode ("inc", "%s", rname);
9878 /* now some housekeeping stuff */
9879 if (aop) /* we had to allocate for this iCode */
9881 if (pi) { /* post increment present */
9882 aopPut (left, rname, 0);
9884 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9888 /* we did not allocate which means left
9889 already in a pointer register, then
9890 if size > 0 && this could be used again
9891 we have to point it back to where it
9893 if ((AOP_SIZE (result) > 1 &&
9894 !OP_SYMBOL (left)->remat &&
9895 (OP_SYMBOL (left)->liveTo > ic->seq ||
9899 int size = AOP_SIZE (result) - 1;
9901 emitcode ("dec", "%s", rname);
9905 if (ifx && !ifx->generated)
9907 genIfxJump (ifx, "a", left, NULL, result);
9911 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9912 freeAsmop (left, NULL, ic, TRUE);
9913 if (pi) pi->generated = 1;
9916 /*-----------------------------------------------------------------*/
9917 /* genPagedPointerGet - emitcode for paged pointer fetch */
9918 /*-----------------------------------------------------------------*/
9920 genPagedPointerGet (operand * left,
9929 sym_link *rtype, *retype;
9931 D (emitcode (";", "genPagedPointerGet"));
9933 rtype = operandType (result);
9934 retype = getSpec (rtype);
9936 aopOp (left, ic, FALSE);
9938 /* if the value is already in a pointer register
9939 then don't need anything more */
9940 if (!AOP_INPREG (AOP (left)))
9942 /* otherwise get a free pointer register */
9944 preg = getFreePtr (ic, &aop, FALSE);
9945 emitcode ("mov", "%s,%s",
9947 aopGet (left, 0, FALSE, TRUE));
9951 rname = aopGet (left, 0, FALSE, FALSE);
9953 aopOp (result, ic, FALSE);
9955 /* if bitfield then unpack the bits */
9956 if (IS_BITFIELD (retype))
9957 genUnpackBits (result, rname, PPOINTER, ifx);
9960 /* we have can just get the values */
9961 int size = AOP_SIZE (result);
9967 emitcode ("movx", "a,@%s", rname);
9969 aopPut (result, "a", offset);
9974 emitcode ("inc", "%s", rname);
9978 /* now some housekeeping stuff */
9979 if (aop) /* we had to allocate for this iCode */
9982 aopPut (left, rname, 0);
9983 freeAsmop (NULL, aop, ic, TRUE);
9987 /* we did not allocate which means left
9988 already in a pointer register, then
9989 if size > 0 && this could be used again
9990 we have to point it back to where it
9992 if ((AOP_SIZE (result) > 1 &&
9993 !OP_SYMBOL (left)->remat &&
9994 (OP_SYMBOL (left)->liveTo > ic->seq ||
9998 int size = AOP_SIZE (result) - 1;
10000 emitcode ("dec", "%s", rname);
10004 if (ifx && !ifx->generated)
10006 genIfxJump (ifx, "a", left, NULL, result);
10010 freeAsmop (result, NULL, ic, TRUE);
10011 freeAsmop (left, NULL, ic, TRUE);
10012 if (pi) pi->generated = 1;
10015 /*--------------------------------------------------------------------*/
10016 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10017 /*--------------------------------------------------------------------*/
10019 loadDptrFromOperand (operand *op, bool loadBToo)
10021 if (AOP_TYPE (op) != AOP_STR)
10023 /* if this is rematerializable */
10024 if (AOP_TYPE (op) == AOP_IMMD)
10026 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10029 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10030 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10033 wassertl(FALSE, "need pointerCode");
10034 emitcode ("", "; mov b,???");
10035 /* genPointerGet and genPointerSet originally did different
10036 ** things for this case. Both seem wrong.
10037 ** from genPointerGet:
10038 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10039 ** from genPointerSet:
10040 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10045 else if (AOP_TYPE (op) == AOP_DPTR)
10049 MOVA (aopGet (op, 0, FALSE, FALSE));
10050 emitcode ("push", "acc");
10051 MOVA (aopGet (op, 1, FALSE, FALSE));
10052 emitcode ("push", "acc");
10053 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10054 emitcode ("pop", "dph");
10055 emitcode ("pop", "dpl");
10059 MOVA (aopGet (op, 0, FALSE, FALSE));
10060 emitcode ("push", "acc");
10061 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10062 emitcode ("pop", "dpl");
10066 { /* we need to get it byte by byte */
10067 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10068 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10070 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10075 /*-----------------------------------------------------------------*/
10076 /* genFarPointerGet - get value from far space */
10077 /*-----------------------------------------------------------------*/
10079 genFarPointerGet (operand * left,
10080 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10083 sym_link *retype = getSpec (operandType (result));
10085 D (emitcode (";", "genFarPointerGet"));
10087 aopOp (left, ic, FALSE);
10088 loadDptrFromOperand (left, FALSE);
10090 /* so dptr now contains the address */
10091 aopOp (result, ic, FALSE);
10093 /* if bit then unpack */
10094 if (IS_BITFIELD (retype))
10095 genUnpackBits (result, "dptr", FPOINTER, ifx);
10098 size = AOP_SIZE (result);
10103 emitcode ("movx", "a,@dptr");
10105 aopPut (result, "a", offset++);
10107 emitcode ("inc", "dptr");
10111 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10113 aopPut (left, "dpl", 0);
10114 aopPut (left, "dph", 1);
10118 if (ifx && !ifx->generated)
10120 genIfxJump (ifx, "a", left, NULL, result);
10123 freeAsmop (result, NULL, ic, TRUE);
10124 freeAsmop (left, NULL, ic, TRUE);
10127 /*-----------------------------------------------------------------*/
10128 /* genCodePointerGet - get value from code space */
10129 /*-----------------------------------------------------------------*/
10131 genCodePointerGet (operand * left,
10132 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10135 sym_link *retype = getSpec (operandType (result));
10137 D (emitcode (";", "genCodePointerGet"));
10139 aopOp (left, ic, FALSE);
10140 loadDptrFromOperand (left, FALSE);
10142 /* so dptr now contains the address */
10143 aopOp (result, ic, FALSE);
10145 /* if bit then unpack */
10146 if (IS_BITFIELD (retype))
10147 genUnpackBits (result, "dptr", CPOINTER, ifx);
10150 size = AOP_SIZE (result);
10155 emitcode ("clr", "a");
10156 emitcode ("movc", "a,@a+dptr");
10158 aopPut (result, "a", offset++);
10160 emitcode ("inc", "dptr");
10164 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10166 aopPut (left, "dpl", 0);
10167 aopPut (left, "dph", 1);
10171 if (ifx && !ifx->generated)
10173 genIfxJump (ifx, "a", left, NULL, result);
10176 freeAsmop (result, NULL, ic, TRUE);
10177 freeAsmop (left, NULL, ic, TRUE);
10180 /*-----------------------------------------------------------------*/
10181 /* genGenPointerGet - get value from generic pointer space */
10182 /*-----------------------------------------------------------------*/
10184 genGenPointerGet (operand * left,
10185 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10188 sym_link *retype = getSpec (operandType (result));
10190 D (emitcode (";", "genGenPointerGet"));
10192 aopOp (left, ic, FALSE);
10193 loadDptrFromOperand (left, TRUE);
10195 /* so dptr now contains the address */
10196 aopOp (result, ic, FALSE);
10198 /* if bit then unpack */
10199 if (IS_BITFIELD (retype))
10201 genUnpackBits (result, "dptr", GPOINTER, ifx);
10205 size = AOP_SIZE (result);
10210 emitcode ("lcall", "__gptrget");
10212 aopPut (result, "a", offset++);
10214 emitcode ("inc", "dptr");
10218 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10220 aopPut (left, "dpl", 0);
10221 aopPut (left, "dph", 1);
10225 if (ifx && !ifx->generated)
10227 genIfxJump (ifx, "a", left, NULL, result);
10230 freeAsmop (result, NULL, ic, TRUE);
10231 freeAsmop (left, NULL, ic, TRUE);
10234 /*-----------------------------------------------------------------*/
10235 /* genPointerGet - generate code for pointer get */
10236 /*-----------------------------------------------------------------*/
10238 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10240 operand *left, *result;
10241 sym_link *type, *etype;
10244 D (emitcode (";", "genPointerGet"));
10246 left = IC_LEFT (ic);
10247 result = IC_RESULT (ic);
10249 if (getSize (operandType (result))>1)
10252 /* depending on the type of pointer we need to
10253 move it to the correct pointer register */
10254 type = operandType (left);
10255 etype = getSpec (type);
10256 /* if left is of type of pointer then it is simple */
10257 if (IS_PTR (type) && !IS_FUNC (type->next))
10258 p_type = DCL_TYPE (type);
10261 /* we have to go by the storage class */
10262 p_type = PTR_TYPE (SPEC_OCLS (etype));
10265 /* special case when cast remat */
10266 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10267 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10269 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10270 type = operandType (left);
10271 p_type = DCL_TYPE (type);
10273 /* now that we have the pointer type we assign
10274 the pointer values */
10280 genNearPointerGet (left, result, ic, pi, ifx);
10284 genPagedPointerGet (left, result, ic, pi, ifx);
10288 genFarPointerGet (left, result, ic, pi, ifx);
10292 genCodePointerGet (left, result, ic, pi, ifx);
10296 genGenPointerGet (left, result, ic, pi, ifx);
10302 /*-----------------------------------------------------------------*/
10303 /* genPackBits - generates code for packed bit storage */
10304 /*-----------------------------------------------------------------*/
10306 genPackBits (sym_link * etype,
10308 char *rname, int p_type)
10310 int offset = 0; /* source byte offset */
10311 int rlen = 0; /* remaining bitfield length */
10312 int blen; /* bitfield length */
10313 int bstr; /* bitfield starting bit within byte */
10314 int litval; /* source literal value (if AOP_LIT) */
10315 unsigned char mask; /* bitmask within current byte */
10317 D(emitcode ("; genPackBits",""));
10319 blen = SPEC_BLEN (etype);
10320 bstr = SPEC_BSTR (etype);
10322 /* If the bitfield length is less than a byte */
10325 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10326 (unsigned char) (0xFF >> (8 - bstr)));
10328 if (AOP_TYPE (right) == AOP_LIT)
10330 /* Case with a bitfield length <8 and literal source
10332 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10334 litval &= (~mask) & 0xff;
10335 emitPtrByteGet (rname, p_type, FALSE);
10336 if ((mask|litval)!=0xff)
10337 emitcode ("anl","a,#0x%02x", mask);
10339 emitcode ("orl","a,#0x%02x", litval);
10343 if ((blen==1) && (p_type!=GPOINTER))
10345 /* Case with a bitfield length == 1 and no generic pointer
10347 if (AOP_TYPE (right) == AOP_CRY)
10348 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10351 MOVA (aopGet (right, 0, FALSE, FALSE));
10352 emitcode ("rrc","a");
10354 emitPtrByteGet (rname, p_type, FALSE);
10355 emitcode ("mov","acc.%d,c",bstr);
10360 /* Case with a bitfield length < 8 and arbitrary source
10362 MOVA (aopGet (right, 0, FALSE, FALSE));
10363 /* shift and mask source value */
10365 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10367 pushedB = pushB ();
10368 /* transfer A to B and get next byte */
10369 emitPtrByteGet (rname, p_type, TRUE);
10371 emitcode ("anl", "a,#0x%02x", mask);
10372 emitcode ("orl", "a,b");
10373 if (p_type == GPOINTER)
10374 emitcode ("pop", "b");
10380 emitPtrByteSet (rname, p_type, "a");
10384 /* Bit length is greater than 7 bits. In this case, copy */
10385 /* all except the partial byte at the end */
10386 for (rlen=blen;rlen>=8;rlen-=8)
10388 emitPtrByteSet (rname, p_type,
10389 aopGet (right, offset++, FALSE, TRUE) );
10391 emitcode ("inc", "%s", rname);
10394 /* If there was a partial byte at the end */
10397 mask = (((unsigned char) -1 << rlen) & 0xff);
10399 if (AOP_TYPE (right) == AOP_LIT)
10401 /* Case with partial byte and literal source
10403 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10404 litval >>= (blen-rlen);
10405 litval &= (~mask) & 0xff;
10406 emitPtrByteGet (rname, p_type, FALSE);
10407 if ((mask|litval)!=0xff)
10408 emitcode ("anl","a,#0x%02x", mask);
10410 emitcode ("orl","a,#0x%02x", litval);
10415 /* Case with partial byte and arbitrary source
10417 MOVA (aopGet (right, offset++, FALSE, FALSE));
10418 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10420 pushedB = pushB ();
10421 /* transfer A to B and get next byte */
10422 emitPtrByteGet (rname, p_type, TRUE);
10424 emitcode ("anl", "a,#0x%02x", mask);
10425 emitcode ("orl", "a,b");
10426 if (p_type == GPOINTER)
10427 emitcode ("pop", "b");
10431 emitPtrByteSet (rname, p_type, "a");
10436 /*-----------------------------------------------------------------*/
10437 /* genDataPointerSet - remat pointer to data space */
10438 /*-----------------------------------------------------------------*/
10440 genDataPointerSet (operand * right,
10444 int size, offset = 0;
10445 char *l, buffer[256];
10447 D (emitcode (";", "genDataPointerSet"));
10449 aopOp (right, ic, FALSE);
10451 l = aopGet (result, 0, FALSE, TRUE);
10453 size = AOP_SIZE (right);
10457 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10459 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10460 emitcode ("mov", "%s,%s", buffer,
10461 aopGet (right, offset++, FALSE, FALSE));
10464 freeAsmop (result, NULL, ic, TRUE);
10465 freeAsmop (right, NULL, ic, TRUE);
10468 /*-----------------------------------------------------------------*/
10469 /* genNearPointerSet - emitcode for near pointer put */
10470 /*-----------------------------------------------------------------*/
10472 genNearPointerSet (operand * right,
10480 sym_link *retype, *letype;
10481 sym_link *ptype = operandType (result);
10483 D (emitcode (";", "genNearPointerSet"));
10485 retype = getSpec (operandType (right));
10486 letype = getSpec (ptype);
10488 aopOp (result, ic, FALSE);
10490 /* if the result is rematerializable &
10491 in data space & not a bit variable */
10492 if (AOP_TYPE (result) == AOP_IMMD &&
10493 DCL_TYPE (ptype) == POINTER &&
10494 !IS_BITVAR (retype) &&
10495 !IS_BITVAR (letype))
10497 genDataPointerSet (right, result, ic);
10501 /* if the value is already in a pointer register
10502 then don't need anything more */
10503 if (!AOP_INPREG (AOP (result)))
10506 //AOP_TYPE (result) == AOP_STK
10507 IS_AOP_PREG(result)
10510 // Aha, it is a pointer, just in disguise.
10511 rname = aopGet (result, 0, FALSE, FALSE);
10514 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10515 __FILE__, __LINE__);
10520 emitcode ("mov", "a%s,%s", rname + 1, rname);
10521 rname++; // skip the '@'.
10526 /* otherwise get a free pointer register */
10527 aop = newAsmop (0);
10528 preg = getFreePtr (ic, &aop, FALSE);
10529 emitcode ("mov", "%s,%s",
10531 aopGet (result, 0, FALSE, TRUE));
10532 rname = preg->name;
10537 rname = aopGet (result, 0, FALSE, FALSE);
10540 aopOp (right, ic, FALSE);
10542 /* if bitfield then unpack the bits */
10543 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10544 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10547 /* we can just get the values */
10548 int size = AOP_SIZE (right);
10553 l = aopGet (right, offset, FALSE, TRUE);
10554 if ((*l == '@') || (strcmp (l, "acc") == 0))
10557 emitcode ("mov", "@%s,a", rname);
10560 emitcode ("mov", "@%s,%s", rname, l);
10562 emitcode ("inc", "%s", rname);
10567 /* now some housekeeping stuff */
10568 if (aop) /* we had to allocate for this iCode */
10571 aopPut (result, rname, 0);
10572 freeAsmop (NULL, aop, ic, TRUE);
10576 /* we did not allocate which means left
10577 already in a pointer register, then
10578 if size > 0 && this could be used again
10579 we have to point it back to where it
10581 if ((AOP_SIZE (right) > 1 &&
10582 !OP_SYMBOL (result)->remat &&
10583 (OP_SYMBOL (result)->liveTo > ic->seq ||
10587 int size = AOP_SIZE (right) - 1;
10589 emitcode ("dec", "%s", rname);
10594 if (pi) pi->generated = 1;
10595 freeAsmop (result, NULL, ic, TRUE);
10596 freeAsmop (right, NULL, ic, TRUE);
10599 /*-----------------------------------------------------------------*/
10600 /* genPagedPointerSet - emitcode for Paged pointer put */
10601 /*-----------------------------------------------------------------*/
10603 genPagedPointerSet (operand * right,
10611 sym_link *retype, *letype;
10613 D (emitcode (";", "genPagedPointerSet"));
10615 retype = getSpec (operandType (right));
10616 letype = getSpec (operandType (result));
10618 aopOp (result, ic, FALSE);
10620 /* if the value is already in a pointer register
10621 then don't need anything more */
10622 if (!AOP_INPREG (AOP (result)))
10624 /* otherwise get a free pointer register */
10625 aop = newAsmop (0);
10626 preg = getFreePtr (ic, &aop, FALSE);
10627 emitcode ("mov", "%s,%s",
10629 aopGet (result, 0, FALSE, TRUE));
10630 rname = preg->name;
10633 rname = aopGet (result, 0, FALSE, FALSE);
10635 aopOp (right, ic, FALSE);
10637 /* if bitfield then unpack the bits */
10638 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10639 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10642 /* we have can just get the values */
10643 int size = AOP_SIZE (right);
10648 l = aopGet (right, offset, FALSE, TRUE);
10650 emitcode ("movx", "@%s,a", rname);
10653 emitcode ("inc", "%s", rname);
10659 /* now some housekeeping stuff */
10660 if (aop) /* we had to allocate for this iCode */
10663 aopPut (result, rname, 0);
10664 freeAsmop (NULL, aop, ic, TRUE);
10668 /* we did not allocate which means left
10669 already in a pointer register, then
10670 if size > 0 && this could be used again
10671 we have to point it back to where it
10673 if (AOP_SIZE (right) > 1 &&
10674 !OP_SYMBOL (result)->remat &&
10675 (OP_SYMBOL (result)->liveTo > ic->seq ||
10678 int size = AOP_SIZE (right) - 1;
10680 emitcode ("dec", "%s", rname);
10685 if (pi) pi->generated = 1;
10686 freeAsmop (result, NULL, ic, TRUE);
10687 freeAsmop (right, NULL, ic, TRUE);
10690 /*-----------------------------------------------------------------*/
10691 /* genFarPointerSet - set value from far space */
10692 /*-----------------------------------------------------------------*/
10694 genFarPointerSet (operand * right,
10695 operand * result, iCode * ic, iCode * pi)
10698 sym_link *retype = getSpec (operandType (right));
10699 sym_link *letype = getSpec (operandType (result));
10701 D(emitcode ("; genFarPointerSet",""));
10703 aopOp (result, ic, FALSE);
10704 loadDptrFromOperand (result, FALSE);
10706 /* so dptr now contains the address */
10707 aopOp (right, ic, FALSE);
10709 /* if bit then unpack */
10710 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10711 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10714 size = AOP_SIZE (right);
10719 char *l = aopGet (right, offset++, FALSE, FALSE);
10721 emitcode ("movx", "@dptr,a");
10723 emitcode ("inc", "dptr");
10726 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10727 aopPut (result, "dpl", 0);
10728 aopPut (result, "dph", 1);
10731 freeAsmop (result, NULL, ic, TRUE);
10732 freeAsmop (right, NULL, ic, TRUE);
10735 /*-----------------------------------------------------------------*/
10736 /* genGenPointerSet - set value from generic pointer space */
10737 /*-----------------------------------------------------------------*/
10739 genGenPointerSet (operand * right,
10740 operand * result, iCode * ic, iCode * pi)
10743 sym_link *retype = getSpec (operandType (right));
10744 sym_link *letype = getSpec (operandType (result));
10746 D (emitcode (";", "genGenPointerSet"));
10748 aopOp (result, ic, FALSE);
10749 loadDptrFromOperand (result, TRUE);
10751 /* so dptr now contains the address */
10752 aopOp (right, ic, FALSE);
10754 /* if bit then unpack */
10755 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10757 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10761 size = AOP_SIZE (right);
10766 char *l = aopGet (right, offset++, FALSE, FALSE);
10768 emitcode ("lcall", "__gptrput");
10770 emitcode ("inc", "dptr");
10774 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10775 aopPut (result, "dpl", 0);
10776 aopPut (result, "dph", 1);
10779 freeAsmop (result, NULL, ic, TRUE);
10780 freeAsmop (right, NULL, ic, TRUE);
10783 /*-----------------------------------------------------------------*/
10784 /* genPointerSet - stores the value into a pointer location */
10785 /*-----------------------------------------------------------------*/
10787 genPointerSet (iCode * ic, iCode *pi)
10789 operand *right, *result;
10790 sym_link *type, *etype;
10793 D (emitcode (";", "genPointerSet"));
10795 right = IC_RIGHT (ic);
10796 result = IC_RESULT (ic);
10798 /* depending on the type of pointer we need to
10799 move it to the correct pointer register */
10800 type = operandType (result);
10801 etype = getSpec (type);
10802 /* if left is of type of pointer then it is simple */
10803 if (IS_PTR (type) && !IS_FUNC (type->next))
10805 p_type = DCL_TYPE (type);
10809 /* we have to go by the storage class */
10810 p_type = PTR_TYPE (SPEC_OCLS (etype));
10813 /* special case when cast remat */
10814 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10815 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10816 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10817 type = operandType (result);
10818 p_type = DCL_TYPE (type);
10821 /* now that we have the pointer type we assign
10822 the pointer values */
10828 genNearPointerSet (right, result, ic, pi);
10832 genPagedPointerSet (right, result, ic, pi);
10836 genFarPointerSet (right, result, ic, pi);
10840 genGenPointerSet (right, result, ic, pi);
10844 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10845 "genPointerSet: illegal pointer type");
10849 /*-----------------------------------------------------------------*/
10850 /* genIfx - generate code for Ifx statement */
10851 /*-----------------------------------------------------------------*/
10853 genIfx (iCode * ic, iCode * popIc)
10855 operand *cond = IC_COND (ic);
10859 D (emitcode (";", "genIfx"));
10861 aopOp (cond, ic, FALSE);
10863 /* get the value into acc */
10864 if (AOP_TYPE (cond) != AOP_CRY)
10871 if (AOP(cond)->aopu.aop_dir)
10872 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10875 /* the result is now in the accumulator or a directly addressable bit */
10876 freeAsmop (cond, NULL, ic, TRUE);
10878 /* if there was something to be popped then do it */
10882 /* if the condition is a bit variable */
10884 genIfxJump(ic, dup, NULL, NULL, NULL);
10885 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10886 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10887 else if (isbit && !IS_ITEMP (cond))
10888 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10890 genIfxJump (ic, "a", NULL, NULL, NULL);
10895 /*-----------------------------------------------------------------*/
10896 /* genAddrOf - generates code for address of */
10897 /*-----------------------------------------------------------------*/
10899 genAddrOf (iCode * ic)
10901 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10904 D (emitcode (";", "genAddrOf"));
10906 aopOp (IC_RESULT (ic), ic, FALSE);
10908 /* if the operand is on the stack then we
10909 need to get the stack offset of this
10913 /* if it has an offset then we need to compute it */
10916 int stack_offset = ((sym->stack < 0) ?
10917 ((char) (sym->stack - _G.nRegsSaved)) :
10918 ((char) sym->stack)) & 0xff;
10919 if ((abs(stack_offset) == 1) &&
10920 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10921 !isOperandVolatile (IC_RESULT (ic), FALSE))
10923 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10924 if (stack_offset > 0)
10925 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10927 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10931 emitcode ("mov", "a,%s", SYM_BP (sym));
10932 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10933 aopPut (IC_RESULT (ic), "a", 0);
10938 /* we can just move _bp */
10939 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10941 /* fill the result with zero */
10942 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10947 aopPut (IC_RESULT (ic), zero, offset++);
10952 /* object not on stack then we need the name */
10953 size = AOP_SIZE (IC_RESULT (ic));
10958 char s[SDCC_NAME_MAX];
10960 sprintf (s, "#(%s >> %d)",
10964 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10965 aopPut (IC_RESULT (ic), s, offset++);
10969 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10973 /*-----------------------------------------------------------------*/
10974 /* genFarFarAssign - assignment when both are in far space */
10975 /*-----------------------------------------------------------------*/
10977 genFarFarAssign (operand * result, operand * right, iCode * ic)
10979 int size = AOP_SIZE (right);
10983 D (emitcode (";", "genFarFarAssign"));
10985 /* first push the right side on to the stack */
10988 l = aopGet (right, offset++, FALSE, FALSE);
10990 emitcode ("push", "acc");
10993 freeAsmop (right, NULL, ic, FALSE);
10994 /* now assign DPTR to result */
10995 aopOp (result, ic, FALSE);
10996 size = AOP_SIZE (result);
10999 emitcode ("pop", "acc");
11000 aopPut (result, "a", --offset);
11002 freeAsmop (result, NULL, ic, FALSE);
11005 /*-----------------------------------------------------------------*/
11006 /* genAssign - generate code for assignment */
11007 /*-----------------------------------------------------------------*/
11009 genAssign (iCode * ic)
11011 operand *result, *right;
11013 unsigned long lit = 0L;
11015 D (emitcode (";", "genAssign"));
11017 result = IC_RESULT (ic);
11018 right = IC_RIGHT (ic);
11020 /* if they are the same */
11021 if (operandsEqu (result, right) &&
11022 !isOperandVolatile (result, FALSE) &&
11023 !isOperandVolatile (right, FALSE))
11026 aopOp (right, ic, FALSE);
11028 /* special case both in far space */
11029 if (AOP_TYPE (right) == AOP_DPTR &&
11030 IS_TRUE_SYMOP (result) &&
11031 isOperandInFarSpace (result))
11033 genFarFarAssign (result, right, ic);
11037 aopOp (result, ic, TRUE);
11039 /* if they are the same registers */
11040 if (sameRegs (AOP (right), AOP (result)) &&
11041 !isOperandVolatile (result, FALSE) &&
11042 !isOperandVolatile (right, FALSE))
11045 /* if the result is a bit */
11046 if (AOP_TYPE (result) == AOP_CRY)
11048 /* if the right size is a literal then
11049 we know what the value is */
11050 if (AOP_TYPE (right) == AOP_LIT)
11052 if (((int) operandLitValue (right)))
11053 aopPut (result, one, 0);
11055 aopPut (result, zero, 0);
11059 /* the right is also a bit variable */
11060 if (AOP_TYPE (right) == AOP_CRY)
11062 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11063 aopPut (result, "c", 0);
11067 /* we need to or */
11069 aopPut (result, "a", 0);
11073 /* bit variables done */
11075 size = AOP_SIZE (result);
11077 if (AOP_TYPE (right) == AOP_LIT)
11078 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11081 (AOP_TYPE (result) != AOP_REG) &&
11082 (AOP_TYPE (right) == AOP_LIT) &&
11083 !IS_FLOAT (operandType (right)) &&
11086 while ((size) && (lit))
11089 aopGet (right, offset, FALSE, FALSE),
11095 /* And now fill the rest with zeros. */
11098 emitcode ("clr", "a");
11102 aopPut (result, "a", offset);
11111 aopGet (right, offset, FALSE, FALSE),
11118 freeAsmop (result, NULL, ic, TRUE);
11119 freeAsmop (right, NULL, ic, TRUE);
11122 /*-----------------------------------------------------------------*/
11123 /* genJumpTab - generates code for jump table */
11124 /*-----------------------------------------------------------------*/
11126 genJumpTab (iCode * ic)
11128 symbol *jtab,*jtablo,*jtabhi;
11130 unsigned int count;
11132 D (emitcode (";", "genJumpTab"));
11134 count = elementsInSet( IC_JTLABELS (ic) );
11138 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11139 if the switch argument is in a register.
11140 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11141 /* Peephole may not convert ljmp to sjmp or ret
11142 labelIsReturnOnly & labelInRange must check
11143 currPl->ic->op != JUMPTABLE */
11144 aopOp (IC_JTCOND (ic), ic, FALSE);
11145 /* get the condition into accumulator */
11146 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11148 /* multiply by three */
11149 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11151 emitcode ("mov", "b,#3");
11152 emitcode ("mul", "ab");
11156 emitcode ("add", "a,acc");
11157 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11159 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11161 jtab = newiTempLabel (NULL);
11162 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11163 emitcode ("jmp", "@a+dptr");
11165 /* now generate the jump labels */
11166 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11167 jtab = setNextItem (IC_JTLABELS (ic)))
11168 emitcode ("ljmp", "%05d$", jtab->key + 100);
11172 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11173 if the switch argument is in a register.
11174 For n>6 this algorithm may be more compact */
11175 jtablo = newiTempLabel (NULL);
11176 jtabhi = newiTempLabel (NULL);
11178 /* get the condition into accumulator.
11179 Using b as temporary storage, if register push/pop is needed */
11180 aopOp (IC_JTCOND (ic), ic, FALSE);
11181 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11182 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11183 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11185 // (MB) what if B is in use???
11186 wassertl(!BINUSE, "B was in use");
11187 emitcode ("mov", "b,%s", l);
11190 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11194 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11195 emitcode ("movc", "a,@a+pc");
11196 emitcode ("push", "acc");
11199 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11200 emitcode ("movc", "a,@a+pc");
11201 emitcode ("push", "acc");
11205 /* this scales up to n<=255, but needs two more bytes
11206 and changes dptr */
11207 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11208 emitcode ("movc", "a,@a+dptr");
11209 emitcode ("push", "acc");
11212 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11213 emitcode ("movc", "a,@a+dptr");
11214 emitcode ("push", "acc");
11217 emitcode ("ret", "");
11219 /* now generate jump table, LSB */
11220 emitLabel (jtablo);
11221 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11222 jtab = setNextItem (IC_JTLABELS (ic)))
11223 emitcode (".db", "%05d$", jtab->key + 100);
11225 /* now generate jump table, MSB */
11226 emitLabel (jtabhi);
11227 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11228 jtab = setNextItem (IC_JTLABELS (ic)))
11229 emitcode (".db", "%05d$>>8", jtab->key + 100);
11233 /*-----------------------------------------------------------------*/
11234 /* genCast - gen code for casting */
11235 /*-----------------------------------------------------------------*/
11237 genCast (iCode * ic)
11239 operand *result = IC_RESULT (ic);
11240 sym_link *ctype = operandType (IC_LEFT (ic));
11241 sym_link *rtype = operandType (IC_RIGHT (ic));
11242 operand *right = IC_RIGHT (ic);
11245 D (emitcode (";", "genCast"));
11247 /* if they are equivalent then do nothing */
11248 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11251 aopOp (right, ic, FALSE);
11252 aopOp (result, ic, FALSE);
11254 /* if the result is a bit (and not a bitfield) */
11255 if (IS_BIT (OP_SYMBOL (result)->type))
11257 /* if the right size is a literal then
11258 we know what the value is */
11259 if (AOP_TYPE (right) == AOP_LIT)
11261 if (((int) operandLitValue (right)))
11262 aopPut (result, one, 0);
11264 aopPut (result, zero, 0);
11269 /* the right is also a bit variable */
11270 if (AOP_TYPE (right) == AOP_CRY)
11272 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11273 aopPut (result, "c", 0);
11277 /* we need to or */
11279 aopPut (result, "a", 0);
11283 /* if they are the same size : or less */
11284 if (AOP_SIZE (result) <= AOP_SIZE (right))
11287 /* if they are in the same place */
11288 if (sameRegs (AOP (right), AOP (result)))
11291 /* if they in different places then copy */
11292 size = AOP_SIZE (result);
11297 aopGet (right, offset, FALSE, FALSE),
11304 /* if the result is of type pointer */
11305 if (IS_PTR (ctype))
11309 sym_link *type = operandType (right);
11310 sym_link *etype = getSpec (type);
11312 /* pointer to generic pointer */
11313 if (IS_GENPTR (ctype))
11317 p_type = DCL_TYPE (type);
11321 if (SPEC_SCLS(etype)==S_REGISTER) {
11322 // let's assume it is a generic pointer
11325 /* we have to go by the storage class */
11326 p_type = PTR_TYPE (SPEC_OCLS (etype));
11330 /* the first two bytes are known */
11331 size = GPTRSIZE - 1;
11336 aopGet (right, offset, FALSE, FALSE),
11340 /* the last byte depending on type */
11342 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11347 // pointerTypeToGPByte will have bitched.
11351 sprintf(gpValStr, "#0x%x", gpVal);
11352 aopPut (result, gpValStr, GPTRSIZE - 1);
11357 /* just copy the pointers */
11358 size = AOP_SIZE (result);
11363 aopGet (right, offset, FALSE, FALSE),
11370 /* so we now know that the size of destination is greater
11371 than the size of the source */
11372 /* we move to result for the size of source */
11373 size = AOP_SIZE (right);
11378 aopGet (right, offset, FALSE, FALSE),
11383 /* now depending on the sign of the source && destination */
11384 size = AOP_SIZE (result) - AOP_SIZE (right);
11385 /* if unsigned or not an integral type */
11386 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11389 aopPut (result, zero, offset++);
11393 /* we need to extend the sign :{ */
11394 char *l = aopGet (right, AOP_SIZE (right) - 1,
11397 emitcode ("rlc", "a");
11398 emitcode ("subb", "a,acc");
11400 aopPut (result, "a", offset++);
11403 /* we are done hurray !!!! */
11406 freeAsmop (result, NULL, ic, TRUE);
11407 freeAsmop (right, NULL, ic, TRUE);
11410 /*-----------------------------------------------------------------*/
11411 /* genDjnz - generate decrement & jump if not zero instrucion */
11412 /*-----------------------------------------------------------------*/
11414 genDjnz (iCode * ic, iCode * ifx)
11416 symbol *lbl, *lbl1;
11420 /* if the if condition has a false label
11421 then we cannot save */
11422 if (IC_FALSE (ifx))
11425 /* if the minus is not of the form a = a - 1 */
11426 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11427 !IS_OP_LITERAL (IC_RIGHT (ic)))
11430 if (operandLitValue (IC_RIGHT (ic)) != 1)
11433 /* if the size of this greater than one then no
11435 if (getSize (operandType (IC_RESULT (ic))) > 1)
11438 /* otherwise we can save BIG */
11440 D (emitcode (";", "genDjnz"));
11442 lbl = newiTempLabel (NULL);
11443 lbl1 = newiTempLabel (NULL);
11445 aopOp (IC_RESULT (ic), ic, FALSE);
11447 if (AOP_NEEDSACC(IC_RESULT(ic)))
11449 /* If the result is accessed indirectly via
11450 * the accumulator, we must explicitly write
11451 * it back after the decrement.
11453 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11455 if (strcmp(rByte, "a"))
11457 /* Something is hopelessly wrong */
11458 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11459 __FILE__, __LINE__);
11460 /* We can just give up; the generated code will be inefficient,
11461 * but what the hey.
11463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11466 emitcode ("dec", "%s", rByte);
11467 aopPut (IC_RESULT (ic), rByte, 0);
11468 emitcode ("jnz", "%05d$", lbl->key + 100);
11470 else if (IS_AOP_PREG (IC_RESULT (ic)))
11472 emitcode ("dec", "%s",
11473 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11474 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11476 ifx->generated = 1;
11477 emitcode ("jnz", "%05d$", lbl->key + 100);
11481 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11484 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11486 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11489 if (!ifx->generated)
11490 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11491 ifx->generated = 1;
11495 /*-----------------------------------------------------------------*/
11496 /* genReceive - generate code for a receive iCode */
11497 /*-----------------------------------------------------------------*/
11499 genReceive (iCode * ic)
11501 int size = getSize (operandType (IC_RESULT (ic)));
11504 D (emitcode (";", "genReceive"));
11506 if (ic->argreg == 1)
11507 { /* first parameter */
11508 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11509 isOperandInPagedSpace (IC_RESULT (ic))) &&
11510 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11511 IS_TRUE_SYMOP (IC_RESULT (ic))))
11514 int receivingA = 0;
11517 for (offset = 0; offset<size; offset++)
11518 if (!strcmp (fReturn[offset], "a"))
11523 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11525 for (offset = size-1; offset>0; offset--)
11526 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11527 emitcode("mov","a,%s", fReturn[0]);
11529 aopOp (IC_RESULT (ic), ic, FALSE);
11531 aopPut (IC_RESULT (ic), "a", offset);
11532 for (offset = 1; offset<size; offset++)
11533 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11539 if (getTempRegs(tempRegs, size, ic))
11541 for (offset = 0; offset<size; offset++)
11542 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11543 aopOp (IC_RESULT (ic), ic, FALSE);
11544 for (offset = 0; offset<size; offset++)
11545 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11550 offset = fReturnSizeMCS51 - size;
11553 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11554 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11557 aopOp (IC_RESULT (ic), ic, FALSE);
11558 size = AOP_SIZE (IC_RESULT (ic));
11562 emitcode ("pop", "acc");
11563 aopPut (IC_RESULT (ic), "a", offset++);
11569 aopOp (IC_RESULT (ic), ic, FALSE);
11571 assignResultValue (IC_RESULT (ic), NULL);
11574 else if (ic->argreg > 12)
11575 { /* bit parameters */
11576 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11578 aopOp (IC_RESULT (ic), ic, FALSE);
11579 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11580 outBitC(IC_RESULT (ic));
11584 { /* other parameters */
11586 aopOp (IC_RESULT (ic), ic, FALSE);
11587 rb1off = ic->argreg;
11590 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11598 /*-----------------------------------------------------------------*/
11599 /* genDummyRead - generate code for dummy read of volatiles */
11600 /*-----------------------------------------------------------------*/
11602 genDummyRead (iCode * ic)
11607 D (emitcode(";", "genDummyRead"));
11609 op = IC_RIGHT (ic);
11610 if (op && IS_SYMOP (op))
11612 aopOp (op, ic, FALSE);
11614 /* if the result is a bit */
11615 if (AOP_TYPE (op) == AOP_CRY)
11616 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11619 /* bit variables done */
11621 size = AOP_SIZE (op);
11625 MOVA (aopGet (op, offset, FALSE, FALSE));
11630 freeAsmop (op, NULL, ic, TRUE);
11634 if (op && IS_SYMOP (op))
11636 aopOp (op, ic, FALSE);
11638 /* if the result is a bit */
11639 if (AOP_TYPE (op) == AOP_CRY)
11640 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11643 /* bit variables done */
11645 size = AOP_SIZE (op);
11649 MOVA (aopGet (op, offset, FALSE, FALSE));
11654 freeAsmop (op, NULL, ic, TRUE);
11658 /*-----------------------------------------------------------------*/
11659 /* genCritical - generate code for start of a critical sequence */
11660 /*-----------------------------------------------------------------*/
11662 genCritical (iCode *ic)
11664 symbol *tlbl = newiTempLabel (NULL);
11666 D (emitcode(";", "genCritical"));
11668 if (IC_RESULT (ic))
11670 aopOp (IC_RESULT (ic), ic, TRUE);
11671 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11672 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11673 aopPut (IC_RESULT (ic), zero, 0);
11675 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11679 emitcode ("setb", "c");
11680 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11681 emitcode ("clr", "c");
11683 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11687 /*-----------------------------------------------------------------*/
11688 /* genEndCritical - generate code for end of a critical sequence */
11689 /*-----------------------------------------------------------------*/
11691 genEndCritical (iCode *ic)
11693 D(emitcode("; genEndCritical",""));
11697 aopOp (IC_RIGHT (ic), ic, FALSE);
11698 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11700 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11701 emitcode ("mov", "ea,c");
11705 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11706 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11707 emitcode ("rrc", "a");
11708 emitcode ("mov", "ea,c");
11710 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11714 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11715 emitcode ("mov", "ea,c");
11719 /*-----------------------------------------------------------------*/
11720 /* gen51Code - generate code for 8051 based controllers */
11721 /*-----------------------------------------------------------------*/
11723 gen51Code (iCode * lic)
11727 /* int cseq = 0; */
11729 _G.currentFunc = NULL;
11730 lineHead = lineCurr = NULL;
11732 /* print the allocation information */
11733 if (allocInfo && currFunc)
11734 printAllocInfo (currFunc, codeOutBuf);
11735 /* if debug information required */
11736 if (options.debug && currFunc)
11738 debugFile->writeFunction (currFunc, lic);
11740 /* stack pointer name */
11741 if (options.useXstack)
11747 for (ic = lic; ic; ic = ic->next)
11749 _G.current_iCode = ic;
11751 if (ic->lineno && cln != ic->lineno)
11755 debugFile->writeCLine (ic);
11757 if (!options.noCcodeInAsm) {
11758 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11759 printCLine(ic->filename, ic->lineno));
11764 if (ic->seqPoint && ic->seqPoint != cseq)
11766 emitcode ("", "; sequence point %d", ic->seqPoint);
11767 cseq = ic->seqPoint;
11770 if (options.iCodeInAsm) {
11771 char regsInUse[80];
11776 for (i=0; i<8; i++) {
11777 sprintf (®sInUse[i],
11778 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11781 strcpy (regsInUse, "--------");
11782 for (i=0; i < 8; i++) {
11783 if (bitVectBitValue (ic->rMask, i))
11785 int offset = regs8051[i].offset;
11786 regsInUse[offset] = offset + '0'; /* show rMask */
11790 iLine = printILine(ic);
11791 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11794 /* if the result is marked as
11795 spilt and rematerializable or code for
11796 this has already been generated then
11798 if (resultRemat (ic) || ic->generated)
11801 /* depending on the operation */
11821 /* IPOP happens only when trying to restore a
11822 spilt live range, if there is an ifx statement
11823 following this pop then the if statement might
11824 be using some of the registers being popped which
11825 would destory the contents of the register so
11826 we need to check for this condition and handle it */
11828 ic->next->op == IFX &&
11829 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11830 genIfx (ic->next, ic);
11848 genEndFunction (ic);
11868 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11885 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11889 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11896 /* note these two are xlated by algebraic equivalence
11897 in decorateType() in SDCCast.c */
11898 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11899 "got '>=' or '<=' shouldn't have come here");
11903 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11915 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11919 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11923 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11959 genRightShift (ic);
11962 case GET_VALUE_AT_ADDRESS:
11964 hasInc (IC_LEFT (ic), ic,
11965 getSize (operandType (IC_RESULT (ic)))),
11966 ifxForOp (IC_RESULT (ic), ic) );
11970 if (POINTER_SET (ic))
11972 hasInc (IC_RESULT (ic), ic,
11973 getSize (operandType (IC_RIGHT (ic)))));
11999 addSet (&_G.sendSet, ic);
12002 case DUMMY_READ_VOLATILE:
12011 genEndCritical (ic);
12023 _G.current_iCode = NULL;
12025 /* now we are ready to call the
12026 peep hole optimizer */
12027 if (!options.nopeep)
12028 peepHole (&lineHead);
12030 /* now do the actual printing */
12031 printLine (lineHead, codeOutBuf);