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 || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4089 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4090 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4098 /* If the next instruction is a goto and the goto target
4099 * is < 10 instructions previous to this, we can generate
4100 * jumps straight to that target.
4102 if (ic->next && ic->next->op == GOTO
4103 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4104 && labelRange <= 10)
4106 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4107 tlbl = IC_LABEL (ic->next);
4112 tlbl = newiTempLabel (NULL);
4115 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4116 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4117 IS_AOP_PREG (IC_RESULT (ic)))
4118 emitcode ("cjne", "%s,#0x00,%05d$",
4119 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4123 emitcode ("clr", "a");
4124 emitcode ("cjne", "a,%s,%05d$",
4125 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4129 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4133 IS_AOP_PREG (IC_RESULT (ic)))
4134 emitcode ("cjne", "%s,#0x00,%05d$",
4135 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4138 emitcode ("cjne", "a,%s,%05d$",
4139 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4142 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4146 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4147 IS_AOP_PREG (IC_RESULT (ic)))
4148 emitcode ("cjne", "%s,#0x00,%05d$",
4149 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4153 emitcode ("cjne", "a,%s,%05d$",
4154 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4157 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4167 /* if result is dptr */
4168 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4169 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4170 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4171 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4173 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4179 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4182 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4183 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4185 emitcode ("inc", "dptr");
4190 /* if the literal value of the right hand side
4191 is greater than 4 then it is not worth it */
4195 /* if the sizes are greater than 1 then we cannot */
4196 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4197 AOP_SIZE (IC_LEFT (ic)) > 1)
4200 /* we can if the aops of the left & result match or
4201 if they are in registers and the registers are the
4203 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4207 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4208 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4209 aopPut (IC_RESULT (ic), "a", 0);
4215 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4225 /*-----------------------------------------------------------------*/
4226 /* outBitAcc - output a bit in acc */
4227 /*-----------------------------------------------------------------*/
4229 outBitAcc (operand * result)
4231 symbol *tlbl = newiTempLabel (NULL);
4232 /* if the result is a bit */
4233 if (AOP_TYPE (result) == AOP_CRY)
4235 aopPut (result, "a", 0);
4239 emitcode ("jz", "%05d$", tlbl->key + 100);
4240 emitcode ("mov", "a,%s", one);
4246 /*-----------------------------------------------------------------*/
4247 /* genPlusBits - generates code for addition of two bits */
4248 /*-----------------------------------------------------------------*/
4250 genPlusBits (iCode * ic)
4252 D (emitcode (";", "genPlusBits"));
4254 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4256 symbol *lbl = newiTempLabel (NULL);
4257 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4258 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4259 emitcode ("cpl", "c");
4261 outBitC (IC_RESULT (ic));
4265 emitcode ("clr", "a");
4266 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267 emitcode ("rlc", "a");
4268 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4269 emitcode ("addc", "a,%s", zero);
4270 outAcc (IC_RESULT (ic));
4275 /* This is the original version of this code.
4277 * This is being kept around for reference,
4278 * because I am not entirely sure I got it right...
4281 adjustArithmeticResult (iCode * ic)
4283 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4284 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4285 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4286 aopPut (IC_RESULT (ic),
4287 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4290 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4291 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4292 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4293 aopPut (IC_RESULT (ic),
4294 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4297 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4298 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4299 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4300 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4301 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4304 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4305 aopPut (IC_RESULT (ic), buffer, 2);
4309 /* This is the pure and virtuous version of this code.
4310 * I'm pretty certain it's right, but not enough to toss the old
4314 adjustArithmeticResult (iCode * ic)
4316 if (opIsGptr (IC_RESULT (ic)) &&
4317 opIsGptr (IC_LEFT (ic)) &&
4318 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4320 aopPut (IC_RESULT (ic),
4321 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4325 if (opIsGptr (IC_RESULT (ic)) &&
4326 opIsGptr (IC_RIGHT (ic)) &&
4327 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4329 aopPut (IC_RESULT (ic),
4330 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4334 if (opIsGptr (IC_RESULT (ic)) &&
4335 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4336 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4338 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4341 SNPRINTF (buffer, sizeof(buffer),
4342 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4343 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4348 /*-----------------------------------------------------------------*/
4349 /* genPlus - generates code for addition */
4350 /*-----------------------------------------------------------------*/
4352 genPlus (iCode * ic)
4354 int size, offset = 0;
4357 bool swappedLR = FALSE;
4358 operand *leftOp, *rightOp;
4361 D (emitcode (";", "genPlus"));
4363 /* special cases :- */
4365 aopOp (IC_LEFT (ic), ic, FALSE);
4366 aopOp (IC_RIGHT (ic), ic, FALSE);
4367 aopOp (IC_RESULT (ic), ic, TRUE);
4369 /* if literal, literal on the right or
4370 if left requires ACC or right is already
4372 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4373 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4374 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4376 operand *t = IC_RIGHT (ic);
4377 IC_RIGHT (ic) = IC_LEFT (ic);
4382 /* if both left & right are in bit
4384 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4385 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4391 /* if left in bit space & right literal */
4392 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4393 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4395 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396 /* if result in bit space */
4397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4399 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4400 emitcode ("cpl", "c");
4401 outBitC (IC_RESULT (ic));
4405 size = getDataSize (IC_RESULT (ic));
4408 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4409 emitcode ("addc", "a,%s", zero);
4410 aopPut (IC_RESULT (ic), "a", offset++);
4416 /* if I can do an increment instead
4417 of add then GOOD for ME */
4418 if (genPlusIncr (ic) == TRUE)
4421 size = getDataSize (IC_RESULT (ic));
4422 leftOp = IC_LEFT(ic);
4423 rightOp = IC_RIGHT(ic);
4426 /* if this is an add for an array access
4427 at a 256 byte boundary */
4429 && AOP_TYPE (op) == AOP_IMMD
4431 && IS_SPEC (OP_SYM_ETYPE (op))
4432 && SPEC_ABSA (OP_SYM_ETYPE (op))
4433 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4436 D(emitcode ("; genPlus aligned array",""));
4437 aopPut (IC_RESULT (ic),
4438 aopGet (rightOp, 0, FALSE, FALSE),
4441 if( 1 == getDataSize (IC_RIGHT (ic)) )
4443 aopPut (IC_RESULT (ic),
4444 aopGet (leftOp, 1, FALSE, FALSE),
4449 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4450 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4451 aopPut (IC_RESULT (ic), "a", 1);
4456 /* if the lower bytes of a literal are zero skip the addition */
4457 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4459 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4460 (skip_bytes+1 < size))
4465 D(emitcode ("; genPlus shortcut",""));
4470 if( offset >= skip_bytes )
4472 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4475 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4477 emitcode("xch", "a,b");
4478 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4479 emitcode (add, "a,b");
4482 else if (aopGetUsesAcc (leftOp, offset))
4484 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4485 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4489 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4492 aopPut (IC_RESULT (ic), "a", offset);
4493 add = "addc"; /* further adds must propagate carry */
4497 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4498 isOperandVolatile (IC_RESULT (ic), FALSE))
4501 aopPut (IC_RESULT (ic),
4502 aopGet (leftOp, offset, FALSE, FALSE),
4509 adjustArithmeticResult (ic);
4512 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4515 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525 /*-----------------------------------------------------------------*/
4526 /* genMinusDec :- does subtraction with decrement if possible */
4527 /*-----------------------------------------------------------------*/
4529 genMinusDec (iCode * ic)
4531 unsigned int icount;
4532 unsigned int size = getDataSize (IC_RESULT (ic));
4534 /* will try to generate an increment */
4535 /* if the right side is not a literal
4537 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4540 /* if the literal value of the right hand side
4541 is greater than 4 then it is not worth it */
4542 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4545 D (emitcode (";", "genMinusDec"));
4547 /* if decrement >=16 bits in register or direct space */
4548 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4549 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4557 /* If the next instruction is a goto and the goto target
4558 * is <= 10 instructions previous to this, we can generate
4559 * jumps straight to that target.
4561 if (ic->next && ic->next->op == GOTO
4562 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4563 && labelRange <= 10)
4565 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4566 tlbl = IC_LABEL (ic->next);
4571 tlbl = newiTempLabel (NULL);
4575 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4576 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4577 IS_AOP_PREG (IC_RESULT (ic)))
4578 emitcode ("cjne", "%s,#0xff,%05d$"
4579 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4583 emitcode ("mov", "a,#0xff");
4584 emitcode ("cjne", "a,%s,%05d$"
4585 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4588 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4591 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4592 IS_AOP_PREG (IC_RESULT (ic)))
4593 emitcode ("cjne", "%s,#0xff,%05d$"
4594 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4598 emitcode ("cjne", "a,%s,%05d$"
4599 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4602 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4606 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4607 IS_AOP_PREG (IC_RESULT (ic)))
4608 emitcode ("cjne", "%s,#0xff,%05d$"
4609 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4613 emitcode ("cjne", "a,%s,%05d$"
4614 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4617 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4626 /* if the sizes are greater than 1 then we cannot */
4627 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4628 AOP_SIZE (IC_LEFT (ic)) > 1)
4631 /* we can if the aops of the left & result match or
4632 if they are in registers and the registers are the
4634 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4638 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4640 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4645 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4650 emitcode ("dec", "%s", l);
4653 if (AOP_NEEDSACC (IC_RESULT (ic)))
4654 aopPut (IC_RESULT (ic), "a", 0);
4662 /*-----------------------------------------------------------------*/
4663 /* addSign - complete with sign */
4664 /*-----------------------------------------------------------------*/
4666 addSign (operand * result, int offset, int sign)
4668 int size = (getDataSize (result) - offset);
4673 emitcode ("rlc", "a");
4674 emitcode ("subb", "a,acc");
4677 aopPut (result, "a", offset++);
4684 aopPut (result, zero, offset++);
4690 /*-----------------------------------------------------------------*/
4691 /* genMinusBits - generates code for subtraction of two bits */
4692 /*-----------------------------------------------------------------*/
4694 genMinusBits (iCode * ic)
4696 symbol *lbl = newiTempLabel (NULL);
4698 D (emitcode (";", "genMinusBits"));
4700 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4702 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4703 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4704 emitcode ("cpl", "c");
4706 outBitC (IC_RESULT (ic));
4710 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4711 emitcode ("subb", "a,acc");
4712 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4713 emitcode ("inc", "a");
4715 aopPut (IC_RESULT (ic), "a", 0);
4716 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4720 /*-----------------------------------------------------------------*/
4721 /* genMinus - generates code for subtraction */
4722 /*-----------------------------------------------------------------*/
4724 genMinus (iCode * ic)
4726 int size, offset = 0;
4728 D (emitcode (";", "genMinus"));
4730 aopOp (IC_LEFT (ic), ic, FALSE);
4731 aopOp (IC_RIGHT (ic), ic, FALSE);
4732 aopOp (IC_RESULT (ic), ic, TRUE);
4734 /* special cases :- */
4735 /* if both left & right are in bit space */
4736 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4743 /* if I can do an decrement instead
4744 of subtract then GOOD for ME */
4745 if (genMinusDec (ic) == TRUE)
4748 size = getDataSize (IC_RESULT (ic));
4750 /* if literal, add a,#-lit, else normal subb */
4751 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4753 unsigned long lit = 0L;
4754 bool useCarry = FALSE;
4756 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4761 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4763 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4764 if (!offset && !size && lit== (unsigned long) -1)
4766 emitcode ("dec", "a");
4770 /* first add without previous c */
4771 emitcode ("add", "a,#0x%02x",
4772 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4777 emitcode ("addc", "a,#0x%02x",
4778 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4780 aopPut (IC_RESULT (ic), "a", offset++);
4784 /* no need to add zeroes */
4785 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4787 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4796 operand *leftOp, *rightOp;
4798 leftOp = IC_LEFT(ic);
4799 rightOp = IC_RIGHT(ic);
4803 if (aopGetUsesAcc(rightOp, offset)) {
4804 if (aopGetUsesAcc(leftOp, offset)) {
4807 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4809 emitcode ("mov", "b,a");
4812 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4813 emitcode ("subb", "a,b");
4816 /* reverse subtraction with 2's complement */
4818 emitcode( "setb", "c");
4820 emitcode( "cpl", "c");
4821 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4822 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4823 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4824 emitcode("cpl", "a");
4825 if (size) /* skip if last byte */
4826 emitcode( "cpl", "c");
4829 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4832 emitcode ("subb", "a,%s",
4833 aopGet(rightOp, offset, FALSE, TRUE));
4836 aopPut (IC_RESULT (ic), "a", offset++);
4840 adjustArithmeticResult (ic);
4843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4844 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 /*-----------------------------------------------------------------*/
4850 /* genMultbits :- multiplication of bits */
4851 /*-----------------------------------------------------------------*/
4853 genMultbits (operand * left,
4857 D (emitcode (";", "genMultbits"));
4859 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4860 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4864 /*-----------------------------------------------------------------*/
4865 /* genMultOneByte : 8*8=8/16 bit multiplication */
4866 /*-----------------------------------------------------------------*/
4868 genMultOneByte (operand * left,
4873 int size = AOP_SIZE (result);
4874 bool runtimeSign, compiletimeSign;
4875 bool lUnsigned, rUnsigned, pushedB;
4877 D (emitcode (";", "genMultOneByte"));
4879 if (size < 1 || size > 2)
4881 /* this should never happen */
4882 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4883 AOP_SIZE(result), __FILE__, lineno);
4887 /* (if two literals: the value is computed before) */
4888 /* if one literal, literal on the right */
4889 if (AOP_TYPE (left) == AOP_LIT)
4894 /* emitcode (";", "swapped left and right"); */
4896 /* if no literal, unsigned on the right: shorter code */
4897 if ( AOP_TYPE (right) != AOP_LIT
4898 && SPEC_USIGN (getSpec (operandType (left))))
4905 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4906 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4910 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4911 no need to take care about the signedness! */
4912 || (lUnsigned && rUnsigned))
4914 /* just an unsigned 8 * 8 = 8 multiply
4916 /* emitcode (";","unsigned"); */
4917 /* TODO: check for accumulator clash between left & right aops? */
4919 if (AOP_TYPE (right) == AOP_LIT)
4921 /* moving to accumulator first helps peepholes */
4922 MOVA (aopGet (left, 0, FALSE, FALSE));
4923 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4927 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4928 MOVA (aopGet (left, 0, FALSE, FALSE));
4931 emitcode ("mul", "ab");
4932 aopPut (result, "a", 0);
4934 aopPut (result, "b", 1);
4940 /* we have to do a signed multiply */
4941 /* emitcode (";", "signed"); */
4943 /* now sign adjust for both left & right */
4945 /* let's see what's needed: */
4946 /* apply negative sign during runtime */
4947 runtimeSign = FALSE;
4948 /* negative sign from literals */
4949 compiletimeSign = FALSE;
4953 if (AOP_TYPE(left) == AOP_LIT)
4955 /* signed literal */
4956 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4958 compiletimeSign = TRUE;
4961 /* signed but not literal */
4967 if (AOP_TYPE(right) == AOP_LIT)
4969 /* signed literal */
4970 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4972 compiletimeSign ^= TRUE;
4975 /* signed but not literal */
4979 /* initialize F0, which stores the runtime sign */
4982 if (compiletimeSign)
4983 emitcode ("setb", "F0"); /* set sign flag */
4985 emitcode ("clr", "F0"); /* reset sign flag */
4988 /* save the signs of the operands */
4989 if (AOP_TYPE(right) == AOP_LIT)
4991 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4993 if (!rUnsigned && val < 0)
4994 emitcode ("mov", "b,#0x%02x", -val);
4996 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4998 else /* ! literal */
5000 if (rUnsigned) /* emitcode (";", "signed"); */
5001 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5004 MOVA (aopGet (right, 0, FALSE, FALSE));
5005 lbl = newiTempLabel (NULL);
5006 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5007 emitcode ("cpl", "F0"); /* complement sign flag */
5008 emitcode ("cpl", "a"); /* 2's complement */
5009 emitcode ("inc", "a");
5011 emitcode ("mov", "b,a");
5015 if (AOP_TYPE(left) == AOP_LIT)
5017 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5019 if (!lUnsigned && val < 0)
5020 emitcode ("mov", "a,#0x%02x", -val);
5022 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5024 else /* ! literal */
5026 MOVA (aopGet (left, 0, FALSE, FALSE));
5030 lbl = newiTempLabel (NULL);
5031 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032 emitcode ("cpl", "F0"); /* complement sign flag */
5033 emitcode ("cpl", "a"); /* 2's complement */
5034 emitcode ("inc", "a");
5039 /* now the multiplication */
5040 emitcode ("mul", "ab");
5041 if (runtimeSign || compiletimeSign)
5043 lbl = newiTempLabel (NULL);
5045 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5046 emitcode ("cpl", "a"); /* lsb 2's complement */
5048 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5051 emitcode ("add", "a,#1"); /* this sets carry flag */
5052 emitcode ("xch", "a,b");
5053 emitcode ("cpl", "a"); /* msb 2's complement */
5054 emitcode ("addc", "a,#0");
5055 emitcode ("xch", "a,b");
5059 aopPut (result, "a", 0);
5061 aopPut (result, "b", 1);
5066 /*-----------------------------------------------------------------*/
5067 /* genMult - generates code for multiplication */
5068 /*-----------------------------------------------------------------*/
5070 genMult (iCode * ic)
5072 operand *left = IC_LEFT (ic);
5073 operand *right = IC_RIGHT (ic);
5074 operand *result = IC_RESULT (ic);
5076 D (emitcode (";", "genMult"));
5078 /* assign the asmops */
5079 aopOp (left, ic, FALSE);
5080 aopOp (right, ic, FALSE);
5081 aopOp (result, ic, TRUE);
5083 /* special cases first */
5085 if (AOP_TYPE (left) == AOP_CRY &&
5086 AOP_TYPE (right) == AOP_CRY)
5088 genMultbits (left, right, result);
5092 /* if both are of size == 1 */
5093 #if 0 // one of them can be a sloc shared with the result
5094 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5096 if (getSize(operandType(left)) == 1 &&
5097 getSize(operandType(right)) == 1)
5100 genMultOneByte (left, right, result);
5104 /* should have been converted to function call */
5105 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5106 getSize(OP_SYMBOL(right)->type));
5110 freeAsmop (result, NULL, ic, TRUE);
5111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115 /*-----------------------------------------------------------------*/
5116 /* genDivbits :- division of bits */
5117 /*-----------------------------------------------------------------*/
5119 genDivbits (operand * left,
5126 D(emitcode ("; genDivbits",""));
5130 /* the result must be bit */
5131 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5132 l = aopGet (left, 0, FALSE, FALSE);
5136 emitcode ("div", "ab");
5137 emitcode ("rrc", "a");
5141 aopPut (result, "c", 0);
5144 /*-----------------------------------------------------------------*/
5145 /* genDivOneByte : 8 bit division */
5146 /*-----------------------------------------------------------------*/
5148 genDivOneByte (operand * left,
5152 bool lUnsigned, rUnsigned, pushedB;
5153 bool runtimeSign, compiletimeSign;
5154 bool accuse = FALSE;
5155 bool pushedA = FALSE;
5159 D(emitcode ("; genDivOneByte",""));
5161 /* Why is it necessary that genDivOneByte() can return an int result?
5164 volatile unsigned char uc;
5165 volatile signed char sc1, sc2;
5178 In all cases a one byte result would overflow, the following cast to int
5179 would return the wrong result.
5181 Two possible solution:
5182 a) cast operands to int, if ((unsigned) / (signed)) or
5183 ((signed) / (signed))
5184 b) return an 16 bit signed int; this is what we're doing here!
5187 size = AOP_SIZE (result) - 1;
5189 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5190 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5194 /* signed or unsigned */
5195 if (lUnsigned && rUnsigned)
5197 /* unsigned is easy */
5198 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5199 MOVA (aopGet (left, 0, FALSE, FALSE));
5200 emitcode ("div", "ab");
5201 aopPut (result, "a", 0);
5203 aopPut (result, zero, offset++);
5209 /* signed is a little bit more difficult */
5211 /* now sign adjust for both left & right */
5213 /* let's see what's needed: */
5214 /* apply negative sign during runtime */
5215 runtimeSign = FALSE;
5216 /* negative sign from literals */
5217 compiletimeSign = FALSE;
5221 if (AOP_TYPE(left) == AOP_LIT)
5223 /* signed literal */
5224 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5226 compiletimeSign = TRUE;
5229 /* signed but not literal */
5235 if (AOP_TYPE(right) == AOP_LIT)
5237 /* signed literal */
5238 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5240 compiletimeSign ^= TRUE;
5243 /* signed but not literal */
5247 /* initialize F0, which stores the runtime sign */
5250 if (compiletimeSign)
5251 emitcode ("setb", "F0"); /* set sign flag */
5253 emitcode ("clr", "F0"); /* reset sign flag */
5256 /* save the signs of the operands */
5257 if (AOP_TYPE(right) == AOP_LIT)
5259 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5261 if (!rUnsigned && val < 0)
5262 emitcode ("mov", "b,#0x%02x", -val);
5264 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5266 else /* ! literal */
5269 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5272 MOVA (aopGet (right, 0, FALSE, FALSE));
5273 lbl = newiTempLabel (NULL);
5274 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5275 emitcode ("cpl", "F0"); /* complement sign flag */
5276 emitcode ("cpl", "a"); /* 2's complement */
5277 emitcode ("inc", "a");
5279 emitcode ("mov", "b,a");
5283 if (AOP_TYPE(left) == AOP_LIT)
5285 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5287 if (!lUnsigned && val < 0)
5288 emitcode ("mov", "a,#0x%02x", -val);
5290 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5292 else /* ! literal */
5294 MOVA (aopGet (left, 0, FALSE, FALSE));
5298 lbl = newiTempLabel (NULL);
5299 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300 emitcode ("cpl", "F0"); /* complement sign flag */
5301 emitcode ("cpl", "a"); /* 2's complement */
5302 emitcode ("inc", "a");
5307 /* now the division */
5308 emitcode ("div", "ab");
5310 if (runtimeSign || compiletimeSign)
5312 lbl = newiTempLabel (NULL);
5314 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5315 emitcode ("cpl", "a"); /* lsb 2's complement */
5316 emitcode ("inc", "a");
5319 accuse = aopPut (result, "a", 0);
5322 /* msb is 0x00 or 0xff depending on the sign */
5327 emitcode ("push", "acc");
5330 emitcode ("mov", "c,F0");
5331 emitcode ("subb", "a,acc");
5333 aopPut (result, "a", offset++);
5335 else /* compiletimeSign */
5337 if (aopPutUsesAcc (result, "#0xFF", offset))
5339 emitcode ("push", "acc");
5343 aopPut (result, "#0xff", offset++);
5349 aopPut (result, "a", 0);
5351 aopPut (result, zero, offset++);
5355 emitcode ("pop", "acc");
5359 /*-----------------------------------------------------------------*/
5360 /* genDiv - generates code for division */
5361 /*-----------------------------------------------------------------*/
5365 operand *left = IC_LEFT (ic);
5366 operand *right = IC_RIGHT (ic);
5367 operand *result = IC_RESULT (ic);
5369 D (emitcode (";", "genDiv"));
5371 /* assign the amsops */
5372 aopOp (left, ic, FALSE);
5373 aopOp (right, ic, FALSE);
5374 aopOp (result, ic, TRUE);
5376 /* special cases first */
5378 if (AOP_TYPE (left) == AOP_CRY &&
5379 AOP_TYPE (right) == AOP_CRY)
5381 genDivbits (left, right, result);
5385 /* if both are of size == 1 */
5386 if (AOP_SIZE (left) == 1 &&
5387 AOP_SIZE (right) == 1)
5389 genDivOneByte (left, right, result);
5393 /* should have been converted to function call */
5396 freeAsmop (result, NULL, ic, TRUE);
5397 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401 /*-----------------------------------------------------------------*/
5402 /* genModbits :- modulus of bits */
5403 /*-----------------------------------------------------------------*/
5405 genModbits (operand * left,
5412 D (emitcode (";", "genModbits"));
5416 /* the result must be bit */
5417 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5418 l = aopGet (left, 0, FALSE, FALSE);
5422 emitcode ("div", "ab");
5423 emitcode ("mov", "a,b");
5424 emitcode ("rrc", "a");
5428 aopPut (result, "c", 0);
5431 /*-----------------------------------------------------------------*/
5432 /* genModOneByte : 8 bit modulus */
5433 /*-----------------------------------------------------------------*/
5435 genModOneByte (operand * left,
5439 bool lUnsigned, rUnsigned, pushedB;
5440 bool runtimeSign, compiletimeSign;
5444 D (emitcode (";", "genModOneByte"));
5446 size = AOP_SIZE (result) - 1;
5448 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5449 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5451 /* if right is a literal, check it for 2^n */
5452 if (AOP_TYPE(right) == AOP_LIT)
5454 unsigned char val = abs((int) operandLitValue(right));
5455 symbol *lbl2 = NULL;
5459 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5468 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5469 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5470 /* because iCode should have been changed to genAnd */
5471 /* see file "SDCCopt.c", function "convertToFcall()" */
5473 MOVA (aopGet (left, 0, FALSE, FALSE));
5474 emitcode ("mov", "c,acc.7");
5475 emitcode ("anl", "a,#0x%02x", val - 1);
5476 lbl = newiTempLabel (NULL);
5477 emitcode ("jz", "%05d$", (lbl->key + 100));
5478 emitcode ("jnc", "%05d$", (lbl->key + 100));
5479 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5485 aopPut (result, "a", 0);
5487 aopPut (result, "#0xff", offs2++);
5488 lbl2 = newiTempLabel (NULL);
5489 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5492 aopPut (result, "a", 0);
5494 aopPut (result, zero, offset++);
5508 /* signed or unsigned */
5509 if (lUnsigned && rUnsigned)
5511 /* unsigned is easy */
5512 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513 MOVA (aopGet (left, 0, FALSE, FALSE));
5514 emitcode ("div", "ab");
5515 aopPut (result, "b", 0);
5517 aopPut (result, zero, offset++);
5523 /* signed is a little bit more difficult */
5525 /* now sign adjust for both left & right */
5527 /* modulus: sign of the right operand has no influence on the result! */
5528 if (AOP_TYPE(right) == AOP_LIT)
5530 signed char val = (char) operandLitValue(right);
5532 if (!rUnsigned && val < 0)
5533 emitcode ("mov", "b,#0x%02x", -val);
5535 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5537 else /* not literal */
5540 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5543 MOVA (aopGet (right, 0, FALSE, FALSE));
5544 lbl = newiTempLabel (NULL);
5545 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5546 emitcode ("cpl", "a"); /* 2's complement */
5547 emitcode ("inc", "a");
5549 emitcode ("mov", "b,a");
5553 /* let's see what's needed: */
5554 /* apply negative sign during runtime */
5555 runtimeSign = FALSE;
5556 /* negative sign from literals */
5557 compiletimeSign = FALSE;
5559 /* sign adjust left side */
5560 if (AOP_TYPE(left) == AOP_LIT)
5562 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5564 if (!lUnsigned && val < 0)
5566 compiletimeSign = TRUE; /* set sign flag */
5567 emitcode ("mov", "a,#0x%02x", -val);
5570 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5572 else /* ! literal */
5574 MOVA (aopGet (left, 0, FALSE, FALSE));
5579 emitcode ("clr", "F0"); /* clear sign flag */
5581 lbl = newiTempLabel (NULL);
5582 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5583 emitcode ("setb", "F0"); /* set sign flag */
5584 emitcode ("cpl", "a"); /* 2's complement */
5585 emitcode ("inc", "a");
5590 /* now the modulus */
5591 emitcode ("div", "ab");
5593 if (runtimeSign || compiletimeSign)
5595 emitcode ("mov", "a,b");
5596 lbl = newiTempLabel (NULL);
5598 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5599 emitcode ("cpl", "a"); /* 2's complement */
5600 emitcode ("inc", "a");
5603 aopPut (result, "a", 0);
5606 /* msb is 0x00 or 0xff depending on the sign */
5609 emitcode ("mov", "c,F0");
5610 emitcode ("subb", "a,acc");
5612 aopPut (result, "a", offset++);
5614 else /* compiletimeSign */
5616 aopPut (result, "#0xff", offset++);
5621 aopPut (result, "b", 0);
5623 aopPut (result, zero, offset++);
5629 /*-----------------------------------------------------------------*/
5630 /* genMod - generates code for division */
5631 /*-----------------------------------------------------------------*/
5635 operand *left = IC_LEFT (ic);
5636 operand *right = IC_RIGHT (ic);
5637 operand *result = IC_RESULT (ic);
5639 D (emitcode (";", "genMod"));
5641 /* assign the asmops */
5642 aopOp (left, ic, FALSE);
5643 aopOp (right, ic, FALSE);
5644 aopOp (result, ic, TRUE);
5646 /* special cases first */
5648 if (AOP_TYPE (left) == AOP_CRY &&
5649 AOP_TYPE (right) == AOP_CRY)
5651 genModbits (left, right, result);
5655 /* if both are of size == 1 */
5656 if (AOP_SIZE (left) == 1 &&
5657 AOP_SIZE (right) == 1)
5659 genModOneByte (left, right, result);
5663 /* should have been converted to function call */
5667 freeAsmop (result, NULL, ic, TRUE);
5668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5672 /*-----------------------------------------------------------------*/
5673 /* genIfxJump :- will create a jump depending on the ifx */
5674 /*-----------------------------------------------------------------*/
5676 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5679 symbol *tlbl = newiTempLabel (NULL);
5682 D (emitcode (";", "genIfxJump"));
5684 /* if true label then we jump if condition
5688 jlbl = IC_TRUE (ic);
5689 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5690 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5694 /* false label is present */
5695 jlbl = IC_FALSE (ic);
5696 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5697 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5699 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5700 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5702 emitcode (inst, "%05d$", tlbl->key + 100);
5703 freeForBranchAsmop (result);
5704 freeForBranchAsmop (right);
5705 freeForBranchAsmop (left);
5706 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5709 /* mark the icode as generated */
5713 /*-----------------------------------------------------------------*/
5714 /* genCmp :- greater or less than comparison */
5715 /*-----------------------------------------------------------------*/
5717 genCmp (operand * left, operand * right,
5718 operand * result, iCode * ifx, int sign, iCode *ic)
5720 int size, offset = 0;
5721 unsigned long lit = 0L;
5724 D (emitcode (";", "genCmp"));
5726 /* if left & right are bit variables */
5727 if (AOP_TYPE (left) == AOP_CRY &&
5728 AOP_TYPE (right) == AOP_CRY)
5730 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5731 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5735 /* subtract right from left if at the
5736 end the carry flag is set then we know that
5737 left is greater than right */
5738 size = max (AOP_SIZE (left), AOP_SIZE (right));
5740 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5741 if ((size == 1) && !sign &&
5742 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5744 symbol *lbl = newiTempLabel (NULL);
5745 emitcode ("cjne", "%s,%s,%05d$",
5746 aopGet (left, offset, FALSE, FALSE),
5747 aopGet (right, offset, FALSE, FALSE),
5753 if (AOP_TYPE (right) == AOP_LIT)
5755 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5756 /* optimize if(x < 0) or if(x >= 0) */
5765 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5766 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5768 genIfxJump (ifx, "acc.7", left, right, result);
5769 freeAsmop (right, NULL, ic, TRUE);
5770 freeAsmop (left, NULL, ic, TRUE);
5776 emitcode ("rlc", "a");
5783 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5784 while (size && (bytelit == 0))
5787 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5793 MOVA (aopGet (left, offset, FALSE, FALSE));
5794 if (sign && size == 0)
5796 emitcode ("xrl", "a,#0x80");
5797 emitcode ("subb", "a,#0x%02x",
5798 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5802 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5812 bool pushedB = FALSE;
5813 rightInB = aopGetUsesAcc(right, offset);
5817 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5819 MOVA (aopGet (left, offset, FALSE, FALSE));
5820 if (sign && size == 0)
5822 emitcode ("xrl", "a,#0x80");
5827 MOVB (aopGet (right, offset, FALSE, FALSE));
5829 emitcode ("xrl", "b,#0x80");
5830 emitcode ("subb", "a,b");
5835 emitcode ("subb", "a,b");
5837 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5849 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5855 /* if the result is used in the next
5856 ifx conditional branch then generate
5857 code a little differently */
5860 genIfxJump (ifx, "c", NULL, NULL, result);
5866 /* leave the result in acc */
5870 /*-----------------------------------------------------------------*/
5871 /* genCmpGt :- greater than comparison */
5872 /*-----------------------------------------------------------------*/
5874 genCmpGt (iCode * ic, iCode * ifx)
5876 operand *left, *right, *result;
5877 sym_link *letype, *retype;
5880 D (emitcode (";", "genCmpGt"));
5882 left = IC_LEFT (ic);
5883 right = IC_RIGHT (ic);
5884 result = IC_RESULT (ic);
5886 letype = getSpec (operandType (left));
5887 retype = getSpec (operandType (right));
5888 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5889 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5890 /* assign the amsops */
5891 aopOp (result, ic, TRUE);
5892 aopOp (left, ic, FALSE);
5893 aopOp (right, ic, FALSE);
5895 genCmp (right, left, result, ifx, sign, ic);
5897 freeAsmop (result, NULL, ic, TRUE);
5900 /*-----------------------------------------------------------------*/
5901 /* genCmpLt - less than comparisons */
5902 /*-----------------------------------------------------------------*/
5904 genCmpLt (iCode * ic, iCode * ifx)
5906 operand *left, *right, *result;
5907 sym_link *letype, *retype;
5910 D (emitcode (";", "genCmpLt"));
5912 left = IC_LEFT (ic);
5913 right = IC_RIGHT (ic);
5914 result = IC_RESULT (ic);
5916 letype = getSpec (operandType (left));
5917 retype = getSpec (operandType (right));
5918 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5919 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5920 /* assign the amsops */
5921 aopOp (result, ic, TRUE);
5922 aopOp (left, ic, FALSE);
5923 aopOp (right, ic, FALSE);
5925 genCmp (left, right, result, ifx, sign, ic);
5927 freeAsmop (result, NULL, ic, TRUE);
5930 /*-----------------------------------------------------------------*/
5931 /* gencjneshort - compare and jump if not equal */
5932 /*-----------------------------------------------------------------*/
5934 gencjneshort (operand * left, operand * right, symbol * lbl)
5936 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5938 unsigned long lit = 0L;
5940 D (emitcode (";", "gencjneshort"));
5942 /* if the left side is a literal or
5943 if the right is in a pointer register and left
5945 if ((AOP_TYPE (left) == AOP_LIT) ||
5946 (AOP_TYPE (left) == AOP_IMMD) ||
5947 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5954 if (AOP_TYPE (right) == AOP_LIT)
5955 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5957 /* if the right side is a literal then anything goes */
5958 if (AOP_TYPE (right) == AOP_LIT &&
5959 AOP_TYPE (left) != AOP_DIR &&
5960 AOP_TYPE (left) != AOP_IMMD)
5964 emitcode ("cjne", "%s,%s,%05d$",
5965 aopGet (left, offset, FALSE, FALSE),
5966 aopGet (right, offset, FALSE, FALSE),
5972 /* if the right side is in a register or in direct space or
5973 if the left is a pointer register & right is not */
5974 else if (AOP_TYPE (right) == AOP_REG ||
5975 AOP_TYPE (right) == AOP_DIR ||
5976 AOP_TYPE (right) == AOP_LIT ||
5977 AOP_TYPE (right) == AOP_IMMD ||
5978 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5979 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5983 MOVA (aopGet (left, offset, FALSE, FALSE));
5984 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5985 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5986 emitcode ("jnz", "%05d$", lbl->key + 100);
5988 emitcode ("cjne", "a,%s,%05d$",
5989 aopGet (right, offset, FALSE, TRUE),
5996 /* right is a pointer reg need both a & b */
5999 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6000 wassertl(!BINUSE, "B was in use");
6001 MOVB (aopGet (left, offset, FALSE, FALSE));
6002 MOVA (aopGet (right, offset, FALSE, FALSE));
6003 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6009 /*-----------------------------------------------------------------*/
6010 /* gencjne - compare and jump if not equal */
6011 /*-----------------------------------------------------------------*/
6013 gencjne (operand * left, operand * right, symbol * lbl)
6015 symbol *tlbl = newiTempLabel (NULL);
6017 D (emitcode (";", "gencjne"));
6019 gencjneshort (left, right, lbl);
6021 emitcode ("mov", "a,%s", one);
6022 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6024 emitcode ("clr", "a");
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpEq - generates code for equal to */
6030 /*-----------------------------------------------------------------*/
6032 genCmpEq (iCode * ic, iCode * ifx)
6034 bool swappedLR = FALSE;
6035 operand *left, *right, *result;
6037 D (emitcode (";", "genCmpEq"));
6039 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6040 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6041 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6043 /* if literal, literal on the right or
6044 if the right is in a pointer register and left
6046 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6047 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6049 operand *t = IC_RIGHT (ic);
6050 IC_RIGHT (ic) = IC_LEFT (ic);
6055 if (ifx && !AOP_SIZE (result))
6058 /* if they are both bit variables */
6059 if (AOP_TYPE (left) == AOP_CRY &&
6060 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6062 if (AOP_TYPE (right) == AOP_LIT)
6064 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6068 emitcode ("cpl", "c");
6072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6076 emitcode ("clr", "c");
6078 /* AOP_TYPE(right) == AOP_CRY */
6082 symbol *lbl = newiTempLabel (NULL);
6083 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6084 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6085 emitcode ("cpl", "c");
6088 /* if true label then we jump if condition
6090 tlbl = newiTempLabel (NULL);
6093 emitcode ("jnc", "%05d$", tlbl->key + 100);
6094 freeForBranchAsmop (result);
6095 freeForBranchAsmop (right);
6096 freeForBranchAsmop (left);
6097 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6101 emitcode ("jc", "%05d$", tlbl->key + 100);
6102 freeForBranchAsmop (result);
6103 freeForBranchAsmop (right);
6104 freeForBranchAsmop (left);
6105 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6111 tlbl = newiTempLabel (NULL);
6112 gencjneshort (left, right, tlbl);
6115 freeForBranchAsmop (result);
6116 freeForBranchAsmop (right);
6117 freeForBranchAsmop (left);
6118 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6123 symbol *lbl = newiTempLabel (NULL);
6124 emitcode ("sjmp", "%05d$", lbl->key + 100);
6126 freeForBranchAsmop (result);
6127 freeForBranchAsmop (right);
6128 freeForBranchAsmop (left);
6129 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6133 /* mark the icode as generated */
6138 /* if they are both bit variables */
6139 if (AOP_TYPE (left) == AOP_CRY &&
6140 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6142 if (AOP_TYPE (right) == AOP_LIT)
6144 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6147 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6148 emitcode ("cpl", "c");
6152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6156 emitcode ("clr", "c");
6158 /* AOP_TYPE(right) == AOP_CRY */
6162 symbol *lbl = newiTempLabel (NULL);
6163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6165 emitcode ("cpl", "c");
6169 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6176 genIfxJump (ifx, "c", left, right, result);
6179 /* if the result is used in an arithmetic operation
6180 then put the result in place */
6185 gencjne (left, right, newiTempLabel (NULL));
6186 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6188 aopPut (result, "a", 0);
6193 genIfxJump (ifx, "a", left, right, result);
6196 /* if the result is used in an arithmetic operation
6197 then put the result in place */
6198 if (AOP_TYPE (result) != AOP_CRY)
6200 /* leave the result in acc */
6204 freeAsmop (result, NULL, ic, TRUE);
6207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6208 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6217 /*-----------------------------------------------------------------*/
6218 /* ifxForOp - returns the icode containing the ifx for operand */
6219 /*-----------------------------------------------------------------*/
6221 ifxForOp (operand * op, iCode * ic)
6223 /* if true symbol then needs to be assigned */
6224 if (IS_TRUE_SYMOP (op))
6227 /* if this has register type condition and
6228 the next instruction is ifx with the same operand
6229 and live to of the operand is upto the ifx only then */
6231 ic->next->op == IFX &&
6232 IC_COND (ic->next)->key == op->key &&
6233 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6239 /*-----------------------------------------------------------------*/
6240 /* hasInc - operand is incremented before any other use */
6241 /*-----------------------------------------------------------------*/
6243 hasInc (operand *op, iCode *ic, int osize)
6245 sym_link *type = operandType(op);
6246 sym_link *retype = getSpec (type);
6247 iCode *lic = ic->next;
6250 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6251 if (!IS_SYMOP(op)) return NULL;
6253 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6254 if (IS_AGGREGATE(type->next)) return NULL;
6255 if (osize != (isize = getSize(type->next))) return NULL;
6258 /* if operand of the form op = op + <sizeof *op> */
6259 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6260 isOperandEqual(IC_RESULT(lic),op) &&
6261 isOperandLiteral(IC_RIGHT(lic)) &&
6262 operandLitValue(IC_RIGHT(lic)) == isize) {
6265 /* if the operand used or deffed */
6266 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6269 /* if GOTO or IFX */
6270 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6276 /*-----------------------------------------------------------------*/
6277 /* genAndOp - for && operation */
6278 /*-----------------------------------------------------------------*/
6280 genAndOp (iCode * ic)
6282 operand *left, *right, *result;
6285 D (emitcode (";", "genAndOp"));
6287 /* note here that && operations that are in an
6288 if statement are taken away by backPatchLabels
6289 only those used in arthmetic operations remain */
6290 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6291 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6292 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6294 /* if both are bit variables */
6295 if (AOP_TYPE (left) == AOP_CRY &&
6296 AOP_TYPE (right) == AOP_CRY)
6298 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6299 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6304 tlbl = newiTempLabel (NULL);
6306 emitcode ("jz", "%05d$", tlbl->key + 100);
6312 freeAsmop (result, NULL, ic, TRUE);
6313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318 /*-----------------------------------------------------------------*/
6319 /* genOrOp - for || operation */
6320 /*-----------------------------------------------------------------*/
6322 genOrOp (iCode * ic)
6324 operand *left, *right, *result;
6327 D (emitcode (";", "genOrOp"));
6329 /* note here that || operations that are in an
6330 if statement are taken away by backPatchLabels
6331 only those used in arthmetic operations remain */
6332 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6333 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6334 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6336 /* if both are bit variables */
6337 if (AOP_TYPE (left) == AOP_CRY &&
6338 AOP_TYPE (right) == AOP_CRY)
6340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6341 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6346 tlbl = newiTempLabel (NULL);
6348 emitcode ("jnz", "%05d$", tlbl->key + 100);
6354 freeAsmop (result, NULL, ic, TRUE);
6355 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6359 /*-----------------------------------------------------------------*/
6360 /* isLiteralBit - test if lit == 2^n */
6361 /*-----------------------------------------------------------------*/
6363 isLiteralBit (unsigned long lit)
6365 unsigned long pw[32] =
6366 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6367 0x100L, 0x200L, 0x400L, 0x800L,
6368 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6369 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6370 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6371 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6372 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6375 for (idx = 0; idx < 32; idx++)
6381 /*-----------------------------------------------------------------*/
6382 /* continueIfTrue - */
6383 /*-----------------------------------------------------------------*/
6385 continueIfTrue (iCode * ic)
6388 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6392 /*-----------------------------------------------------------------*/
6394 /*-----------------------------------------------------------------*/
6396 jumpIfTrue (iCode * ic)
6399 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6403 /*-----------------------------------------------------------------*/
6404 /* jmpTrueOrFalse - */
6405 /*-----------------------------------------------------------------*/
6407 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6409 // ugly but optimized by peephole
6412 symbol *nlbl = newiTempLabel (NULL);
6413 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6415 freeForBranchAsmop (result);
6416 freeForBranchAsmop (right);
6417 freeForBranchAsmop (left);
6418 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6423 freeForBranchAsmop (result);
6424 freeForBranchAsmop (right);
6425 freeForBranchAsmop (left);
6426 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6432 /*-----------------------------------------------------------------*/
6433 /* genAnd - code for and */
6434 /*-----------------------------------------------------------------*/
6436 genAnd (iCode * ic, iCode * ifx)
6438 operand *left, *right, *result;
6439 int size, offset = 0;
6440 unsigned long lit = 0L;
6444 D (emitcode (";", "genAnd"));
6446 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6447 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6448 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6451 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6453 AOP_TYPE (left), AOP_TYPE (right));
6454 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6456 AOP_SIZE (left), AOP_SIZE (right));
6459 /* if left is a literal & right is not then exchange them */
6460 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6461 AOP_NEEDSACC (left))
6463 operand *tmp = right;
6468 /* if result = right then exchange left and right */
6469 if (sameRegs (AOP (result), AOP (right)))
6471 operand *tmp = right;
6476 /* if right is bit then exchange them */
6477 if (AOP_TYPE (right) == AOP_CRY &&
6478 AOP_TYPE (left) != AOP_CRY)
6480 operand *tmp = right;
6484 if (AOP_TYPE (right) == AOP_LIT)
6485 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6487 size = AOP_SIZE (result);
6490 // result = bit & yy;
6491 if (AOP_TYPE (left) == AOP_CRY)
6493 // c = bit & literal;
6494 if (AOP_TYPE (right) == AOP_LIT)
6498 if (size && sameRegs (AOP (result), AOP (left)))
6501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6506 if (size && (AOP_TYPE (result) == AOP_CRY))
6508 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6511 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6516 emitcode ("clr", "c");
6521 if (AOP_TYPE (right) == AOP_CRY)
6524 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6525 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6530 MOVA (aopGet (right, 0, FALSE, FALSE));
6532 emitcode ("rrc", "a");
6533 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6541 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542 genIfxJump (ifx, "c", left, right, result);
6546 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6547 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6548 if ((AOP_TYPE (right) == AOP_LIT) &&
6549 (AOP_TYPE (result) == AOP_CRY) &&
6550 (AOP_TYPE (left) != AOP_CRY))
6552 int posbit = isLiteralBit (lit);
6557 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6561 switch (posbit & 0x07)
6563 case 0: emitcode ("rrc", "a");
6565 case 7: emitcode ("rlc", "a");
6567 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6576 SNPRINTF (buffer, sizeof(buffer),
6577 "acc.%d", posbit & 0x07);
6578 genIfxJump (ifx, buffer, left, right, result);
6581 {// what is this case? just found it in ds390/gen.c
6582 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6589 symbol *tlbl = newiTempLabel (NULL);
6590 int sizel = AOP_SIZE (left);
6592 emitcode ("setb", "c");
6595 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6597 MOVA (aopGet (left, offset, FALSE, FALSE));
6599 if ((posbit = isLiteralBit (bytelit)) != 0)
6600 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6603 if (bytelit != 0x0FFL)
6604 emitcode ("anl", "a,%s",
6605 aopGet (right, offset, FALSE, TRUE));
6606 emitcode ("jnz", "%05d$", tlbl->key + 100);
6611 // bit = left & literal
6614 emitcode ("clr", "c");
6617 // if(left & literal)
6621 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6631 /* if left is same as result */
6632 if (sameRegs (AOP (result), AOP (left)))
6634 for (; size--; offset++)
6636 if (AOP_TYPE (right) == AOP_LIT)
6638 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6639 if (bytelit == 0x0FF)
6641 /* dummy read of volatile operand */
6642 if (isOperandVolatile (left, FALSE))
6643 MOVA (aopGet (left, offset, FALSE, FALSE));
6647 else if (bytelit == 0)
6649 aopPut (result, zero, offset);
6651 else if (IS_AOP_PREG (result))
6653 MOVA (aopGet (left, offset, FALSE, TRUE));
6654 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6655 aopPut (result, "a", offset);
6658 emitcode ("anl", "%s,%s",
6659 aopGet (left, offset, FALSE, TRUE),
6660 aopGet (right, offset, FALSE, FALSE));
6664 if (AOP_TYPE (left) == AOP_ACC)
6667 emitcode("mov", "a,b");
6668 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6670 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6672 MOVB (aopGet (left, offset, FALSE, FALSE));
6673 MOVA (aopGet (right, offset, FALSE, FALSE));
6674 emitcode ("anl", "a,b");
6675 aopPut (result, "a", offset);
6677 else if (aopGetUsesAcc (left, offset))
6679 MOVA (aopGet (left, offset, FALSE, FALSE));
6680 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681 aopPut (result, "a", offset);
6685 MOVA (aopGet (right, offset, FALSE, FALSE));
6686 if (IS_AOP_PREG (result))
6688 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6689 aopPut (result, "a", offset);
6692 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6699 // left & result in different registers
6700 if (AOP_TYPE (result) == AOP_CRY)
6703 // if(size), result in bit
6704 // if(!size && ifx), conditional oper: if(left & right)
6705 symbol *tlbl = newiTempLabel (NULL);
6706 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6708 emitcode ("setb", "c");
6711 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6712 && AOP_TYPE(left)==AOP_ACC)
6715 emitcode("mov", "a,b");
6716 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6718 else if (AOP_TYPE(left)==AOP_ACC)
6722 bool pushedB = pushB ();
6723 emitcode("mov", "b,a");
6724 MOVA (aopGet (right, offset, FALSE, FALSE));
6725 emitcode("anl", "a,b");
6730 MOVA (aopGet (right, offset, FALSE, FALSE));
6731 emitcode("anl", "a,b");
6734 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6736 MOVB (aopGet (left, offset, FALSE, FALSE));
6737 MOVA (aopGet (right, offset, FALSE, FALSE));
6738 emitcode ("anl", "a,b");
6740 else if (aopGetUsesAcc (left, offset))
6742 MOVA (aopGet (left, offset, FALSE, FALSE));
6743 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6747 MOVA (aopGet (right, offset, FALSE, FALSE));
6748 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6751 emitcode ("jnz", "%05d$", tlbl->key + 100);
6761 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6767 for (; (size--); offset++)
6770 // result = left & right
6771 if (AOP_TYPE (right) == AOP_LIT)
6773 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6774 if (bytelit == 0x0FF)
6777 aopGet (left, offset, FALSE, FALSE),
6781 else if (bytelit == 0)
6783 /* dummy read of volatile operand */
6784 if (isOperandVolatile (left, FALSE))
6785 MOVA (aopGet (left, offset, FALSE, FALSE));
6786 aopPut (result, zero, offset);
6789 else if (AOP_TYPE (left) == AOP_ACC)
6793 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6794 aopPut (result, "a", offset);
6799 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6800 aopPut (result, "b", offset);
6805 // faster than result <- left, anl result,right
6806 // and better if result is SFR
6807 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6808 && AOP_TYPE(left)==AOP_ACC)
6811 emitcode("mov", "a,b");
6812 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6814 else if (AOP_TYPE(left)==AOP_ACC)
6818 bool pushedB = pushB ();
6819 emitcode("mov", "b,a");
6820 MOVA (aopGet (right, offset, FALSE, FALSE));
6821 emitcode("anl", "a,b");
6826 MOVA (aopGet (right, offset, FALSE, FALSE));
6827 emitcode("anl", "a,b");
6830 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6832 MOVB (aopGet (left, offset, FALSE, FALSE));
6833 MOVA (aopGet (right, offset, FALSE, FALSE));
6834 emitcode ("anl", "a,b");
6836 else if (aopGetUsesAcc (left, offset))
6838 MOVA (aopGet (left, offset, FALSE, FALSE));
6839 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6843 MOVA (aopGet (right, offset, FALSE, FALSE));
6844 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6846 aopPut (result, "a", offset);
6852 freeAsmop (result, NULL, ic, TRUE);
6853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6857 /*-----------------------------------------------------------------*/
6858 /* genOr - code for or */
6859 /*-----------------------------------------------------------------*/
6861 genOr (iCode * ic, iCode * ifx)
6863 operand *left, *right, *result;
6864 int size, offset = 0;
6865 unsigned long lit = 0L;
6868 D (emitcode (";", "genOr"));
6870 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6871 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6872 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6875 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6877 AOP_TYPE (left), AOP_TYPE (right));
6878 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6880 AOP_SIZE (left), AOP_SIZE (right));
6883 /* if left is a literal & right is not then exchange them */
6884 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6885 AOP_NEEDSACC (left))
6887 operand *tmp = right;
6892 /* if result = right then exchange them */
6893 if (sameRegs (AOP (result), AOP (right)))
6895 operand *tmp = right;
6900 /* if right is bit then exchange them */
6901 if (AOP_TYPE (right) == AOP_CRY &&
6902 AOP_TYPE (left) != AOP_CRY)
6904 operand *tmp = right;
6908 if (AOP_TYPE (right) == AOP_LIT)
6909 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6911 size = AOP_SIZE (result);
6915 if (AOP_TYPE (left) == AOP_CRY)
6917 if (AOP_TYPE (right) == AOP_LIT)
6919 // c = bit | literal;
6922 // lit != 0 => result = 1
6923 if (AOP_TYPE (result) == AOP_CRY)
6926 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6928 continueIfTrue (ifx);
6931 emitcode ("setb", "c");
6935 // lit == 0 => result = left
6936 if (size && sameRegs (AOP (result), AOP (left)))
6938 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6943 if (AOP_TYPE (right) == AOP_CRY)
6946 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6947 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6952 symbol *tlbl = newiTempLabel (NULL);
6953 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6954 emitcode ("setb", "c");
6955 emitcode ("jb", "%s,%05d$",
6956 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6958 emitcode ("jnz", "%05d$", tlbl->key + 100);
6959 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6961 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6976 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6977 genIfxJump (ifx, "c", left, right, result);
6981 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6982 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6983 if ((AOP_TYPE (right) == AOP_LIT) &&
6984 (AOP_TYPE (result) == AOP_CRY) &&
6985 (AOP_TYPE (left) != AOP_CRY))
6991 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6993 continueIfTrue (ifx);
6998 // lit = 0, result = boolean(left)
7000 emitcode ("setb", "c");
7004 symbol *tlbl = newiTempLabel (NULL);
7005 emitcode ("jnz", "%05d$", tlbl->key + 100);
7011 genIfxJump (ifx, "a", left, right, result);
7019 /* if left is same as result */
7020 if (sameRegs (AOP (result), AOP (left)))
7022 for (; size--; offset++)
7024 if (AOP_TYPE (right) == AOP_LIT)
7026 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7029 /* dummy read of volatile operand */
7030 if (isOperandVolatile (left, FALSE))
7031 MOVA (aopGet (left, offset, FALSE, FALSE));
7035 else if (bytelit == 0x0FF)
7037 aopPut (result, "#0xFF", offset);
7039 else if (IS_AOP_PREG (left))
7041 MOVA (aopGet (left, offset, FALSE, TRUE));
7042 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7043 aopPut (result, "a", offset);
7047 emitcode ("orl", "%s,%s",
7048 aopGet (left, offset, FALSE, TRUE),
7049 aopGet (right, offset, FALSE, FALSE));
7054 if (AOP_TYPE (left) == AOP_ACC)
7057 emitcode("mov", "a,b");
7058 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7060 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7062 MOVB (aopGet (left, offset, FALSE, FALSE));
7063 MOVA (aopGet (right, offset, FALSE, FALSE));
7064 emitcode ("orl", "a,b");
7065 aopPut (result, "a", offset);
7067 else if (aopGetUsesAcc (left, offset))
7069 MOVA (aopGet (left, offset, FALSE, FALSE));
7070 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7071 aopPut (result, "a", offset);
7075 MOVA (aopGet (right, offset, FALSE, FALSE));
7076 if (IS_AOP_PREG (left))
7078 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7079 aopPut (result, "a", offset);
7083 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7091 // left & result in different registers
7092 if (AOP_TYPE (result) == AOP_CRY)
7095 // if(size), result in bit
7096 // if(!size && ifx), conditional oper: if(left | right)
7097 symbol *tlbl = newiTempLabel (NULL);
7098 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7100 emitcode ("setb", "c");
7103 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7104 && AOP_TYPE(left)==AOP_ACC)
7107 emitcode("mov", "a,b");
7108 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7110 else if (AOP_TYPE(left)==AOP_ACC)
7114 bool pushedB = pushB ();
7115 emitcode("mov", "b,a");
7116 MOVA (aopGet (right, offset, FALSE, FALSE));
7117 emitcode("orl", "a,b");
7122 MOVA (aopGet (right, offset, FALSE, FALSE));
7123 emitcode("orl", "a,b");
7126 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7128 MOVB (aopGet (left, offset, FALSE, FALSE));
7129 MOVA (aopGet (right, offset, FALSE, FALSE));
7130 emitcode ("orl", "a,b");
7132 else if (aopGetUsesAcc (left, offset))
7134 MOVA (aopGet (left, offset, FALSE, FALSE));
7135 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7139 MOVA (aopGet (right, offset, FALSE, FALSE));
7140 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7143 emitcode ("jnz", "%05d$", tlbl->key + 100);
7153 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7159 for (; (size--); offset++)
7162 // result = left | right
7163 if (AOP_TYPE (right) == AOP_LIT)
7165 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7169 aopGet (left, offset, FALSE, FALSE),
7173 else if (bytelit == 0x0FF)
7175 /* dummy read of volatile operand */
7176 if (isOperandVolatile (left, FALSE))
7177 MOVA (aopGet (left, offset, FALSE, FALSE));
7178 aopPut (result, "#0xFF", offset);
7182 // faster than result <- left, orl result,right
7183 // and better if result is SFR
7184 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7185 && AOP_TYPE(left)==AOP_ACC)
7188 emitcode("mov", "a,b");
7189 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7191 else if (AOP_TYPE(left)==AOP_ACC)
7195 bool pushedB = pushB ();
7196 emitcode("mov", "b,a");
7197 MOVA (aopGet (right, offset, FALSE, FALSE));
7198 emitcode("orl", "a,b");
7203 MOVA (aopGet (right, offset, FALSE, FALSE));
7204 emitcode("orl", "a,b");
7207 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7209 MOVB (aopGet (left, offset, FALSE, FALSE));
7210 MOVA (aopGet (right, offset, FALSE, FALSE));
7211 emitcode ("orl", "a,b");
7213 else if (aopGetUsesAcc (left, offset))
7215 MOVA (aopGet (left, offset, FALSE, FALSE));
7216 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7220 MOVA (aopGet (right, offset, FALSE, FALSE));
7221 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7223 aopPut (result, "a", offset);
7229 freeAsmop (result, NULL, ic, TRUE);
7230 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7231 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7234 /*-----------------------------------------------------------------*/
7235 /* genXor - code for xclusive or */
7236 /*-----------------------------------------------------------------*/
7238 genXor (iCode * ic, iCode * ifx)
7240 operand *left, *right, *result;
7241 int size, offset = 0;
7242 unsigned long lit = 0L;
7245 D (emitcode (";", "genXor"));
7247 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7248 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7249 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7252 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7254 AOP_TYPE (left), AOP_TYPE (right));
7255 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7257 AOP_SIZE (left), AOP_SIZE (right));
7260 /* if left is a literal & right is not ||
7261 if left needs acc & right does not */
7262 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7263 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7265 operand *tmp = right;
7270 /* if result = right then exchange them */
7271 if (sameRegs (AOP (result), AOP (right)))
7273 operand *tmp = right;
7278 /* if right is bit then exchange them */
7279 if (AOP_TYPE (right) == AOP_CRY &&
7280 AOP_TYPE (left) != AOP_CRY)
7282 operand *tmp = right;
7286 if (AOP_TYPE (right) == AOP_LIT)
7287 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7289 size = AOP_SIZE (result);
7293 if (AOP_TYPE (left) == AOP_CRY)
7295 if (AOP_TYPE (right) == AOP_LIT)
7297 // c = bit & literal;
7300 // lit>>1 != 0 => result = 1
7301 if (AOP_TYPE (result) == AOP_CRY)
7304 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7306 continueIfTrue (ifx);
7309 emitcode ("setb", "c");
7316 // lit == 0, result = left
7317 if (size && sameRegs (AOP (result), AOP (left)))
7319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7323 // lit == 1, result = not(left)
7324 if (size && sameRegs (AOP (result), AOP (left)))
7326 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7331 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7332 emitcode ("cpl", "c");
7340 symbol *tlbl = newiTempLabel (NULL);
7341 if (AOP_TYPE (right) == AOP_CRY)
7344 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7348 int sizer = AOP_SIZE (right);
7350 // if val>>1 != 0, result = 1
7351 emitcode ("setb", "c");
7354 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7356 // test the msb of the lsb
7357 emitcode ("anl", "a,#0xfe");
7358 emitcode ("jnz", "%05d$", tlbl->key + 100);
7362 emitcode ("rrc", "a");
7364 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7365 emitcode ("cpl", "c");
7373 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7374 genIfxJump (ifx, "c", left, right, result);
7378 /* if left is same as result */
7379 if (sameRegs (AOP (result), AOP (left)))
7381 for (; size--; offset++)
7383 if (AOP_TYPE (right) == AOP_LIT)
7385 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7388 /* dummy read of volatile operand */
7389 if (isOperandVolatile (left, FALSE))
7390 MOVA (aopGet (left, offset, FALSE, FALSE));
7394 else if (IS_AOP_PREG (left))
7396 MOVA (aopGet (left, offset, FALSE, TRUE));
7397 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7398 aopPut (result, "a", offset);
7402 emitcode ("xrl", "%s,%s",
7403 aopGet (left, offset, FALSE, TRUE),
7404 aopGet (right, offset, FALSE, FALSE));
7409 if (AOP_TYPE (left) == AOP_ACC)
7412 emitcode("mov", "a,b");
7413 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7415 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7417 MOVB (aopGet (left, offset, FALSE, FALSE));
7418 MOVA (aopGet (right, offset, FALSE, FALSE));
7419 emitcode ("xrl", "a,b");
7420 aopPut (result, "a", offset);
7422 else if (aopGetUsesAcc (left, offset))
7424 MOVA (aopGet (left, offset, FALSE, FALSE));
7425 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7426 aopPut (result, "a", offset);
7430 MOVA (aopGet (right, offset, FALSE, FALSE));
7431 if (IS_AOP_PREG (left))
7433 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7434 aopPut (result, "a", offset);
7437 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7444 // left & result in different registers
7445 if (AOP_TYPE (result) == AOP_CRY)
7448 // if(size), result in bit
7449 // if(!size && ifx), conditional oper: if(left ^ right)
7450 symbol *tlbl = newiTempLabel (NULL);
7451 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7454 emitcode ("setb", "c");
7457 if ((AOP_TYPE (right) == AOP_LIT) &&
7458 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7460 MOVA (aopGet (left, offset, FALSE, FALSE));
7462 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7463 && AOP_TYPE(left)==AOP_ACC)
7466 emitcode("mov", "a,b");
7467 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7469 else if (AOP_TYPE(left)==AOP_ACC)
7473 bool pushedB = pushB ();
7474 emitcode("mov", "b,a");
7475 MOVA (aopGet (right, offset, FALSE, FALSE));
7476 emitcode("xrl", "a,b");
7481 MOVA (aopGet (right, offset, FALSE, FALSE));
7482 emitcode("xrl", "a,b");
7485 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7487 MOVB (aopGet (left, offset, FALSE, FALSE));
7488 MOVA (aopGet (right, offset, FALSE, FALSE));
7489 emitcode ("xrl", "a,b");
7491 else if (aopGetUsesAcc (left, offset))
7493 MOVA (aopGet (left, offset, FALSE, FALSE));
7494 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7498 MOVA (aopGet (right, offset, FALSE, FALSE));
7499 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7502 emitcode ("jnz", "%05d$", tlbl->key + 100);
7512 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7516 for (; (size--); offset++)
7519 // result = left ^ right
7520 if (AOP_TYPE (right) == AOP_LIT)
7522 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7526 aopGet (left, offset, FALSE, FALSE),
7531 // faster than result <- left, xrl result,right
7532 // and better if result is SFR
7533 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7534 && AOP_TYPE(left)==AOP_ACC)
7537 emitcode("mov", "a,b");
7538 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7540 else if (AOP_TYPE(left)==AOP_ACC)
7544 bool pushedB = pushB ();
7545 emitcode("mov", "b,a");
7546 MOVA (aopGet (right, offset, FALSE, FALSE));
7547 emitcode("xrl", "a,b");
7552 MOVA (aopGet (right, offset, FALSE, FALSE));
7553 emitcode("xrl", "a,b");
7556 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7558 MOVB (aopGet (left, offset, FALSE, FALSE));
7559 MOVA (aopGet (right, offset, FALSE, FALSE));
7560 emitcode ("xrl", "a,b");
7562 else if (aopGetUsesAcc (left, offset))
7564 MOVA (aopGet (left, offset, FALSE, FALSE));
7565 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7569 MOVA (aopGet (right, offset, FALSE, FALSE));
7570 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7572 aopPut (result, "a", offset);
7578 freeAsmop (result, NULL, ic, TRUE);
7579 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7580 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7583 /*-----------------------------------------------------------------*/
7584 /* genInline - write the inline code out */
7585 /*-----------------------------------------------------------------*/
7587 genInline (iCode * ic)
7589 char *buffer, *bp, *bp1;
7591 D (emitcode (";", "genInline"));
7593 _G.inLine += (!options.asmpeep);
7595 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7597 /* emit each line as a code */
7608 /* Add \n for labels, not dirs such as c:\mydir */
7609 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7623 /* emitcode("",buffer); */
7624 _G.inLine -= (!options.asmpeep);
7627 /*-----------------------------------------------------------------*/
7628 /* genRRC - rotate right with carry */
7629 /*-----------------------------------------------------------------*/
7633 operand *left, *result;
7637 D (emitcode (";", "genRRC"));
7639 /* rotate right with carry */
7640 left = IC_LEFT (ic);
7641 result = IC_RESULT (ic);
7642 aopOp (left, ic, FALSE);
7643 aopOp (result, ic, FALSE);
7645 /* move it to the result */
7646 size = AOP_SIZE (result);
7648 if (size == 1) { /* special case for 1 byte */
7649 l = aopGet (left, offset, FALSE, FALSE);
7651 emitcode ("rr", "a");
7654 /* no need to clear carry, bit7 will be written later */
7657 l = aopGet (left, offset, FALSE, FALSE);
7659 emitcode ("rrc", "a");
7660 if (AOP_SIZE (result) > 1)
7661 aopPut (result, "a", offset--);
7663 /* now we need to put the carry into the
7664 highest order byte of the result */
7665 if (AOP_SIZE (result) > 1)
7667 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7670 emitcode ("mov", "acc.7,c");
7672 aopPut (result, "a", AOP_SIZE (result) - 1);
7673 freeAsmop (result, NULL, ic, TRUE);
7674 freeAsmop (left, NULL, ic, TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genRLC - generate code for rotate left with carry */
7679 /*-----------------------------------------------------------------*/
7683 operand *left, *result;
7687 D (emitcode (";", "genRLC"));
7689 /* rotate right with carry */
7690 left = IC_LEFT (ic);
7691 result = IC_RESULT (ic);
7692 aopOp (left, ic, FALSE);
7693 aopOp (result, ic, FALSE);
7695 /* move it to the result */
7696 size = AOP_SIZE (result);
7700 l = aopGet (left, offset, FALSE, FALSE);
7702 if (size == 0) { /* special case for 1 byte */
7706 emitcode("rlc","a"); /* bit0 will be written later */
7707 if (AOP_SIZE (result) > 1)
7709 aopPut (result, "a", offset++);
7714 l = aopGet (left, offset, FALSE, FALSE);
7716 emitcode ("rlc", "a");
7717 if (AOP_SIZE (result) > 1)
7718 aopPut (result, "a", offset++);
7721 /* now we need to put the carry into the
7722 highest order byte of the result */
7723 if (AOP_SIZE (result) > 1)
7725 l = aopGet (result, 0, FALSE, FALSE);
7728 emitcode ("mov", "acc.0,c");
7730 aopPut (result, "a", 0);
7731 freeAsmop (result, NULL, ic, TRUE);
7732 freeAsmop (left, NULL, ic, TRUE);
7735 /*-----------------------------------------------------------------*/
7736 /* genGetHbit - generates code get highest order bit */
7737 /*-----------------------------------------------------------------*/
7739 genGetHbit (iCode * ic)
7741 operand *left, *result;
7743 D (emitcode (";", "genGetHbit"));
7745 left = IC_LEFT (ic);
7746 result = IC_RESULT (ic);
7747 aopOp (left, ic, FALSE);
7748 aopOp (result, ic, FALSE);
7750 /* get the highest order byte into a */
7751 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7752 if (AOP_TYPE (result) == AOP_CRY)
7754 emitcode ("rlc", "a");
7759 emitcode ("rl", "a");
7760 emitcode ("anl", "a,#0x01");
7764 freeAsmop (result, NULL, ic, TRUE);
7765 freeAsmop (left, NULL, ic, TRUE);
7768 /*-----------------------------------------------------------------*/
7769 /* genGetAbit - generates code get a single bit */
7770 /*-----------------------------------------------------------------*/
7772 genGetAbit (iCode * ic)
7774 operand *left, *right, *result;
7777 D (emitcode (";", "genGetAbit"));
7779 left = IC_LEFT (ic);
7780 right = IC_RIGHT (ic);
7781 result = IC_RESULT (ic);
7782 aopOp (left, ic, FALSE);
7783 aopOp (right, ic, FALSE);
7784 aopOp (result, ic, FALSE);
7786 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7788 /* get the needed byte into a */
7789 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7791 if (AOP_TYPE (result) == AOP_CRY)
7794 emitcode ("rlc", "a");
7795 else if ((shCount) == 0)
7796 emitcode ("rrc", "a");
7798 emitcode ("mov", "c,acc[%d]", shCount);
7806 emitcode ("rr", "a");
7809 emitcode ("rr", "a");
7812 emitcode ("anl", "a,#0x01");
7816 emitcode ("mov", "c,acc[%d]", shCount);
7817 emitcode ("clr", "a");
7818 emitcode ("rlc", "a");
7821 emitcode ("swap", "a");
7822 emitcode ("anl", "a,#0x01");
7825 emitcode ("rl", "a");
7828 emitcode ("rl", "a");
7829 emitcode ("anl", "a,#0x01");
7835 freeAsmop (result, NULL, ic, TRUE);
7836 freeAsmop (right, NULL, ic, TRUE);
7837 freeAsmop (left, NULL, ic, TRUE);
7840 /*-----------------------------------------------------------------*/
7841 /* genGetByte - generates code get a single byte */
7842 /*-----------------------------------------------------------------*/
7844 genGetByte (iCode * ic)
7846 operand *left, *right, *result;
7849 D (emitcode (";", "genGetByte"));
7851 left = IC_LEFT (ic);
7852 right = IC_RIGHT (ic);
7853 result = IC_RESULT (ic);
7854 aopOp (left, ic, FALSE);
7855 aopOp (right, ic, FALSE);
7856 aopOp (result, ic, FALSE);
7858 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7860 aopGet (left, offset, FALSE, FALSE),
7863 freeAsmop (result, NULL, ic, TRUE);
7864 freeAsmop (right, NULL, ic, TRUE);
7865 freeAsmop (left, NULL, ic, TRUE);
7868 /*-----------------------------------------------------------------*/
7869 /* genGetWord - generates code get two bytes */
7870 /*-----------------------------------------------------------------*/
7872 genGetWord (iCode * ic)
7874 operand *left, *right, *result;
7877 D (emitcode (";", "genGetWord"));
7879 left = IC_LEFT (ic);
7880 right = IC_RIGHT (ic);
7881 result = IC_RESULT (ic);
7882 aopOp (left, ic, FALSE);
7883 aopOp (right, ic, FALSE);
7884 aopOp (result, ic, FALSE);
7886 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7888 aopGet (left, offset, FALSE, FALSE),
7891 aopGet (left, offset+1, FALSE, FALSE),
7894 freeAsmop (result, NULL, ic, TRUE);
7895 freeAsmop (right, NULL, ic, TRUE);
7896 freeAsmop (left, NULL, ic, TRUE);
7899 /*-----------------------------------------------------------------*/
7900 /* genSwap - generates code to swap nibbles or bytes */
7901 /*-----------------------------------------------------------------*/
7903 genSwap (iCode * ic)
7905 operand *left, *result;
7907 D(emitcode ("; genSwap",""));
7909 left = IC_LEFT (ic);
7910 result = IC_RESULT (ic);
7911 aopOp (left, ic, FALSE);
7912 aopOp (result, ic, FALSE);
7914 switch (AOP_SIZE (left))
7916 case 1: /* swap nibbles in byte */
7917 MOVA (aopGet (left, 0, FALSE, FALSE));
7918 emitcode ("swap", "a");
7919 aopPut (result, "a", 0);
7921 case 2: /* swap bytes in word */
7922 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7924 MOVA (aopGet (left, 0, FALSE, FALSE));
7925 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7926 aopPut (result, "a", 1);
7928 else if (operandsEqu (left, result))
7931 bool pushedB = FALSE, leftInB = FALSE;
7933 MOVA (aopGet (left, 0, FALSE, FALSE));
7934 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7937 emitcode ("mov", "b,a");
7941 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7942 aopPut (result, reg, 1);
7949 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7950 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7954 wassertl(FALSE, "unsupported SWAP operand size");
7957 freeAsmop (result, NULL, ic, TRUE);
7958 freeAsmop (left, NULL, ic, TRUE);
7961 /*-----------------------------------------------------------------*/
7962 /* AccRol - rotate left accumulator by known count */
7963 /*-----------------------------------------------------------------*/
7965 AccRol (int shCount)
7967 shCount &= 0x0007; // shCount : 0..7
7974 emitcode ("rl", "a");
7977 emitcode ("rl", "a");
7978 emitcode ("rl", "a");
7981 emitcode ("swap", "a");
7982 emitcode ("rr", "a");
7985 emitcode ("swap", "a");
7988 emitcode ("swap", "a");
7989 emitcode ("rl", "a");
7992 emitcode ("rr", "a");
7993 emitcode ("rr", "a");
7996 emitcode ("rr", "a");
8001 /*-----------------------------------------------------------------*/
8002 /* AccLsh - left shift accumulator by known count */
8003 /*-----------------------------------------------------------------*/
8005 AccLsh (int shCount)
8010 emitcode ("add", "a,acc");
8011 else if (shCount == 2)
8013 emitcode ("add", "a,acc");
8014 emitcode ("add", "a,acc");
8018 /* rotate left accumulator */
8020 /* and kill the lower order bits */
8021 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8026 /*-----------------------------------------------------------------*/
8027 /* AccRsh - right shift accumulator by known count */
8028 /*-----------------------------------------------------------------*/
8030 AccRsh (int shCount)
8037 emitcode ("rrc", "a");
8041 /* rotate right accumulator */
8042 AccRol (8 - shCount);
8043 /* and kill the higher order bits */
8044 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8049 /*-----------------------------------------------------------------*/
8050 /* AccSRsh - signed right shift accumulator by known count */
8051 /*-----------------------------------------------------------------*/
8053 AccSRsh (int shCount)
8060 emitcode ("mov", "c,acc.7");
8061 emitcode ("rrc", "a");
8063 else if (shCount == 2)
8065 emitcode ("mov", "c,acc.7");
8066 emitcode ("rrc", "a");
8067 emitcode ("mov", "c,acc.7");
8068 emitcode ("rrc", "a");
8072 tlbl = newiTempLabel (NULL);
8073 /* rotate right accumulator */
8074 AccRol (8 - shCount);
8075 /* and kill the higher order bits */
8076 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8077 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8078 emitcode ("orl", "a,#0x%02x",
8079 (unsigned char) ~SRMask[shCount]);
8085 /*-----------------------------------------------------------------*/
8086 /* shiftR1Left2Result - shift right one byte from left to result */
8087 /*-----------------------------------------------------------------*/
8089 shiftR1Left2Result (operand * left, int offl,
8090 operand * result, int offr,
8091 int shCount, int sign)
8093 MOVA (aopGet (left, offl, FALSE, FALSE));
8094 /* shift right accumulator */
8099 aopPut (result, "a", offr);
8102 /*-----------------------------------------------------------------*/
8103 /* shiftL1Left2Result - shift left one byte from left to result */
8104 /*-----------------------------------------------------------------*/
8106 shiftL1Left2Result (operand * left, int offl,
8107 operand * result, int offr, int shCount)
8110 l = aopGet (left, offl, FALSE, FALSE);
8112 /* shift left accumulator */
8114 aopPut (result, "a", offr);
8117 /*-----------------------------------------------------------------*/
8118 /* movLeft2Result - move byte from left to result */
8119 /*-----------------------------------------------------------------*/
8121 movLeft2Result (operand * left, int offl,
8122 operand * result, int offr, int sign)
8125 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8127 l = aopGet (left, offl, FALSE, FALSE);
8129 if (*l == '@' && (IS_AOP_PREG (result)))
8131 emitcode ("mov", "a,%s", l);
8132 aopPut (result, "a", offr);
8138 aopPut (result, l, offr);
8142 /* MSB sign in acc.7 ! */
8143 if (getDataSize (left) == offl + 1)
8146 aopPut (result, "a", offr);
8153 /*-----------------------------------------------------------------*/
8154 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8155 /*-----------------------------------------------------------------*/
8159 emitcode ("rrc", "a");
8160 emitcode ("xch", "a,%s", x);
8161 emitcode ("rrc", "a");
8162 emitcode ("xch", "a,%s", x);
8165 /*-----------------------------------------------------------------*/
8166 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8167 /*-----------------------------------------------------------------*/
8171 emitcode ("xch", "a,%s", x);
8172 emitcode ("rlc", "a");
8173 emitcode ("xch", "a,%s", x);
8174 emitcode ("rlc", "a");
8177 /*-----------------------------------------------------------------*/
8178 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8179 /*-----------------------------------------------------------------*/
8183 emitcode ("xch", "a,%s", x);
8184 emitcode ("add", "a,acc");
8185 emitcode ("xch", "a,%s", x);
8186 emitcode ("rlc", "a");
8189 /*-----------------------------------------------------------------*/
8190 /* AccAXLsh - left shift a:x by known count (0..7) */
8191 /*-----------------------------------------------------------------*/
8193 AccAXLsh (char *x, int shCount)
8208 case 5: // AAAAABBB:CCCCCDDD
8210 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8212 emitcode ("anl", "a,#0x%02x",
8213 SLMask[shCount]); // BBB00000:CCCCCDDD
8215 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8217 AccRol (shCount); // DDDCCCCC:BBB00000
8219 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8221 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8223 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8225 emitcode ("anl", "a,#0x%02x",
8226 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8228 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8230 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8233 case 6: // AAAAAABB:CCCCCCDD
8234 emitcode ("anl", "a,#0x%02x",
8235 SRMask[shCount]); // 000000BB:CCCCCCDD
8236 emitcode ("mov", "c,acc.0"); // c = B
8237 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8239 AccAXRrl1 (x); // BCCCCCCD:D000000B
8240 AccAXRrl1 (x); // BBCCCCCC:DD000000
8242 emitcode("rrc","a");
8243 emitcode("xch","a,%s", x);
8244 emitcode("rrc","a");
8245 emitcode("mov","c,acc.0"); //<< get correct bit
8246 emitcode("xch","a,%s", x);
8248 emitcode("rrc","a");
8249 emitcode("xch","a,%s", x);
8250 emitcode("rrc","a");
8251 emitcode("xch","a,%s", x);
8254 case 7: // a:x <<= 7
8256 emitcode ("anl", "a,#0x%02x",
8257 SRMask[shCount]); // 0000000B:CCCCCCCD
8259 emitcode ("mov", "c,acc.0"); // c = B
8261 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8263 AccAXRrl1 (x); // BCCCCCCC:D0000000
8271 /*-----------------------------------------------------------------*/
8272 /* AccAXRsh - right shift a:x known count (0..7) */
8273 /*-----------------------------------------------------------------*/
8275 AccAXRsh (char *x, int shCount)
8283 AccAXRrl1 (x); // 0->a:x
8288 AccAXRrl1 (x); // 0->a:x
8291 AccAXRrl1 (x); // 0->a:x
8296 case 5: // AAAAABBB:CCCCCDDD = a:x
8298 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8300 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8302 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8304 emitcode ("anl", "a,#0x%02x",
8305 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8307 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8309 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8311 emitcode ("anl", "a,#0x%02x",
8312 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8314 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8316 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8318 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8321 case 6: // AABBBBBB:CCDDDDDD
8323 emitcode ("mov", "c,acc.7");
8324 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8326 emitcode ("mov", "c,acc.7");
8327 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8329 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8331 emitcode ("anl", "a,#0x%02x",
8332 SRMask[shCount]); // 000000AA:BBBBBBCC
8335 case 7: // ABBBBBBB:CDDDDDDD
8337 emitcode ("mov", "c,acc.7"); // c = A
8339 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8341 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8343 emitcode ("anl", "a,#0x%02x",
8344 SRMask[shCount]); // 0000000A:BBBBBBBC
8352 /*-----------------------------------------------------------------*/
8353 /* AccAXRshS - right shift signed a:x known count (0..7) */
8354 /*-----------------------------------------------------------------*/
8356 AccAXRshS (char *x, int shCount)
8364 emitcode ("mov", "c,acc.7");
8365 AccAXRrl1 (x); // s->a:x
8369 emitcode ("mov", "c,acc.7");
8370 AccAXRrl1 (x); // s->a:x
8372 emitcode ("mov", "c,acc.7");
8373 AccAXRrl1 (x); // s->a:x
8378 case 5: // AAAAABBB:CCCCCDDD = a:x
8380 tlbl = newiTempLabel (NULL);
8381 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8383 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8385 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8387 emitcode ("anl", "a,#0x%02x",
8388 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8390 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8392 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8394 emitcode ("anl", "a,#0x%02x",
8395 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8397 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8399 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8401 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8403 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8404 emitcode ("orl", "a,#0x%02x",
8405 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8408 break; // SSSSAAAA:BBBCCCCC
8410 case 6: // AABBBBBB:CCDDDDDD
8412 tlbl = newiTempLabel (NULL);
8413 emitcode ("mov", "c,acc.7");
8414 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8416 emitcode ("mov", "c,acc.7");
8417 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8419 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8421 emitcode ("anl", "a,#0x%02x",
8422 SRMask[shCount]); // 000000AA:BBBBBBCC
8424 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8425 emitcode ("orl", "a,#0x%02x",
8426 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8430 case 7: // ABBBBBBB:CDDDDDDD
8432 tlbl = newiTempLabel (NULL);
8433 emitcode ("mov", "c,acc.7"); // c = A
8435 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8437 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8439 emitcode ("anl", "a,#0x%02x",
8440 SRMask[shCount]); // 0000000A:BBBBBBBC
8442 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8443 emitcode ("orl", "a,#0x%02x",
8444 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8453 /*-----------------------------------------------------------------*/
8454 /* shiftL2Left2Result - shift left two bytes from left to result */
8455 /*-----------------------------------------------------------------*/
8457 shiftL2Left2Result (operand * left, int offl,
8458 operand * result, int offr, int shCount)
8461 bool pushedB = FALSE;
8464 if (sameRegs (AOP (result), AOP (left)) &&
8465 ((offl + MSB16) == offr))
8467 /* don't crash result[offr] */
8468 MOVA (aopGet (left, offl, FALSE, FALSE));
8469 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8470 usedB = !strncmp(x, "b", 1);
8472 else if (aopGetUsesAcc (result, offr))
8474 movLeft2Result (left, offl, result, offr, 0);
8477 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8478 MOVA (aopGet (result, offr, FALSE, FALSE));
8479 emitcode ("xch", "a,b");
8484 movLeft2Result (left, offl, result, offr, 0);
8485 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8486 x = aopGet (result, offr, FALSE, FALSE);
8488 /* ax << shCount (x = lsb(result)) */
8489 AccAXLsh (x, shCount);
8492 emitcode ("xch", "a,b");
8493 aopPut (result, "a", offr);
8494 aopPut (result, "b", offr + MSB16);
8499 aopPut (result, "a", offr + MSB16);
8504 /*-----------------------------------------------------------------*/
8505 /* shiftR2Left2Result - shift right two bytes from left to result */
8506 /*-----------------------------------------------------------------*/
8508 shiftR2Left2Result (operand * left, int offl,
8509 operand * result, int offr,
8510 int shCount, int sign)
8513 bool pushedB = FALSE;
8516 if (sameRegs (AOP (result), AOP (left)) &&
8517 ((offl + MSB16) == offr))
8519 /* don't crash result[offr] */
8520 MOVA (aopGet (left, offl, FALSE, FALSE));
8521 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8522 usedB = !strncmp(x, "b", 1);
8524 else if (aopGetUsesAcc (result, offr))
8526 movLeft2Result (left, offl, result, offr, 0);
8529 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8530 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8535 movLeft2Result (left, offl, result, offr, 0);
8536 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8537 x = aopGet (result, offr, FALSE, FALSE);
8539 /* a:x >> shCount (x = lsb(result)) */
8541 AccAXRshS (x, shCount);
8543 AccAXRsh (x, shCount);
8546 emitcode ("xch", "a,b");
8547 aopPut (result, "a", offr);
8548 emitcode ("xch", "a,b");
8551 if (getDataSize (result) > 1)
8552 aopPut (result, "a", offr + MSB16);
8555 /*-----------------------------------------------------------------*/
8556 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8557 /*-----------------------------------------------------------------*/
8559 shiftLLeftOrResult (operand * left, int offl,
8560 operand * result, int offr, int shCount)
8562 MOVA (aopGet (left, offl, FALSE, FALSE));
8563 /* shift left accumulator */
8565 /* or with result */
8566 if (aopGetUsesAcc (result, offr))
8568 emitcode ("xch", "a,b");
8569 MOVA (aopGet (result, offr, FALSE, FALSE));
8570 emitcode ("orl", "a,b");
8574 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8576 /* back to result */
8577 aopPut (result, "a", offr);
8580 /*-----------------------------------------------------------------*/
8581 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8582 /*-----------------------------------------------------------------*/
8584 shiftRLeftOrResult (operand * left, int offl,
8585 operand * result, int offr, int shCount)
8587 MOVA (aopGet (left, offl, FALSE, FALSE));
8588 /* shift right accumulator */
8590 /* or with result */
8591 if (aopGetUsesAcc(result, offr))
8593 emitcode ("xch", "a,b");
8594 MOVA (aopGet (result, offr, FALSE, FALSE));
8595 emitcode ("orl", "a,b");
8599 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8601 /* back to result */
8602 aopPut (result, "a", offr);
8605 /*-----------------------------------------------------------------*/
8606 /* genlshOne - left shift a one byte quantity by known count */
8607 /*-----------------------------------------------------------------*/
8609 genlshOne (operand * result, operand * left, int shCount)
8611 D (emitcode (";", "genlshOne"));
8613 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8616 /*-----------------------------------------------------------------*/
8617 /* genlshTwo - left shift two bytes by known amount != 0 */
8618 /*-----------------------------------------------------------------*/
8620 genlshTwo (operand * result, operand * left, int shCount)
8624 D (emitcode (";", "genlshTwo"));
8626 size = getDataSize (result);
8628 /* if shCount >= 8 */
8636 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8638 movLeft2Result (left, LSB, result, MSB16, 0);
8640 aopPut (result, zero, LSB);
8643 /* 1 <= shCount <= 7 */
8647 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8649 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8653 /*-----------------------------------------------------------------*/
8654 /* shiftLLong - shift left one long from left to result */
8655 /* offl = LSB or MSB16 */
8656 /*-----------------------------------------------------------------*/
8658 shiftLLong (operand * left, operand * result, int offr)
8661 int size = AOP_SIZE (result);
8663 if (size >= LSB + offr)
8665 l = aopGet (left, LSB, FALSE, FALSE);
8667 emitcode ("add", "a,acc");
8668 if (sameRegs (AOP (left), AOP (result)) &&
8669 size >= MSB16 + offr && offr != LSB)
8670 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8672 aopPut (result, "a", LSB + offr);
8675 if (size >= MSB16 + offr)
8677 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8679 l = aopGet (left, MSB16, FALSE, FALSE);
8682 emitcode ("rlc", "a");
8683 if (sameRegs (AOP (left), AOP (result)) &&
8684 size >= MSB24 + offr && offr != LSB)
8685 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8687 aopPut (result, "a", MSB16 + offr);
8690 if (size >= MSB24 + offr)
8692 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8694 l = aopGet (left, MSB24, FALSE, FALSE);
8697 emitcode ("rlc", "a");
8698 if (sameRegs (AOP (left), AOP (result)) &&
8699 size >= MSB32 + offr && offr != LSB)
8700 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8702 aopPut (result, "a", MSB24 + offr);
8705 if (size > MSB32 + offr)
8707 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8709 l = aopGet (left, MSB32, FALSE, FALSE);
8712 emitcode ("rlc", "a");
8713 aopPut (result, "a", MSB32 + offr);
8716 aopPut (result, zero, LSB);
8719 /*-----------------------------------------------------------------*/
8720 /* genlshFour - shift four byte by a known amount != 0 */
8721 /*-----------------------------------------------------------------*/
8723 genlshFour (operand * result, operand * left, int shCount)
8727 D (emitcode (";", "genlshFour"));
8729 size = AOP_SIZE (result);
8731 /* if shifting more that 3 bytes */
8736 /* lowest order of left goes to the highest
8737 order of the destination */
8738 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8740 movLeft2Result (left, LSB, result, MSB32, 0);
8741 aopPut (result, zero, LSB);
8742 aopPut (result, zero, MSB16);
8743 aopPut (result, zero, MSB24);
8747 /* more than two bytes */
8748 else if (shCount >= 16)
8750 /* lower order two bytes goes to higher order two bytes */
8752 /* if some more remaining */
8754 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8757 movLeft2Result (left, MSB16, result, MSB32, 0);
8758 movLeft2Result (left, LSB, result, MSB24, 0);
8760 aopPut (result, zero, MSB16);
8761 aopPut (result, zero, LSB);
8765 /* if more than 1 byte */
8766 else if (shCount >= 8)
8768 /* lower order three bytes goes to higher order three bytes */
8773 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8775 movLeft2Result (left, LSB, result, MSB16, 0);
8781 movLeft2Result (left, MSB24, result, MSB32, 0);
8782 movLeft2Result (left, MSB16, result, MSB24, 0);
8783 movLeft2Result (left, LSB, result, MSB16, 0);
8784 aopPut (result, zero, LSB);
8786 else if (shCount == 1)
8787 shiftLLong (left, result, MSB16);
8790 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8791 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8792 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8793 aopPut (result, zero, LSB);
8798 /* 1 <= shCount <= 7 */
8799 else if (shCount <= 2)
8801 shiftLLong (left, result, LSB);
8803 shiftLLong (result, result, LSB);
8805 /* 3 <= shCount <= 7, optimize */
8808 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8809 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8810 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8814 /*-----------------------------------------------------------------*/
8815 /* genLeftShiftLiteral - left shifting by known count */
8816 /*-----------------------------------------------------------------*/
8818 genLeftShiftLiteral (operand * left,
8823 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8826 D (emitcode (";", "genLeftShiftLiteral"));
8828 freeAsmop (right, NULL, ic, TRUE);
8830 aopOp (left, ic, FALSE);
8831 aopOp (result, ic, FALSE);
8833 size = getSize (operandType (result));
8836 emitcode ("; shift left ", "result %d, left %d", size,
8840 /* I suppose that the left size >= result size */
8845 movLeft2Result (left, size, result, size, 0);
8848 else if (shCount >= (size * 8))
8852 aopPut (result, zero, size);
8860 genlshOne (result, left, shCount);
8864 genlshTwo (result, left, shCount);
8868 genlshFour (result, left, shCount);
8871 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8872 "*** ack! mystery literal shift!\n");
8876 freeAsmop (result, NULL, ic, TRUE);
8877 freeAsmop (left, NULL, ic, TRUE);
8880 /*-----------------------------------------------------------------*/
8881 /* genLeftShift - generates code for left shifting */
8882 /*-----------------------------------------------------------------*/
8884 genLeftShift (iCode * ic)
8886 operand *left, *right, *result;
8889 symbol *tlbl, *tlbl1;
8892 D (emitcode (";", "genLeftShift"));
8894 right = IC_RIGHT (ic);
8895 left = IC_LEFT (ic);
8896 result = IC_RESULT (ic);
8898 aopOp (right, ic, FALSE);
8900 /* if the shift count is known then do it
8901 as efficiently as possible */
8902 if (AOP_TYPE (right) == AOP_LIT)
8904 genLeftShiftLiteral (left, right, result, ic);
8908 /* shift count is unknown then we have to form
8909 a loop get the loop count in B : Note: we take
8910 only the lower order byte since shifting
8911 more that 32 bits make no sense anyway, ( the
8912 largest size of an object can be only 32 bits ) */
8915 MOVB (aopGet (right, 0, FALSE, FALSE));
8916 emitcode ("inc", "b");
8917 freeAsmop (right, NULL, ic, TRUE);
8918 aopOp (left, ic, FALSE);
8919 aopOp (result, ic, FALSE);
8921 /* now move the left to the result if they are not the same */
8922 if (!sameRegs (AOP (left), AOP (result)) &&
8923 AOP_SIZE (result) > 1)
8926 size = AOP_SIZE (result);
8930 l = aopGet (left, offset, FALSE, TRUE);
8931 if (*l == '@' && (IS_AOP_PREG (result)))
8934 emitcode ("mov", "a,%s", l);
8935 aopPut (result, "a", offset);
8938 aopPut (result, l, offset);
8943 tlbl = newiTempLabel (NULL);
8944 size = AOP_SIZE (result);
8946 tlbl1 = newiTempLabel (NULL);
8948 /* if it is only one byte then */
8951 symbol *tlbl1 = newiTempLabel (NULL);
8953 l = aopGet (left, 0, FALSE, FALSE);
8955 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8957 emitcode ("add", "a,acc");
8959 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8961 aopPut (result, "a", 0);
8965 reAdjustPreg (AOP (result));
8967 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8969 l = aopGet (result, offset, FALSE, FALSE);
8971 emitcode ("add", "a,acc");
8972 aopPut (result, "a", offset++);
8975 l = aopGet (result, offset, FALSE, FALSE);
8977 emitcode ("rlc", "a");
8978 aopPut (result, "a", offset++);
8980 reAdjustPreg (AOP (result));
8983 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8986 freeAsmop (result, NULL, ic, TRUE);
8987 freeAsmop (left, NULL, ic, TRUE);
8990 /*-----------------------------------------------------------------*/
8991 /* genrshOne - right shift a one byte quantity by known count */
8992 /*-----------------------------------------------------------------*/
8994 genrshOne (operand * result, operand * left,
8995 int shCount, int sign)
8997 D (emitcode (";", "genrshOne"));
8999 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9002 /*-----------------------------------------------------------------*/
9003 /* genrshTwo - right shift two bytes by known amount != 0 */
9004 /*-----------------------------------------------------------------*/
9006 genrshTwo (operand * result, operand * left,
9007 int shCount, int sign)
9009 D (emitcode (";", "genrshTwo"));
9011 /* if shCount >= 8 */
9016 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9018 movLeft2Result (left, MSB16, result, LSB, sign);
9019 addSign (result, MSB16, sign);
9022 /* 1 <= shCount <= 7 */
9024 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9027 /*-----------------------------------------------------------------*/
9028 /* shiftRLong - shift right one long from left to result */
9029 /* offl = LSB or MSB16 */
9030 /*-----------------------------------------------------------------*/
9032 shiftRLong (operand * left, int offl,
9033 operand * result, int sign)
9035 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9037 if (overlapping && offl>1)
9039 // we are in big trouble, but this shouldn't happen
9040 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9043 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9050 emitcode ("rlc", "a");
9051 emitcode ("subb", "a,acc");
9052 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9054 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9058 aopPut (result, "a", MSB32);
9059 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9064 if (aopPutUsesAcc (result, zero, MSB32))
9066 emitcode("xch", "a,b");
9067 aopPut (result, zero, MSB32);
9068 emitcode("xch", "a,b");
9072 aopPut (result, zero, MSB32);
9079 emitcode ("clr", "c");
9083 emitcode ("mov", "c,acc.7");
9086 emitcode ("rrc", "a");
9088 if (overlapping && offl==MSB16 &&
9089 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9091 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9095 aopPut (result, "a", MSB32 - offl);
9096 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9099 emitcode ("rrc", "a");
9100 if (overlapping && offl==MSB16 &&
9101 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9103 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9107 aopPut (result, "a", MSB24 - offl);
9108 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9111 emitcode ("rrc", "a");
9114 aopPut (result, "a", MSB16 - offl);
9119 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9121 xch_a_aopGet (left, LSB, FALSE, FALSE);
9125 aopPut (result, "a", MSB16 - offl);
9126 MOVA (aopGet (left, LSB, FALSE, FALSE));
9128 emitcode ("rrc", "a");
9129 aopPut (result, "a", LSB);
9133 /*-----------------------------------------------------------------*/
9134 /* genrshFour - shift four byte by a known amount != 0 */
9135 /*-----------------------------------------------------------------*/
9137 genrshFour (operand * result, operand * left,
9138 int shCount, int sign)
9140 D (emitcode (";", "genrshFour"));
9142 /* if shifting more that 3 bytes */
9147 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9149 movLeft2Result (left, MSB32, result, LSB, sign);
9150 addSign (result, MSB16, sign);
9152 else if (shCount >= 16)
9156 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9159 movLeft2Result (left, MSB24, result, LSB, 0);
9160 movLeft2Result (left, MSB32, result, MSB16, sign);
9162 addSign (result, MSB24, sign);
9164 else if (shCount >= 8)
9169 shiftRLong (left, MSB16, result, sign);
9171 else if (shCount == 0)
9173 movLeft2Result (left, MSB16, result, LSB, 0);
9174 movLeft2Result (left, MSB24, result, MSB16, 0);
9175 movLeft2Result (left, MSB32, result, MSB24, sign);
9176 addSign (result, MSB32, sign);
9180 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9181 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9182 /* the last shift is signed */
9183 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9184 addSign (result, MSB32, sign);
9189 /* 1 <= shCount <= 7 */
9192 shiftRLong (left, LSB, result, sign);
9194 shiftRLong (result, LSB, result, sign);
9198 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9199 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9200 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9205 /*-----------------------------------------------------------------*/
9206 /* genRightShiftLiteral - right shifting by known count */
9207 /*-----------------------------------------------------------------*/
9209 genRightShiftLiteral (operand * left,
9215 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9218 D (emitcode (";", "genRightShiftLiteral"));
9220 freeAsmop (right, NULL, ic, TRUE);
9222 aopOp (left, ic, FALSE);
9223 aopOp (result, ic, FALSE);
9226 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9230 size = getDataSize (left);
9231 /* test the LEFT size !!! */
9233 /* I suppose that the left size >= result size */
9236 size = getDataSize (result);
9238 movLeft2Result (left, size, result, size, 0);
9241 else if (shCount >= (size * 8))
9245 /* get sign in acc.7 */
9246 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9248 addSign (result, LSB, sign);
9255 genrshOne (result, left, shCount, sign);
9259 genrshTwo (result, left, shCount, sign);
9263 genrshFour (result, left, shCount, sign);
9269 freeAsmop (result, NULL, ic, TRUE);
9270 freeAsmop (left, NULL, ic, TRUE);
9273 /*-----------------------------------------------------------------*/
9274 /* genSignedRightShift - right shift of signed number */
9275 /*-----------------------------------------------------------------*/
9277 genSignedRightShift (iCode * ic)
9279 operand *right, *left, *result;
9282 symbol *tlbl, *tlbl1;
9285 D (emitcode (";", "genSignedRightShift"));
9287 /* we do it the hard way put the shift count in b
9288 and loop thru preserving the sign */
9290 right = IC_RIGHT (ic);
9291 left = IC_LEFT (ic);
9292 result = IC_RESULT (ic);
9294 aopOp (right, ic, FALSE);
9297 if (AOP_TYPE (right) == AOP_LIT)
9299 genRightShiftLiteral (left, right, result, ic, 1);
9302 /* shift count is unknown then we have to form
9303 a loop get the loop count in B : Note: we take
9304 only the lower order byte since shifting
9305 more that 32 bits make no sense anyway, ( the
9306 largest size of an object can be only 32 bits ) */
9309 MOVB (aopGet (right, 0, FALSE, FALSE));
9310 emitcode ("inc", "b");
9311 freeAsmop (right, NULL, ic, TRUE);
9312 aopOp (left, ic, FALSE);
9313 aopOp (result, ic, FALSE);
9315 /* now move the left to the result if they are not the
9317 if (!sameRegs (AOP (left), AOP (result)) &&
9318 AOP_SIZE (result) > 1)
9321 size = AOP_SIZE (result);
9325 l = aopGet (left, offset, FALSE, TRUE);
9326 if (*l == '@' && IS_AOP_PREG (result))
9329 emitcode ("mov", "a,%s", l);
9330 aopPut (result, "a", offset);
9333 aopPut (result, l, offset);
9338 /* mov the highest order bit to OVR */
9339 tlbl = newiTempLabel (NULL);
9340 tlbl1 = newiTempLabel (NULL);
9342 size = AOP_SIZE (result);
9344 MOVA (aopGet (left, offset, FALSE, FALSE));
9345 emitcode ("rlc", "a");
9346 emitcode ("mov", "ov,c");
9347 /* if it is only one byte then */
9350 l = aopGet (left, 0, FALSE, FALSE);
9352 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9354 emitcode ("mov", "c,ov");
9355 emitcode ("rrc", "a");
9357 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9359 aopPut (result, "a", 0);
9363 reAdjustPreg (AOP (result));
9364 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9366 emitcode ("mov", "c,ov");
9369 l = aopGet (result, offset, FALSE, FALSE);
9371 emitcode ("rrc", "a");
9372 aopPut (result, "a", offset--);
9374 reAdjustPreg (AOP (result));
9376 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9380 freeAsmop (result, NULL, ic, TRUE);
9381 freeAsmop (left, NULL, ic, TRUE);
9384 /*-----------------------------------------------------------------*/
9385 /* genRightShift - generate code for right shifting */
9386 /*-----------------------------------------------------------------*/
9388 genRightShift (iCode * ic)
9390 operand *right, *left, *result;
9394 symbol *tlbl, *tlbl1;
9397 D (emitcode (";", "genRightShift"));
9399 /* if signed then we do it the hard way preserve the
9400 sign bit moving it inwards */
9401 letype = getSpec (operandType (IC_LEFT (ic)));
9403 if (!SPEC_USIGN (letype))
9405 genSignedRightShift (ic);
9409 /* signed & unsigned types are treated the same : i.e. the
9410 signed is NOT propagated inwards : quoting from the
9411 ANSI - standard : "for E1 >> E2, is equivalent to division
9412 by 2**E2 if unsigned or if it has a non-negative value,
9413 otherwise the result is implementation defined ", MY definition
9414 is that the sign does not get propagated */
9416 right = IC_RIGHT (ic);
9417 left = IC_LEFT (ic);
9418 result = IC_RESULT (ic);
9420 aopOp (right, ic, FALSE);
9422 /* if the shift count is known then do it
9423 as efficiently as possible */
9424 if (AOP_TYPE (right) == AOP_LIT)
9426 genRightShiftLiteral (left, right, result, ic, 0);
9430 /* shift count is unknown then we have to form
9431 a loop get the loop count in B : Note: we take
9432 only the lower order byte since shifting
9433 more that 32 bits make no sense anyway, ( the
9434 largest size of an object can be only 32 bits ) */
9437 MOVB (aopGet (right, 0, FALSE, FALSE));
9438 emitcode ("inc", "b");
9439 freeAsmop (right, NULL, ic, TRUE);
9440 aopOp (left, ic, FALSE);
9441 aopOp (result, ic, FALSE);
9443 /* now move the left to the result if they are not the
9445 if (!sameRegs (AOP (left), AOP (result)) &&
9446 AOP_SIZE (result) > 1)
9448 size = AOP_SIZE (result);
9452 l = aopGet (left, offset, FALSE, TRUE);
9453 if (*l == '@' && IS_AOP_PREG (result))
9456 emitcode ("mov", "a,%s", l);
9457 aopPut (result, "a", offset);
9460 aopPut (result, l, offset);
9465 tlbl = newiTempLabel (NULL);
9466 tlbl1 = newiTempLabel (NULL);
9467 size = AOP_SIZE (result);
9470 /* if it is only one byte then */
9473 l = aopGet (left, 0, FALSE, FALSE);
9475 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9478 emitcode ("rrc", "a");
9480 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9482 aopPut (result, "a", 0);
9486 reAdjustPreg (AOP (result));
9487 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9492 l = aopGet (result, offset, FALSE, FALSE);
9494 emitcode ("rrc", "a");
9495 aopPut (result, "a", offset--);
9497 reAdjustPreg (AOP (result));
9500 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9504 freeAsmop (result, NULL, ic, TRUE);
9505 freeAsmop (left, NULL, ic, TRUE);
9508 /*-----------------------------------------------------------------*/
9509 /* emitPtrByteGet - emits code to get a byte into A through a */
9510 /* pointer register (R0, R1, or DPTR). The */
9511 /* original value of A can be preserved in B. */
9512 /*-----------------------------------------------------------------*/
9514 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9521 emitcode ("mov", "b,a");
9522 emitcode ("mov", "a,@%s", rname);
9527 emitcode ("mov", "b,a");
9528 emitcode ("movx", "a,@%s", rname);
9533 emitcode ("mov", "b,a");
9534 emitcode ("movx", "a,@dptr");
9539 emitcode ("mov", "b,a");
9540 emitcode ("clr", "a");
9541 emitcode ("movc", "a,@a+dptr");
9547 emitcode ("push", "b");
9548 emitcode ("push", "acc");
9550 emitcode ("lcall", "__gptrget");
9552 emitcode ("pop", "b");
9557 /*-----------------------------------------------------------------*/
9558 /* emitPtrByteSet - emits code to set a byte from src through a */
9559 /* pointer register (R0, R1, or DPTR). */
9560 /*-----------------------------------------------------------------*/
9562 emitPtrByteSet (char *rname, int p_type, char *src)
9571 emitcode ("mov", "@%s,a", rname);
9574 emitcode ("mov", "@%s,%s", rname, src);
9579 emitcode ("movx", "@%s,a", rname);
9584 emitcode ("movx", "@dptr,a");
9589 emitcode ("lcall", "__gptrput");
9594 /*-----------------------------------------------------------------*/
9595 /* genUnpackBits - generates code for unpacking bits */
9596 /*-----------------------------------------------------------------*/
9598 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9600 int offset = 0; /* result byte offset */
9601 int rsize; /* result size */
9602 int rlen = 0; /* remaining bitfield length */
9603 sym_link *etype; /* bitfield type information */
9604 int blen; /* bitfield length */
9605 int bstr; /* bitfield starting bit within byte */
9608 D(emitcode ("; genUnpackBits",""));
9610 etype = getSpec (operandType (result));
9611 rsize = getSize (operandType (result));
9612 blen = SPEC_BLEN (etype);
9613 bstr = SPEC_BSTR (etype);
9615 if (ifx && blen <= 8)
9617 emitPtrByteGet (rname, ptype, FALSE);
9620 SNPRINTF (buffer, sizeof(buffer),
9622 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9627 emitcode ("anl", "a,#0x%02x",
9628 (((unsigned char) -1) >> (8 - blen)) << bstr);
9629 genIfxJump (ifx, "a", NULL, NULL, NULL);
9635 /* If the bitfield length is less than a byte */
9638 emitPtrByteGet (rname, ptype, FALSE);
9640 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9641 if (!SPEC_USIGN (etype))
9643 /* signed bitfield */
9644 symbol *tlbl = newiTempLabel (NULL);
9646 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9647 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9650 aopPut (result, "a", offset++);
9654 /* Bit field did not fit in a byte. Copy all
9655 but the partial byte at the end. */
9656 for (rlen=blen;rlen>=8;rlen-=8)
9658 emitPtrByteGet (rname, ptype, FALSE);
9659 aopPut (result, "a", offset++);
9661 emitcode ("inc", "%s", rname);
9664 /* Handle the partial byte at the end */
9667 emitPtrByteGet (rname, ptype, FALSE);
9668 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9669 if (!SPEC_USIGN (etype))
9671 /* signed bitfield */
9672 symbol *tlbl = newiTempLabel (NULL);
9674 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9675 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9678 aopPut (result, "a", offset++);
9686 if (SPEC_USIGN (etype))
9690 /* signed bitfield: sign extension with 0x00 or 0xff */
9691 emitcode ("rlc", "a");
9692 emitcode ("subb", "a,acc");
9698 aopPut (result, source, offset++);
9703 /*-----------------------------------------------------------------*/
9704 /* genDataPointerGet - generates code when ptr offset is known */
9705 /*-----------------------------------------------------------------*/
9707 genDataPointerGet (operand * left,
9713 int size, offset = 0;
9715 D (emitcode (";", "genDataPointerGet"));
9717 aopOp (result, ic, TRUE);
9719 /* get the string representation of the name */
9720 l = aopGet (left, 0, FALSE, TRUE);
9721 size = AOP_SIZE (result);
9726 SNPRINTF (buffer, sizeof(buffer),
9727 "(%s + %d)", l + 1, offset);
9731 SNPRINTF (buffer, sizeof(buffer),
9734 aopPut (result, buffer, offset++);
9737 freeAsmop (result, NULL, ic, TRUE);
9738 freeAsmop (left, NULL, ic, TRUE);
9741 /*-----------------------------------------------------------------*/
9742 /* genNearPointerGet - emitcode for near pointer fetch */
9743 /*-----------------------------------------------------------------*/
9745 genNearPointerGet (operand * left,
9754 sym_link *rtype, *retype;
9755 sym_link *ltype = operandType (left);
9758 D (emitcode (";", "genNearPointerGet"));
9760 rtype = operandType (result);
9761 retype = getSpec (rtype);
9763 aopOp (left, ic, FALSE);
9765 /* if left is rematerialisable and
9766 result is not bitfield variable type and
9767 the left is pointer to data space i.e
9768 lower 128 bytes of space */
9769 if (AOP_TYPE (left) == AOP_IMMD &&
9770 !IS_BITFIELD (retype) &&
9771 DCL_TYPE (ltype) == POINTER)
9773 genDataPointerGet (left, result, ic);
9777 /* if the value is already in a pointer register
9778 then don't need anything more */
9779 if (!AOP_INPREG (AOP (left)))
9781 if (IS_AOP_PREG (left))
9783 // Aha, it is a pointer, just in disguise.
9784 rname = aopGet (left, 0, FALSE, FALSE);
9787 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9788 __FILE__, __LINE__);
9793 emitcode ("mov", "a%s,%s", rname + 1, rname);
9794 rname++; // skip the '@'.
9799 /* otherwise get a free pointer register */
9801 preg = getFreePtr (ic, &aop, FALSE);
9802 emitcode ("mov", "%s,%s",
9804 aopGet (left, 0, FALSE, TRUE));
9809 rname = aopGet (left, 0, FALSE, FALSE);
9811 //aopOp (result, ic, FALSE);
9812 aopOp (result, ic, result?TRUE:FALSE);
9814 /* if bitfield then unpack the bits */
9815 if (IS_BITFIELD (retype))
9816 genUnpackBits (result, rname, POINTER, ifx);
9819 /* we have can just get the values */
9820 int size = AOP_SIZE (result);
9825 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9828 emitcode ("mov", "a,@%s", rname);
9830 aopPut (result, "a", offset);
9834 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9835 aopPut (result, buffer, offset);
9839 emitcode ("inc", "%s", rname);
9843 /* now some housekeeping stuff */
9844 if (aop) /* we had to allocate for this iCode */
9846 if (pi) { /* post increment present */
9847 aopPut (left, rname, 0);
9849 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9853 /* we did not allocate which means left
9854 already in a pointer register, then
9855 if size > 0 && this could be used again
9856 we have to point it back to where it
9858 if ((AOP_SIZE (result) > 1 &&
9859 !OP_SYMBOL (left)->remat &&
9860 (OP_SYMBOL (left)->liveTo > ic->seq ||
9864 int size = AOP_SIZE (result) - 1;
9866 emitcode ("dec", "%s", rname);
9870 if (ifx && !ifx->generated)
9872 genIfxJump (ifx, "a", left, NULL, result);
9876 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9877 freeAsmop (left, NULL, ic, TRUE);
9878 if (pi) pi->generated = 1;
9881 /*-----------------------------------------------------------------*/
9882 /* genPagedPointerGet - emitcode for paged pointer fetch */
9883 /*-----------------------------------------------------------------*/
9885 genPagedPointerGet (operand * left,
9894 sym_link *rtype, *retype;
9896 D (emitcode (";", "genPagedPointerGet"));
9898 rtype = operandType (result);
9899 retype = getSpec (rtype);
9901 aopOp (left, ic, FALSE);
9903 /* if the value is already in a pointer register
9904 then don't need anything more */
9905 if (!AOP_INPREG (AOP (left)))
9907 /* otherwise get a free pointer register */
9909 preg = getFreePtr (ic, &aop, FALSE);
9910 emitcode ("mov", "%s,%s",
9912 aopGet (left, 0, FALSE, TRUE));
9916 rname = aopGet (left, 0, FALSE, FALSE);
9918 aopOp (result, ic, FALSE);
9920 /* if bitfield then unpack the bits */
9921 if (IS_BITFIELD (retype))
9922 genUnpackBits (result, rname, PPOINTER, ifx);
9925 /* we have can just get the values */
9926 int size = AOP_SIZE (result);
9932 emitcode ("movx", "a,@%s", rname);
9934 aopPut (result, "a", offset);
9939 emitcode ("inc", "%s", rname);
9943 /* now some housekeeping stuff */
9944 if (aop) /* we had to allocate for this iCode */
9947 aopPut (left, rname, 0);
9948 freeAsmop (NULL, aop, ic, TRUE);
9952 /* we did not allocate which means left
9953 already in a pointer register, then
9954 if size > 0 && this could be used again
9955 we have to point it back to where it
9957 if ((AOP_SIZE (result) > 1 &&
9958 !OP_SYMBOL (left)->remat &&
9959 (OP_SYMBOL (left)->liveTo > ic->seq ||
9963 int size = AOP_SIZE (result) - 1;
9965 emitcode ("dec", "%s", rname);
9969 if (ifx && !ifx->generated)
9971 genIfxJump (ifx, "a", left, NULL, result);
9975 freeAsmop (result, NULL, ic, TRUE);
9976 freeAsmop (left, NULL, ic, TRUE);
9977 if (pi) pi->generated = 1;
9980 /*--------------------------------------------------------------------*/
9981 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9982 /*--------------------------------------------------------------------*/
9984 loadDptrFromOperand (operand *op, bool loadBToo)
9986 if (AOP_TYPE (op) != AOP_STR)
9988 /* if this is rematerializable */
9989 if (AOP_TYPE (op) == AOP_IMMD)
9991 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9994 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9995 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9998 wassertl(FALSE, "need pointerCode");
9999 emitcode ("", "; mov b,???");
10000 /* genPointerGet and genPointerSet originally did different
10001 ** things for this case. Both seem wrong.
10002 ** from genPointerGet:
10003 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10004 ** from genPointerSet:
10005 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10010 else if (AOP_TYPE (op) == AOP_DPTR)
10014 MOVA (aopGet (op, 0, FALSE, FALSE));
10015 emitcode ("push", "acc");
10016 MOVA (aopGet (op, 1, FALSE, FALSE));
10017 emitcode ("push", "acc");
10018 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10019 emitcode ("pop", "dph");
10020 emitcode ("pop", "dpl");
10024 MOVA (aopGet (op, 0, FALSE, FALSE));
10025 emitcode ("push", "acc");
10026 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10027 emitcode ("pop", "dpl");
10031 { /* we need to get it byte by byte */
10032 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10033 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10035 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10040 /*-----------------------------------------------------------------*/
10041 /* genFarPointerGet - get value from far space */
10042 /*-----------------------------------------------------------------*/
10044 genFarPointerGet (operand * left,
10045 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10048 sym_link *retype = getSpec (operandType (result));
10050 D (emitcode (";", "genFarPointerGet"));
10052 aopOp (left, ic, FALSE);
10053 loadDptrFromOperand (left, FALSE);
10055 /* so dptr now contains the address */
10056 aopOp (result, ic, FALSE);
10058 /* if bit then unpack */
10059 if (IS_BITFIELD (retype))
10060 genUnpackBits (result, "dptr", FPOINTER, ifx);
10063 size = AOP_SIZE (result);
10068 emitcode ("movx", "a,@dptr");
10070 aopPut (result, "a", offset++);
10072 emitcode ("inc", "dptr");
10076 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10078 aopPut (left, "dpl", 0);
10079 aopPut (left, "dph", 1);
10083 if (ifx && !ifx->generated)
10085 genIfxJump (ifx, "a", left, NULL, result);
10088 freeAsmop (result, NULL, ic, TRUE);
10089 freeAsmop (left, NULL, ic, TRUE);
10092 /*-----------------------------------------------------------------*/
10093 /* genCodePointerGet - get value from code space */
10094 /*-----------------------------------------------------------------*/
10096 genCodePointerGet (operand * left,
10097 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10100 sym_link *retype = getSpec (operandType (result));
10102 D (emitcode (";", "genCodePointerGet"));
10104 aopOp (left, ic, FALSE);
10105 loadDptrFromOperand (left, FALSE);
10107 /* so dptr now contains the address */
10108 aopOp (result, ic, FALSE);
10110 /* if bit then unpack */
10111 if (IS_BITFIELD (retype))
10112 genUnpackBits (result, "dptr", CPOINTER, ifx);
10115 size = AOP_SIZE (result);
10120 emitcode ("clr", "a");
10121 emitcode ("movc", "a,@a+dptr");
10123 aopPut (result, "a", offset++);
10125 emitcode ("inc", "dptr");
10129 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10131 aopPut (left, "dpl", 0);
10132 aopPut (left, "dph", 1);
10136 if (ifx && !ifx->generated)
10138 genIfxJump (ifx, "a", left, NULL, result);
10141 freeAsmop (result, NULL, ic, TRUE);
10142 freeAsmop (left, NULL, ic, TRUE);
10145 /*-----------------------------------------------------------------*/
10146 /* genGenPointerGet - get value from generic pointer space */
10147 /*-----------------------------------------------------------------*/
10149 genGenPointerGet (operand * left,
10150 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10153 sym_link *retype = getSpec (operandType (result));
10155 D (emitcode (";", "genGenPointerGet"));
10157 aopOp (left, ic, FALSE);
10158 loadDptrFromOperand (left, TRUE);
10160 /* so dptr now contains the address */
10161 aopOp (result, ic, FALSE);
10163 /* if bit then unpack */
10164 if (IS_BITFIELD (retype))
10166 genUnpackBits (result, "dptr", GPOINTER, ifx);
10170 size = AOP_SIZE (result);
10175 emitcode ("lcall", "__gptrget");
10177 aopPut (result, "a", offset++);
10179 emitcode ("inc", "dptr");
10183 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10185 aopPut (left, "dpl", 0);
10186 aopPut (left, "dph", 1);
10190 if (ifx && !ifx->generated)
10192 genIfxJump (ifx, "a", left, NULL, result);
10195 freeAsmop (result, NULL, ic, TRUE);
10196 freeAsmop (left, NULL, ic, TRUE);
10199 /*-----------------------------------------------------------------*/
10200 /* genPointerGet - generate code for pointer get */
10201 /*-----------------------------------------------------------------*/
10203 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10205 operand *left, *result;
10206 sym_link *type, *etype;
10209 D (emitcode (";", "genPointerGet"));
10211 left = IC_LEFT (ic);
10212 result = IC_RESULT (ic);
10214 if (getSize (operandType (result))>1)
10217 /* depending on the type of pointer we need to
10218 move it to the correct pointer register */
10219 type = operandType (left);
10220 etype = getSpec (type);
10221 /* if left is of type of pointer then it is simple */
10222 if (IS_PTR (type) && !IS_FUNC (type->next))
10223 p_type = DCL_TYPE (type);
10226 /* we have to go by the storage class */
10227 p_type = PTR_TYPE (SPEC_OCLS (etype));
10230 /* special case when cast remat */
10231 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10232 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10234 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10235 type = operandType (left);
10236 p_type = DCL_TYPE (type);
10238 /* now that we have the pointer type we assign
10239 the pointer values */
10245 genNearPointerGet (left, result, ic, pi, ifx);
10249 genPagedPointerGet (left, result, ic, pi, ifx);
10253 genFarPointerGet (left, result, ic, pi, ifx);
10257 genCodePointerGet (left, result, ic, pi, ifx);
10261 genGenPointerGet (left, result, ic, pi, ifx);
10267 /*-----------------------------------------------------------------*/
10268 /* genPackBits - generates code for packed bit storage */
10269 /*-----------------------------------------------------------------*/
10271 genPackBits (sym_link * etype,
10273 char *rname, int p_type)
10275 int offset = 0; /* source byte offset */
10276 int rlen = 0; /* remaining bitfield length */
10277 int blen; /* bitfield length */
10278 int bstr; /* bitfield starting bit within byte */
10279 int litval; /* source literal value (if AOP_LIT) */
10280 unsigned char mask; /* bitmask within current byte */
10282 D(emitcode ("; genPackBits",""));
10284 blen = SPEC_BLEN (etype);
10285 bstr = SPEC_BSTR (etype);
10287 /* If the bitfield length is less than a byte */
10290 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10291 (unsigned char) (0xFF >> (8 - bstr)));
10293 if (AOP_TYPE (right) == AOP_LIT)
10295 /* Case with a bitfield length <8 and literal source
10297 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10299 litval &= (~mask) & 0xff;
10300 emitPtrByteGet (rname, p_type, FALSE);
10301 if ((mask|litval)!=0xff)
10302 emitcode ("anl","a,#0x%02x", mask);
10304 emitcode ("orl","a,#0x%02x", litval);
10308 if ((blen==1) && (p_type!=GPOINTER))
10310 /* Case with a bitfield length == 1 and no generic pointer
10312 if (AOP_TYPE (right) == AOP_CRY)
10313 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10316 MOVA (aopGet (right, 0, FALSE, FALSE));
10317 emitcode ("rrc","a");
10319 emitPtrByteGet (rname, p_type, FALSE);
10320 emitcode ("mov","acc.%d,c",bstr);
10325 /* Case with a bitfield length < 8 and arbitrary source
10327 MOVA (aopGet (right, 0, FALSE, FALSE));
10328 /* shift and mask source value */
10330 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10332 pushedB = pushB ();
10333 /* transfer A to B and get next byte */
10334 emitPtrByteGet (rname, p_type, TRUE);
10336 emitcode ("anl", "a,#0x%02x", mask);
10337 emitcode ("orl", "a,b");
10338 if (p_type == GPOINTER)
10339 emitcode ("pop", "b");
10345 emitPtrByteSet (rname, p_type, "a");
10349 /* Bit length is greater than 7 bits. In this case, copy */
10350 /* all except the partial byte at the end */
10351 for (rlen=blen;rlen>=8;rlen-=8)
10353 emitPtrByteSet (rname, p_type,
10354 aopGet (right, offset++, FALSE, TRUE) );
10356 emitcode ("inc", "%s", rname);
10359 /* If there was a partial byte at the end */
10362 mask = (((unsigned char) -1 << rlen) & 0xff);
10364 if (AOP_TYPE (right) == AOP_LIT)
10366 /* Case with partial byte and literal source
10368 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10369 litval >>= (blen-rlen);
10370 litval &= (~mask) & 0xff;
10371 emitPtrByteGet (rname, p_type, FALSE);
10372 if ((mask|litval)!=0xff)
10373 emitcode ("anl","a,#0x%02x", mask);
10375 emitcode ("orl","a,#0x%02x", litval);
10380 /* Case with partial byte and arbitrary source
10382 MOVA (aopGet (right, offset++, FALSE, FALSE));
10383 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10385 pushedB = pushB ();
10386 /* transfer A to B and get next byte */
10387 emitPtrByteGet (rname, p_type, TRUE);
10389 emitcode ("anl", "a,#0x%02x", mask);
10390 emitcode ("orl", "a,b");
10391 if (p_type == GPOINTER)
10392 emitcode ("pop", "b");
10396 emitPtrByteSet (rname, p_type, "a");
10401 /*-----------------------------------------------------------------*/
10402 /* genDataPointerSet - remat pointer to data space */
10403 /*-----------------------------------------------------------------*/
10405 genDataPointerSet (operand * right,
10409 int size, offset = 0;
10410 char *l, buffer[256];
10412 D (emitcode (";", "genDataPointerSet"));
10414 aopOp (right, ic, FALSE);
10416 l = aopGet (result, 0, FALSE, TRUE);
10417 size = AOP_SIZE (right);
10421 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10423 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10424 emitcode ("mov", "%s,%s", buffer,
10425 aopGet (right, offset++, FALSE, FALSE));
10428 freeAsmop (result, NULL, ic, TRUE);
10429 freeAsmop (right, NULL, ic, TRUE);
10432 /*-----------------------------------------------------------------*/
10433 /* genNearPointerSet - emitcode for near pointer put */
10434 /*-----------------------------------------------------------------*/
10436 genNearPointerSet (operand * right,
10444 sym_link *retype, *letype;
10445 sym_link *ptype = operandType (result);
10447 D (emitcode (";", "genNearPointerSet"));
10449 retype = getSpec (operandType (right));
10450 letype = getSpec (ptype);
10452 aopOp (result, ic, FALSE);
10454 /* if the result is rematerializable &
10455 in data space & not a bit variable */
10456 if (AOP_TYPE (result) == AOP_IMMD &&
10457 DCL_TYPE (ptype) == POINTER &&
10458 !IS_BITVAR (retype) &&
10459 !IS_BITVAR (letype))
10461 genDataPointerSet (right, result, ic);
10465 /* if the value is already in a pointer register
10466 then don't need anything more */
10467 if (!AOP_INPREG (AOP (result)))
10470 //AOP_TYPE (result) == AOP_STK
10471 IS_AOP_PREG(result)
10474 // Aha, it is a pointer, just in disguise.
10475 rname = aopGet (result, 0, FALSE, FALSE);
10478 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10479 __FILE__, __LINE__);
10484 emitcode ("mov", "a%s,%s", rname + 1, rname);
10485 rname++; // skip the '@'.
10490 /* otherwise get a free pointer register */
10491 aop = newAsmop (0);
10492 preg = getFreePtr (ic, &aop, FALSE);
10493 emitcode ("mov", "%s,%s",
10495 aopGet (result, 0, FALSE, TRUE));
10496 rname = preg->name;
10501 rname = aopGet (result, 0, FALSE, FALSE);
10504 aopOp (right, ic, FALSE);
10506 /* if bitfield then unpack the bits */
10507 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10508 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10511 /* we can just get the values */
10512 int size = AOP_SIZE (right);
10517 l = aopGet (right, offset, FALSE, TRUE);
10518 if ((*l == '@') || (strcmp (l, "acc") == 0))
10521 emitcode ("mov", "@%s,a", rname);
10524 emitcode ("mov", "@%s,%s", rname, l);
10526 emitcode ("inc", "%s", rname);
10531 /* now some housekeeping stuff */
10532 if (aop) /* we had to allocate for this iCode */
10535 aopPut (result, rname, 0);
10536 freeAsmop (NULL, aop, ic, TRUE);
10540 /* we did not allocate which means left
10541 already in a pointer register, then
10542 if size > 0 && this could be used again
10543 we have to point it back to where it
10545 if ((AOP_SIZE (right) > 1 &&
10546 !OP_SYMBOL (result)->remat &&
10547 (OP_SYMBOL (result)->liveTo > ic->seq ||
10551 int size = AOP_SIZE (right) - 1;
10553 emitcode ("dec", "%s", rname);
10558 if (pi) pi->generated = 1;
10559 freeAsmop (result, NULL, ic, TRUE);
10560 freeAsmop (right, NULL, ic, TRUE);
10563 /*-----------------------------------------------------------------*/
10564 /* genPagedPointerSet - emitcode for Paged pointer put */
10565 /*-----------------------------------------------------------------*/
10567 genPagedPointerSet (operand * right,
10575 sym_link *retype, *letype;
10577 D (emitcode (";", "genPagedPointerSet"));
10579 retype = getSpec (operandType (right));
10580 letype = getSpec (operandType (result));
10582 aopOp (result, ic, FALSE);
10584 /* if the value is already in a pointer register
10585 then don't need anything more */
10586 if (!AOP_INPREG (AOP (result)))
10588 /* otherwise get a free pointer register */
10589 aop = newAsmop (0);
10590 preg = getFreePtr (ic, &aop, FALSE);
10591 emitcode ("mov", "%s,%s",
10593 aopGet (result, 0, FALSE, TRUE));
10594 rname = preg->name;
10597 rname = aopGet (result, 0, FALSE, FALSE);
10599 aopOp (right, ic, FALSE);
10601 /* if bitfield then unpack the bits */
10602 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10603 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10606 /* we have can just get the values */
10607 int size = AOP_SIZE (right);
10612 l = aopGet (right, offset, FALSE, TRUE);
10614 emitcode ("movx", "@%s,a", rname);
10617 emitcode ("inc", "%s", rname);
10623 /* now some housekeeping stuff */
10624 if (aop) /* we had to allocate for this iCode */
10627 aopPut (result, rname, 0);
10628 freeAsmop (NULL, aop, ic, TRUE);
10632 /* we did not allocate which means left
10633 already in a pointer register, then
10634 if size > 0 && this could be used again
10635 we have to point it back to where it
10637 if (AOP_SIZE (right) > 1 &&
10638 !OP_SYMBOL (result)->remat &&
10639 (OP_SYMBOL (result)->liveTo > ic->seq ||
10642 int size = AOP_SIZE (right) - 1;
10644 emitcode ("dec", "%s", rname);
10649 if (pi) pi->generated = 1;
10650 freeAsmop (result, NULL, ic, TRUE);
10651 freeAsmop (right, NULL, ic, TRUE);
10654 /*-----------------------------------------------------------------*/
10655 /* genFarPointerSet - set value from far space */
10656 /*-----------------------------------------------------------------*/
10658 genFarPointerSet (operand * right,
10659 operand * result, iCode * ic, iCode * pi)
10662 sym_link *retype = getSpec (operandType (right));
10663 sym_link *letype = getSpec (operandType (result));
10665 D(emitcode ("; genFarPointerSet",""));
10667 aopOp (result, ic, FALSE);
10668 loadDptrFromOperand (result, FALSE);
10670 /* so dptr now contains the address */
10671 aopOp (right, ic, FALSE);
10673 /* if bit then unpack */
10674 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10675 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10678 size = AOP_SIZE (right);
10683 char *l = aopGet (right, offset++, FALSE, FALSE);
10685 emitcode ("movx", "@dptr,a");
10687 emitcode ("inc", "dptr");
10690 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10691 aopPut (result, "dpl", 0);
10692 aopPut (result, "dph", 1);
10695 freeAsmop (result, NULL, ic, TRUE);
10696 freeAsmop (right, NULL, ic, TRUE);
10699 /*-----------------------------------------------------------------*/
10700 /* genGenPointerSet - set value from generic pointer space */
10701 /*-----------------------------------------------------------------*/
10703 genGenPointerSet (operand * right,
10704 operand * result, iCode * ic, iCode * pi)
10707 sym_link *retype = getSpec (operandType (right));
10708 sym_link *letype = getSpec (operandType (result));
10710 D (emitcode (";", "genGenPointerSet"));
10712 aopOp (result, ic, FALSE);
10713 loadDptrFromOperand (result, TRUE);
10715 /* so dptr now contains the address */
10716 aopOp (right, ic, FALSE);
10718 /* if bit then unpack */
10719 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10721 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10725 size = AOP_SIZE (right);
10730 char *l = aopGet (right, offset++, FALSE, FALSE);
10732 emitcode ("lcall", "__gptrput");
10734 emitcode ("inc", "dptr");
10738 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10739 aopPut (result, "dpl", 0);
10740 aopPut (result, "dph", 1);
10743 freeAsmop (result, NULL, ic, TRUE);
10744 freeAsmop (right, NULL, ic, TRUE);
10747 /*-----------------------------------------------------------------*/
10748 /* genPointerSet - stores the value into a pointer location */
10749 /*-----------------------------------------------------------------*/
10751 genPointerSet (iCode * ic, iCode *pi)
10753 operand *right, *result;
10754 sym_link *type, *etype;
10757 D (emitcode (";", "genPointerSet"));
10759 right = IC_RIGHT (ic);
10760 result = IC_RESULT (ic);
10762 /* depending on the type of pointer we need to
10763 move it to the correct pointer register */
10764 type = operandType (result);
10765 etype = getSpec (type);
10766 /* if left is of type of pointer then it is simple */
10767 if (IS_PTR (type) && !IS_FUNC (type->next))
10769 p_type = DCL_TYPE (type);
10773 /* we have to go by the storage class */
10774 p_type = PTR_TYPE (SPEC_OCLS (etype));
10777 /* special case when cast remat */
10778 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10779 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10780 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10781 type = operandType (result);
10782 p_type = DCL_TYPE (type);
10785 /* now that we have the pointer type we assign
10786 the pointer values */
10792 genNearPointerSet (right, result, ic, pi);
10796 genPagedPointerSet (right, result, ic, pi);
10800 genFarPointerSet (right, result, ic, pi);
10804 genGenPointerSet (right, result, ic, pi);
10808 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10809 "genPointerSet: illegal pointer type");
10813 /*-----------------------------------------------------------------*/
10814 /* genIfx - generate code for Ifx statement */
10815 /*-----------------------------------------------------------------*/
10817 genIfx (iCode * ic, iCode * popIc)
10819 operand *cond = IC_COND (ic);
10823 D (emitcode (";", "genIfx"));
10825 aopOp (cond, ic, FALSE);
10827 /* get the value into acc */
10828 if (AOP_TYPE (cond) != AOP_CRY)
10835 if (AOP(cond)->aopu.aop_dir)
10836 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10839 /* the result is now in the accumulator or a directly addressable bit */
10840 freeAsmop (cond, NULL, ic, TRUE);
10842 /* if there was something to be popped then do it */
10846 /* if the condition is a bit variable */
10848 genIfxJump(ic, dup, NULL, NULL, NULL);
10849 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10850 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10851 else if (isbit && !IS_ITEMP (cond))
10852 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10854 genIfxJump (ic, "a", NULL, NULL, NULL);
10859 /*-----------------------------------------------------------------*/
10860 /* genAddrOf - generates code for address of */
10861 /*-----------------------------------------------------------------*/
10863 genAddrOf (iCode * ic)
10865 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10868 D (emitcode (";", "genAddrOf"));
10870 aopOp (IC_RESULT (ic), ic, FALSE);
10872 /* if the operand is on the stack then we
10873 need to get the stack offset of this
10877 /* if it has an offset then we need to compute it */
10880 emitcode ("mov", "a,%s", SYM_BP (sym));
10881 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10882 ((char) (sym->stack - _G.nRegsSaved)) :
10883 ((char) sym->stack)) & 0xff);
10884 aopPut (IC_RESULT (ic), "a", 0);
10888 /* we can just move _bp */
10889 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10891 /* fill the result with zero */
10892 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10897 aopPut (IC_RESULT (ic), zero, offset++);
10902 /* object not on stack then we need the name */
10903 size = AOP_SIZE (IC_RESULT (ic));
10908 char s[SDCC_NAME_MAX];
10910 sprintf (s, "#(%s >> %d)",
10914 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10915 aopPut (IC_RESULT (ic), s, offset++);
10919 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10923 /*-----------------------------------------------------------------*/
10924 /* genFarFarAssign - assignment when both are in far space */
10925 /*-----------------------------------------------------------------*/
10927 genFarFarAssign (operand * result, operand * right, iCode * ic)
10929 int size = AOP_SIZE (right);
10933 D (emitcode (";", "genFarFarAssign"));
10935 /* first push the right side on to the stack */
10938 l = aopGet (right, offset++, FALSE, FALSE);
10940 emitcode ("push", "acc");
10943 freeAsmop (right, NULL, ic, FALSE);
10944 /* now assign DPTR to result */
10945 aopOp (result, ic, FALSE);
10946 size = AOP_SIZE (result);
10949 emitcode ("pop", "acc");
10950 aopPut (result, "a", --offset);
10952 freeAsmop (result, NULL, ic, FALSE);
10955 /*-----------------------------------------------------------------*/
10956 /* genAssign - generate code for assignment */
10957 /*-----------------------------------------------------------------*/
10959 genAssign (iCode * ic)
10961 operand *result, *right;
10963 unsigned long lit = 0L;
10965 D (emitcode (";", "genAssign"));
10967 result = IC_RESULT (ic);
10968 right = IC_RIGHT (ic);
10970 /* if they are the same */
10971 if (operandsEqu (result, right) &&
10972 !isOperandVolatile (result, FALSE) &&
10973 !isOperandVolatile (right, FALSE))
10976 aopOp (right, ic, FALSE);
10978 /* special case both in far space */
10979 if (AOP_TYPE (right) == AOP_DPTR &&
10980 IS_TRUE_SYMOP (result) &&
10981 isOperandInFarSpace (result))
10983 genFarFarAssign (result, right, ic);
10987 aopOp (result, ic, TRUE);
10989 /* if they are the same registers */
10990 if (sameRegs (AOP (right), AOP (result)) &&
10991 !isOperandVolatile (result, FALSE) &&
10992 !isOperandVolatile (right, FALSE))
10995 /* if the result is a bit */
10996 if (AOP_TYPE (result) == AOP_CRY)
10998 /* if the right size is a literal then
10999 we know what the value is */
11000 if (AOP_TYPE (right) == AOP_LIT)
11002 if (((int) operandLitValue (right)))
11003 aopPut (result, one, 0);
11005 aopPut (result, zero, 0);
11009 /* the right is also a bit variable */
11010 if (AOP_TYPE (right) == AOP_CRY)
11012 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11013 aopPut (result, "c", 0);
11017 /* we need to or */
11019 aopPut (result, "a", 0);
11023 /* bit variables done */
11025 size = AOP_SIZE (result);
11027 if (AOP_TYPE (right) == AOP_LIT)
11028 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11031 (AOP_TYPE (result) != AOP_REG) &&
11032 (AOP_TYPE (right) == AOP_LIT) &&
11033 !IS_FLOAT (operandType (right)) &&
11036 while ((size) && (lit))
11039 aopGet (right, offset, FALSE, FALSE),
11045 /* And now fill the rest with zeros. */
11048 emitcode ("clr", "a");
11052 aopPut (result, "a", offset);
11061 aopGet (right, offset, FALSE, FALSE),
11068 freeAsmop (result, NULL, ic, TRUE);
11069 freeAsmop (right, NULL, ic, TRUE);
11072 /*-----------------------------------------------------------------*/
11073 /* genJumpTab - generates code for jump table */
11074 /*-----------------------------------------------------------------*/
11076 genJumpTab (iCode * ic)
11078 symbol *jtab,*jtablo,*jtabhi;
11080 unsigned int count;
11082 D (emitcode (";", "genJumpTab"));
11084 count = elementsInSet( IC_JTLABELS (ic) );
11088 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11089 if the switch argument is in a register.
11090 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11091 /* Peephole may not convert ljmp to sjmp or ret
11092 labelIsReturnOnly & labelInRange must check
11093 currPl->ic->op != JUMPTABLE */
11094 aopOp (IC_JTCOND (ic), ic, FALSE);
11095 /* get the condition into accumulator */
11096 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11098 /* multiply by three */
11099 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11101 emitcode ("mov", "b,#3");
11102 emitcode ("mul", "ab");
11106 emitcode ("add", "a,acc");
11107 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11109 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11111 jtab = newiTempLabel (NULL);
11112 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11113 emitcode ("jmp", "@a+dptr");
11115 /* now generate the jump labels */
11116 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11117 jtab = setNextItem (IC_JTLABELS (ic)))
11118 emitcode ("ljmp", "%05d$", jtab->key + 100);
11122 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11123 if the switch argument is in a register.
11124 For n>6 this algorithm may be more compact */
11125 jtablo = newiTempLabel (NULL);
11126 jtabhi = newiTempLabel (NULL);
11128 /* get the condition into accumulator.
11129 Using b as temporary storage, if register push/pop is needed */
11130 aopOp (IC_JTCOND (ic), ic, FALSE);
11131 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11132 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11133 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11135 // (MB) what if B is in use???
11136 wassertl(!BINUSE, "B was in use");
11137 emitcode ("mov", "b,%s", l);
11140 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11144 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11145 emitcode ("movc", "a,@a+pc");
11146 emitcode ("push", "acc");
11149 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11150 emitcode ("movc", "a,@a+pc");
11151 emitcode ("push", "acc");
11155 /* this scales up to n<=255, but needs two more bytes
11156 and changes dptr */
11157 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11158 emitcode ("movc", "a,@a+dptr");
11159 emitcode ("push", "acc");
11162 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11163 emitcode ("movc", "a,@a+dptr");
11164 emitcode ("push", "acc");
11167 emitcode ("ret", "");
11169 /* now generate jump table, LSB */
11170 emitLabel (jtablo);
11171 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11172 jtab = setNextItem (IC_JTLABELS (ic)))
11173 emitcode (".db", "%05d$", jtab->key + 100);
11175 /* now generate jump table, MSB */
11176 emitLabel (jtabhi);
11177 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11178 jtab = setNextItem (IC_JTLABELS (ic)))
11179 emitcode (".db", "%05d$>>8", jtab->key + 100);
11183 /*-----------------------------------------------------------------*/
11184 /* genCast - gen code for casting */
11185 /*-----------------------------------------------------------------*/
11187 genCast (iCode * ic)
11189 operand *result = IC_RESULT (ic);
11190 sym_link *ctype = operandType (IC_LEFT (ic));
11191 sym_link *rtype = operandType (IC_RIGHT (ic));
11192 operand *right = IC_RIGHT (ic);
11195 D (emitcode (";", "genCast"));
11197 /* if they are equivalent then do nothing */
11198 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11201 aopOp (right, ic, FALSE);
11202 aopOp (result, ic, FALSE);
11204 /* if the result is a bit (and not a bitfield) */
11205 if (IS_BIT (OP_SYMBOL (result)->type))
11207 /* if the right size is a literal then
11208 we know what the value is */
11209 if (AOP_TYPE (right) == AOP_LIT)
11211 if (((int) operandLitValue (right)))
11212 aopPut (result, one, 0);
11214 aopPut (result, zero, 0);
11219 /* the right is also a bit variable */
11220 if (AOP_TYPE (right) == AOP_CRY)
11222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11223 aopPut (result, "c", 0);
11227 /* we need to or */
11229 aopPut (result, "a", 0);
11233 /* if they are the same size : or less */
11234 if (AOP_SIZE (result) <= AOP_SIZE (right))
11237 /* if they are in the same place */
11238 if (sameRegs (AOP (right), AOP (result)))
11241 /* if they in different places then copy */
11242 size = AOP_SIZE (result);
11247 aopGet (right, offset, FALSE, FALSE),
11254 /* if the result is of type pointer */
11255 if (IS_PTR (ctype))
11259 sym_link *type = operandType (right);
11260 sym_link *etype = getSpec (type);
11262 /* pointer to generic pointer */
11263 if (IS_GENPTR (ctype))
11267 p_type = DCL_TYPE (type);
11271 if (SPEC_SCLS(etype)==S_REGISTER) {
11272 // let's assume it is a generic pointer
11275 /* we have to go by the storage class */
11276 p_type = PTR_TYPE (SPEC_OCLS (etype));
11280 /* the first two bytes are known */
11281 size = GPTRSIZE - 1;
11286 aopGet (right, offset, FALSE, FALSE),
11290 /* the last byte depending on type */
11292 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11297 // pointerTypeToGPByte will have bitched.
11301 sprintf(gpValStr, "#0x%x", gpVal);
11302 aopPut (result, gpValStr, GPTRSIZE - 1);
11307 /* just copy the pointers */
11308 size = AOP_SIZE (result);
11313 aopGet (right, offset, FALSE, FALSE),
11320 /* so we now know that the size of destination is greater
11321 than the size of the source */
11322 /* we move to result for the size of source */
11323 size = AOP_SIZE (right);
11328 aopGet (right, offset, FALSE, FALSE),
11333 /* now depending on the sign of the source && destination */
11334 size = AOP_SIZE (result) - AOP_SIZE (right);
11335 /* if unsigned or not an integral type */
11336 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11339 aopPut (result, zero, offset++);
11343 /* we need to extend the sign :{ */
11344 char *l = aopGet (right, AOP_SIZE (right) - 1,
11347 emitcode ("rlc", "a");
11348 emitcode ("subb", "a,acc");
11350 aopPut (result, "a", offset++);
11353 /* we are done hurray !!!! */
11356 freeAsmop (result, NULL, ic, TRUE);
11357 freeAsmop (right, NULL, ic, TRUE);
11360 /*-----------------------------------------------------------------*/
11361 /* genDjnz - generate decrement & jump if not zero instrucion */
11362 /*-----------------------------------------------------------------*/
11364 genDjnz (iCode * ic, iCode * ifx)
11366 symbol *lbl, *lbl1;
11370 /* if the if condition has a false label
11371 then we cannot save */
11372 if (IC_FALSE (ifx))
11375 /* if the minus is not of the form a = a - 1 */
11376 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11377 !IS_OP_LITERAL (IC_RIGHT (ic)))
11380 if (operandLitValue (IC_RIGHT (ic)) != 1)
11383 /* if the size of this greater than one then no
11385 if (getSize (operandType (IC_RESULT (ic))) > 1)
11388 /* otherwise we can save BIG */
11390 D (emitcode (";", "genDjnz"));
11392 lbl = newiTempLabel (NULL);
11393 lbl1 = newiTempLabel (NULL);
11395 aopOp (IC_RESULT (ic), ic, FALSE);
11397 if (AOP_NEEDSACC(IC_RESULT(ic)))
11399 /* If the result is accessed indirectly via
11400 * the accumulator, we must explicitly write
11401 * it back after the decrement.
11403 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11405 if (strcmp(rByte, "a"))
11407 /* Something is hopelessly wrong */
11408 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11409 __FILE__, __LINE__);
11410 /* We can just give up; the generated code will be inefficient,
11411 * but what the hey.
11413 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11416 emitcode ("dec", "%s", rByte);
11417 aopPut (IC_RESULT (ic), rByte, 0);
11418 emitcode ("jnz", "%05d$", lbl->key + 100);
11420 else if (IS_AOP_PREG (IC_RESULT (ic)))
11422 emitcode ("dec", "%s",
11423 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11424 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11425 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11426 ifx->generated = 1;
11427 emitcode ("jnz", "%05d$", lbl->key + 100);
11431 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11434 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11436 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11439 if (!ifx->generated)
11440 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11441 ifx->generated = 1;
11445 /*-----------------------------------------------------------------*/
11446 /* genReceive - generate code for a receive iCode */
11447 /*-----------------------------------------------------------------*/
11449 genReceive (iCode * ic)
11451 int size = getSize (operandType (IC_RESULT (ic)));
11454 D (emitcode (";", "genReceive"));
11456 if (ic->argreg == 1)
11457 { /* first parameter */
11458 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11459 isOperandInPagedSpace (IC_RESULT (ic))) &&
11460 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11461 IS_TRUE_SYMOP (IC_RESULT (ic))))
11464 int receivingA = 0;
11467 for (offset = 0; offset<size; offset++)
11468 if (!strcmp (fReturn[offset], "a"))
11473 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11475 for (offset = size-1; offset>0; offset--)
11476 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11477 emitcode("mov","a,%s", fReturn[0]);
11479 aopOp (IC_RESULT (ic), ic, FALSE);
11481 aopPut (IC_RESULT (ic), "a", offset);
11482 for (offset = 1; offset<size; offset++)
11483 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11489 if (getTempRegs(tempRegs, size, ic))
11491 for (offset = 0; offset<size; offset++)
11492 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11493 aopOp (IC_RESULT (ic), ic, FALSE);
11494 for (offset = 0; offset<size; offset++)
11495 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11500 offset = fReturnSizeMCS51 - size;
11503 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11504 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11507 aopOp (IC_RESULT (ic), ic, FALSE);
11508 size = AOP_SIZE (IC_RESULT (ic));
11512 emitcode ("pop", "acc");
11513 aopPut (IC_RESULT (ic), "a", offset++);
11519 aopOp (IC_RESULT (ic), ic, FALSE);
11521 assignResultValue (IC_RESULT (ic), NULL);
11524 else if (ic->argreg > 12)
11525 { /* bit parameters */
11526 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11528 aopOp (IC_RESULT (ic), ic, FALSE);
11529 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11530 outBitC(IC_RESULT (ic));
11534 { /* other parameters */
11536 aopOp (IC_RESULT (ic), ic, FALSE);
11537 rb1off = ic->argreg;
11540 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11545 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11548 /*-----------------------------------------------------------------*/
11549 /* genDummyRead - generate code for dummy read of volatiles */
11550 /*-----------------------------------------------------------------*/
11552 genDummyRead (iCode * ic)
11557 D (emitcode(";", "genDummyRead"));
11559 op = IC_RIGHT (ic);
11560 if (op && IS_SYMOP (op))
11562 aopOp (op, ic, FALSE);
11564 /* if the result is a bit */
11565 if (AOP_TYPE (op) == AOP_CRY)
11566 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11569 /* bit variables done */
11571 size = AOP_SIZE (op);
11575 MOVA (aopGet (op, offset, FALSE, FALSE));
11580 freeAsmop (op, NULL, ic, TRUE);
11584 if (op && IS_SYMOP (op))
11586 aopOp (op, ic, FALSE);
11588 /* if the result is a bit */
11589 if (AOP_TYPE (op) == AOP_CRY)
11590 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11593 /* bit variables done */
11595 size = AOP_SIZE (op);
11599 MOVA (aopGet (op, offset, FALSE, FALSE));
11604 freeAsmop (op, NULL, ic, TRUE);
11608 /*-----------------------------------------------------------------*/
11609 /* genCritical - generate code for start of a critical sequence */
11610 /*-----------------------------------------------------------------*/
11612 genCritical (iCode *ic)
11614 symbol *tlbl = newiTempLabel (NULL);
11616 D (emitcode(";", "genCritical"));
11618 if (IC_RESULT (ic))
11620 aopOp (IC_RESULT (ic), ic, TRUE);
11621 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11622 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11623 aopPut (IC_RESULT (ic), zero, 0);
11625 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11629 emitcode ("setb", "c");
11630 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11631 emitcode ("clr", "c");
11633 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11637 /*-----------------------------------------------------------------*/
11638 /* genEndCritical - generate code for end of a critical sequence */
11639 /*-----------------------------------------------------------------*/
11641 genEndCritical (iCode *ic)
11643 D(emitcode("; genEndCritical",""));
11647 aopOp (IC_RIGHT (ic), ic, FALSE);
11648 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11650 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11651 emitcode ("mov", "ea,c");
11655 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11656 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11657 emitcode ("rrc", "a");
11658 emitcode ("mov", "ea,c");
11660 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11664 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11665 emitcode ("mov", "ea,c");
11669 /*-----------------------------------------------------------------*/
11670 /* gen51Code - generate code for 8051 based controllers */
11671 /*-----------------------------------------------------------------*/
11673 gen51Code (iCode * lic)
11677 /* int cseq = 0; */
11679 _G.currentFunc = NULL;
11680 lineHead = lineCurr = NULL;
11682 /* print the allocation information */
11683 if (allocInfo && currFunc)
11684 printAllocInfo (currFunc, codeOutFile);
11685 /* if debug information required */
11686 if (options.debug && currFunc)
11688 debugFile->writeFunction (currFunc, lic);
11690 /* stack pointer name */
11691 if (options.useXstack)
11697 for (ic = lic; ic; ic = ic->next)
11699 _G.current_iCode = ic;
11701 if (ic->lineno && cln != ic->lineno)
11705 debugFile->writeCLine (ic);
11707 if (!options.noCcodeInAsm) {
11708 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11709 printCLine(ic->filename, ic->lineno));
11714 if (ic->seqPoint && ic->seqPoint != cseq)
11716 emitcode ("", "; sequence point %d", ic->seqPoint);
11717 cseq = ic->seqPoint;
11720 if (options.iCodeInAsm) {
11721 char regsInUse[80];
11725 for (i=0; i<8; i++) {
11726 sprintf (®sInUse[i],
11727 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11730 strcpy (regsInUse, "--------");
11731 for (i=0; i < 8; i++) {
11732 if (bitVectBitValue (ic->rMask, i))
11734 int offset = regs8051[i].offset;
11735 regsInUse[offset] = offset + '0'; /* show rMask */
11739 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11741 /* if the result is marked as
11742 spilt and rematerializable or code for
11743 this has already been generated then
11745 if (resultRemat (ic) || ic->generated)
11748 /* depending on the operation */
11768 /* IPOP happens only when trying to restore a
11769 spilt live range, if there is an ifx statement
11770 following this pop then the if statement might
11771 be using some of the registers being popped which
11772 would destory the contents of the register so
11773 we need to check for this condition and handle it */
11775 ic->next->op == IFX &&
11776 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11777 genIfx (ic->next, ic);
11795 genEndFunction (ic);
11815 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11832 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11836 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11843 /* note these two are xlated by algebraic equivalence
11844 in decorateType() in SDCCast.c */
11845 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11846 "got '>=' or '<=' shouldn't have come here");
11850 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11862 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11866 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11870 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11906 genRightShift (ic);
11909 case GET_VALUE_AT_ADDRESS:
11911 hasInc (IC_LEFT (ic), ic,
11912 getSize (operandType (IC_RESULT (ic)))),
11913 ifxForOp (IC_RESULT (ic), ic) );
11917 if (POINTER_SET (ic))
11919 hasInc (IC_RESULT (ic), ic,
11920 getSize (operandType (IC_RIGHT (ic)))));
11946 addSet (&_G.sendSet, ic);
11949 case DUMMY_READ_VOLATILE:
11958 genEndCritical (ic);
11970 _G.current_iCode = NULL;
11972 /* now we are ready to call the
11973 peep hole optimizer */
11974 if (!options.nopeep)
11975 peepHole (&lineHead);
11977 /* now do the actual printing */
11978 printLine (lineHead, codeOutFile);