1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define REG_WITH_INDEX mcs51_regWithIdx
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74 AOP_TYPE(x) == AOP_R0))
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
77 AOP_TYPE(x) == AOP_DPTR || \
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
81 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86 #define R0INB _G.bu.bs.r0InB
87 #define R1INB _G.bu.bs.r1InB
88 #define OPINB _G.bu.bs.OpInB
89 #define BINUSE _G.bu.BInUse
99 short r0InB : 2;//2 so we can see it overflow
100 short r1InB : 2;//2 so we can see it overflow
101 short OpInB : 2;//2 so we can see it overflow
110 iCode *current_iCode;
115 static char *rb1regs[] = {
116 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (char *inst, const char *fmt,...)
155 char lb[INITIAL_INLINEASM];
164 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
168 SNPRINTF (lb, sizeof(lb), "%s", inst);
171 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
175 tvsprintf (lb, sizeof(lb), fmt, ap);
178 while (isspace ((unsigned char)*lbp))
185 lineCurr = (lineCurr ?
186 connectLine (lineCurr, newLineNode (lb)) :
187 (lineHead = newLineNode (lb)));
190 lineCurr->isInline = _G.inLine;
191 lineCurr->isDebug = _G.debugLine;
192 lineCurr->ic = _G.current_iCode;
193 lineCurr->isComment = (*lbp==';');
198 emitLabel (symbol *tlbl)
200 emitcode ("", "%05d$:", tlbl->key + 100);
203 /*-----------------------------------------------------------------*/
204 /* mcs51_emitDebuggerSymbol - associate the current code location */
205 /* with a debugger symbol */
206 /*-----------------------------------------------------------------*/
208 mcs51_emitDebuggerSymbol (char * debugSym)
211 emitcode ("", "%s ==.", debugSym);
215 /*-----------------------------------------------------------------*/
216 /* mova - moves specified value into accumulator */
217 /*-----------------------------------------------------------------*/
221 /* do some early peephole optimization */
222 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
225 emitcode("mov", "a,%s", x);
228 /*-----------------------------------------------------------------*/
229 /* movb - moves specified value into register b */
230 /*-----------------------------------------------------------------*/
234 /* do some early peephole optimization */
235 if (!strncmp(x, "b", 2))
238 emitcode("mov","b,%s", x);
241 /*-----------------------------------------------------------------*/
242 /* movc - moves specified value into the carry */
243 /*-----------------------------------------------------------------*/
247 if (!strcmp (s, zero))
249 else if (!strcmp (s, one))
251 else if (strcmp (s, "c"))
252 {/* it's not in carry already */
254 /* set C, if a >= 1 */
255 emitcode ("add", "a,#0xff");
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary */
261 /*-----------------------------------------------------------------*/
265 bool pushedB = FALSE;
269 emitcode ("push", "b");
270 // printf("B was in use !\n");
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary */
282 /*-----------------------------------------------------------------*/
288 emitcode ("pop", "b");
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register */
298 /*-----------------------------------------------------------------*/
300 pushReg (int index, bool bits_pushed)
302 regs * reg = REG_WITH_INDEX (index);
303 if (reg->type == REG_BIT)
306 emitcode ("push", "%s", reg->base);
310 emitcode ("push", "%s", reg->dname);
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register */
316 /*-----------------------------------------------------------------*/
318 popReg (int index, bool bits_popped)
320 regs * reg = REG_WITH_INDEX (index);
321 if (reg->type == REG_BIT)
324 emitcode ("pop", "%s", reg->base);
328 emitcode ("pop", "%s", reg->dname);
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
341 /* the logic: if r0 & r1 used in the instruction
342 then we are in trouble otherwise */
344 /* first check if r0 & r1 are used by this
345 instruction, in which case we are in trouble */
346 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
352 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355 /* if no usage of r0 then return it */
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
364 /* if no usage of r1 then return it */
367 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368 (*aopp)->type = AOP_R1;
370 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
373 /* now we know they both have usage */
374 /* if r0 not used in this instruction */
377 /* push it if not already pushed */
380 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
383 else if (!_G.r0Pushed)
385 emitcode ("push", "%s",
386 REG_WITH_INDEX (R0_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391 (*aopp)->type = AOP_R0;
393 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
396 /* if r1 not used then */
400 /* push it if not already pushed */
403 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
406 else if (!_G.r1Pushed)
408 emitcode ("push", "%s",
409 REG_WITH_INDEX (R1_IDX)->dname);
413 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414 (*aopp)->type = AOP_R1;
415 return REG_WITH_INDEX (R1_IDX);
419 /* I said end of world, but not quite end of world yet */
420 /* if this is a result then we can push it on the stack */
423 (*aopp)->type = AOP_STK;
426 /* in the case that result AND left AND right needs a pointer reg
427 we can safely use the result's */
428 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430 (*aopp)->type = AOP_R0;
431 return REG_WITH_INDEX (R0_IDX);
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435 (*aopp)->type = AOP_R1;
436 return REG_WITH_INDEX (R1_IDX);
439 /* now this is REALLY the end of the world */
440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441 "getFreePtr should never reach here");
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /* that are not in use. Returns 1 if the requested */
449 /* number of registers were available, 0 otherwise. */
450 /*-----------------------------------------------------------------*/
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
459 ic = _G.current_iCode;
465 freeRegs = newBitVect(8);
466 bitVectSetBit (freeRegs, R2_IDX);
467 bitVectSetBit (freeRegs, R3_IDX);
468 bitVectSetBit (freeRegs, R4_IDX);
469 bitVectSetBit (freeRegs, R5_IDX);
470 bitVectSetBit (freeRegs, R6_IDX);
471 bitVectSetBit (freeRegs, R7_IDX);
473 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475 bitVect * newfreeRegs;
476 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477 freeBitVect(freeRegs);
478 freeRegs = newfreeRegs;
480 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
483 for (i=0; i<freeRegs->size; i++)
485 if (bitVectBitValue(freeRegs,i))
486 tempRegs[offset++] = REG_WITH_INDEX(i);
489 freeBitVect(freeRegs);
494 freeBitVect(freeRegs);
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp */
501 /*-----------------------------------------------------------------*/
503 newAsmop (short type)
507 aop = Safe_calloc (1, sizeof (asmop));
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type */
515 /*-----------------------------------------------------------------*/
517 pointerCode (sym_link * etype)
520 return PTR_TYPE (SPEC_OCLS (etype));
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands */
526 /*-----------------------------------------------------------------*/
528 leftRightUseAcc(iCode *ic)
537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538 "null iCode pointer");
545 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
548 size = getSize (OP_SYMBOL (op)->type);
553 else if (ic->op == JUMPTABLE)
556 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
559 size = getSize (OP_SYMBOL (op)->type);
567 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
570 size = getSize (OP_SYMBOL (op)->type);
575 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
578 size = getSize (OP_SYMBOL (op)->type);
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol */
592 /*-----------------------------------------------------------------*/
594 aopForSym (iCode * ic, symbol * sym, bool result)
598 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600 wassertl (ic != NULL, "Got a null iCode");
601 wassertl (sym != NULL, "Got a null symbol");
603 space = SPEC_OCLS (sym->etype);
605 /* if already has one */
608 sym->aop->allocated++;
612 /* assign depending on the storage class */
613 /* if it is on the stack or indirectly addressable */
614 /* space we need to assign either r0 or r1 to it */
615 if (sym->onStack || sym->iaccess)
617 sym->aop = aop = newAsmop (0);
618 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619 aop->size = getSize (sym->type);
621 /* now assign the address of the variable to
622 the pointer register */
623 if (aop->type != AOP_STK)
627 signed char offset = ((sym->stack < 0) ?
628 ((signed char) (sym->stack - _G.nRegsSaved)) :
629 ((signed char) sym->stack)) & 0xff;
631 if ((abs(offset) <= 3) ||
632 (accuse && (abs(offset) <= 7)))
634 emitcode ("mov", "%s,%s",
635 aop->aopu.aop_ptr->name, SYM_BP (sym));
638 emitcode ("dec", aop->aopu.aop_ptr->name);
643 emitcode ("inc", aop->aopu.aop_ptr->name);
650 emitcode ("push", "acc");
651 emitcode ("mov", "a,%s", SYM_BP (sym));
652 emitcode ("add", "a,#0x%02x", offset & 0xff);
653 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655 emitcode ("pop", "acc");
660 emitcode ("mov", "%s,#%s",
661 aop->aopu.aop_ptr->name,
664 aop->paged = space->paged;
667 aop->aopu.aop_stk = sym->stack;
671 /* if in bit space */
672 if (IN_BITSPACE (space))
674 sym->aop = aop = newAsmop (AOP_CRY);
675 aop->aopu.aop_dir = sym->rname;
676 aop->size = getSize (sym->type);
679 /* if it is in direct space */
680 if (IN_DIRSPACE (space))
682 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683 //printTypeChainRaw(sym->type, NULL);
684 //printf("space = %s\n", space ? space->sname : "NULL");
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = getSize (sym->type);
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop (AOP_DPTR);
703 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
751 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
754 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755 /* set immd2 field if required */
756 if (aop->aopu.aop_immd.from_cast_remat)
758 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common */
767 /*-----------------------------------------------------------------*/
769 regsInCommon (operand * op1, operand * op2)
774 /* if they have registers in common */
775 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
778 sym1 = OP_SYMBOL (op1);
779 sym2 = OP_SYMBOL (op2);
781 if (sym1->nRegs == 0 || sym2->nRegs == 0)
784 for (i = 0; i < sym1->nRegs; i++)
790 for (j = 0; j < sym2->nRegs; j++)
795 if (sym2->regs[j] == sym1->regs[i])
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent */
805 /*-----------------------------------------------------------------*/
807 operandsEqu (operand * op1, operand * op2)
811 /* if they're not symbols */
812 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
815 sym1 = OP_SYMBOL (op1);
816 sym2 = OP_SYMBOL (op2);
818 /* if both are itemps & one is spilt
819 and the other is not then false */
820 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821 sym1->isspilt != sym2->isspilt)
824 /* if they are the same */
828 /* if they have the same rname */
829 if (sym1->rname[0] && sym2->rname[0] &&
830 strcmp (sym1->rname, sym2->rname) == 0 &&
831 !(IS_PARM (op2) && IS_ITEMP (op1)))
834 /* if left is a tmp & right is not */
835 if (IS_ITEMP (op1) &&
838 (sym1->usl.spillLoc == sym2))
841 if (IS_ITEMP (op2) &&
845 (sym2->usl.spillLoc == sym1))
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets */
853 /*-----------------------------------------------------------------*/
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
857 if (aop1 == aop2 && off1 == off2)
860 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
863 if (aop1->type != aop2->type)
866 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers */
874 /*-----------------------------------------------------------------*/
876 sameRegs (asmop * aop1, asmop * aop2)
883 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
886 if (aop1->type != aop2->type)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand : */
901 /*-----------------------------------------------------------------*/
903 aopOp (operand * op, iCode * ic, bool result)
912 /* if this a literal */
913 if (IS_OP_LITERAL (op))
915 op->aop = aop = newAsmop (AOP_LIT);
916 aop->aopu.aop_lit = op->operand.valOperand;
917 aop->size = getSize (operandType (op));
921 /* if already has a asmop then continue */
924 op->aop->allocated++;
928 /* if the underlying symbol has a aop */
929 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
931 op->aop = OP_SYMBOL (op)->aop;
932 op->aop->allocated++;
936 /* if this is a true symbol */
937 if (IS_TRUE_SYMOP (op))
939 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
943 /* this is a temporary : this has
949 e) can be a return use only */
951 sym = OP_SYMBOL (op);
953 /* if the type is a conditional */
954 if (sym->regType == REG_CND)
956 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
961 /* if it is spilt then two situations
963 b) has a spill location */
964 if (sym->isspilt || sym->nRegs == 0)
967 /* rematerialize it NOW */
970 sym->aop = op->aop = aop = aopForRemat (sym);
971 aop->size = getSize (sym->type);
978 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
979 aop->size = getSize (sym->type);
980 for (i = 0; i < 2; i++)
981 aop->aopu.aop_str[i] = accUse[i];
989 aop = op->aop = sym->aop = newAsmop (AOP_STR);
990 aop->size = getSize (sym->type);
991 for (i = 0; i < fReturnSizeMCS51; i++)
992 aop->aopu.aop_str[i] = fReturn[i];
996 if (sym->usl.spillLoc)
998 asmop *oldAsmOp = NULL;
1000 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002 /* force a new aop if sizes differ */
1003 oldAsmOp = sym->usl.spillLoc->aop;
1004 sym->usl.spillLoc->aop = NULL;
1006 sym->aop = op->aop = aop =
1007 aopForSym (ic, sym->usl.spillLoc, result);
1008 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010 /* Don't reuse the new aop, go with the last one */
1011 sym->usl.spillLoc->aop = oldAsmOp;
1013 aop->size = getSize (sym->type);
1017 /* else must be a dummy iTemp */
1018 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019 aop->size = getSize (sym->type);
1023 /* if the type is a bit register */
1024 if (sym->regType == REG_BIT)
1026 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027 aop->size = sym->nRegs;//1???
1028 aop->aopu.aop_reg[0] = sym->regs[0];
1029 aop->aopu.aop_dir = sym->regs[0]->name;
1033 /* must be in a register */
1034 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035 aop->size = sym->nRegs;
1036 for (i = 0; i < sym->nRegs; i++)
1037 aop->aopu.aop_reg[i] = sym->regs[i];
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand */
1042 /*----------------------------------------------------------------*/
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1061 /* depending on the asmop type only three cases need work
1062 AOP_R0, AOP_R1 & AOP_STK */
1068 emitcode ("mov", "r0,b");
1071 else if (_G.r0Pushed)
1075 emitcode ("pop", "ar0");
1079 bitVectUnSetBit (ic->rUsed, R0_IDX);
1085 emitcode ("mov", "r1,b");
1088 else if (_G.r1Pushed)
1092 emitcode ("pop", "ar1");
1096 bitVectUnSetBit (ic->rUsed, R1_IDX);
1102 int stk = aop->aopu.aop_stk + aop->size - 1;
1103 bitVectUnSetBit (ic->rUsed, R0_IDX);
1104 bitVectUnSetBit (ic->rUsed, R1_IDX);
1106 getFreePtr (ic, &aop, FALSE);
1110 emitcode ("mov", "a,_bp");
1111 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1116 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1121 emitcode ("pop", "acc");
1122 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1125 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 freeAsmop (op, NULL, ic, TRUE);
1131 emitcode ("pop", "ar1");
1136 emitcode ("pop", "ar0");
1144 /* all other cases just dealloc */
1150 OP_SYMBOL (op)->aop = NULL;
1151 /* if the symbol has a spill */
1153 SPIL_LOC (op)->aop = NULL;
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /* pop r0 or r1 off stack if pushed */
1161 /*------------------------------------------------------------------*/
1163 freeForBranchAsmop (operand * op)
1175 if (!aop->allocated)
1183 emitcode ("mov", "r0,b");
1185 else if (_G.r0Pushed)
1187 emitcode ("pop", "ar0");
1194 emitcode ("mov", "r1,b");
1196 else if (_G.r1Pushed)
1198 emitcode ("pop", "ar1");
1205 int stk = aop->aopu.aop_stk + aop->size - 1;
1207 emitcode ("mov", "b,r0");
1210 emitcode ("mov", "a,_bp");
1211 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212 emitcode ("mov", "r0,a");
1216 emitcode ("mov", "r0,_bp");
1221 emitcode ("pop", "acc");
1222 emitcode ("mov", "@r0,a");
1225 emitcode ("dec", "r0");
1227 emitcode ("mov", "r0,b");
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1235 /* clobber the accumulator */
1236 /*-----------------------------------------------------------------*/
1238 aopGetUsesAcc (operand * oper, int offset)
1240 asmop * aop = AOP (oper);
1242 if (offset > (aop->size - 1))
1260 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1271 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1277 /* Error case --- will have been caught already */
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop */
1285 /*-------------------------------------------------------------------*/
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 asmop * aop = AOP (oper);
1291 /* offset is greater than
1293 if (offset > (aop->size - 1) &&
1294 aop->type != AOP_LIT)
1297 /* depending on type */
1305 /* if we need to increment it */
1306 while (offset > aop->coff)
1308 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1312 while (offset < aop->coff)
1314 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1321 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322 return (dname ? "acc" : "a");
1324 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325 return Safe_strdup(buffer);
1328 if (aop->code && aop->coff==0 && offset>=1) {
1329 emitcode ("mov", "a,#0x%02x", offset);
1330 emitcode ("movc", "a,@a+dptr");
1331 return (dname ? "acc" : "a");
1334 while (offset > aop->coff)
1336 emitcode ("inc", "dptr");
1340 while (offset < aop->coff)
1342 emitcode ("lcall", "__decdptr");
1349 emitcode ("clr", "a");
1350 emitcode ("movc", "a,@a+dptr");
1354 emitcode ("movx", "a,@dptr");
1356 return (dname ? "acc" : "a");
1359 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361 SNPRINTF(buffer, sizeof(buffer),
1362 "%s",aop->aopu.aop_immd.aop_immd2);
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "#%s", aop->aopu.aop_immd.aop_immd1);
1371 SNPRINTF (buffer, sizeof(buffer),
1373 aop->aopu.aop_immd.aop_immd1,
1378 SNPRINTF (buffer, sizeof(buffer),
1380 aop->aopu.aop_immd.aop_immd1);
1382 return Safe_strdup(buffer);
1385 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387 SNPRINTF (buffer, sizeof(buffer),
1389 aop->aopu.aop_dir, offset * 8);
1393 SNPRINTF (buffer, sizeof(buffer),
1400 SNPRINTF (buffer, sizeof(buffer),
1405 return Safe_strdup(buffer);
1409 return aop->aopu.aop_reg[offset]->dname;
1411 return aop->aopu.aop_reg[offset]->name;
1414 emitcode ("clr", "a");
1415 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1416 emitcode ("rlc", "a");
1417 return (dname ? "acc" : "a");
1420 if (!offset && dname)
1422 return aop->aopu.aop_str[offset];
1425 return aopLiteral (aop->aopu.aop_lit, offset);
1429 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1433 return aop->aopu.aop_str[offset];
1437 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438 "aopget got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1444 /* clobber the accumulator */
1445 /*-----------------------------------------------------------------*/
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 asmop * aop = AOP (oper);
1451 if (offset > (aop->size - 1))
1461 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1467 return ((aop->paged) || (*s == '@'));
1471 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1479 /* Error case --- will have been caught already */
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1489 aopPut (operand * result, const char *s, int offset)
1491 bool bvolatile = isOperandVolatile (result, FALSE);
1492 bool accuse = FALSE;
1493 asmop * aop = AOP (result);
1495 if (aop->size && offset > (aop->size - 1))
1497 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498 "aopPut got offset > aop->size");
1502 /* will assign value to value */
1503 /* depending on where it is ofcourse */
1507 MOVA (s); /* read s in case it was volatile */
1512 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514 SNPRINTF (buffer, sizeof(buffer),
1516 aop->aopu.aop_dir, offset * 8);
1520 SNPRINTF (buffer, sizeof(buffer),
1522 aop->aopu.aop_dir, offset);
1526 SNPRINTF (buffer, sizeof(buffer),
1531 if (strcmp (buffer, s) || bvolatile)
1533 emitcode ("mov", "%s,%s", buffer, s);
1535 if (!strcmp (buffer, "acc"))
1542 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1546 strcmp (s, "r0") == 0 ||
1547 strcmp (s, "r1") == 0 ||
1548 strcmp (s, "r2") == 0 ||
1549 strcmp (s, "r3") == 0 ||
1550 strcmp (s, "r4") == 0 ||
1551 strcmp (s, "r5") == 0 ||
1552 strcmp (s, "r6") == 0 ||
1553 strcmp (s, "r7") == 0)
1555 emitcode ("mov", "%s,%s",
1556 aop->aopu.aop_reg[offset]->dname, s);
1560 emitcode ("mov", "%s,%s",
1561 aop->aopu.aop_reg[offset]->name, s);
1569 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570 "aopPut writing to code space");
1574 while (offset > aop->coff)
1577 emitcode ("inc", "dptr");
1580 while (offset < aop->coff)
1583 emitcode ("lcall", "__decdptr");
1588 /* if not in accumulator */
1591 emitcode ("movx", "@dptr,a");
1596 while (offset > aop->coff)
1599 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601 while (offset < aop->coff)
1604 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1611 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1616 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618 else if (strcmp (s, "r0") == 0 ||
1619 strcmp (s, "r1") == 0 ||
1620 strcmp (s, "r2") == 0 ||
1621 strcmp (s, "r3") == 0 ||
1622 strcmp (s, "r4") == 0 ||
1623 strcmp (s, "r5") == 0 ||
1624 strcmp (s, "r6") == 0 ||
1625 strcmp (s, "r7") == 0)
1628 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629 emitcode ("mov", "@%s,%s",
1630 aop->aopu.aop_ptr->name, buffer);
1634 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1639 if (strcmp (s, "a") == 0)
1640 emitcode ("push", "acc");
1644 emitcode ("push", "acc");
1646 emitcode ("push", s);
1652 /* if not bit variable */
1653 if (!aop->aopu.aop_dir)
1655 /* inefficient: move carry into A and use jz/jnz */
1656 emitcode ("clr", "a");
1657 emitcode ("rlc", "a");
1663 emitcode ("clr", "%s", aop->aopu.aop_dir);
1665 emitcode ("setb", "%s", aop->aopu.aop_dir);
1666 else if (!strcmp (s, "c"))
1667 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1668 else if (strcmp (s, aop->aopu.aop_dir))
1671 /* set C, if a >= 1 */
1672 emitcode ("add", "a,#0xff");
1673 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1680 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1681 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1687 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1690 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1691 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1695 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1696 "aopPut got unsupported aop->type");
1705 /*-----------------------------------------------------------------*/
1706 /* pointToEnd :- points to the last byte of the operand */
1707 /*-----------------------------------------------------------------*/
1709 pointToEnd (asmop * aop)
1715 aop->coff = count = (aop->size - 1);
1721 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1725 emitcode ("inc", "dptr");
1732 /*-----------------------------------------------------------------*/
1733 /* reAdjustPreg - points a register back to where it should */
1734 /*-----------------------------------------------------------------*/
1736 reAdjustPreg (asmop * aop)
1738 if ((aop->coff==0) || (aop->size <= 1))
1746 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1751 emitcode ("lcall", "__decdptr");
1758 /*-----------------------------------------------------------------*/
1759 /* opIsGptr: returns non-zero if the passed operand is */
1760 /* a generic pointer type. */
1761 /*-----------------------------------------------------------------*/
1763 opIsGptr (operand * op)
1765 sym_link *type = operandType (op);
1767 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1774 /*-----------------------------------------------------------------*/
1775 /* getDataSize - get the operand data size */
1776 /*-----------------------------------------------------------------*/
1778 getDataSize (operand * op)
1781 size = AOP_SIZE (op);
1782 if (size == GPTRSIZE)
1784 sym_link *type = operandType (op);
1785 if (IS_GENPTR (type))
1787 /* generic pointer; arithmetic operations
1788 * should ignore the high byte (pointer type).
1796 /*-----------------------------------------------------------------*/
1797 /* outAcc - output Acc */
1798 /*-----------------------------------------------------------------*/
1800 outAcc (operand * result)
1803 size = getDataSize (result);
1806 aopPut (result, "a", 0);
1809 /* unsigned or positive */
1812 aopPut (result, zero, offset++);
1817 /*-----------------------------------------------------------------*/
1818 /* outBitC - output a bit C */
1819 /*-----------------------------------------------------------------*/
1821 outBitC (operand * result)
1823 /* if the result is bit */
1824 if (AOP_TYPE (result) == AOP_CRY)
1826 aopPut (result, "c", 0);
1830 emitcode ("clr", "a");
1831 emitcode ("rlc", "a");
1836 /*-----------------------------------------------------------------*/
1837 /* toBoolean - emit code for orl a,operator(sizeop) */
1838 /*-----------------------------------------------------------------*/
1840 toBoolean (operand * oper)
1842 int size = AOP_SIZE (oper) - 1;
1844 bool AccUsed = FALSE;
1847 while (!AccUsed && size--)
1849 AccUsed |= aopGetUsesAcc(oper, offset++);
1852 size = AOP_SIZE (oper) - 1;
1854 MOVA (aopGet (oper, 0, FALSE, FALSE));
1855 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1858 emitcode("mov", "b,a");
1861 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1862 emitcode ("orl", "b,a");
1864 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1865 emitcode ("orl", "a,b");
1872 emitcode ("orl", "a,%s",
1873 aopGet (oper, offset++, FALSE, FALSE));
1879 /*-------------------------------------------------------------------*/
1880 /* xch_a_aopGet - for exchanging acc with value of the aop */
1881 /*-------------------------------------------------------------------*/
1883 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1887 if (aopGetUsesAcc (oper, offset))
1889 emitcode("mov", "b,a");
1890 MOVA (aopGet (oper, offset, bit16, dname));
1891 emitcode("xch", "a,b");
1892 aopPut (oper, "a", offset);
1893 emitcode("xch", "a,b");
1898 l = aopGet (oper, offset, bit16, dname);
1899 emitcode("xch", "a,%s", l);
1905 /*-----------------------------------------------------------------*/
1906 /* genNot - generate code for ! operation */
1907 /*-----------------------------------------------------------------*/
1913 D (emitcode (";", "genNot"));
1915 /* assign asmOps to operand & result */
1916 aopOp (IC_LEFT (ic), ic, FALSE);
1917 aopOp (IC_RESULT (ic), ic, TRUE);
1919 /* if in bit space then a special case */
1920 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1922 /* if left==result then cpl bit */
1923 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1925 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1930 emitcode ("cpl", "c");
1931 outBitC (IC_RESULT (ic));
1936 toBoolean (IC_LEFT (ic));
1938 /* set C, if a == 0 */
1939 tlbl = newiTempLabel (NULL);
1940 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1942 outBitC (IC_RESULT (ic));
1945 /* release the aops */
1946 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1947 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1951 /*-----------------------------------------------------------------*/
1952 /* genCpl - generate code for complement */
1953 /*-----------------------------------------------------------------*/
1960 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1962 D(emitcode (";", "genCpl"));
1964 /* assign asmOps to operand & result */
1965 aopOp (IC_LEFT (ic), ic, FALSE);
1966 aopOp (IC_RESULT (ic), ic, TRUE);
1968 /* special case if in bit space */
1969 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1973 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1974 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1976 /* promotion rules are responsible for this strange result:
1977 bit -> int -> ~int -> bit
1978 uchar -> int -> ~int -> bit
1980 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1984 tlbl=newiTempLabel(NULL);
1985 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1986 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1987 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1988 IS_AOP_PREG (IC_LEFT (ic)))
1990 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1995 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1998 outBitC (IC_RESULT(ic));
2002 size = AOP_SIZE (IC_RESULT (ic));
2005 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2007 emitcode ("cpl", "a");
2008 aopPut (IC_RESULT (ic), "a", offset++);
2013 /* release the aops */
2014 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2015 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2018 /*-----------------------------------------------------------------*/
2019 /* genUminusFloat - unary minus for floating points */
2020 /*-----------------------------------------------------------------*/
2022 genUminusFloat (operand * op, operand * result)
2024 int size, offset = 0;
2027 D (emitcode (";", "genUminusFloat"));
2029 /* for this we just copy and then flip the bit */
2031 size = AOP_SIZE (op) - 1;
2036 aopGet (op, offset, FALSE, FALSE),
2041 l = aopGet (op, offset, FALSE, FALSE);
2044 emitcode ("cpl", "acc.7");
2045 aopPut (result, "a", offset);
2048 /*-----------------------------------------------------------------*/
2049 /* genUminus - unary minus code generation */
2050 /*-----------------------------------------------------------------*/
2052 genUminus (iCode * ic)
2057 D (emitcode (";", "genUminus"));
2060 aopOp (IC_LEFT (ic), ic, FALSE);
2061 aopOp (IC_RESULT (ic), ic, TRUE);
2063 /* if both in bit space then special
2065 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2066 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2069 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2070 emitcode ("cpl", "c");
2071 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2075 optype = operandType (IC_LEFT (ic));
2077 /* if float then do float stuff */
2078 if (IS_FLOAT (optype))
2080 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2084 /* otherwise subtract from zero */
2085 size = AOP_SIZE (IC_LEFT (ic));
2089 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2090 if (!strcmp (l, "a"))
2094 emitcode ("cpl", "a");
2095 emitcode ("addc", "a,#0");
2101 emitcode ("clr", "a");
2102 emitcode ("subb", "a,%s", l);
2104 aopPut (IC_RESULT (ic), "a", offset++);
2107 /* if any remaining bytes in the result */
2108 /* we just need to propagate the sign */
2109 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2111 emitcode ("rlc", "a");
2112 emitcode ("subb", "a,acc");
2114 aopPut (IC_RESULT (ic), "a", offset++);
2118 /* release the aops */
2119 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2120 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2123 /*-----------------------------------------------------------------*/
2124 /* saveRegisters - will look for a call and save the registers */
2125 /*-----------------------------------------------------------------*/
2127 saveRegisters (iCode * lic)
2134 for (ic = lic; ic; ic = ic->next)
2135 if (ic->op == CALL || ic->op == PCALL)
2140 fprintf (stderr, "found parameter push with no function call\n");
2144 /* if the registers have been saved already or don't need to be then
2148 if (IS_SYMOP(IC_LEFT(ic)) &&
2149 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2150 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2153 /* save the registers in use at this time but skip the
2154 ones for the result */
2155 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2156 mcs51_rUmaskForOp (IC_RESULT(ic)));
2159 if (options.useXstack)
2161 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2162 int nBits = bitVectnBitsOn (rsavebits);
2163 int count = bitVectnBitsOn (rsave);
2167 count = count - nBits + 1;
2168 /* remove all but the first bits as they are pushed all at once */
2169 rsave = bitVectCplAnd (rsave, rsavebits);
2170 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2175 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2176 if (reg->type == REG_BIT)
2178 emitcode ("mov", "a,%s", reg->base);
2182 emitcode ("mov", "a,%s", reg->name);
2184 emitcode ("mov", "r0,%s", spname);
2185 emitcode ("inc", "%s", spname);// allocate before use
2186 emitcode ("movx", "@r0,a");
2187 if (bitVectBitValue (rsave, R0_IDX))
2188 emitcode ("mov", "r0,a");
2190 else if (count != 0)
2192 if (bitVectBitValue (rsave, R0_IDX))
2194 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2196 emitcode ("mov", "r0,%s", spname);
2198 emitcode ("add", "a,#%d", count);
2199 emitcode ("mov", "%s,a", spname);
2200 for (i = 0; i < mcs51_nRegs; i++)
2202 if (bitVectBitValue (rsave, i))
2204 regs * reg = REG_WITH_INDEX (i);
2207 emitcode ("pop", "acc");
2208 emitcode ("push", "acc");
2210 else if (reg->type == REG_BIT)
2212 emitcode ("mov", "a,%s", reg->base);
2216 emitcode ("mov", "a,%s", reg->name);
2218 emitcode ("movx", "@r0,a");
2221 emitcode ("inc", "r0");
2225 if (bitVectBitValue (rsave, R0_IDX))
2227 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2233 bool bits_pushed = FALSE;
2234 for (i = 0; i < mcs51_nRegs; i++)
2236 if (bitVectBitValue (rsave, i))
2238 bits_pushed = pushReg (i, bits_pushed);
2244 /*-----------------------------------------------------------------*/
2245 /* unsaveRegisters - pop the pushed registers */
2246 /*-----------------------------------------------------------------*/
2248 unsaveRegisters (iCode * ic)
2253 /* restore the registers in use at this time but skip the
2254 ones for the result */
2255 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2256 mcs51_rUmaskForOp (IC_RESULT(ic)));
2258 if (options.useXstack)
2260 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2261 int nBits = bitVectnBitsOn (rsavebits);
2262 int count = bitVectnBitsOn (rsave);
2266 count = count - nBits + 1;
2267 /* remove all but the first bits as they are popped all at once */
2268 rsave = bitVectCplAnd (rsave, rsavebits);
2269 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2274 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2275 emitcode ("mov", "r0,%s", spname);
2276 emitcode ("dec", "r0");
2277 emitcode ("movx", "a,@r0");
2278 if (reg->type == REG_BIT)
2280 emitcode ("mov", "%s,a", reg->base);
2284 emitcode ("mov", "%s,a", reg->name);
2286 emitcode ("dec", "%s", spname);
2288 else if (count != 0)
2290 emitcode ("mov", "r0,%s", spname);
2291 for (i = mcs51_nRegs; i >= 0; i--)
2293 if (bitVectBitValue (rsave, i))
2295 regs * reg = REG_WITH_INDEX (i);
2296 emitcode ("dec", "r0");
2297 emitcode ("movx", "a,@r0");
2300 emitcode ("push", "acc");
2302 else if (reg->type == REG_BIT)
2304 emitcode ("mov", "%s,a", reg->base);
2308 emitcode ("mov", "%s,a", reg->name);
2312 emitcode ("mov", "%s,r0", spname);
2313 if (bitVectBitValue (rsave, R0_IDX))
2315 emitcode ("pop", "ar0");
2321 bool bits_popped = FALSE;
2322 for (i = mcs51_nRegs; i >= 0; i--)
2324 if (bitVectBitValue (rsave, i))
2326 bits_popped = popReg (i, bits_popped);
2333 /*-----------------------------------------------------------------*/
2335 /*-----------------------------------------------------------------*/
2337 pushSide (operand * oper, int size)
2342 char *l = aopGet (oper, offset++, FALSE, TRUE);
2343 if (AOP_TYPE (oper) != AOP_REG &&
2344 AOP_TYPE (oper) != AOP_DIR &&
2348 emitcode ("push", "acc");
2352 emitcode ("push", "%s", l);
2357 /*-----------------------------------------------------------------*/
2358 /* assignResultValue - also indicates if acc is in use afterwards */
2359 /*-----------------------------------------------------------------*/
2361 assignResultValue (operand * oper, operand * func)
2364 int size = AOP_SIZE (oper);
2365 bool accuse = FALSE;
2366 bool pushedA = FALSE;
2368 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2374 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2376 emitcode ("push", "acc");
2381 if ((offset == 3) && pushedA)
2382 emitcode ("pop", "acc");
2383 accuse |= aopPut (oper, fReturn[offset], offset);
2390 /*-----------------------------------------------------------------*/
2391 /* genXpush - pushes onto the external stack */
2392 /*-----------------------------------------------------------------*/
2394 genXpush (iCode * ic)
2396 asmop *aop = newAsmop (0);
2398 int size, offset = 0;
2400 D (emitcode (";", "genXpush"));
2402 aopOp (IC_LEFT (ic), ic, FALSE);
2403 r = getFreePtr (ic, &aop, FALSE);
2405 size = AOP_SIZE (IC_LEFT (ic));
2409 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2410 emitcode ("mov", "%s,%s", r->name, spname);
2411 emitcode ("inc", "%s", spname); // allocate space first
2412 emitcode ("movx", "@%s,a", r->name);
2416 // allocate space first
2417 emitcode ("mov", "%s,%s", r->name, spname);
2419 emitcode ("add", "a,#%d", size);
2420 emitcode ("mov", "%s,a", spname);
2424 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2425 emitcode ("movx", "@%s,a", r->name);
2426 emitcode ("inc", "%s", r->name);
2430 freeAsmop (NULL, aop, ic, TRUE);
2431 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2434 /*-----------------------------------------------------------------*/
2435 /* genIpush - generate code for pushing this gets a little complex */
2436 /*-----------------------------------------------------------------*/
2438 genIpush (iCode * ic)
2440 int size, offset = 0;
2444 D (emitcode (";", "genIpush"));
2446 /* if this is not a parm push : ie. it is spill push
2447 and spill push is always done on the local stack */
2451 /* and the item is spilt then do nothing */
2452 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2455 aopOp (IC_LEFT (ic), ic, FALSE);
2456 size = AOP_SIZE (IC_LEFT (ic));
2457 /* push it on the stack */
2460 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2466 emitcode ("push", "%s", l);
2471 /* this is a parameter push: in this case we call
2472 the routine to find the call and save those
2473 registers that need to be saved */
2476 /* if use external stack then call the external
2477 stack pushing routine */
2478 if (options.useXstack)
2484 /* then do the push */
2485 aopOp (IC_LEFT (ic), ic, FALSE);
2487 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2488 size = AOP_SIZE (IC_LEFT (ic));
2492 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2493 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2494 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2496 if (strcmp (l, prev) || *l == '@')
2498 emitcode ("push", "acc");
2502 emitcode ("push", "%s", l);
2507 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2510 /*-----------------------------------------------------------------*/
2511 /* genIpop - recover the registers: can happen only for spilling */
2512 /*-----------------------------------------------------------------*/
2514 genIpop (iCode * ic)
2518 D (emitcode (";", "genIpop"));
2520 /* if the temp was not pushed then */
2521 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2524 aopOp (IC_LEFT (ic), ic, FALSE);
2525 size = AOP_SIZE (IC_LEFT (ic));
2526 offset = (size - 1);
2529 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2533 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2536 /*-----------------------------------------------------------------*/
2537 /* saveRBank - saves an entire register bank on the stack */
2538 /*-----------------------------------------------------------------*/
2540 saveRBank (int bank, iCode * ic, bool pushPsw)
2543 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2547 if (options.useXstack)
2551 /* Assume r0 is available for use. */
2552 r = REG_WITH_INDEX (R0_IDX);;
2557 r = getFreePtr (ic, &aop, FALSE);
2559 // allocate space first
2560 emitcode ("mov", "%s,%s", r->name, spname);
2562 emitcode ("add", "a,#%d", count);
2563 emitcode ("mov", "%s,a", spname);
2566 for (i = 0; i < 8; i++)
2568 if (options.useXstack)
2570 emitcode ("mov", "a,(%s+%d)",
2571 regs8051[i].base, 8 * bank + regs8051[i].offset);
2572 emitcode ("movx", "@%s,a", r->name);
2574 emitcode ("inc", "%s", r->name);
2577 emitcode ("push", "(%s+%d)",
2578 regs8051[i].base, 8 * bank + regs8051[i].offset);
2581 if (mcs51_nRegs > 8)
2583 if (options.useXstack)
2585 emitcode ("mov", "a,bits");
2586 emitcode ("movx", "@%s,a", r->name);
2588 emitcode ("inc", "%s", r->name);
2592 emitcode ("push", "bits");
2599 if (options.useXstack)
2601 emitcode ("mov", "a,psw");
2602 emitcode ("movx", "@%s,a", r->name);
2606 emitcode ("push", "psw");
2609 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2614 freeAsmop (NULL, aop, ic, TRUE);
2623 /*-----------------------------------------------------------------*/
2624 /* unsaveRBank - restores the register bank from stack */
2625 /*-----------------------------------------------------------------*/
2627 unsaveRBank (int bank, iCode * ic, bool popPsw)
2633 if (options.useXstack)
2637 /* Assume r0 is available for use. */
2638 r = REG_WITH_INDEX (R0_IDX);;
2643 r = getFreePtr (ic, &aop, FALSE);
2645 emitcode ("mov", "%s,%s", r->name, spname);
2650 if (options.useXstack)
2652 emitcode ("dec", "%s", r->name);
2653 emitcode ("movx", "a,@%s", r->name);
2654 emitcode ("mov", "psw,a");
2658 emitcode ("pop", "psw");
2662 if (mcs51_nRegs > 8)
2664 if (options.useXstack)
2666 emitcode ("dec", "%s", r->name);
2667 emitcode ("movx", "a,@%s", r->name);
2668 emitcode ("mov", "bits,a");
2672 emitcode ("pop", "bits");
2676 for (i = 7; i >= 0; i--)
2678 if (options.useXstack)
2680 emitcode ("dec", "%s", r->name);
2681 emitcode ("movx", "a,@%s", r->name);
2682 emitcode ("mov", "(%s+%d),a",
2683 regs8051[i].base, 8 * bank + regs8051[i].offset);
2687 emitcode ("pop", "(%s+%d)",
2688 regs8051[i].base, 8 * bank + regs8051[i].offset);
2692 if (options.useXstack)
2694 emitcode ("mov", "%s,%s", spname, r->name);
2699 freeAsmop (NULL, aop, ic, TRUE);
2703 /*-----------------------------------------------------------------*/
2704 /* genSend - gen code for SEND */
2705 /*-----------------------------------------------------------------*/
2706 static void genSend(set *sendSet)
2711 /* first we do all bit parameters */
2712 for (sic = setFirstItem (sendSet); sic;
2713 sic = setNextItem (sendSet))
2715 if (sic->argreg > 12)
2717 int bit = sic->argreg-13;
2719 aopOp (IC_LEFT (sic), sic, FALSE);
2721 /* if left is a literal then
2722 we know what the value is */
2723 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2725 if (((int) operandLitValue (IC_LEFT (sic))))
2726 emitcode ("setb", "b[%d]", bit);
2728 emitcode ("clr", "b[%d]", bit);
2730 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2732 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2733 if (strcmp (l, "c"))
2734 emitcode ("mov", "c,%s", l);
2735 emitcode ("mov", "b[%d],c", bit);
2740 toBoolean (IC_LEFT (sic));
2741 /* set C, if a >= 1 */
2742 emitcode ("add", "a,#0xff");
2743 emitcode ("mov", "b[%d],c", bit);
2748 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2754 saveRegisters (setFirstItem (sendSet));
2755 emitcode ("mov", "bits,b");
2758 /* then we do all other parameters */
2759 for (sic = setFirstItem (sendSet); sic;
2760 sic = setNextItem (sendSet))
2762 if (sic->argreg <= 12)
2764 int size, offset = 0;
2765 aopOp (IC_LEFT (sic), sic, FALSE);
2766 size = AOP_SIZE (IC_LEFT (sic));
2768 if (sic->argreg == 1)
2772 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2773 if (strcmp (l, fReturn[offset]))
2775 emitcode ("mov", "%s,%s", fReturn[offset], l);
2784 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2785 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2789 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2794 /*-----------------------------------------------------------------*/
2795 /* selectRegBank - emit code to select the register bank */
2796 /*-----------------------------------------------------------------*/
2798 selectRegBank (short bank, bool keepFlags)
2800 /* if f.e. result is in carry */
2803 emitcode ("anl", "psw,#0xE7");
2805 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2809 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2813 /*-----------------------------------------------------------------*/
2814 /* genCall - generates a call statement */
2815 /*-----------------------------------------------------------------*/
2817 genCall (iCode * ic)
2821 // bool restoreBank = FALSE;
2822 bool swapBanks = FALSE;
2823 bool accuse = FALSE;
2824 bool accPushed = FALSE;
2825 bool resultInF0 = FALSE;
2826 bool assignResultGenerated = FALSE;
2828 D (emitcode (";", "genCall"));
2830 dtype = operandType (IC_LEFT (ic));
2831 etype = getSpec(dtype);
2832 /* if send set is not empty then assign */
2835 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2836 genSend(reverseSet(_G.sendSet));
2838 genSend(_G.sendSet);
2843 /* if we are calling a not _naked function that is not using
2844 the same register bank then we need to save the
2845 destination registers on the stack */
2846 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2847 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2848 !IFFUNC_ISISR (dtype))
2853 /* if caller saves & we have not saved then */
2859 emitcode ("mov", "psw,#0x%02x",
2860 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2864 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2866 if (IFFUNC_CALLEESAVES(dtype))
2868 werror (E_BANKED_WITH_CALLEESAVES);
2872 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2873 OP_SYMBOL (IC_LEFT (ic))->rname :
2874 OP_SYMBOL (IC_LEFT (ic))->name);
2876 emitcode ("mov", "r0,#%s", l);
2877 emitcode ("mov", "r1,#(%s >> 8)", l);
2878 emitcode ("mov", "r2,#(%s >> 16)", l);
2879 emitcode ("lcall", "__sdcc_banked_call");
2884 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2885 OP_SYMBOL (IC_LEFT (ic))->rname :
2886 OP_SYMBOL (IC_LEFT (ic))->name));
2891 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2894 /* if we need assign a result value */
2895 if ((IS_ITEMP (IC_RESULT (ic)) &&
2896 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2897 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2898 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2899 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2900 IS_TRUE_SYMOP (IC_RESULT (ic)))
2904 aopOp (IC_RESULT (ic), ic, FALSE);
2907 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2908 assignResultGenerated = TRUE;
2910 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2913 /* adjust the stack for parameters if required */
2917 if (ic->parmBytes > 3)
2921 emitcode ("push", "acc");
2924 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2925 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2926 !assignResultGenerated)
2928 emitcode ("mov", "F0,c");
2932 emitcode ("mov", "a,%s", spname);
2933 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2934 emitcode ("mov", "%s,a", spname);
2936 /* unsaveRegisters from xstack needs acc, but */
2937 /* unsaveRegisters from stack needs this popped */
2938 if (accPushed && !options.useXstack)
2940 emitcode ("pop", "acc");
2945 for (i = 0; i < ic->parmBytes; i++)
2946 emitcode ("dec", "%s", spname);
2949 /* if we had saved some registers then unsave them */
2950 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2952 if (accuse && !accPushed && options.useXstack)
2954 /* xstack needs acc, but doesn't touch normal stack */
2955 emitcode ("push", "acc");
2958 unsaveRegisters (ic);
2961 // /* if register bank was saved then pop them */
2963 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2965 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2968 emitcode ("mov", "c,F0");
2970 aopOp (IC_RESULT (ic), ic, FALSE);
2971 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2972 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2976 emitcode ("pop", "acc");
2979 /*-----------------------------------------------------------------*/
2980 /* genPcall - generates a call by pointer statement */
2981 /*-----------------------------------------------------------------*/
2983 genPcall (iCode * ic)
2987 symbol *rlbl = newiTempLabel (NULL);
2988 // bool restoreBank=FALSE;
2989 bool swapBanks = FALSE;
2990 bool resultInF0 = FALSE;
2992 D (emitcode (";", "genPcall"));
2994 dtype = operandType (IC_LEFT (ic))->next;
2995 etype = getSpec(dtype);
2996 /* if caller saves & we have not saved then */
3000 /* if we are calling a not _naked function that is not using
3001 the same register bank then we need to save the
3002 destination registers on the stack */
3003 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3004 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3005 !IFFUNC_ISISR (dtype))
3007 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3008 // restoreBank=TRUE;
3010 // need caution message to user here
3013 if (IS_LITERAL(etype))
3015 /* if send set is not empty then assign */
3018 genSend(reverseSet(_G.sendSet));
3024 emitcode ("mov", "psw,#0x%02x",
3025 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3028 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3030 if (IFFUNC_CALLEESAVES(dtype))
3032 werror (E_BANKED_WITH_CALLEESAVES);
3036 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3038 emitcode ("mov", "r0,#%s", l);
3039 emitcode ("mov", "r1,#(%s >> 8)", l);
3040 emitcode ("mov", "r2,#(%s >> 16)", l);
3041 emitcode ("lcall", "__sdcc_banked_call");
3046 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3051 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3053 if (IFFUNC_CALLEESAVES(dtype))
3055 werror (E_BANKED_WITH_CALLEESAVES);
3059 aopOp (IC_LEFT (ic), ic, FALSE);
3063 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3064 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3065 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3069 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3070 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3071 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3072 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3075 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077 /* if send set is not empty then assign */
3080 genSend(reverseSet(_G.sendSet));
3086 emitcode ("mov", "psw,#0x%02x",
3087 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3091 emitcode ("lcall", "__sdcc_banked_call");
3096 /* push the return address on to the stack */
3097 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3098 emitcode ("push", "acc");
3099 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3100 emitcode ("push", "acc");
3102 /* now push the calling address */
3103 aopOp (IC_LEFT (ic), ic, FALSE);
3105 pushSide (IC_LEFT (ic), FPTRSIZE);
3107 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109 /* if send set is not empty the assign */
3112 genSend(reverseSet(_G.sendSet));
3118 emitcode ("mov", "psw,#0x%02x",
3119 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3123 emitcode ("ret", "");
3129 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3132 /* if we need assign a result value */
3133 if ((IS_ITEMP (IC_RESULT (ic)) &&
3134 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3135 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3136 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3137 IS_TRUE_SYMOP (IC_RESULT (ic)))
3141 aopOp (IC_RESULT (ic), ic, FALSE);
3144 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3146 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3149 /* adjust the stack for parameters if required */
3153 if (ic->parmBytes > 3)
3155 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3156 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3158 emitcode ("mov", "F0,c");
3162 emitcode ("mov", "a,%s", spname);
3163 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3164 emitcode ("mov", "%s,a", spname);
3167 for (i = 0; i < ic->parmBytes; i++)
3168 emitcode ("dec", "%s", spname);
3171 // /* if register bank was saved then unsave them */
3173 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3175 /* if we had saved some registers then unsave them */
3176 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3177 unsaveRegisters (ic);
3179 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3182 emitcode ("mov", "c,F0");
3184 aopOp (IC_RESULT (ic), ic, FALSE);
3185 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3190 /*-----------------------------------------------------------------*/
3191 /* resultRemat - result is rematerializable */
3192 /*-----------------------------------------------------------------*/
3194 resultRemat (iCode * ic)
3196 if (SKIP_IC (ic) || ic->op == IFX)
3199 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3201 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3202 if (sym->remat && !POINTER_SET (ic))
3209 #if defined(__BORLANDC__) || defined(_MSC_VER)
3210 #define STRCASECMP stricmp
3212 #define STRCASECMP strcasecmp
3215 /*-----------------------------------------------------------------*/
3216 /* inExcludeList - return 1 if the string is in exclude Reg list */
3217 /*-----------------------------------------------------------------*/
3219 regsCmp(void *p1, void *p2)
3221 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3225 inExcludeList (char *s)
3227 const char *p = setFirstItem(options.excludeRegsSet);
3229 if (p == NULL || STRCASECMP(p, "none") == 0)
3233 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3236 /*-----------------------------------------------------------------*/
3237 /* genFunction - generated code for function entry */
3238 /*-----------------------------------------------------------------*/
3240 genFunction (iCode * ic)
3242 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3244 bool switchedPSW = FALSE;
3245 int calleesaves_saved_register = -1;
3246 int stackAdjust = sym->stack;
3247 int accIsFree = sym->recvSize < 4;
3248 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3249 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3252 /* create the function header */
3253 emitcode (";", "-----------------------------------------");
3254 emitcode (";", " function %s", sym->name);
3255 emitcode (";", "-----------------------------------------");
3257 emitcode ("", "%s:", sym->rname);
3258 ftype = operandType (IC_LEFT (ic));
3259 _G.currentFunc = sym;
3261 if (IFFUNC_ISNAKED(ftype))
3263 emitcode(";", "naked function: no prologue.");
3267 /* here we need to generate the equates for the
3268 register bank if required */
3269 if (FUNC_REGBANK (ftype) != rbank)
3273 rbank = FUNC_REGBANK (ftype);
3274 for (i = 0; i < mcs51_nRegs; i++)
3276 if (regs8051[i].type != REG_BIT)
3278 if (strcmp (regs8051[i].base, "0") == 0)
3279 emitcode ("", "%s = 0x%02x",
3281 8 * rbank + regs8051[i].offset);
3283 emitcode ("", "%s = %s + 0x%02x",
3286 8 * rbank + regs8051[i].offset);
3291 /* if this is an interrupt service routine then
3292 save acc, b, dpl, dph */
3293 if (IFFUNC_ISISR (sym->type))
3295 if (!inExcludeList ("acc"))
3296 emitcode ("push", "acc");
3297 if (!inExcludeList ("b"))
3298 emitcode ("push", "b");
3299 if (!inExcludeList ("dpl"))
3300 emitcode ("push", "dpl");
3301 if (!inExcludeList ("dph"))
3302 emitcode ("push", "dph");
3303 /* if this isr has no bank i.e. is going to
3304 run with bank 0 , then we need to save more
3306 if (!FUNC_REGBANK (sym->type))
3310 /* if this function does not call any other
3311 function then we can be economical and
3312 save only those registers that are used */
3313 if (!IFFUNC_HASFCALL(sym->type))
3315 /* if any registers used */
3318 bool bits_pushed = FALSE;
3319 /* save the registers used */
3320 for (i = 0; i < sym->regsUsed->size; i++)
3322 if (bitVectBitValue (sym->regsUsed, i))
3323 bits_pushed = pushReg (i, bits_pushed);
3329 /* this function has a function call. We cannot
3330 determine register usage so we will have to push the
3332 saveRBank (0, ic, FALSE);
3333 if (options.parms_in_bank1) {
3334 for (i=0; i < 8 ; i++ ) {
3335 emitcode ("push","%s",rb1regs[i]);
3342 /* This ISR uses a non-zero bank.
3344 * We assume that the bank is available for our
3347 * However, if this ISR calls a function which uses some
3348 * other bank, we must save that bank entirely.
3350 unsigned long banksToSave = 0;
3352 if (IFFUNC_HASFCALL(sym->type))
3355 #define MAX_REGISTER_BANKS 4
3360 for (i = ic; i; i = i->next)
3362 if (i->op == ENDFUNCTION)
3364 /* we got to the end OK. */
3372 dtype = operandType (IC_LEFT(i));
3374 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3376 /* Mark this bank for saving. */
3377 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3379 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3383 banksToSave |= (1 << FUNC_REGBANK(dtype));
3386 /* And note that we don't need to do it in
3394 /* This is a mess; we have no idea what
3395 * register bank the called function might
3398 * The only thing I can think of to do is
3399 * throw a warning and hope.
3401 werror(W_FUNCPTR_IN_USING_ISR);
3405 if (banksToSave && options.useXstack)
3407 /* Since we aren't passing it an ic,
3408 * saveRBank will assume r0 is available to abuse.
3410 * So switch to our (trashable) bank now, so
3411 * the caller's R0 isn't trashed.
3413 emitcode ("push", "psw");
3414 emitcode ("mov", "psw,#0x%02x",
3415 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3419 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3421 if (banksToSave & (1 << ix))
3423 saveRBank(ix, NULL, FALSE);
3427 // TODO: this needs a closer look
3428 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3431 /* Set the register bank to the desired value if nothing else */
3432 /* has done so yet. */
3435 emitcode ("push", "psw");
3436 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3441 /* This is a non-ISR function. The caller has already switched register */
3442 /* banks, if necessary, so just handle the callee-saves option. */
3444 /* if callee-save to be used for this function
3445 then save the registers being used in this function */
3446 if (IFFUNC_CALLEESAVES(sym->type))
3450 /* if any registers used */
3453 bool bits_pushed = FALSE;
3454 /* save the registers used */
3455 for (i = 0; i < sym->regsUsed->size; i++)
3457 if (bitVectBitValue (sym->regsUsed, i))
3459 /* remember one saved register for later usage */
3460 if (calleesaves_saved_register < 0)
3461 calleesaves_saved_register = i;
3462 bits_pushed = pushReg (i, bits_pushed);
3472 if (options.useXstack)
3474 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3476 emitcode ("mov", "r0,%s", spname);
3477 emitcode ("inc", "%s", spname);
3478 emitcode ("xch", "a,_bpx");
3479 emitcode ("movx", "@r0,a");
3480 emitcode ("inc", "r0");
3481 emitcode ("mov", "a,r0");
3482 emitcode ("xch", "a,_bpx");
3486 emitcode ("push", "_bp"); /* save the callers stack */
3487 emitcode ("mov", "_bp,sp");
3492 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3494 /* set up the stack */
3495 emitcode ("push", "_bp"); /* save the callers stack */
3496 emitcode ("mov", "_bp,sp");
3501 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3502 /* before setting up the stack frame completely. */
3503 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3505 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3509 if (rsym && rsym->regType == REG_CND)
3511 if (rsym && (rsym->accuse || rsym->ruonly))
3513 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3514 rsym = rsym->usl.spillLoc;
3517 /* If the RECEIVE operand immediately spills to the first entry on the */
3518 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3519 /* rather than the usual @r0/r1 machinations. */
3520 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3524 _G.current_iCode = ric;
3525 D(emitcode ("; genReceive",""));
3526 for (ofs=0; ofs < sym->recvSize; ofs++)
3528 if (!strcmp (fReturn[ofs], "a"))
3529 emitcode ("push", "acc");
3531 emitcode ("push", fReturn[ofs]);
3533 stackAdjust -= sym->recvSize;
3536 assert (stackAdjust>=0);
3539 _G.current_iCode = ic;
3543 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3544 /* to free up the accumulator. */
3545 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3549 _G.current_iCode = ric;
3550 D(emitcode ("; genReceive",""));
3551 for (ofs=0; ofs < sym->recvSize; ofs++)
3553 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3555 _G.current_iCode = ic;
3561 /* adjust the stack for the function */
3564 int i = stackAdjust;
3566 werror (W_STACK_OVERFLOW, sym->name);
3568 if (i > 3 && accIsFree)
3570 emitcode ("mov", "a,sp");
3571 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3572 emitcode ("mov", "sp,a");
3576 /* The accumulator is not free, so we will need another register */
3577 /* to clobber. No need to worry about a possible conflict with */
3578 /* the above early RECEIVE optimizations since they would have */
3579 /* freed the accumulator if they were generated. */
3581 if (IFFUNC_CALLEESAVES(sym->type))
3583 /* if it's a callee-saves function we need a saved register */
3584 if (calleesaves_saved_register >= 0)
3586 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3587 emitcode ("mov", "a,sp");
3588 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3589 emitcode ("mov", "sp,a");
3590 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3593 /* do it the hard way */
3595 emitcode ("inc", "sp");
3599 /* not callee-saves, we can clobber r0 */
3600 emitcode ("mov", "r0,a");
3601 emitcode ("mov", "a,sp");
3602 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3603 emitcode ("mov", "sp,a");
3604 emitcode ("mov", "a,r0");
3609 emitcode ("inc", "sp");
3614 char i = ((char) sym->xstack & 0xff);
3616 if (i > 3 && accIsFree)
3618 emitcode ("mov", "a,_spx");
3619 emitcode ("add", "a,#0x%02x", i & 0xff);
3620 emitcode ("mov", "_spx,a");
3624 emitcode ("push", "acc");
3625 emitcode ("mov", "a,_spx");
3626 emitcode ("add", "a,#0x%02x", i & 0xff);
3627 emitcode ("mov", "_spx,a");
3628 emitcode ("pop", "acc");
3633 emitcode ("inc", "_spx");
3637 /* if critical function then turn interrupts off */
3638 if (IFFUNC_ISCRITICAL (ftype))
3640 symbol *tlbl = newiTempLabel (NULL);
3641 emitcode ("setb", "c");
3642 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3643 emitcode ("clr", "c");
3645 emitcode ("push", "psw"); /* save old ea via c in psw */
3649 /*-----------------------------------------------------------------*/
3650 /* genEndFunction - generates epilogue for functions */
3651 /*-----------------------------------------------------------------*/
3653 genEndFunction (iCode * ic)
3655 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3656 lineNode *lnp = lineCurr;
3658 bitVect *regsUsedPrologue;
3659 bitVect *regsUnneeded;
3662 _G.currentFunc = NULL;
3663 if (IFFUNC_ISNAKED(sym->type))
3665 emitcode(";", "naked function: no epilogue.");
3666 if (options.debug && currFunc)
3667 debugFile->writeEndFunction (currFunc, ic, 0);
3671 if (IFFUNC_ISCRITICAL (sym->type))
3673 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3675 emitcode ("rlc", "a"); /* save c in a */
3676 emitcode ("pop", "psw"); /* restore ea via c in psw */
3677 emitcode ("mov", "ea,c");
3678 emitcode ("rrc", "a"); /* restore c from a */
3682 emitcode ("pop", "psw"); /* restore ea via c in psw */
3683 emitcode ("mov", "ea,c");
3687 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3689 if (options.useXstack)
3693 emitcode ("mov", "sp,_bp");
3694 emitcode ("pop", "_bp");
3696 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3698 emitcode ("xch", "a,_bpx");
3699 emitcode ("mov", "r0,a");
3700 emitcode ("dec", "r0");
3701 emitcode ("movx", "a,@r0");
3702 emitcode ("xch", "a,_bpx");
3703 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3706 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3709 emitcode ("mov", "sp,_bp");
3710 emitcode ("pop", "_bp");
3714 /* restore the register bank */
3715 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3717 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3718 || !options.useXstack)
3720 /* Special case of ISR using non-zero bank with useXstack
3723 emitcode ("pop", "psw");
3727 if (IFFUNC_ISISR (sym->type))
3730 /* now we need to restore the registers */
3731 /* if this isr has no bank i.e. is going to
3732 run with bank 0 , then we need to save more
3734 if (!FUNC_REGBANK (sym->type))
3737 /* if this function does not call any other
3738 function then we can be economical and
3739 save only those registers that are used */
3740 if (!IFFUNC_HASFCALL(sym->type))
3742 /* if any registers used */
3745 bool bits_popped = FALSE;
3746 /* save the registers used */
3747 for (i = sym->regsUsed->size; i >= 0; i--)
3749 if (bitVectBitValue (sym->regsUsed, i))
3750 bits_popped = popReg (i, bits_popped);
3756 if (options.parms_in_bank1) {
3757 for (i = 7 ; i >= 0 ; i-- ) {
3758 emitcode ("pop","%s",rb1regs[i]);
3761 /* this function has a function call cannot
3762 determines register usage so we will have to pop the
3764 unsaveRBank (0, ic, FALSE);
3769 /* This ISR uses a non-zero bank.
3771 * Restore any register banks saved by genFunction
3774 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3777 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3779 if (savedBanks & (1 << ix))
3781 unsaveRBank(ix, NULL, FALSE);
3785 if (options.useXstack)
3787 /* Restore bank AFTER calling unsaveRBank,
3788 * since it can trash r0.
3790 emitcode ("pop", "psw");
3794 if (!inExcludeList ("dph"))
3795 emitcode ("pop", "dph");
3796 if (!inExcludeList ("dpl"))
3797 emitcode ("pop", "dpl");
3798 if (!inExcludeList ("b"))
3799 emitcode ("pop", "b");
3800 if (!inExcludeList ("acc"))
3801 emitcode ("pop", "acc");
3803 /* if debug then send end of function */
3804 if (options.debug && currFunc)
3806 debugFile->writeEndFunction (currFunc, ic, 1);
3809 emitcode ("reti", "");
3813 if (IFFUNC_CALLEESAVES(sym->type))
3817 /* if any registers used */
3820 /* save the registers used */
3821 for (i = sym->regsUsed->size; i >= 0; i--)
3823 if (bitVectBitValue (sym->regsUsed, i) ||
3824 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3825 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3828 else if (mcs51_ptrRegReq)
3830 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3831 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3836 /* if debug then send end of function */
3837 if (options.debug && currFunc)
3839 debugFile->writeEndFunction (currFunc, ic, 1);
3842 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3844 emitcode ("ljmp", "__sdcc_banked_ret");
3848 emitcode ("ret", "");
3852 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3855 /* If this was an interrupt handler using bank 0 that called another */
3856 /* function, then all registers must be saved; nothing to optimized. */
3857 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3858 && !FUNC_REGBANK(sym->type))
3861 /* There are no push/pops to optimize if not callee-saves or ISR */
3862 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3865 /* If there were stack parameters, we cannot optimize without also */
3866 /* fixing all of the stack offsets; this is too dificult to consider. */
3867 if (FUNC_HASSTACKPARM(sym->type))
3870 /* Compute the registers actually used */
3871 regsUsed = newBitVect (mcs51_nRegs);
3872 regsUsedPrologue = newBitVect (mcs51_nRegs);
3875 if (lnp->ic && lnp->ic->op == FUNCTION)
3876 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3878 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3880 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3881 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3888 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3889 && !bitVectBitValue (regsUsed, CND_IDX))
3891 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3892 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3893 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3894 bitVectUnSetBit (regsUsed, CND_IDX);
3897 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3899 /* If this was an interrupt handler that called another function */
3900 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3901 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3903 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3904 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3905 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3906 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3907 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3910 /* Remove the unneeded push/pops */
3911 regsUnneeded = newBitVect (mcs51_nRegs);
3914 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3916 if (!strncmp(lnp->line, "push", 4))
3918 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3919 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3921 connectLine (lnp->prev, lnp->next);
3922 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3925 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3927 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3928 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3930 connectLine (lnp->prev, lnp->next);
3931 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3938 for (idx = 0; idx < regsUnneeded->size; idx++)
3939 if (bitVectBitValue (regsUnneeded, idx))
3940 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3942 freeBitVect (regsUnneeded);
3943 freeBitVect (regsUsed);
3944 freeBitVect (regsUsedPrologue);
3947 /*-----------------------------------------------------------------*/
3948 /* genRet - generate code for return statement */
3949 /*-----------------------------------------------------------------*/
3953 int size, offset = 0, pushed = 0;
3955 D (emitcode (";", "genRet"));
3957 /* if we have no return value then
3958 just generate the "ret" */
3962 /* we have something to return then
3963 move the return value into place */
3964 aopOp (IC_LEFT (ic), ic, FALSE);
3965 size = AOP_SIZE (IC_LEFT (ic));
3967 if (IS_BIT(_G.currentFunc->etype))
3969 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3976 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3979 l = aopGet (IC_LEFT (ic), offset++,
3981 emitcode ("push", "%s", l);
3986 l = aopGet (IC_LEFT (ic), offset,
3988 if (strcmp (fReturn[offset], l))
3989 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3996 if (strcmp (fReturn[pushed], "a"))
3997 emitcode ("pop", fReturn[pushed]);
3999 emitcode ("pop", "acc");
4001 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4004 /* generate a jump to the return label
4005 if the next is not the return statement */
4006 if (!(ic->next && ic->next->op == LABEL &&
4007 IC_LABEL (ic->next) == returnLabel))
4009 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4013 /*-----------------------------------------------------------------*/
4014 /* genLabel - generates a label */
4015 /*-----------------------------------------------------------------*/
4017 genLabel (iCode * ic)
4019 /* special case never generate */
4020 if (IC_LABEL (ic) == entryLabel)
4023 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4026 /*-----------------------------------------------------------------*/
4027 /* genGoto - generates a ljmp */
4028 /*-----------------------------------------------------------------*/
4030 genGoto (iCode * ic)
4032 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4035 /*-----------------------------------------------------------------*/
4036 /* findLabelBackwards: walks back through the iCode chain looking */
4037 /* for the given label. Returns number of iCode instructions */
4038 /* between that label and given ic. */
4039 /* Returns zero if label not found. */
4040 /*-----------------------------------------------------------------*/
4042 findLabelBackwards (iCode * ic, int key)
4051 /* If we have any pushes or pops, we cannot predict the distance.
4052 I don't like this at all, this should be dealt with in the
4054 if (ic->op == IPUSH || ic->op == IPOP) {
4058 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4067 /*-----------------------------------------------------------------*/
4068 /* genPlusIncr :- does addition with increment if possible */
4069 /*-----------------------------------------------------------------*/
4071 genPlusIncr (iCode * ic)
4073 unsigned int icount;
4074 unsigned int size = getDataSize (IC_RESULT (ic));
4076 /* will try to generate an increment */
4077 /* if the right side is not a literal
4079 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4082 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4084 D(emitcode (";","genPlusIncr"));
4086 /* if increment >=16 bits in register or direct space */
4087 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4088 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4089 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4090 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4091 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4099 /* If the next instruction is a goto and the goto target
4100 * is < 10 instructions previous to this, we can generate
4101 * jumps straight to that target.
4103 if (ic->next && ic->next->op == GOTO
4104 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4105 && labelRange <= 10)
4107 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4108 tlbl = IC_LABEL (ic->next);
4113 tlbl = newiTempLabel (NULL);
4116 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4117 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4118 IS_AOP_PREG (IC_RESULT (ic)))
4119 emitcode ("cjne", "%s,#0x00,%05d$",
4120 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4124 emitcode ("clr", "a");
4125 emitcode ("cjne", "a,%s,%05d$",
4126 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4130 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4133 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4134 IS_AOP_PREG (IC_RESULT (ic)))
4135 emitcode ("cjne", "%s,#0x00,%05d$",
4136 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4139 emitcode ("cjne", "a,%s,%05d$",
4140 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4143 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4147 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4148 IS_AOP_PREG (IC_RESULT (ic)))
4149 emitcode ("cjne", "%s,#0x00,%05d$",
4150 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4154 emitcode ("cjne", "a,%s,%05d$",
4155 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4158 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4168 /* if result is dptr */
4169 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4170 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4171 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4172 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4174 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4180 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4183 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4184 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4186 emitcode ("inc", "dptr");
4191 /* if the literal value of the right hand side
4192 is greater than 4 then it is not worth it */
4196 /* if the sizes are greater than 1 then we cannot */
4197 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4198 AOP_SIZE (IC_LEFT (ic)) > 1)
4201 /* we can if the aops of the left & result match or
4202 if they are in registers and the registers are the
4204 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4208 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4209 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4210 aopPut (IC_RESULT (ic), "a", 0);
4216 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4225 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4226 emitcode ("inc", "a");
4227 aopPut (IC_RESULT (ic), "a", 0);
4234 /*-----------------------------------------------------------------*/
4235 /* outBitAcc - output a bit in acc */
4236 /*-----------------------------------------------------------------*/
4238 outBitAcc (operand * result)
4240 symbol *tlbl = newiTempLabel (NULL);
4241 /* if the result is a bit */
4242 if (AOP_TYPE (result) == AOP_CRY)
4244 aopPut (result, "a", 0);
4248 emitcode ("jz", "%05d$", tlbl->key + 100);
4249 emitcode ("mov", "a,%s", one);
4255 /*-----------------------------------------------------------------*/
4256 /* genPlusBits - generates code for addition of two bits */
4257 /*-----------------------------------------------------------------*/
4259 genPlusBits (iCode * ic)
4261 D (emitcode (";", "genPlusBits"));
4263 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4265 symbol *lbl = newiTempLabel (NULL);
4266 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4268 emitcode ("cpl", "c");
4270 outBitC (IC_RESULT (ic));
4274 emitcode ("clr", "a");
4275 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4276 emitcode ("rlc", "a");
4277 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4278 emitcode ("addc", "a,%s", zero);
4279 outAcc (IC_RESULT (ic));
4284 /* This is the original version of this code.
4286 * This is being kept around for reference,
4287 * because I am not entirely sure I got it right...
4290 adjustArithmeticResult (iCode * ic)
4292 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4293 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4294 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4295 aopPut (IC_RESULT (ic),
4296 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4299 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4300 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4301 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302 aopPut (IC_RESULT (ic),
4303 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4306 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4307 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4308 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4309 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4313 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4314 aopPut (IC_RESULT (ic), buffer, 2);
4318 /* This is the pure and virtuous version of this code.
4319 * I'm pretty certain it's right, but not enough to toss the old
4323 adjustArithmeticResult (iCode * ic)
4325 if (opIsGptr (IC_RESULT (ic)) &&
4326 opIsGptr (IC_LEFT (ic)) &&
4327 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4329 aopPut (IC_RESULT (ic),
4330 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4334 if (opIsGptr (IC_RESULT (ic)) &&
4335 opIsGptr (IC_RIGHT (ic)) &&
4336 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4338 aopPut (IC_RESULT (ic),
4339 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4343 if (opIsGptr (IC_RESULT (ic)) &&
4344 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4345 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4346 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4347 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4350 SNPRINTF (buffer, sizeof(buffer),
4351 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4352 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4357 /*-----------------------------------------------------------------*/
4358 /* genPlus - generates code for addition */
4359 /*-----------------------------------------------------------------*/
4361 genPlus (iCode * ic)
4363 int size, offset = 0;
4366 bool swappedLR = FALSE;
4367 operand *leftOp, *rightOp;
4370 D (emitcode (";", "genPlus"));
4372 /* special cases :- */
4374 aopOp (IC_LEFT (ic), ic, FALSE);
4375 aopOp (IC_RIGHT (ic), ic, FALSE);
4376 aopOp (IC_RESULT (ic), ic, TRUE);
4378 /* if literal, literal on the right or
4379 if left requires ACC or right is already
4381 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4382 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4383 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4385 operand *t = IC_RIGHT (ic);
4386 IC_RIGHT (ic) = IC_LEFT (ic);
4391 /* if both left & right are in bit
4393 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4394 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4400 /* if left in bit space & right literal */
4401 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4402 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4404 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4405 /* if result in bit space */
4406 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4408 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4409 emitcode ("cpl", "c");
4410 outBitC (IC_RESULT (ic));
4414 size = getDataSize (IC_RESULT (ic));
4417 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4418 emitcode ("addc", "a,%s", zero);
4419 aopPut (IC_RESULT (ic), "a", offset++);
4425 /* if I can do an increment instead
4426 of add then GOOD for ME */
4427 if (genPlusIncr (ic) == TRUE)
4430 size = getDataSize (IC_RESULT (ic));
4431 leftOp = IC_LEFT(ic);
4432 rightOp = IC_RIGHT(ic);
4435 /* if this is an add for an array access
4436 at a 256 byte boundary */
4438 && AOP_TYPE (op) == AOP_IMMD
4440 && IS_SPEC (OP_SYM_ETYPE (op))
4441 && SPEC_ABSA (OP_SYM_ETYPE (op))
4442 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4445 D(emitcode ("; genPlus aligned array",""));
4446 aopPut (IC_RESULT (ic),
4447 aopGet (rightOp, 0, FALSE, FALSE),
4450 if( 1 == getDataSize (IC_RIGHT (ic)) )
4452 aopPut (IC_RESULT (ic),
4453 aopGet (leftOp, 1, FALSE, FALSE),
4458 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4459 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4460 aopPut (IC_RESULT (ic), "a", 1);
4465 /* if the lower bytes of a literal are zero skip the addition */
4466 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4468 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4469 (skip_bytes+1 < size))
4474 D(emitcode ("; genPlus shortcut",""));
4479 if( offset >= skip_bytes )
4481 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4484 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4486 emitcode("xch", "a,b");
4487 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4488 emitcode (add, "a,b");
4491 else if (aopGetUsesAcc (leftOp, offset))
4493 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4494 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4498 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4499 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4501 aopPut (IC_RESULT (ic), "a", offset);
4502 add = "addc"; /* further adds must propagate carry */
4506 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4507 isOperandVolatile (IC_RESULT (ic), FALSE))
4510 aopPut (IC_RESULT (ic),
4511 aopGet (leftOp, offset, FALSE, FALSE),
4518 adjustArithmeticResult (ic);
4521 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4524 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4529 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4534 /*-----------------------------------------------------------------*/
4535 /* genMinusDec :- does subtraction with decrement if possible */
4536 /*-----------------------------------------------------------------*/
4538 genMinusDec (iCode * ic)
4540 unsigned int icount;
4541 unsigned int size = getDataSize (IC_RESULT (ic));
4543 /* will try to generate an increment */
4544 /* if the right side is not a literal
4546 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4549 /* if the literal value of the right hand side
4550 is greater than 4 then it is not worth it */
4551 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4554 D (emitcode (";", "genMinusDec"));
4556 /* if decrement >=16 bits in register or direct space */
4557 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4558 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4559 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4560 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4568 /* If the next instruction is a goto and the goto target
4569 * is <= 10 instructions previous to this, we can generate
4570 * jumps straight to that target.
4572 if (ic->next && ic->next->op == GOTO
4573 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4574 && labelRange <= 10)
4576 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4577 tlbl = IC_LABEL (ic->next);
4582 tlbl = newiTempLabel (NULL);
4586 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4587 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4588 IS_AOP_PREG (IC_RESULT (ic)))
4589 emitcode ("cjne", "%s,#0xff,%05d$"
4590 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4594 emitcode ("mov", "a,#0xff");
4595 emitcode ("cjne", "a,%s,%05d$"
4596 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4599 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4602 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4603 IS_AOP_PREG (IC_RESULT (ic)))
4604 emitcode ("cjne", "%s,#0xff,%05d$"
4605 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4609 emitcode ("cjne", "a,%s,%05d$"
4610 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4613 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4617 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4618 IS_AOP_PREG (IC_RESULT (ic)))
4619 emitcode ("cjne", "%s,#0xff,%05d$"
4620 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4624 emitcode ("cjne", "a,%s,%05d$"
4625 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4628 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4637 /* if the sizes are greater than 1 then we cannot */
4638 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4639 AOP_SIZE (IC_LEFT (ic)) > 1)
4642 /* we can if the aops of the left & result match or
4643 if they are in registers and the registers are the
4645 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4649 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4651 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4656 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4661 emitcode ("dec", "%s", l);
4664 if (AOP_NEEDSACC (IC_RESULT (ic)))
4665 aopPut (IC_RESULT (ic), "a", 0);
4672 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4673 emitcode ("dec", "a");
4674 aopPut (IC_RESULT (ic), "a", 0);
4681 /*-----------------------------------------------------------------*/
4682 /* addSign - complete with sign */
4683 /*-----------------------------------------------------------------*/
4685 addSign (operand * result, int offset, int sign)
4687 int size = (getDataSize (result) - offset);
4692 emitcode ("rlc", "a");
4693 emitcode ("subb", "a,acc");
4696 aopPut (result, "a", offset++);
4703 aopPut (result, zero, offset++);
4709 /*-----------------------------------------------------------------*/
4710 /* genMinusBits - generates code for subtraction of two bits */
4711 /*-----------------------------------------------------------------*/
4713 genMinusBits (iCode * ic)
4715 symbol *lbl = newiTempLabel (NULL);
4717 D (emitcode (";", "genMinusBits"));
4719 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4721 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4722 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4723 emitcode ("cpl", "c");
4725 outBitC (IC_RESULT (ic));
4729 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4730 emitcode ("subb", "a,acc");
4731 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4732 emitcode ("inc", "a");
4734 aopPut (IC_RESULT (ic), "a", 0);
4735 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4739 /*-----------------------------------------------------------------*/
4740 /* genMinus - generates code for subtraction */
4741 /*-----------------------------------------------------------------*/
4743 genMinus (iCode * ic)
4745 int size, offset = 0;
4747 D (emitcode (";", "genMinus"));
4749 aopOp (IC_LEFT (ic), ic, FALSE);
4750 aopOp (IC_RIGHT (ic), ic, FALSE);
4751 aopOp (IC_RESULT (ic), ic, TRUE);
4753 /* special cases :- */
4754 /* if both left & right are in bit space */
4755 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4756 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4762 /* if I can do an decrement instead
4763 of subtract then GOOD for ME */
4764 if (genMinusDec (ic) == TRUE)
4767 size = getDataSize (IC_RESULT (ic));
4769 /* if literal, add a,#-lit, else normal subb */
4770 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4772 unsigned long lit = 0L;
4773 bool useCarry = FALSE;
4775 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4780 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4782 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4783 if (!offset && !size && lit== (unsigned long) -1)
4785 emitcode ("dec", "a");
4789 /* first add without previous c */
4790 emitcode ("add", "a,#0x%02x",
4791 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4796 emitcode ("addc", "a,#0x%02x",
4797 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4799 aopPut (IC_RESULT (ic), "a", offset++);
4803 /* no need to add zeroes */
4804 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4806 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4815 operand *leftOp, *rightOp;
4817 leftOp = IC_LEFT(ic);
4818 rightOp = IC_RIGHT(ic);
4822 if (aopGetUsesAcc(rightOp, offset)) {
4823 if (aopGetUsesAcc(leftOp, offset)) {
4826 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4828 emitcode ("mov", "b,a");
4831 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4832 emitcode ("subb", "a,b");
4835 /* reverse subtraction with 2's complement */
4837 emitcode( "setb", "c");
4839 emitcode( "cpl", "c");
4840 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4841 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4842 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4843 emitcode("cpl", "a");
4844 if (size) /* skip if last byte */
4845 emitcode( "cpl", "c");
4848 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4851 emitcode ("subb", "a,%s",
4852 aopGet(rightOp, offset, FALSE, TRUE));
4855 aopPut (IC_RESULT (ic), "a", offset++);
4859 adjustArithmeticResult (ic);
4862 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4863 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4868 /*-----------------------------------------------------------------*/
4869 /* genMultbits :- multiplication of bits */
4870 /*-----------------------------------------------------------------*/
4872 genMultbits (operand * left,
4876 D (emitcode (";", "genMultbits"));
4878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4879 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4883 /*-----------------------------------------------------------------*/
4884 /* genMultOneByte : 8*8=8/16 bit multiplication */
4885 /*-----------------------------------------------------------------*/
4887 genMultOneByte (operand * left,
4892 int size = AOP_SIZE (result);
4893 bool runtimeSign, compiletimeSign;
4894 bool lUnsigned, rUnsigned, pushedB;
4896 D (emitcode (";", "genMultOneByte"));
4898 if (size < 1 || size > 2)
4900 /* this should never happen */
4901 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4902 AOP_SIZE(result), __FILE__, lineno);
4906 /* (if two literals: the value is computed before) */
4907 /* if one literal, literal on the right */
4908 if (AOP_TYPE (left) == AOP_LIT)
4913 /* emitcode (";", "swapped left and right"); */
4915 /* if no literal, unsigned on the right: shorter code */
4916 if ( AOP_TYPE (right) != AOP_LIT
4917 && SPEC_USIGN (getSpec (operandType (left))))
4924 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4925 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4929 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4930 no need to take care about the signedness! */
4931 || (lUnsigned && rUnsigned))
4933 /* just an unsigned 8 * 8 = 8 multiply
4935 /* emitcode (";","unsigned"); */
4936 /* TODO: check for accumulator clash between left & right aops? */
4938 if (AOP_TYPE (right) == AOP_LIT)
4940 /* moving to accumulator first helps peepholes */
4941 MOVA (aopGet (left, 0, FALSE, FALSE));
4942 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4946 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4947 MOVA (aopGet (left, 0, FALSE, FALSE));
4950 emitcode ("mul", "ab");
4951 aopPut (result, "a", 0);
4953 aopPut (result, "b", 1);
4959 /* we have to do a signed multiply */
4960 /* emitcode (";", "signed"); */
4962 /* now sign adjust for both left & right */
4964 /* let's see what's needed: */
4965 /* apply negative sign during runtime */
4966 runtimeSign = FALSE;
4967 /* negative sign from literals */
4968 compiletimeSign = FALSE;
4972 if (AOP_TYPE(left) == AOP_LIT)
4974 /* signed literal */
4975 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4977 compiletimeSign = TRUE;
4980 /* signed but not literal */
4986 if (AOP_TYPE(right) == AOP_LIT)
4988 /* signed literal */
4989 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4991 compiletimeSign ^= TRUE;
4994 /* signed but not literal */
4998 /* initialize F0, which stores the runtime sign */
5001 if (compiletimeSign)
5002 emitcode ("setb", "F0"); /* set sign flag */
5004 emitcode ("clr", "F0"); /* reset sign flag */
5007 /* save the signs of the operands */
5008 if (AOP_TYPE(right) == AOP_LIT)
5010 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5012 if (!rUnsigned && val < 0)
5013 emitcode ("mov", "b,#0x%02x", -val);
5015 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5017 else /* ! literal */
5019 if (rUnsigned) /* emitcode (";", "signed"); */
5020 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5023 MOVA (aopGet (right, 0, FALSE, FALSE));
5024 lbl = newiTempLabel (NULL);
5025 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5026 emitcode ("cpl", "F0"); /* complement sign flag */
5027 emitcode ("cpl", "a"); /* 2's complement */
5028 emitcode ("inc", "a");
5030 emitcode ("mov", "b,a");
5034 if (AOP_TYPE(left) == AOP_LIT)
5036 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5038 if (!lUnsigned && val < 0)
5039 emitcode ("mov", "a,#0x%02x", -val);
5041 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5043 else /* ! literal */
5045 MOVA (aopGet (left, 0, FALSE, FALSE));
5049 lbl = newiTempLabel (NULL);
5050 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5051 emitcode ("cpl", "F0"); /* complement sign flag */
5052 emitcode ("cpl", "a"); /* 2's complement */
5053 emitcode ("inc", "a");
5058 /* now the multiplication */
5059 emitcode ("mul", "ab");
5060 if (runtimeSign || compiletimeSign)
5062 lbl = newiTempLabel (NULL);
5064 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5065 emitcode ("cpl", "a"); /* lsb 2's complement */
5067 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5070 emitcode ("add", "a,#1"); /* this sets carry flag */
5071 emitcode ("xch", "a,b");
5072 emitcode ("cpl", "a"); /* msb 2's complement */
5073 emitcode ("addc", "a,#0");
5074 emitcode ("xch", "a,b");
5078 aopPut (result, "a", 0);
5080 aopPut (result, "b", 1);
5085 /*-----------------------------------------------------------------*/
5086 /* genMult - generates code for multiplication */
5087 /*-----------------------------------------------------------------*/
5089 genMult (iCode * ic)
5091 operand *left = IC_LEFT (ic);
5092 operand *right = IC_RIGHT (ic);
5093 operand *result = IC_RESULT (ic);
5095 D (emitcode (";", "genMult"));
5097 /* assign the asmops */
5098 aopOp (left, ic, FALSE);
5099 aopOp (right, ic, FALSE);
5100 aopOp (result, ic, TRUE);
5102 /* special cases first */
5104 if (AOP_TYPE (left) == AOP_CRY &&
5105 AOP_TYPE (right) == AOP_CRY)
5107 genMultbits (left, right, result);
5111 /* if both are of size == 1 */
5112 #if 0 // one of them can be a sloc shared with the result
5113 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5115 if (getSize(operandType(left)) == 1 &&
5116 getSize(operandType(right)) == 1)
5119 genMultOneByte (left, right, result);
5123 /* should have been converted to function call */
5124 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5125 getSize(OP_SYMBOL(right)->type));
5129 freeAsmop (result, NULL, ic, TRUE);
5130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 /*-----------------------------------------------------------------*/
5135 /* genDivbits :- division of bits */
5136 /*-----------------------------------------------------------------*/
5138 genDivbits (operand * left,
5145 D(emitcode ("; genDivbits",""));
5149 /* the result must be bit */
5150 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5151 l = aopGet (left, 0, FALSE, FALSE);
5155 emitcode ("div", "ab");
5156 emitcode ("rrc", "a");
5160 aopPut (result, "c", 0);
5163 /*-----------------------------------------------------------------*/
5164 /* genDivOneByte : 8 bit division */
5165 /*-----------------------------------------------------------------*/
5167 genDivOneByte (operand * left,
5171 bool lUnsigned, rUnsigned, pushedB;
5172 bool runtimeSign, compiletimeSign;
5173 bool accuse = FALSE;
5174 bool pushedA = FALSE;
5178 D(emitcode ("; genDivOneByte",""));
5180 /* Why is it necessary that genDivOneByte() can return an int result?
5183 volatile unsigned char uc;
5184 volatile signed char sc1, sc2;
5197 In all cases a one byte result would overflow, the following cast to int
5198 would return the wrong result.
5200 Two possible solution:
5201 a) cast operands to int, if ((unsigned) / (signed)) or
5202 ((signed) / (signed))
5203 b) return an 16 bit signed int; this is what we're doing here!
5206 size = AOP_SIZE (result) - 1;
5208 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5209 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5213 /* signed or unsigned */
5214 if (lUnsigned && rUnsigned)
5216 /* unsigned is easy */
5217 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5218 MOVA (aopGet (left, 0, FALSE, FALSE));
5219 emitcode ("div", "ab");
5220 aopPut (result, "a", 0);
5222 aopPut (result, zero, offset++);
5228 /* signed is a little bit more difficult */
5230 /* now sign adjust for both left & right */
5232 /* let's see what's needed: */
5233 /* apply negative sign during runtime */
5234 runtimeSign = FALSE;
5235 /* negative sign from literals */
5236 compiletimeSign = FALSE;
5240 if (AOP_TYPE(left) == AOP_LIT)
5242 /* signed literal */
5243 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5245 compiletimeSign = TRUE;
5248 /* signed but not literal */
5254 if (AOP_TYPE(right) == AOP_LIT)
5256 /* signed literal */
5257 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5259 compiletimeSign ^= TRUE;
5262 /* signed but not literal */
5266 /* initialize F0, which stores the runtime sign */
5269 if (compiletimeSign)
5270 emitcode ("setb", "F0"); /* set sign flag */
5272 emitcode ("clr", "F0"); /* reset sign flag */
5275 /* save the signs of the operands */
5276 if (AOP_TYPE(right) == AOP_LIT)
5278 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5280 if (!rUnsigned && val < 0)
5281 emitcode ("mov", "b,#0x%02x", -val);
5283 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5285 else /* ! literal */
5288 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5291 MOVA (aopGet (right, 0, FALSE, FALSE));
5292 lbl = newiTempLabel (NULL);
5293 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5294 emitcode ("cpl", "F0"); /* complement sign flag */
5295 emitcode ("cpl", "a"); /* 2's complement */
5296 emitcode ("inc", "a");
5298 emitcode ("mov", "b,a");
5302 if (AOP_TYPE(left) == AOP_LIT)
5304 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5306 if (!lUnsigned && val < 0)
5307 emitcode ("mov", "a,#0x%02x", -val);
5309 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5311 else /* ! literal */
5313 MOVA (aopGet (left, 0, FALSE, FALSE));
5317 lbl = newiTempLabel (NULL);
5318 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5319 emitcode ("cpl", "F0"); /* complement sign flag */
5320 emitcode ("cpl", "a"); /* 2's complement */
5321 emitcode ("inc", "a");
5326 /* now the division */
5327 emitcode ("div", "ab");
5329 if (runtimeSign || compiletimeSign)
5331 lbl = newiTempLabel (NULL);
5333 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5334 emitcode ("cpl", "a"); /* lsb 2's complement */
5335 emitcode ("inc", "a");
5338 accuse = aopPut (result, "a", 0);
5341 /* msb is 0x00 or 0xff depending on the sign */
5346 emitcode ("push", "acc");
5349 emitcode ("mov", "c,F0");
5350 emitcode ("subb", "a,acc");
5352 aopPut (result, "a", offset++);
5354 else /* compiletimeSign */
5356 if (aopPutUsesAcc (result, "#0xFF", offset))
5358 emitcode ("push", "acc");
5362 aopPut (result, "#0xff", offset++);
5368 aopPut (result, "a", 0);
5370 aopPut (result, zero, offset++);
5374 emitcode ("pop", "acc");
5378 /*-----------------------------------------------------------------*/
5379 /* genDiv - generates code for division */
5380 /*-----------------------------------------------------------------*/
5384 operand *left = IC_LEFT (ic);
5385 operand *right = IC_RIGHT (ic);
5386 operand *result = IC_RESULT (ic);
5388 D (emitcode (";", "genDiv"));
5390 /* assign the amsops */
5391 aopOp (left, ic, FALSE);
5392 aopOp (right, ic, FALSE);
5393 aopOp (result, ic, TRUE);
5395 /* special cases first */
5397 if (AOP_TYPE (left) == AOP_CRY &&
5398 AOP_TYPE (right) == AOP_CRY)
5400 genDivbits (left, right, result);
5404 /* if both are of size == 1 */
5405 if (AOP_SIZE (left) == 1 &&
5406 AOP_SIZE (right) == 1)
5408 genDivOneByte (left, right, result);
5412 /* should have been converted to function call */
5415 freeAsmop (result, NULL, ic, TRUE);
5416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 /*-----------------------------------------------------------------*/
5421 /* genModbits :- modulus of bits */
5422 /*-----------------------------------------------------------------*/
5424 genModbits (operand * left,
5431 D (emitcode (";", "genModbits"));
5435 /* the result must be bit */
5436 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5437 l = aopGet (left, 0, FALSE, FALSE);
5441 emitcode ("div", "ab");
5442 emitcode ("mov", "a,b");
5443 emitcode ("rrc", "a");
5447 aopPut (result, "c", 0);
5450 /*-----------------------------------------------------------------*/
5451 /* genModOneByte : 8 bit modulus */
5452 /*-----------------------------------------------------------------*/
5454 genModOneByte (operand * left,
5458 bool lUnsigned, rUnsigned, pushedB;
5459 bool runtimeSign, compiletimeSign;
5463 D (emitcode (";", "genModOneByte"));
5465 size = AOP_SIZE (result) - 1;
5467 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5468 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5470 /* if right is a literal, check it for 2^n */
5471 if (AOP_TYPE(right) == AOP_LIT)
5473 unsigned char val = abs((int) operandLitValue(right));
5474 symbol *lbl2 = NULL;
5478 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5487 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5488 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5489 /* because iCode should have been changed to genAnd */
5490 /* see file "SDCCopt.c", function "convertToFcall()" */
5492 MOVA (aopGet (left, 0, FALSE, FALSE));
5493 emitcode ("mov", "c,acc.7");
5494 emitcode ("anl", "a,#0x%02x", val - 1);
5495 lbl = newiTempLabel (NULL);
5496 emitcode ("jz", "%05d$", (lbl->key + 100));
5497 emitcode ("jnc", "%05d$", (lbl->key + 100));
5498 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5504 aopPut (result, "a", 0);
5506 aopPut (result, "#0xff", offs2++);
5507 lbl2 = newiTempLabel (NULL);
5508 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5511 aopPut (result, "a", 0);
5513 aopPut (result, zero, offset++);
5527 /* signed or unsigned */
5528 if (lUnsigned && rUnsigned)
5530 /* unsigned is easy */
5531 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5532 MOVA (aopGet (left, 0, FALSE, FALSE));
5533 emitcode ("div", "ab");
5534 aopPut (result, "b", 0);
5536 aopPut (result, zero, offset++);
5542 /* signed is a little bit more difficult */
5544 /* now sign adjust for both left & right */
5546 /* modulus: sign of the right operand has no influence on the result! */
5547 if (AOP_TYPE(right) == AOP_LIT)
5549 signed char val = (char) operandLitValue(right);
5551 if (!rUnsigned && val < 0)
5552 emitcode ("mov", "b,#0x%02x", -val);
5554 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5556 else /* not literal */
5559 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5562 MOVA (aopGet (right, 0, FALSE, FALSE));
5563 lbl = newiTempLabel (NULL);
5564 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5565 emitcode ("cpl", "a"); /* 2's complement */
5566 emitcode ("inc", "a");
5568 emitcode ("mov", "b,a");
5572 /* let's see what's needed: */
5573 /* apply negative sign during runtime */
5574 runtimeSign = FALSE;
5575 /* negative sign from literals */
5576 compiletimeSign = FALSE;
5578 /* sign adjust left side */
5579 if (AOP_TYPE(left) == AOP_LIT)
5581 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5583 if (!lUnsigned && val < 0)
5585 compiletimeSign = TRUE; /* set sign flag */
5586 emitcode ("mov", "a,#0x%02x", -val);
5589 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5591 else /* ! literal */
5593 MOVA (aopGet (left, 0, FALSE, FALSE));
5598 emitcode ("clr", "F0"); /* clear sign flag */
5600 lbl = newiTempLabel (NULL);
5601 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5602 emitcode ("setb", "F0"); /* set sign flag */
5603 emitcode ("cpl", "a"); /* 2's complement */
5604 emitcode ("inc", "a");
5609 /* now the modulus */
5610 emitcode ("div", "ab");
5612 if (runtimeSign || compiletimeSign)
5614 emitcode ("mov", "a,b");
5615 lbl = newiTempLabel (NULL);
5617 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5618 emitcode ("cpl", "a"); /* 2's complement */
5619 emitcode ("inc", "a");
5622 aopPut (result, "a", 0);
5625 /* msb is 0x00 or 0xff depending on the sign */
5628 emitcode ("mov", "c,F0");
5629 emitcode ("subb", "a,acc");
5631 aopPut (result, "a", offset++);
5633 else /* compiletimeSign */
5635 aopPut (result, "#0xff", offset++);
5640 aopPut (result, "b", 0);
5642 aopPut (result, zero, offset++);
5648 /*-----------------------------------------------------------------*/
5649 /* genMod - generates code for division */
5650 /*-----------------------------------------------------------------*/
5654 operand *left = IC_LEFT (ic);
5655 operand *right = IC_RIGHT (ic);
5656 operand *result = IC_RESULT (ic);
5658 D (emitcode (";", "genMod"));
5660 /* assign the asmops */
5661 aopOp (left, ic, FALSE);
5662 aopOp (right, ic, FALSE);
5663 aopOp (result, ic, TRUE);
5665 /* special cases first */
5667 if (AOP_TYPE (left) == AOP_CRY &&
5668 AOP_TYPE (right) == AOP_CRY)
5670 genModbits (left, right, result);
5674 /* if both are of size == 1 */
5675 if (AOP_SIZE (left) == 1 &&
5676 AOP_SIZE (right) == 1)
5678 genModOneByte (left, right, result);
5682 /* should have been converted to function call */
5686 freeAsmop (result, NULL, ic, TRUE);
5687 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691 /*-----------------------------------------------------------------*/
5692 /* genIfxJump :- will create a jump depending on the ifx */
5693 /*-----------------------------------------------------------------*/
5695 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5698 symbol *tlbl = newiTempLabel (NULL);
5701 D (emitcode (";", "genIfxJump"));
5703 /* if true label then we jump if condition
5707 jlbl = IC_TRUE (ic);
5708 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5709 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5713 /* false label is present */
5714 jlbl = IC_FALSE (ic);
5715 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5716 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5718 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5719 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5721 emitcode (inst, "%05d$", tlbl->key + 100);
5722 freeForBranchAsmop (result);
5723 freeForBranchAsmop (right);
5724 freeForBranchAsmop (left);
5725 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5728 /* mark the icode as generated */
5732 /*-----------------------------------------------------------------*/
5733 /* genCmp :- greater or less than comparison */
5734 /*-----------------------------------------------------------------*/
5736 genCmp (operand * left, operand * right,
5737 operand * result, iCode * ifx, int sign, iCode *ic)
5739 int size, offset = 0;
5740 unsigned long lit = 0L;
5743 D (emitcode (";", "genCmp"));
5745 /* if left & right are bit variables */
5746 if (AOP_TYPE (left) == AOP_CRY &&
5747 AOP_TYPE (right) == AOP_CRY)
5749 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5750 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5754 /* subtract right from left if at the
5755 end the carry flag is set then we know that
5756 left is greater than right */
5757 size = max (AOP_SIZE (left), AOP_SIZE (right));
5759 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5760 if ((size == 1) && !sign &&
5761 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5763 symbol *lbl = newiTempLabel (NULL);
5764 emitcode ("cjne", "%s,%s,%05d$",
5765 aopGet (left, offset, FALSE, FALSE),
5766 aopGet (right, offset, FALSE, FALSE),
5772 if (AOP_TYPE (right) == AOP_LIT)
5774 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5775 /* optimize if(x < 0) or if(x >= 0) */
5784 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5785 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5787 genIfxJump (ifx, "acc.7", left, right, result);
5788 freeAsmop (right, NULL, ic, TRUE);
5789 freeAsmop (left, NULL, ic, TRUE);
5795 emitcode ("rlc", "a");
5802 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5803 while (size && (bytelit == 0))
5806 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5812 MOVA (aopGet (left, offset, FALSE, FALSE));
5813 if (sign && size == 0)
5815 emitcode ("xrl", "a,#0x80");
5816 emitcode ("subb", "a,#0x%02x",
5817 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5821 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5831 bool pushedB = FALSE;
5832 rightInB = aopGetUsesAcc(right, offset);
5836 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5838 MOVA (aopGet (left, offset, FALSE, FALSE));
5839 if (sign && size == 0)
5841 emitcode ("xrl", "a,#0x80");
5846 MOVB (aopGet (right, offset, FALSE, FALSE));
5848 emitcode ("xrl", "b,#0x80");
5849 emitcode ("subb", "a,b");
5854 emitcode ("subb", "a,b");
5856 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5874 /* if the result is used in the next
5875 ifx conditional branch then generate
5876 code a little differently */
5879 genIfxJump (ifx, "c", NULL, NULL, result);
5885 /* leave the result in acc */
5889 /*-----------------------------------------------------------------*/
5890 /* genCmpGt :- greater than comparison */
5891 /*-----------------------------------------------------------------*/
5893 genCmpGt (iCode * ic, iCode * ifx)
5895 operand *left, *right, *result;
5896 sym_link *letype, *retype;
5899 D (emitcode (";", "genCmpGt"));
5901 left = IC_LEFT (ic);
5902 right = IC_RIGHT (ic);
5903 result = IC_RESULT (ic);
5905 letype = getSpec (operandType (left));
5906 retype = getSpec (operandType (right));
5907 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5908 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5909 /* assign the amsops */
5910 aopOp (result, ic, TRUE);
5911 aopOp (left, ic, FALSE);
5912 aopOp (right, ic, FALSE);
5914 genCmp (right, left, result, ifx, sign, ic);
5916 freeAsmop (result, NULL, ic, TRUE);
5919 /*-----------------------------------------------------------------*/
5920 /* genCmpLt - less than comparisons */
5921 /*-----------------------------------------------------------------*/
5923 genCmpLt (iCode * ic, iCode * ifx)
5925 operand *left, *right, *result;
5926 sym_link *letype, *retype;
5929 D (emitcode (";", "genCmpLt"));
5931 left = IC_LEFT (ic);
5932 right = IC_RIGHT (ic);
5933 result = IC_RESULT (ic);
5935 letype = getSpec (operandType (left));
5936 retype = getSpec (operandType (right));
5937 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5938 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5939 /* assign the amsops */
5940 aopOp (result, ic, TRUE);
5941 aopOp (left, ic, FALSE);
5942 aopOp (right, ic, FALSE);
5944 genCmp (left, right, result, ifx, sign, ic);
5946 freeAsmop (result, NULL, ic, TRUE);
5949 /*-----------------------------------------------------------------*/
5950 /* gencjneshort - compare and jump if not equal */
5951 /*-----------------------------------------------------------------*/
5953 gencjneshort (operand * left, operand * right, symbol * lbl)
5955 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5957 unsigned long lit = 0L;
5959 D (emitcode (";", "gencjneshort"));
5961 /* if the left side is a literal or
5962 if the right is in a pointer register and left
5964 if ((AOP_TYPE (left) == AOP_LIT) ||
5965 (AOP_TYPE (left) == AOP_IMMD) ||
5966 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5973 if (AOP_TYPE (right) == AOP_LIT)
5974 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5976 /* if the right side is a literal then anything goes */
5977 if (AOP_TYPE (right) == AOP_LIT &&
5978 AOP_TYPE (left) != AOP_DIR &&
5979 AOP_TYPE (left) != AOP_IMMD)
5983 emitcode ("cjne", "%s,%s,%05d$",
5984 aopGet (left, offset, FALSE, FALSE),
5985 aopGet (right, offset, FALSE, FALSE),
5991 /* if the right side is in a register or in direct space or
5992 if the left is a pointer register & right is not */
5993 else if (AOP_TYPE (right) == AOP_REG ||
5994 AOP_TYPE (right) == AOP_DIR ||
5995 AOP_TYPE (right) == AOP_LIT ||
5996 AOP_TYPE (right) == AOP_IMMD ||
5997 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5998 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6002 MOVA (aopGet (left, offset, FALSE, FALSE));
6003 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6004 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6005 emitcode ("jnz", "%05d$", lbl->key + 100);
6007 emitcode ("cjne", "a,%s,%05d$",
6008 aopGet (right, offset, FALSE, TRUE),
6015 /* right is a pointer reg need both a & b */
6018 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6019 wassertl(!BINUSE, "B was in use");
6020 MOVB (aopGet (left, offset, FALSE, FALSE));
6021 MOVA (aopGet (right, offset, FALSE, FALSE));
6022 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6028 /*-----------------------------------------------------------------*/
6029 /* gencjne - compare and jump if not equal */
6030 /*-----------------------------------------------------------------*/
6032 gencjne (operand * left, operand * right, symbol * lbl)
6034 symbol *tlbl = newiTempLabel (NULL);
6036 D (emitcode (";", "gencjne"));
6038 gencjneshort (left, right, lbl);
6040 emitcode ("mov", "a,%s", one);
6041 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6043 emitcode ("clr", "a");
6047 /*-----------------------------------------------------------------*/
6048 /* genCmpEq - generates code for equal to */
6049 /*-----------------------------------------------------------------*/
6051 genCmpEq (iCode * ic, iCode * ifx)
6053 bool swappedLR = FALSE;
6054 operand *left, *right, *result;
6056 D (emitcode (";", "genCmpEq"));
6058 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6059 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6060 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6062 /* if literal, literal on the right or
6063 if the right is in a pointer register and left
6065 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6066 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6068 operand *t = IC_RIGHT (ic);
6069 IC_RIGHT (ic) = IC_LEFT (ic);
6074 if (ifx && !AOP_SIZE (result))
6077 /* if they are both bit variables */
6078 if (AOP_TYPE (left) == AOP_CRY &&
6079 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6081 if (AOP_TYPE (right) == AOP_LIT)
6083 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6086 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6087 emitcode ("cpl", "c");
6091 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6095 emitcode ("clr", "c");
6097 /* AOP_TYPE(right) == AOP_CRY */
6101 symbol *lbl = newiTempLabel (NULL);
6102 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6103 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6104 emitcode ("cpl", "c");
6107 /* if true label then we jump if condition
6109 tlbl = newiTempLabel (NULL);
6112 emitcode ("jnc", "%05d$", tlbl->key + 100);
6113 freeForBranchAsmop (result);
6114 freeForBranchAsmop (right);
6115 freeForBranchAsmop (left);
6116 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6120 emitcode ("jc", "%05d$", tlbl->key + 100);
6121 freeForBranchAsmop (result);
6122 freeForBranchAsmop (right);
6123 freeForBranchAsmop (left);
6124 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6130 tlbl = newiTempLabel (NULL);
6131 gencjneshort (left, right, tlbl);
6134 freeForBranchAsmop (result);
6135 freeForBranchAsmop (right);
6136 freeForBranchAsmop (left);
6137 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6142 symbol *lbl = newiTempLabel (NULL);
6143 emitcode ("sjmp", "%05d$", lbl->key + 100);
6145 freeForBranchAsmop (result);
6146 freeForBranchAsmop (right);
6147 freeForBranchAsmop (left);
6148 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6152 /* mark the icode as generated */
6157 /* if they are both bit variables */
6158 if (AOP_TYPE (left) == AOP_CRY &&
6159 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6161 if (AOP_TYPE (right) == AOP_LIT)
6163 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6166 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6167 emitcode ("cpl", "c");
6171 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6175 emitcode ("clr", "c");
6177 /* AOP_TYPE(right) == AOP_CRY */
6181 symbol *lbl = newiTempLabel (NULL);
6182 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6183 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6184 emitcode ("cpl", "c");
6188 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6195 genIfxJump (ifx, "c", left, right, result);
6198 /* if the result is used in an arithmetic operation
6199 then put the result in place */
6204 gencjne (left, right, newiTempLabel (NULL));
6205 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6207 aopPut (result, "a", 0);
6212 genIfxJump (ifx, "a", left, right, result);
6215 /* if the result is used in an arithmetic operation
6216 then put the result in place */
6217 if (AOP_TYPE (result) != AOP_CRY)
6219 /* leave the result in acc */
6223 freeAsmop (result, NULL, ic, TRUE);
6226 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6227 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6231 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236 /*-----------------------------------------------------------------*/
6237 /* ifxForOp - returns the icode containing the ifx for operand */
6238 /*-----------------------------------------------------------------*/
6240 ifxForOp (operand * op, iCode * ic)
6242 /* if true symbol then needs to be assigned */
6243 if (IS_TRUE_SYMOP (op))
6246 /* if this has register type condition and
6247 the next instruction is ifx with the same operand
6248 and live to of the operand is upto the ifx only then */
6250 ic->next->op == IFX &&
6251 IC_COND (ic->next)->key == op->key &&
6252 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6258 /*-----------------------------------------------------------------*/
6259 /* hasInc - operand is incremented before any other use */
6260 /*-----------------------------------------------------------------*/
6262 hasInc (operand *op, iCode *ic, int osize)
6264 sym_link *type = operandType(op);
6265 sym_link *retype = getSpec (type);
6266 iCode *lic = ic->next;
6269 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6270 if (!IS_SYMOP(op)) return NULL;
6272 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6273 if (IS_AGGREGATE(type->next)) return NULL;
6274 if (osize != (isize = getSize(type->next))) return NULL;
6277 /* if operand of the form op = op + <sizeof *op> */
6278 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6279 isOperandEqual(IC_RESULT(lic),op) &&
6280 isOperandLiteral(IC_RIGHT(lic)) &&
6281 operandLitValue(IC_RIGHT(lic)) == isize) {
6284 /* if the operand used or deffed */
6285 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6288 /* if GOTO or IFX */
6289 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6295 /*-----------------------------------------------------------------*/
6296 /* genAndOp - for && operation */
6297 /*-----------------------------------------------------------------*/
6299 genAndOp (iCode * ic)
6301 operand *left, *right, *result;
6304 D (emitcode (";", "genAndOp"));
6306 /* note here that && operations that are in an
6307 if statement are taken away by backPatchLabels
6308 only those used in arthmetic operations remain */
6309 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6310 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6311 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6313 /* if both are bit variables */
6314 if (AOP_TYPE (left) == AOP_CRY &&
6315 AOP_TYPE (right) == AOP_CRY)
6317 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6318 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6323 tlbl = newiTempLabel (NULL);
6325 emitcode ("jz", "%05d$", tlbl->key + 100);
6331 freeAsmop (result, NULL, ic, TRUE);
6332 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6333 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6337 /*-----------------------------------------------------------------*/
6338 /* genOrOp - for || operation */
6339 /*-----------------------------------------------------------------*/
6341 genOrOp (iCode * ic)
6343 operand *left, *right, *result;
6346 D (emitcode (";", "genOrOp"));
6348 /* note here that || operations that are in an
6349 if statement are taken away by backPatchLabels
6350 only those used in arthmetic operations remain */
6351 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6352 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6353 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6355 /* if both are bit variables */
6356 if (AOP_TYPE (left) == AOP_CRY &&
6357 AOP_TYPE (right) == AOP_CRY)
6359 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6360 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6365 tlbl = newiTempLabel (NULL);
6367 emitcode ("jnz", "%05d$", tlbl->key + 100);
6373 freeAsmop (result, NULL, ic, TRUE);
6374 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6375 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6378 /*-----------------------------------------------------------------*/
6379 /* isLiteralBit - test if lit == 2^n */
6380 /*-----------------------------------------------------------------*/
6382 isLiteralBit (unsigned long lit)
6384 unsigned long pw[32] =
6385 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6386 0x100L, 0x200L, 0x400L, 0x800L,
6387 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6388 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6389 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6390 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6391 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6394 for (idx = 0; idx < 32; idx++)
6400 /*-----------------------------------------------------------------*/
6401 /* continueIfTrue - */
6402 /*-----------------------------------------------------------------*/
6404 continueIfTrue (iCode * ic)
6407 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6411 /*-----------------------------------------------------------------*/
6413 /*-----------------------------------------------------------------*/
6415 jumpIfTrue (iCode * ic)
6418 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6422 /*-----------------------------------------------------------------*/
6423 /* jmpTrueOrFalse - */
6424 /*-----------------------------------------------------------------*/
6426 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6428 // ugly but optimized by peephole
6431 symbol *nlbl = newiTempLabel (NULL);
6432 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6434 freeForBranchAsmop (result);
6435 freeForBranchAsmop (right);
6436 freeForBranchAsmop (left);
6437 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6442 freeForBranchAsmop (result);
6443 freeForBranchAsmop (right);
6444 freeForBranchAsmop (left);
6445 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6451 /*-----------------------------------------------------------------*/
6452 /* genAnd - code for and */
6453 /*-----------------------------------------------------------------*/
6455 genAnd (iCode * ic, iCode * ifx)
6457 operand *left, *right, *result;
6458 int size, offset = 0;
6459 unsigned long lit = 0L;
6463 D (emitcode (";", "genAnd"));
6465 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6466 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6467 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6470 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6472 AOP_TYPE (left), AOP_TYPE (right));
6473 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6475 AOP_SIZE (left), AOP_SIZE (right));
6478 /* if left is a literal & right is not then exchange them */
6479 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6480 AOP_NEEDSACC (left))
6482 operand *tmp = right;
6487 /* if result = right then exchange left and right */
6488 if (sameRegs (AOP (result), AOP (right)))
6490 operand *tmp = right;
6495 /* if right is bit then exchange them */
6496 if (AOP_TYPE (right) == AOP_CRY &&
6497 AOP_TYPE (left) != AOP_CRY)
6499 operand *tmp = right;
6503 if (AOP_TYPE (right) == AOP_LIT)
6504 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6506 size = AOP_SIZE (result);
6509 // result = bit & yy;
6510 if (AOP_TYPE (left) == AOP_CRY)
6512 // c = bit & literal;
6513 if (AOP_TYPE (right) == AOP_LIT)
6517 if (size && sameRegs (AOP (result), AOP (left)))
6520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6525 if (size && (AOP_TYPE (result) == AOP_CRY))
6527 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6530 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6535 emitcode ("clr", "c");
6540 if (AOP_TYPE (right) == AOP_CRY)
6543 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6544 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6549 MOVA (aopGet (right, 0, FALSE, FALSE));
6551 emitcode ("rrc", "a");
6552 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6560 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6561 genIfxJump (ifx, "c", left, right, result);
6565 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6566 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6567 if ((AOP_TYPE (right) == AOP_LIT) &&
6568 (AOP_TYPE (result) == AOP_CRY) &&
6569 (AOP_TYPE (left) != AOP_CRY))
6571 int posbit = isLiteralBit (lit);
6576 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6580 switch (posbit & 0x07)
6582 case 0: emitcode ("rrc", "a");
6584 case 7: emitcode ("rlc", "a");
6586 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6595 SNPRINTF (buffer, sizeof(buffer),
6596 "acc.%d", posbit & 0x07);
6597 genIfxJump (ifx, buffer, left, right, result);
6600 {// what is this case? just found it in ds390/gen.c
6601 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6608 symbol *tlbl = newiTempLabel (NULL);
6609 int sizel = AOP_SIZE (left);
6611 emitcode ("setb", "c");
6614 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6616 MOVA (aopGet (left, offset, FALSE, FALSE));
6618 if ((posbit = isLiteralBit (bytelit)) != 0)
6619 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6622 if (bytelit != 0x0FFL)
6623 emitcode ("anl", "a,%s",
6624 aopGet (right, offset, FALSE, TRUE));
6625 emitcode ("jnz", "%05d$", tlbl->key + 100);
6630 // bit = left & literal
6633 emitcode ("clr", "c");
6636 // if(left & literal)
6640 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6650 /* if left is same as result */
6651 if (sameRegs (AOP (result), AOP (left)))
6653 for (; size--; offset++)
6655 if (AOP_TYPE (right) == AOP_LIT)
6657 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6658 if (bytelit == 0x0FF)
6660 /* dummy read of volatile operand */
6661 if (isOperandVolatile (left, FALSE))
6662 MOVA (aopGet (left, offset, FALSE, FALSE));
6666 else if (bytelit == 0)
6668 aopPut (result, zero, offset);
6670 else if (IS_AOP_PREG (result))
6672 MOVA (aopGet (left, offset, FALSE, TRUE));
6673 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6674 aopPut (result, "a", offset);
6677 emitcode ("anl", "%s,%s",
6678 aopGet (left, offset, FALSE, TRUE),
6679 aopGet (right, offset, FALSE, FALSE));
6683 if (AOP_TYPE (left) == AOP_ACC)
6686 emitcode("mov", "a,b");
6687 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6689 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6691 MOVB (aopGet (left, offset, FALSE, FALSE));
6692 MOVA (aopGet (right, offset, FALSE, FALSE));
6693 emitcode ("anl", "a,b");
6694 aopPut (result, "a", offset);
6696 else if (aopGetUsesAcc (left, offset))
6698 MOVA (aopGet (left, offset, FALSE, FALSE));
6699 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6700 aopPut (result, "a", offset);
6704 MOVA (aopGet (right, offset, FALSE, FALSE));
6705 if (IS_AOP_PREG (result))
6707 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6708 aopPut (result, "a", offset);
6711 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6718 // left & result in different registers
6719 if (AOP_TYPE (result) == AOP_CRY)
6722 // if(size), result in bit
6723 // if(!size && ifx), conditional oper: if(left & right)
6724 symbol *tlbl = newiTempLabel (NULL);
6725 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6727 emitcode ("setb", "c");
6730 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6731 && AOP_TYPE(left)==AOP_ACC)
6734 emitcode("mov", "a,b");
6735 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6737 else if (AOP_TYPE(left)==AOP_ACC)
6741 bool pushedB = pushB ();
6742 emitcode("mov", "b,a");
6743 MOVA (aopGet (right, offset, FALSE, FALSE));
6744 emitcode("anl", "a,b");
6749 MOVA (aopGet (right, offset, FALSE, FALSE));
6750 emitcode("anl", "a,b");
6753 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6755 MOVB (aopGet (left, offset, FALSE, FALSE));
6756 MOVA (aopGet (right, offset, FALSE, FALSE));
6757 emitcode ("anl", "a,b");
6759 else if (aopGetUsesAcc (left, offset))
6761 MOVA (aopGet (left, offset, FALSE, FALSE));
6762 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6766 MOVA (aopGet (right, offset, FALSE, FALSE));
6767 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6770 emitcode ("jnz", "%05d$", tlbl->key + 100);
6780 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6786 for (; (size--); offset++)
6789 // result = left & right
6790 if (AOP_TYPE (right) == AOP_LIT)
6792 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6793 if (bytelit == 0x0FF)
6796 aopGet (left, offset, FALSE, FALSE),
6800 else if (bytelit == 0)
6802 /* dummy read of volatile operand */
6803 if (isOperandVolatile (left, FALSE))
6804 MOVA (aopGet (left, offset, FALSE, FALSE));
6805 aopPut (result, zero, offset);
6808 else if (AOP_TYPE (left) == AOP_ACC)
6812 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6813 aopPut (result, "a", offset);
6818 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6819 aopPut (result, "b", offset);
6824 // faster than result <- left, anl result,right
6825 // and better if result is SFR
6826 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6827 && AOP_TYPE(left)==AOP_ACC)
6830 emitcode("mov", "a,b");
6831 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6833 else if (AOP_TYPE(left)==AOP_ACC)
6837 bool pushedB = pushB ();
6838 emitcode("mov", "b,a");
6839 MOVA (aopGet (right, offset, FALSE, FALSE));
6840 emitcode("anl", "a,b");
6845 MOVA (aopGet (right, offset, FALSE, FALSE));
6846 emitcode("anl", "a,b");
6849 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6851 MOVB (aopGet (left, offset, FALSE, FALSE));
6852 MOVA (aopGet (right, offset, FALSE, FALSE));
6853 emitcode ("anl", "a,b");
6855 else if (aopGetUsesAcc (left, offset))
6857 MOVA (aopGet (left, offset, FALSE, FALSE));
6858 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6862 MOVA (aopGet (right, offset, FALSE, FALSE));
6863 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6865 aopPut (result, "a", offset);
6871 freeAsmop (result, NULL, ic, TRUE);
6872 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6873 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6876 /*-----------------------------------------------------------------*/
6877 /* genOr - code for or */
6878 /*-----------------------------------------------------------------*/
6880 genOr (iCode * ic, iCode * ifx)
6882 operand *left, *right, *result;
6883 int size, offset = 0;
6884 unsigned long lit = 0L;
6887 D (emitcode (";", "genOr"));
6889 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6890 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6891 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6894 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6896 AOP_TYPE (left), AOP_TYPE (right));
6897 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6899 AOP_SIZE (left), AOP_SIZE (right));
6902 /* if left is a literal & right is not then exchange them */
6903 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6904 AOP_NEEDSACC (left))
6906 operand *tmp = right;
6911 /* if result = right then exchange them */
6912 if (sameRegs (AOP (result), AOP (right)))
6914 operand *tmp = right;
6919 /* if right is bit then exchange them */
6920 if (AOP_TYPE (right) == AOP_CRY &&
6921 AOP_TYPE (left) != AOP_CRY)
6923 operand *tmp = right;
6927 if (AOP_TYPE (right) == AOP_LIT)
6928 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6930 size = AOP_SIZE (result);
6934 if (AOP_TYPE (left) == AOP_CRY)
6936 if (AOP_TYPE (right) == AOP_LIT)
6938 // c = bit | literal;
6941 // lit != 0 => result = 1
6942 if (AOP_TYPE (result) == AOP_CRY)
6945 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6947 continueIfTrue (ifx);
6950 emitcode ("setb", "c");
6954 // lit == 0 => result = left
6955 if (size && sameRegs (AOP (result), AOP (left)))
6957 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6962 if (AOP_TYPE (right) == AOP_CRY)
6965 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6966 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6971 symbol *tlbl = newiTempLabel (NULL);
6972 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6973 emitcode ("setb", "c");
6974 emitcode ("jb", "%s,%05d$",
6975 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6977 emitcode ("jnz", "%05d$", tlbl->key + 100);
6978 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6980 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6995 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6996 genIfxJump (ifx, "c", left, right, result);
7000 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7001 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7002 if ((AOP_TYPE (right) == AOP_LIT) &&
7003 (AOP_TYPE (result) == AOP_CRY) &&
7004 (AOP_TYPE (left) != AOP_CRY))
7010 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7012 continueIfTrue (ifx);
7017 // lit = 0, result = boolean(left)
7019 emitcode ("setb", "c");
7023 symbol *tlbl = newiTempLabel (NULL);
7024 emitcode ("jnz", "%05d$", tlbl->key + 100);
7030 genIfxJump (ifx, "a", left, right, result);
7038 /* if left is same as result */
7039 if (sameRegs (AOP (result), AOP (left)))
7041 for (; size--; offset++)
7043 if (AOP_TYPE (right) == AOP_LIT)
7045 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7048 /* dummy read of volatile operand */
7049 if (isOperandVolatile (left, FALSE))
7050 MOVA (aopGet (left, offset, FALSE, FALSE));
7054 else if (bytelit == 0x0FF)
7056 aopPut (result, "#0xFF", offset);
7058 else if (IS_AOP_PREG (left))
7060 MOVA (aopGet (left, offset, FALSE, TRUE));
7061 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7062 aopPut (result, "a", offset);
7066 emitcode ("orl", "%s,%s",
7067 aopGet (left, offset, FALSE, TRUE),
7068 aopGet (right, offset, FALSE, FALSE));
7073 if (AOP_TYPE (left) == AOP_ACC)
7076 emitcode("mov", "a,b");
7077 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7079 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7081 MOVB (aopGet (left, offset, FALSE, FALSE));
7082 MOVA (aopGet (right, offset, FALSE, FALSE));
7083 emitcode ("orl", "a,b");
7084 aopPut (result, "a", offset);
7086 else if (aopGetUsesAcc (left, offset))
7088 MOVA (aopGet (left, offset, FALSE, FALSE));
7089 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7090 aopPut (result, "a", offset);
7094 MOVA (aopGet (right, offset, FALSE, FALSE));
7095 if (IS_AOP_PREG (left))
7097 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7098 aopPut (result, "a", offset);
7102 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7110 // left & result in different registers
7111 if (AOP_TYPE (result) == AOP_CRY)
7114 // if(size), result in bit
7115 // if(!size && ifx), conditional oper: if(left | right)
7116 symbol *tlbl = newiTempLabel (NULL);
7117 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7119 emitcode ("setb", "c");
7122 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7123 && AOP_TYPE(left)==AOP_ACC)
7126 emitcode("mov", "a,b");
7127 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7129 else if (AOP_TYPE(left)==AOP_ACC)
7133 bool pushedB = pushB ();
7134 emitcode("mov", "b,a");
7135 MOVA (aopGet (right, offset, FALSE, FALSE));
7136 emitcode("orl", "a,b");
7141 MOVA (aopGet (right, offset, FALSE, FALSE));
7142 emitcode("orl", "a,b");
7145 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7147 MOVB (aopGet (left, offset, FALSE, FALSE));
7148 MOVA (aopGet (right, offset, FALSE, FALSE));
7149 emitcode ("orl", "a,b");
7151 else if (aopGetUsesAcc (left, offset))
7153 MOVA (aopGet (left, offset, FALSE, FALSE));
7154 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7158 MOVA (aopGet (right, offset, FALSE, FALSE));
7159 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7162 emitcode ("jnz", "%05d$", tlbl->key + 100);
7172 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7178 for (; (size--); offset++)
7181 // result = left | right
7182 if (AOP_TYPE (right) == AOP_LIT)
7184 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7188 aopGet (left, offset, FALSE, FALSE),
7192 else if (bytelit == 0x0FF)
7194 /* dummy read of volatile operand */
7195 if (isOperandVolatile (left, FALSE))
7196 MOVA (aopGet (left, offset, FALSE, FALSE));
7197 aopPut (result, "#0xFF", offset);
7201 // faster than result <- left, orl result,right
7202 // and better if result is SFR
7203 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7204 && AOP_TYPE(left)==AOP_ACC)
7207 emitcode("mov", "a,b");
7208 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7210 else if (AOP_TYPE(left)==AOP_ACC)
7214 bool pushedB = pushB ();
7215 emitcode("mov", "b,a");
7216 MOVA (aopGet (right, offset, FALSE, FALSE));
7217 emitcode("orl", "a,b");
7222 MOVA (aopGet (right, offset, FALSE, FALSE));
7223 emitcode("orl", "a,b");
7226 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7228 MOVB (aopGet (left, offset, FALSE, FALSE));
7229 MOVA (aopGet (right, offset, FALSE, FALSE));
7230 emitcode ("orl", "a,b");
7232 else if (aopGetUsesAcc (left, offset))
7234 MOVA (aopGet (left, offset, FALSE, FALSE));
7235 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7239 MOVA (aopGet (right, offset, FALSE, FALSE));
7240 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7242 aopPut (result, "a", offset);
7248 freeAsmop (result, NULL, ic, TRUE);
7249 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7250 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7253 /*-----------------------------------------------------------------*/
7254 /* genXor - code for xclusive or */
7255 /*-----------------------------------------------------------------*/
7257 genXor (iCode * ic, iCode * ifx)
7259 operand *left, *right, *result;
7260 int size, offset = 0;
7261 unsigned long lit = 0L;
7264 D (emitcode (";", "genXor"));
7266 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7267 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7268 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7271 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7273 AOP_TYPE (left), AOP_TYPE (right));
7274 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7276 AOP_SIZE (left), AOP_SIZE (right));
7279 /* if left is a literal & right is not ||
7280 if left needs acc & right does not */
7281 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7282 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7284 operand *tmp = right;
7289 /* if result = right then exchange them */
7290 if (sameRegs (AOP (result), AOP (right)))
7292 operand *tmp = right;
7297 /* if right is bit then exchange them */
7298 if (AOP_TYPE (right) == AOP_CRY &&
7299 AOP_TYPE (left) != AOP_CRY)
7301 operand *tmp = right;
7305 if (AOP_TYPE (right) == AOP_LIT)
7306 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7308 size = AOP_SIZE (result);
7312 if (AOP_TYPE (left) == AOP_CRY)
7314 if (AOP_TYPE (right) == AOP_LIT)
7316 // c = bit & literal;
7319 // lit>>1 != 0 => result = 1
7320 if (AOP_TYPE (result) == AOP_CRY)
7323 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7325 continueIfTrue (ifx);
7328 emitcode ("setb", "c");
7335 // lit == 0, result = left
7336 if (size && sameRegs (AOP (result), AOP (left)))
7338 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7342 // lit == 1, result = not(left)
7343 if (size && sameRegs (AOP (result), AOP (left)))
7345 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7350 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7351 emitcode ("cpl", "c");
7359 symbol *tlbl = newiTempLabel (NULL);
7360 if (AOP_TYPE (right) == AOP_CRY)
7363 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7367 int sizer = AOP_SIZE (right);
7369 // if val>>1 != 0, result = 1
7370 emitcode ("setb", "c");
7373 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7375 // test the msb of the lsb
7376 emitcode ("anl", "a,#0xfe");
7377 emitcode ("jnz", "%05d$", tlbl->key + 100);
7381 emitcode ("rrc", "a");
7383 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7384 emitcode ("cpl", "c");
7392 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7393 genIfxJump (ifx, "c", left, right, result);
7397 /* if left is same as result */
7398 if (sameRegs (AOP (result), AOP (left)))
7400 for (; size--; offset++)
7402 if (AOP_TYPE (right) == AOP_LIT)
7404 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7407 /* dummy read of volatile operand */
7408 if (isOperandVolatile (left, FALSE))
7409 MOVA (aopGet (left, offset, FALSE, FALSE));
7413 else if (IS_AOP_PREG (left))
7415 MOVA (aopGet (left, offset, FALSE, TRUE));
7416 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7417 aopPut (result, "a", offset);
7421 emitcode ("xrl", "%s,%s",
7422 aopGet (left, offset, FALSE, TRUE),
7423 aopGet (right, offset, FALSE, FALSE));
7428 if (AOP_TYPE (left) == AOP_ACC)
7431 emitcode("mov", "a,b");
7432 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7434 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7436 MOVB (aopGet (left, offset, FALSE, FALSE));
7437 MOVA (aopGet (right, offset, FALSE, FALSE));
7438 emitcode ("xrl", "a,b");
7439 aopPut (result, "a", offset);
7441 else if (aopGetUsesAcc (left, offset))
7443 MOVA (aopGet (left, offset, FALSE, FALSE));
7444 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7445 aopPut (result, "a", offset);
7449 MOVA (aopGet (right, offset, FALSE, FALSE));
7450 if (IS_AOP_PREG (left))
7452 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7453 aopPut (result, "a", offset);
7456 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7463 // left & result in different registers
7464 if (AOP_TYPE (result) == AOP_CRY)
7467 // if(size), result in bit
7468 // if(!size && ifx), conditional oper: if(left ^ right)
7469 symbol *tlbl = newiTempLabel (NULL);
7470 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7473 emitcode ("setb", "c");
7476 if ((AOP_TYPE (right) == AOP_LIT) &&
7477 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7479 MOVA (aopGet (left, offset, FALSE, FALSE));
7481 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7482 && AOP_TYPE(left)==AOP_ACC)
7485 emitcode("mov", "a,b");
7486 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7488 else if (AOP_TYPE(left)==AOP_ACC)
7492 bool pushedB = pushB ();
7493 emitcode("mov", "b,a");
7494 MOVA (aopGet (right, offset, FALSE, FALSE));
7495 emitcode("xrl", "a,b");
7500 MOVA (aopGet (right, offset, FALSE, FALSE));
7501 emitcode("xrl", "a,b");
7504 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7506 MOVB (aopGet (left, offset, FALSE, FALSE));
7507 MOVA (aopGet (right, offset, FALSE, FALSE));
7508 emitcode ("xrl", "a,b");
7510 else if (aopGetUsesAcc (left, offset))
7512 MOVA (aopGet (left, offset, FALSE, FALSE));
7513 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7517 MOVA (aopGet (right, offset, FALSE, FALSE));
7518 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7521 emitcode ("jnz", "%05d$", tlbl->key + 100);
7531 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7535 for (; (size--); offset++)
7538 // result = left ^ right
7539 if (AOP_TYPE (right) == AOP_LIT)
7541 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7545 aopGet (left, offset, FALSE, FALSE),
7550 // faster than result <- left, xrl result,right
7551 // and better if result is SFR
7552 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7553 && AOP_TYPE(left)==AOP_ACC)
7556 emitcode("mov", "a,b");
7557 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7559 else if (AOP_TYPE(left)==AOP_ACC)
7563 bool pushedB = pushB ();
7564 emitcode("mov", "b,a");
7565 MOVA (aopGet (right, offset, FALSE, FALSE));
7566 emitcode("xrl", "a,b");
7571 MOVA (aopGet (right, offset, FALSE, FALSE));
7572 emitcode("xrl", "a,b");
7575 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7577 MOVB (aopGet (left, offset, FALSE, FALSE));
7578 MOVA (aopGet (right, offset, FALSE, FALSE));
7579 emitcode ("xrl", "a,b");
7581 else if (aopGetUsesAcc (left, offset))
7583 MOVA (aopGet (left, offset, FALSE, FALSE));
7584 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7588 MOVA (aopGet (right, offset, FALSE, FALSE));
7589 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7591 aopPut (result, "a", offset);
7597 freeAsmop (result, NULL, ic, TRUE);
7598 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7599 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7602 /*-----------------------------------------------------------------*/
7603 /* genInline - write the inline code out */
7604 /*-----------------------------------------------------------------*/
7606 genInline (iCode * ic)
7608 char *buffer, *bp, *bp1;
7610 D (emitcode (";", "genInline"));
7612 _G.inLine += (!options.asmpeep);
7614 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7616 /* emit each line as a code */
7627 /* Add \n for labels, not dirs such as c:\mydir */
7628 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7642 /* emitcode("",buffer); */
7643 _G.inLine -= (!options.asmpeep);
7646 /*-----------------------------------------------------------------*/
7647 /* genRRC - rotate right with carry */
7648 /*-----------------------------------------------------------------*/
7652 operand *left, *result;
7656 D (emitcode (";", "genRRC"));
7658 /* rotate right with carry */
7659 left = IC_LEFT (ic);
7660 result = IC_RESULT (ic);
7661 aopOp (left, ic, FALSE);
7662 aopOp (result, ic, FALSE);
7664 /* move it to the result */
7665 size = AOP_SIZE (result);
7667 if (size == 1) { /* special case for 1 byte */
7668 l = aopGet (left, offset, FALSE, FALSE);
7670 emitcode ("rr", "a");
7673 /* no need to clear carry, bit7 will be written later */
7676 l = aopGet (left, offset, FALSE, FALSE);
7678 emitcode ("rrc", "a");
7679 if (AOP_SIZE (result) > 1)
7680 aopPut (result, "a", offset--);
7682 /* now we need to put the carry into the
7683 highest order byte of the result */
7684 if (AOP_SIZE (result) > 1)
7686 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7689 emitcode ("mov", "acc.7,c");
7691 aopPut (result, "a", AOP_SIZE (result) - 1);
7692 freeAsmop (result, NULL, ic, TRUE);
7693 freeAsmop (left, NULL, ic, TRUE);
7696 /*-----------------------------------------------------------------*/
7697 /* genRLC - generate code for rotate left with carry */
7698 /*-----------------------------------------------------------------*/
7702 operand *left, *result;
7706 D (emitcode (";", "genRLC"));
7708 /* rotate right with carry */
7709 left = IC_LEFT (ic);
7710 result = IC_RESULT (ic);
7711 aopOp (left, ic, FALSE);
7712 aopOp (result, ic, FALSE);
7714 /* move it to the result */
7715 size = AOP_SIZE (result);
7719 l = aopGet (left, offset, FALSE, FALSE);
7721 if (size == 0) { /* special case for 1 byte */
7725 emitcode("rlc","a"); /* bit0 will be written later */
7726 if (AOP_SIZE (result) > 1)
7728 aopPut (result, "a", offset++);
7733 l = aopGet (left, offset, FALSE, FALSE);
7735 emitcode ("rlc", "a");
7736 if (AOP_SIZE (result) > 1)
7737 aopPut (result, "a", offset++);
7740 /* now we need to put the carry into the
7741 highest order byte of the result */
7742 if (AOP_SIZE (result) > 1)
7744 l = aopGet (result, 0, FALSE, FALSE);
7747 emitcode ("mov", "acc.0,c");
7749 aopPut (result, "a", 0);
7750 freeAsmop (result, NULL, ic, TRUE);
7751 freeAsmop (left, NULL, ic, TRUE);
7754 /*-----------------------------------------------------------------*/
7755 /* genGetHbit - generates code get highest order bit */
7756 /*-----------------------------------------------------------------*/
7758 genGetHbit (iCode * ic)
7760 operand *left, *result;
7762 D (emitcode (";", "genGetHbit"));
7764 left = IC_LEFT (ic);
7765 result = IC_RESULT (ic);
7766 aopOp (left, ic, FALSE);
7767 aopOp (result, ic, FALSE);
7769 /* get the highest order byte into a */
7770 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7771 if (AOP_TYPE (result) == AOP_CRY)
7773 emitcode ("rlc", "a");
7778 emitcode ("rl", "a");
7779 emitcode ("anl", "a,#0x01");
7783 freeAsmop (result, NULL, ic, TRUE);
7784 freeAsmop (left, NULL, ic, TRUE);
7787 /*-----------------------------------------------------------------*/
7788 /* genGetAbit - generates code get a single bit */
7789 /*-----------------------------------------------------------------*/
7791 genGetAbit (iCode * ic)
7793 operand *left, *right, *result;
7796 D (emitcode (";", "genGetAbit"));
7798 left = IC_LEFT (ic);
7799 right = IC_RIGHT (ic);
7800 result = IC_RESULT (ic);
7801 aopOp (left, ic, FALSE);
7802 aopOp (right, ic, FALSE);
7803 aopOp (result, ic, FALSE);
7805 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7807 /* get the needed byte into a */
7808 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7810 if (AOP_TYPE (result) == AOP_CRY)
7813 emitcode ("rlc", "a");
7814 else if ((shCount) == 0)
7815 emitcode ("rrc", "a");
7817 emitcode ("mov", "c,acc[%d]", shCount);
7825 emitcode ("rr", "a");
7828 emitcode ("rr", "a");
7831 emitcode ("anl", "a,#0x01");
7835 emitcode ("mov", "c,acc[%d]", shCount);
7836 emitcode ("clr", "a");
7837 emitcode ("rlc", "a");
7840 emitcode ("swap", "a");
7841 emitcode ("anl", "a,#0x01");
7844 emitcode ("rl", "a");
7847 emitcode ("rl", "a");
7848 emitcode ("anl", "a,#0x01");
7854 freeAsmop (result, NULL, ic, TRUE);
7855 freeAsmop (right, NULL, ic, TRUE);
7856 freeAsmop (left, NULL, ic, TRUE);
7859 /*-----------------------------------------------------------------*/
7860 /* genGetByte - generates code get a single byte */
7861 /*-----------------------------------------------------------------*/
7863 genGetByte (iCode * ic)
7865 operand *left, *right, *result;
7868 D (emitcode (";", "genGetByte"));
7870 left = IC_LEFT (ic);
7871 right = IC_RIGHT (ic);
7872 result = IC_RESULT (ic);
7873 aopOp (left, ic, FALSE);
7874 aopOp (right, ic, FALSE);
7875 aopOp (result, ic, FALSE);
7877 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7879 aopGet (left, offset, FALSE, FALSE),
7882 freeAsmop (result, NULL, ic, TRUE);
7883 freeAsmop (right, NULL, ic, TRUE);
7884 freeAsmop (left, NULL, ic, TRUE);
7887 /*-----------------------------------------------------------------*/
7888 /* genGetWord - generates code get two bytes */
7889 /*-----------------------------------------------------------------*/
7891 genGetWord (iCode * ic)
7893 operand *left, *right, *result;
7896 D (emitcode (";", "genGetWord"));
7898 left = IC_LEFT (ic);
7899 right = IC_RIGHT (ic);
7900 result = IC_RESULT (ic);
7901 aopOp (left, ic, FALSE);
7902 aopOp (right, ic, FALSE);
7903 aopOp (result, ic, FALSE);
7905 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7907 aopGet (left, offset, FALSE, FALSE),
7910 aopGet (left, offset+1, FALSE, FALSE),
7913 freeAsmop (result, NULL, ic, TRUE);
7914 freeAsmop (right, NULL, ic, TRUE);
7915 freeAsmop (left, NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genSwap - generates code to swap nibbles or bytes */
7920 /*-----------------------------------------------------------------*/
7922 genSwap (iCode * ic)
7924 operand *left, *result;
7926 D(emitcode ("; genSwap",""));
7928 left = IC_LEFT (ic);
7929 result = IC_RESULT (ic);
7930 aopOp (left, ic, FALSE);
7931 aopOp (result, ic, FALSE);
7933 switch (AOP_SIZE (left))
7935 case 1: /* swap nibbles in byte */
7936 MOVA (aopGet (left, 0, FALSE, FALSE));
7937 emitcode ("swap", "a");
7938 aopPut (result, "a", 0);
7940 case 2: /* swap bytes in word */
7941 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7943 MOVA (aopGet (left, 0, FALSE, FALSE));
7944 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7945 aopPut (result, "a", 1);
7947 else if (operandsEqu (left, result))
7950 bool pushedB = FALSE, leftInB = FALSE;
7952 MOVA (aopGet (left, 0, FALSE, FALSE));
7953 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7956 emitcode ("mov", "b,a");
7960 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7961 aopPut (result, reg, 1);
7968 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7969 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7973 wassertl(FALSE, "unsupported SWAP operand size");
7976 freeAsmop (result, NULL, ic, TRUE);
7977 freeAsmop (left, NULL, ic, TRUE);
7980 /*-----------------------------------------------------------------*/
7981 /* AccRol - rotate left accumulator by known count */
7982 /*-----------------------------------------------------------------*/
7984 AccRol (int shCount)
7986 shCount &= 0x0007; // shCount : 0..7
7993 emitcode ("rl", "a");
7996 emitcode ("rl", "a");
7997 emitcode ("rl", "a");
8000 emitcode ("swap", "a");
8001 emitcode ("rr", "a");
8004 emitcode ("swap", "a");
8007 emitcode ("swap", "a");
8008 emitcode ("rl", "a");
8011 emitcode ("rr", "a");
8012 emitcode ("rr", "a");
8015 emitcode ("rr", "a");
8020 /*-----------------------------------------------------------------*/
8021 /* AccLsh - left shift accumulator by known count */
8022 /*-----------------------------------------------------------------*/
8024 AccLsh (int shCount)
8029 emitcode ("add", "a,acc");
8030 else if (shCount == 2)
8032 emitcode ("add", "a,acc");
8033 emitcode ("add", "a,acc");
8037 /* rotate left accumulator */
8039 /* and kill the lower order bits */
8040 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8045 /*-----------------------------------------------------------------*/
8046 /* AccRsh - right shift accumulator by known count */
8047 /*-----------------------------------------------------------------*/
8049 AccRsh (int shCount)
8056 emitcode ("rrc", "a");
8060 /* rotate right accumulator */
8061 AccRol (8 - shCount);
8062 /* and kill the higher order bits */
8063 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8068 /*-----------------------------------------------------------------*/
8069 /* AccSRsh - signed right shift accumulator by known count */
8070 /*-----------------------------------------------------------------*/
8072 AccSRsh (int shCount)
8079 emitcode ("mov", "c,acc.7");
8080 emitcode ("rrc", "a");
8082 else if (shCount == 2)
8084 emitcode ("mov", "c,acc.7");
8085 emitcode ("rrc", "a");
8086 emitcode ("mov", "c,acc.7");
8087 emitcode ("rrc", "a");
8091 tlbl = newiTempLabel (NULL);
8092 /* rotate right accumulator */
8093 AccRol (8 - shCount);
8094 /* and kill the higher order bits */
8095 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8096 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8097 emitcode ("orl", "a,#0x%02x",
8098 (unsigned char) ~SRMask[shCount]);
8104 /*-----------------------------------------------------------------*/
8105 /* shiftR1Left2Result - shift right one byte from left to result */
8106 /*-----------------------------------------------------------------*/
8108 shiftR1Left2Result (operand * left, int offl,
8109 operand * result, int offr,
8110 int shCount, int sign)
8112 MOVA (aopGet (left, offl, FALSE, FALSE));
8113 /* shift right accumulator */
8118 aopPut (result, "a", offr);
8121 /*-----------------------------------------------------------------*/
8122 /* shiftL1Left2Result - shift left one byte from left to result */
8123 /*-----------------------------------------------------------------*/
8125 shiftL1Left2Result (operand * left, int offl,
8126 operand * result, int offr, int shCount)
8129 l = aopGet (left, offl, FALSE, FALSE);
8131 /* shift left accumulator */
8133 aopPut (result, "a", offr);
8136 /*-----------------------------------------------------------------*/
8137 /* movLeft2Result - move byte from left to result */
8138 /*-----------------------------------------------------------------*/
8140 movLeft2Result (operand * left, int offl,
8141 operand * result, int offr, int sign)
8144 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8146 l = aopGet (left, offl, FALSE, FALSE);
8148 if (*l == '@' && (IS_AOP_PREG (result)))
8150 emitcode ("mov", "a,%s", l);
8151 aopPut (result, "a", offr);
8157 aopPut (result, l, offr);
8161 /* MSB sign in acc.7 ! */
8162 if (getDataSize (left) == offl + 1)
8165 aopPut (result, "a", offr);
8172 /*-----------------------------------------------------------------*/
8173 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8174 /*-----------------------------------------------------------------*/
8178 emitcode ("rrc", "a");
8179 emitcode ("xch", "a,%s", x);
8180 emitcode ("rrc", "a");
8181 emitcode ("xch", "a,%s", x);
8184 /*-----------------------------------------------------------------*/
8185 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8186 /*-----------------------------------------------------------------*/
8190 emitcode ("xch", "a,%s", x);
8191 emitcode ("rlc", "a");
8192 emitcode ("xch", "a,%s", x);
8193 emitcode ("rlc", "a");
8196 /*-----------------------------------------------------------------*/
8197 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8198 /*-----------------------------------------------------------------*/
8202 emitcode ("xch", "a,%s", x);
8203 emitcode ("add", "a,acc");
8204 emitcode ("xch", "a,%s", x);
8205 emitcode ("rlc", "a");
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXLsh - left shift a:x by known count (0..7) */
8210 /*-----------------------------------------------------------------*/
8212 AccAXLsh (char *x, int shCount)
8227 case 5: // AAAAABBB:CCCCCDDD
8229 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8231 emitcode ("anl", "a,#0x%02x",
8232 SLMask[shCount]); // BBB00000:CCCCCDDD
8234 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8236 AccRol (shCount); // DDDCCCCC:BBB00000
8238 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8240 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8242 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8244 emitcode ("anl", "a,#0x%02x",
8245 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8247 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8249 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8252 case 6: // AAAAAABB:CCCCCCDD
8253 emitcode ("anl", "a,#0x%02x",
8254 SRMask[shCount]); // 000000BB:CCCCCCDD
8255 emitcode ("mov", "c,acc.0"); // c = B
8256 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8258 AccAXRrl1 (x); // BCCCCCCD:D000000B
8259 AccAXRrl1 (x); // BBCCCCCC:DD000000
8261 emitcode("rrc","a");
8262 emitcode("xch","a,%s", x);
8263 emitcode("rrc","a");
8264 emitcode("mov","c,acc.0"); //<< get correct bit
8265 emitcode("xch","a,%s", x);
8267 emitcode("rrc","a");
8268 emitcode("xch","a,%s", x);
8269 emitcode("rrc","a");
8270 emitcode("xch","a,%s", x);
8273 case 7: // a:x <<= 7
8275 emitcode ("anl", "a,#0x%02x",
8276 SRMask[shCount]); // 0000000B:CCCCCCCD
8278 emitcode ("mov", "c,acc.0"); // c = B
8280 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8282 AccAXRrl1 (x); // BCCCCCCC:D0000000
8290 /*-----------------------------------------------------------------*/
8291 /* AccAXRsh - right shift a:x known count (0..7) */
8292 /*-----------------------------------------------------------------*/
8294 AccAXRsh (char *x, int shCount)
8302 AccAXRrl1 (x); // 0->a:x
8307 AccAXRrl1 (x); // 0->a:x
8310 AccAXRrl1 (x); // 0->a:x
8315 case 5: // AAAAABBB:CCCCCDDD = a:x
8317 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8319 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8321 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8323 emitcode ("anl", "a,#0x%02x",
8324 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8326 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8328 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8330 emitcode ("anl", "a,#0x%02x",
8331 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8333 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8335 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8337 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8340 case 6: // AABBBBBB:CCDDDDDD
8342 emitcode ("mov", "c,acc.7");
8343 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8345 emitcode ("mov", "c,acc.7");
8346 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8348 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8350 emitcode ("anl", "a,#0x%02x",
8351 SRMask[shCount]); // 000000AA:BBBBBBCC
8354 case 7: // ABBBBBBB:CDDDDDDD
8356 emitcode ("mov", "c,acc.7"); // c = A
8358 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8360 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8362 emitcode ("anl", "a,#0x%02x",
8363 SRMask[shCount]); // 0000000A:BBBBBBBC
8371 /*-----------------------------------------------------------------*/
8372 /* AccAXRshS - right shift signed a:x known count (0..7) */
8373 /*-----------------------------------------------------------------*/
8375 AccAXRshS (char *x, int shCount)
8383 emitcode ("mov", "c,acc.7");
8384 AccAXRrl1 (x); // s->a:x
8388 emitcode ("mov", "c,acc.7");
8389 AccAXRrl1 (x); // s->a:x
8391 emitcode ("mov", "c,acc.7");
8392 AccAXRrl1 (x); // s->a:x
8397 case 5: // AAAAABBB:CCCCCDDD = a:x
8399 tlbl = newiTempLabel (NULL);
8400 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8402 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8404 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8406 emitcode ("anl", "a,#0x%02x",
8407 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8409 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8411 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8413 emitcode ("anl", "a,#0x%02x",
8414 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8416 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8418 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8420 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8422 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8423 emitcode ("orl", "a,#0x%02x",
8424 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8427 break; // SSSSAAAA:BBBCCCCC
8429 case 6: // AABBBBBB:CCDDDDDD
8431 tlbl = newiTempLabel (NULL);
8432 emitcode ("mov", "c,acc.7");
8433 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8435 emitcode ("mov", "c,acc.7");
8436 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8438 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8440 emitcode ("anl", "a,#0x%02x",
8441 SRMask[shCount]); // 000000AA:BBBBBBCC
8443 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8444 emitcode ("orl", "a,#0x%02x",
8445 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8449 case 7: // ABBBBBBB:CDDDDDDD
8451 tlbl = newiTempLabel (NULL);
8452 emitcode ("mov", "c,acc.7"); // c = A
8454 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8456 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8458 emitcode ("anl", "a,#0x%02x",
8459 SRMask[shCount]); // 0000000A:BBBBBBBC
8461 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8462 emitcode ("orl", "a,#0x%02x",
8463 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8472 /*-----------------------------------------------------------------*/
8473 /* shiftL2Left2Result - shift left two bytes from left to result */
8474 /*-----------------------------------------------------------------*/
8476 shiftL2Left2Result (operand * left, int offl,
8477 operand * result, int offr, int shCount)
8480 bool pushedB = FALSE;
8483 if (sameRegs (AOP (result), AOP (left)) &&
8484 ((offl + MSB16) == offr))
8486 /* don't crash result[offr] */
8487 MOVA (aopGet (left, offl, FALSE, FALSE));
8488 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8489 usedB = !strncmp(x, "b", 1);
8491 else if (aopGetUsesAcc (result, offr))
8493 movLeft2Result (left, offl, result, offr, 0);
8496 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8497 MOVA (aopGet (result, offr, FALSE, FALSE));
8498 emitcode ("xch", "a,b");
8503 movLeft2Result (left, offl, result, offr, 0);
8504 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8505 x = aopGet (result, offr, FALSE, FALSE);
8507 /* ax << shCount (x = lsb(result)) */
8508 AccAXLsh (x, shCount);
8511 emitcode ("xch", "a,b");
8512 aopPut (result, "a", offr);
8513 aopPut (result, "b", offr + MSB16);
8518 aopPut (result, "a", offr + MSB16);
8523 /*-----------------------------------------------------------------*/
8524 /* shiftR2Left2Result - shift right two bytes from left to result */
8525 /*-----------------------------------------------------------------*/
8527 shiftR2Left2Result (operand * left, int offl,
8528 operand * result, int offr,
8529 int shCount, int sign)
8532 bool pushedB = FALSE;
8535 if (sameRegs (AOP (result), AOP (left)) &&
8536 ((offl + MSB16) == offr))
8538 /* don't crash result[offr] */
8539 MOVA (aopGet (left, offl, FALSE, FALSE));
8540 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8541 usedB = !strncmp(x, "b", 1);
8543 else if (aopGetUsesAcc (result, offr))
8545 movLeft2Result (left, offl, result, offr, 0);
8548 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8549 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8554 movLeft2Result (left, offl, result, offr, 0);
8555 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8556 x = aopGet (result, offr, FALSE, FALSE);
8558 /* a:x >> shCount (x = lsb(result)) */
8560 AccAXRshS (x, shCount);
8562 AccAXRsh (x, shCount);
8565 emitcode ("xch", "a,b");
8566 aopPut (result, "a", offr);
8567 emitcode ("xch", "a,b");
8570 if (getDataSize (result) > 1)
8571 aopPut (result, "a", offr + MSB16);
8574 /*-----------------------------------------------------------------*/
8575 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8576 /*-----------------------------------------------------------------*/
8578 shiftLLeftOrResult (operand * left, int offl,
8579 operand * result, int offr, int shCount)
8581 MOVA (aopGet (left, offl, FALSE, FALSE));
8582 /* shift left accumulator */
8584 /* or with result */
8585 if (aopGetUsesAcc (result, offr))
8587 emitcode ("xch", "a,b");
8588 MOVA (aopGet (result, offr, FALSE, FALSE));
8589 emitcode ("orl", "a,b");
8593 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8595 /* back to result */
8596 aopPut (result, "a", offr);
8599 /*-----------------------------------------------------------------*/
8600 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8601 /*-----------------------------------------------------------------*/
8603 shiftRLeftOrResult (operand * left, int offl,
8604 operand * result, int offr, int shCount)
8606 MOVA (aopGet (left, offl, FALSE, FALSE));
8607 /* shift right accumulator */
8609 /* or with result */
8610 if (aopGetUsesAcc(result, offr))
8612 emitcode ("xch", "a,b");
8613 MOVA (aopGet (result, offr, FALSE, FALSE));
8614 emitcode ("orl", "a,b");
8618 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8620 /* back to result */
8621 aopPut (result, "a", offr);
8624 /*-----------------------------------------------------------------*/
8625 /* genlshOne - left shift a one byte quantity by known count */
8626 /*-----------------------------------------------------------------*/
8628 genlshOne (operand * result, operand * left, int shCount)
8630 D (emitcode (";", "genlshOne"));
8632 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8635 /*-----------------------------------------------------------------*/
8636 /* genlshTwo - left shift two bytes by known amount != 0 */
8637 /*-----------------------------------------------------------------*/
8639 genlshTwo (operand * result, operand * left, int shCount)
8643 D (emitcode (";", "genlshTwo"));
8645 size = getDataSize (result);
8647 /* if shCount >= 8 */
8655 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8657 movLeft2Result (left, LSB, result, MSB16, 0);
8659 aopPut (result, zero, LSB);
8662 /* 1 <= shCount <= 7 */
8666 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8668 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8672 /*-----------------------------------------------------------------*/
8673 /* shiftLLong - shift left one long from left to result */
8674 /* offl = LSB or MSB16 */
8675 /*-----------------------------------------------------------------*/
8677 shiftLLong (operand * left, operand * result, int offr)
8680 int size = AOP_SIZE (result);
8682 if (size >= LSB + offr)
8684 l = aopGet (left, LSB, FALSE, FALSE);
8686 emitcode ("add", "a,acc");
8687 if (sameRegs (AOP (left), AOP (result)) &&
8688 size >= MSB16 + offr && offr != LSB)
8689 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8691 aopPut (result, "a", LSB + offr);
8694 if (size >= MSB16 + offr)
8696 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8698 l = aopGet (left, MSB16, FALSE, FALSE);
8701 emitcode ("rlc", "a");
8702 if (sameRegs (AOP (left), AOP (result)) &&
8703 size >= MSB24 + offr && offr != LSB)
8704 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8706 aopPut (result, "a", MSB16 + offr);
8709 if (size >= MSB24 + offr)
8711 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8713 l = aopGet (left, MSB24, FALSE, FALSE);
8716 emitcode ("rlc", "a");
8717 if (sameRegs (AOP (left), AOP (result)) &&
8718 size >= MSB32 + offr && offr != LSB)
8719 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8721 aopPut (result, "a", MSB24 + offr);
8724 if (size > MSB32 + offr)
8726 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8728 l = aopGet (left, MSB32, FALSE, FALSE);
8731 emitcode ("rlc", "a");
8732 aopPut (result, "a", MSB32 + offr);
8735 aopPut (result, zero, LSB);
8738 /*-----------------------------------------------------------------*/
8739 /* genlshFour - shift four byte by a known amount != 0 */
8740 /*-----------------------------------------------------------------*/
8742 genlshFour (operand * result, operand * left, int shCount)
8746 D (emitcode (";", "genlshFour"));
8748 size = AOP_SIZE (result);
8750 /* if shifting more that 3 bytes */
8755 /* lowest order of left goes to the highest
8756 order of the destination */
8757 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8759 movLeft2Result (left, LSB, result, MSB32, 0);
8760 aopPut (result, zero, LSB);
8761 aopPut (result, zero, MSB16);
8762 aopPut (result, zero, MSB24);
8766 /* more than two bytes */
8767 else if (shCount >= 16)
8769 /* lower order two bytes goes to higher order two bytes */
8771 /* if some more remaining */
8773 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8776 movLeft2Result (left, MSB16, result, MSB32, 0);
8777 movLeft2Result (left, LSB, result, MSB24, 0);
8779 aopPut (result, zero, MSB16);
8780 aopPut (result, zero, LSB);
8784 /* if more than 1 byte */
8785 else if (shCount >= 8)
8787 /* lower order three bytes goes to higher order three bytes */
8792 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8794 movLeft2Result (left, LSB, result, MSB16, 0);
8800 movLeft2Result (left, MSB24, result, MSB32, 0);
8801 movLeft2Result (left, MSB16, result, MSB24, 0);
8802 movLeft2Result (left, LSB, result, MSB16, 0);
8803 aopPut (result, zero, LSB);
8805 else if (shCount == 1)
8806 shiftLLong (left, result, MSB16);
8809 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8810 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8811 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8812 aopPut (result, zero, LSB);
8817 /* 1 <= shCount <= 7 */
8818 else if (shCount <= 2)
8820 shiftLLong (left, result, LSB);
8822 shiftLLong (result, result, LSB);
8824 /* 3 <= shCount <= 7, optimize */
8827 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8828 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8829 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8833 /*-----------------------------------------------------------------*/
8834 /* genLeftShiftLiteral - left shifting by known count */
8835 /*-----------------------------------------------------------------*/
8837 genLeftShiftLiteral (operand * left,
8842 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8845 D (emitcode (";", "genLeftShiftLiteral"));
8847 freeAsmop (right, NULL, ic, TRUE);
8849 aopOp (left, ic, FALSE);
8850 aopOp (result, ic, FALSE);
8852 size = getSize (operandType (result));
8855 emitcode ("; shift left ", "result %d, left %d", size,
8859 /* I suppose that the left size >= result size */
8864 movLeft2Result (left, size, result, size, 0);
8867 else if (shCount >= (size * 8))
8871 aopPut (result, zero, size);
8879 genlshOne (result, left, shCount);
8883 genlshTwo (result, left, shCount);
8887 genlshFour (result, left, shCount);
8890 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8891 "*** ack! mystery literal shift!\n");
8895 freeAsmop (result, NULL, ic, TRUE);
8896 freeAsmop (left, NULL, ic, TRUE);
8899 /*-----------------------------------------------------------------*/
8900 /* genLeftShift - generates code for left shifting */
8901 /*-----------------------------------------------------------------*/
8903 genLeftShift (iCode * ic)
8905 operand *left, *right, *result;
8908 symbol *tlbl, *tlbl1;
8911 D (emitcode (";", "genLeftShift"));
8913 right = IC_RIGHT (ic);
8914 left = IC_LEFT (ic);
8915 result = IC_RESULT (ic);
8917 aopOp (right, ic, FALSE);
8919 /* if the shift count is known then do it
8920 as efficiently as possible */
8921 if (AOP_TYPE (right) == AOP_LIT)
8923 genLeftShiftLiteral (left, right, result, ic);
8927 /* shift count is unknown then we have to form
8928 a loop get the loop count in B : Note: we take
8929 only the lower order byte since shifting
8930 more that 32 bits make no sense anyway, ( the
8931 largest size of an object can be only 32 bits ) */
8934 MOVB (aopGet (right, 0, FALSE, FALSE));
8935 emitcode ("inc", "b");
8936 freeAsmop (right, NULL, ic, TRUE);
8937 aopOp (left, ic, FALSE);
8938 aopOp (result, ic, FALSE);
8940 /* now move the left to the result if they are not the same */
8941 if (!sameRegs (AOP (left), AOP (result)) &&
8942 AOP_SIZE (result) > 1)
8945 size = AOP_SIZE (result);
8949 l = aopGet (left, offset, FALSE, TRUE);
8950 if (*l == '@' && (IS_AOP_PREG (result)))
8953 emitcode ("mov", "a,%s", l);
8954 aopPut (result, "a", offset);
8957 aopPut (result, l, offset);
8962 tlbl = newiTempLabel (NULL);
8963 size = AOP_SIZE (result);
8965 tlbl1 = newiTempLabel (NULL);
8967 /* if it is only one byte then */
8970 symbol *tlbl1 = newiTempLabel (NULL);
8972 l = aopGet (left, 0, FALSE, FALSE);
8974 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8976 emitcode ("add", "a,acc");
8978 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8980 aopPut (result, "a", 0);
8984 reAdjustPreg (AOP (result));
8986 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8988 l = aopGet (result, offset, FALSE, FALSE);
8990 emitcode ("add", "a,acc");
8991 aopPut (result, "a", offset++);
8994 l = aopGet (result, offset, FALSE, FALSE);
8996 emitcode ("rlc", "a");
8997 aopPut (result, "a", offset++);
8999 reAdjustPreg (AOP (result));
9002 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9005 freeAsmop (result, NULL, ic, TRUE);
9006 freeAsmop (left, NULL, ic, TRUE);
9009 /*-----------------------------------------------------------------*/
9010 /* genrshOne - right shift a one byte quantity by known count */
9011 /*-----------------------------------------------------------------*/
9013 genrshOne (operand * result, operand * left,
9014 int shCount, int sign)
9016 D (emitcode (";", "genrshOne"));
9018 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9021 /*-----------------------------------------------------------------*/
9022 /* genrshTwo - right shift two bytes by known amount != 0 */
9023 /*-----------------------------------------------------------------*/
9025 genrshTwo (operand * result, operand * left,
9026 int shCount, int sign)
9028 D (emitcode (";", "genrshTwo"));
9030 /* if shCount >= 8 */
9035 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9037 movLeft2Result (left, MSB16, result, LSB, sign);
9038 addSign (result, MSB16, sign);
9041 /* 1 <= shCount <= 7 */
9043 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9046 /*-----------------------------------------------------------------*/
9047 /* shiftRLong - shift right one long from left to result */
9048 /* offl = LSB or MSB16 */
9049 /*-----------------------------------------------------------------*/
9051 shiftRLong (operand * left, int offl,
9052 operand * result, int sign)
9054 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9056 if (overlapping && offl>1)
9058 // we are in big trouble, but this shouldn't happen
9059 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9062 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9069 emitcode ("rlc", "a");
9070 emitcode ("subb", "a,acc");
9071 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9073 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9077 aopPut (result, "a", MSB32);
9078 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9083 if (aopPutUsesAcc (result, zero, MSB32))
9085 emitcode("xch", "a,b");
9086 aopPut (result, zero, MSB32);
9087 emitcode("xch", "a,b");
9091 aopPut (result, zero, MSB32);
9098 emitcode ("clr", "c");
9102 emitcode ("mov", "c,acc.7");
9105 emitcode ("rrc", "a");
9107 if (overlapping && offl==MSB16 &&
9108 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9110 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9114 aopPut (result, "a", MSB32 - offl);
9115 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9118 emitcode ("rrc", "a");
9119 if (overlapping && offl==MSB16 &&
9120 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9122 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9126 aopPut (result, "a", MSB24 - offl);
9127 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9130 emitcode ("rrc", "a");
9133 aopPut (result, "a", MSB16 - offl);
9138 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9140 xch_a_aopGet (left, LSB, FALSE, FALSE);
9144 aopPut (result, "a", MSB16 - offl);
9145 MOVA (aopGet (left, LSB, FALSE, FALSE));
9147 emitcode ("rrc", "a");
9148 aopPut (result, "a", LSB);
9152 /*-----------------------------------------------------------------*/
9153 /* genrshFour - shift four byte by a known amount != 0 */
9154 /*-----------------------------------------------------------------*/
9156 genrshFour (operand * result, operand * left,
9157 int shCount, int sign)
9159 D (emitcode (";", "genrshFour"));
9161 /* if shifting more that 3 bytes */
9166 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9168 movLeft2Result (left, MSB32, result, LSB, sign);
9169 addSign (result, MSB16, sign);
9171 else if (shCount >= 16)
9175 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9178 movLeft2Result (left, MSB24, result, LSB, 0);
9179 movLeft2Result (left, MSB32, result, MSB16, sign);
9181 addSign (result, MSB24, sign);
9183 else if (shCount >= 8)
9188 shiftRLong (left, MSB16, result, sign);
9190 else if (shCount == 0)
9192 movLeft2Result (left, MSB16, result, LSB, 0);
9193 movLeft2Result (left, MSB24, result, MSB16, 0);
9194 movLeft2Result (left, MSB32, result, MSB24, sign);
9195 addSign (result, MSB32, sign);
9199 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9200 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9201 /* the last shift is signed */
9202 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9203 addSign (result, MSB32, sign);
9208 /* 1 <= shCount <= 7 */
9211 shiftRLong (left, LSB, result, sign);
9213 shiftRLong (result, LSB, result, sign);
9217 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9218 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9219 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9224 /*-----------------------------------------------------------------*/
9225 /* genRightShiftLiteral - right shifting by known count */
9226 /*-----------------------------------------------------------------*/
9228 genRightShiftLiteral (operand * left,
9234 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9237 D (emitcode (";", "genRightShiftLiteral"));
9239 freeAsmop (right, NULL, ic, TRUE);
9241 aopOp (left, ic, FALSE);
9242 aopOp (result, ic, FALSE);
9245 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9249 size = getDataSize (left);
9250 /* test the LEFT size !!! */
9252 /* I suppose that the left size >= result size */
9255 size = getDataSize (result);
9257 movLeft2Result (left, size, result, size, 0);
9260 else if (shCount >= (size * 8))
9264 /* get sign in acc.7 */
9265 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9267 addSign (result, LSB, sign);
9274 genrshOne (result, left, shCount, sign);
9278 genrshTwo (result, left, shCount, sign);
9282 genrshFour (result, left, shCount, sign);
9288 freeAsmop (result, NULL, ic, TRUE);
9289 freeAsmop (left, NULL, ic, TRUE);
9292 /*-----------------------------------------------------------------*/
9293 /* genSignedRightShift - right shift of signed number */
9294 /*-----------------------------------------------------------------*/
9296 genSignedRightShift (iCode * ic)
9298 operand *right, *left, *result;
9301 symbol *tlbl, *tlbl1;
9304 D (emitcode (";", "genSignedRightShift"));
9306 /* we do it the hard way put the shift count in b
9307 and loop thru preserving the sign */
9309 right = IC_RIGHT (ic);
9310 left = IC_LEFT (ic);
9311 result = IC_RESULT (ic);
9313 aopOp (right, ic, FALSE);
9316 if (AOP_TYPE (right) == AOP_LIT)
9318 genRightShiftLiteral (left, right, result, ic, 1);
9321 /* shift count is unknown then we have to form
9322 a loop get the loop count in B : Note: we take
9323 only the lower order byte since shifting
9324 more that 32 bits make no sense anyway, ( the
9325 largest size of an object can be only 32 bits ) */
9328 MOVB (aopGet (right, 0, FALSE, FALSE));
9329 emitcode ("inc", "b");
9330 freeAsmop (right, NULL, ic, TRUE);
9331 aopOp (left, ic, FALSE);
9332 aopOp (result, ic, FALSE);
9334 /* now move the left to the result if they are not the
9336 if (!sameRegs (AOP (left), AOP (result)) &&
9337 AOP_SIZE (result) > 1)
9340 size = AOP_SIZE (result);
9344 l = aopGet (left, offset, FALSE, TRUE);
9345 if (*l == '@' && IS_AOP_PREG (result))
9348 emitcode ("mov", "a,%s", l);
9349 aopPut (result, "a", offset);
9352 aopPut (result, l, offset);
9357 /* mov the highest order bit to OVR */
9358 tlbl = newiTempLabel (NULL);
9359 tlbl1 = newiTempLabel (NULL);
9361 size = AOP_SIZE (result);
9363 MOVA (aopGet (left, offset, FALSE, FALSE));
9364 emitcode ("rlc", "a");
9365 emitcode ("mov", "ov,c");
9366 /* if it is only one byte then */
9369 l = aopGet (left, 0, FALSE, FALSE);
9371 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9373 emitcode ("mov", "c,ov");
9374 emitcode ("rrc", "a");
9376 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9378 aopPut (result, "a", 0);
9382 reAdjustPreg (AOP (result));
9383 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9385 emitcode ("mov", "c,ov");
9388 l = aopGet (result, offset, FALSE, FALSE);
9390 emitcode ("rrc", "a");
9391 aopPut (result, "a", offset--);
9393 reAdjustPreg (AOP (result));
9395 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9399 freeAsmop (result, NULL, ic, TRUE);
9400 freeAsmop (left, NULL, ic, TRUE);
9403 /*-----------------------------------------------------------------*/
9404 /* genRightShift - generate code for right shifting */
9405 /*-----------------------------------------------------------------*/
9407 genRightShift (iCode * ic)
9409 operand *right, *left, *result;
9413 symbol *tlbl, *tlbl1;
9416 D (emitcode (";", "genRightShift"));
9418 /* if signed then we do it the hard way preserve the
9419 sign bit moving it inwards */
9420 letype = getSpec (operandType (IC_LEFT (ic)));
9422 if (!SPEC_USIGN (letype))
9424 genSignedRightShift (ic);
9428 /* signed & unsigned types are treated the same : i.e. the
9429 signed is NOT propagated inwards : quoting from the
9430 ANSI - standard : "for E1 >> E2, is equivalent to division
9431 by 2**E2 if unsigned or if it has a non-negative value,
9432 otherwise the result is implementation defined ", MY definition
9433 is that the sign does not get propagated */
9435 right = IC_RIGHT (ic);
9436 left = IC_LEFT (ic);
9437 result = IC_RESULT (ic);
9439 aopOp (right, ic, FALSE);
9441 /* if the shift count is known then do it
9442 as efficiently as possible */
9443 if (AOP_TYPE (right) == AOP_LIT)
9445 genRightShiftLiteral (left, right, result, ic, 0);
9449 /* shift count is unknown then we have to form
9450 a loop get the loop count in B : Note: we take
9451 only the lower order byte since shifting
9452 more that 32 bits make no sense anyway, ( the
9453 largest size of an object can be only 32 bits ) */
9456 MOVB (aopGet (right, 0, FALSE, FALSE));
9457 emitcode ("inc", "b");
9458 freeAsmop (right, NULL, ic, TRUE);
9459 aopOp (left, ic, FALSE);
9460 aopOp (result, ic, FALSE);
9462 /* now move the left to the result if they are not the
9464 if (!sameRegs (AOP (left), AOP (result)) &&
9465 AOP_SIZE (result) > 1)
9467 size = AOP_SIZE (result);
9471 l = aopGet (left, offset, FALSE, TRUE);
9472 if (*l == '@' && IS_AOP_PREG (result))
9475 emitcode ("mov", "a,%s", l);
9476 aopPut (result, "a", offset);
9479 aopPut (result, l, offset);
9484 tlbl = newiTempLabel (NULL);
9485 tlbl1 = newiTempLabel (NULL);
9486 size = AOP_SIZE (result);
9489 /* if it is only one byte then */
9492 l = aopGet (left, 0, FALSE, FALSE);
9494 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9497 emitcode ("rrc", "a");
9499 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9501 aopPut (result, "a", 0);
9505 reAdjustPreg (AOP (result));
9506 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9511 l = aopGet (result, offset, FALSE, FALSE);
9513 emitcode ("rrc", "a");
9514 aopPut (result, "a", offset--);
9516 reAdjustPreg (AOP (result));
9519 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9523 freeAsmop (result, NULL, ic, TRUE);
9524 freeAsmop (left, NULL, ic, TRUE);
9527 /*-----------------------------------------------------------------*/
9528 /* emitPtrByteGet - emits code to get a byte into A through a */
9529 /* pointer register (R0, R1, or DPTR). The */
9530 /* original value of A can be preserved in B. */
9531 /*-----------------------------------------------------------------*/
9533 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9540 emitcode ("mov", "b,a");
9541 emitcode ("mov", "a,@%s", rname);
9546 emitcode ("mov", "b,a");
9547 emitcode ("movx", "a,@%s", rname);
9552 emitcode ("mov", "b,a");
9553 emitcode ("movx", "a,@dptr");
9558 emitcode ("mov", "b,a");
9559 emitcode ("clr", "a");
9560 emitcode ("movc", "a,@a+dptr");
9566 emitcode ("push", "b");
9567 emitcode ("push", "acc");
9569 emitcode ("lcall", "__gptrget");
9571 emitcode ("pop", "b");
9576 /*-----------------------------------------------------------------*/
9577 /* emitPtrByteSet - emits code to set a byte from src through a */
9578 /* pointer register (R0, R1, or DPTR). */
9579 /*-----------------------------------------------------------------*/
9581 emitPtrByteSet (char *rname, int p_type, char *src)
9590 emitcode ("mov", "@%s,a", rname);
9593 emitcode ("mov", "@%s,%s", rname, src);
9598 emitcode ("movx", "@%s,a", rname);
9603 emitcode ("movx", "@dptr,a");
9608 emitcode ("lcall", "__gptrput");
9613 /*-----------------------------------------------------------------*/
9614 /* genUnpackBits - generates code for unpacking bits */
9615 /*-----------------------------------------------------------------*/
9617 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9619 int offset = 0; /* result byte offset */
9620 int rsize; /* result size */
9621 int rlen = 0; /* remaining bitfield length */
9622 sym_link *etype; /* bitfield type information */
9623 int blen; /* bitfield length */
9624 int bstr; /* bitfield starting bit within byte */
9627 D(emitcode ("; genUnpackBits",""));
9629 etype = getSpec (operandType (result));
9630 rsize = getSize (operandType (result));
9631 blen = SPEC_BLEN (etype);
9632 bstr = SPEC_BSTR (etype);
9634 if (ifx && blen <= 8)
9636 emitPtrByteGet (rname, ptype, FALSE);
9639 SNPRINTF (buffer, sizeof(buffer),
9641 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9646 emitcode ("anl", "a,#0x%02x",
9647 (((unsigned char) -1) >> (8 - blen)) << bstr);
9648 genIfxJump (ifx, "a", NULL, NULL, NULL);
9654 /* If the bitfield length is less than a byte */
9657 emitPtrByteGet (rname, ptype, FALSE);
9659 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9660 if (!SPEC_USIGN (etype))
9662 /* signed bitfield */
9663 symbol *tlbl = newiTempLabel (NULL);
9665 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9666 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9669 aopPut (result, "a", offset++);
9673 /* Bit field did not fit in a byte. Copy all
9674 but the partial byte at the end. */
9675 for (rlen=blen;rlen>=8;rlen-=8)
9677 emitPtrByteGet (rname, ptype, FALSE);
9678 aopPut (result, "a", offset++);
9680 emitcode ("inc", "%s", rname);
9683 /* Handle the partial byte at the end */
9686 emitPtrByteGet (rname, ptype, FALSE);
9687 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9688 if (!SPEC_USIGN (etype))
9690 /* signed bitfield */
9691 symbol *tlbl = newiTempLabel (NULL);
9693 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9694 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9697 aopPut (result, "a", offset++);
9705 if (SPEC_USIGN (etype))
9709 /* signed bitfield: sign extension with 0x00 or 0xff */
9710 emitcode ("rlc", "a");
9711 emitcode ("subb", "a,acc");
9717 aopPut (result, source, offset++);
9722 /*-----------------------------------------------------------------*/
9723 /* genDataPointerGet - generates code when ptr offset is known */
9724 /*-----------------------------------------------------------------*/
9726 genDataPointerGet (operand * left,
9732 int size, offset = 0;
9734 D (emitcode (";", "genDataPointerGet"));
9736 aopOp (result, ic, TRUE);
9738 /* get the string representation of the name */
9739 l = aopGet (left, 0, FALSE, TRUE);
9741 size = AOP_SIZE (result);
9746 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9750 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9752 aopPut (result, buffer, offset++);
9755 freeAsmop (result, NULL, ic, TRUE);
9756 freeAsmop (left, NULL, ic, TRUE);
9759 /*-----------------------------------------------------------------*/
9760 /* genNearPointerGet - emitcode for near pointer fetch */
9761 /*-----------------------------------------------------------------*/
9763 genNearPointerGet (operand * left,
9772 sym_link *rtype, *retype;
9773 sym_link *ltype = operandType (left);
9776 D (emitcode (";", "genNearPointerGet"));
9778 rtype = operandType (result);
9779 retype = getSpec (rtype);
9781 aopOp (left, ic, FALSE);
9783 /* if left is rematerialisable and
9784 result is not bitfield variable type and
9785 the left is pointer to data space i.e
9786 lower 128 bytes of space */
9787 if (AOP_TYPE (left) == AOP_IMMD &&
9788 !IS_BITFIELD (retype) &&
9789 DCL_TYPE (ltype) == POINTER)
9791 genDataPointerGet (left, result, ic);
9795 /* if the value is already in a pointer register
9796 then don't need anything more */
9797 if (!AOP_INPREG (AOP (left)))
9799 if (IS_AOP_PREG (left))
9801 // Aha, it is a pointer, just in disguise.
9802 rname = aopGet (left, 0, FALSE, FALSE);
9805 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9806 __FILE__, __LINE__);
9811 emitcode ("mov", "a%s,%s", rname + 1, rname);
9812 rname++; // skip the '@'.
9817 /* otherwise get a free pointer register */
9819 preg = getFreePtr (ic, &aop, FALSE);
9820 emitcode ("mov", "%s,%s",
9822 aopGet (left, 0, FALSE, TRUE));
9827 rname = aopGet (left, 0, FALSE, FALSE);
9829 //aopOp (result, ic, FALSE);
9830 aopOp (result, ic, result?TRUE:FALSE);
9832 /* if bitfield then unpack the bits */
9833 if (IS_BITFIELD (retype))
9834 genUnpackBits (result, rname, POINTER, ifx);
9837 /* we have can just get the values */
9838 int size = AOP_SIZE (result);
9843 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9846 emitcode ("mov", "a,@%s", rname);
9848 aopPut (result, "a", offset);
9852 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9853 aopPut (result, buffer, offset);
9857 emitcode ("inc", "%s", rname);
9861 /* now some housekeeping stuff */
9862 if (aop) /* we had to allocate for this iCode */
9864 if (pi) { /* post increment present */
9865 aopPut (left, rname, 0);
9867 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9871 /* we did not allocate which means left
9872 already in a pointer register, then
9873 if size > 0 && this could be used again
9874 we have to point it back to where it
9876 if ((AOP_SIZE (result) > 1 &&
9877 !OP_SYMBOL (left)->remat &&
9878 (OP_SYMBOL (left)->liveTo > ic->seq ||
9882 int size = AOP_SIZE (result) - 1;
9884 emitcode ("dec", "%s", rname);
9888 if (ifx && !ifx->generated)
9890 genIfxJump (ifx, "a", left, NULL, result);
9894 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9895 freeAsmop (left, NULL, ic, TRUE);
9896 if (pi) pi->generated = 1;
9899 /*-----------------------------------------------------------------*/
9900 /* genPagedPointerGet - emitcode for paged pointer fetch */
9901 /*-----------------------------------------------------------------*/
9903 genPagedPointerGet (operand * left,
9912 sym_link *rtype, *retype;
9914 D (emitcode (";", "genPagedPointerGet"));
9916 rtype = operandType (result);
9917 retype = getSpec (rtype);
9919 aopOp (left, ic, FALSE);
9921 /* if the value is already in a pointer register
9922 then don't need anything more */
9923 if (!AOP_INPREG (AOP (left)))
9925 /* otherwise get a free pointer register */
9927 preg = getFreePtr (ic, &aop, FALSE);
9928 emitcode ("mov", "%s,%s",
9930 aopGet (left, 0, FALSE, TRUE));
9934 rname = aopGet (left, 0, FALSE, FALSE);
9936 aopOp (result, ic, FALSE);
9938 /* if bitfield then unpack the bits */
9939 if (IS_BITFIELD (retype))
9940 genUnpackBits (result, rname, PPOINTER, ifx);
9943 /* we have can just get the values */
9944 int size = AOP_SIZE (result);
9950 emitcode ("movx", "a,@%s", rname);
9952 aopPut (result, "a", offset);
9957 emitcode ("inc", "%s", rname);
9961 /* now some housekeeping stuff */
9962 if (aop) /* we had to allocate for this iCode */
9965 aopPut (left, rname, 0);
9966 freeAsmop (NULL, aop, ic, TRUE);
9970 /* we did not allocate which means left
9971 already in a pointer register, then
9972 if size > 0 && this could be used again
9973 we have to point it back to where it
9975 if ((AOP_SIZE (result) > 1 &&
9976 !OP_SYMBOL (left)->remat &&
9977 (OP_SYMBOL (left)->liveTo > ic->seq ||
9981 int size = AOP_SIZE (result) - 1;
9983 emitcode ("dec", "%s", rname);
9987 if (ifx && !ifx->generated)
9989 genIfxJump (ifx, "a", left, NULL, result);
9993 freeAsmop (result, NULL, ic, TRUE);
9994 freeAsmop (left, NULL, ic, TRUE);
9995 if (pi) pi->generated = 1;
9998 /*--------------------------------------------------------------------*/
9999 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10000 /*--------------------------------------------------------------------*/
10002 loadDptrFromOperand (operand *op, bool loadBToo)
10004 if (AOP_TYPE (op) != AOP_STR)
10006 /* if this is rematerializable */
10007 if (AOP_TYPE (op) == AOP_IMMD)
10009 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10012 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10013 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10016 wassertl(FALSE, "need pointerCode");
10017 emitcode ("", "; mov b,???");
10018 /* genPointerGet and genPointerSet originally did different
10019 ** things for this case. Both seem wrong.
10020 ** from genPointerGet:
10021 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10022 ** from genPointerSet:
10023 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10028 else if (AOP_TYPE (op) == AOP_DPTR)
10032 MOVA (aopGet (op, 0, FALSE, FALSE));
10033 emitcode ("push", "acc");
10034 MOVA (aopGet (op, 1, FALSE, FALSE));
10035 emitcode ("push", "acc");
10036 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10037 emitcode ("pop", "dph");
10038 emitcode ("pop", "dpl");
10042 MOVA (aopGet (op, 0, FALSE, FALSE));
10043 emitcode ("push", "acc");
10044 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10045 emitcode ("pop", "dpl");
10049 { /* we need to get it byte by byte */
10050 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10051 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10053 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10058 /*-----------------------------------------------------------------*/
10059 /* genFarPointerGet - get value from far space */
10060 /*-----------------------------------------------------------------*/
10062 genFarPointerGet (operand * left,
10063 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10066 sym_link *retype = getSpec (operandType (result));
10068 D (emitcode (";", "genFarPointerGet"));
10070 aopOp (left, ic, FALSE);
10071 loadDptrFromOperand (left, FALSE);
10073 /* so dptr now contains the address */
10074 aopOp (result, ic, FALSE);
10076 /* if bit then unpack */
10077 if (IS_BITFIELD (retype))
10078 genUnpackBits (result, "dptr", FPOINTER, ifx);
10081 size = AOP_SIZE (result);
10086 emitcode ("movx", "a,@dptr");
10088 aopPut (result, "a", offset++);
10090 emitcode ("inc", "dptr");
10094 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10096 aopPut (left, "dpl", 0);
10097 aopPut (left, "dph", 1);
10101 if (ifx && !ifx->generated)
10103 genIfxJump (ifx, "a", left, NULL, result);
10106 freeAsmop (result, NULL, ic, TRUE);
10107 freeAsmop (left, NULL, ic, TRUE);
10110 /*-----------------------------------------------------------------*/
10111 /* genCodePointerGet - get value from code space */
10112 /*-----------------------------------------------------------------*/
10114 genCodePointerGet (operand * left,
10115 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10118 sym_link *retype = getSpec (operandType (result));
10120 D (emitcode (";", "genCodePointerGet"));
10122 aopOp (left, ic, FALSE);
10123 loadDptrFromOperand (left, FALSE);
10125 /* so dptr now contains the address */
10126 aopOp (result, ic, FALSE);
10128 /* if bit then unpack */
10129 if (IS_BITFIELD (retype))
10130 genUnpackBits (result, "dptr", CPOINTER, ifx);
10133 size = AOP_SIZE (result);
10138 emitcode ("clr", "a");
10139 emitcode ("movc", "a,@a+dptr");
10141 aopPut (result, "a", offset++);
10143 emitcode ("inc", "dptr");
10147 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10149 aopPut (left, "dpl", 0);
10150 aopPut (left, "dph", 1);
10154 if (ifx && !ifx->generated)
10156 genIfxJump (ifx, "a", left, NULL, result);
10159 freeAsmop (result, NULL, ic, TRUE);
10160 freeAsmop (left, NULL, ic, TRUE);
10163 /*-----------------------------------------------------------------*/
10164 /* genGenPointerGet - get value from generic pointer space */
10165 /*-----------------------------------------------------------------*/
10167 genGenPointerGet (operand * left,
10168 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10171 sym_link *retype = getSpec (operandType (result));
10173 D (emitcode (";", "genGenPointerGet"));
10175 aopOp (left, ic, FALSE);
10176 loadDptrFromOperand (left, TRUE);
10178 /* so dptr now contains the address */
10179 aopOp (result, ic, FALSE);
10181 /* if bit then unpack */
10182 if (IS_BITFIELD (retype))
10184 genUnpackBits (result, "dptr", GPOINTER, ifx);
10188 size = AOP_SIZE (result);
10193 emitcode ("lcall", "__gptrget");
10195 aopPut (result, "a", offset++);
10197 emitcode ("inc", "dptr");
10201 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10203 aopPut (left, "dpl", 0);
10204 aopPut (left, "dph", 1);
10208 if (ifx && !ifx->generated)
10210 genIfxJump (ifx, "a", left, NULL, result);
10213 freeAsmop (result, NULL, ic, TRUE);
10214 freeAsmop (left, NULL, ic, TRUE);
10217 /*-----------------------------------------------------------------*/
10218 /* genPointerGet - generate code for pointer get */
10219 /*-----------------------------------------------------------------*/
10221 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10223 operand *left, *result;
10224 sym_link *type, *etype;
10227 D (emitcode (";", "genPointerGet"));
10229 left = IC_LEFT (ic);
10230 result = IC_RESULT (ic);
10232 if (getSize (operandType (result))>1)
10235 /* depending on the type of pointer we need to
10236 move it to the correct pointer register */
10237 type = operandType (left);
10238 etype = getSpec (type);
10239 /* if left is of type of pointer then it is simple */
10240 if (IS_PTR (type) && !IS_FUNC (type->next))
10241 p_type = DCL_TYPE (type);
10244 /* we have to go by the storage class */
10245 p_type = PTR_TYPE (SPEC_OCLS (etype));
10248 /* special case when cast remat */
10249 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10250 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10252 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10253 type = operandType (left);
10254 p_type = DCL_TYPE (type);
10256 /* now that we have the pointer type we assign
10257 the pointer values */
10263 genNearPointerGet (left, result, ic, pi, ifx);
10267 genPagedPointerGet (left, result, ic, pi, ifx);
10271 genFarPointerGet (left, result, ic, pi, ifx);
10275 genCodePointerGet (left, result, ic, pi, ifx);
10279 genGenPointerGet (left, result, ic, pi, ifx);
10285 /*-----------------------------------------------------------------*/
10286 /* genPackBits - generates code for packed bit storage */
10287 /*-----------------------------------------------------------------*/
10289 genPackBits (sym_link * etype,
10291 char *rname, int p_type)
10293 int offset = 0; /* source byte offset */
10294 int rlen = 0; /* remaining bitfield length */
10295 int blen; /* bitfield length */
10296 int bstr; /* bitfield starting bit within byte */
10297 int litval; /* source literal value (if AOP_LIT) */
10298 unsigned char mask; /* bitmask within current byte */
10300 D(emitcode ("; genPackBits",""));
10302 blen = SPEC_BLEN (etype);
10303 bstr = SPEC_BSTR (etype);
10305 /* If the bitfield length is less than a byte */
10308 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10309 (unsigned char) (0xFF >> (8 - bstr)));
10311 if (AOP_TYPE (right) == AOP_LIT)
10313 /* Case with a bitfield length <8 and literal source
10315 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10317 litval &= (~mask) & 0xff;
10318 emitPtrByteGet (rname, p_type, FALSE);
10319 if ((mask|litval)!=0xff)
10320 emitcode ("anl","a,#0x%02x", mask);
10322 emitcode ("orl","a,#0x%02x", litval);
10326 if ((blen==1) && (p_type!=GPOINTER))
10328 /* Case with a bitfield length == 1 and no generic pointer
10330 if (AOP_TYPE (right) == AOP_CRY)
10331 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10334 MOVA (aopGet (right, 0, FALSE, FALSE));
10335 emitcode ("rrc","a");
10337 emitPtrByteGet (rname, p_type, FALSE);
10338 emitcode ("mov","acc.%d,c",bstr);
10343 /* Case with a bitfield length < 8 and arbitrary source
10345 MOVA (aopGet (right, 0, FALSE, FALSE));
10346 /* shift and mask source value */
10348 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10350 pushedB = pushB ();
10351 /* transfer A to B and get next byte */
10352 emitPtrByteGet (rname, p_type, TRUE);
10354 emitcode ("anl", "a,#0x%02x", mask);
10355 emitcode ("orl", "a,b");
10356 if (p_type == GPOINTER)
10357 emitcode ("pop", "b");
10363 emitPtrByteSet (rname, p_type, "a");
10367 /* Bit length is greater than 7 bits. In this case, copy */
10368 /* all except the partial byte at the end */
10369 for (rlen=blen;rlen>=8;rlen-=8)
10371 emitPtrByteSet (rname, p_type,
10372 aopGet (right, offset++, FALSE, TRUE) );
10374 emitcode ("inc", "%s", rname);
10377 /* If there was a partial byte at the end */
10380 mask = (((unsigned char) -1 << rlen) & 0xff);
10382 if (AOP_TYPE (right) == AOP_LIT)
10384 /* Case with partial byte and literal source
10386 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10387 litval >>= (blen-rlen);
10388 litval &= (~mask) & 0xff;
10389 emitPtrByteGet (rname, p_type, FALSE);
10390 if ((mask|litval)!=0xff)
10391 emitcode ("anl","a,#0x%02x", mask);
10393 emitcode ("orl","a,#0x%02x", litval);
10398 /* Case with partial byte and arbitrary source
10400 MOVA (aopGet (right, offset++, FALSE, FALSE));
10401 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10403 pushedB = pushB ();
10404 /* transfer A to B and get next byte */
10405 emitPtrByteGet (rname, p_type, TRUE);
10407 emitcode ("anl", "a,#0x%02x", mask);
10408 emitcode ("orl", "a,b");
10409 if (p_type == GPOINTER)
10410 emitcode ("pop", "b");
10414 emitPtrByteSet (rname, p_type, "a");
10419 /*-----------------------------------------------------------------*/
10420 /* genDataPointerSet - remat pointer to data space */
10421 /*-----------------------------------------------------------------*/
10423 genDataPointerSet (operand * right,
10427 int size, offset = 0;
10428 char *l, buffer[256];
10430 D (emitcode (";", "genDataPointerSet"));
10432 aopOp (right, ic, FALSE);
10434 l = aopGet (result, 0, FALSE, TRUE);
10436 size = AOP_SIZE (right);
10440 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10442 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10443 emitcode ("mov", "%s,%s", buffer,
10444 aopGet (right, offset++, FALSE, FALSE));
10447 freeAsmop (result, NULL, ic, TRUE);
10448 freeAsmop (right, NULL, ic, TRUE);
10451 /*-----------------------------------------------------------------*/
10452 /* genNearPointerSet - emitcode for near pointer put */
10453 /*-----------------------------------------------------------------*/
10455 genNearPointerSet (operand * right,
10463 sym_link *retype, *letype;
10464 sym_link *ptype = operandType (result);
10466 D (emitcode (";", "genNearPointerSet"));
10468 retype = getSpec (operandType (right));
10469 letype = getSpec (ptype);
10471 aopOp (result, ic, FALSE);
10473 /* if the result is rematerializable &
10474 in data space & not a bit variable */
10475 if (AOP_TYPE (result) == AOP_IMMD &&
10476 DCL_TYPE (ptype) == POINTER &&
10477 !IS_BITVAR (retype) &&
10478 !IS_BITVAR (letype))
10480 genDataPointerSet (right, result, ic);
10484 /* if the value is already in a pointer register
10485 then don't need anything more */
10486 if (!AOP_INPREG (AOP (result)))
10489 //AOP_TYPE (result) == AOP_STK
10490 IS_AOP_PREG(result)
10493 // Aha, it is a pointer, just in disguise.
10494 rname = aopGet (result, 0, FALSE, FALSE);
10497 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10498 __FILE__, __LINE__);
10503 emitcode ("mov", "a%s,%s", rname + 1, rname);
10504 rname++; // skip the '@'.
10509 /* otherwise get a free pointer register */
10510 aop = newAsmop (0);
10511 preg = getFreePtr (ic, &aop, FALSE);
10512 emitcode ("mov", "%s,%s",
10514 aopGet (result, 0, FALSE, TRUE));
10515 rname = preg->name;
10520 rname = aopGet (result, 0, FALSE, FALSE);
10523 aopOp (right, ic, FALSE);
10525 /* if bitfield then unpack the bits */
10526 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10527 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10530 /* we can just get the values */
10531 int size = AOP_SIZE (right);
10536 l = aopGet (right, offset, FALSE, TRUE);
10537 if ((*l == '@') || (strcmp (l, "acc") == 0))
10540 emitcode ("mov", "@%s,a", rname);
10543 emitcode ("mov", "@%s,%s", rname, l);
10545 emitcode ("inc", "%s", rname);
10550 /* now some housekeeping stuff */
10551 if (aop) /* we had to allocate for this iCode */
10554 aopPut (result, rname, 0);
10555 freeAsmop (NULL, aop, ic, TRUE);
10559 /* we did not allocate which means left
10560 already in a pointer register, then
10561 if size > 0 && this could be used again
10562 we have to point it back to where it
10564 if ((AOP_SIZE (right) > 1 &&
10565 !OP_SYMBOL (result)->remat &&
10566 (OP_SYMBOL (result)->liveTo > ic->seq ||
10570 int size = AOP_SIZE (right) - 1;
10572 emitcode ("dec", "%s", rname);
10577 if (pi) pi->generated = 1;
10578 freeAsmop (result, NULL, ic, TRUE);
10579 freeAsmop (right, NULL, ic, TRUE);
10582 /*-----------------------------------------------------------------*/
10583 /* genPagedPointerSet - emitcode for Paged pointer put */
10584 /*-----------------------------------------------------------------*/
10586 genPagedPointerSet (operand * right,
10594 sym_link *retype, *letype;
10596 D (emitcode (";", "genPagedPointerSet"));
10598 retype = getSpec (operandType (right));
10599 letype = getSpec (operandType (result));
10601 aopOp (result, ic, FALSE);
10603 /* if the value is already in a pointer register
10604 then don't need anything more */
10605 if (!AOP_INPREG (AOP (result)))
10607 /* otherwise get a free pointer register */
10608 aop = newAsmop (0);
10609 preg = getFreePtr (ic, &aop, FALSE);
10610 emitcode ("mov", "%s,%s",
10612 aopGet (result, 0, FALSE, TRUE));
10613 rname = preg->name;
10616 rname = aopGet (result, 0, FALSE, FALSE);
10618 aopOp (right, ic, FALSE);
10620 /* if bitfield then unpack the bits */
10621 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10622 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10625 /* we have can just get the values */
10626 int size = AOP_SIZE (right);
10631 l = aopGet (right, offset, FALSE, TRUE);
10633 emitcode ("movx", "@%s,a", rname);
10636 emitcode ("inc", "%s", rname);
10642 /* now some housekeeping stuff */
10643 if (aop) /* we had to allocate for this iCode */
10646 aopPut (result, rname, 0);
10647 freeAsmop (NULL, aop, ic, TRUE);
10651 /* we did not allocate which means left
10652 already in a pointer register, then
10653 if size > 0 && this could be used again
10654 we have to point it back to where it
10656 if (AOP_SIZE (right) > 1 &&
10657 !OP_SYMBOL (result)->remat &&
10658 (OP_SYMBOL (result)->liveTo > ic->seq ||
10661 int size = AOP_SIZE (right) - 1;
10663 emitcode ("dec", "%s", rname);
10668 if (pi) pi->generated = 1;
10669 freeAsmop (result, NULL, ic, TRUE);
10670 freeAsmop (right, NULL, ic, TRUE);
10673 /*-----------------------------------------------------------------*/
10674 /* genFarPointerSet - set value from far space */
10675 /*-----------------------------------------------------------------*/
10677 genFarPointerSet (operand * right,
10678 operand * result, iCode * ic, iCode * pi)
10681 sym_link *retype = getSpec (operandType (right));
10682 sym_link *letype = getSpec (operandType (result));
10684 D(emitcode ("; genFarPointerSet",""));
10686 aopOp (result, ic, FALSE);
10687 loadDptrFromOperand (result, FALSE);
10689 /* so dptr now contains the address */
10690 aopOp (right, ic, FALSE);
10692 /* if bit then unpack */
10693 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10694 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10697 size = AOP_SIZE (right);
10702 char *l = aopGet (right, offset++, FALSE, FALSE);
10704 emitcode ("movx", "@dptr,a");
10706 emitcode ("inc", "dptr");
10709 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10710 aopPut (result, "dpl", 0);
10711 aopPut (result, "dph", 1);
10714 freeAsmop (result, NULL, ic, TRUE);
10715 freeAsmop (right, NULL, ic, TRUE);
10718 /*-----------------------------------------------------------------*/
10719 /* genGenPointerSet - set value from generic pointer space */
10720 /*-----------------------------------------------------------------*/
10722 genGenPointerSet (operand * right,
10723 operand * result, iCode * ic, iCode * pi)
10726 sym_link *retype = getSpec (operandType (right));
10727 sym_link *letype = getSpec (operandType (result));
10729 D (emitcode (";", "genGenPointerSet"));
10731 aopOp (result, ic, FALSE);
10732 loadDptrFromOperand (result, TRUE);
10734 /* so dptr now contains the address */
10735 aopOp (right, ic, FALSE);
10737 /* if bit then unpack */
10738 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10740 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10744 size = AOP_SIZE (right);
10749 char *l = aopGet (right, offset++, FALSE, FALSE);
10751 emitcode ("lcall", "__gptrput");
10753 emitcode ("inc", "dptr");
10757 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10758 aopPut (result, "dpl", 0);
10759 aopPut (result, "dph", 1);
10762 freeAsmop (result, NULL, ic, TRUE);
10763 freeAsmop (right, NULL, ic, TRUE);
10766 /*-----------------------------------------------------------------*/
10767 /* genPointerSet - stores the value into a pointer location */
10768 /*-----------------------------------------------------------------*/
10770 genPointerSet (iCode * ic, iCode *pi)
10772 operand *right, *result;
10773 sym_link *type, *etype;
10776 D (emitcode (";", "genPointerSet"));
10778 right = IC_RIGHT (ic);
10779 result = IC_RESULT (ic);
10781 /* depending on the type of pointer we need to
10782 move it to the correct pointer register */
10783 type = operandType (result);
10784 etype = getSpec (type);
10785 /* if left is of type of pointer then it is simple */
10786 if (IS_PTR (type) && !IS_FUNC (type->next))
10788 p_type = DCL_TYPE (type);
10792 /* we have to go by the storage class */
10793 p_type = PTR_TYPE (SPEC_OCLS (etype));
10796 /* special case when cast remat */
10797 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10798 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10799 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10800 type = operandType (result);
10801 p_type = DCL_TYPE (type);
10804 /* now that we have the pointer type we assign
10805 the pointer values */
10811 genNearPointerSet (right, result, ic, pi);
10815 genPagedPointerSet (right, result, ic, pi);
10819 genFarPointerSet (right, result, ic, pi);
10823 genGenPointerSet (right, result, ic, pi);
10827 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10828 "genPointerSet: illegal pointer type");
10832 /*-----------------------------------------------------------------*/
10833 /* genIfx - generate code for Ifx statement */
10834 /*-----------------------------------------------------------------*/
10836 genIfx (iCode * ic, iCode * popIc)
10838 operand *cond = IC_COND (ic);
10842 D (emitcode (";", "genIfx"));
10844 aopOp (cond, ic, FALSE);
10846 /* get the value into acc */
10847 if (AOP_TYPE (cond) != AOP_CRY)
10854 if (AOP(cond)->aopu.aop_dir)
10855 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10858 /* the result is now in the accumulator or a directly addressable bit */
10859 freeAsmop (cond, NULL, ic, TRUE);
10861 /* if there was something to be popped then do it */
10865 /* if the condition is a bit variable */
10867 genIfxJump(ic, dup, NULL, NULL, NULL);
10868 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10869 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10870 else if (isbit && !IS_ITEMP (cond))
10871 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10873 genIfxJump (ic, "a", NULL, NULL, NULL);
10878 /*-----------------------------------------------------------------*/
10879 /* genAddrOf - generates code for address of */
10880 /*-----------------------------------------------------------------*/
10882 genAddrOf (iCode * ic)
10884 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10887 D (emitcode (";", "genAddrOf"));
10889 aopOp (IC_RESULT (ic), ic, FALSE);
10891 /* if the operand is on the stack then we
10892 need to get the stack offset of this
10896 /* if it has an offset then we need to compute it */
10899 int stack_offset = ((sym->stack < 0) ?
10900 ((char) (sym->stack - _G.nRegsSaved)) :
10901 ((char) sym->stack)) & 0xff;
10902 if ((abs(stack_offset) == 1) &&
10903 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10904 !isOperandVolatile (IC_RESULT (ic), FALSE))
10906 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10907 if (stack_offset > 0)
10908 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10910 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10914 emitcode ("mov", "a,%s", SYM_BP (sym));
10915 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10916 aopPut (IC_RESULT (ic), "a", 0);
10921 /* we can just move _bp */
10922 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10924 /* fill the result with zero */
10925 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10930 aopPut (IC_RESULT (ic), zero, offset++);
10935 /* object not on stack then we need the name */
10936 size = AOP_SIZE (IC_RESULT (ic));
10941 char s[SDCC_NAME_MAX];
10943 sprintf (s, "#(%s >> %d)",
10947 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10948 aopPut (IC_RESULT (ic), s, offset++);
10952 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10956 /*-----------------------------------------------------------------*/
10957 /* genFarFarAssign - assignment when both are in far space */
10958 /*-----------------------------------------------------------------*/
10960 genFarFarAssign (operand * result, operand * right, iCode * ic)
10962 int size = AOP_SIZE (right);
10966 D (emitcode (";", "genFarFarAssign"));
10968 /* first push the right side on to the stack */
10971 l = aopGet (right, offset++, FALSE, FALSE);
10973 emitcode ("push", "acc");
10976 freeAsmop (right, NULL, ic, FALSE);
10977 /* now assign DPTR to result */
10978 aopOp (result, ic, FALSE);
10979 size = AOP_SIZE (result);
10982 emitcode ("pop", "acc");
10983 aopPut (result, "a", --offset);
10985 freeAsmop (result, NULL, ic, FALSE);
10988 /*-----------------------------------------------------------------*/
10989 /* genAssign - generate code for assignment */
10990 /*-----------------------------------------------------------------*/
10992 genAssign (iCode * ic)
10994 operand *result, *right;
10996 unsigned long lit = 0L;
10998 D (emitcode (";", "genAssign"));
11000 result = IC_RESULT (ic);
11001 right = IC_RIGHT (ic);
11003 /* if they are the same */
11004 if (operandsEqu (result, right) &&
11005 !isOperandVolatile (result, FALSE) &&
11006 !isOperandVolatile (right, FALSE))
11009 aopOp (right, ic, FALSE);
11011 /* special case both in far space */
11012 if (AOP_TYPE (right) == AOP_DPTR &&
11013 IS_TRUE_SYMOP (result) &&
11014 isOperandInFarSpace (result))
11016 genFarFarAssign (result, right, ic);
11020 aopOp (result, ic, TRUE);
11022 /* if they are the same registers */
11023 if (sameRegs (AOP (right), AOP (result)) &&
11024 !isOperandVolatile (result, FALSE) &&
11025 !isOperandVolatile (right, FALSE))
11028 /* if the result is a bit */
11029 if (AOP_TYPE (result) == AOP_CRY)
11031 /* if the right size is a literal then
11032 we know what the value is */
11033 if (AOP_TYPE (right) == AOP_LIT)
11035 if (((int) operandLitValue (right)))
11036 aopPut (result, one, 0);
11038 aopPut (result, zero, 0);
11042 /* the right is also a bit variable */
11043 if (AOP_TYPE (right) == AOP_CRY)
11045 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11046 aopPut (result, "c", 0);
11050 /* we need to or */
11052 aopPut (result, "a", 0);
11056 /* bit variables done */
11058 size = AOP_SIZE (result);
11060 if (AOP_TYPE (right) == AOP_LIT)
11061 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11064 (AOP_TYPE (result) != AOP_REG) &&
11065 (AOP_TYPE (right) == AOP_LIT) &&
11066 !IS_FLOAT (operandType (right)) &&
11069 while ((size) && (lit))
11072 aopGet (right, offset, FALSE, FALSE),
11078 /* And now fill the rest with zeros. */
11081 emitcode ("clr", "a");
11085 aopPut (result, "a", offset);
11094 aopGet (right, offset, FALSE, FALSE),
11101 freeAsmop (result, NULL, ic, TRUE);
11102 freeAsmop (right, NULL, ic, TRUE);
11105 /*-----------------------------------------------------------------*/
11106 /* genJumpTab - generates code for jump table */
11107 /*-----------------------------------------------------------------*/
11109 genJumpTab (iCode * ic)
11111 symbol *jtab,*jtablo,*jtabhi;
11113 unsigned int count;
11115 D (emitcode (";", "genJumpTab"));
11117 count = elementsInSet( IC_JTLABELS (ic) );
11121 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11122 if the switch argument is in a register.
11123 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11124 /* Peephole may not convert ljmp to sjmp or ret
11125 labelIsReturnOnly & labelInRange must check
11126 currPl->ic->op != JUMPTABLE */
11127 aopOp (IC_JTCOND (ic), ic, FALSE);
11128 /* get the condition into accumulator */
11129 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11131 /* multiply by three */
11132 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11134 emitcode ("mov", "b,#3");
11135 emitcode ("mul", "ab");
11139 emitcode ("add", "a,acc");
11140 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11142 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11144 jtab = newiTempLabel (NULL);
11145 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11146 emitcode ("jmp", "@a+dptr");
11148 /* now generate the jump labels */
11149 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11150 jtab = setNextItem (IC_JTLABELS (ic)))
11151 emitcode ("ljmp", "%05d$", jtab->key + 100);
11155 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11156 if the switch argument is in a register.
11157 For n>6 this algorithm may be more compact */
11158 jtablo = newiTempLabel (NULL);
11159 jtabhi = newiTempLabel (NULL);
11161 /* get the condition into accumulator.
11162 Using b as temporary storage, if register push/pop is needed */
11163 aopOp (IC_JTCOND (ic), ic, FALSE);
11164 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11165 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11166 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11168 // (MB) what if B is in use???
11169 wassertl(!BINUSE, "B was in use");
11170 emitcode ("mov", "b,%s", l);
11173 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11177 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11178 emitcode ("movc", "a,@a+pc");
11179 emitcode ("push", "acc");
11182 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11183 emitcode ("movc", "a,@a+pc");
11184 emitcode ("push", "acc");
11188 /* this scales up to n<=255, but needs two more bytes
11189 and changes dptr */
11190 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11191 emitcode ("movc", "a,@a+dptr");
11192 emitcode ("push", "acc");
11195 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11196 emitcode ("movc", "a,@a+dptr");
11197 emitcode ("push", "acc");
11200 emitcode ("ret", "");
11202 /* now generate jump table, LSB */
11203 emitLabel (jtablo);
11204 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11205 jtab = setNextItem (IC_JTLABELS (ic)))
11206 emitcode (".db", "%05d$", jtab->key + 100);
11208 /* now generate jump table, MSB */
11209 emitLabel (jtabhi);
11210 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11211 jtab = setNextItem (IC_JTLABELS (ic)))
11212 emitcode (".db", "%05d$>>8", jtab->key + 100);
11216 /*-----------------------------------------------------------------*/
11217 /* genCast - gen code for casting */
11218 /*-----------------------------------------------------------------*/
11220 genCast (iCode * ic)
11222 operand *result = IC_RESULT (ic);
11223 sym_link *ctype = operandType (IC_LEFT (ic));
11224 sym_link *rtype = operandType (IC_RIGHT (ic));
11225 operand *right = IC_RIGHT (ic);
11228 D (emitcode (";", "genCast"));
11230 /* if they are equivalent then do nothing */
11231 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11234 aopOp (right, ic, FALSE);
11235 aopOp (result, ic, FALSE);
11237 /* if the result is a bit (and not a bitfield) */
11238 if (IS_BIT (OP_SYMBOL (result)->type))
11240 /* if the right size is a literal then
11241 we know what the value is */
11242 if (AOP_TYPE (right) == AOP_LIT)
11244 if (((int) operandLitValue (right)))
11245 aopPut (result, one, 0);
11247 aopPut (result, zero, 0);
11252 /* the right is also a bit variable */
11253 if (AOP_TYPE (right) == AOP_CRY)
11255 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11256 aopPut (result, "c", 0);
11260 /* we need to or */
11262 aopPut (result, "a", 0);
11266 /* if they are the same size : or less */
11267 if (AOP_SIZE (result) <= AOP_SIZE (right))
11270 /* if they are in the same place */
11271 if (sameRegs (AOP (right), AOP (result)))
11274 /* if they in different places then copy */
11275 size = AOP_SIZE (result);
11280 aopGet (right, offset, FALSE, FALSE),
11287 /* if the result is of type pointer */
11288 if (IS_PTR (ctype))
11292 sym_link *type = operandType (right);
11293 sym_link *etype = getSpec (type);
11295 /* pointer to generic pointer */
11296 if (IS_GENPTR (ctype))
11300 p_type = DCL_TYPE (type);
11304 if (SPEC_SCLS(etype)==S_REGISTER) {
11305 // let's assume it is a generic pointer
11308 /* we have to go by the storage class */
11309 p_type = PTR_TYPE (SPEC_OCLS (etype));
11313 /* the first two bytes are known */
11314 size = GPTRSIZE - 1;
11319 aopGet (right, offset, FALSE, FALSE),
11323 /* the last byte depending on type */
11325 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11330 // pointerTypeToGPByte will have bitched.
11334 sprintf(gpValStr, "#0x%x", gpVal);
11335 aopPut (result, gpValStr, GPTRSIZE - 1);
11340 /* just copy the pointers */
11341 size = AOP_SIZE (result);
11346 aopGet (right, offset, FALSE, FALSE),
11353 /* so we now know that the size of destination is greater
11354 than the size of the source */
11355 /* we move to result for the size of source */
11356 size = AOP_SIZE (right);
11361 aopGet (right, offset, FALSE, FALSE),
11366 /* now depending on the sign of the source && destination */
11367 size = AOP_SIZE (result) - AOP_SIZE (right);
11368 /* if unsigned or not an integral type */
11369 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11372 aopPut (result, zero, offset++);
11376 /* we need to extend the sign :{ */
11377 char *l = aopGet (right, AOP_SIZE (right) - 1,
11380 emitcode ("rlc", "a");
11381 emitcode ("subb", "a,acc");
11383 aopPut (result, "a", offset++);
11386 /* we are done hurray !!!! */
11389 freeAsmop (result, NULL, ic, TRUE);
11390 freeAsmop (right, NULL, ic, TRUE);
11393 /*-----------------------------------------------------------------*/
11394 /* genDjnz - generate decrement & jump if not zero instrucion */
11395 /*-----------------------------------------------------------------*/
11397 genDjnz (iCode * ic, iCode * ifx)
11399 symbol *lbl, *lbl1;
11403 /* if the if condition has a false label
11404 then we cannot save */
11405 if (IC_FALSE (ifx))
11408 /* if the minus is not of the form a = a - 1 */
11409 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11410 !IS_OP_LITERAL (IC_RIGHT (ic)))
11413 if (operandLitValue (IC_RIGHT (ic)) != 1)
11416 /* if the size of this greater than one then no
11418 if (getSize (operandType (IC_RESULT (ic))) > 1)
11421 /* otherwise we can save BIG */
11423 D (emitcode (";", "genDjnz"));
11425 lbl = newiTempLabel (NULL);
11426 lbl1 = newiTempLabel (NULL);
11428 aopOp (IC_RESULT (ic), ic, FALSE);
11430 if (AOP_NEEDSACC(IC_RESULT(ic)))
11432 /* If the result is accessed indirectly via
11433 * the accumulator, we must explicitly write
11434 * it back after the decrement.
11436 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11438 if (strcmp(rByte, "a"))
11440 /* Something is hopelessly wrong */
11441 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11442 __FILE__, __LINE__);
11443 /* We can just give up; the generated code will be inefficient,
11444 * but what the hey.
11446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11449 emitcode ("dec", "%s", rByte);
11450 aopPut (IC_RESULT (ic), rByte, 0);
11451 emitcode ("jnz", "%05d$", lbl->key + 100);
11453 else if (IS_AOP_PREG (IC_RESULT (ic)))
11455 emitcode ("dec", "%s",
11456 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11457 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11458 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11459 ifx->generated = 1;
11460 emitcode ("jnz", "%05d$", lbl->key + 100);
11464 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11467 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11469 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11472 if (!ifx->generated)
11473 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11474 ifx->generated = 1;
11478 /*-----------------------------------------------------------------*/
11479 /* genReceive - generate code for a receive iCode */
11480 /*-----------------------------------------------------------------*/
11482 genReceive (iCode * ic)
11484 int size = getSize (operandType (IC_RESULT (ic)));
11487 D (emitcode (";", "genReceive"));
11489 if (ic->argreg == 1)
11490 { /* first parameter */
11491 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11492 isOperandInPagedSpace (IC_RESULT (ic))) &&
11493 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11494 IS_TRUE_SYMOP (IC_RESULT (ic))))
11497 int receivingA = 0;
11500 for (offset = 0; offset<size; offset++)
11501 if (!strcmp (fReturn[offset], "a"))
11506 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11508 for (offset = size-1; offset>0; offset--)
11509 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11510 emitcode("mov","a,%s", fReturn[0]);
11512 aopOp (IC_RESULT (ic), ic, FALSE);
11514 aopPut (IC_RESULT (ic), "a", offset);
11515 for (offset = 1; offset<size; offset++)
11516 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11522 if (getTempRegs(tempRegs, size, ic))
11524 for (offset = 0; offset<size; offset++)
11525 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11526 aopOp (IC_RESULT (ic), ic, FALSE);
11527 for (offset = 0; offset<size; offset++)
11528 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11533 offset = fReturnSizeMCS51 - size;
11536 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11537 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11540 aopOp (IC_RESULT (ic), ic, FALSE);
11541 size = AOP_SIZE (IC_RESULT (ic));
11545 emitcode ("pop", "acc");
11546 aopPut (IC_RESULT (ic), "a", offset++);
11552 aopOp (IC_RESULT (ic), ic, FALSE);
11554 assignResultValue (IC_RESULT (ic), NULL);
11557 else if (ic->argreg > 12)
11558 { /* bit parameters */
11559 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11561 aopOp (IC_RESULT (ic), ic, FALSE);
11562 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11563 outBitC(IC_RESULT (ic));
11567 { /* other parameters */
11569 aopOp (IC_RESULT (ic), ic, FALSE);
11570 rb1off = ic->argreg;
11573 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11578 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11581 /*-----------------------------------------------------------------*/
11582 /* genDummyRead - generate code for dummy read of volatiles */
11583 /*-----------------------------------------------------------------*/
11585 genDummyRead (iCode * ic)
11590 D (emitcode(";", "genDummyRead"));
11592 op = IC_RIGHT (ic);
11593 if (op && IS_SYMOP (op))
11595 aopOp (op, ic, FALSE);
11597 /* if the result is a bit */
11598 if (AOP_TYPE (op) == AOP_CRY)
11599 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11602 /* bit variables done */
11604 size = AOP_SIZE (op);
11608 MOVA (aopGet (op, offset, FALSE, FALSE));
11613 freeAsmop (op, NULL, ic, TRUE);
11617 if (op && IS_SYMOP (op))
11619 aopOp (op, ic, FALSE);
11621 /* if the result is a bit */
11622 if (AOP_TYPE (op) == AOP_CRY)
11623 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11626 /* bit variables done */
11628 size = AOP_SIZE (op);
11632 MOVA (aopGet (op, offset, FALSE, FALSE));
11637 freeAsmop (op, NULL, ic, TRUE);
11641 /*-----------------------------------------------------------------*/
11642 /* genCritical - generate code for start of a critical sequence */
11643 /*-----------------------------------------------------------------*/
11645 genCritical (iCode *ic)
11647 symbol *tlbl = newiTempLabel (NULL);
11649 D (emitcode(";", "genCritical"));
11651 if (IC_RESULT (ic))
11653 aopOp (IC_RESULT (ic), ic, TRUE);
11654 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11655 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11656 aopPut (IC_RESULT (ic), zero, 0);
11658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11662 emitcode ("setb", "c");
11663 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11664 emitcode ("clr", "c");
11666 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11670 /*-----------------------------------------------------------------*/
11671 /* genEndCritical - generate code for end of a critical sequence */
11672 /*-----------------------------------------------------------------*/
11674 genEndCritical (iCode *ic)
11676 D(emitcode("; genEndCritical",""));
11680 aopOp (IC_RIGHT (ic), ic, FALSE);
11681 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11683 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11684 emitcode ("mov", "ea,c");
11688 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11689 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11690 emitcode ("rrc", "a");
11691 emitcode ("mov", "ea,c");
11693 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11697 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11698 emitcode ("mov", "ea,c");
11702 /*-----------------------------------------------------------------*/
11703 /* gen51Code - generate code for 8051 based controllers */
11704 /*-----------------------------------------------------------------*/
11706 gen51Code (iCode * lic)
11710 /* int cseq = 0; */
11712 _G.currentFunc = NULL;
11713 lineHead = lineCurr = NULL;
11715 /* print the allocation information */
11716 if (allocInfo && currFunc)
11717 printAllocInfo (currFunc, codeOutFile);
11718 /* if debug information required */
11719 if (options.debug && currFunc)
11721 debugFile->writeFunction (currFunc, lic);
11723 /* stack pointer name */
11724 if (options.useXstack)
11730 for (ic = lic; ic; ic = ic->next)
11732 _G.current_iCode = ic;
11734 if (ic->lineno && cln != ic->lineno)
11738 debugFile->writeCLine (ic);
11740 if (!options.noCcodeInAsm) {
11741 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11742 printCLine(ic->filename, ic->lineno));
11747 if (ic->seqPoint && ic->seqPoint != cseq)
11749 emitcode ("", "; sequence point %d", ic->seqPoint);
11750 cseq = ic->seqPoint;
11753 if (options.iCodeInAsm) {
11754 char regsInUse[80];
11758 for (i=0; i<8; i++) {
11759 sprintf (®sInUse[i],
11760 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11763 strcpy (regsInUse, "--------");
11764 for (i=0; i < 8; i++) {
11765 if (bitVectBitValue (ic->rMask, i))
11767 int offset = regs8051[i].offset;
11768 regsInUse[offset] = offset + '0'; /* show rMask */
11772 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11774 /* if the result is marked as
11775 spilt and rematerializable or code for
11776 this has already been generated then
11778 if (resultRemat (ic) || ic->generated)
11781 /* depending on the operation */
11801 /* IPOP happens only when trying to restore a
11802 spilt live range, if there is an ifx statement
11803 following this pop then the if statement might
11804 be using some of the registers being popped which
11805 would destory the contents of the register so
11806 we need to check for this condition and handle it */
11808 ic->next->op == IFX &&
11809 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11810 genIfx (ic->next, ic);
11828 genEndFunction (ic);
11848 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11865 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11869 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11876 /* note these two are xlated by algebraic equivalence
11877 in decorateType() in SDCCast.c */
11878 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11879 "got '>=' or '<=' shouldn't have come here");
11883 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11895 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11899 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11903 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11939 genRightShift (ic);
11942 case GET_VALUE_AT_ADDRESS:
11944 hasInc (IC_LEFT (ic), ic,
11945 getSize (operandType (IC_RESULT (ic)))),
11946 ifxForOp (IC_RESULT (ic), ic) );
11950 if (POINTER_SET (ic))
11952 hasInc (IC_RESULT (ic), ic,
11953 getSize (operandType (IC_RIGHT (ic)))));
11979 addSet (&_G.sendSet, ic);
11982 case DUMMY_READ_VOLATILE:
11991 genEndCritical (ic);
12003 _G.current_iCode = NULL;
12005 /* now we are ready to call the
12006 peep hole optimizer */
12007 if (!options.nopeep)
12008 peepHole (&lineHead);
12010 /* now do the actual printing */
12011 printLine (lineHead, codeOutFile);