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 /*-----------------------------------------------------------------*/
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);
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 =
972 aop->size = getSize (sym->type);
979 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
980 aop->size = getSize (sym->type);
981 for (i = 0; i < 2; i++)
982 aop->aopu.aop_str[i] = accUse[i];
990 aop = op->aop = sym->aop = newAsmop (AOP_STR);
991 aop->size = getSize (sym->type);
992 for (i = 0; i < fReturnSizeMCS51; i++)
993 aop->aopu.aop_str[i] = fReturn[i];
997 if (sym->usl.spillLoc)
999 asmop *oldAsmOp = NULL;
1001 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1003 /* force a new aop if sizes differ */
1004 oldAsmOp = sym->usl.spillLoc->aop;
1005 sym->usl.spillLoc->aop = NULL;
1007 sym->aop = op->aop = aop =
1008 aopForSym (ic, sym->usl.spillLoc, result);
1009 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1011 /* Don't reuse the new aop, go with the last one */
1012 sym->usl.spillLoc->aop = oldAsmOp;
1014 aop->size = getSize (sym->type);
1018 /* else must be a dummy iTemp */
1019 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020 aop->size = getSize (sym->type);
1024 /* if the type is a bit register */
1025 if (sym->regType == REG_BIT)
1027 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028 aop->size = sym->nRegs;//1???
1029 aop->aopu.aop_reg[0] = sym->regs[0];
1030 aop->aopu.aop_dir = sym->regs[0]->name;
1034 /* must be in a register */
1035 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036 aop->size = sym->nRegs;
1037 for (i = 0; i < sym->nRegs; i++)
1038 aop->aopu.aop_reg[i] = sym->regs[i];
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand */
1043 /*----------------------------------------------------------------*/
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1062 /* depending on the asmop type only three cases need work
1063 AOP_R0, AOP_R1 & AOP_STK */
1069 emitcode ("mov", "r0,b");
1072 else if (_G.r0Pushed)
1076 emitcode ("pop", "ar0");
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1086 emitcode ("mov", "r1,b");
1089 else if (_G.r1Pushed)
1093 emitcode ("pop", "ar1");
1097 bitVectUnSetBit (ic->rUsed, R1_IDX);
1103 int stk = aop->aopu.aop_stk + aop->size - 1;
1104 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 getFreePtr (ic, &aop, FALSE);
1111 emitcode ("mov", "a,_bp");
1112 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1117 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122 emitcode ("pop", "acc");
1123 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1129 freeAsmop (op, NULL, ic, TRUE);
1132 emitcode ("pop", "ar1");
1137 emitcode ("pop", "ar0");
1145 /* all other cases just dealloc */
1151 OP_SYMBOL (op)->aop = NULL;
1152 /* if the symbol has a spill */
1154 SPIL_LOC (op)->aop = NULL;
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /* pop r0 or r1 off stack if pushed */
1162 /*------------------------------------------------------------------*/
1164 freeForBranchAsmop (operand * op)
1176 if (!aop->allocated)
1184 emitcode ("mov", "r0,b");
1186 else if (_G.r0Pushed)
1188 emitcode ("pop", "ar0");
1195 emitcode ("mov", "r1,b");
1197 else if (_G.r1Pushed)
1199 emitcode ("pop", "ar1");
1206 int stk = aop->aopu.aop_stk + aop->size - 1;
1208 emitcode ("mov", "b,r0");
1211 emitcode ("mov", "a,_bp");
1212 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213 emitcode ("mov", "r0,a");
1217 emitcode ("mov", "r0,_bp");
1222 emitcode ("pop", "acc");
1223 emitcode ("mov", "@r0,a");
1226 emitcode ("dec", "r0");
1228 emitcode ("mov", "r0,b");
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1236 /* clobber the accumulator */
1237 /*-----------------------------------------------------------------*/
1239 aopGetUsesAcc (operand * oper, int offset)
1241 asmop * aop = AOP (oper);
1243 if (offset > (aop->size - 1))
1261 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1272 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1278 /* Error case --- will have been caught already */
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop */
1286 /*-------------------------------------------------------------------*/
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1290 asmop * aop = AOP (oper);
1292 /* offset is greater than
1294 if (offset > (aop->size - 1) &&
1295 aop->type != AOP_LIT)
1298 /* depending on type */
1306 /* if we need to increment it */
1307 while (offset > aop->coff)
1309 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1313 while (offset < aop->coff)
1315 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1322 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323 return (dname ? "acc" : "a");
1325 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326 return Safe_strdup(buffer);
1329 if (aop->code && aop->coff==0 && offset>=1) {
1330 emitcode ("mov", "a,#0x%02x", offset);
1331 emitcode ("movc", "a,@a+dptr");
1332 return (dname ? "acc" : "a");
1335 while (offset > aop->coff)
1337 emitcode ("inc", "dptr");
1341 while (offset < aop->coff)
1343 emitcode ("lcall", "__decdptr");
1350 emitcode ("clr", "a");
1351 emitcode ("movc", "a,@a+dptr");
1355 emitcode ("movx", "a,@dptr");
1357 return (dname ? "acc" : "a");
1360 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s",aop->aopu.aop_immd.aop_immd2);
1367 SNPRINTF(buffer, sizeof(buffer),
1368 "#%s", aop->aopu.aop_immd.aop_immd1);
1372 SNPRINTF (buffer, sizeof(buffer),
1374 aop->aopu.aop_immd.aop_immd1,
1379 SNPRINTF (buffer, sizeof(buffer),
1381 aop->aopu.aop_immd.aop_immd1);
1383 return Safe_strdup(buffer);
1386 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1388 SNPRINTF (buffer, sizeof(buffer),
1390 aop->aopu.aop_dir, offset * 8);
1394 SNPRINTF (buffer, sizeof(buffer),
1401 SNPRINTF (buffer, sizeof(buffer),
1406 return Safe_strdup(buffer);
1410 return aop->aopu.aop_reg[offset]->dname;
1412 return aop->aopu.aop_reg[offset]->name;
1415 emitcode ("clr", "a");
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("rlc", "a");
1418 return (dname ? "acc" : "a");
1421 if (!offset && dname)
1423 return aop->aopu.aop_str[offset];
1426 return aopLiteral (aop->aopu.aop_lit, offset);
1430 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1434 return aop->aopu.aop_str[offset];
1438 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439 "aopget got unsupported aop->type");
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1445 /* clobber the accumulator */
1446 /*-----------------------------------------------------------------*/
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1450 asmop * aop = AOP (oper);
1452 if (offset > (aop->size - 1))
1462 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1468 return ((aop->paged) || (*s == '@'));
1472 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1480 /* Error case --- will have been caught already */
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1490 aopPut (operand * result, const char *s, int offset)
1492 bool bvolatile = isOperandVolatile (result, FALSE);
1493 bool accuse = FALSE;
1494 asmop * aop = AOP (result);
1496 if (aop->size && offset > (aop->size - 1))
1498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499 "aopPut got offset > aop->size");
1503 /* will assign value to value */
1504 /* depending on where it is ofcourse */
1508 MOVA (s); /* read s in case it was volatile */
1513 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1515 SNPRINTF (buffer, sizeof(buffer),
1517 aop->aopu.aop_dir, offset * 8);
1521 SNPRINTF (buffer, sizeof(buffer),
1523 aop->aopu.aop_dir, offset);
1527 SNPRINTF (buffer, sizeof(buffer),
1532 if (strcmp (buffer, s) || bvolatile)
1534 emitcode ("mov", "%s,%s", buffer, s);
1536 if (!strcmp (buffer, "acc"))
1543 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1547 strcmp (s, "r0") == 0 ||
1548 strcmp (s, "r1") == 0 ||
1549 strcmp (s, "r2") == 0 ||
1550 strcmp (s, "r3") == 0 ||
1551 strcmp (s, "r4") == 0 ||
1552 strcmp (s, "r5") == 0 ||
1553 strcmp (s, "r6") == 0 ||
1554 strcmp (s, "r7") == 0)
1556 emitcode ("mov", "%s,%s",
1557 aop->aopu.aop_reg[offset]->dname, s);
1561 emitcode ("mov", "%s,%s",
1562 aop->aopu.aop_reg[offset]->name, s);
1570 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571 "aopPut writing to code space");
1575 while (offset > aop->coff)
1578 emitcode ("inc", "dptr");
1581 while (offset < aop->coff)
1584 emitcode ("lcall", "__decdptr");
1589 /* if not in accumulator */
1592 emitcode ("movx", "@dptr,a");
1597 while (offset > aop->coff)
1600 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1602 while (offset < aop->coff)
1605 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1612 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1617 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1619 else if (strcmp (s, "r0") == 0 ||
1620 strcmp (s, "r1") == 0 ||
1621 strcmp (s, "r2") == 0 ||
1622 strcmp (s, "r3") == 0 ||
1623 strcmp (s, "r4") == 0 ||
1624 strcmp (s, "r5") == 0 ||
1625 strcmp (s, "r6") == 0 ||
1626 strcmp (s, "r7") == 0)
1629 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630 emitcode ("mov", "@%s,%s",
1631 aop->aopu.aop_ptr->name, buffer);
1635 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1640 if (strcmp (s, "a") == 0)
1641 emitcode ("push", "acc");
1645 emitcode ("push", "acc");
1647 emitcode ("push", s);
1653 /* if not bit variable */
1654 if (!aop->aopu.aop_dir)
1656 /* inefficient: move carry into A and use jz/jnz */
1657 emitcode ("clr", "a");
1658 emitcode ("rlc", "a");
1664 emitcode ("clr", "%s", aop->aopu.aop_dir);
1666 emitcode ("setb", "%s", aop->aopu.aop_dir);
1667 else if (!strcmp (s, "c"))
1668 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669 else if (strcmp (s, aop->aopu.aop_dir))
1672 /* set C, if a >= 1 */
1673 emitcode ("add", "a,#0xff");
1674 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1681 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1688 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1691 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697 "aopPut got unsupported aop->type");
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand */
1708 /*-----------------------------------------------------------------*/
1710 pointToEnd (asmop * aop)
1716 aop->coff = count = (aop->size - 1);
1722 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1726 emitcode ("inc", "dptr");
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should */
1735 /*-----------------------------------------------------------------*/
1737 reAdjustPreg (asmop * aop)
1739 if ((aop->coff==0) || (aop->size <= 1))
1747 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1752 emitcode ("lcall", "__decdptr");
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is */
1761 /* a generic pointer type. */
1762 /*-----------------------------------------------------------------*/
1764 opIsGptr (operand * op)
1766 sym_link *type = operandType (op);
1768 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size */
1777 /*-----------------------------------------------------------------*/
1779 getDataSize (operand * op)
1782 size = AOP_SIZE (op);
1783 if (size == GPTRSIZE)
1785 sym_link *type = operandType (op);
1786 if (IS_GENPTR (type))
1788 /* generic pointer; arithmetic operations
1789 * should ignore the high byte (pointer type).
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc */
1799 /*-----------------------------------------------------------------*/
1801 outAcc (operand * result)
1804 size = getDataSize (result);
1807 aopPut (result, "a", 0);
1810 /* unsigned or positive */
1813 aopPut (result, zero, offset++);
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C */
1820 /*-----------------------------------------------------------------*/
1822 outBitC (operand * result)
1824 /* if the result is bit */
1825 if (AOP_TYPE (result) == AOP_CRY)
1827 aopPut (result, "c", 0);
1831 emitcode ("clr", "a");
1832 emitcode ("rlc", "a");
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop) */
1839 /*-----------------------------------------------------------------*/
1841 toBoolean (operand * oper)
1843 int size = AOP_SIZE (oper) - 1;
1845 bool AccUsed = FALSE;
1848 while (!AccUsed && size--)
1850 AccUsed |= aopGetUsesAcc(oper, offset++);
1853 size = AOP_SIZE (oper) - 1;
1855 MOVA (aopGet (oper, 0, FALSE, FALSE));
1856 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1859 emitcode("mov", "b,a");
1862 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863 emitcode ("orl", "b,a");
1865 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866 emitcode ("orl", "a,b");
1873 emitcode ("orl", "a,%s",
1874 aopGet (oper, offset++, FALSE, FALSE));
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop */
1882 /*-------------------------------------------------------------------*/
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1888 if (aopGetUsesAcc (oper, offset))
1890 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset, bit16, dname));
1892 emitcode("xch", "a,b");
1893 aopPut (oper, "a", offset);
1894 emitcode("xch", "a,b");
1899 l = aopGet (oper, offset, bit16, dname);
1900 emitcode("xch", "a,%s", l);
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation */
1908 /*-----------------------------------------------------------------*/
1914 D (emitcode (";", "genNot"));
1916 /* assign asmOps to operand & result */
1917 aopOp (IC_LEFT (ic), ic, FALSE);
1918 aopOp (IC_RESULT (ic), ic, TRUE);
1920 /* if in bit space then a special case */
1921 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1923 /* if left==result then cpl bit */
1924 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1926 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1930 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931 emitcode ("cpl", "c");
1932 outBitC (IC_RESULT (ic));
1937 toBoolean (IC_LEFT (ic));
1939 /* set C, if a == 0 */
1940 tlbl = newiTempLabel (NULL);
1941 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1943 outBitC (IC_RESULT (ic));
1946 /* release the aops */
1947 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement */
1954 /*-----------------------------------------------------------------*/
1961 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1963 D(emitcode (";", "genCpl"));
1965 /* assign asmOps to operand & result */
1966 aopOp (IC_LEFT (ic), ic, FALSE);
1967 aopOp (IC_RESULT (ic), ic, TRUE);
1969 /* special case if in bit space */
1970 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1974 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1977 /* promotion rules are responsible for this strange result:
1978 bit -> int -> ~int -> bit
1979 uchar -> int -> ~int -> bit
1981 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1985 tlbl=newiTempLabel(NULL);
1986 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989 IS_AOP_PREG (IC_LEFT (ic)))
1991 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1996 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1999 outBitC (IC_RESULT(ic));
2003 size = AOP_SIZE (IC_RESULT (ic));
2006 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2008 emitcode ("cpl", "a");
2009 aopPut (IC_RESULT (ic), "a", offset++);
2014 /* release the aops */
2015 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2019 /*-----------------------------------------------------------------*/
2020 /* genUminusFloat - unary minus for floating points */
2021 /*-----------------------------------------------------------------*/
2023 genUminusFloat (operand * op, operand * result)
2025 int size, offset = 0;
2028 D (emitcode (";", "genUminusFloat"));
2030 /* for this we just copy and then flip the bit */
2032 size = AOP_SIZE (op) - 1;
2037 aopGet (op, offset, FALSE, FALSE),
2042 l = aopGet (op, offset, FALSE, FALSE);
2045 emitcode ("cpl", "acc.7");
2046 aopPut (result, "a", offset);
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation */
2051 /*-----------------------------------------------------------------*/
2053 genUminus (iCode * ic)
2058 D (emitcode (";", "genUminus"));
2061 aopOp (IC_LEFT (ic), ic, FALSE);
2062 aopOp (IC_RESULT (ic), ic, TRUE);
2064 /* if both in bit space then special
2066 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2070 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071 emitcode ("cpl", "c");
2072 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2076 optype = operandType (IC_LEFT (ic));
2078 /* if float then do float stuff */
2079 if (IS_FLOAT (optype))
2081 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2085 /* otherwise subtract from zero */
2086 size = AOP_SIZE (IC_LEFT (ic));
2090 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091 if (!strcmp (l, "a"))
2095 emitcode ("cpl", "a");
2096 emitcode ("addc", "a,#0");
2102 emitcode ("clr", "a");
2103 emitcode ("subb", "a,%s", l);
2105 aopPut (IC_RESULT (ic), "a", offset++);
2108 /* if any remaining bytes in the result */
2109 /* we just need to propagate the sign */
2110 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2112 emitcode ("rlc", "a");
2113 emitcode ("subb", "a,acc");
2115 aopPut (IC_RESULT (ic), "a", offset++);
2119 /* release the aops */
2120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers */
2126 /*-----------------------------------------------------------------*/
2128 saveRegisters (iCode * lic)
2135 for (ic = lic; ic; ic = ic->next)
2136 if (ic->op == CALL || ic->op == PCALL)
2141 fprintf (stderr, "found parameter push with no function call\n");
2145 /* if the registers have been saved already or don't need to be then
2149 if (IS_SYMOP(IC_LEFT(ic)) &&
2150 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2154 /* save the registers in use at this time but skip the
2155 ones for the result */
2156 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157 mcs51_rUmaskForOp (IC_RESULT(ic)));
2160 if (options.useXstack)
2162 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163 int nBits = bitVectnBitsOn (rsavebits);
2164 int count = bitVectnBitsOn (rsave);
2168 count = count - nBits + 1;
2169 /* remove all but the first bits as they are pushed all at once */
2170 rsave = bitVectCplAnd (rsave, rsavebits);
2171 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2176 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177 if (reg->type == REG_BIT)
2179 emitcode ("mov", "a,%s", reg->base);
2183 emitcode ("mov", "a,%s", reg->name);
2185 emitcode ("mov", "r0,%s", spname);
2186 emitcode ("inc", "%s", spname);// allocate before use
2187 emitcode ("movx", "@r0,a");
2188 if (bitVectBitValue (rsave, R0_IDX))
2189 emitcode ("mov", "r0,a");
2191 else if (count != 0)
2193 if (bitVectBitValue (rsave, R0_IDX))
2195 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2197 emitcode ("mov", "r0,%s", spname);
2199 emitcode ("add", "a,#%d", count);
2200 emitcode ("mov", "%s,a", spname);
2201 for (i = 0; i < mcs51_nRegs; i++)
2203 if (bitVectBitValue (rsave, i))
2205 regs * reg = REG_WITH_INDEX (i);
2208 emitcode ("pop", "acc");
2209 emitcode ("push", "acc");
2211 else if (reg->type == REG_BIT)
2213 emitcode ("mov", "a,%s", reg->base);
2217 emitcode ("mov", "a,%s", reg->name);
2219 emitcode ("movx", "@r0,a");
2222 emitcode ("inc", "r0");
2226 if (bitVectBitValue (rsave, R0_IDX))
2228 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2234 bool bits_pushed = FALSE;
2235 for (i = 0; i < mcs51_nRegs; i++)
2237 if (bitVectBitValue (rsave, i))
2239 bits_pushed = pushReg (i, bits_pushed);
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers */
2247 /*-----------------------------------------------------------------*/
2249 unsaveRegisters (iCode * ic)
2254 /* restore the registers in use at this time but skip the
2255 ones for the result */
2256 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257 mcs51_rUmaskForOp (IC_RESULT(ic)));
2259 if (options.useXstack)
2261 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262 int nBits = bitVectnBitsOn (rsavebits);
2263 int count = bitVectnBitsOn (rsave);
2267 count = count - nBits + 1;
2268 /* remove all but the first bits as they are popped all at once */
2269 rsave = bitVectCplAnd (rsave, rsavebits);
2270 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2275 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276 emitcode ("mov", "r0,%s", spname);
2277 emitcode ("dec", "r0");
2278 emitcode ("movx", "a,@r0");
2279 if (reg->type == REG_BIT)
2281 emitcode ("mov", "%s,a", reg->base);
2285 emitcode ("mov", "%s,a", reg->name);
2287 emitcode ("dec", "%s", spname);
2289 else if (count != 0)
2291 emitcode ("mov", "r0,%s", spname);
2292 for (i = mcs51_nRegs; i >= 0; i--)
2294 if (bitVectBitValue (rsave, i))
2296 regs * reg = REG_WITH_INDEX (i);
2297 emitcode ("dec", "r0");
2298 emitcode ("movx", "a,@r0");
2301 emitcode ("push", "acc");
2303 else if (reg->type == REG_BIT)
2305 emitcode ("mov", "%s,a", reg->base);
2309 emitcode ("mov", "%s,a", reg->name);
2313 emitcode ("mov", "%s,r0", spname);
2314 if (bitVectBitValue (rsave, R0_IDX))
2316 emitcode ("pop", "ar0");
2322 bool bits_popped = FALSE;
2323 for (i = mcs51_nRegs; i >= 0; i--)
2325 if (bitVectBitValue (rsave, i))
2327 bits_popped = popReg (i, bits_popped);
2334 /*-----------------------------------------------------------------*/
2336 /*-----------------------------------------------------------------*/
2338 pushSide (operand * oper, int size)
2343 char *l = aopGet (oper, offset++, FALSE, TRUE);
2344 if (AOP_TYPE (oper) != AOP_REG &&
2345 AOP_TYPE (oper) != AOP_DIR &&
2349 emitcode ("push", "acc");
2353 emitcode ("push", "%s", l);
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards */
2360 /*-----------------------------------------------------------------*/
2362 assignResultValue (operand * oper, operand * func)
2365 int size = AOP_SIZE (oper);
2366 bool accuse = FALSE;
2367 bool pushedA = FALSE;
2369 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2375 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2377 emitcode ("push", "acc");
2382 if ((offset == 3) && pushedA)
2383 emitcode ("pop", "acc");
2384 accuse |= aopPut (oper, fReturn[offset], offset);
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack */
2393 /*-----------------------------------------------------------------*/
2395 genXpush (iCode * ic)
2397 asmop *aop = newAsmop (0);
2399 int size, offset = 0;
2401 D (emitcode (";", "genXpush"));
2403 aopOp (IC_LEFT (ic), ic, FALSE);
2404 r = getFreePtr (ic, &aop, FALSE);
2406 size = AOP_SIZE (IC_LEFT (ic));
2410 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411 emitcode ("mov", "%s,%s", r->name, spname);
2412 emitcode ("inc", "%s", spname); // allocate space first
2413 emitcode ("movx", "@%s,a", r->name);
2417 // allocate space first
2418 emitcode ("mov", "%s,%s", r->name, spname);
2420 emitcode ("add", "a,#%d", size);
2421 emitcode ("mov", "%s,a", spname);
2425 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426 emitcode ("movx", "@%s,a", r->name);
2427 emitcode ("inc", "%s", r->name);
2431 freeAsmop (NULL, aop, ic, TRUE);
2432 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2439 genIpush (iCode * ic)
2441 int size, offset = 0;
2445 D (emitcode (";", "genIpush"));
2447 /* if this is not a parm push : ie. it is spill push
2448 and spill push is always done on the local stack */
2452 /* and the item is spilt then do nothing */
2453 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2456 aopOp (IC_LEFT (ic), ic, FALSE);
2457 size = AOP_SIZE (IC_LEFT (ic));
2458 /* push it on the stack */
2461 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2467 emitcode ("push", "%s", l);
2472 /* this is a parameter push: in this case we call
2473 the routine to find the call and save those
2474 registers that need to be saved */
2477 /* if use external stack then call the external
2478 stack pushing routine */
2479 if (options.useXstack)
2485 /* then do the push */
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2488 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489 size = AOP_SIZE (IC_LEFT (ic));
2493 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2497 if (strcmp (l, prev) || *l == '@')
2499 emitcode ("push", "acc");
2503 emitcode ("push", "%s", l);
2508 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling */
2513 /*-----------------------------------------------------------------*/
2515 genIpop (iCode * ic)
2519 D (emitcode (";", "genIpop"));
2521 /* if the temp was not pushed then */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2527 offset = (size - 1);
2530 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2534 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack */
2539 /*-----------------------------------------------------------------*/
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2544 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2548 if (options.useXstack)
2552 /* Assume r0 is available for use. */
2553 r = REG_WITH_INDEX (R0_IDX);;
2558 r = getFreePtr (ic, &aop, FALSE);
2560 // allocate space first
2561 emitcode ("mov", "%s,%s", r->name, spname);
2563 emitcode ("add", "a,#%d", count);
2564 emitcode ("mov", "%s,a", spname);
2567 for (i = 0; i < 8; i++)
2569 if (options.useXstack)
2571 emitcode ("mov", "a,(%s+%d)",
2572 regs8051[i].base, 8 * bank + regs8051[i].offset);
2573 emitcode ("movx", "@%s,a", r->name);
2575 emitcode ("inc", "%s", r->name);
2578 emitcode ("push", "(%s+%d)",
2579 regs8051[i].base, 8 * bank + regs8051[i].offset);
2582 if (mcs51_nRegs > 8)
2584 if (options.useXstack)
2586 emitcode ("mov", "a,bits");
2587 emitcode ("movx", "@%s,a", r->name);
2589 emitcode ("inc", "%s", r->name);
2593 emitcode ("push", "bits");
2600 if (options.useXstack)
2602 emitcode ("mov", "a,psw");
2603 emitcode ("movx", "@%s,a", r->name);
2607 emitcode ("push", "psw");
2610 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2615 freeAsmop (NULL, aop, ic, TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack */
2626 /*-----------------------------------------------------------------*/
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2634 if (options.useXstack)
2638 /* Assume r0 is available for use. */
2639 r = REG_WITH_INDEX (R0_IDX);;
2644 r = getFreePtr (ic, &aop, FALSE);
2646 emitcode ("mov", "%s,%s", r->name, spname);
2651 if (options.useXstack)
2653 emitcode ("dec", "%s", r->name);
2654 emitcode ("movx", "a,@%s", r->name);
2655 emitcode ("mov", "psw,a");
2659 emitcode ("pop", "psw");
2663 if (mcs51_nRegs > 8)
2665 if (options.useXstack)
2667 emitcode ("dec", "%s", r->name);
2668 emitcode ("movx", "a,@%s", r->name);
2669 emitcode ("mov", "bits,a");
2673 emitcode ("pop", "bits");
2677 for (i = 7; i >= 0; i--)
2679 if (options.useXstack)
2681 emitcode ("dec", "%s", r->name);
2682 emitcode ("movx", "a,@%s", r->name);
2683 emitcode ("mov", "(%s+%d),a",
2684 regs8051[i].base, 8 * bank + regs8051[i].offset);
2688 emitcode ("pop", "(%s+%d)",
2689 regs8051[i].base, 8 * bank + regs8051[i].offset);
2693 if (options.useXstack)
2695 emitcode ("mov", "%s,%s", spname, r->name);
2700 freeAsmop (NULL, aop, ic, TRUE);
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2712 /* first we do all bit parameters */
2713 for (sic = setFirstItem (sendSet); sic;
2714 sic = setNextItem (sendSet))
2716 if (sic->argreg > 12)
2718 int bit = sic->argreg-13;
2720 aopOp (IC_LEFT (sic), sic, FALSE);
2722 /* if left is a literal then
2723 we know what the value is */
2724 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2726 if (((int) operandLitValue (IC_LEFT (sic))))
2727 emitcode ("setb", "b[%d]", bit);
2729 emitcode ("clr", "b[%d]", bit);
2731 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2733 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734 if (strcmp (l, "c"))
2735 emitcode ("mov", "c,%s", l);
2736 emitcode ("mov", "b[%d],c", bit);
2741 toBoolean (IC_LEFT (sic));
2742 /* set C, if a >= 1 */
2743 emitcode ("add", "a,#0xff");
2744 emitcode ("mov", "b[%d],c", bit);
2749 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2755 saveRegisters (setFirstItem (sendSet));
2756 emitcode ("mov", "bits,b");
2759 /* then we do all other parameters */
2760 for (sic = setFirstItem (sendSet); sic;
2761 sic = setNextItem (sendSet))
2763 if (sic->argreg <= 12)
2765 int size, offset = 0;
2766 aopOp (IC_LEFT (sic), sic, FALSE);
2767 size = AOP_SIZE (IC_LEFT (sic));
2769 if (sic->argreg == 1)
2773 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774 if (strcmp (l, fReturn[offset]))
2776 emitcode ("mov", "%s,%s", fReturn[offset], l);
2785 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2790 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank */
2797 /*-----------------------------------------------------------------*/
2799 selectRegBank (short bank, bool keepFlags)
2801 /* if f.e. result is in carry */
2804 emitcode ("anl", "psw,#0xE7");
2806 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2810 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement */
2816 /*-----------------------------------------------------------------*/
2818 genCall (iCode * ic)
2822 // bool restoreBank = FALSE;
2823 bool swapBanks = FALSE;
2824 bool accuse = FALSE;
2825 bool accPushed = FALSE;
2826 bool resultInF0 = FALSE;
2827 bool assignResultGenerated = FALSE;
2829 D (emitcode (";", "genCall"));
2831 dtype = operandType (IC_LEFT (ic));
2832 etype = getSpec(dtype);
2833 /* if send set is not empty then assign */
2836 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837 genSend(reverseSet(_G.sendSet));
2839 genSend(_G.sendSet);
2844 /* if we are calling a not _naked function that is not using
2845 the same register bank then we need to save the
2846 destination registers on the stack */
2847 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849 !IFFUNC_ISISR (dtype))
2854 /* if caller saves & we have not saved then */
2860 emitcode ("mov", "psw,#0x%02x",
2861 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2865 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2867 if (IFFUNC_CALLEESAVES(dtype))
2869 werror (E_BANKED_WITH_CALLEESAVES);
2873 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874 OP_SYMBOL (IC_LEFT (ic))->rname :
2875 OP_SYMBOL (IC_LEFT (ic))->name);
2877 emitcode ("mov", "r0,#%s", l);
2878 emitcode ("mov", "r1,#(%s >> 8)", l);
2879 emitcode ("mov", "r2,#(%s >> 16)", l);
2880 emitcode ("lcall", "__sdcc_banked_call");
2885 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886 OP_SYMBOL (IC_LEFT (ic))->rname :
2887 OP_SYMBOL (IC_LEFT (ic))->name));
2892 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2895 /* if we need assign a result value */
2896 if ((IS_ITEMP (IC_RESULT (ic)) &&
2897 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901 IS_TRUE_SYMOP (IC_RESULT (ic)))
2905 aopOp (IC_RESULT (ic), ic, FALSE);
2908 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909 assignResultGenerated = TRUE;
2911 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2914 /* adjust the stack for parameters if required */
2918 if (ic->parmBytes > 3)
2922 emitcode ("push", "acc");
2925 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927 !assignResultGenerated)
2929 emitcode ("mov", "F0,c");
2933 emitcode ("mov", "a,%s", spname);
2934 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935 emitcode ("mov", "%s,a", spname);
2937 /* unsaveRegisters from xstack needs acc, but */
2938 /* unsaveRegisters from stack needs this popped */
2939 if (accPushed && !options.useXstack)
2941 emitcode ("pop", "acc");
2946 for (i = 0; i < ic->parmBytes; i++)
2947 emitcode ("dec", "%s", spname);
2950 /* if we had saved some registers then unsave them */
2951 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2953 if (accuse && !accPushed && options.useXstack)
2955 /* xstack needs acc, but doesn't touch normal stack */
2956 emitcode ("push", "acc");
2959 unsaveRegisters (ic);
2962 // /* if register bank was saved then pop them */
2964 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2966 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2969 emitcode ("mov", "c,F0");
2971 aopOp (IC_RESULT (ic), ic, FALSE);
2972 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2977 emitcode ("pop", "acc");
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement */
2982 /*-----------------------------------------------------------------*/
2984 genPcall (iCode * ic)
2988 symbol *rlbl = newiTempLabel (NULL);
2989 // bool restoreBank=FALSE;
2990 bool swapBanks = FALSE;
2991 bool resultInF0 = FALSE;
2993 D (emitcode (";", "genPcall"));
2995 dtype = operandType (IC_LEFT (ic))->next;
2996 etype = getSpec(dtype);
2997 /* if caller saves & we have not saved then */
3001 /* if we are calling a not _naked function that is not using
3002 the same register bank then we need to save the
3003 destination registers on the stack */
3004 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006 !IFFUNC_ISISR (dtype))
3008 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 // restoreBank=TRUE;
3011 // need caution message to user here
3014 if (IS_LITERAL(etype))
3016 /* if send set is not empty then assign */
3019 genSend(reverseSet(_G.sendSet));
3025 emitcode ("mov", "psw,#0x%02x",
3026 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3029 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3031 if (IFFUNC_CALLEESAVES(dtype))
3033 werror (E_BANKED_WITH_CALLEESAVES);
3037 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3039 emitcode ("mov", "r0,#%s", l);
3040 emitcode ("mov", "r1,#(%s >> 8)", l);
3041 emitcode ("mov", "r2,#(%s >> 16)", l);
3042 emitcode ("lcall", "__sdcc_banked_call");
3047 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3052 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3054 if (IFFUNC_CALLEESAVES(dtype))
3056 werror (E_BANKED_WITH_CALLEESAVES);
3060 aopOp (IC_LEFT (ic), ic, FALSE);
3064 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3070 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3078 /* if send set is not empty then assign */
3081 genSend(reverseSet(_G.sendSet));
3087 emitcode ("mov", "psw,#0x%02x",
3088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3092 emitcode ("lcall", "__sdcc_banked_call");
3097 /* push the return address on to the stack */
3098 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099 emitcode ("push", "acc");
3100 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101 emitcode ("push", "acc");
3103 /* now push the calling address */
3104 aopOp (IC_LEFT (ic), ic, FALSE);
3106 pushSide (IC_LEFT (ic), FPTRSIZE);
3108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3110 /* if send set is not empty the assign */
3113 genSend(reverseSet(_G.sendSet));
3119 emitcode ("mov", "psw,#0x%02x",
3120 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3124 emitcode ("ret", "");
3130 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3133 /* if we need assign a result value */
3134 if ((IS_ITEMP (IC_RESULT (ic)) &&
3135 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138 IS_TRUE_SYMOP (IC_RESULT (ic)))
3142 aopOp (IC_RESULT (ic), ic, FALSE);
3145 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3147 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3150 /* adjust the stack for parameters if required */
3154 if (ic->parmBytes > 3)
3156 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3159 emitcode ("mov", "F0,c");
3163 emitcode ("mov", "a,%s", spname);
3164 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165 emitcode ("mov", "%s,a", spname);
3168 for (i = 0; i < ic->parmBytes; i++)
3169 emitcode ("dec", "%s", spname);
3172 // /* if register bank was saved then unsave them */
3174 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3176 /* if we had saved some registers then unsave them */
3177 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178 unsaveRegisters (ic);
3180 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3183 emitcode ("mov", "c,F0");
3185 aopOp (IC_RESULT (ic), ic, FALSE);
3186 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result is rematerializable */
3193 /*-----------------------------------------------------------------*/
3195 resultRemat (iCode * ic)
3197 if (SKIP_IC (ic) || ic->op == IFX)
3200 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3202 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203 if (sym->remat && !POINTER_SET (ic))
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3213 #define STRCASECMP strcasecmp
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list */
3218 /*-----------------------------------------------------------------*/
3220 regsCmp(void *p1, void *p2)
3222 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3226 inExcludeList (char *s)
3228 const char *p = setFirstItem(options.excludeRegsSet);
3230 if (p == NULL || STRCASECMP(p, "none") == 0)
3234 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry */
3239 /*-----------------------------------------------------------------*/
3241 genFunction (iCode * ic)
3243 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3245 bool switchedPSW = FALSE;
3246 int calleesaves_saved_register = -1;
3247 int stackAdjust = sym->stack;
3248 int accIsFree = sym->recvSize < 4;
3249 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3253 /* create the function header */
3254 emitcode (";", "-----------------------------------------");
3255 emitcode (";", " function %s", sym->name);
3256 emitcode (";", "-----------------------------------------");
3258 emitcode ("", "%s:", sym->rname);
3259 ftype = operandType (IC_LEFT (ic));
3260 _G.currentFunc = sym;
3262 if (IFFUNC_ISNAKED(ftype))
3264 emitcode(";", "naked function: no prologue.");
3268 /* here we need to generate the equates for the
3269 register bank if required */
3270 if (FUNC_REGBANK (ftype) != rbank)
3274 rbank = FUNC_REGBANK (ftype);
3275 for (i = 0; i < mcs51_nRegs; i++)
3277 if (regs8051[i].type != REG_BIT)
3279 if (strcmp (regs8051[i].base, "0") == 0)
3280 emitcode ("", "%s = 0x%02x",
3282 8 * rbank + regs8051[i].offset);
3284 emitcode ("", "%s = %s + 0x%02x",
3287 8 * rbank + regs8051[i].offset);
3292 /* if this is an interrupt service routine then
3293 save acc, b, dpl, dph */
3294 if (IFFUNC_ISISR (sym->type))
3296 if (!inExcludeList ("acc"))
3297 emitcode ("push", "acc");
3298 if (!inExcludeList ("b"))
3299 emitcode ("push", "b");
3300 if (!inExcludeList ("dpl"))
3301 emitcode ("push", "dpl");
3302 if (!inExcludeList ("dph"))
3303 emitcode ("push", "dph");
3304 /* if this isr has no bank i.e. is going to
3305 run with bank 0 , then we need to save more
3307 if (!FUNC_REGBANK (sym->type))
3311 /* if this function does not call any other
3312 function then we can be economical and
3313 save only those registers that are used */
3314 if (!IFFUNC_HASFCALL(sym->type))
3316 /* if any registers used */
3319 bool bits_pushed = FALSE;
3320 /* save the registers used */
3321 for (i = 0; i < sym->regsUsed->size; i++)
3323 if (bitVectBitValue (sym->regsUsed, i))
3324 bits_pushed = pushReg (i, bits_pushed);
3330 /* this function has a function call. We cannot
3331 determine register usage so we will have to push the
3333 saveRBank (0, ic, FALSE);
3334 if (options.parms_in_bank1) {
3335 for (i=0; i < 8 ; i++ ) {
3336 emitcode ("push","%s",rb1regs[i]);
3343 /* This ISR uses a non-zero bank.
3345 * We assume that the bank is available for our
3348 * However, if this ISR calls a function which uses some
3349 * other bank, we must save that bank entirely.
3351 unsigned long banksToSave = 0;
3353 if (IFFUNC_HASFCALL(sym->type))
3356 #define MAX_REGISTER_BANKS 4
3361 for (i = ic; i; i = i->next)
3363 if (i->op == ENDFUNCTION)
3365 /* we got to the end OK. */
3373 dtype = operandType (IC_LEFT(i));
3375 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3377 /* Mark this bank for saving. */
3378 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3380 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3384 banksToSave |= (1 << FUNC_REGBANK(dtype));
3387 /* And note that we don't need to do it in
3395 /* This is a mess; we have no idea what
3396 * register bank the called function might
3399 * The only thing I can think of to do is
3400 * throw a warning and hope.
3402 werror(W_FUNCPTR_IN_USING_ISR);
3406 if (banksToSave && options.useXstack)
3408 /* Since we aren't passing it an ic,
3409 * saveRBank will assume r0 is available to abuse.
3411 * So switch to our (trashable) bank now, so
3412 * the caller's R0 isn't trashed.
3414 emitcode ("push", "psw");
3415 emitcode ("mov", "psw,#0x%02x",
3416 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3420 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3422 if (banksToSave & (1 << ix))
3424 saveRBank(ix, NULL, FALSE);
3428 // TODO: this needs a closer look
3429 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3432 /* Set the register bank to the desired value if nothing else */
3433 /* has done so yet. */
3436 emitcode ("push", "psw");
3437 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3442 /* This is a non-ISR function. The caller has already switched register */
3443 /* banks, if necessary, so just handle the callee-saves option. */
3445 /* if callee-save to be used for this function
3446 then save the registers being used in this function */
3447 if (IFFUNC_CALLEESAVES(sym->type))
3451 /* if any registers used */
3454 bool bits_pushed = FALSE;
3455 /* save the registers used */
3456 for (i = 0; i < sym->regsUsed->size; i++)
3458 if (bitVectBitValue (sym->regsUsed, i))
3460 /* remember one saved register for later usage */
3461 if (calleesaves_saved_register < 0)
3462 calleesaves_saved_register = i;
3463 bits_pushed = pushReg (i, bits_pushed);
3473 if (options.useXstack)
3475 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3477 emitcode ("mov", "r0,%s", spname);
3478 emitcode ("inc", "%s", spname);
3479 emitcode ("xch", "a,_bpx");
3480 emitcode ("movx", "@r0,a");
3481 emitcode ("inc", "r0");
3482 emitcode ("mov", "a,r0");
3483 emitcode ("xch", "a,_bpx");
3487 emitcode ("push", "_bp"); /* save the callers stack */
3488 emitcode ("mov", "_bp,sp");
3493 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3495 /* set up the stack */
3496 emitcode ("push", "_bp"); /* save the callers stack */
3497 emitcode ("mov", "_bp,sp");
3502 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3503 /* before setting up the stack frame completely. */
3504 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3506 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3510 if (rsym && rsym->regType == REG_CND)
3512 if (rsym && (rsym->accuse || rsym->ruonly))
3514 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3515 rsym = rsym->usl.spillLoc;
3518 /* If the RECEIVE operand immediately spills to the first entry on the */
3519 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3520 /* rather than the usual @r0/r1 machinations. */
3521 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3525 _G.current_iCode = ric;
3526 D(emitcode ("; genReceive",""));
3527 for (ofs=0; ofs < sym->recvSize; ofs++)
3529 if (!strcmp (fReturn[ofs], "a"))
3530 emitcode ("push", "acc");
3532 emitcode ("push", fReturn[ofs]);
3534 stackAdjust -= sym->recvSize;
3537 assert (stackAdjust>=0);
3540 _G.current_iCode = ic;
3544 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3545 /* to free up the accumulator. */
3546 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3550 _G.current_iCode = ric;
3551 D(emitcode ("; genReceive",""));
3552 for (ofs=0; ofs < sym->recvSize; ofs++)
3554 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3556 _G.current_iCode = ic;
3562 /* adjust the stack for the function */
3565 int i = stackAdjust;
3567 werror (W_STACK_OVERFLOW, sym->name);
3569 if (i > 3 && accIsFree)
3571 emitcode ("mov", "a,sp");
3572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3573 emitcode ("mov", "sp,a");
3577 /* The accumulator is not free, so we will need another register */
3578 /* to clobber. No need to worry about a possible conflict with */
3579 /* the above early RECEIVE optimizations since they would have */
3580 /* freed the accumulator if they were generated. */
3582 if (IFFUNC_CALLEESAVES(sym->type))
3584 /* if it's a callee-saves function we need a saved register */
3585 if (calleesaves_saved_register >= 0)
3587 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3588 emitcode ("mov", "a,sp");
3589 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3590 emitcode ("mov", "sp,a");
3591 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3594 /* do it the hard way */
3596 emitcode ("inc", "sp");
3600 /* not callee-saves, we can clobber r0 */
3601 emitcode ("mov", "r0,a");
3602 emitcode ("mov", "a,sp");
3603 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604 emitcode ("mov", "sp,a");
3605 emitcode ("mov", "a,r0");
3610 emitcode ("inc", "sp");
3615 char i = ((char) sym->xstack & 0xff);
3617 if (i > 3 && accIsFree)
3619 emitcode ("mov", "a,_spx");
3620 emitcode ("add", "a,#0x%02x", i);
3621 emitcode ("mov", "_spx,a");
3625 emitcode ("push", "acc");
3626 emitcode ("mov", "a,_spx");
3627 emitcode ("add", "a,#0x%02x", i);
3628 emitcode ("mov", "_spx,a");
3629 emitcode ("pop", "acc");
3634 emitcode ("inc", "_spx");
3638 /* if critical function then turn interrupts off */
3639 if (IFFUNC_ISCRITICAL (ftype))
3641 symbol *tlbl = newiTempLabel (NULL);
3642 emitcode ("setb", "c");
3643 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3644 emitcode ("clr", "c");
3646 emitcode ("push", "psw"); /* save old ea via c in psw */
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions */
3652 /*-----------------------------------------------------------------*/
3654 genEndFunction (iCode * ic)
3656 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3657 lineNode *lnp = lineCurr;
3659 bitVect *regsUsedPrologue;
3660 bitVect *regsUnneeded;
3663 _G.currentFunc = NULL;
3664 if (IFFUNC_ISNAKED(sym->type))
3666 emitcode(";", "naked function: no epilogue.");
3667 if (options.debug && currFunc)
3668 debugFile->writeEndFunction (currFunc, ic, 0);
3672 if (IFFUNC_ISCRITICAL (sym->type))
3674 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3676 emitcode ("rlc", "a"); /* save c in a */
3677 emitcode ("pop", "psw"); /* restore ea via c in psw */
3678 emitcode ("mov", "ea,c");
3679 emitcode ("rrc", "a"); /* restore c from a */
3683 emitcode ("pop", "psw"); /* restore ea via c in psw */
3684 emitcode ("mov", "ea,c");
3688 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3690 if (options.useXstack)
3694 emitcode ("mov", "sp,_bp");
3695 emitcode ("pop", "_bp");
3697 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3699 emitcode ("xch", "a,_bpx");
3700 emitcode ("mov", "r0,a");
3701 emitcode ("dec", "r0");
3702 emitcode ("movx", "a,@r0");
3703 emitcode ("xch", "a,_bpx");
3704 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3707 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3710 emitcode ("mov", "sp,_bp");
3711 emitcode ("pop", "_bp");
3715 /* restore the register bank */
3716 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3718 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3719 || !options.useXstack)
3721 /* Special case of ISR using non-zero bank with useXstack
3724 emitcode ("pop", "psw");
3728 if (IFFUNC_ISISR (sym->type))
3731 /* now we need to restore the registers */
3732 /* if this isr has no bank i.e. is going to
3733 run with bank 0 , then we need to save more
3735 if (!FUNC_REGBANK (sym->type))
3738 /* if this function does not call any other
3739 function then we can be economical and
3740 save only those registers that are used */
3741 if (!IFFUNC_HASFCALL(sym->type))
3743 /* if any registers used */
3746 bool bits_popped = FALSE;
3747 /* save the registers used */
3748 for (i = sym->regsUsed->size; i >= 0; i--)
3750 if (bitVectBitValue (sym->regsUsed, i))
3751 bits_popped = popReg (i, bits_popped);
3757 if (options.parms_in_bank1) {
3758 for (i = 7 ; i >= 0 ; i-- ) {
3759 emitcode ("pop","%s",rb1regs[i]);
3762 /* this function has a function call cannot
3763 determines register usage so we will have to pop the
3765 unsaveRBank (0, ic, FALSE);
3770 /* This ISR uses a non-zero bank.
3772 * Restore any register banks saved by genFunction
3775 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3778 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3780 if (savedBanks & (1 << ix))
3782 unsaveRBank(ix, NULL, FALSE);
3786 if (options.useXstack)
3788 /* Restore bank AFTER calling unsaveRBank,
3789 * since it can trash r0.
3791 emitcode ("pop", "psw");
3795 if (!inExcludeList ("dph"))
3796 emitcode ("pop", "dph");
3797 if (!inExcludeList ("dpl"))
3798 emitcode ("pop", "dpl");
3799 if (!inExcludeList ("b"))
3800 emitcode ("pop", "b");
3801 if (!inExcludeList ("acc"))
3802 emitcode ("pop", "acc");
3804 /* if debug then send end of function */
3805 if (options.debug && currFunc)
3807 debugFile->writeEndFunction (currFunc, ic, 1);
3810 emitcode ("reti", "");
3814 if (IFFUNC_CALLEESAVES(sym->type))
3818 /* if any registers used */
3821 /* save the registers used */
3822 for (i = sym->regsUsed->size; i >= 0; i--)
3824 if (bitVectBitValue (sym->regsUsed, i) ||
3825 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3826 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3829 else if (mcs51_ptrRegReq)
3831 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3832 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3837 /* if debug then send end of function */
3838 if (options.debug && currFunc)
3840 debugFile->writeEndFunction (currFunc, ic, 1);
3843 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3845 emitcode ("ljmp", "__sdcc_banked_ret");
3849 emitcode ("ret", "");
3853 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3856 /* If this was an interrupt handler using bank 0 that called another */
3857 /* function, then all registers must be saved; nothing to optimized. */
3858 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3859 && !FUNC_REGBANK(sym->type))
3862 /* There are no push/pops to optimize if not callee-saves or ISR */
3863 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3866 /* If there were stack parameters, we cannot optimize without also */
3867 /* fixing all of the stack offsets; this is too dificult to consider. */
3868 if (FUNC_HASSTACKPARM(sym->type))
3871 /* Compute the registers actually used */
3872 regsUsed = newBitVect (mcs51_nRegs);
3873 regsUsedPrologue = newBitVect (mcs51_nRegs);
3876 if (lnp->ic && lnp->ic->op == FUNCTION)
3877 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3879 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3881 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3882 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3889 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3890 && !bitVectBitValue (regsUsed, CND_IDX))
3892 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3893 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3894 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3895 bitVectUnSetBit (regsUsed, CND_IDX);
3898 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3900 /* If this was an interrupt handler that called another function */
3901 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3902 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3904 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3905 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3906 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3907 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3908 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3911 /* Remove the unneeded push/pops */
3912 regsUnneeded = newBitVect (mcs51_nRegs);
3915 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3917 if (!strncmp(lnp->line, "push", 4))
3919 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3920 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3922 connectLine (lnp->prev, lnp->next);
3923 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3926 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3928 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3929 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3931 connectLine (lnp->prev, lnp->next);
3932 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3939 for (idx = 0; idx < regsUnneeded->size; idx++)
3940 if (bitVectBitValue (regsUnneeded, idx))
3941 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3943 freeBitVect (regsUnneeded);
3944 freeBitVect (regsUsed);
3945 freeBitVect (regsUsedPrologue);
3948 /*-----------------------------------------------------------------*/
3949 /* genRet - generate code for return statement */
3950 /*-----------------------------------------------------------------*/
3954 int size, offset = 0, pushed = 0;
3956 D (emitcode (";", "genRet"));
3958 /* if we have no return value then
3959 just generate the "ret" */
3963 /* we have something to return then
3964 move the return value into place */
3965 aopOp (IC_LEFT (ic), ic, FALSE);
3966 size = AOP_SIZE (IC_LEFT (ic));
3968 if (IS_BIT(_G.currentFunc->etype))
3970 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3977 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3980 l = aopGet (IC_LEFT (ic), offset++,
3982 emitcode ("push", "%s", l);
3987 l = aopGet (IC_LEFT (ic), offset,
3989 if (strcmp (fReturn[offset], l))
3990 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3997 if (strcmp (fReturn[pushed], "a"))
3998 emitcode ("pop", fReturn[pushed]);
4000 emitcode ("pop", "acc");
4002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4005 /* generate a jump to the return label
4006 if the next is not the return statement */
4007 if (!(ic->next && ic->next->op == LABEL &&
4008 IC_LABEL (ic->next) == returnLabel))
4010 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4014 /*-----------------------------------------------------------------*/
4015 /* genLabel - generates a label */
4016 /*-----------------------------------------------------------------*/
4018 genLabel (iCode * ic)
4020 /* special case never generate */
4021 if (IC_LABEL (ic) == entryLabel)
4024 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4027 /*-----------------------------------------------------------------*/
4028 /* genGoto - generates a ljmp */
4029 /*-----------------------------------------------------------------*/
4031 genGoto (iCode * ic)
4033 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4036 /*-----------------------------------------------------------------*/
4037 /* findLabelBackwards: walks back through the iCode chain looking */
4038 /* for the given label. Returns number of iCode instructions */
4039 /* between that label and given ic. */
4040 /* Returns zero if label not found. */
4041 /*-----------------------------------------------------------------*/
4043 findLabelBackwards (iCode * ic, int key)
4052 /* If we have any pushes or pops, we cannot predict the distance.
4053 I don't like this at all, this should be dealt with in the
4055 if (ic->op == IPUSH || ic->op == IPOP) {
4059 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4068 /*-----------------------------------------------------------------*/
4069 /* genPlusIncr :- does addition with increment if possible */
4070 /*-----------------------------------------------------------------*/
4072 genPlusIncr (iCode * ic)
4074 unsigned int icount;
4075 unsigned int size = getDataSize (IC_RESULT (ic));
4077 /* will try to generate an increment */
4078 /* if the right side is not a literal
4080 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4083 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4085 D(emitcode ("; genPlusIncr",""));
4087 /* if increment >=16 bits in register or direct space */
4088 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4089 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4090 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4091 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4092 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4100 /* If the next instruction is a goto and the goto target
4101 * is < 10 instructions previous to this, we can generate
4102 * jumps straight to that target.
4104 if (ic->next && ic->next->op == GOTO
4105 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4106 && labelRange <= 10)
4108 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4109 tlbl = IC_LABEL (ic->next);
4114 tlbl = newiTempLabel (NULL);
4117 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4118 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119 IS_AOP_PREG (IC_RESULT (ic)))
4120 emitcode ("cjne", "%s,#0x00,%05d$",
4121 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4125 emitcode ("clr", "a");
4126 emitcode ("cjne", "a,%s,%05d$",
4127 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4131 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4134 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4135 IS_AOP_PREG (IC_RESULT (ic)))
4136 emitcode ("cjne", "%s,#0x00,%05d$",
4137 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4140 emitcode ("cjne", "a,%s,%05d$",
4141 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4144 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4148 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4149 IS_AOP_PREG (IC_RESULT (ic)))
4150 emitcode ("cjne", "%s,#0x00,%05d$",
4151 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4155 emitcode ("cjne", "a,%s,%05d$",
4156 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4159 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4169 /* if result is dptr */
4170 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4171 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4172 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4173 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4175 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4181 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4184 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4185 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4187 emitcode ("inc", "dptr");
4192 /* if the literal value of the right hand side
4193 is greater than 4 then it is not worth it */
4197 /* if the sizes are greater than 1 then we cannot */
4198 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4199 AOP_SIZE (IC_LEFT (ic)) > 1)
4202 /* we can if the aops of the left & result match or
4203 if they are in registers and the registers are the
4205 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4209 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4210 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4211 aopPut (IC_RESULT (ic), "a", 0);
4217 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4226 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4227 emitcode ("inc", "a");
4228 aopPut (IC_RESULT (ic), "a", 0);
4235 /*-----------------------------------------------------------------*/
4236 /* outBitAcc - output a bit in acc */
4237 /*-----------------------------------------------------------------*/
4239 outBitAcc (operand * result)
4241 symbol *tlbl = newiTempLabel (NULL);
4242 /* if the result is a bit */
4243 if (AOP_TYPE (result) == AOP_CRY)
4245 aopPut (result, "a", 0);
4249 emitcode ("jz", "%05d$", tlbl->key + 100);
4250 emitcode ("mov", "a,%s", one);
4256 /*-----------------------------------------------------------------*/
4257 /* genPlusBits - generates code for addition of two bits */
4258 /*-----------------------------------------------------------------*/
4260 genPlusBits (iCode * ic)
4262 D (emitcode (";", "genPlusBits"));
4264 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4266 symbol *lbl = newiTempLabel (NULL);
4267 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4268 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4269 emitcode ("cpl", "c");
4271 outBitC (IC_RESULT (ic));
4275 emitcode ("clr", "a");
4276 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4277 emitcode ("rlc", "a");
4278 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4279 emitcode ("addc", "a,%s", zero);
4280 outAcc (IC_RESULT (ic));
4285 /* This is the original version of this code.
4287 * This is being kept around for reference,
4288 * because I am not entirely sure I got it right...
4291 adjustArithmeticResult (iCode * ic)
4293 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4294 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4295 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4296 aopPut (IC_RESULT (ic),
4297 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4300 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4301 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4302 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4303 aopPut (IC_RESULT (ic),
4304 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4307 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4308 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4309 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4310 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4311 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4314 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315 aopPut (IC_RESULT (ic), buffer, 2);
4319 /* This is the pure and virtuous version of this code.
4320 * I'm pretty certain it's right, but not enough to toss the old
4324 adjustArithmeticResult (iCode * ic)
4326 if (opIsGptr (IC_RESULT (ic)) &&
4327 opIsGptr (IC_LEFT (ic)) &&
4328 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4330 aopPut (IC_RESULT (ic),
4331 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4335 if (opIsGptr (IC_RESULT (ic)) &&
4336 opIsGptr (IC_RIGHT (ic)) &&
4337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4339 aopPut (IC_RESULT (ic),
4340 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4344 if (opIsGptr (IC_RESULT (ic)) &&
4345 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4346 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4347 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4348 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4351 SNPRINTF (buffer, sizeof(buffer),
4352 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4353 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4358 /*-----------------------------------------------------------------*/
4359 /* genPlus - generates code for addition */
4360 /*-----------------------------------------------------------------*/
4362 genPlus (iCode * ic)
4364 int size, offset = 0;
4367 bool swappedLR = FALSE;
4368 operand *leftOp, *rightOp;
4371 D (emitcode (";", "genPlus"));
4373 /* special cases :- */
4375 aopOp (IC_LEFT (ic), ic, FALSE);
4376 aopOp (IC_RIGHT (ic), ic, FALSE);
4377 aopOp (IC_RESULT (ic), ic, TRUE);
4379 /* if literal, literal on the right or
4380 if left requires ACC or right is already
4382 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4383 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4384 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4386 operand *t = IC_RIGHT (ic);
4387 IC_RIGHT (ic) = IC_LEFT (ic);
4392 /* if both left & right are in bit
4394 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4395 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4401 /* if left in bit space & right literal */
4402 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4403 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4405 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4406 /* if result in bit space */
4407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4409 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4410 emitcode ("cpl", "c");
4411 outBitC (IC_RESULT (ic));
4415 size = getDataSize (IC_RESULT (ic));
4418 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4419 emitcode ("addc", "a,%s", zero);
4420 aopPut (IC_RESULT (ic), "a", offset++);
4426 /* if I can do an increment instead
4427 of add then GOOD for ME */
4428 if (genPlusIncr (ic) == TRUE)
4431 size = getDataSize (IC_RESULT (ic));
4432 leftOp = IC_LEFT(ic);
4433 rightOp = IC_RIGHT(ic);
4436 /* if this is an add for an array access
4437 at a 256 byte boundary */
4439 && AOP_TYPE (op) == AOP_IMMD
4441 && IS_SPEC (OP_SYM_ETYPE (op))
4442 && SPEC_ABSA (OP_SYM_ETYPE (op))
4443 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4446 D(emitcode ("; genPlus aligned array",""));
4447 aopPut (IC_RESULT (ic),
4448 aopGet (rightOp, 0, FALSE, FALSE),
4451 if( 1 == getDataSize (IC_RIGHT (ic)) )
4453 aopPut (IC_RESULT (ic),
4454 aopGet (leftOp, 1, FALSE, FALSE),
4459 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4460 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4461 aopPut (IC_RESULT (ic), "a", 1);
4466 /* if the lower bytes of a literal are zero skip the addition */
4467 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4469 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4470 (skip_bytes+1 < size))
4475 D(emitcode ("; genPlus shortcut",""));
4480 if( offset >= skip_bytes )
4482 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4485 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4487 emitcode("xch", "a,b");
4488 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4489 emitcode (add, "a,b");
4492 else if (aopGetUsesAcc (leftOp, offset))
4494 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4495 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4499 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4500 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4502 aopPut (IC_RESULT (ic), "a", offset);
4503 add = "addc"; /* further adds must propagate carry */
4507 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4508 isOperandVolatile (IC_RESULT (ic), FALSE))
4511 aopPut (IC_RESULT (ic),
4512 aopGet (leftOp, offset, FALSE, FALSE),
4519 adjustArithmeticResult (ic);
4522 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4525 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4535 /*-----------------------------------------------------------------*/
4536 /* genMinusDec :- does subtraction with decrement if possible */
4537 /*-----------------------------------------------------------------*/
4539 genMinusDec (iCode * ic)
4541 unsigned int icount;
4542 unsigned int size = getDataSize (IC_RESULT (ic));
4544 /* will try to generate an increment */
4545 /* if the right side is not a literal
4547 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4550 /* if the literal value of the right hand side
4551 is greater than 4 then it is not worth it */
4552 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4555 D (emitcode (";", "genMinusDec"));
4557 /* if decrement >=16 bits in register or direct space */
4558 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4559 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4560 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4561 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4569 /* If the next instruction is a goto and the goto target
4570 * is <= 10 instructions previous to this, we can generate
4571 * jumps straight to that target.
4573 if (ic->next && ic->next->op == GOTO
4574 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4575 && labelRange <= 10)
4577 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4578 tlbl = IC_LABEL (ic->next);
4583 tlbl = newiTempLabel (NULL);
4587 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4588 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4589 IS_AOP_PREG (IC_RESULT (ic)))
4590 emitcode ("cjne", "%s,#0xff,%05d$"
4591 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4595 emitcode ("mov", "a,#0xff");
4596 emitcode ("cjne", "a,%s,%05d$"
4597 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4600 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4603 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4604 IS_AOP_PREG (IC_RESULT (ic)))
4605 emitcode ("cjne", "%s,#0xff,%05d$"
4606 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4610 emitcode ("cjne", "a,%s,%05d$"
4611 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4614 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4618 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4619 IS_AOP_PREG (IC_RESULT (ic)))
4620 emitcode ("cjne", "%s,#0xff,%05d$"
4621 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4625 emitcode ("cjne", "a,%s,%05d$"
4626 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4629 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4638 /* if the sizes are greater than 1 then we cannot */
4639 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4640 AOP_SIZE (IC_LEFT (ic)) > 1)
4643 /* we can if the aops of the left & result match or
4644 if they are in registers and the registers are the
4646 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4650 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4652 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4657 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4662 emitcode ("dec", "%s", l);
4665 if (AOP_NEEDSACC (IC_RESULT (ic)))
4666 aopPut (IC_RESULT (ic), "a", 0);
4673 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4674 emitcode ("dec", "a");
4675 aopPut (IC_RESULT (ic), "a", 0);
4682 /*-----------------------------------------------------------------*/
4683 /* addSign - complete with sign */
4684 /*-----------------------------------------------------------------*/
4686 addSign (operand * result, int offset, int sign)
4688 int size = (getDataSize (result) - offset);
4693 emitcode ("rlc", "a");
4694 emitcode ("subb", "a,acc");
4697 aopPut (result, "a", offset++);
4704 aopPut (result, zero, offset++);
4710 /*-----------------------------------------------------------------*/
4711 /* genMinusBits - generates code for subtraction of two bits */
4712 /*-----------------------------------------------------------------*/
4714 genMinusBits (iCode * ic)
4716 symbol *lbl = newiTempLabel (NULL);
4718 D (emitcode (";", "genMinusBits"));
4720 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4722 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4723 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4724 emitcode ("cpl", "c");
4726 outBitC (IC_RESULT (ic));
4730 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4731 emitcode ("subb", "a,acc");
4732 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4733 emitcode ("inc", "a");
4735 aopPut (IC_RESULT (ic), "a", 0);
4736 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4740 /*-----------------------------------------------------------------*/
4741 /* genMinus - generates code for subtraction */
4742 /*-----------------------------------------------------------------*/
4744 genMinus (iCode * ic)
4746 int size, offset = 0;
4748 D (emitcode (";", "genMinus"));
4750 aopOp (IC_LEFT (ic), ic, FALSE);
4751 aopOp (IC_RIGHT (ic), ic, FALSE);
4752 aopOp (IC_RESULT (ic), ic, TRUE);
4754 /* special cases :- */
4755 /* if both left & right are in bit space */
4756 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4757 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4763 /* if I can do an decrement instead
4764 of subtract then GOOD for ME */
4765 if (genMinusDec (ic) == TRUE)
4768 size = getDataSize (IC_RESULT (ic));
4770 /* if literal, add a,#-lit, else normal subb */
4771 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4773 unsigned long lit = 0L;
4774 bool useCarry = FALSE;
4776 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4781 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4783 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4784 if (!offset && !size && lit== (unsigned long) -1)
4786 emitcode ("dec", "a");
4790 /* first add without previous c */
4791 emitcode ("add", "a,#0x%02x",
4792 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4797 emitcode ("addc", "a,#0x%02x",
4798 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4800 aopPut (IC_RESULT (ic), "a", offset++);
4804 /* no need to add zeroes */
4805 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4807 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4816 operand *leftOp, *rightOp;
4818 leftOp = IC_LEFT(ic);
4819 rightOp = IC_RIGHT(ic);
4823 if (aopGetUsesAcc(rightOp, offset)) {
4824 if (aopGetUsesAcc(leftOp, offset)) {
4827 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4829 emitcode ("mov", "b,a");
4832 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4833 emitcode ("subb", "a,b");
4836 /* reverse subtraction with 2's complement */
4838 emitcode( "setb", "c");
4840 emitcode( "cpl", "c");
4841 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4842 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4843 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4844 emitcode("cpl", "a");
4845 if (size) /* skip if last byte */
4846 emitcode( "cpl", "c");
4849 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4852 emitcode ("subb", "a,%s",
4853 aopGet(rightOp, offset, FALSE, TRUE));
4856 aopPut (IC_RESULT (ic), "a", offset++);
4860 adjustArithmeticResult (ic);
4863 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4864 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869 /*-----------------------------------------------------------------*/
4870 /* genMultbits :- multiplication of bits */
4871 /*-----------------------------------------------------------------*/
4873 genMultbits (operand * left,
4877 D (emitcode (";", "genMultbits"));
4879 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4880 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4884 /*-----------------------------------------------------------------*/
4885 /* genMultOneByte : 8*8=8/16 bit multiplication */
4886 /*-----------------------------------------------------------------*/
4888 genMultOneByte (operand * left,
4893 int size = AOP_SIZE (result);
4894 bool runtimeSign, compiletimeSign;
4895 bool lUnsigned, rUnsigned, pushedB;
4897 D (emitcode (";", "genMultOneByte"));
4899 if (size < 1 || size > 2)
4901 /* this should never happen */
4902 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4903 AOP_SIZE(result), __FILE__, lineno);
4907 /* (if two literals: the value is computed before) */
4908 /* if one literal, literal on the right */
4909 if (AOP_TYPE (left) == AOP_LIT)
4914 /* emitcode (";", "swapped left and right"); */
4916 /* if no literal, unsigned on the right: shorter code */
4917 if ( AOP_TYPE (right) != AOP_LIT
4918 && SPEC_USIGN (getSpec (operandType (left))))
4925 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4926 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4930 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4931 no need to take care about the signedness! */
4932 || (lUnsigned && rUnsigned))
4934 /* just an unsigned 8 * 8 = 8 multiply
4936 /* emitcode (";","unsigned"); */
4937 /* TODO: check for accumulator clash between left & right aops? */
4939 if (AOP_TYPE (right) == AOP_LIT)
4941 /* moving to accumulator first helps peepholes */
4942 MOVA (aopGet (left, 0, FALSE, FALSE));
4943 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4947 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4948 MOVA (aopGet (left, 0, FALSE, FALSE));
4951 emitcode ("mul", "ab");
4952 aopPut (result, "a", 0);
4954 aopPut (result, "b", 1);
4960 /* we have to do a signed multiply */
4961 /* emitcode (";", "signed"); */
4963 /* now sign adjust for both left & right */
4965 /* let's see what's needed: */
4966 /* apply negative sign during runtime */
4967 runtimeSign = FALSE;
4968 /* negative sign from literals */
4969 compiletimeSign = FALSE;
4973 if (AOP_TYPE(left) == AOP_LIT)
4975 /* signed literal */
4976 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4978 compiletimeSign = TRUE;
4981 /* signed but not literal */
4987 if (AOP_TYPE(right) == AOP_LIT)
4989 /* signed literal */
4990 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4992 compiletimeSign ^= TRUE;
4995 /* signed but not literal */
4999 /* initialize F0, which stores the runtime sign */
5002 if (compiletimeSign)
5003 emitcode ("setb", "F0"); /* set sign flag */
5005 emitcode ("clr", "F0"); /* reset sign flag */
5008 /* save the signs of the operands */
5009 if (AOP_TYPE(right) == AOP_LIT)
5011 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5013 if (!rUnsigned && val < 0)
5014 emitcode ("mov", "b,#0x%02x", -val);
5016 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5018 else /* ! literal */
5020 if (rUnsigned) /* emitcode (";", "signed"); */
5021 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5024 MOVA (aopGet (right, 0, FALSE, FALSE));
5025 lbl = newiTempLabel (NULL);
5026 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5027 emitcode ("cpl", "F0"); /* complement sign flag */
5028 emitcode ("cpl", "a"); /* 2's complement */
5029 emitcode ("inc", "a");
5031 emitcode ("mov", "b,a");
5035 if (AOP_TYPE(left) == AOP_LIT)
5037 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5039 if (!lUnsigned && val < 0)
5040 emitcode ("mov", "a,#0x%02x", -val);
5042 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5044 else /* ! literal */
5046 MOVA (aopGet (left, 0, FALSE, FALSE));
5050 lbl = newiTempLabel (NULL);
5051 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5052 emitcode ("cpl", "F0"); /* complement sign flag */
5053 emitcode ("cpl", "a"); /* 2's complement */
5054 emitcode ("inc", "a");
5059 /* now the multiplication */
5060 emitcode ("mul", "ab");
5061 if (runtimeSign || compiletimeSign)
5063 lbl = newiTempLabel (NULL);
5065 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5066 emitcode ("cpl", "a"); /* lsb 2's complement */
5068 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5071 emitcode ("add", "a,#1"); /* this sets carry flag */
5072 emitcode ("xch", "a,b");
5073 emitcode ("cpl", "a"); /* msb 2's complement */
5074 emitcode ("addc", "a,#0");
5075 emitcode ("xch", "a,b");
5079 aopPut (result, "a", 0);
5081 aopPut (result, "b", 1);
5086 /*-----------------------------------------------------------------*/
5087 /* genMult - generates code for multiplication */
5088 /*-----------------------------------------------------------------*/
5090 genMult (iCode * ic)
5092 operand *left = IC_LEFT (ic);
5093 operand *right = IC_RIGHT (ic);
5094 operand *result = IC_RESULT (ic);
5096 D (emitcode (";", "genMult"));
5098 /* assign the asmops */
5099 aopOp (left, ic, FALSE);
5100 aopOp (right, ic, FALSE);
5101 aopOp (result, ic, TRUE);
5103 /* special cases first */
5105 if (AOP_TYPE (left) == AOP_CRY &&
5106 AOP_TYPE (right) == AOP_CRY)
5108 genMultbits (left, right, result);
5112 /* if both are of size == 1 */
5113 #if 0 // one of them can be a sloc shared with the result
5114 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5116 if (getSize(operandType(left)) == 1 &&
5117 getSize(operandType(right)) == 1)
5120 genMultOneByte (left, right, result);
5124 /* should have been converted to function call */
5125 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5126 getSize(OP_SYMBOL(right)->type));
5130 freeAsmop (result, NULL, ic, TRUE);
5131 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5132 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 /*-----------------------------------------------------------------*/
5136 /* genDivbits :- division of bits */
5137 /*-----------------------------------------------------------------*/
5139 genDivbits (operand * left,
5146 D(emitcode ("; genDivbits",""));
5150 /* the result must be bit */
5151 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5152 l = aopGet (left, 0, FALSE, FALSE);
5156 emitcode ("div", "ab");
5157 emitcode ("rrc", "a");
5161 aopPut (result, "c", 0);
5164 /*-----------------------------------------------------------------*/
5165 /* genDivOneByte : 8 bit division */
5166 /*-----------------------------------------------------------------*/
5168 genDivOneByte (operand * left,
5172 bool lUnsigned, rUnsigned, pushedB;
5173 bool runtimeSign, compiletimeSign;
5174 bool accuse = FALSE;
5175 bool pushedA = FALSE;
5179 D(emitcode ("; genDivOneByte",""));
5181 /* Why is it necessary that genDivOneByte() can return an int result?
5184 volatile unsigned char uc;
5185 volatile signed char sc1, sc2;
5198 In all cases a one byte result would overflow, the following cast to int
5199 would return the wrong result.
5201 Two possible solution:
5202 a) cast operands to int, if ((unsigned) / (signed)) or
5203 ((signed) / (signed))
5204 b) return an 16 bit signed int; this is what we're doing here!
5207 size = AOP_SIZE (result) - 1;
5209 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5210 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5214 /* signed or unsigned */
5215 if (lUnsigned && rUnsigned)
5217 /* unsigned is easy */
5218 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5219 MOVA (aopGet (left, 0, FALSE, FALSE));
5220 emitcode ("div", "ab");
5221 aopPut (result, "a", 0);
5223 aopPut (result, zero, offset++);
5229 /* signed is a little bit more difficult */
5231 /* now sign adjust for both left & right */
5233 /* let's see what's needed: */
5234 /* apply negative sign during runtime */
5235 runtimeSign = FALSE;
5236 /* negative sign from literals */
5237 compiletimeSign = FALSE;
5241 if (AOP_TYPE(left) == AOP_LIT)
5243 /* signed literal */
5244 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5246 compiletimeSign = TRUE;
5249 /* signed but not literal */
5255 if (AOP_TYPE(right) == AOP_LIT)
5257 /* signed literal */
5258 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5260 compiletimeSign ^= TRUE;
5263 /* signed but not literal */
5267 /* initialize F0, which stores the runtime sign */
5270 if (compiletimeSign)
5271 emitcode ("setb", "F0"); /* set sign flag */
5273 emitcode ("clr", "F0"); /* reset sign flag */
5276 /* save the signs of the operands */
5277 if (AOP_TYPE(right) == AOP_LIT)
5279 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5281 if (!rUnsigned && val < 0)
5282 emitcode ("mov", "b,#0x%02x", -val);
5284 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5286 else /* ! literal */
5289 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5292 MOVA (aopGet (right, 0, FALSE, FALSE));
5293 lbl = newiTempLabel (NULL);
5294 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5295 emitcode ("cpl", "F0"); /* complement sign flag */
5296 emitcode ("cpl", "a"); /* 2's complement */
5297 emitcode ("inc", "a");
5299 emitcode ("mov", "b,a");
5303 if (AOP_TYPE(left) == AOP_LIT)
5305 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5307 if (!lUnsigned && val < 0)
5308 emitcode ("mov", "a,#0x%02x", -val);
5310 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5312 else /* ! literal */
5314 MOVA (aopGet (left, 0, FALSE, FALSE));
5318 lbl = newiTempLabel (NULL);
5319 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5320 emitcode ("cpl", "F0"); /* complement sign flag */
5321 emitcode ("cpl", "a"); /* 2's complement */
5322 emitcode ("inc", "a");
5327 /* now the division */
5328 emitcode ("div", "ab");
5330 if (runtimeSign || compiletimeSign)
5332 lbl = newiTempLabel (NULL);
5334 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5335 emitcode ("cpl", "a"); /* lsb 2's complement */
5336 emitcode ("inc", "a");
5339 accuse = aopPut (result, "a", 0);
5342 /* msb is 0x00 or 0xff depending on the sign */
5347 emitcode ("push", "acc");
5350 emitcode ("mov", "c,F0");
5351 emitcode ("subb", "a,acc");
5353 aopPut (result, "a", offset++);
5355 else /* compiletimeSign */
5357 if (aopPutUsesAcc (result, "#0xFF", offset))
5359 emitcode ("push", "acc");
5363 aopPut (result, "#0xff", offset++);
5369 aopPut (result, "a", 0);
5371 aopPut (result, zero, offset++);
5375 emitcode ("pop", "acc");
5379 /*-----------------------------------------------------------------*/
5380 /* genDiv - generates code for division */
5381 /*-----------------------------------------------------------------*/
5385 operand *left = IC_LEFT (ic);
5386 operand *right = IC_RIGHT (ic);
5387 operand *result = IC_RESULT (ic);
5389 D (emitcode (";", "genDiv"));
5391 /* assign the amsops */
5392 aopOp (left, ic, FALSE);
5393 aopOp (right, ic, FALSE);
5394 aopOp (result, ic, TRUE);
5396 /* special cases first */
5398 if (AOP_TYPE (left) == AOP_CRY &&
5399 AOP_TYPE (right) == AOP_CRY)
5401 genDivbits (left, right, result);
5405 /* if both are of size == 1 */
5406 if (AOP_SIZE (left) == 1 &&
5407 AOP_SIZE (right) == 1)
5409 genDivOneByte (left, right, result);
5413 /* should have been converted to function call */
5416 freeAsmop (result, NULL, ic, TRUE);
5417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5421 /*-----------------------------------------------------------------*/
5422 /* genModbits :- modulus of bits */
5423 /*-----------------------------------------------------------------*/
5425 genModbits (operand * left,
5432 D (emitcode (";", "genModbits"));
5436 /* the result must be bit */
5437 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5438 l = aopGet (left, 0, FALSE, FALSE);
5442 emitcode ("div", "ab");
5443 emitcode ("mov", "a,b");
5444 emitcode ("rrc", "a");
5448 aopPut (result, "c", 0);
5451 /*-----------------------------------------------------------------*/
5452 /* genModOneByte : 8 bit modulus */
5453 /*-----------------------------------------------------------------*/
5455 genModOneByte (operand * left,
5459 bool lUnsigned, rUnsigned, pushedB;
5460 bool runtimeSign, compiletimeSign;
5464 D (emitcode (";", "genModOneByte"));
5466 size = AOP_SIZE (result) - 1;
5468 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5469 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5471 /* if right is a literal, check it for 2^n */
5472 if (AOP_TYPE(right) == AOP_LIT)
5474 unsigned char val = abs((int) operandLitValue(right));
5475 symbol *lbl2 = NULL;
5479 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5488 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5489 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5490 /* because iCode should have been changed to genAnd */
5491 /* see file "SDCCopt.c", function "convertToFcall()" */
5493 MOVA (aopGet (left, 0, FALSE, FALSE));
5494 emitcode ("mov", "c,acc.7");
5495 emitcode ("anl", "a,#0x%02x", val - 1);
5496 lbl = newiTempLabel (NULL);
5497 emitcode ("jz", "%05d$", (lbl->key + 100));
5498 emitcode ("jnc", "%05d$", (lbl->key + 100));
5499 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5505 aopPut (result, "a", 0);
5507 aopPut (result, "#0xff", offs2++);
5508 lbl2 = newiTempLabel (NULL);
5509 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5512 aopPut (result, "a", 0);
5514 aopPut (result, zero, offset++);
5528 /* signed or unsigned */
5529 if (lUnsigned && rUnsigned)
5531 /* unsigned is easy */
5532 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5533 MOVA (aopGet (left, 0, FALSE, FALSE));
5534 emitcode ("div", "ab");
5535 aopPut (result, "b", 0);
5537 aopPut (result, zero, offset++);
5543 /* signed is a little bit more difficult */
5545 /* now sign adjust for both left & right */
5547 /* modulus: sign of the right operand has no influence on the result! */
5548 if (AOP_TYPE(right) == AOP_LIT)
5550 signed char val = (char) operandLitValue(right);
5552 if (!rUnsigned && val < 0)
5553 emitcode ("mov", "b,#0x%02x", -val);
5555 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5557 else /* not literal */
5560 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5563 MOVA (aopGet (right, 0, FALSE, FALSE));
5564 lbl = newiTempLabel (NULL);
5565 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5566 emitcode ("cpl", "a"); /* 2's complement */
5567 emitcode ("inc", "a");
5569 emitcode ("mov", "b,a");
5573 /* let's see what's needed: */
5574 /* apply negative sign during runtime */
5575 runtimeSign = FALSE;
5576 /* negative sign from literals */
5577 compiletimeSign = FALSE;
5579 /* sign adjust left side */
5580 if (AOP_TYPE(left) == AOP_LIT)
5582 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5584 if (!lUnsigned && val < 0)
5586 compiletimeSign = TRUE; /* set sign flag */
5587 emitcode ("mov", "a,#0x%02x", -val);
5590 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5592 else /* ! literal */
5594 MOVA (aopGet (left, 0, FALSE, FALSE));
5599 emitcode ("clr", "F0"); /* clear sign flag */
5601 lbl = newiTempLabel (NULL);
5602 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5603 emitcode ("setb", "F0"); /* set sign flag */
5604 emitcode ("cpl", "a"); /* 2's complement */
5605 emitcode ("inc", "a");
5610 /* now the modulus */
5611 emitcode ("div", "ab");
5613 if (runtimeSign || compiletimeSign)
5615 emitcode ("mov", "a,b");
5616 lbl = newiTempLabel (NULL);
5618 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5619 emitcode ("cpl", "a"); /* 2's complement */
5620 emitcode ("inc", "a");
5623 aopPut (result, "a", 0);
5626 /* msb is 0x00 or 0xff depending on the sign */
5629 emitcode ("mov", "c,F0");
5630 emitcode ("subb", "a,acc");
5632 aopPut (result, "a", offset++);
5634 else /* compiletimeSign */
5636 aopPut (result, "#0xff", offset++);
5641 aopPut (result, "b", 0);
5643 aopPut (result, zero, offset++);
5649 /*-----------------------------------------------------------------*/
5650 /* genMod - generates code for division */
5651 /*-----------------------------------------------------------------*/
5655 operand *left = IC_LEFT (ic);
5656 operand *right = IC_RIGHT (ic);
5657 operand *result = IC_RESULT (ic);
5659 D (emitcode (";", "genMod"));
5661 /* assign the asmops */
5662 aopOp (left, ic, FALSE);
5663 aopOp (right, ic, FALSE);
5664 aopOp (result, ic, TRUE);
5666 /* special cases first */
5668 if (AOP_TYPE (left) == AOP_CRY &&
5669 AOP_TYPE (right) == AOP_CRY)
5671 genModbits (left, right, result);
5675 /* if both are of size == 1 */
5676 if (AOP_SIZE (left) == 1 &&
5677 AOP_SIZE (right) == 1)
5679 genModOneByte (left, right, result);
5683 /* should have been converted to function call */
5687 freeAsmop (result, NULL, ic, TRUE);
5688 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5692 /*-----------------------------------------------------------------*/
5693 /* genIfxJump :- will create a jump depending on the ifx */
5694 /*-----------------------------------------------------------------*/
5696 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5699 symbol *tlbl = newiTempLabel (NULL);
5702 D (emitcode (";", "genIfxJump"));
5704 /* if true label then we jump if condition
5708 jlbl = IC_TRUE (ic);
5709 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5710 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5714 /* false label is present */
5715 jlbl = IC_FALSE (ic);
5716 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5717 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5719 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5720 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5722 emitcode (inst, "%05d$", tlbl->key + 100);
5723 freeForBranchAsmop (result);
5724 freeForBranchAsmop (right);
5725 freeForBranchAsmop (left);
5726 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5729 /* mark the icode as generated */
5733 /*-----------------------------------------------------------------*/
5734 /* genCmp :- greater or less than comparison */
5735 /*-----------------------------------------------------------------*/
5737 genCmp (operand * left, operand * right,
5738 operand * result, iCode * ifx, int sign, iCode *ic)
5740 int size, offset = 0;
5741 unsigned long lit = 0L;
5744 D (emitcode (";", "genCmp"));
5746 /* if left & right are bit variables */
5747 if (AOP_TYPE (left) == AOP_CRY &&
5748 AOP_TYPE (right) == AOP_CRY)
5750 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5751 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5755 /* subtract right from left if at the
5756 end the carry flag is set then we know that
5757 left is greater than right */
5758 size = max (AOP_SIZE (left), AOP_SIZE (right));
5760 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5761 if ((size == 1) && !sign &&
5762 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5764 symbol *lbl = newiTempLabel (NULL);
5765 emitcode ("cjne", "%s,%s,%05d$",
5766 aopGet (left, offset, FALSE, FALSE),
5767 aopGet (right, offset, FALSE, FALSE),
5773 if (AOP_TYPE (right) == AOP_LIT)
5775 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776 /* optimize if(x < 0) or if(x >= 0) */
5785 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5786 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5788 genIfxJump (ifx, "acc.7", left, right, result);
5789 freeAsmop (right, NULL, ic, TRUE);
5790 freeAsmop (left, NULL, ic, TRUE);
5796 emitcode ("rlc", "a");
5803 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5804 while (size && (bytelit == 0))
5807 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5813 MOVA (aopGet (left, offset, FALSE, FALSE));
5814 if (sign && size == 0)
5816 emitcode ("xrl", "a,#0x80");
5817 emitcode ("subb", "a,#0x%02x",
5818 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5822 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5832 bool pushedB = FALSE;
5833 rightInB = aopGetUsesAcc(right, offset);
5837 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5839 MOVA (aopGet (left, offset, FALSE, FALSE));
5840 if (sign && size == 0)
5842 emitcode ("xrl", "a,#0x80");
5847 MOVB (aopGet (right, offset, FALSE, FALSE));
5849 emitcode ("xrl", "b,#0x80");
5850 emitcode ("subb", "a,b");
5855 emitcode ("subb", "a,b");
5857 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5867 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5875 /* if the result is used in the next
5876 ifx conditional branch then generate
5877 code a little differently */
5880 genIfxJump (ifx, "c", NULL, NULL, result);
5886 /* leave the result in acc */
5890 /*-----------------------------------------------------------------*/
5891 /* genCmpGt :- greater than comparison */
5892 /*-----------------------------------------------------------------*/
5894 genCmpGt (iCode * ic, iCode * ifx)
5896 operand *left, *right, *result;
5897 sym_link *letype, *retype;
5900 D (emitcode (";", "genCmpGt"));
5902 left = IC_LEFT (ic);
5903 right = IC_RIGHT (ic);
5904 result = IC_RESULT (ic);
5906 letype = getSpec (operandType (left));
5907 retype = getSpec (operandType (right));
5908 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5909 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5910 /* assign the amsops */
5911 aopOp (result, ic, TRUE);
5912 aopOp (left, ic, FALSE);
5913 aopOp (right, ic, FALSE);
5915 genCmp (right, left, result, ifx, sign, ic);
5917 freeAsmop (result, NULL, ic, TRUE);
5920 /*-----------------------------------------------------------------*/
5921 /* genCmpLt - less than comparisons */
5922 /*-----------------------------------------------------------------*/
5924 genCmpLt (iCode * ic, iCode * ifx)
5926 operand *left, *right, *result;
5927 sym_link *letype, *retype;
5930 D (emitcode (";", "genCmpLt"));
5932 left = IC_LEFT (ic);
5933 right = IC_RIGHT (ic);
5934 result = IC_RESULT (ic);
5936 letype = getSpec (operandType (left));
5937 retype = getSpec (operandType (right));
5938 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5939 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5940 /* assign the amsops */
5941 aopOp (result, ic, TRUE);
5942 aopOp (left, ic, FALSE);
5943 aopOp (right, ic, FALSE);
5945 genCmp (left, right, result, ifx, sign, ic);
5947 freeAsmop (result, NULL, ic, TRUE);
5950 /*-----------------------------------------------------------------*/
5951 /* gencjneshort - compare and jump if not equal */
5952 /*-----------------------------------------------------------------*/
5954 gencjneshort (operand * left, operand * right, symbol * lbl)
5956 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5958 unsigned long lit = 0L;
5960 D (emitcode (";", "gencjneshort"));
5962 /* if the left side is a literal or
5963 if the right is in a pointer register and left
5965 if ((AOP_TYPE (left) == AOP_LIT) ||
5966 (AOP_TYPE (left) == AOP_IMMD) ||
5967 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5974 if (AOP_TYPE (right) == AOP_LIT)
5975 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5977 /* if the right side is a literal then anything goes */
5978 if (AOP_TYPE (right) == AOP_LIT &&
5979 AOP_TYPE (left) != AOP_DIR &&
5980 AOP_TYPE (left) != AOP_IMMD)
5984 emitcode ("cjne", "%s,%s,%05d$",
5985 aopGet (left, offset, FALSE, FALSE),
5986 aopGet (right, offset, FALSE, FALSE),
5992 /* if the right side is in a register or in direct space or
5993 if the left is a pointer register & right is not */
5994 else if (AOP_TYPE (right) == AOP_REG ||
5995 AOP_TYPE (right) == AOP_DIR ||
5996 AOP_TYPE (right) == AOP_LIT ||
5997 AOP_TYPE (right) == AOP_IMMD ||
5998 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5999 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6003 MOVA (aopGet (left, offset, FALSE, FALSE));
6004 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6005 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6006 emitcode ("jnz", "%05d$", lbl->key + 100);
6008 emitcode ("cjne", "a,%s,%05d$",
6009 aopGet (right, offset, FALSE, TRUE),
6016 /* right is a pointer reg need both a & b */
6019 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6020 wassertl(!BINUSE, "B was in use");
6021 MOVB (aopGet (left, offset, FALSE, FALSE));
6022 MOVA (aopGet (right, offset, FALSE, FALSE));
6023 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6029 /*-----------------------------------------------------------------*/
6030 /* gencjne - compare and jump if not equal */
6031 /*-----------------------------------------------------------------*/
6033 gencjne (operand * left, operand * right, symbol * lbl)
6035 symbol *tlbl = newiTempLabel (NULL);
6037 D (emitcode (";", "gencjne"));
6039 gencjneshort (left, right, lbl);
6041 emitcode ("mov", "a,%s", one);
6042 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6044 emitcode ("clr", "a");
6048 /*-----------------------------------------------------------------*/
6049 /* genCmpEq - generates code for equal to */
6050 /*-----------------------------------------------------------------*/
6052 genCmpEq (iCode * ic, iCode * ifx)
6054 bool swappedLR = FALSE;
6055 operand *left, *right, *result;
6057 D (emitcode (";", "genCmpEq"));
6059 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6060 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6061 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6063 /* if literal, literal on the right or
6064 if the right is in a pointer register and left
6066 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6067 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6069 operand *t = IC_RIGHT (ic);
6070 IC_RIGHT (ic) = IC_LEFT (ic);
6075 if (ifx && !AOP_SIZE (result))
6078 /* if they are both bit variables */
6079 if (AOP_TYPE (left) == AOP_CRY &&
6080 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6082 if (AOP_TYPE (right) == AOP_LIT)
6084 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6087 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6088 emitcode ("cpl", "c");
6092 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6096 emitcode ("clr", "c");
6098 /* AOP_TYPE(right) == AOP_CRY */
6102 symbol *lbl = newiTempLabel (NULL);
6103 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6104 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6105 emitcode ("cpl", "c");
6108 /* if true label then we jump if condition
6110 tlbl = newiTempLabel (NULL);
6113 emitcode ("jnc", "%05d$", tlbl->key + 100);
6114 freeForBranchAsmop (result);
6115 freeForBranchAsmop (right);
6116 freeForBranchAsmop (left);
6117 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6121 emitcode ("jc", "%05d$", tlbl->key + 100);
6122 freeForBranchAsmop (result);
6123 freeForBranchAsmop (right);
6124 freeForBranchAsmop (left);
6125 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6131 tlbl = newiTempLabel (NULL);
6132 gencjneshort (left, right, tlbl);
6135 freeForBranchAsmop (result);
6136 freeForBranchAsmop (right);
6137 freeForBranchAsmop (left);
6138 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6143 symbol *lbl = newiTempLabel (NULL);
6144 emitcode ("sjmp", "%05d$", lbl->key + 100);
6146 freeForBranchAsmop (result);
6147 freeForBranchAsmop (right);
6148 freeForBranchAsmop (left);
6149 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6153 /* mark the icode as generated */
6158 /* if they are both bit variables */
6159 if (AOP_TYPE (left) == AOP_CRY &&
6160 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6162 if (AOP_TYPE (right) == AOP_LIT)
6164 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6167 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6168 emitcode ("cpl", "c");
6172 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176 emitcode ("clr", "c");
6178 /* AOP_TYPE(right) == AOP_CRY */
6182 symbol *lbl = newiTempLabel (NULL);
6183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6184 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6185 emitcode ("cpl", "c");
6189 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6196 genIfxJump (ifx, "c", left, right, result);
6199 /* if the result is used in an arithmetic operation
6200 then put the result in place */
6205 gencjne (left, right, newiTempLabel (NULL));
6206 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6208 aopPut (result, "a", 0);
6213 genIfxJump (ifx, "a", left, right, result);
6216 /* if the result is used in an arithmetic operation
6217 then put the result in place */
6218 if (AOP_TYPE (result) != AOP_CRY)
6220 /* leave the result in acc */
6224 freeAsmop (result, NULL, ic, TRUE);
6227 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6228 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6232 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6237 /*-----------------------------------------------------------------*/
6238 /* ifxForOp - returns the icode containing the ifx for operand */
6239 /*-----------------------------------------------------------------*/
6241 ifxForOp (operand * op, iCode * ic)
6243 /* if true symbol then needs to be assigned */
6244 if (IS_TRUE_SYMOP (op))
6247 /* if this has register type condition and
6248 the next instruction is ifx with the same operand
6249 and live to of the operand is upto the ifx only then */
6251 ic->next->op == IFX &&
6252 IC_COND (ic->next)->key == op->key &&
6253 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6259 /*-----------------------------------------------------------------*/
6260 /* hasInc - operand is incremented before any other use */
6261 /*-----------------------------------------------------------------*/
6263 hasInc (operand *op, iCode *ic, int osize)
6265 sym_link *type = operandType(op);
6266 sym_link *retype = getSpec (type);
6267 iCode *lic = ic->next;
6270 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6271 if (!IS_SYMOP(op)) return NULL;
6273 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6274 if (IS_AGGREGATE(type->next)) return NULL;
6275 if (osize != (isize = getSize(type->next))) return NULL;
6278 /* if operand of the form op = op + <sizeof *op> */
6279 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6280 isOperandEqual(IC_RESULT(lic),op) &&
6281 isOperandLiteral(IC_RIGHT(lic)) &&
6282 operandLitValue(IC_RIGHT(lic)) == isize) {
6285 /* if the operand used or deffed */
6286 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6289 /* if GOTO or IFX */
6290 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6296 /*-----------------------------------------------------------------*/
6297 /* genAndOp - for && operation */
6298 /*-----------------------------------------------------------------*/
6300 genAndOp (iCode * ic)
6302 operand *left, *right, *result;
6305 D (emitcode (";", "genAndOp"));
6307 /* note here that && operations that are in an
6308 if statement are taken away by backPatchLabels
6309 only those used in arthmetic operations remain */
6310 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6311 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6312 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6314 /* if both are bit variables */
6315 if (AOP_TYPE (left) == AOP_CRY &&
6316 AOP_TYPE (right) == AOP_CRY)
6318 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6319 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6324 tlbl = newiTempLabel (NULL);
6326 emitcode ("jz", "%05d$", tlbl->key + 100);
6332 freeAsmop (result, NULL, ic, TRUE);
6333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6334 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338 /*-----------------------------------------------------------------*/
6339 /* genOrOp - for || operation */
6340 /*-----------------------------------------------------------------*/
6342 genOrOp (iCode * ic)
6344 operand *left, *right, *result;
6347 D (emitcode (";", "genOrOp"));
6349 /* note here that || operations that are in an
6350 if statement are taken away by backPatchLabels
6351 only those used in arthmetic operations remain */
6352 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6353 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6354 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6356 /* if both are bit variables */
6357 if (AOP_TYPE (left) == AOP_CRY &&
6358 AOP_TYPE (right) == AOP_CRY)
6360 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6361 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6366 tlbl = newiTempLabel (NULL);
6368 emitcode ("jnz", "%05d$", tlbl->key + 100);
6374 freeAsmop (result, NULL, ic, TRUE);
6375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6376 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6379 /*-----------------------------------------------------------------*/
6380 /* isLiteralBit - test if lit == 2^n */
6381 /*-----------------------------------------------------------------*/
6383 isLiteralBit (unsigned long lit)
6385 unsigned long pw[32] =
6386 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6387 0x100L, 0x200L, 0x400L, 0x800L,
6388 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6389 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6390 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6391 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6392 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6395 for (idx = 0; idx < 32; idx++)
6401 /*-----------------------------------------------------------------*/
6402 /* continueIfTrue - */
6403 /*-----------------------------------------------------------------*/
6405 continueIfTrue (iCode * ic)
6408 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6412 /*-----------------------------------------------------------------*/
6414 /*-----------------------------------------------------------------*/
6416 jumpIfTrue (iCode * ic)
6419 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6423 /*-----------------------------------------------------------------*/
6424 /* jmpTrueOrFalse - */
6425 /*-----------------------------------------------------------------*/
6427 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6429 // ugly but optimized by peephole
6432 symbol *nlbl = newiTempLabel (NULL);
6433 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6435 freeForBranchAsmop (result);
6436 freeForBranchAsmop (right);
6437 freeForBranchAsmop (left);
6438 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6443 freeForBranchAsmop (result);
6444 freeForBranchAsmop (right);
6445 freeForBranchAsmop (left);
6446 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6452 /*-----------------------------------------------------------------*/
6453 /* genAnd - code for and */
6454 /*-----------------------------------------------------------------*/
6456 genAnd (iCode * ic, iCode * ifx)
6458 operand *left, *right, *result;
6459 int size, offset = 0;
6460 unsigned long lit = 0L;
6464 D (emitcode (";", "genAnd"));
6466 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6467 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6468 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6471 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6473 AOP_TYPE (left), AOP_TYPE (right));
6474 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6476 AOP_SIZE (left), AOP_SIZE (right));
6479 /* if left is a literal & right is not then exchange them */
6480 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6481 AOP_NEEDSACC (left))
6483 operand *tmp = right;
6488 /* if result = right then exchange left and right */
6489 if (sameRegs (AOP (result), AOP (right)))
6491 operand *tmp = right;
6496 /* if right is bit then exchange them */
6497 if (AOP_TYPE (right) == AOP_CRY &&
6498 AOP_TYPE (left) != AOP_CRY)
6500 operand *tmp = right;
6504 if (AOP_TYPE (right) == AOP_LIT)
6505 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6507 size = AOP_SIZE (result);
6510 // result = bit & yy;
6511 if (AOP_TYPE (left) == AOP_CRY)
6513 // c = bit & literal;
6514 if (AOP_TYPE (right) == AOP_LIT)
6518 if (size && sameRegs (AOP (result), AOP (left)))
6521 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6526 if (size && (AOP_TYPE (result) == AOP_CRY))
6528 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6531 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6536 emitcode ("clr", "c");
6541 if (AOP_TYPE (right) == AOP_CRY)
6544 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6545 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6550 MOVA (aopGet (right, 0, FALSE, FALSE));
6552 emitcode ("rrc", "a");
6553 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6561 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6562 genIfxJump (ifx, "c", left, right, result);
6566 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6567 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6568 if ((AOP_TYPE (right) == AOP_LIT) &&
6569 (AOP_TYPE (result) == AOP_CRY) &&
6570 (AOP_TYPE (left) != AOP_CRY))
6572 int posbit = isLiteralBit (lit);
6577 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6581 switch (posbit & 0x07)
6583 case 0: emitcode ("rrc", "a");
6585 case 7: emitcode ("rlc", "a");
6587 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6596 SNPRINTF (buffer, sizeof(buffer),
6597 "acc.%d", posbit & 0x07);
6598 genIfxJump (ifx, buffer, left, right, result);
6601 {// what is this case? just found it in ds390/gen.c
6602 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6609 symbol *tlbl = newiTempLabel (NULL);
6610 int sizel = AOP_SIZE (left);
6612 emitcode ("setb", "c");
6615 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6617 MOVA (aopGet (left, offset, FALSE, FALSE));
6619 if ((posbit = isLiteralBit (bytelit)) != 0)
6620 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6623 if (bytelit != 0x0FFL)
6624 emitcode ("anl", "a,%s",
6625 aopGet (right, offset, FALSE, TRUE));
6626 emitcode ("jnz", "%05d$", tlbl->key + 100);
6631 // bit = left & literal
6634 emitcode ("clr", "c");
6637 // if(left & literal)
6641 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6651 /* if left is same as result */
6652 if (sameRegs (AOP (result), AOP (left)))
6654 for (; size--; offset++)
6656 if (AOP_TYPE (right) == AOP_LIT)
6658 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6659 if (bytelit == 0x0FF)
6661 /* dummy read of volatile operand */
6662 if (isOperandVolatile (left, FALSE))
6663 MOVA (aopGet (left, offset, FALSE, FALSE));
6667 else if (bytelit == 0)
6669 aopPut (result, zero, offset);
6671 else if (IS_AOP_PREG (result))
6673 MOVA (aopGet (left, offset, FALSE, TRUE));
6674 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6675 aopPut (result, "a", offset);
6678 emitcode ("anl", "%s,%s",
6679 aopGet (left, offset, FALSE, TRUE),
6680 aopGet (right, offset, FALSE, FALSE));
6684 if (AOP_TYPE (left) == AOP_ACC)
6687 emitcode("mov", "a,b");
6688 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6690 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6692 MOVB (aopGet (left, offset, FALSE, FALSE));
6693 MOVA (aopGet (right, offset, FALSE, FALSE));
6694 emitcode ("anl", "a,b");
6695 aopPut (result, "a", offset);
6697 else if (aopGetUsesAcc (left, offset))
6699 MOVA (aopGet (left, offset, FALSE, FALSE));
6700 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6701 aopPut (result, "a", offset);
6705 MOVA (aopGet (right, offset, FALSE, FALSE));
6706 if (IS_AOP_PREG (result))
6708 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6709 aopPut (result, "a", offset);
6712 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6719 // left & result in different registers
6720 if (AOP_TYPE (result) == AOP_CRY)
6723 // if(size), result in bit
6724 // if(!size && ifx), conditional oper: if(left & right)
6725 symbol *tlbl = newiTempLabel (NULL);
6726 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6728 emitcode ("setb", "c");
6731 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6732 && AOP_TYPE(left)==AOP_ACC)
6735 emitcode("mov", "a,b");
6736 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6738 else if (AOP_TYPE(left)==AOP_ACC)
6742 bool pushedB = pushB ();
6743 emitcode("mov", "b,a");
6744 MOVA (aopGet (right, offset, FALSE, FALSE));
6745 emitcode("anl", "a,b");
6750 MOVA (aopGet (right, offset, FALSE, FALSE));
6751 emitcode("anl", "a,b");
6754 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6756 MOVB (aopGet (left, offset, FALSE, FALSE));
6757 MOVA (aopGet (right, offset, FALSE, FALSE));
6758 emitcode ("anl", "a,b");
6760 else if (aopGetUsesAcc (left, offset))
6762 MOVA (aopGet (left, offset, FALSE, FALSE));
6763 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6767 MOVA (aopGet (right, offset, FALSE, FALSE));
6768 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6771 emitcode ("jnz", "%05d$", tlbl->key + 100);
6781 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6787 for (; (size--); offset++)
6790 // result = left & right
6791 if (AOP_TYPE (right) == AOP_LIT)
6793 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6794 if (bytelit == 0x0FF)
6797 aopGet (left, offset, FALSE, FALSE),
6801 else if (bytelit == 0)
6803 /* dummy read of volatile operand */
6804 if (isOperandVolatile (left, FALSE))
6805 MOVA (aopGet (left, offset, FALSE, FALSE));
6806 aopPut (result, zero, offset);
6809 else if (AOP_TYPE (left) == AOP_ACC)
6813 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6814 aopPut (result, "a", offset);
6819 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6820 aopPut (result, "b", offset);
6825 // faster than result <- left, anl result,right
6826 // and better if result is SFR
6827 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6828 && AOP_TYPE(left)==AOP_ACC)
6831 emitcode("mov", "a,b");
6832 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6834 else if (AOP_TYPE(left)==AOP_ACC)
6838 bool pushedB = pushB ();
6839 emitcode("mov", "b,a");
6840 MOVA (aopGet (right, offset, FALSE, FALSE));
6841 emitcode("anl", "a,b");
6846 MOVA (aopGet (right, offset, FALSE, FALSE));
6847 emitcode("anl", "a,b");
6850 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6852 MOVB (aopGet (left, offset, FALSE, FALSE));
6853 MOVA (aopGet (right, offset, FALSE, FALSE));
6854 emitcode ("anl", "a,b");
6856 else if (aopGetUsesAcc (left, offset))
6858 MOVA (aopGet (left, offset, FALSE, FALSE));
6859 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6863 MOVA (aopGet (right, offset, FALSE, FALSE));
6864 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6866 aopPut (result, "a", offset);
6872 freeAsmop (result, NULL, ic, TRUE);
6873 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6874 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6877 /*-----------------------------------------------------------------*/
6878 /* genOr - code for or */
6879 /*-----------------------------------------------------------------*/
6881 genOr (iCode * ic, iCode * ifx)
6883 operand *left, *right, *result;
6884 int size, offset = 0;
6885 unsigned long lit = 0L;
6888 D (emitcode (";", "genOr"));
6890 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6891 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6892 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6895 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6897 AOP_TYPE (left), AOP_TYPE (right));
6898 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6900 AOP_SIZE (left), AOP_SIZE (right));
6903 /* if left is a literal & right is not then exchange them */
6904 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6905 AOP_NEEDSACC (left))
6907 operand *tmp = right;
6912 /* if result = right then exchange them */
6913 if (sameRegs (AOP (result), AOP (right)))
6915 operand *tmp = right;
6920 /* if right is bit then exchange them */
6921 if (AOP_TYPE (right) == AOP_CRY &&
6922 AOP_TYPE (left) != AOP_CRY)
6924 operand *tmp = right;
6928 if (AOP_TYPE (right) == AOP_LIT)
6929 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6931 size = AOP_SIZE (result);
6935 if (AOP_TYPE (left) == AOP_CRY)
6937 if (AOP_TYPE (right) == AOP_LIT)
6939 // c = bit | literal;
6942 // lit != 0 => result = 1
6943 if (AOP_TYPE (result) == AOP_CRY)
6946 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6948 continueIfTrue (ifx);
6951 emitcode ("setb", "c");
6955 // lit == 0 => result = left
6956 if (size && sameRegs (AOP (result), AOP (left)))
6958 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6963 if (AOP_TYPE (right) == AOP_CRY)
6966 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6967 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6972 symbol *tlbl = newiTempLabel (NULL);
6973 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6974 emitcode ("setb", "c");
6975 emitcode ("jb", "%s,%05d$",
6976 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6978 emitcode ("jnz", "%05d$", tlbl->key + 100);
6979 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6981 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6996 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6997 genIfxJump (ifx, "c", left, right, result);
7001 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7002 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7003 if ((AOP_TYPE (right) == AOP_LIT) &&
7004 (AOP_TYPE (result) == AOP_CRY) &&
7005 (AOP_TYPE (left) != AOP_CRY))
7011 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7013 continueIfTrue (ifx);
7018 // lit = 0, result = boolean(left)
7020 emitcode ("setb", "c");
7024 symbol *tlbl = newiTempLabel (NULL);
7025 emitcode ("jnz", "%05d$", tlbl->key + 100);
7031 genIfxJump (ifx, "a", left, right, result);
7039 /* if left is same as result */
7040 if (sameRegs (AOP (result), AOP (left)))
7042 for (; size--; offset++)
7044 if (AOP_TYPE (right) == AOP_LIT)
7046 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7049 /* dummy read of volatile operand */
7050 if (isOperandVolatile (left, FALSE))
7051 MOVA (aopGet (left, offset, FALSE, FALSE));
7055 else if (bytelit == 0x0FF)
7057 aopPut (result, "#0xFF", offset);
7059 else if (IS_AOP_PREG (left))
7061 MOVA (aopGet (left, offset, FALSE, TRUE));
7062 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7063 aopPut (result, "a", offset);
7067 emitcode ("orl", "%s,%s",
7068 aopGet (left, offset, FALSE, TRUE),
7069 aopGet (right, offset, FALSE, FALSE));
7074 if (AOP_TYPE (left) == AOP_ACC)
7077 emitcode("mov", "a,b");
7078 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7080 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7082 MOVB (aopGet (left, offset, FALSE, FALSE));
7083 MOVA (aopGet (right, offset, FALSE, FALSE));
7084 emitcode ("orl", "a,b");
7085 aopPut (result, "a", offset);
7087 else if (aopGetUsesAcc (left, offset))
7089 MOVA (aopGet (left, offset, FALSE, FALSE));
7090 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7091 aopPut (result, "a", offset);
7095 MOVA (aopGet (right, offset, FALSE, FALSE));
7096 if (IS_AOP_PREG (left))
7098 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7099 aopPut (result, "a", offset);
7103 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7111 // left & result in different registers
7112 if (AOP_TYPE (result) == AOP_CRY)
7115 // if(size), result in bit
7116 // if(!size && ifx), conditional oper: if(left | right)
7117 symbol *tlbl = newiTempLabel (NULL);
7118 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7120 emitcode ("setb", "c");
7123 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7124 && AOP_TYPE(left)==AOP_ACC)
7127 emitcode("mov", "a,b");
7128 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7130 else if (AOP_TYPE(left)==AOP_ACC)
7134 bool pushedB = pushB ();
7135 emitcode("mov", "b,a");
7136 MOVA (aopGet (right, offset, FALSE, FALSE));
7137 emitcode("orl", "a,b");
7142 MOVA (aopGet (right, offset, FALSE, FALSE));
7143 emitcode("orl", "a,b");
7146 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7148 MOVB (aopGet (left, offset, FALSE, FALSE));
7149 MOVA (aopGet (right, offset, FALSE, FALSE));
7150 emitcode ("orl", "a,b");
7152 else if (aopGetUsesAcc (left, offset))
7154 MOVA (aopGet (left, offset, FALSE, FALSE));
7155 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7159 MOVA (aopGet (right, offset, FALSE, FALSE));
7160 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7163 emitcode ("jnz", "%05d$", tlbl->key + 100);
7173 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7179 for (; (size--); offset++)
7182 // result = left | right
7183 if (AOP_TYPE (right) == AOP_LIT)
7185 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7189 aopGet (left, offset, FALSE, FALSE),
7193 else if (bytelit == 0x0FF)
7195 /* dummy read of volatile operand */
7196 if (isOperandVolatile (left, FALSE))
7197 MOVA (aopGet (left, offset, FALSE, FALSE));
7198 aopPut (result, "#0xFF", offset);
7202 // faster than result <- left, orl result,right
7203 // and better if result is SFR
7204 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7205 && AOP_TYPE(left)==AOP_ACC)
7208 emitcode("mov", "a,b");
7209 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7211 else if (AOP_TYPE(left)==AOP_ACC)
7215 bool pushedB = pushB ();
7216 emitcode("mov", "b,a");
7217 MOVA (aopGet (right, offset, FALSE, FALSE));
7218 emitcode("orl", "a,b");
7223 MOVA (aopGet (right, offset, FALSE, FALSE));
7224 emitcode("orl", "a,b");
7227 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7229 MOVB (aopGet (left, offset, FALSE, FALSE));
7230 MOVA (aopGet (right, offset, FALSE, FALSE));
7231 emitcode ("orl", "a,b");
7233 else if (aopGetUsesAcc (left, offset))
7235 MOVA (aopGet (left, offset, FALSE, FALSE));
7236 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7240 MOVA (aopGet (right, offset, FALSE, FALSE));
7241 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7243 aopPut (result, "a", offset);
7249 freeAsmop (result, NULL, ic, TRUE);
7250 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7251 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7254 /*-----------------------------------------------------------------*/
7255 /* genXor - code for xclusive or */
7256 /*-----------------------------------------------------------------*/
7258 genXor (iCode * ic, iCode * ifx)
7260 operand *left, *right, *result;
7261 int size, offset = 0;
7262 unsigned long lit = 0L;
7265 D (emitcode (";", "genXor"));
7267 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7268 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7269 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7272 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7274 AOP_TYPE (left), AOP_TYPE (right));
7275 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7277 AOP_SIZE (left), AOP_SIZE (right));
7280 /* if left is a literal & right is not ||
7281 if left needs acc & right does not */
7282 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7283 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7285 operand *tmp = right;
7290 /* if result = right then exchange them */
7291 if (sameRegs (AOP (result), AOP (right)))
7293 operand *tmp = right;
7298 /* if right is bit then exchange them */
7299 if (AOP_TYPE (right) == AOP_CRY &&
7300 AOP_TYPE (left) != AOP_CRY)
7302 operand *tmp = right;
7306 if (AOP_TYPE (right) == AOP_LIT)
7307 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7309 size = AOP_SIZE (result);
7313 if (AOP_TYPE (left) == AOP_CRY)
7315 if (AOP_TYPE (right) == AOP_LIT)
7317 // c = bit & literal;
7320 // lit>>1 != 0 => result = 1
7321 if (AOP_TYPE (result) == AOP_CRY)
7324 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7326 continueIfTrue (ifx);
7329 emitcode ("setb", "c");
7336 // lit == 0, result = left
7337 if (size && sameRegs (AOP (result), AOP (left)))
7339 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7343 // lit == 1, result = not(left)
7344 if (size && sameRegs (AOP (result), AOP (left)))
7346 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7351 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7352 emitcode ("cpl", "c");
7360 symbol *tlbl = newiTempLabel (NULL);
7361 if (AOP_TYPE (right) == AOP_CRY)
7364 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7368 int sizer = AOP_SIZE (right);
7370 // if val>>1 != 0, result = 1
7371 emitcode ("setb", "c");
7374 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7376 // test the msb of the lsb
7377 emitcode ("anl", "a,#0xfe");
7378 emitcode ("jnz", "%05d$", tlbl->key + 100);
7382 emitcode ("rrc", "a");
7384 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7385 emitcode ("cpl", "c");
7393 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7394 genIfxJump (ifx, "c", left, right, result);
7398 /* if left is same as result */
7399 if (sameRegs (AOP (result), AOP (left)))
7401 for (; size--; offset++)
7403 if (AOP_TYPE (right) == AOP_LIT)
7405 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7408 /* dummy read of volatile operand */
7409 if (isOperandVolatile (left, FALSE))
7410 MOVA (aopGet (left, offset, FALSE, FALSE));
7414 else if (IS_AOP_PREG (left))
7416 MOVA (aopGet (left, offset, FALSE, TRUE));
7417 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7418 aopPut (result, "a", offset);
7422 emitcode ("xrl", "%s,%s",
7423 aopGet (left, offset, FALSE, TRUE),
7424 aopGet (right, offset, FALSE, FALSE));
7429 if (AOP_TYPE (left) == AOP_ACC)
7432 emitcode("mov", "a,b");
7433 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7435 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7437 MOVB (aopGet (left, offset, FALSE, FALSE));
7438 MOVA (aopGet (right, offset, FALSE, FALSE));
7439 emitcode ("xrl", "a,b");
7440 aopPut (result, "a", offset);
7442 else if (aopGetUsesAcc (left, offset))
7444 MOVA (aopGet (left, offset, FALSE, FALSE));
7445 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7446 aopPut (result, "a", offset);
7450 MOVA (aopGet (right, offset, FALSE, FALSE));
7451 if (IS_AOP_PREG (left))
7453 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7454 aopPut (result, "a", offset);
7457 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7464 // left & result in different registers
7465 if (AOP_TYPE (result) == AOP_CRY)
7468 // if(size), result in bit
7469 // if(!size && ifx), conditional oper: if(left ^ right)
7470 symbol *tlbl = newiTempLabel (NULL);
7471 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7474 emitcode ("setb", "c");
7477 if ((AOP_TYPE (right) == AOP_LIT) &&
7478 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7480 MOVA (aopGet (left, offset, FALSE, FALSE));
7482 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7483 && AOP_TYPE(left)==AOP_ACC)
7486 emitcode("mov", "a,b");
7487 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7489 else if (AOP_TYPE(left)==AOP_ACC)
7493 bool pushedB = pushB ();
7494 emitcode("mov", "b,a");
7495 MOVA (aopGet (right, offset, FALSE, FALSE));
7496 emitcode("xrl", "a,b");
7501 MOVA (aopGet (right, offset, FALSE, FALSE));
7502 emitcode("xrl", "a,b");
7505 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7507 MOVB (aopGet (left, offset, FALSE, FALSE));
7508 MOVA (aopGet (right, offset, FALSE, FALSE));
7509 emitcode ("xrl", "a,b");
7511 else if (aopGetUsesAcc (left, offset))
7513 MOVA (aopGet (left, offset, FALSE, FALSE));
7514 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7518 MOVA (aopGet (right, offset, FALSE, FALSE));
7519 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7522 emitcode ("jnz", "%05d$", tlbl->key + 100);
7532 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7536 for (; (size--); offset++)
7539 // result = left ^ right
7540 if (AOP_TYPE (right) == AOP_LIT)
7542 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7546 aopGet (left, offset, FALSE, FALSE),
7551 // faster than result <- left, xrl result,right
7552 // and better if result is SFR
7553 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7554 && AOP_TYPE(left)==AOP_ACC)
7557 emitcode("mov", "a,b");
7558 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7560 else if (AOP_TYPE(left)==AOP_ACC)
7564 bool pushedB = pushB ();
7565 emitcode("mov", "b,a");
7566 MOVA (aopGet (right, offset, FALSE, FALSE));
7567 emitcode("xrl", "a,b");
7572 MOVA (aopGet (right, offset, FALSE, FALSE));
7573 emitcode("xrl", "a,b");
7576 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7578 MOVB (aopGet (left, offset, FALSE, FALSE));
7579 MOVA (aopGet (right, offset, FALSE, FALSE));
7580 emitcode ("xrl", "a,b");
7582 else if (aopGetUsesAcc (left, offset))
7584 MOVA (aopGet (left, offset, FALSE, FALSE));
7585 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7589 MOVA (aopGet (right, offset, FALSE, FALSE));
7590 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7592 aopPut (result, "a", offset);
7598 freeAsmop (result, NULL, ic, TRUE);
7599 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7600 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7603 /*-----------------------------------------------------------------*/
7604 /* genInline - write the inline code out */
7605 /*-----------------------------------------------------------------*/
7607 genInline (iCode * ic)
7609 char *buffer, *bp, *bp1;
7611 D (emitcode (";", "genInline"));
7613 _G.inLine += (!options.asmpeep);
7615 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7617 /* emit each line as a code */
7628 /* Add \n for labels, not dirs such as c:\mydir */
7629 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7643 /* emitcode("",buffer); */
7644 _G.inLine -= (!options.asmpeep);
7647 /*-----------------------------------------------------------------*/
7648 /* genRRC - rotate right with carry */
7649 /*-----------------------------------------------------------------*/
7653 operand *left, *result;
7657 D (emitcode (";", "genRRC"));
7659 /* rotate right with carry */
7660 left = IC_LEFT (ic);
7661 result = IC_RESULT (ic);
7662 aopOp (left, ic, FALSE);
7663 aopOp (result, ic, FALSE);
7665 /* move it to the result */
7666 size = AOP_SIZE (result);
7668 if (size == 1) { /* special case for 1 byte */
7669 l = aopGet (left, offset, FALSE, FALSE);
7671 emitcode ("rr", "a");
7674 /* no need to clear carry, bit7 will be written later */
7677 l = aopGet (left, offset, FALSE, FALSE);
7679 emitcode ("rrc", "a");
7680 if (AOP_SIZE (result) > 1)
7681 aopPut (result, "a", offset--);
7683 /* now we need to put the carry into the
7684 highest order byte of the result */
7685 if (AOP_SIZE (result) > 1)
7687 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7690 emitcode ("mov", "acc.7,c");
7692 aopPut (result, "a", AOP_SIZE (result) - 1);
7693 freeAsmop (result, NULL, ic, TRUE);
7694 freeAsmop (left, NULL, ic, TRUE);
7697 /*-----------------------------------------------------------------*/
7698 /* genRLC - generate code for rotate left with carry */
7699 /*-----------------------------------------------------------------*/
7703 operand *left, *result;
7707 D (emitcode (";", "genRLC"));
7709 /* rotate right with carry */
7710 left = IC_LEFT (ic);
7711 result = IC_RESULT (ic);
7712 aopOp (left, ic, FALSE);
7713 aopOp (result, ic, FALSE);
7715 /* move it to the result */
7716 size = AOP_SIZE (result);
7720 l = aopGet (left, offset, FALSE, FALSE);
7722 if (size == 0) { /* special case for 1 byte */
7726 emitcode("rlc","a"); /* bit0 will be written later */
7727 if (AOP_SIZE (result) > 1)
7729 aopPut (result, "a", offset++);
7734 l = aopGet (left, offset, FALSE, FALSE);
7736 emitcode ("rlc", "a");
7737 if (AOP_SIZE (result) > 1)
7738 aopPut (result, "a", offset++);
7741 /* now we need to put the carry into the
7742 highest order byte of the result */
7743 if (AOP_SIZE (result) > 1)
7745 l = aopGet (result, 0, FALSE, FALSE);
7748 emitcode ("mov", "acc.0,c");
7750 aopPut (result, "a", 0);
7751 freeAsmop (result, NULL, ic, TRUE);
7752 freeAsmop (left, NULL, ic, TRUE);
7755 /*-----------------------------------------------------------------*/
7756 /* genGetHbit - generates code get highest order bit */
7757 /*-----------------------------------------------------------------*/
7759 genGetHbit (iCode * ic)
7761 operand *left, *result;
7763 D (emitcode (";", "genGetHbit"));
7765 left = IC_LEFT (ic);
7766 result = IC_RESULT (ic);
7767 aopOp (left, ic, FALSE);
7768 aopOp (result, ic, FALSE);
7770 /* get the highest order byte into a */
7771 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7772 if (AOP_TYPE (result) == AOP_CRY)
7774 emitcode ("rlc", "a");
7779 emitcode ("rl", "a");
7780 emitcode ("anl", "a,#0x01");
7784 freeAsmop (result, NULL, ic, TRUE);
7785 freeAsmop (left, NULL, ic, TRUE);
7788 /*-----------------------------------------------------------------*/
7789 /* genGetAbit - generates code get a single bit */
7790 /*-----------------------------------------------------------------*/
7792 genGetAbit (iCode * ic)
7794 operand *left, *right, *result;
7797 D (emitcode (";", "genGetAbit"));
7799 left = IC_LEFT (ic);
7800 right = IC_RIGHT (ic);
7801 result = IC_RESULT (ic);
7802 aopOp (left, ic, FALSE);
7803 aopOp (right, ic, FALSE);
7804 aopOp (result, ic, FALSE);
7806 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7808 /* get the needed byte into a */
7809 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7811 if (AOP_TYPE (result) == AOP_CRY)
7814 emitcode ("rlc", "a");
7815 else if ((shCount) == 0)
7816 emitcode ("rrc", "a");
7818 emitcode ("mov", "c,acc[%d]", shCount);
7826 emitcode ("rr", "a");
7829 emitcode ("rr", "a");
7832 emitcode ("anl", "a,#0x01");
7836 emitcode ("mov", "c,acc[%d]", shCount);
7837 emitcode ("clr", "a");
7838 emitcode ("rlc", "a");
7841 emitcode ("swap", "a");
7842 emitcode ("anl", "a,#0x01");
7845 emitcode ("rl", "a");
7848 emitcode ("rl", "a");
7849 emitcode ("anl", "a,#0x01");
7855 freeAsmop (result, NULL, ic, TRUE);
7856 freeAsmop (right, NULL, ic, TRUE);
7857 freeAsmop (left, NULL, ic, TRUE);
7860 /*-----------------------------------------------------------------*/
7861 /* genGetByte - generates code get a single byte */
7862 /*-----------------------------------------------------------------*/
7864 genGetByte (iCode * ic)
7866 operand *left, *right, *result;
7869 D (emitcode (";", "genGetByte"));
7871 left = IC_LEFT (ic);
7872 right = IC_RIGHT (ic);
7873 result = IC_RESULT (ic);
7874 aopOp (left, ic, FALSE);
7875 aopOp (right, ic, FALSE);
7876 aopOp (result, ic, FALSE);
7878 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7880 aopGet (left, offset, FALSE, FALSE),
7883 freeAsmop (result, NULL, ic, TRUE);
7884 freeAsmop (right, NULL, ic, TRUE);
7885 freeAsmop (left, NULL, ic, TRUE);
7888 /*-----------------------------------------------------------------*/
7889 /* genGetWord - generates code get two bytes */
7890 /*-----------------------------------------------------------------*/
7892 genGetWord (iCode * ic)
7894 operand *left, *right, *result;
7897 D (emitcode (";", "genGetWord"));
7899 left = IC_LEFT (ic);
7900 right = IC_RIGHT (ic);
7901 result = IC_RESULT (ic);
7902 aopOp (left, ic, FALSE);
7903 aopOp (right, ic, FALSE);
7904 aopOp (result, ic, FALSE);
7906 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7908 aopGet (left, offset, FALSE, FALSE),
7911 aopGet (left, offset+1, FALSE, FALSE),
7914 freeAsmop (result, NULL, ic, TRUE);
7915 freeAsmop (right, NULL, ic, TRUE);
7916 freeAsmop (left, NULL, ic, TRUE);
7919 /*-----------------------------------------------------------------*/
7920 /* genSwap - generates code to swap nibbles or bytes */
7921 /*-----------------------------------------------------------------*/
7923 genSwap (iCode * ic)
7925 operand *left, *result;
7927 D(emitcode ("; genSwap",""));
7929 left = IC_LEFT (ic);
7930 result = IC_RESULT (ic);
7931 aopOp (left, ic, FALSE);
7932 aopOp (result, ic, FALSE);
7934 switch (AOP_SIZE (left))
7936 case 1: /* swap nibbles in byte */
7937 MOVA (aopGet (left, 0, FALSE, FALSE));
7938 emitcode ("swap", "a");
7939 aopPut (result, "a", 0);
7941 case 2: /* swap bytes in word */
7942 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7944 MOVA (aopGet (left, 0, FALSE, FALSE));
7945 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7946 aopPut (result, "a", 1);
7948 else if (operandsEqu (left, result))
7951 bool pushedB = FALSE, leftInB = FALSE;
7953 MOVA (aopGet (left, 0, FALSE, FALSE));
7954 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7957 emitcode ("mov", "b,a");
7961 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7962 aopPut (result, reg, 1);
7969 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7970 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7974 wassertl(FALSE, "unsupported SWAP operand size");
7977 freeAsmop (result, NULL, ic, TRUE);
7978 freeAsmop (left, NULL, ic, TRUE);
7981 /*-----------------------------------------------------------------*/
7982 /* AccRol - rotate left accumulator by known count */
7983 /*-----------------------------------------------------------------*/
7985 AccRol (int shCount)
7987 shCount &= 0x0007; // shCount : 0..7
7994 emitcode ("rl", "a");
7997 emitcode ("rl", "a");
7998 emitcode ("rl", "a");
8001 emitcode ("swap", "a");
8002 emitcode ("rr", "a");
8005 emitcode ("swap", "a");
8008 emitcode ("swap", "a");
8009 emitcode ("rl", "a");
8012 emitcode ("rr", "a");
8013 emitcode ("rr", "a");
8016 emitcode ("rr", "a");
8021 /*-----------------------------------------------------------------*/
8022 /* AccLsh - left shift accumulator by known count */
8023 /*-----------------------------------------------------------------*/
8025 AccLsh (int shCount)
8030 emitcode ("add", "a,acc");
8031 else if (shCount == 2)
8033 emitcode ("add", "a,acc");
8034 emitcode ("add", "a,acc");
8038 /* rotate left accumulator */
8040 /* and kill the lower order bits */
8041 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8046 /*-----------------------------------------------------------------*/
8047 /* AccRsh - right shift accumulator by known count */
8048 /*-----------------------------------------------------------------*/
8050 AccRsh (int shCount)
8057 emitcode ("rrc", "a");
8061 /* rotate right accumulator */
8062 AccRol (8 - shCount);
8063 /* and kill the higher order bits */
8064 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8069 /*-----------------------------------------------------------------*/
8070 /* AccSRsh - signed right shift accumulator by known count */
8071 /*-----------------------------------------------------------------*/
8073 AccSRsh (int shCount)
8080 emitcode ("mov", "c,acc.7");
8081 emitcode ("rrc", "a");
8083 else if (shCount == 2)
8085 emitcode ("mov", "c,acc.7");
8086 emitcode ("rrc", "a");
8087 emitcode ("mov", "c,acc.7");
8088 emitcode ("rrc", "a");
8092 tlbl = newiTempLabel (NULL);
8093 /* rotate right accumulator */
8094 AccRol (8 - shCount);
8095 /* and kill the higher order bits */
8096 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8097 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8098 emitcode ("orl", "a,#0x%02x",
8099 (unsigned char) ~SRMask[shCount]);
8105 /*-----------------------------------------------------------------*/
8106 /* shiftR1Left2Result - shift right one byte from left to result */
8107 /*-----------------------------------------------------------------*/
8109 shiftR1Left2Result (operand * left, int offl,
8110 operand * result, int offr,
8111 int shCount, int sign)
8113 MOVA (aopGet (left, offl, FALSE, FALSE));
8114 /* shift right accumulator */
8119 aopPut (result, "a", offr);
8122 /*-----------------------------------------------------------------*/
8123 /* shiftL1Left2Result - shift left one byte from left to result */
8124 /*-----------------------------------------------------------------*/
8126 shiftL1Left2Result (operand * left, int offl,
8127 operand * result, int offr, int shCount)
8130 l = aopGet (left, offl, FALSE, FALSE);
8132 /* shift left accumulator */
8134 aopPut (result, "a", offr);
8137 /*-----------------------------------------------------------------*/
8138 /* movLeft2Result - move byte from left to result */
8139 /*-----------------------------------------------------------------*/
8141 movLeft2Result (operand * left, int offl,
8142 operand * result, int offr, int sign)
8145 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8147 l = aopGet (left, offl, FALSE, FALSE);
8149 if (*l == '@' && (IS_AOP_PREG (result)))
8151 emitcode ("mov", "a,%s", l);
8152 aopPut (result, "a", offr);
8158 aopPut (result, l, offr);
8162 /* MSB sign in acc.7 ! */
8163 if (getDataSize (left) == offl + 1)
8166 aopPut (result, "a", offr);
8173 /*-----------------------------------------------------------------*/
8174 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8175 /*-----------------------------------------------------------------*/
8179 emitcode ("rrc", "a");
8180 emitcode ("xch", "a,%s", x);
8181 emitcode ("rrc", "a");
8182 emitcode ("xch", "a,%s", x);
8185 /*-----------------------------------------------------------------*/
8186 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8187 /*-----------------------------------------------------------------*/
8191 emitcode ("xch", "a,%s", x);
8192 emitcode ("rlc", "a");
8193 emitcode ("xch", "a,%s", x);
8194 emitcode ("rlc", "a");
8197 /*-----------------------------------------------------------------*/
8198 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8199 /*-----------------------------------------------------------------*/
8203 emitcode ("xch", "a,%s", x);
8204 emitcode ("add", "a,acc");
8205 emitcode ("xch", "a,%s", x);
8206 emitcode ("rlc", "a");
8209 /*-----------------------------------------------------------------*/
8210 /* AccAXLsh - left shift a:x by known count (0..7) */
8211 /*-----------------------------------------------------------------*/
8213 AccAXLsh (char *x, int shCount)
8228 case 5: // AAAAABBB:CCCCCDDD
8230 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8232 emitcode ("anl", "a,#0x%02x",
8233 SLMask[shCount]); // BBB00000:CCCCCDDD
8235 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8237 AccRol (shCount); // DDDCCCCC:BBB00000
8239 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8241 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8243 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8245 emitcode ("anl", "a,#0x%02x",
8246 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8248 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8250 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8253 case 6: // AAAAAABB:CCCCCCDD
8254 emitcode ("anl", "a,#0x%02x",
8255 SRMask[shCount]); // 000000BB:CCCCCCDD
8256 emitcode ("mov", "c,acc.0"); // c = B
8257 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8259 AccAXRrl1 (x); // BCCCCCCD:D000000B
8260 AccAXRrl1 (x); // BBCCCCCC:DD000000
8262 emitcode("rrc","a");
8263 emitcode("xch","a,%s", x);
8264 emitcode("rrc","a");
8265 emitcode("mov","c,acc.0"); //<< get correct bit
8266 emitcode("xch","a,%s", x);
8268 emitcode("rrc","a");
8269 emitcode("xch","a,%s", x);
8270 emitcode("rrc","a");
8271 emitcode("xch","a,%s", x);
8274 case 7: // a:x <<= 7
8276 emitcode ("anl", "a,#0x%02x",
8277 SRMask[shCount]); // 0000000B:CCCCCCCD
8279 emitcode ("mov", "c,acc.0"); // c = B
8281 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8283 AccAXRrl1 (x); // BCCCCCCC:D0000000
8291 /*-----------------------------------------------------------------*/
8292 /* AccAXRsh - right shift a:x known count (0..7) */
8293 /*-----------------------------------------------------------------*/
8295 AccAXRsh (char *x, int shCount)
8303 AccAXRrl1 (x); // 0->a:x
8308 AccAXRrl1 (x); // 0->a:x
8311 AccAXRrl1 (x); // 0->a:x
8316 case 5: // AAAAABBB:CCCCCDDD = a:x
8318 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8320 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8322 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8324 emitcode ("anl", "a,#0x%02x",
8325 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8327 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8329 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8331 emitcode ("anl", "a,#0x%02x",
8332 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8334 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8336 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8338 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8341 case 6: // AABBBBBB:CCDDDDDD
8343 emitcode ("mov", "c,acc.7");
8344 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8346 emitcode ("mov", "c,acc.7");
8347 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8349 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8351 emitcode ("anl", "a,#0x%02x",
8352 SRMask[shCount]); // 000000AA:BBBBBBCC
8355 case 7: // ABBBBBBB:CDDDDDDD
8357 emitcode ("mov", "c,acc.7"); // c = A
8359 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8361 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8363 emitcode ("anl", "a,#0x%02x",
8364 SRMask[shCount]); // 0000000A:BBBBBBBC
8372 /*-----------------------------------------------------------------*/
8373 /* AccAXRshS - right shift signed a:x known count (0..7) */
8374 /*-----------------------------------------------------------------*/
8376 AccAXRshS (char *x, int shCount)
8384 emitcode ("mov", "c,acc.7");
8385 AccAXRrl1 (x); // s->a:x
8389 emitcode ("mov", "c,acc.7");
8390 AccAXRrl1 (x); // s->a:x
8392 emitcode ("mov", "c,acc.7");
8393 AccAXRrl1 (x); // s->a:x
8398 case 5: // AAAAABBB:CCCCCDDD = a:x
8400 tlbl = newiTempLabel (NULL);
8401 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8403 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8405 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8407 emitcode ("anl", "a,#0x%02x",
8408 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8410 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8412 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8414 emitcode ("anl", "a,#0x%02x",
8415 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8417 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8419 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8421 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8423 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8424 emitcode ("orl", "a,#0x%02x",
8425 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8428 break; // SSSSAAAA:BBBCCCCC
8430 case 6: // AABBBBBB:CCDDDDDD
8432 tlbl = newiTempLabel (NULL);
8433 emitcode ("mov", "c,acc.7");
8434 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8436 emitcode ("mov", "c,acc.7");
8437 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8439 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8441 emitcode ("anl", "a,#0x%02x",
8442 SRMask[shCount]); // 000000AA:BBBBBBCC
8444 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8445 emitcode ("orl", "a,#0x%02x",
8446 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8450 case 7: // ABBBBBBB:CDDDDDDD
8452 tlbl = newiTempLabel (NULL);
8453 emitcode ("mov", "c,acc.7"); // c = A
8455 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8457 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8459 emitcode ("anl", "a,#0x%02x",
8460 SRMask[shCount]); // 0000000A:BBBBBBBC
8462 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8463 emitcode ("orl", "a,#0x%02x",
8464 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8473 /*-----------------------------------------------------------------*/
8474 /* shiftL2Left2Result - shift left two bytes from left to result */
8475 /*-----------------------------------------------------------------*/
8477 shiftL2Left2Result (operand * left, int offl,
8478 operand * result, int offr, int shCount)
8481 bool pushedB = FALSE;
8484 if (sameRegs (AOP (result), AOP (left)) &&
8485 ((offl + MSB16) == offr))
8487 /* don't crash result[offr] */
8488 MOVA (aopGet (left, offl, FALSE, FALSE));
8489 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8490 usedB = !strncmp(x, "b", 1);
8492 else if (aopGetUsesAcc (result, offr))
8494 movLeft2Result (left, offl, result, offr, 0);
8497 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8498 MOVA (aopGet (result, offr, FALSE, FALSE));
8499 emitcode ("xch", "a,b");
8504 movLeft2Result (left, offl, result, offr, 0);
8505 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8506 x = aopGet (result, offr, FALSE, FALSE);
8508 /* ax << shCount (x = lsb(result)) */
8509 AccAXLsh (x, shCount);
8512 emitcode ("xch", "a,b");
8513 aopPut (result, "a", offr);
8514 aopPut (result, "b", offr + MSB16);
8519 aopPut (result, "a", offr + MSB16);
8524 /*-----------------------------------------------------------------*/
8525 /* shiftR2Left2Result - shift right two bytes from left to result */
8526 /*-----------------------------------------------------------------*/
8528 shiftR2Left2Result (operand * left, int offl,
8529 operand * result, int offr,
8530 int shCount, int sign)
8533 bool pushedB = FALSE;
8536 if (sameRegs (AOP (result), AOP (left)) &&
8537 ((offl + MSB16) == offr))
8539 /* don't crash result[offr] */
8540 MOVA (aopGet (left, offl, FALSE, FALSE));
8541 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8542 usedB = !strncmp(x, "b", 1);
8544 else if (aopGetUsesAcc (result, offr))
8546 movLeft2Result (left, offl, result, offr, 0);
8549 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8550 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8555 movLeft2Result (left, offl, result, offr, 0);
8556 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8557 x = aopGet (result, offr, FALSE, FALSE);
8559 /* a:x >> shCount (x = lsb(result)) */
8561 AccAXRshS (x, shCount);
8563 AccAXRsh (x, shCount);
8566 emitcode ("xch", "a,b");
8567 aopPut (result, "a", offr);
8568 emitcode ("xch", "a,b");
8571 if (getDataSize (result) > 1)
8572 aopPut (result, "a", offr + MSB16);
8575 /*-----------------------------------------------------------------*/
8576 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8577 /*-----------------------------------------------------------------*/
8579 shiftLLeftOrResult (operand * left, int offl,
8580 operand * result, int offr, int shCount)
8582 MOVA (aopGet (left, offl, FALSE, FALSE));
8583 /* shift left accumulator */
8585 /* or with result */
8586 if (aopGetUsesAcc (result, offr))
8588 emitcode ("xch", "a,b");
8589 MOVA (aopGet (result, offr, FALSE, FALSE));
8590 emitcode ("orl", "a,b");
8594 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8596 /* back to result */
8597 aopPut (result, "a", offr);
8600 /*-----------------------------------------------------------------*/
8601 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8602 /*-----------------------------------------------------------------*/
8604 shiftRLeftOrResult (operand * left, int offl,
8605 operand * result, int offr, int shCount)
8607 MOVA (aopGet (left, offl, FALSE, FALSE));
8608 /* shift right accumulator */
8610 /* or with result */
8611 if (aopGetUsesAcc(result, offr))
8613 emitcode ("xch", "a,b");
8614 MOVA (aopGet (result, offr, FALSE, FALSE));
8615 emitcode ("orl", "a,b");
8619 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8621 /* back to result */
8622 aopPut (result, "a", offr);
8625 /*-----------------------------------------------------------------*/
8626 /* genlshOne - left shift a one byte quantity by known count */
8627 /*-----------------------------------------------------------------*/
8629 genlshOne (operand * result, operand * left, int shCount)
8631 D (emitcode (";", "genlshOne"));
8633 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8636 /*-----------------------------------------------------------------*/
8637 /* genlshTwo - left shift two bytes by known amount != 0 */
8638 /*-----------------------------------------------------------------*/
8640 genlshTwo (operand * result, operand * left, int shCount)
8644 D (emitcode (";", "genlshTwo"));
8646 size = getDataSize (result);
8648 /* if shCount >= 8 */
8656 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8658 movLeft2Result (left, LSB, result, MSB16, 0);
8660 aopPut (result, zero, LSB);
8663 /* 1 <= shCount <= 7 */
8667 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8669 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8673 /*-----------------------------------------------------------------*/
8674 /* shiftLLong - shift left one long from left to result */
8675 /* offl = LSB or MSB16 */
8676 /*-----------------------------------------------------------------*/
8678 shiftLLong (operand * left, operand * result, int offr)
8681 int size = AOP_SIZE (result);
8683 if (size >= LSB + offr)
8685 l = aopGet (left, LSB, FALSE, FALSE);
8687 emitcode ("add", "a,acc");
8688 if (sameRegs (AOP (left), AOP (result)) &&
8689 size >= MSB16 + offr && offr != LSB)
8690 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8692 aopPut (result, "a", LSB + offr);
8695 if (size >= MSB16 + offr)
8697 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8699 l = aopGet (left, MSB16, FALSE, FALSE);
8702 emitcode ("rlc", "a");
8703 if (sameRegs (AOP (left), AOP (result)) &&
8704 size >= MSB24 + offr && offr != LSB)
8705 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8707 aopPut (result, "a", MSB16 + offr);
8710 if (size >= MSB24 + offr)
8712 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8714 l = aopGet (left, MSB24, FALSE, FALSE);
8717 emitcode ("rlc", "a");
8718 if (sameRegs (AOP (left), AOP (result)) &&
8719 size >= MSB32 + offr && offr != LSB)
8720 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8722 aopPut (result, "a", MSB24 + offr);
8725 if (size > MSB32 + offr)
8727 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8729 l = aopGet (left, MSB32, FALSE, FALSE);
8732 emitcode ("rlc", "a");
8733 aopPut (result, "a", MSB32 + offr);
8736 aopPut (result, zero, LSB);
8739 /*-----------------------------------------------------------------*/
8740 /* genlshFour - shift four byte by a known amount != 0 */
8741 /*-----------------------------------------------------------------*/
8743 genlshFour (operand * result, operand * left, int shCount)
8747 D (emitcode (";", "genlshFour"));
8749 size = AOP_SIZE (result);
8751 /* if shifting more that 3 bytes */
8756 /* lowest order of left goes to the highest
8757 order of the destination */
8758 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8760 movLeft2Result (left, LSB, result, MSB32, 0);
8761 aopPut (result, zero, LSB);
8762 aopPut (result, zero, MSB16);
8763 aopPut (result, zero, MSB24);
8767 /* more than two bytes */
8768 else if (shCount >= 16)
8770 /* lower order two bytes goes to higher order two bytes */
8772 /* if some more remaining */
8774 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8777 movLeft2Result (left, MSB16, result, MSB32, 0);
8778 movLeft2Result (left, LSB, result, MSB24, 0);
8780 aopPut (result, zero, MSB16);
8781 aopPut (result, zero, LSB);
8785 /* if more than 1 byte */
8786 else if (shCount >= 8)
8788 /* lower order three bytes goes to higher order three bytes */
8793 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8795 movLeft2Result (left, LSB, result, MSB16, 0);
8801 movLeft2Result (left, MSB24, result, MSB32, 0);
8802 movLeft2Result (left, MSB16, result, MSB24, 0);
8803 movLeft2Result (left, LSB, result, MSB16, 0);
8804 aopPut (result, zero, LSB);
8806 else if (shCount == 1)
8807 shiftLLong (left, result, MSB16);
8810 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8811 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8812 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8813 aopPut (result, zero, LSB);
8818 /* 1 <= shCount <= 7 */
8819 else if (shCount <= 2)
8821 shiftLLong (left, result, LSB);
8823 shiftLLong (result, result, LSB);
8825 /* 3 <= shCount <= 7, optimize */
8828 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8829 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8830 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8834 /*-----------------------------------------------------------------*/
8835 /* genLeftShiftLiteral - left shifting by known count */
8836 /*-----------------------------------------------------------------*/
8838 genLeftShiftLiteral (operand * left,
8843 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8846 D (emitcode (";", "genLeftShiftLiteral"));
8848 freeAsmop (right, NULL, ic, TRUE);
8850 aopOp (left, ic, FALSE);
8851 aopOp (result, ic, FALSE);
8853 size = getSize (operandType (result));
8856 emitcode ("; shift left ", "result %d, left %d", size,
8860 /* I suppose that the left size >= result size */
8865 movLeft2Result (left, size, result, size, 0);
8868 else if (shCount >= (size * 8))
8872 aopPut (result, zero, size);
8880 genlshOne (result, left, shCount);
8884 genlshTwo (result, left, shCount);
8888 genlshFour (result, left, shCount);
8891 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8892 "*** ack! mystery literal shift!\n");
8896 freeAsmop (result, NULL, ic, TRUE);
8897 freeAsmop (left, NULL, ic, TRUE);
8900 /*-----------------------------------------------------------------*/
8901 /* genLeftShift - generates code for left shifting */
8902 /*-----------------------------------------------------------------*/
8904 genLeftShift (iCode * ic)
8906 operand *left, *right, *result;
8909 symbol *tlbl, *tlbl1;
8912 D (emitcode (";", "genLeftShift"));
8914 right = IC_RIGHT (ic);
8915 left = IC_LEFT (ic);
8916 result = IC_RESULT (ic);
8918 aopOp (right, ic, FALSE);
8920 /* if the shift count is known then do it
8921 as efficiently as possible */
8922 if (AOP_TYPE (right) == AOP_LIT)
8924 genLeftShiftLiteral (left, right, result, ic);
8928 /* shift count is unknown then we have to form
8929 a loop get the loop count in B : Note: we take
8930 only the lower order byte since shifting
8931 more that 32 bits make no sense anyway, ( the
8932 largest size of an object can be only 32 bits ) */
8935 MOVB (aopGet (right, 0, FALSE, FALSE));
8936 emitcode ("inc", "b");
8937 freeAsmop (right, NULL, ic, TRUE);
8938 aopOp (left, ic, FALSE);
8939 aopOp (result, ic, FALSE);
8941 /* now move the left to the result if they are not the same */
8942 if (!sameRegs (AOP (left), AOP (result)) &&
8943 AOP_SIZE (result) > 1)
8946 size = AOP_SIZE (result);
8950 l = aopGet (left, offset, FALSE, TRUE);
8951 if (*l == '@' && (IS_AOP_PREG (result)))
8954 emitcode ("mov", "a,%s", l);
8955 aopPut (result, "a", offset);
8958 aopPut (result, l, offset);
8963 tlbl = newiTempLabel (NULL);
8964 size = AOP_SIZE (result);
8966 tlbl1 = newiTempLabel (NULL);
8968 /* if it is only one byte then */
8971 symbol *tlbl1 = newiTempLabel (NULL);
8973 l = aopGet (left, 0, FALSE, FALSE);
8975 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8977 emitcode ("add", "a,acc");
8979 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8981 aopPut (result, "a", 0);
8985 reAdjustPreg (AOP (result));
8987 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8989 l = aopGet (result, offset, FALSE, FALSE);
8991 emitcode ("add", "a,acc");
8992 aopPut (result, "a", offset++);
8995 l = aopGet (result, offset, FALSE, FALSE);
8997 emitcode ("rlc", "a");
8998 aopPut (result, "a", offset++);
9000 reAdjustPreg (AOP (result));
9003 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9006 freeAsmop (result, NULL, ic, TRUE);
9007 freeAsmop (left, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genrshOne - right shift a one byte quantity by known count */
9012 /*-----------------------------------------------------------------*/
9014 genrshOne (operand * result, operand * left,
9015 int shCount, int sign)
9017 D (emitcode (";", "genrshOne"));
9019 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9022 /*-----------------------------------------------------------------*/
9023 /* genrshTwo - right shift two bytes by known amount != 0 */
9024 /*-----------------------------------------------------------------*/
9026 genrshTwo (operand * result, operand * left,
9027 int shCount, int sign)
9029 D (emitcode (";", "genrshTwo"));
9031 /* if shCount >= 8 */
9036 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9038 movLeft2Result (left, MSB16, result, LSB, sign);
9039 addSign (result, MSB16, sign);
9042 /* 1 <= shCount <= 7 */
9044 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9047 /*-----------------------------------------------------------------*/
9048 /* shiftRLong - shift right one long from left to result */
9049 /* offl = LSB or MSB16 */
9050 /*-----------------------------------------------------------------*/
9052 shiftRLong (operand * left, int offl,
9053 operand * result, int sign)
9055 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9057 if (overlapping && offl>1)
9059 // we are in big trouble, but this shouldn't happen
9060 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9063 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9070 emitcode ("rlc", "a");
9071 emitcode ("subb", "a,acc");
9072 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9074 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9078 aopPut (result, "a", MSB32);
9079 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9084 if (aopPutUsesAcc (result, zero, MSB32))
9086 emitcode("xch", "a,b");
9087 aopPut (result, zero, MSB32);
9088 emitcode("xch", "a,b");
9092 aopPut (result, zero, MSB32);
9099 emitcode ("clr", "c");
9103 emitcode ("mov", "c,acc.7");
9106 emitcode ("rrc", "a");
9108 if (overlapping && offl==MSB16 &&
9109 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9111 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9115 aopPut (result, "a", MSB32 - offl);
9116 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9119 emitcode ("rrc", "a");
9120 if (overlapping && offl==MSB16 &&
9121 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9123 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9127 aopPut (result, "a", MSB24 - offl);
9128 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9131 emitcode ("rrc", "a");
9134 aopPut (result, "a", MSB16 - offl);
9139 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9141 xch_a_aopGet (left, LSB, FALSE, FALSE);
9145 aopPut (result, "a", MSB16 - offl);
9146 MOVA (aopGet (left, LSB, FALSE, FALSE));
9148 emitcode ("rrc", "a");
9149 aopPut (result, "a", LSB);
9153 /*-----------------------------------------------------------------*/
9154 /* genrshFour - shift four byte by a known amount != 0 */
9155 /*-----------------------------------------------------------------*/
9157 genrshFour (operand * result, operand * left,
9158 int shCount, int sign)
9160 D (emitcode (";", "genrshFour"));
9162 /* if shifting more that 3 bytes */
9167 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9169 movLeft2Result (left, MSB32, result, LSB, sign);
9170 addSign (result, MSB16, sign);
9172 else if (shCount >= 16)
9176 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9179 movLeft2Result (left, MSB24, result, LSB, 0);
9180 movLeft2Result (left, MSB32, result, MSB16, sign);
9182 addSign (result, MSB24, sign);
9184 else if (shCount >= 8)
9189 shiftRLong (left, MSB16, result, sign);
9191 else if (shCount == 0)
9193 movLeft2Result (left, MSB16, result, LSB, 0);
9194 movLeft2Result (left, MSB24, result, MSB16, 0);
9195 movLeft2Result (left, MSB32, result, MSB24, sign);
9196 addSign (result, MSB32, sign);
9200 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9201 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9202 /* the last shift is signed */
9203 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9204 addSign (result, MSB32, sign);
9209 /* 1 <= shCount <= 7 */
9212 shiftRLong (left, LSB, result, sign);
9214 shiftRLong (result, LSB, result, sign);
9218 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9219 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9220 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9225 /*-----------------------------------------------------------------*/
9226 /* genRightShiftLiteral - right shifting by known count */
9227 /*-----------------------------------------------------------------*/
9229 genRightShiftLiteral (operand * left,
9235 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9238 D (emitcode (";", "genRightShiftLiteral"));
9240 freeAsmop (right, NULL, ic, TRUE);
9242 aopOp (left, ic, FALSE);
9243 aopOp (result, ic, FALSE);
9246 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9250 size = getDataSize (left);
9251 /* test the LEFT size !!! */
9253 /* I suppose that the left size >= result size */
9256 size = getDataSize (result);
9258 movLeft2Result (left, size, result, size, 0);
9261 else if (shCount >= (size * 8))
9265 /* get sign in acc.7 */
9266 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9268 addSign (result, LSB, sign);
9275 genrshOne (result, left, shCount, sign);
9279 genrshTwo (result, left, shCount, sign);
9283 genrshFour (result, left, shCount, sign);
9289 freeAsmop (result, NULL, ic, TRUE);
9290 freeAsmop (left, NULL, ic, TRUE);
9293 /*-----------------------------------------------------------------*/
9294 /* genSignedRightShift - right shift of signed number */
9295 /*-----------------------------------------------------------------*/
9297 genSignedRightShift (iCode * ic)
9299 operand *right, *left, *result;
9302 symbol *tlbl, *tlbl1;
9305 D (emitcode (";", "genSignedRightShift"));
9307 /* we do it the hard way put the shift count in b
9308 and loop thru preserving the sign */
9310 right = IC_RIGHT (ic);
9311 left = IC_LEFT (ic);
9312 result = IC_RESULT (ic);
9314 aopOp (right, ic, FALSE);
9317 if (AOP_TYPE (right) == AOP_LIT)
9319 genRightShiftLiteral (left, right, result, ic, 1);
9322 /* shift count is unknown then we have to form
9323 a loop get the loop count in B : Note: we take
9324 only the lower order byte since shifting
9325 more that 32 bits make no sense anyway, ( the
9326 largest size of an object can be only 32 bits ) */
9329 MOVB (aopGet (right, 0, FALSE, FALSE));
9330 emitcode ("inc", "b");
9331 freeAsmop (right, NULL, ic, TRUE);
9332 aopOp (left, ic, FALSE);
9333 aopOp (result, ic, FALSE);
9335 /* now move the left to the result if they are not the
9337 if (!sameRegs (AOP (left), AOP (result)) &&
9338 AOP_SIZE (result) > 1)
9341 size = AOP_SIZE (result);
9345 l = aopGet (left, offset, FALSE, TRUE);
9346 if (*l == '@' && IS_AOP_PREG (result))
9349 emitcode ("mov", "a,%s", l);
9350 aopPut (result, "a", offset);
9353 aopPut (result, l, offset);
9358 /* mov the highest order bit to OVR */
9359 tlbl = newiTempLabel (NULL);
9360 tlbl1 = newiTempLabel (NULL);
9362 size = AOP_SIZE (result);
9364 MOVA (aopGet (left, offset, FALSE, FALSE));
9365 emitcode ("rlc", "a");
9366 emitcode ("mov", "ov,c");
9367 /* if it is only one byte then */
9370 l = aopGet (left, 0, FALSE, FALSE);
9372 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9374 emitcode ("mov", "c,ov");
9375 emitcode ("rrc", "a");
9377 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9379 aopPut (result, "a", 0);
9383 reAdjustPreg (AOP (result));
9384 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9386 emitcode ("mov", "c,ov");
9389 l = aopGet (result, offset, FALSE, FALSE);
9391 emitcode ("rrc", "a");
9392 aopPut (result, "a", offset--);
9394 reAdjustPreg (AOP (result));
9396 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9400 freeAsmop (result, NULL, ic, TRUE);
9401 freeAsmop (left, NULL, ic, TRUE);
9404 /*-----------------------------------------------------------------*/
9405 /* genRightShift - generate code for right shifting */
9406 /*-----------------------------------------------------------------*/
9408 genRightShift (iCode * ic)
9410 operand *right, *left, *result;
9414 symbol *tlbl, *tlbl1;
9417 D (emitcode (";", "genRightShift"));
9419 /* if signed then we do it the hard way preserve the
9420 sign bit moving it inwards */
9421 letype = getSpec (operandType (IC_LEFT (ic)));
9423 if (!SPEC_USIGN (letype))
9425 genSignedRightShift (ic);
9429 /* signed & unsigned types are treated the same : i.e. the
9430 signed is NOT propagated inwards : quoting from the
9431 ANSI - standard : "for E1 >> E2, is equivalent to division
9432 by 2**E2 if unsigned or if it has a non-negative value,
9433 otherwise the result is implementation defined ", MY definition
9434 is that the sign does not get propagated */
9436 right = IC_RIGHT (ic);
9437 left = IC_LEFT (ic);
9438 result = IC_RESULT (ic);
9440 aopOp (right, ic, FALSE);
9442 /* if the shift count is known then do it
9443 as efficiently as possible */
9444 if (AOP_TYPE (right) == AOP_LIT)
9446 genRightShiftLiteral (left, right, result, ic, 0);
9450 /* shift count is unknown then we have to form
9451 a loop get the loop count in B : Note: we take
9452 only the lower order byte since shifting
9453 more that 32 bits make no sense anyway, ( the
9454 largest size of an object can be only 32 bits ) */
9457 MOVB (aopGet (right, 0, FALSE, FALSE));
9458 emitcode ("inc", "b");
9459 freeAsmop (right, NULL, ic, TRUE);
9460 aopOp (left, ic, FALSE);
9461 aopOp (result, ic, FALSE);
9463 /* now move the left to the result if they are not the
9465 if (!sameRegs (AOP (left), AOP (result)) &&
9466 AOP_SIZE (result) > 1)
9468 size = AOP_SIZE (result);
9472 l = aopGet (left, offset, FALSE, TRUE);
9473 if (*l == '@' && IS_AOP_PREG (result))
9476 emitcode ("mov", "a,%s", l);
9477 aopPut (result, "a", offset);
9480 aopPut (result, l, offset);
9485 tlbl = newiTempLabel (NULL);
9486 tlbl1 = newiTempLabel (NULL);
9487 size = AOP_SIZE (result);
9490 /* if it is only one byte then */
9493 l = aopGet (left, 0, FALSE, FALSE);
9495 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9498 emitcode ("rrc", "a");
9500 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9502 aopPut (result, "a", 0);
9506 reAdjustPreg (AOP (result));
9507 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9512 l = aopGet (result, offset, FALSE, FALSE);
9514 emitcode ("rrc", "a");
9515 aopPut (result, "a", offset--);
9517 reAdjustPreg (AOP (result));
9520 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9524 freeAsmop (result, NULL, ic, TRUE);
9525 freeAsmop (left, NULL, ic, TRUE);
9528 /*-----------------------------------------------------------------*/
9529 /* emitPtrByteGet - emits code to get a byte into A through a */
9530 /* pointer register (R0, R1, or DPTR). The */
9531 /* original value of A can be preserved in B. */
9532 /*-----------------------------------------------------------------*/
9534 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9541 emitcode ("mov", "b,a");
9542 emitcode ("mov", "a,@%s", rname);
9547 emitcode ("mov", "b,a");
9548 emitcode ("movx", "a,@%s", rname);
9553 emitcode ("mov", "b,a");
9554 emitcode ("movx", "a,@dptr");
9559 emitcode ("mov", "b,a");
9560 emitcode ("clr", "a");
9561 emitcode ("movc", "a,@a+dptr");
9567 emitcode ("push", "b");
9568 emitcode ("push", "acc");
9570 emitcode ("lcall", "__gptrget");
9572 emitcode ("pop", "b");
9577 /*-----------------------------------------------------------------*/
9578 /* emitPtrByteSet - emits code to set a byte from src through a */
9579 /* pointer register (R0, R1, or DPTR). */
9580 /*-----------------------------------------------------------------*/
9582 emitPtrByteSet (char *rname, int p_type, char *src)
9591 emitcode ("mov", "@%s,a", rname);
9594 emitcode ("mov", "@%s,%s", rname, src);
9599 emitcode ("movx", "@%s,a", rname);
9604 emitcode ("movx", "@dptr,a");
9609 emitcode ("lcall", "__gptrput");
9614 /*-----------------------------------------------------------------*/
9615 /* genUnpackBits - generates code for unpacking bits */
9616 /*-----------------------------------------------------------------*/
9618 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9620 int offset = 0; /* result byte offset */
9621 int rsize; /* result size */
9622 int rlen = 0; /* remaining bitfield length */
9623 sym_link *etype; /* bitfield type information */
9624 int blen; /* bitfield length */
9625 int bstr; /* bitfield starting bit within byte */
9628 D(emitcode ("; genUnpackBits",""));
9630 etype = getSpec (operandType (result));
9631 rsize = getSize (operandType (result));
9632 blen = SPEC_BLEN (etype);
9633 bstr = SPEC_BSTR (etype);
9635 if (ifx && blen <= 8)
9637 emitPtrByteGet (rname, ptype, FALSE);
9640 SNPRINTF (buffer, sizeof(buffer),
9642 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9647 emitcode ("anl", "a,#0x%02x",
9648 (((unsigned char) -1) >> (8 - blen)) << bstr);
9649 genIfxJump (ifx, "a", NULL, NULL, NULL);
9655 /* If the bitfield length is less than a byte */
9658 emitPtrByteGet (rname, ptype, FALSE);
9660 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9661 if (!SPEC_USIGN (etype))
9663 /* signed bitfield */
9664 symbol *tlbl = newiTempLabel (NULL);
9666 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9667 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9670 aopPut (result, "a", offset++);
9674 /* Bit field did not fit in a byte. Copy all
9675 but the partial byte at the end. */
9676 for (rlen=blen;rlen>=8;rlen-=8)
9678 emitPtrByteGet (rname, ptype, FALSE);
9679 aopPut (result, "a", offset++);
9681 emitcode ("inc", "%s", rname);
9684 /* Handle the partial byte at the end */
9687 emitPtrByteGet (rname, ptype, FALSE);
9688 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9689 if (!SPEC_USIGN (etype))
9691 /* signed bitfield */
9692 symbol *tlbl = newiTempLabel (NULL);
9694 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9695 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9698 aopPut (result, "a", offset++);
9706 if (SPEC_USIGN (etype))
9710 /* signed bitfield: sign extension with 0x00 or 0xff */
9711 emitcode ("rlc", "a");
9712 emitcode ("subb", "a,acc");
9718 aopPut (result, source, offset++);
9723 /*-----------------------------------------------------------------*/
9724 /* genDataPointerGet - generates code when ptr offset is known */
9725 /*-----------------------------------------------------------------*/
9727 genDataPointerGet (operand * left,
9733 int size, offset = 0;
9735 D (emitcode (";", "genDataPointerGet"));
9737 aopOp (result, ic, TRUE);
9739 /* get the string representation of the name */
9740 l = aopGet (left, 0, FALSE, TRUE);
9741 size = AOP_SIZE (result);
9746 SNPRINTF (buffer, sizeof(buffer),
9747 "(%s + %d)", l + 1, offset);
9751 SNPRINTF (buffer, sizeof(buffer),
9754 aopPut (result, buffer, offset++);
9757 freeAsmop (result, NULL, ic, TRUE);
9758 freeAsmop (left, NULL, ic, TRUE);
9761 /*-----------------------------------------------------------------*/
9762 /* genNearPointerGet - emitcode for near pointer fetch */
9763 /*-----------------------------------------------------------------*/
9765 genNearPointerGet (operand * left,
9774 sym_link *rtype, *retype;
9775 sym_link *ltype = operandType (left);
9778 D (emitcode (";", "genNearPointerGet"));
9780 rtype = operandType (result);
9781 retype = getSpec (rtype);
9783 aopOp (left, ic, FALSE);
9785 /* if left is rematerialisable and
9786 result is not bitfield variable type and
9787 the left is pointer to data space i.e
9788 lower 128 bytes of space */
9789 if (AOP_TYPE (left) == AOP_IMMD &&
9790 !IS_BITFIELD (retype) &&
9791 DCL_TYPE (ltype) == POINTER)
9793 genDataPointerGet (left, result, ic);
9797 /* if the value is already in a pointer register
9798 then don't need anything more */
9799 if (!AOP_INPREG (AOP (left)))
9801 if (IS_AOP_PREG (left))
9803 // Aha, it is a pointer, just in disguise.
9804 rname = aopGet (left, 0, FALSE, FALSE);
9807 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9808 __FILE__, __LINE__);
9813 emitcode ("mov", "a%s,%s", rname + 1, rname);
9814 rname++; // skip the '@'.
9819 /* otherwise get a free pointer register */
9821 preg = getFreePtr (ic, &aop, FALSE);
9822 emitcode ("mov", "%s,%s",
9824 aopGet (left, 0, FALSE, TRUE));
9829 rname = aopGet (left, 0, FALSE, FALSE);
9831 //aopOp (result, ic, FALSE);
9832 aopOp (result, ic, result?TRUE:FALSE);
9834 /* if bitfield then unpack the bits */
9835 if (IS_BITFIELD (retype))
9836 genUnpackBits (result, rname, POINTER, ifx);
9839 /* we have can just get the values */
9840 int size = AOP_SIZE (result);
9845 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9848 emitcode ("mov", "a,@%s", rname);
9850 aopPut (result, "a", offset);
9854 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9855 aopPut (result, buffer, offset);
9859 emitcode ("inc", "%s", rname);
9863 /* now some housekeeping stuff */
9864 if (aop) /* we had to allocate for this iCode */
9866 if (pi) { /* post increment present */
9867 aopPut (left, rname, 0);
9869 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9873 /* we did not allocate which means left
9874 already in a pointer register, then
9875 if size > 0 && this could be used again
9876 we have to point it back to where it
9878 if ((AOP_SIZE (result) > 1 &&
9879 !OP_SYMBOL (left)->remat &&
9880 (OP_SYMBOL (left)->liveTo > ic->seq ||
9884 int size = AOP_SIZE (result) - 1;
9886 emitcode ("dec", "%s", rname);
9890 if (ifx && !ifx->generated)
9892 genIfxJump (ifx, "a", left, NULL, result);
9896 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9897 freeAsmop (left, NULL, ic, TRUE);
9898 if (pi) pi->generated = 1;
9901 /*-----------------------------------------------------------------*/
9902 /* genPagedPointerGet - emitcode for paged pointer fetch */
9903 /*-----------------------------------------------------------------*/
9905 genPagedPointerGet (operand * left,
9914 sym_link *rtype, *retype;
9916 D (emitcode (";", "genPagedPointerGet"));
9918 rtype = operandType (result);
9919 retype = getSpec (rtype);
9921 aopOp (left, ic, FALSE);
9923 /* if the value is already in a pointer register
9924 then don't need anything more */
9925 if (!AOP_INPREG (AOP (left)))
9927 /* otherwise get a free pointer register */
9929 preg = getFreePtr (ic, &aop, FALSE);
9930 emitcode ("mov", "%s,%s",
9932 aopGet (left, 0, FALSE, TRUE));
9936 rname = aopGet (left, 0, FALSE, FALSE);
9938 aopOp (result, ic, FALSE);
9940 /* if bitfield then unpack the bits */
9941 if (IS_BITFIELD (retype))
9942 genUnpackBits (result, rname, PPOINTER, ifx);
9945 /* we have can just get the values */
9946 int size = AOP_SIZE (result);
9952 emitcode ("movx", "a,@%s", rname);
9954 aopPut (result, "a", offset);
9959 emitcode ("inc", "%s", rname);
9963 /* now some housekeeping stuff */
9964 if (aop) /* we had to allocate for this iCode */
9967 aopPut (left, rname, 0);
9968 freeAsmop (NULL, aop, ic, TRUE);
9972 /* we did not allocate which means left
9973 already in a pointer register, then
9974 if size > 0 && this could be used again
9975 we have to point it back to where it
9977 if ((AOP_SIZE (result) > 1 &&
9978 !OP_SYMBOL (left)->remat &&
9979 (OP_SYMBOL (left)->liveTo > ic->seq ||
9983 int size = AOP_SIZE (result) - 1;
9985 emitcode ("dec", "%s", rname);
9989 if (ifx && !ifx->generated)
9991 genIfxJump (ifx, "a", left, NULL, result);
9995 freeAsmop (result, NULL, ic, TRUE);
9996 freeAsmop (left, NULL, ic, TRUE);
9997 if (pi) pi->generated = 1;
10000 /*--------------------------------------------------------------------*/
10001 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10002 /*--------------------------------------------------------------------*/
10004 loadDptrFromOperand (operand *op, bool loadBToo)
10006 if (AOP_TYPE (op) != AOP_STR)
10008 /* if this is rematerializable */
10009 if (AOP_TYPE (op) == AOP_IMMD)
10011 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10014 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10015 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10018 wassertl(FALSE, "need pointerCode");
10019 emitcode ("", "; mov b,???");
10020 /* genPointerGet and genPointerSet originally did different
10021 ** things for this case. Both seem wrong.
10022 ** from genPointerGet:
10023 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10024 ** from genPointerSet:
10025 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10030 else if (AOP_TYPE (op) == AOP_DPTR)
10034 MOVA (aopGet (op, 0, FALSE, FALSE));
10035 emitcode ("push", "acc");
10036 MOVA (aopGet (op, 1, FALSE, FALSE));
10037 emitcode ("push", "acc");
10038 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10039 emitcode ("pop", "dph");
10040 emitcode ("pop", "dpl");
10044 MOVA (aopGet (op, 0, FALSE, FALSE));
10045 emitcode ("push", "acc");
10046 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10047 emitcode ("pop", "dpl");
10051 { /* we need to get it byte by byte */
10052 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10053 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10055 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerGet - get value from far space */
10062 /*-----------------------------------------------------------------*/
10064 genFarPointerGet (operand * left,
10065 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10068 sym_link *retype = getSpec (operandType (result));
10070 D (emitcode (";", "genFarPointerGet"));
10072 aopOp (left, ic, FALSE);
10073 loadDptrFromOperand (left, FALSE);
10075 /* so dptr now contains the address */
10076 aopOp (result, ic, FALSE);
10078 /* if bit then unpack */
10079 if (IS_BITFIELD (retype))
10080 genUnpackBits (result, "dptr", FPOINTER, ifx);
10083 size = AOP_SIZE (result);
10088 emitcode ("movx", "a,@dptr");
10090 aopPut (result, "a", offset++);
10092 emitcode ("inc", "dptr");
10096 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10098 aopPut (left, "dpl", 0);
10099 aopPut (left, "dph", 1);
10103 if (ifx && !ifx->generated)
10105 genIfxJump (ifx, "a", left, NULL, result);
10108 freeAsmop (result, NULL, ic, TRUE);
10109 freeAsmop (left, NULL, ic, TRUE);
10112 /*-----------------------------------------------------------------*/
10113 /* genCodePointerGet - get value from code space */
10114 /*-----------------------------------------------------------------*/
10116 genCodePointerGet (operand * left,
10117 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10120 sym_link *retype = getSpec (operandType (result));
10122 D (emitcode (";", "genCodePointerGet"));
10124 aopOp (left, ic, FALSE);
10125 loadDptrFromOperand (left, FALSE);
10127 /* so dptr now contains the address */
10128 aopOp (result, ic, FALSE);
10130 /* if bit then unpack */
10131 if (IS_BITFIELD (retype))
10132 genUnpackBits (result, "dptr", CPOINTER, ifx);
10135 size = AOP_SIZE (result);
10140 emitcode ("clr", "a");
10141 emitcode ("movc", "a,@a+dptr");
10143 aopPut (result, "a", offset++);
10145 emitcode ("inc", "dptr");
10149 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10151 aopPut (left, "dpl", 0);
10152 aopPut (left, "dph", 1);
10156 if (ifx && !ifx->generated)
10158 genIfxJump (ifx, "a", left, NULL, result);
10161 freeAsmop (result, NULL, ic, TRUE);
10162 freeAsmop (left, NULL, ic, TRUE);
10165 /*-----------------------------------------------------------------*/
10166 /* genGenPointerGet - get value from generic pointer space */
10167 /*-----------------------------------------------------------------*/
10169 genGenPointerGet (operand * left,
10170 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10173 sym_link *retype = getSpec (operandType (result));
10175 D (emitcode (";", "genGenPointerGet"));
10177 aopOp (left, ic, FALSE);
10178 loadDptrFromOperand (left, TRUE);
10180 /* so dptr now contains the address */
10181 aopOp (result, ic, FALSE);
10183 /* if bit then unpack */
10184 if (IS_BITFIELD (retype))
10186 genUnpackBits (result, "dptr", GPOINTER, ifx);
10190 size = AOP_SIZE (result);
10195 emitcode ("lcall", "__gptrget");
10197 aopPut (result, "a", offset++);
10199 emitcode ("inc", "dptr");
10203 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10205 aopPut (left, "dpl", 0);
10206 aopPut (left, "dph", 1);
10210 if (ifx && !ifx->generated)
10212 genIfxJump (ifx, "a", left, NULL, result);
10215 freeAsmop (result, NULL, ic, TRUE);
10216 freeAsmop (left, NULL, ic, TRUE);
10219 /*-----------------------------------------------------------------*/
10220 /* genPointerGet - generate code for pointer get */
10221 /*-----------------------------------------------------------------*/
10223 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10225 operand *left, *result;
10226 sym_link *type, *etype;
10229 D (emitcode (";", "genPointerGet"));
10231 left = IC_LEFT (ic);
10232 result = IC_RESULT (ic);
10234 if (getSize (operandType (result))>1)
10237 /* depending on the type of pointer we need to
10238 move it to the correct pointer register */
10239 type = operandType (left);
10240 etype = getSpec (type);
10241 /* if left is of type of pointer then it is simple */
10242 if (IS_PTR (type) && !IS_FUNC (type->next))
10243 p_type = DCL_TYPE (type);
10246 /* we have to go by the storage class */
10247 p_type = PTR_TYPE (SPEC_OCLS (etype));
10250 /* special case when cast remat */
10251 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10252 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10254 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10255 type = operandType (left);
10256 p_type = DCL_TYPE (type);
10258 /* now that we have the pointer type we assign
10259 the pointer values */
10265 genNearPointerGet (left, result, ic, pi, ifx);
10269 genPagedPointerGet (left, result, ic, pi, ifx);
10273 genFarPointerGet (left, result, ic, pi, ifx);
10277 genCodePointerGet (left, result, ic, pi, ifx);
10281 genGenPointerGet (left, result, ic, pi, ifx);
10287 /*-----------------------------------------------------------------*/
10288 /* genPackBits - generates code for packed bit storage */
10289 /*-----------------------------------------------------------------*/
10291 genPackBits (sym_link * etype,
10293 char *rname, int p_type)
10295 int offset = 0; /* source byte offset */
10296 int rlen = 0; /* remaining bitfield length */
10297 int blen; /* bitfield length */
10298 int bstr; /* bitfield starting bit within byte */
10299 int litval; /* source literal value (if AOP_LIT) */
10300 unsigned char mask; /* bitmask within current byte */
10302 D(emitcode ("; genPackBits",""));
10304 blen = SPEC_BLEN (etype);
10305 bstr = SPEC_BSTR (etype);
10307 /* If the bitfield length is less than a byte */
10310 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10311 (unsigned char) (0xFF >> (8 - bstr)));
10313 if (AOP_TYPE (right) == AOP_LIT)
10315 /* Case with a bitfield length <8 and literal source
10317 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10319 litval &= (~mask) & 0xff;
10320 emitPtrByteGet (rname, p_type, FALSE);
10321 if ((mask|litval)!=0xff)
10322 emitcode ("anl","a,#0x%02x", mask);
10324 emitcode ("orl","a,#0x%02x", litval);
10328 if ((blen==1) && (p_type!=GPOINTER))
10330 /* Case with a bitfield length == 1 and no generic pointer
10332 if (AOP_TYPE (right) == AOP_CRY)
10333 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10336 MOVA (aopGet (right, 0, FALSE, FALSE));
10337 emitcode ("rrc","a");
10339 emitPtrByteGet (rname, p_type, FALSE);
10340 emitcode ("mov","acc.%d,c",bstr);
10345 /* Case with a bitfield length < 8 and arbitrary source
10347 MOVA (aopGet (right, 0, FALSE, FALSE));
10348 /* shift and mask source value */
10350 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10352 pushedB = pushB ();
10353 /* transfer A to B and get next byte */
10354 emitPtrByteGet (rname, p_type, TRUE);
10356 emitcode ("anl", "a,#0x%02x", mask);
10357 emitcode ("orl", "a,b");
10358 if (p_type == GPOINTER)
10359 emitcode ("pop", "b");
10365 emitPtrByteSet (rname, p_type, "a");
10369 /* Bit length is greater than 7 bits. In this case, copy */
10370 /* all except the partial byte at the end */
10371 for (rlen=blen;rlen>=8;rlen-=8)
10373 emitPtrByteSet (rname, p_type,
10374 aopGet (right, offset++, FALSE, TRUE) );
10376 emitcode ("inc", "%s", rname);
10379 /* If there was a partial byte at the end */
10382 mask = (((unsigned char) -1 << rlen) & 0xff);
10384 if (AOP_TYPE (right) == AOP_LIT)
10386 /* Case with partial byte and literal source
10388 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389 litval >>= (blen-rlen);
10390 litval &= (~mask) & 0xff;
10391 emitPtrByteGet (rname, p_type, FALSE);
10392 if ((mask|litval)!=0xff)
10393 emitcode ("anl","a,#0x%02x", mask);
10395 emitcode ("orl","a,#0x%02x", litval);
10400 /* Case with partial byte and arbitrary source
10402 MOVA (aopGet (right, offset++, FALSE, FALSE));
10403 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10405 pushedB = pushB ();
10406 /* transfer A to B and get next byte */
10407 emitPtrByteGet (rname, p_type, TRUE);
10409 emitcode ("anl", "a,#0x%02x", mask);
10410 emitcode ("orl", "a,b");
10411 if (p_type == GPOINTER)
10412 emitcode ("pop", "b");
10416 emitPtrByteSet (rname, p_type, "a");
10421 /*-----------------------------------------------------------------*/
10422 /* genDataPointerSet - remat pointer to data space */
10423 /*-----------------------------------------------------------------*/
10425 genDataPointerSet (operand * right,
10429 int size, offset = 0;
10430 char *l, buffer[256];
10432 D (emitcode (";", "genDataPointerSet"));
10434 aopOp (right, ic, FALSE);
10436 l = aopGet (result, 0, FALSE, TRUE);
10437 size = AOP_SIZE (right);
10441 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10443 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10444 emitcode ("mov", "%s,%s", buffer,
10445 aopGet (right, offset++, FALSE, FALSE));
10448 freeAsmop (result, NULL, ic, TRUE);
10449 freeAsmop (right, NULL, ic, TRUE);
10452 /*-----------------------------------------------------------------*/
10453 /* genNearPointerSet - emitcode for near pointer put */
10454 /*-----------------------------------------------------------------*/
10456 genNearPointerSet (operand * right,
10464 sym_link *retype, *letype;
10465 sym_link *ptype = operandType (result);
10467 D (emitcode (";", "genNearPointerSet"));
10469 retype = getSpec (operandType (right));
10470 letype = getSpec (ptype);
10472 aopOp (result, ic, FALSE);
10474 /* if the result is rematerializable &
10475 in data space & not a bit variable */
10476 if (AOP_TYPE (result) == AOP_IMMD &&
10477 DCL_TYPE (ptype) == POINTER &&
10478 !IS_BITVAR (retype) &&
10479 !IS_BITVAR (letype))
10481 genDataPointerSet (right, result, ic);
10485 /* if the value is already in a pointer register
10486 then don't need anything more */
10487 if (!AOP_INPREG (AOP (result)))
10490 //AOP_TYPE (result) == AOP_STK
10491 IS_AOP_PREG(result)
10494 // Aha, it is a pointer, just in disguise.
10495 rname = aopGet (result, 0, FALSE, FALSE);
10498 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10499 __FILE__, __LINE__);
10504 emitcode ("mov", "a%s,%s", rname + 1, rname);
10505 rname++; // skip the '@'.
10510 /* otherwise get a free pointer register */
10511 aop = newAsmop (0);
10512 preg = getFreePtr (ic, &aop, FALSE);
10513 emitcode ("mov", "%s,%s",
10515 aopGet (result, 0, FALSE, TRUE));
10516 rname = preg->name;
10521 rname = aopGet (result, 0, FALSE, FALSE);
10524 aopOp (right, ic, FALSE);
10526 /* if bitfield then unpack the bits */
10527 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10528 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10531 /* we can just get the values */
10532 int size = AOP_SIZE (right);
10537 l = aopGet (right, offset, FALSE, TRUE);
10538 if ((*l == '@') || (strcmp (l, "acc") == 0))
10541 emitcode ("mov", "@%s,a", rname);
10544 emitcode ("mov", "@%s,%s", rname, l);
10546 emitcode ("inc", "%s", rname);
10551 /* now some housekeeping stuff */
10552 if (aop) /* we had to allocate for this iCode */
10555 aopPut (result, rname, 0);
10556 freeAsmop (NULL, aop, ic, TRUE);
10560 /* we did not allocate which means left
10561 already in a pointer register, then
10562 if size > 0 && this could be used again
10563 we have to point it back to where it
10565 if ((AOP_SIZE (right) > 1 &&
10566 !OP_SYMBOL (result)->remat &&
10567 (OP_SYMBOL (result)->liveTo > ic->seq ||
10571 int size = AOP_SIZE (right) - 1;
10573 emitcode ("dec", "%s", rname);
10578 if (pi) pi->generated = 1;
10579 freeAsmop (result, NULL, ic, TRUE);
10580 freeAsmop (right, NULL, ic, TRUE);
10583 /*-----------------------------------------------------------------*/
10584 /* genPagedPointerSet - emitcode for Paged pointer put */
10585 /*-----------------------------------------------------------------*/
10587 genPagedPointerSet (operand * right,
10595 sym_link *retype, *letype;
10597 D (emitcode (";", "genPagedPointerSet"));
10599 retype = getSpec (operandType (right));
10600 letype = getSpec (operandType (result));
10602 aopOp (result, ic, FALSE);
10604 /* if the value is already in a pointer register
10605 then don't need anything more */
10606 if (!AOP_INPREG (AOP (result)))
10608 /* otherwise get a free pointer register */
10609 aop = newAsmop (0);
10610 preg = getFreePtr (ic, &aop, FALSE);
10611 emitcode ("mov", "%s,%s",
10613 aopGet (result, 0, FALSE, TRUE));
10614 rname = preg->name;
10617 rname = aopGet (result, 0, FALSE, FALSE);
10619 aopOp (right, ic, FALSE);
10621 /* if bitfield then unpack the bits */
10622 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10623 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10626 /* we have can just get the values */
10627 int size = AOP_SIZE (right);
10632 l = aopGet (right, offset, FALSE, TRUE);
10634 emitcode ("movx", "@%s,a", rname);
10637 emitcode ("inc", "%s", rname);
10643 /* now some housekeeping stuff */
10644 if (aop) /* we had to allocate for this iCode */
10647 aopPut (result, rname, 0);
10648 freeAsmop (NULL, aop, ic, TRUE);
10652 /* we did not allocate which means left
10653 already in a pointer register, then
10654 if size > 0 && this could be used again
10655 we have to point it back to where it
10657 if (AOP_SIZE (right) > 1 &&
10658 !OP_SYMBOL (result)->remat &&
10659 (OP_SYMBOL (result)->liveTo > ic->seq ||
10662 int size = AOP_SIZE (right) - 1;
10664 emitcode ("dec", "%s", rname);
10669 if (pi) pi->generated = 1;
10670 freeAsmop (result, NULL, ic, TRUE);
10671 freeAsmop (right, NULL, ic, TRUE);
10674 /*-----------------------------------------------------------------*/
10675 /* genFarPointerSet - set value from far space */
10676 /*-----------------------------------------------------------------*/
10678 genFarPointerSet (operand * right,
10679 operand * result, iCode * ic, iCode * pi)
10682 sym_link *retype = getSpec (operandType (right));
10683 sym_link *letype = getSpec (operandType (result));
10685 D(emitcode ("; genFarPointerSet",""));
10687 aopOp (result, ic, FALSE);
10688 loadDptrFromOperand (result, FALSE);
10690 /* so dptr now contains the address */
10691 aopOp (right, ic, FALSE);
10693 /* if bit then unpack */
10694 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10695 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10698 size = AOP_SIZE (right);
10703 char *l = aopGet (right, offset++, FALSE, FALSE);
10705 emitcode ("movx", "@dptr,a");
10707 emitcode ("inc", "dptr");
10710 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10711 aopPut (result, "dpl", 0);
10712 aopPut (result, "dph", 1);
10715 freeAsmop (result, NULL, ic, TRUE);
10716 freeAsmop (right, NULL, ic, TRUE);
10719 /*-----------------------------------------------------------------*/
10720 /* genGenPointerSet - set value from generic pointer space */
10721 /*-----------------------------------------------------------------*/
10723 genGenPointerSet (operand * right,
10724 operand * result, iCode * ic, iCode * pi)
10727 sym_link *retype = getSpec (operandType (right));
10728 sym_link *letype = getSpec (operandType (result));
10730 D (emitcode (";", "genGenPointerSet"));
10732 aopOp (result, ic, FALSE);
10733 loadDptrFromOperand (result, TRUE);
10735 /* so dptr now contains the address */
10736 aopOp (right, ic, FALSE);
10738 /* if bit then unpack */
10739 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10741 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10745 size = AOP_SIZE (right);
10750 char *l = aopGet (right, offset++, FALSE, FALSE);
10752 emitcode ("lcall", "__gptrput");
10754 emitcode ("inc", "dptr");
10758 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10759 aopPut (result, "dpl", 0);
10760 aopPut (result, "dph", 1);
10763 freeAsmop (result, NULL, ic, TRUE);
10764 freeAsmop (right, NULL, ic, TRUE);
10767 /*-----------------------------------------------------------------*/
10768 /* genPointerSet - stores the value into a pointer location */
10769 /*-----------------------------------------------------------------*/
10771 genPointerSet (iCode * ic, iCode *pi)
10773 operand *right, *result;
10774 sym_link *type, *etype;
10777 D (emitcode (";", "genPointerSet"));
10779 right = IC_RIGHT (ic);
10780 result = IC_RESULT (ic);
10782 /* depending on the type of pointer we need to
10783 move it to the correct pointer register */
10784 type = operandType (result);
10785 etype = getSpec (type);
10786 /* if left is of type of pointer then it is simple */
10787 if (IS_PTR (type) && !IS_FUNC (type->next))
10789 p_type = DCL_TYPE (type);
10793 /* we have to go by the storage class */
10794 p_type = PTR_TYPE (SPEC_OCLS (etype));
10797 /* special case when cast remat */
10798 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10799 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10800 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10801 type = operandType (result);
10802 p_type = DCL_TYPE (type);
10805 /* now that we have the pointer type we assign
10806 the pointer values */
10812 genNearPointerSet (right, result, ic, pi);
10816 genPagedPointerSet (right, result, ic, pi);
10820 genFarPointerSet (right, result, ic, pi);
10824 genGenPointerSet (right, result, ic, pi);
10828 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10829 "genPointerSet: illegal pointer type");
10833 /*-----------------------------------------------------------------*/
10834 /* genIfx - generate code for Ifx statement */
10835 /*-----------------------------------------------------------------*/
10837 genIfx (iCode * ic, iCode * popIc)
10839 operand *cond = IC_COND (ic);
10843 D (emitcode (";", "genIfx"));
10845 aopOp (cond, ic, FALSE);
10847 /* get the value into acc */
10848 if (AOP_TYPE (cond) != AOP_CRY)
10855 if (AOP(cond)->aopu.aop_dir)
10856 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10859 /* the result is now in the accumulator or a directly addressable bit */
10860 freeAsmop (cond, NULL, ic, TRUE);
10862 /* if there was something to be popped then do it */
10866 /* if the condition is a bit variable */
10868 genIfxJump(ic, dup, NULL, NULL, NULL);
10869 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10870 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10871 else if (isbit && !IS_ITEMP (cond))
10872 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10874 genIfxJump (ic, "a", NULL, NULL, NULL);
10879 /*-----------------------------------------------------------------*/
10880 /* genAddrOf - generates code for address of */
10881 /*-----------------------------------------------------------------*/
10883 genAddrOf (iCode * ic)
10885 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10888 D (emitcode (";", "genAddrOf"));
10890 aopOp (IC_RESULT (ic), ic, FALSE);
10892 /* if the operand is on the stack then we
10893 need to get the stack offset of this
10897 /* if it has an offset then we need to compute it */
10900 int stack_offset = ((sym->stack < 0) ?
10901 ((char) (sym->stack - _G.nRegsSaved)) :
10902 ((char) sym->stack)) & 0xff;
10903 if ((abs(stack_offset) == 1) &&
10904 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10905 !isOperandVolatile (IC_RESULT (ic), FALSE))
10907 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10908 if (stack_offset > 0)
10909 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10911 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10915 emitcode ("mov", "a,%s", SYM_BP (sym));
10916 emitcode ("add", "a,#0x%02x", stack_offset);
10917 aopPut (IC_RESULT (ic), "a", 0);
10922 /* we can just move _bp */
10923 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10925 /* fill the result with zero */
10926 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10931 aopPut (IC_RESULT (ic), zero, offset++);
10936 /* object not on stack then we need the name */
10937 size = AOP_SIZE (IC_RESULT (ic));
10942 char s[SDCC_NAME_MAX];
10944 sprintf (s, "#(%s >> %d)",
10948 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10949 aopPut (IC_RESULT (ic), s, offset++);
10953 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10957 /*-----------------------------------------------------------------*/
10958 /* genFarFarAssign - assignment when both are in far space */
10959 /*-----------------------------------------------------------------*/
10961 genFarFarAssign (operand * result, operand * right, iCode * ic)
10963 int size = AOP_SIZE (right);
10967 D (emitcode (";", "genFarFarAssign"));
10969 /* first push the right side on to the stack */
10972 l = aopGet (right, offset++, FALSE, FALSE);
10974 emitcode ("push", "acc");
10977 freeAsmop (right, NULL, ic, FALSE);
10978 /* now assign DPTR to result */
10979 aopOp (result, ic, FALSE);
10980 size = AOP_SIZE (result);
10983 emitcode ("pop", "acc");
10984 aopPut (result, "a", --offset);
10986 freeAsmop (result, NULL, ic, FALSE);
10989 /*-----------------------------------------------------------------*/
10990 /* genAssign - generate code for assignment */
10991 /*-----------------------------------------------------------------*/
10993 genAssign (iCode * ic)
10995 operand *result, *right;
10997 unsigned long lit = 0L;
10999 D (emitcode (";", "genAssign"));
11001 result = IC_RESULT (ic);
11002 right = IC_RIGHT (ic);
11004 /* if they are the same */
11005 if (operandsEqu (result, right) &&
11006 !isOperandVolatile (result, FALSE) &&
11007 !isOperandVolatile (right, FALSE))
11010 aopOp (right, ic, FALSE);
11012 /* special case both in far space */
11013 if (AOP_TYPE (right) == AOP_DPTR &&
11014 IS_TRUE_SYMOP (result) &&
11015 isOperandInFarSpace (result))
11017 genFarFarAssign (result, right, ic);
11021 aopOp (result, ic, TRUE);
11023 /* if they are the same registers */
11024 if (sameRegs (AOP (right), AOP (result)) &&
11025 !isOperandVolatile (result, FALSE) &&
11026 !isOperandVolatile (right, FALSE))
11029 /* if the result is a bit */
11030 if (AOP_TYPE (result) == AOP_CRY)
11032 /* if the right size is a literal then
11033 we know what the value is */
11034 if (AOP_TYPE (right) == AOP_LIT)
11036 if (((int) operandLitValue (right)))
11037 aopPut (result, one, 0);
11039 aopPut (result, zero, 0);
11043 /* the right is also a bit variable */
11044 if (AOP_TYPE (right) == AOP_CRY)
11046 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11047 aopPut (result, "c", 0);
11051 /* we need to or */
11053 aopPut (result, "a", 0);
11057 /* bit variables done */
11059 size = AOP_SIZE (result);
11061 if (AOP_TYPE (right) == AOP_LIT)
11062 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11065 (AOP_TYPE (result) != AOP_REG) &&
11066 (AOP_TYPE (right) == AOP_LIT) &&
11067 !IS_FLOAT (operandType (right)) &&
11070 while ((size) && (lit))
11073 aopGet (right, offset, FALSE, FALSE),
11079 /* And now fill the rest with zeros. */
11082 emitcode ("clr", "a");
11086 aopPut (result, "a", offset);
11095 aopGet (right, offset, FALSE, FALSE),
11102 freeAsmop (result, NULL, ic, TRUE);
11103 freeAsmop (right, NULL, ic, TRUE);
11106 /*-----------------------------------------------------------------*/
11107 /* genJumpTab - generates code for jump table */
11108 /*-----------------------------------------------------------------*/
11110 genJumpTab (iCode * ic)
11112 symbol *jtab,*jtablo,*jtabhi;
11114 unsigned int count;
11116 D (emitcode (";", "genJumpTab"));
11118 count = elementsInSet( IC_JTLABELS (ic) );
11122 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11123 if the switch argument is in a register.
11124 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11125 /* Peephole may not convert ljmp to sjmp or ret
11126 labelIsReturnOnly & labelInRange must check
11127 currPl->ic->op != JUMPTABLE */
11128 aopOp (IC_JTCOND (ic), ic, FALSE);
11129 /* get the condition into accumulator */
11130 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11132 /* multiply by three */
11133 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11135 emitcode ("mov", "b,#3");
11136 emitcode ("mul", "ab");
11140 emitcode ("add", "a,acc");
11141 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11143 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11145 jtab = newiTempLabel (NULL);
11146 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11147 emitcode ("jmp", "@a+dptr");
11149 /* now generate the jump labels */
11150 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11151 jtab = setNextItem (IC_JTLABELS (ic)))
11152 emitcode ("ljmp", "%05d$", jtab->key + 100);
11156 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11157 if the switch argument is in a register.
11158 For n>6 this algorithm may be more compact */
11159 jtablo = newiTempLabel (NULL);
11160 jtabhi = newiTempLabel (NULL);
11162 /* get the condition into accumulator.
11163 Using b as temporary storage, if register push/pop is needed */
11164 aopOp (IC_JTCOND (ic), ic, FALSE);
11165 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11166 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11167 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11169 // (MB) what if B is in use???
11170 wassertl(!BINUSE, "B was in use");
11171 emitcode ("mov", "b,%s", l);
11174 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11178 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11179 emitcode ("movc", "a,@a+pc");
11180 emitcode ("push", "acc");
11183 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11184 emitcode ("movc", "a,@a+pc");
11185 emitcode ("push", "acc");
11189 /* this scales up to n<=255, but needs two more bytes
11190 and changes dptr */
11191 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11192 emitcode ("movc", "a,@a+dptr");
11193 emitcode ("push", "acc");
11196 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11197 emitcode ("movc", "a,@a+dptr");
11198 emitcode ("push", "acc");
11201 emitcode ("ret", "");
11203 /* now generate jump table, LSB */
11204 emitLabel (jtablo);
11205 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11206 jtab = setNextItem (IC_JTLABELS (ic)))
11207 emitcode (".db", "%05d$", jtab->key + 100);
11209 /* now generate jump table, MSB */
11210 emitLabel (jtabhi);
11211 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11212 jtab = setNextItem (IC_JTLABELS (ic)))
11213 emitcode (".db", "%05d$>>8", jtab->key + 100);
11217 /*-----------------------------------------------------------------*/
11218 /* genCast - gen code for casting */
11219 /*-----------------------------------------------------------------*/
11221 genCast (iCode * ic)
11223 operand *result = IC_RESULT (ic);
11224 sym_link *ctype = operandType (IC_LEFT (ic));
11225 sym_link *rtype = operandType (IC_RIGHT (ic));
11226 operand *right = IC_RIGHT (ic);
11229 D (emitcode (";", "genCast"));
11231 /* if they are equivalent then do nothing */
11232 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11235 aopOp (right, ic, FALSE);
11236 aopOp (result, ic, FALSE);
11238 /* if the result is a bit (and not a bitfield) */
11239 if (IS_BIT (OP_SYMBOL (result)->type))
11241 /* if the right size is a literal then
11242 we know what the value is */
11243 if (AOP_TYPE (right) == AOP_LIT)
11245 if (((int) operandLitValue (right)))
11246 aopPut (result, one, 0);
11248 aopPut (result, zero, 0);
11253 /* the right is also a bit variable */
11254 if (AOP_TYPE (right) == AOP_CRY)
11256 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11257 aopPut (result, "c", 0);
11261 /* we need to or */
11263 aopPut (result, "a", 0);
11267 /* if they are the same size : or less */
11268 if (AOP_SIZE (result) <= AOP_SIZE (right))
11271 /* if they are in the same place */
11272 if (sameRegs (AOP (right), AOP (result)))
11275 /* if they in different places then copy */
11276 size = AOP_SIZE (result);
11281 aopGet (right, offset, FALSE, FALSE),
11288 /* if the result is of type pointer */
11289 if (IS_PTR (ctype))
11293 sym_link *type = operandType (right);
11294 sym_link *etype = getSpec (type);
11296 /* pointer to generic pointer */
11297 if (IS_GENPTR (ctype))
11301 p_type = DCL_TYPE (type);
11305 if (SPEC_SCLS(etype)==S_REGISTER) {
11306 // let's assume it is a generic pointer
11309 /* we have to go by the storage class */
11310 p_type = PTR_TYPE (SPEC_OCLS (etype));
11314 /* the first two bytes are known */
11315 size = GPTRSIZE - 1;
11320 aopGet (right, offset, FALSE, FALSE),
11324 /* the last byte depending on type */
11326 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11331 // pointerTypeToGPByte will have bitched.
11335 sprintf(gpValStr, "#0x%x", gpVal);
11336 aopPut (result, gpValStr, GPTRSIZE - 1);
11341 /* just copy the pointers */
11342 size = AOP_SIZE (result);
11347 aopGet (right, offset, FALSE, FALSE),
11354 /* so we now know that the size of destination is greater
11355 than the size of the source */
11356 /* we move to result for the size of source */
11357 size = AOP_SIZE (right);
11362 aopGet (right, offset, FALSE, FALSE),
11367 /* now depending on the sign of the source && destination */
11368 size = AOP_SIZE (result) - AOP_SIZE (right);
11369 /* if unsigned or not an integral type */
11370 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11373 aopPut (result, zero, offset++);
11377 /* we need to extend the sign :{ */
11378 char *l = aopGet (right, AOP_SIZE (right) - 1,
11381 emitcode ("rlc", "a");
11382 emitcode ("subb", "a,acc");
11384 aopPut (result, "a", offset++);
11387 /* we are done hurray !!!! */
11390 freeAsmop (result, NULL, ic, TRUE);
11391 freeAsmop (right, NULL, ic, TRUE);
11394 /*-----------------------------------------------------------------*/
11395 /* genDjnz - generate decrement & jump if not zero instrucion */
11396 /*-----------------------------------------------------------------*/
11398 genDjnz (iCode * ic, iCode * ifx)
11400 symbol *lbl, *lbl1;
11404 /* if the if condition has a false label
11405 then we cannot save */
11406 if (IC_FALSE (ifx))
11409 /* if the minus is not of the form a = a - 1 */
11410 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11411 !IS_OP_LITERAL (IC_RIGHT (ic)))
11414 if (operandLitValue (IC_RIGHT (ic)) != 1)
11417 /* if the size of this greater than one then no
11419 if (getSize (operandType (IC_RESULT (ic))) > 1)
11422 /* otherwise we can save BIG */
11424 D (emitcode (";", "genDjnz"));
11426 lbl = newiTempLabel (NULL);
11427 lbl1 = newiTempLabel (NULL);
11429 aopOp (IC_RESULT (ic), ic, FALSE);
11431 if (AOP_NEEDSACC(IC_RESULT(ic)))
11433 /* If the result is accessed indirectly via
11434 * the accumulator, we must explicitly write
11435 * it back after the decrement.
11437 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11439 if (strcmp(rByte, "a"))
11441 /* Something is hopelessly wrong */
11442 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11443 __FILE__, __LINE__);
11444 /* We can just give up; the generated code will be inefficient,
11445 * but what the hey.
11447 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11450 emitcode ("dec", "%s", rByte);
11451 aopPut (IC_RESULT (ic), rByte, 0);
11452 emitcode ("jnz", "%05d$", lbl->key + 100);
11454 else if (IS_AOP_PREG (IC_RESULT (ic)))
11456 emitcode ("dec", "%s",
11457 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11458 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11459 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11460 ifx->generated = 1;
11461 emitcode ("jnz", "%05d$", lbl->key + 100);
11465 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11468 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11470 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11473 if (!ifx->generated)
11474 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11475 ifx->generated = 1;
11479 /*-----------------------------------------------------------------*/
11480 /* genReceive - generate code for a receive iCode */
11481 /*-----------------------------------------------------------------*/
11483 genReceive (iCode * ic)
11485 int size = getSize (operandType (IC_RESULT (ic)));
11488 D (emitcode (";", "genReceive"));
11490 if (ic->argreg == 1)
11491 { /* first parameter */
11492 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11493 isOperandInPagedSpace (IC_RESULT (ic))) &&
11494 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11495 IS_TRUE_SYMOP (IC_RESULT (ic))))
11498 int receivingA = 0;
11501 for (offset = 0; offset<size; offset++)
11502 if (!strcmp (fReturn[offset], "a"))
11507 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11509 for (offset = size-1; offset>0; offset--)
11510 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11511 emitcode("mov","a,%s", fReturn[0]);
11513 aopOp (IC_RESULT (ic), ic, FALSE);
11515 aopPut (IC_RESULT (ic), "a", offset);
11516 for (offset = 1; offset<size; offset++)
11517 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11523 if (getTempRegs(tempRegs, size, ic))
11525 for (offset = 0; offset<size; offset++)
11526 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11527 aopOp (IC_RESULT (ic), ic, FALSE);
11528 for (offset = 0; offset<size; offset++)
11529 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11534 offset = fReturnSizeMCS51 - size;
11537 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11538 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11541 aopOp (IC_RESULT (ic), ic, FALSE);
11542 size = AOP_SIZE (IC_RESULT (ic));
11546 emitcode ("pop", "acc");
11547 aopPut (IC_RESULT (ic), "a", offset++);
11553 aopOp (IC_RESULT (ic), ic, FALSE);
11555 assignResultValue (IC_RESULT (ic), NULL);
11558 else if (ic->argreg > 12)
11559 { /* bit parameters */
11560 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11562 aopOp (IC_RESULT (ic), ic, FALSE);
11563 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11564 outBitC(IC_RESULT (ic));
11568 { /* other parameters */
11570 aopOp (IC_RESULT (ic), ic, FALSE);
11571 rb1off = ic->argreg;
11574 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11579 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11582 /*-----------------------------------------------------------------*/
11583 /* genDummyRead - generate code for dummy read of volatiles */
11584 /*-----------------------------------------------------------------*/
11586 genDummyRead (iCode * ic)
11591 D (emitcode(";", "genDummyRead"));
11593 op = IC_RIGHT (ic);
11594 if (op && IS_SYMOP (op))
11596 aopOp (op, ic, FALSE);
11598 /* if the result is a bit */
11599 if (AOP_TYPE (op) == AOP_CRY)
11600 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11603 /* bit variables done */
11605 size = AOP_SIZE (op);
11609 MOVA (aopGet (op, offset, FALSE, FALSE));
11614 freeAsmop (op, NULL, ic, TRUE);
11618 if (op && IS_SYMOP (op))
11620 aopOp (op, ic, FALSE);
11622 /* if the result is a bit */
11623 if (AOP_TYPE (op) == AOP_CRY)
11624 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11627 /* bit variables done */
11629 size = AOP_SIZE (op);
11633 MOVA (aopGet (op, offset, FALSE, FALSE));
11638 freeAsmop (op, NULL, ic, TRUE);
11642 /*-----------------------------------------------------------------*/
11643 /* genCritical - generate code for start of a critical sequence */
11644 /*-----------------------------------------------------------------*/
11646 genCritical (iCode *ic)
11648 symbol *tlbl = newiTempLabel (NULL);
11650 D (emitcode(";", "genCritical"));
11652 if (IC_RESULT (ic))
11654 aopOp (IC_RESULT (ic), ic, TRUE);
11655 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11656 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11657 aopPut (IC_RESULT (ic), zero, 0);
11659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11663 emitcode ("setb", "c");
11664 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11665 emitcode ("clr", "c");
11667 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11671 /*-----------------------------------------------------------------*/
11672 /* genEndCritical - generate code for end of a critical sequence */
11673 /*-----------------------------------------------------------------*/
11675 genEndCritical (iCode *ic)
11677 D(emitcode("; genEndCritical",""));
11681 aopOp (IC_RIGHT (ic), ic, FALSE);
11682 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11684 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11685 emitcode ("mov", "ea,c");
11689 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11690 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11691 emitcode ("rrc", "a");
11692 emitcode ("mov", "ea,c");
11694 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11698 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11699 emitcode ("mov", "ea,c");
11703 /*-----------------------------------------------------------------*/
11704 /* gen51Code - generate code for 8051 based controllers */
11705 /*-----------------------------------------------------------------*/
11707 gen51Code (iCode * lic)
11711 /* int cseq = 0; */
11713 _G.currentFunc = NULL;
11714 lineHead = lineCurr = NULL;
11716 /* print the allocation information */
11717 if (allocInfo && currFunc)
11718 printAllocInfo (currFunc, codeOutFile);
11719 /* if debug information required */
11720 if (options.debug && currFunc)
11722 debugFile->writeFunction (currFunc, lic);
11724 /* stack pointer name */
11725 if (options.useXstack)
11731 for (ic = lic; ic; ic = ic->next)
11733 _G.current_iCode = ic;
11735 if (ic->lineno && cln != ic->lineno)
11739 debugFile->writeCLine (ic);
11741 if (!options.noCcodeInAsm) {
11742 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11743 printCLine(ic->filename, ic->lineno));
11748 if (ic->seqPoint && ic->seqPoint != cseq)
11750 emitcode ("", "; sequence point %d", ic->seqPoint);
11751 cseq = ic->seqPoint;
11754 if (options.iCodeInAsm) {
11755 char regsInUse[80];
11759 for (i=0; i<8; i++) {
11760 sprintf (®sInUse[i],
11761 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11764 strcpy (regsInUse, "--------");
11765 for (i=0; i < 8; i++) {
11766 if (bitVectBitValue (ic->rMask, i))
11768 int offset = regs8051[i].offset;
11769 regsInUse[offset] = offset + '0'; /* show rMask */
11773 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11775 /* if the result is marked as
11776 spilt and rematerializable or code for
11777 this has already been generated then
11779 if (resultRemat (ic) || ic->generated)
11782 /* depending on the operation */
11802 /* IPOP happens only when trying to restore a
11803 spilt live range, if there is an ifx statement
11804 following this pop then the if statement might
11805 be using some of the registers being popped which
11806 would destory the contents of the register so
11807 we need to check for this condition and handle it */
11809 ic->next->op == IFX &&
11810 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11811 genIfx (ic->next, ic);
11829 genEndFunction (ic);
11849 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11866 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11870 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11877 /* note these two are xlated by algebraic equivalence
11878 in decorateType() in SDCCast.c */
11879 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11880 "got '>=' or '<=' shouldn't have come here");
11884 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11896 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11900 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11904 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11940 genRightShift (ic);
11943 case GET_VALUE_AT_ADDRESS:
11945 hasInc (IC_LEFT (ic), ic,
11946 getSize (operandType (IC_RESULT (ic)))),
11947 ifxForOp (IC_RESULT (ic), ic) );
11951 if (POINTER_SET (ic))
11953 hasInc (IC_RESULT (ic), ic,
11954 getSize (operandType (IC_RIGHT (ic)))));
11980 addSet (&_G.sendSet, ic);
11983 case DUMMY_READ_VOLATILE:
11992 genEndCritical (ic);
12004 _G.current_iCode = NULL;
12006 /* now we are ready to call the
12007 peep hole optimizer */
12008 if (!options.nopeep)
12009 peepHole (&lineHead);
12011 /* now do the actual printing */
12012 printLine (lineHead, codeOutFile);