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 char offset = ((sym->stack < 0) ?
628 ((char) (sym->stack - _G.nRegsSaved)) :
629 ((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 /* sameReg - two asmops have the same register at given offsets */
853 /*-----------------------------------------------------------------*/
855 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
857 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
860 if (aop1->type != aop2->type)
863 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
869 /*-----------------------------------------------------------------*/
870 /* sameRegs - two asmops have the same registers */
871 /*-----------------------------------------------------------------*/
873 sameRegs (asmop * aop1, asmop * aop2)
880 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
883 if (aop1->type != aop2->type)
886 if (aop1->size != aop2->size)
889 for (i = 0; i < aop1->size; i++)
890 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
896 /*-----------------------------------------------------------------*/
897 /* aopOp - allocates an asmop for an operand : */
898 /*-----------------------------------------------------------------*/
900 aopOp (operand * op, iCode * ic, bool result)
909 /* if this a literal */
910 if (IS_OP_LITERAL (op))
912 op->aop = aop = newAsmop (AOP_LIT);
913 aop->aopu.aop_lit = op->operand.valOperand;
914 aop->size = getSize (operandType (op));
918 /* if already has a asmop then continue */
921 op->aop->allocated++;
925 /* if the underlying symbol has a aop */
926 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
928 op->aop = OP_SYMBOL (op)->aop;
929 op->aop->allocated++;
933 /* if this is a true symbol */
934 if (IS_TRUE_SYMOP (op))
936 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
940 /* this is a temporary : this has
946 e) can be a return use only */
948 sym = OP_SYMBOL (op);
950 /* if the type is a conditional */
951 if (sym->regType == REG_CND)
953 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
958 /* if it is spilt then two situations
960 b) has a spill location */
961 if (sym->isspilt || sym->nRegs == 0)
964 /* rematerialize it NOW */
967 sym->aop = op->aop = aop =
969 aop->size = getSize (sym->type);
976 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
977 aop->size = getSize (sym->type);
978 for (i = 0; i < 2; i++)
979 aop->aopu.aop_str[i] = accUse[i];
987 aop = op->aop = sym->aop = newAsmop (AOP_STR);
988 aop->size = getSize (sym->type);
989 for (i = 0; i < fReturnSizeMCS51; i++)
990 aop->aopu.aop_str[i] = fReturn[i];
994 if (sym->usl.spillLoc)
996 asmop *oldAsmOp = NULL;
998 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1000 /* force a new aop if sizes differ */
1001 oldAsmOp = sym->usl.spillLoc->aop;
1002 sym->usl.spillLoc->aop = NULL;
1004 sym->aop = op->aop = aop =
1005 aopForSym (ic, sym->usl.spillLoc, result);
1006 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1008 /* Don't reuse the new aop, go with the last one */
1009 sym->usl.spillLoc->aop = oldAsmOp;
1011 aop->size = getSize (sym->type);
1015 /* else must be a dummy iTemp */
1016 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1017 aop->size = getSize (sym->type);
1021 /* if the type is a bit register */
1022 if (sym->regType == REG_BIT)
1024 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1025 aop->size = sym->nRegs;//1???
1026 aop->aopu.aop_reg[0] = sym->regs[0];
1027 aop->aopu.aop_dir = sym->regs[0]->name;
1031 /* must be in a register */
1032 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1033 aop->size = sym->nRegs;
1034 for (i = 0; i < sym->nRegs; i++)
1035 aop->aopu.aop_reg[i] = sym->regs[i];
1038 /*-----------------------------------------------------------------*/
1039 /* freeAsmop - free up the asmop given to an operand */
1040 /*----------------------------------------------------------------*/
1042 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1059 /* depending on the asmop type only three cases need work
1060 AOP_R0, AOP_R1 & AOP_STK */
1066 emitcode ("mov", "r0,b");
1069 else if (_G.r0Pushed)
1073 emitcode ("pop", "ar0");
1077 bitVectUnSetBit (ic->rUsed, R0_IDX);
1083 emitcode ("mov", "r1,b");
1086 else if (_G.r1Pushed)
1090 emitcode ("pop", "ar1");
1094 bitVectUnSetBit (ic->rUsed, R1_IDX);
1100 int stk = aop->aopu.aop_stk + aop->size - 1;
1101 bitVectUnSetBit (ic->rUsed, R0_IDX);
1102 bitVectUnSetBit (ic->rUsed, R1_IDX);
1104 getFreePtr (ic, &aop, FALSE);
1108 emitcode ("mov", "a,_bp");
1109 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1110 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1114 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1119 emitcode ("pop", "acc");
1120 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1123 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126 freeAsmop (op, NULL, ic, TRUE);
1129 emitcode ("pop", "ar1");
1134 emitcode ("pop", "ar0");
1142 /* all other cases just dealloc */
1148 OP_SYMBOL (op)->aop = NULL;
1149 /* if the symbol has a spill */
1151 SPIL_LOC (op)->aop = NULL;
1156 /*------------------------------------------------------------------*/
1157 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1158 /* pop r0 or r1 off stack if pushed */
1159 /*------------------------------------------------------------------*/
1161 freeForBranchAsmop (operand * op)
1173 if (!aop->allocated)
1181 emitcode ("mov", "r0,b");
1183 else if (_G.r0Pushed)
1185 emitcode ("pop", "ar0");
1192 emitcode ("mov", "r1,b");
1194 else if (_G.r1Pushed)
1196 emitcode ("pop", "ar1");
1203 int stk = aop->aopu.aop_stk + aop->size - 1;
1205 emitcode ("mov", "b,r0");
1208 emitcode ("mov", "a,_bp");
1209 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1210 emitcode ("mov", "r0,a");
1214 emitcode ("mov", "r0,_bp");
1219 emitcode ("pop", "acc");
1220 emitcode ("mov", "@r0,a");
1223 emitcode ("dec", "r0");
1225 emitcode ("mov", "r0,b");
1231 /*-----------------------------------------------------------------*/
1232 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1233 /* clobber the accumulator */
1234 /*-----------------------------------------------------------------*/
1236 aopGetUsesAcc (operand * oper, int offset)
1238 asmop * aop = AOP (oper);
1240 if (offset > (aop->size - 1))
1258 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1269 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1275 /* Error case --- will have been caught already */
1281 /*-------------------------------------------------------------------*/
1282 /* aopGet - for fetching value of the aop */
1283 /*-------------------------------------------------------------------*/
1285 aopGet (operand * oper, int offset, bool bit16, bool dname)
1287 asmop * aop = AOP (oper);
1289 /* offset is greater than
1291 if (offset > (aop->size - 1) &&
1292 aop->type != AOP_LIT)
1295 /* depending on type */
1303 /* if we need to increment it */
1304 while (offset > aop->coff)
1306 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1310 while (offset < aop->coff)
1312 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1319 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1320 return (dname ? "acc" : "a");
1322 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1323 return Safe_strdup(buffer);
1326 if (aop->code && aop->coff==0 && offset>=1) {
1327 emitcode ("mov", "a,#0x%02x", offset);
1328 emitcode ("movc", "a,@a+dptr");
1329 return (dname ? "acc" : "a");
1332 while (offset > aop->coff)
1334 emitcode ("inc", "dptr");
1338 while (offset < aop->coff)
1340 emitcode ("lcall", "__decdptr");
1347 emitcode ("clr", "a");
1348 emitcode ("movc", "a,@a+dptr");
1352 emitcode ("movx", "a,@dptr");
1354 return (dname ? "acc" : "a");
1357 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1359 SNPRINTF(buffer, sizeof(buffer),
1360 "%s",aop->aopu.aop_immd.aop_immd2);
1364 SNPRINTF(buffer, sizeof(buffer),
1365 "#%s", aop->aopu.aop_immd.aop_immd1);
1369 SNPRINTF (buffer, sizeof(buffer),
1371 aop->aopu.aop_immd.aop_immd1,
1376 SNPRINTF (buffer, sizeof(buffer),
1378 aop->aopu.aop_immd.aop_immd1);
1380 return Safe_strdup(buffer);
1383 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1385 SNPRINTF (buffer, sizeof(buffer),
1387 aop->aopu.aop_dir, offset * 8);
1391 SNPRINTF (buffer, sizeof(buffer),
1398 SNPRINTF (buffer, sizeof(buffer),
1403 return Safe_strdup(buffer);
1407 return aop->aopu.aop_reg[offset]->dname;
1409 return aop->aopu.aop_reg[offset]->name;
1412 emitcode ("clr", "a");
1413 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1414 emitcode ("rlc", "a");
1415 return (dname ? "acc" : "a");
1418 if (!offset && dname)
1420 return aop->aopu.aop_str[offset];
1423 return aopLiteral (aop->aopu.aop_lit, offset);
1427 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1431 return aop->aopu.aop_str[offset];
1435 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1436 "aopget got unsupported aop->type");
1440 /*-----------------------------------------------------------------*/
1441 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1442 /* clobber the accumulator */
1443 /*-----------------------------------------------------------------*/
1445 aopPutUsesAcc (operand * oper, const char *s, int offset)
1447 asmop * aop = AOP (oper);
1449 if (offset > (aop->size - 1))
1459 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1465 return ((aop->paged) || (*s == '@'));
1469 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1477 /* Error case --- will have been caught already */
1483 /*-----------------------------------------------------------------*/
1484 /* aopPut - puts a string for a aop and indicates if acc is in use */
1485 /*-----------------------------------------------------------------*/
1487 aopPut (operand * result, const char *s, int offset)
1489 bool bvolatile = isOperandVolatile (result, FALSE);
1490 bool accuse = FALSE;
1491 asmop * aop = AOP (result);
1493 if (aop->size && offset > (aop->size - 1))
1495 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1496 "aopPut got offset > aop->size");
1500 /* will assign value to value */
1501 /* depending on where it is ofcourse */
1505 MOVA (s); /* read s in case it was volatile */
1510 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1512 SNPRINTF (buffer, sizeof(buffer),
1514 aop->aopu.aop_dir, offset * 8);
1518 SNPRINTF (buffer, sizeof(buffer),
1520 aop->aopu.aop_dir, offset);
1524 SNPRINTF (buffer, sizeof(buffer),
1529 if (strcmp (buffer, s) || bvolatile)
1531 emitcode ("mov", "%s,%s", buffer, s);
1533 if (!strcmp (buffer, "acc"))
1540 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1541 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1544 strcmp (s, "r0") == 0 ||
1545 strcmp (s, "r1") == 0 ||
1546 strcmp (s, "r2") == 0 ||
1547 strcmp (s, "r3") == 0 ||
1548 strcmp (s, "r4") == 0 ||
1549 strcmp (s, "r5") == 0 ||
1550 strcmp (s, "r6") == 0 ||
1551 strcmp (s, "r7") == 0)
1553 emitcode ("mov", "%s,%s",
1554 aop->aopu.aop_reg[offset]->dname, s);
1558 emitcode ("mov", "%s,%s",
1559 aop->aopu.aop_reg[offset]->name, s);
1567 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1568 "aopPut writing to code space");
1572 while (offset > aop->coff)
1575 emitcode ("inc", "dptr");
1578 while (offset < aop->coff)
1581 emitcode ("lcall", "__decdptr");
1586 /* if not in accumulator */
1589 emitcode ("movx", "@dptr,a");
1594 while (offset > aop->coff)
1597 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1599 while (offset < aop->coff)
1602 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1609 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1614 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1616 else if (strcmp (s, "r0") == 0 ||
1617 strcmp (s, "r1") == 0 ||
1618 strcmp (s, "r2") == 0 ||
1619 strcmp (s, "r3") == 0 ||
1620 strcmp (s, "r4") == 0 ||
1621 strcmp (s, "r5") == 0 ||
1622 strcmp (s, "r6") == 0 ||
1623 strcmp (s, "r7") == 0)
1626 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1627 emitcode ("mov", "@%s,%s",
1628 aop->aopu.aop_ptr->name, buffer);
1632 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1637 if (strcmp (s, "a") == 0)
1638 emitcode ("push", "acc");
1642 emitcode ("push", "acc");
1644 emitcode ("push", s);
1650 /* if not bit variable */
1651 if (!aop->aopu.aop_dir)
1653 /* inefficient: move carry into A and use jz/jnz */
1654 emitcode ("clr", "a");
1655 emitcode ("rlc", "a");
1661 emitcode ("clr", "%s", aop->aopu.aop_dir);
1663 emitcode ("setb", "%s", aop->aopu.aop_dir);
1664 else if (!strcmp (s, "c"))
1665 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1666 else if (strcmp (s, aop->aopu.aop_dir))
1669 /* set C, if a >= 1 */
1670 emitcode ("add", "a,#0xff");
1671 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1678 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1679 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1685 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1688 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1689 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1693 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1694 "aopPut got unsupported aop->type");
1703 /*-----------------------------------------------------------------*/
1704 /* pointToEnd :- points to the last byte of the operand */
1705 /*-----------------------------------------------------------------*/
1707 pointToEnd (asmop * aop)
1713 aop->coff = count = (aop->size - 1);
1719 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1723 emitcode ("inc", "dptr");
1730 /*-----------------------------------------------------------------*/
1731 /* reAdjustPreg - points a register back to where it should */
1732 /*-----------------------------------------------------------------*/
1734 reAdjustPreg (asmop * aop)
1736 if ((aop->coff==0) || (aop->size <= 1))
1744 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1749 emitcode ("lcall", "__decdptr");
1756 /*-----------------------------------------------------------------*/
1757 /* opIsGptr: returns non-zero if the passed operand is */
1758 /* a generic pointer type. */
1759 /*-----------------------------------------------------------------*/
1761 opIsGptr (operand * op)
1763 sym_link *type = operandType (op);
1765 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1772 /*-----------------------------------------------------------------*/
1773 /* getDataSize - get the operand data size */
1774 /*-----------------------------------------------------------------*/
1776 getDataSize (operand * op)
1779 size = AOP_SIZE (op);
1780 if (size == GPTRSIZE)
1782 sym_link *type = operandType (op);
1783 if (IS_GENPTR (type))
1785 /* generic pointer; arithmetic operations
1786 * should ignore the high byte (pointer type).
1794 /*-----------------------------------------------------------------*/
1795 /* outAcc - output Acc */
1796 /*-----------------------------------------------------------------*/
1798 outAcc (operand * result)
1801 size = getDataSize (result);
1804 aopPut (result, "a", 0);
1807 /* unsigned or positive */
1810 aopPut (result, zero, offset++);
1815 /*-----------------------------------------------------------------*/
1816 /* outBitC - output a bit C */
1817 /*-----------------------------------------------------------------*/
1819 outBitC (operand * result)
1821 /* if the result is bit */
1822 if (AOP_TYPE (result) == AOP_CRY)
1824 aopPut (result, "c", 0);
1828 emitcode ("clr", "a");
1829 emitcode ("rlc", "a");
1834 /*-----------------------------------------------------------------*/
1835 /* toBoolean - emit code for orl a,operator(sizeop) */
1836 /*-----------------------------------------------------------------*/
1838 toBoolean (operand * oper)
1840 int size = AOP_SIZE (oper) - 1;
1842 bool AccUsed = FALSE;
1845 while (!AccUsed && size--)
1847 AccUsed |= aopGetUsesAcc(oper, offset++);
1850 size = AOP_SIZE (oper) - 1;
1852 MOVA (aopGet (oper, 0, FALSE, FALSE));
1853 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1856 emitcode("mov", "b,a");
1859 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1860 emitcode ("orl", "b,a");
1862 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863 emitcode ("orl", "a,b");
1870 emitcode ("orl", "a,%s",
1871 aopGet (oper, offset++, FALSE, FALSE));
1877 /*-----------------------------------------------------------------*/
1878 /* genNot - generate code for ! operation */
1879 /*-----------------------------------------------------------------*/
1885 D (emitcode (";", "genNot"));
1887 /* assign asmOps to operand & result */
1888 aopOp (IC_LEFT (ic), ic, FALSE);
1889 aopOp (IC_RESULT (ic), ic, TRUE);
1891 /* if in bit space then a special case */
1892 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1894 /* if left==result then cpl bit */
1895 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1897 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1901 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1902 emitcode ("cpl", "c");
1903 outBitC (IC_RESULT (ic));
1908 toBoolean (IC_LEFT (ic));
1910 /* set C, if a == 0 */
1911 tlbl = newiTempLabel (NULL);
1912 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1914 outBitC (IC_RESULT (ic));
1917 /* release the aops */
1918 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1919 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1923 /*-----------------------------------------------------------------*/
1924 /* genCpl - generate code for complement */
1925 /*-----------------------------------------------------------------*/
1932 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1934 D(emitcode (";", "genCpl"));
1936 /* assign asmOps to operand & result */
1937 aopOp (IC_LEFT (ic), ic, FALSE);
1938 aopOp (IC_RESULT (ic), ic, TRUE);
1940 /* special case if in bit space */
1941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1945 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1946 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1948 /* promotion rules are responsible for this strange result:
1949 bit -> int -> ~int -> bit
1950 uchar -> int -> ~int -> bit
1952 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1956 tlbl=newiTempLabel(NULL);
1957 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1958 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1959 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1960 IS_AOP_PREG (IC_LEFT (ic)))
1962 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1967 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1970 outBitC (IC_RESULT(ic));
1974 size = AOP_SIZE (IC_RESULT (ic));
1977 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1979 emitcode ("cpl", "a");
1980 aopPut (IC_RESULT (ic), "a", offset++);
1985 /* release the aops */
1986 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1987 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1990 /*-----------------------------------------------------------------*/
1991 /* genUminusFloat - unary minus for floating points */
1992 /*-----------------------------------------------------------------*/
1994 genUminusFloat (operand * op, operand * result)
1996 int size, offset = 0;
1999 D (emitcode (";", "genUminusFloat"));
2001 /* for this we just copy and then flip the bit */
2003 size = AOP_SIZE (op) - 1;
2008 aopGet (op, offset, FALSE, FALSE),
2013 l = aopGet (op, offset, FALSE, FALSE);
2016 emitcode ("cpl", "acc.7");
2017 aopPut (result, "a", offset);
2020 /*-----------------------------------------------------------------*/
2021 /* genUminus - unary minus code generation */
2022 /*-----------------------------------------------------------------*/
2024 genUminus (iCode * ic)
2029 D (emitcode (";", "genUminus"));
2032 aopOp (IC_LEFT (ic), ic, FALSE);
2033 aopOp (IC_RESULT (ic), ic, TRUE);
2035 /* if both in bit space then special
2037 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2038 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2041 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2042 emitcode ("cpl", "c");
2043 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2047 optype = operandType (IC_LEFT (ic));
2049 /* if float then do float stuff */
2050 if (IS_FLOAT (optype))
2052 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2056 /* otherwise subtract from zero */
2057 size = AOP_SIZE (IC_LEFT (ic));
2061 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2062 if (!strcmp (l, "a"))
2066 emitcode ("cpl", "a");
2067 emitcode ("addc", "a,#0");
2073 emitcode ("clr", "a");
2074 emitcode ("subb", "a,%s", l);
2076 aopPut (IC_RESULT (ic), "a", offset++);
2079 /* if any remaining bytes in the result */
2080 /* we just need to propagate the sign */
2081 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2083 emitcode ("rlc", "a");
2084 emitcode ("subb", "a,acc");
2086 aopPut (IC_RESULT (ic), "a", offset++);
2090 /* release the aops */
2091 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2092 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2095 /*-----------------------------------------------------------------*/
2096 /* saveRegisters - will look for a call and save the registers */
2097 /*-----------------------------------------------------------------*/
2099 saveRegisters (iCode * lic)
2106 for (ic = lic; ic; ic = ic->next)
2107 if (ic->op == CALL || ic->op == PCALL)
2112 fprintf (stderr, "found parameter push with no function call\n");
2116 /* if the registers have been saved already or don't need to be then
2120 if (IS_SYMOP(IC_LEFT(ic)) &&
2121 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2122 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2125 /* save the registers in use at this time but skip the
2126 ones for the result */
2127 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128 mcs51_rUmaskForOp (IC_RESULT(ic)));
2131 if (options.useXstack)
2133 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2134 int nBits = bitVectnBitsOn (rsavebits);
2135 int count = bitVectnBitsOn (rsave);
2139 count = count - nBits + 1;
2140 /* remove all but the first bits as they are pushed all at once */
2141 rsave = bitVectCplAnd (rsave, rsavebits);
2142 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2147 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2148 if (reg->type == REG_BIT)
2150 emitcode ("mov", "a,%s", reg->base);
2154 emitcode ("mov", "a,%s", reg->name);
2156 emitcode ("mov", "r0,%s", spname);
2157 emitcode ("inc", "%s", spname);// allocate before use
2158 emitcode ("movx", "@r0,a");
2159 if (bitVectBitValue (rsave, R0_IDX))
2160 emitcode ("mov", "r0,a");
2162 else if (count != 0)
2164 if (bitVectBitValue (rsave, R0_IDX))
2166 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2168 emitcode ("mov", "r0,%s", spname);
2170 emitcode ("add", "a,#%d", count);
2171 emitcode ("mov", "%s,a", spname);
2172 for (i = 0; i < mcs51_nRegs; i++)
2174 if (bitVectBitValue (rsave, i))
2176 regs * reg = REG_WITH_INDEX (i);
2179 emitcode ("pop", "acc");
2180 emitcode ("push", "acc");
2182 else if (reg->type == REG_BIT)
2184 emitcode ("mov", "a,%s", reg->base);
2188 emitcode ("mov", "a,%s", reg->name);
2190 emitcode ("movx", "@r0,a");
2193 emitcode ("inc", "r0");
2197 if (bitVectBitValue (rsave, R0_IDX))
2199 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2205 bool bits_pushed = FALSE;
2206 for (i = 0; i < mcs51_nRegs; i++)
2208 if (bitVectBitValue (rsave, i))
2210 bits_pushed = pushReg (i, bits_pushed);
2216 /*-----------------------------------------------------------------*/
2217 /* unsaveRegisters - pop the pushed registers */
2218 /*-----------------------------------------------------------------*/
2220 unsaveRegisters (iCode * ic)
2225 /* restore the registers in use at this time but skip the
2226 ones for the result */
2227 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2228 mcs51_rUmaskForOp (IC_RESULT(ic)));
2230 if (options.useXstack)
2232 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2233 int nBits = bitVectnBitsOn (rsavebits);
2234 int count = bitVectnBitsOn (rsave);
2238 count = count - nBits + 1;
2239 /* remove all but the first bits as they are popped all at once */
2240 rsave = bitVectCplAnd (rsave, rsavebits);
2241 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2246 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2247 emitcode ("mov", "r0,%s", spname);
2248 emitcode ("dec", "r0");
2249 emitcode ("movx", "a,@r0");
2250 if (reg->type == REG_BIT)
2252 emitcode ("mov", "%s,a", reg->base);
2256 emitcode ("mov", "%s,a", reg->name);
2258 emitcode ("dec", "%s", spname);
2260 else if (count != 0)
2262 emitcode ("mov", "r0,%s", spname);
2263 for (i = mcs51_nRegs; i >= 0; i--)
2265 if (bitVectBitValue (rsave, i))
2267 regs * reg = REG_WITH_INDEX (i);
2268 emitcode ("dec", "r0");
2269 emitcode ("movx", "a,@r0");
2272 emitcode ("push", "acc");
2274 else if (reg->type == REG_BIT)
2276 emitcode ("mov", "%s,a", reg->base);
2280 emitcode ("mov", "%s,a", reg->name);
2284 emitcode ("mov", "%s,r0", spname);
2285 if (bitVectBitValue (rsave, R0_IDX))
2287 emitcode ("pop", "ar0");
2293 bool bits_popped = FALSE;
2294 for (i = mcs51_nRegs; i >= 0; i--)
2296 if (bitVectBitValue (rsave, i))
2298 bits_popped = popReg (i, bits_popped);
2305 /*-----------------------------------------------------------------*/
2307 /*-----------------------------------------------------------------*/
2309 pushSide (operand * oper, int size)
2314 char *l = aopGet (oper, offset++, FALSE, TRUE);
2315 if (AOP_TYPE (oper) != AOP_REG &&
2316 AOP_TYPE (oper) != AOP_DIR &&
2320 emitcode ("push", "acc");
2324 emitcode ("push", "%s", l);
2329 /*-----------------------------------------------------------------*/
2330 /* assignResultValue - also indicates if acc is in use afterwards */
2331 /*-----------------------------------------------------------------*/
2333 assignResultValue (operand * oper, operand * func)
2336 int size = AOP_SIZE (oper);
2337 bool accuse = FALSE;
2338 bool pushedA = FALSE;
2340 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2346 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2348 emitcode ("push", "acc");
2353 if ((offset == 3) && pushedA)
2354 emitcode ("pop", "acc");
2355 accuse |= aopPut (oper, fReturn[offset], offset);
2362 /*-----------------------------------------------------------------*/
2363 /* genXpush - pushes onto the external stack */
2364 /*-----------------------------------------------------------------*/
2366 genXpush (iCode * ic)
2368 asmop *aop = newAsmop (0);
2370 int size, offset = 0;
2372 D (emitcode (";", "genXpush"));
2374 aopOp (IC_LEFT (ic), ic, FALSE);
2375 r = getFreePtr (ic, &aop, FALSE);
2377 size = AOP_SIZE (IC_LEFT (ic));
2381 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2382 emitcode ("mov", "%s,%s", r->name, spname);
2383 emitcode ("inc", "%s", spname); // allocate space first
2384 emitcode ("movx", "@%s,a", r->name);
2388 // allocate space first
2389 emitcode ("mov", "%s,%s", r->name, spname);
2391 emitcode ("add", "a,#%d", size);
2392 emitcode ("mov", "%s,a", spname);
2396 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2397 emitcode ("movx", "@%s,a", r->name);
2398 emitcode ("inc", "%s", r->name);
2402 freeAsmop (NULL, aop, ic, TRUE);
2403 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2406 /*-----------------------------------------------------------------*/
2407 /* genIpush - generate code for pushing this gets a little complex */
2408 /*-----------------------------------------------------------------*/
2410 genIpush (iCode * ic)
2412 int size, offset = 0;
2416 D (emitcode (";", "genIpush"));
2418 /* if this is not a parm push : ie. it is spill push
2419 and spill push is always done on the local stack */
2423 /* and the item is spilt then do nothing */
2424 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2427 aopOp (IC_LEFT (ic), ic, FALSE);
2428 size = AOP_SIZE (IC_LEFT (ic));
2429 /* push it on the stack */
2432 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2438 emitcode ("push", "%s", l);
2443 /* this is a parameter push: in this case we call
2444 the routine to find the call and save those
2445 registers that need to be saved */
2448 /* if use external stack then call the external
2449 stack pushing routine */
2450 if (options.useXstack)
2456 /* then do the push */
2457 aopOp (IC_LEFT (ic), ic, FALSE);
2459 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2460 size = AOP_SIZE (IC_LEFT (ic));
2464 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2465 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2466 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2468 if (strcmp (l, prev) || *l == '@')
2470 emitcode ("push", "acc");
2474 emitcode ("push", "%s", l);
2479 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2482 /*-----------------------------------------------------------------*/
2483 /* genIpop - recover the registers: can happen only for spilling */
2484 /*-----------------------------------------------------------------*/
2486 genIpop (iCode * ic)
2490 D (emitcode (";", "genIpop"));
2492 /* if the temp was not pushed then */
2493 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2496 aopOp (IC_LEFT (ic), ic, FALSE);
2497 size = AOP_SIZE (IC_LEFT (ic));
2498 offset = (size - 1);
2501 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2505 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2508 /*-----------------------------------------------------------------*/
2509 /* saveRBank - saves an entire register bank on the stack */
2510 /*-----------------------------------------------------------------*/
2512 saveRBank (int bank, iCode * ic, bool pushPsw)
2515 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2519 if (options.useXstack)
2523 /* Assume r0 is available for use. */
2524 r = REG_WITH_INDEX (R0_IDX);;
2529 r = getFreePtr (ic, &aop, FALSE);
2531 // allocate space first
2532 emitcode ("mov", "%s,%s", r->name, spname);
2534 emitcode ("add", "a,#%d", count);
2535 emitcode ("mov", "%s,a", spname);
2538 for (i = 0; i < 8; i++)
2540 if (options.useXstack)
2542 emitcode ("mov", "a,(%s+%d)",
2543 regs8051[i].base, 8 * bank + regs8051[i].offset);
2544 emitcode ("movx", "@%s,a", r->name);
2546 emitcode ("inc", "%s", r->name);
2549 emitcode ("push", "(%s+%d)",
2550 regs8051[i].base, 8 * bank + regs8051[i].offset);
2553 if (mcs51_nRegs > 8)
2555 if (options.useXstack)
2557 emitcode ("mov", "a,bits");
2558 emitcode ("movx", "@%s,a", r->name);
2560 emitcode ("inc", "%s", r->name);
2564 emitcode ("push", "bits");
2571 if (options.useXstack)
2573 emitcode ("mov", "a,psw");
2574 emitcode ("movx", "@%s,a", r->name);
2578 emitcode ("push", "psw");
2581 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2586 freeAsmop (NULL, aop, ic, TRUE);
2595 /*-----------------------------------------------------------------*/
2596 /* unsaveRBank - restores the register bank from stack */
2597 /*-----------------------------------------------------------------*/
2599 unsaveRBank (int bank, iCode * ic, bool popPsw)
2605 if (options.useXstack)
2609 /* Assume r0 is available for use. */
2610 r = REG_WITH_INDEX (R0_IDX);;
2615 r = getFreePtr (ic, &aop, FALSE);
2617 emitcode ("mov", "%s,%s", r->name, spname);
2622 if (options.useXstack)
2624 emitcode ("dec", "%s", r->name);
2625 emitcode ("movx", "a,@%s", r->name);
2626 emitcode ("mov", "psw,a");
2630 emitcode ("pop", "psw");
2634 if (mcs51_nRegs > 8)
2636 if (options.useXstack)
2638 emitcode ("dec", "%s", r->name);
2639 emitcode ("movx", "a,@%s", r->name);
2640 emitcode ("mov", "bits,a");
2644 emitcode ("pop", "bits");
2648 for (i = 7; i >= 0; i--)
2650 if (options.useXstack)
2652 emitcode ("dec", "%s", r->name);
2653 emitcode ("movx", "a,@%s", r->name);
2654 emitcode ("mov", "(%s+%d),a",
2655 regs8051[i].base, 8 * bank + regs8051[i].offset);
2659 emitcode ("pop", "(%s+%d)",
2660 regs8051[i].base, 8 * bank + regs8051[i].offset);
2664 if (options.useXstack)
2666 emitcode ("mov", "%s,%s", spname, r->name);
2671 freeAsmop (NULL, aop, ic, TRUE);
2675 /*-----------------------------------------------------------------*/
2676 /* genSend - gen code for SEND */
2677 /*-----------------------------------------------------------------*/
2678 static void genSend(set *sendSet)
2683 /* first we do all bit parameters */
2684 for (sic = setFirstItem (sendSet); sic;
2685 sic = setNextItem (sendSet))
2687 if (sic->argreg > 12)
2689 int bit = sic->argreg-13;
2691 aopOp (IC_LEFT (sic), sic, FALSE);
2693 /* if left is a literal then
2694 we know what the value is */
2695 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2697 if (((int) operandLitValue (IC_LEFT (sic))))
2698 emitcode ("setb", "b[%d]", bit);
2700 emitcode ("clr", "b[%d]", bit);
2702 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2704 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2705 if (strcmp (l, "c"))
2706 emitcode ("mov", "c,%s", l);
2707 emitcode ("mov", "b[%d],c", bit);
2712 toBoolean (IC_LEFT (sic));
2713 /* set C, if a >= 1 */
2714 emitcode ("add", "a,#0xff");
2715 emitcode ("mov", "b[%d],c", bit);
2720 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2726 saveRegisters (setFirstItem (sendSet));
2727 emitcode ("mov", "bits,b");
2730 /* then we do all other parameters */
2731 for (sic = setFirstItem (sendSet); sic;
2732 sic = setNextItem (sendSet))
2734 if (sic->argreg <= 12)
2736 int size, offset = 0;
2737 aopOp (IC_LEFT (sic), sic, FALSE);
2738 size = AOP_SIZE (IC_LEFT (sic));
2740 if (sic->argreg == 1)
2744 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2745 if (strcmp (l, fReturn[offset]))
2747 emitcode ("mov", "%s,%s", fReturn[offset], l);
2756 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2757 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2761 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2766 /*-----------------------------------------------------------------*/
2767 /* selectRegBank - emit code to select the register bank */
2768 /*-----------------------------------------------------------------*/
2770 selectRegBank (short bank, bool keepFlags)
2772 /* if f.e. result is in carry */
2775 emitcode ("anl", "psw,#0xE7");
2777 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2781 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2785 /*-----------------------------------------------------------------*/
2786 /* genCall - generates a call statement */
2787 /*-----------------------------------------------------------------*/
2789 genCall (iCode * ic)
2793 // bool restoreBank = FALSE;
2794 bool swapBanks = FALSE;
2795 bool accuse = FALSE;
2796 bool accPushed = FALSE;
2797 bool resultInF0 = FALSE;
2798 bool assignResultGenerated = FALSE;
2800 D (emitcode (";", "genCall"));
2802 dtype = operandType (IC_LEFT (ic));
2803 etype = getSpec(dtype);
2804 /* if send set is not empty then assign */
2807 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2808 genSend(reverseSet(_G.sendSet));
2810 genSend(_G.sendSet);
2815 /* if we are calling a not _naked function that is not using
2816 the same register bank then we need to save the
2817 destination registers on the stack */
2818 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2819 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2820 !IFFUNC_ISISR (dtype))
2825 /* if caller saves & we have not saved then */
2831 emitcode ("mov", "psw,#0x%02x",
2832 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2836 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2838 if (IFFUNC_CALLEESAVES(dtype))
2840 werror (E_BANKED_WITH_CALLEESAVES);
2844 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2845 OP_SYMBOL (IC_LEFT (ic))->rname :
2846 OP_SYMBOL (IC_LEFT (ic))->name);
2848 emitcode ("mov", "r0,#%s", l);
2849 emitcode ("mov", "r1,#(%s >> 8)", l);
2850 emitcode ("mov", "r2,#(%s >> 16)", l);
2851 emitcode ("lcall", "__sdcc_banked_call");
2856 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2857 OP_SYMBOL (IC_LEFT (ic))->rname :
2858 OP_SYMBOL (IC_LEFT (ic))->name));
2863 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2866 /* if we need assign a result value */
2867 if ((IS_ITEMP (IC_RESULT (ic)) &&
2868 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2869 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2870 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2871 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2872 IS_TRUE_SYMOP (IC_RESULT (ic)))
2876 aopOp (IC_RESULT (ic), ic, FALSE);
2879 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2880 assignResultGenerated = TRUE;
2882 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2885 /* adjust the stack for parameters if required */
2889 if (ic->parmBytes > 3)
2893 emitcode ("push", "acc");
2896 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2897 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898 !assignResultGenerated)
2900 emitcode ("mov", "F0,c");
2904 emitcode ("mov", "a,%s", spname);
2905 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2906 emitcode ("mov", "%s,a", spname);
2908 /* unsaveRegisters from xstack needs acc, but */
2909 /* unsaveRegisters from stack needs this popped */
2910 if (accPushed && !options.useXstack)
2912 emitcode ("pop", "acc");
2917 for (i = 0; i < ic->parmBytes; i++)
2918 emitcode ("dec", "%s", spname);
2921 /* if we had saved some registers then unsave them */
2922 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2924 if (accuse && !accPushed && options.useXstack)
2926 /* xstack needs acc, but doesn't touch normal stack */
2927 emitcode ("push", "acc");
2930 unsaveRegisters (ic);
2933 // /* if register bank was saved then pop them */
2935 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2937 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2940 emitcode ("mov", "c,F0");
2942 aopOp (IC_RESULT (ic), ic, FALSE);
2943 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2944 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2948 emitcode ("pop", "acc");
2951 /*-----------------------------------------------------------------*/
2952 /* genPcall - generates a call by pointer statement */
2953 /*-----------------------------------------------------------------*/
2955 genPcall (iCode * ic)
2959 symbol *rlbl = newiTempLabel (NULL);
2960 // bool restoreBank=FALSE;
2961 bool swapBanks = FALSE;
2962 bool resultInF0 = FALSE;
2964 D (emitcode (";", "genPcall"));
2966 dtype = operandType (IC_LEFT (ic))->next;
2967 etype = getSpec(dtype);
2968 /* if caller saves & we have not saved then */
2972 /* if we are calling a not _naked function that is not using
2973 the same register bank then we need to save the
2974 destination registers on the stack */
2975 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2976 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2977 !IFFUNC_ISISR (dtype))
2979 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2980 // restoreBank=TRUE;
2982 // need caution message to user here
2985 if (IS_LITERAL(etype))
2987 /* if send set is not empty then assign */
2990 genSend(reverseSet(_G.sendSet));
2996 emitcode ("mov", "psw,#0x%02x",
2997 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3000 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3002 if (IFFUNC_CALLEESAVES(dtype))
3004 werror (E_BANKED_WITH_CALLEESAVES);
3008 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3010 emitcode ("mov", "r0,#%s", l);
3011 emitcode ("mov", "r1,#(%s >> 8)", l);
3012 emitcode ("mov", "r2,#(%s >> 16)", l);
3013 emitcode ("lcall", "__sdcc_banked_call");
3018 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3023 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3025 if (IFFUNC_CALLEESAVES(dtype))
3027 werror (E_BANKED_WITH_CALLEESAVES);
3031 aopOp (IC_LEFT (ic), ic, FALSE);
3035 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3036 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3037 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3041 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3042 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3043 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3044 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3047 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3049 /* if send set is not empty then assign */
3052 genSend(reverseSet(_G.sendSet));
3058 emitcode ("mov", "psw,#0x%02x",
3059 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3063 emitcode ("lcall", "__sdcc_banked_call");
3068 /* push the return address on to the stack */
3069 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3070 emitcode ("push", "acc");
3071 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3072 emitcode ("push", "acc");
3074 /* now push the calling address */
3075 aopOp (IC_LEFT (ic), ic, FALSE);
3077 pushSide (IC_LEFT (ic), FPTRSIZE);
3079 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3081 /* if send set is not empty the assign */
3084 genSend(reverseSet(_G.sendSet));
3090 emitcode ("mov", "psw,#0x%02x",
3091 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3095 emitcode ("ret", "");
3101 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3104 /* if we need assign a result value */
3105 if ((IS_ITEMP (IC_RESULT (ic)) &&
3106 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3107 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3108 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3109 IS_TRUE_SYMOP (IC_RESULT (ic)))
3113 aopOp (IC_RESULT (ic), ic, FALSE);
3116 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3121 /* adjust the stack for parameters if required */
3125 if (ic->parmBytes > 3)
3127 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3128 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3130 emitcode ("mov", "F0,c");
3134 emitcode ("mov", "a,%s", spname);
3135 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3136 emitcode ("mov", "%s,a", spname);
3139 for (i = 0; i < ic->parmBytes; i++)
3140 emitcode ("dec", "%s", spname);
3143 // /* if register bank was saved then unsave them */
3145 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3147 /* if we had saved some registers then unsave them */
3148 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3149 unsaveRegisters (ic);
3151 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3154 emitcode ("mov", "c,F0");
3156 aopOp (IC_RESULT (ic), ic, FALSE);
3157 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3158 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3162 /*-----------------------------------------------------------------*/
3163 /* resultRemat - result is rematerializable */
3164 /*-----------------------------------------------------------------*/
3166 resultRemat (iCode * ic)
3168 if (SKIP_IC (ic) || ic->op == IFX)
3171 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3173 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3174 if (sym->remat && !POINTER_SET (ic))
3181 #if defined(__BORLANDC__) || defined(_MSC_VER)
3182 #define STRCASECMP stricmp
3184 #define STRCASECMP strcasecmp
3187 /*-----------------------------------------------------------------*/
3188 /* inExcludeList - return 1 if the string is in exclude Reg list */
3189 /*-----------------------------------------------------------------*/
3191 regsCmp(void *p1, void *p2)
3193 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3197 inExcludeList (char *s)
3199 const char *p = setFirstItem(options.excludeRegsSet);
3201 if (p == NULL || STRCASECMP(p, "none") == 0)
3205 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3208 /*-----------------------------------------------------------------*/
3209 /* genFunction - generated code for function entry */
3210 /*-----------------------------------------------------------------*/
3212 genFunction (iCode * ic)
3214 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3216 bool switchedPSW = FALSE;
3217 int calleesaves_saved_register = -1;
3218 int stackAdjust = sym->stack;
3219 int accIsFree = sym->recvSize < 4;
3220 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3221 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3224 /* create the function header */
3225 emitcode (";", "-----------------------------------------");
3226 emitcode (";", " function %s", sym->name);
3227 emitcode (";", "-----------------------------------------");
3229 emitcode ("", "%s:", sym->rname);
3230 ftype = operandType (IC_LEFT (ic));
3231 _G.currentFunc = sym;
3233 if (IFFUNC_ISNAKED(ftype))
3235 emitcode(";", "naked function: no prologue.");
3239 /* here we need to generate the equates for the
3240 register bank if required */
3241 if (FUNC_REGBANK (ftype) != rbank)
3245 rbank = FUNC_REGBANK (ftype);
3246 for (i = 0; i < mcs51_nRegs; i++)
3248 if (regs8051[i].type != REG_BIT)
3250 if (strcmp (regs8051[i].base, "0") == 0)
3251 emitcode ("", "%s = 0x%02x",
3253 8 * rbank + regs8051[i].offset);
3255 emitcode ("", "%s = %s + 0x%02x",
3258 8 * rbank + regs8051[i].offset);
3263 /* if this is an interrupt service routine then
3264 save acc, b, dpl, dph */
3265 if (IFFUNC_ISISR (sym->type))
3267 if (!inExcludeList ("acc"))
3268 emitcode ("push", "acc");
3269 if (!inExcludeList ("b"))
3270 emitcode ("push", "b");
3271 if (!inExcludeList ("dpl"))
3272 emitcode ("push", "dpl");
3273 if (!inExcludeList ("dph"))
3274 emitcode ("push", "dph");
3275 /* if this isr has no bank i.e. is going to
3276 run with bank 0 , then we need to save more
3278 if (!FUNC_REGBANK (sym->type))
3282 /* if this function does not call any other
3283 function then we can be economical and
3284 save only those registers that are used */
3285 if (!IFFUNC_HASFCALL(sym->type))
3287 /* if any registers used */
3290 bool bits_pushed = FALSE;
3291 /* save the registers used */
3292 for (i = 0; i < sym->regsUsed->size; i++)
3294 if (bitVectBitValue (sym->regsUsed, i))
3295 bits_pushed = pushReg (i, bits_pushed);
3301 /* this function has a function call. We cannot
3302 determine register usage so we will have to push the
3304 saveRBank (0, ic, FALSE);
3305 if (options.parms_in_bank1) {
3306 for (i=0; i < 8 ; i++ ) {
3307 emitcode ("push","%s",rb1regs[i]);
3314 /* This ISR uses a non-zero bank.
3316 * We assume that the bank is available for our
3319 * However, if this ISR calls a function which uses some
3320 * other bank, we must save that bank entirely.
3322 unsigned long banksToSave = 0;
3324 if (IFFUNC_HASFCALL(sym->type))
3327 #define MAX_REGISTER_BANKS 4
3332 for (i = ic; i; i = i->next)
3334 if (i->op == ENDFUNCTION)
3336 /* we got to the end OK. */
3344 dtype = operandType (IC_LEFT(i));
3346 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3348 /* Mark this bank for saving. */
3349 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3351 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3355 banksToSave |= (1 << FUNC_REGBANK(dtype));
3358 /* And note that we don't need to do it in
3366 /* This is a mess; we have no idea what
3367 * register bank the called function might
3370 * The only thing I can think of to do is
3371 * throw a warning and hope.
3373 werror(W_FUNCPTR_IN_USING_ISR);
3377 if (banksToSave && options.useXstack)
3379 /* Since we aren't passing it an ic,
3380 * saveRBank will assume r0 is available to abuse.
3382 * So switch to our (trashable) bank now, so
3383 * the caller's R0 isn't trashed.
3385 emitcode ("push", "psw");
3386 emitcode ("mov", "psw,#0x%02x",
3387 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3391 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3393 if (banksToSave & (1 << ix))
3395 saveRBank(ix, NULL, FALSE);
3399 // TODO: this needs a closer look
3400 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3403 /* Set the register bank to the desired value if nothing else */
3404 /* has done so yet. */
3407 emitcode ("push", "psw");
3408 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3413 /* This is a non-ISR function. The caller has already switched register */
3414 /* banks, if necessary, so just handle the callee-saves option. */
3416 /* if callee-save to be used for this function
3417 then save the registers being used in this function */
3418 if (IFFUNC_CALLEESAVES(sym->type))
3422 /* if any registers used */
3425 bool bits_pushed = FALSE;
3426 /* save the registers used */
3427 for (i = 0; i < sym->regsUsed->size; i++)
3429 if (bitVectBitValue (sym->regsUsed, i))
3431 /* remember one saved register for later usage */
3432 if (calleesaves_saved_register < 0)
3433 calleesaves_saved_register = i;
3434 bits_pushed = pushReg (i, bits_pushed);
3445 if (options.useXstack)
3447 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3449 emitcode ("mov", "r0,%s", spname);
3450 emitcode ("inc", "%s", spname);
3451 emitcode ("xch", "a,_bpx");
3452 emitcode ("movx", "@r0,a");
3453 emitcode ("inc", "r0");
3454 emitcode ("mov", "a,r0");
3455 emitcode ("xch", "a,_bpx");
3459 emitcode ("push", "_bp"); /* save the callers stack */
3460 emitcode ("mov", "_bp,sp");
3465 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3467 /* set up the stack */
3468 emitcode ("push", "_bp"); /* save the callers stack */
3469 emitcode ("mov", "_bp,sp");
3474 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3475 /* before setting up the stack frame completely. */
3476 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3478 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3482 if (rsym && rsym->regType == REG_CND)
3484 if (rsym && (rsym->accuse || rsym->ruonly))
3486 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3487 rsym = rsym->usl.spillLoc;
3490 /* If the RECEIVE operand immediately spills to the first entry on the */
3491 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3492 /* rather than the usual @r0/r1 machinations. */
3493 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3497 _G.current_iCode = ric;
3498 D(emitcode ("; genReceive",""));
3499 for (ofs=0; ofs < sym->recvSize; ofs++)
3501 if (!strcmp (fReturn[ofs], "a"))
3502 emitcode ("push", "acc");
3504 emitcode ("push", fReturn[ofs]);
3506 stackAdjust -= sym->recvSize;
3509 assert (stackAdjust>=0);
3512 _G.current_iCode = ic;
3516 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3517 /* to free up the accumulator. */
3518 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3522 _G.current_iCode = ric;
3523 D(emitcode ("; genReceive",""));
3524 for (ofs=0; ofs < sym->recvSize; ofs++)
3526 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3528 _G.current_iCode = ic;
3534 /* adjust the stack for the function */
3537 int i = stackAdjust;
3539 werror (W_STACK_OVERFLOW, sym->name);
3541 if (i > 3 && accIsFree)
3543 emitcode ("mov", "a,sp");
3544 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3545 emitcode ("mov", "sp,a");
3549 /* The accumulator is not free, so we will need another register */
3550 /* to clobber. No need to worry about a possible conflict with */
3551 /* the above early RECEIVE optimizations since they would have */
3552 /* freed the accumulator if they were generated. */
3554 if (IFFUNC_CALLEESAVES(sym->type))
3556 /* if it's a callee-saves function we need a saved register */
3557 if (calleesaves_saved_register >= 0)
3559 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3560 emitcode ("mov", "a,sp");
3561 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3562 emitcode ("mov", "sp,a");
3563 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3566 /* do it the hard way */
3568 emitcode ("inc", "sp");
3572 /* not callee-saves, we can clobber r0 */
3573 emitcode ("mov", "r0,a");
3574 emitcode ("mov", "a,sp");
3575 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3576 emitcode ("mov", "sp,a");
3577 emitcode ("mov", "a,r0");
3582 emitcode ("inc", "sp");
3587 char i = ((char) sym->xstack & 0xff);
3589 if (i > 3 && accIsFree)
3591 emitcode ("mov", "a,_spx");
3592 emitcode ("add", "a,#0x%02x", i);
3593 emitcode ("mov", "_spx,a");
3597 emitcode ("push", "acc");
3598 emitcode ("mov", "a,_spx");
3599 emitcode ("add", "a,#0x%02x", i);
3600 emitcode ("mov", "_spx,a");
3601 emitcode ("pop", "acc");
3606 emitcode ("inc", "_spx");
3610 /* if critical function then turn interrupts off */
3611 if (IFFUNC_ISCRITICAL (ftype))
3613 symbol *tlbl = newiTempLabel (NULL);
3614 emitcode ("setb", "c");
3615 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3616 emitcode ("clr", "c");
3618 emitcode ("push", "psw"); /* save old ea via c in psw */
3622 /*-----------------------------------------------------------------*/
3623 /* genEndFunction - generates epilogue for functions */
3624 /*-----------------------------------------------------------------*/
3626 genEndFunction (iCode * ic)
3628 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3629 lineNode *lnp = lineCurr;
3631 bitVect *regsUsedPrologue;
3632 bitVect *regsUnneeded;
3635 _G.currentFunc = NULL;
3636 if (IFFUNC_ISNAKED(sym->type))
3638 emitcode(";", "naked function: no epilogue.");
3639 if (options.debug && currFunc)
3640 debugFile->writeEndFunction (currFunc, ic, 0);
3644 if (IFFUNC_ISCRITICAL (sym->type))
3646 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3648 emitcode ("rlc", "a"); /* save c in a */
3649 emitcode ("pop", "psw"); /* restore ea via c in psw */
3650 emitcode ("mov", "ea,c");
3651 emitcode ("rrc", "a"); /* restore c from a */
3655 emitcode ("pop", "psw"); /* restore ea via c in psw */
3656 emitcode ("mov", "ea,c");
3660 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3662 if (options.useXstack)
3666 emitcode ("mov", "sp,_bp");
3667 emitcode ("pop", "_bp");
3669 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3671 emitcode ("xch", "a,_bpx");
3672 emitcode ("mov", "r0,a");
3673 emitcode ("dec", "r0");
3674 emitcode ("movx", "a,@r0");
3675 emitcode ("xch", "a,_bpx");
3676 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3679 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3682 emitcode ("mov", "sp,_bp");
3683 emitcode ("pop", "_bp");
3687 /* restore the register bank */
3688 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3690 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3691 || !options.useXstack)
3693 /* Special case of ISR using non-zero bank with useXstack
3696 emitcode ("pop", "psw");
3700 if (IFFUNC_ISISR (sym->type))
3703 /* now we need to restore the registers */
3704 /* if this isr has no bank i.e. is going to
3705 run with bank 0 , then we need to save more
3707 if (!FUNC_REGBANK (sym->type))
3710 /* if this function does not call any other
3711 function then we can be economical and
3712 save only those registers that are used */
3713 if (!IFFUNC_HASFCALL(sym->type))
3715 /* if any registers used */
3718 bool bits_popped = FALSE;
3719 /* save the registers used */
3720 for (i = sym->regsUsed->size; i >= 0; i--)
3722 if (bitVectBitValue (sym->regsUsed, i))
3723 bits_popped = popReg (i, bits_popped);
3729 if (options.parms_in_bank1) {
3730 for (i = 7 ; i >= 0 ; i-- ) {
3731 emitcode ("pop","%s",rb1regs[i]);
3734 /* this function has a function call cannot
3735 determines register usage so we will have to pop the
3737 unsaveRBank (0, ic, FALSE);
3742 /* This ISR uses a non-zero bank.
3744 * Restore any register banks saved by genFunction
3747 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3750 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3752 if (savedBanks & (1 << ix))
3754 unsaveRBank(ix, NULL, FALSE);
3758 if (options.useXstack)
3760 /* Restore bank AFTER calling unsaveRBank,
3761 * since it can trash r0.
3763 emitcode ("pop", "psw");
3767 if (!inExcludeList ("dph"))
3768 emitcode ("pop", "dph");
3769 if (!inExcludeList ("dpl"))
3770 emitcode ("pop", "dpl");
3771 if (!inExcludeList ("b"))
3772 emitcode ("pop", "b");
3773 if (!inExcludeList ("acc"))
3774 emitcode ("pop", "acc");
3776 /* if debug then send end of function */
3777 if (options.debug && currFunc)
3779 debugFile->writeEndFunction (currFunc, ic, 1);
3782 emitcode ("reti", "");
3786 if (IFFUNC_CALLEESAVES(sym->type))
3790 /* if any registers used */
3793 /* save the registers used */
3794 for (i = sym->regsUsed->size; i >= 0; i--)
3796 if (bitVectBitValue (sym->regsUsed, i) ||
3797 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3798 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3801 else if (mcs51_ptrRegReq)
3803 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3804 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3809 /* if debug then send end of function */
3810 if (options.debug && currFunc)
3812 debugFile->writeEndFunction (currFunc, ic, 1);
3815 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3817 emitcode ("ljmp", "__sdcc_banked_ret");
3821 emitcode ("ret", "");
3825 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3828 /* If this was an interrupt handler using bank 0 that called another */
3829 /* function, then all registers must be saved; nothing to optimized. */
3830 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3831 && !FUNC_REGBANK(sym->type))
3834 /* There are no push/pops to optimize if not callee-saves or ISR */
3835 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3838 /* If there were stack parameters, we cannot optimize without also */
3839 /* fixing all of the stack offsets; this is too dificult to consider. */
3840 if (FUNC_HASSTACKPARM(sym->type))
3843 /* Compute the registers actually used */
3844 regsUsed = newBitVect (mcs51_nRegs);
3845 regsUsedPrologue = newBitVect (mcs51_nRegs);
3848 if (lnp->ic && lnp->ic->op == FUNCTION)
3849 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3851 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3853 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3854 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3861 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3862 && !bitVectBitValue (regsUsed, CND_IDX))
3864 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3865 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3866 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3867 bitVectUnSetBit (regsUsed, CND_IDX);
3870 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3872 /* If this was an interrupt handler that called another function */
3873 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3874 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3876 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3877 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3878 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3879 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3880 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3883 /* Remove the unneeded push/pops */
3884 regsUnneeded = newBitVect (mcs51_nRegs);
3887 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3889 if (!strncmp(lnp->line, "push", 4))
3891 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3892 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3894 connectLine (lnp->prev, lnp->next);
3895 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3898 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3900 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3901 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3903 connectLine (lnp->prev, lnp->next);
3904 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3911 for (idx = 0; idx < regsUnneeded->size; idx++)
3912 if (bitVectBitValue (regsUnneeded, idx))
3913 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3915 freeBitVect (regsUnneeded);
3916 freeBitVect (regsUsed);
3917 freeBitVect (regsUsedPrologue);
3920 /*-----------------------------------------------------------------*/
3921 /* genRet - generate code for return statement */
3922 /*-----------------------------------------------------------------*/
3926 int size, offset = 0, pushed = 0;
3928 D (emitcode (";", "genRet"));
3930 /* if we have no return value then
3931 just generate the "ret" */
3935 /* we have something to return then
3936 move the return value into place */
3937 aopOp (IC_LEFT (ic), ic, FALSE);
3938 size = AOP_SIZE (IC_LEFT (ic));
3940 if (IS_BIT(_G.currentFunc->etype))
3942 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3949 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3952 l = aopGet (IC_LEFT (ic), offset++,
3954 emitcode ("push", "%s", l);
3959 l = aopGet (IC_LEFT (ic), offset,
3961 if (strcmp (fReturn[offset], l))
3962 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3969 if (strcmp (fReturn[pushed], "a"))
3970 emitcode ("pop", fReturn[pushed]);
3972 emitcode ("pop", "acc");
3974 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3977 /* generate a jump to the return label
3978 if the next is not the return statement */
3979 if (!(ic->next && ic->next->op == LABEL &&
3980 IC_LABEL (ic->next) == returnLabel))
3982 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3986 /*-----------------------------------------------------------------*/
3987 /* genLabel - generates a label */
3988 /*-----------------------------------------------------------------*/
3990 genLabel (iCode * ic)
3992 /* special case never generate */
3993 if (IC_LABEL (ic) == entryLabel)
3996 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3999 /*-----------------------------------------------------------------*/
4000 /* genGoto - generates a ljmp */
4001 /*-----------------------------------------------------------------*/
4003 genGoto (iCode * ic)
4005 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4008 /*-----------------------------------------------------------------*/
4009 /* findLabelBackwards: walks back through the iCode chain looking */
4010 /* for the given label. Returns number of iCode instructions */
4011 /* between that label and given ic. */
4012 /* Returns zero if label not found. */
4013 /*-----------------------------------------------------------------*/
4015 findLabelBackwards (iCode * ic, int key)
4024 /* If we have any pushes or pops, we cannot predict the distance.
4025 I don't like this at all, this should be dealt with in the
4027 if (ic->op == IPUSH || ic->op == IPOP) {
4031 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusIncr :- does addition with increment if possible */
4042 /*-----------------------------------------------------------------*/
4044 genPlusIncr (iCode * ic)
4046 unsigned int icount;
4047 unsigned int size = getDataSize (IC_RESULT (ic));
4049 /* will try to generate an increment */
4050 /* if the right side is not a literal
4052 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4055 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4057 D(emitcode ("; genPlusIncr",""));
4059 /* if increment >=16 bits in register or direct space */
4060 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4061 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4062 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4070 /* If the next instruction is a goto and the goto target
4071 * is < 10 instructions previous to this, we can generate
4072 * jumps straight to that target.
4074 if (ic->next && ic->next->op == GOTO
4075 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4076 && labelRange <= 10)
4078 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4079 tlbl = IC_LABEL (ic->next);
4084 tlbl = newiTempLabel (NULL);
4087 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4089 IS_AOP_PREG (IC_RESULT (ic)))
4090 emitcode ("cjne", "%s,#0x00,%05d$",
4091 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4095 emitcode ("clr", "a");
4096 emitcode ("cjne", "a,%s,%05d$",
4097 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4101 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4104 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4105 IS_AOP_PREG (IC_RESULT (ic)))
4106 emitcode ("cjne", "%s,#0x00,%05d$",
4107 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4110 emitcode ("cjne", "a,%s,%05d$",
4111 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4114 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4118 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119 IS_AOP_PREG (IC_RESULT (ic)))
4120 emitcode ("cjne", "%s,#0x00,%05d$",
4121 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4125 emitcode ("cjne", "a,%s,%05d$",
4126 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4129 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4139 /* if result is dptr */
4140 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4141 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4142 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4143 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4145 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4151 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4154 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4155 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4157 emitcode ("inc", "dptr");
4162 /* if the literal value of the right hand side
4163 is greater than 4 then it is not worth it */
4167 /* if the sizes are greater than 1 then we cannot */
4168 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4169 AOP_SIZE (IC_LEFT (ic)) > 1)
4172 /* we can if the aops of the left & result match or
4173 if they are in registers and the registers are the
4175 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4179 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4180 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4181 aopPut (IC_RESULT (ic), "a", 0);
4187 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4197 /*-----------------------------------------------------------------*/
4198 /* outBitAcc - output a bit in acc */
4199 /*-----------------------------------------------------------------*/
4201 outBitAcc (operand * result)
4203 symbol *tlbl = newiTempLabel (NULL);
4204 /* if the result is a bit */
4205 if (AOP_TYPE (result) == AOP_CRY)
4207 aopPut (result, "a", 0);
4211 emitcode ("jz", "%05d$", tlbl->key + 100);
4212 emitcode ("mov", "a,%s", one);
4218 /*-----------------------------------------------------------------*/
4219 /* genPlusBits - generates code for addition of two bits */
4220 /*-----------------------------------------------------------------*/
4222 genPlusBits (iCode * ic)
4224 D (emitcode (";", "genPlusBits"));
4226 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4228 symbol *lbl = newiTempLabel (NULL);
4229 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4230 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4231 emitcode ("cpl", "c");
4233 outBitC (IC_RESULT (ic));
4237 emitcode ("clr", "a");
4238 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4239 emitcode ("rlc", "a");
4240 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4241 emitcode ("addc", "a,%s", zero);
4242 outAcc (IC_RESULT (ic));
4247 /* This is the original version of this code.
4249 * This is being kept around for reference,
4250 * because I am not entirely sure I got it right...
4253 adjustArithmeticResult (iCode * ic)
4255 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4256 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4257 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4258 aopPut (IC_RESULT (ic),
4259 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4262 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4263 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4264 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4265 aopPut (IC_RESULT (ic),
4266 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4269 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4270 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4271 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4272 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4273 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4276 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4277 aopPut (IC_RESULT (ic), buffer, 2);
4281 /* This is the pure and virtuous version of this code.
4282 * I'm pretty certain it's right, but not enough to toss the old
4286 adjustArithmeticResult (iCode * ic)
4288 if (opIsGptr (IC_RESULT (ic)) &&
4289 opIsGptr (IC_LEFT (ic)) &&
4290 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4292 aopPut (IC_RESULT (ic),
4293 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4297 if (opIsGptr (IC_RESULT (ic)) &&
4298 opIsGptr (IC_RIGHT (ic)) &&
4299 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4301 aopPut (IC_RESULT (ic),
4302 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4306 if (opIsGptr (IC_RESULT (ic)) &&
4307 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4308 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4309 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4313 SNPRINTF (buffer, sizeof(buffer),
4314 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4320 /*-----------------------------------------------------------------*/
4321 /* genPlus - generates code for addition */
4322 /*-----------------------------------------------------------------*/
4324 genPlus (iCode * ic)
4326 int size, offset = 0;
4329 bool swappedLR = FALSE;
4330 operand *leftOp, *rightOp;
4333 D (emitcode (";", "genPlus"));
4335 /* special cases :- */
4337 aopOp (IC_LEFT (ic), ic, FALSE);
4338 aopOp (IC_RIGHT (ic), ic, FALSE);
4339 aopOp (IC_RESULT (ic), ic, TRUE);
4341 /* if literal, literal on the right or
4342 if left requires ACC or right is already
4344 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4345 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4346 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4348 operand *t = IC_RIGHT (ic);
4349 IC_RIGHT (ic) = IC_LEFT (ic);
4354 /* if both left & right are in bit
4356 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4357 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4363 /* if left in bit space & right literal */
4364 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4365 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4367 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368 /* if result in bit space */
4369 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4371 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4372 emitcode ("cpl", "c");
4373 outBitC (IC_RESULT (ic));
4377 size = getDataSize (IC_RESULT (ic));
4380 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4381 emitcode ("addc", "a,%s", zero);
4382 aopPut (IC_RESULT (ic), "a", offset++);
4388 /* if I can do an increment instead
4389 of add then GOOD for ME */
4390 if (genPlusIncr (ic) == TRUE)
4393 size = getDataSize (IC_RESULT (ic));
4394 leftOp = IC_LEFT(ic);
4395 rightOp = IC_RIGHT(ic);
4398 /* if this is an add for an array access
4399 at a 256 byte boundary */
4401 && AOP_TYPE (op) == AOP_IMMD
4403 && IS_SPEC (OP_SYM_ETYPE (op))
4404 && SPEC_ABSA (OP_SYM_ETYPE (op))
4405 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4408 D(emitcode ("; genPlus aligned array",""));
4409 aopPut (IC_RESULT (ic),
4410 aopGet (rightOp, 0, FALSE, FALSE),
4413 if( 1 == getDataSize (IC_RIGHT (ic)) )
4415 aopPut (IC_RESULT (ic),
4416 aopGet (leftOp, 1, FALSE, FALSE),
4421 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4422 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4423 aopPut (IC_RESULT (ic), "a", 1);
4428 /* if the lower bytes of a literal are zero skip the addition */
4429 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4431 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4432 (skip_bytes+1 < size))
4437 D(emitcode ("; genPlus shortcut",""));
4442 if( offset >= skip_bytes )
4444 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4447 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4449 emitcode("xch", "a,b");
4450 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4451 emitcode (add, "a,b");
4454 else if (aopGetUsesAcc (leftOp, offset))
4456 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4457 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4461 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4462 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4464 aopPut (IC_RESULT (ic), "a", offset);
4465 add = "addc"; /* further adds must propagate carry */
4469 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4470 isOperandVolatile (IC_RESULT (ic), FALSE))
4473 aopPut (IC_RESULT (ic),
4474 aopGet (leftOp, offset, FALSE, FALSE),
4481 adjustArithmeticResult (ic);
4484 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4487 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4492 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4497 /*-----------------------------------------------------------------*/
4498 /* genMinusDec :- does subtraction with decrement if possible */
4499 /*-----------------------------------------------------------------*/
4501 genMinusDec (iCode * ic)
4503 unsigned int icount;
4504 unsigned int size = getDataSize (IC_RESULT (ic));
4506 /* will try to generate an increment */
4507 /* if the right side is not a literal
4509 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4512 /* if the literal value of the right hand side
4513 is greater than 4 then it is not worth it */
4514 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4517 D (emitcode (";", "genMinusDec"));
4519 /* if decrement >=16 bits in register or direct space */
4520 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4521 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4529 /* If the next instruction is a goto and the goto target
4530 * is <= 10 instructions previous to this, we can generate
4531 * jumps straight to that target.
4533 if (ic->next && ic->next->op == GOTO
4534 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4535 && labelRange <= 10)
4537 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4538 tlbl = IC_LABEL (ic->next);
4543 tlbl = newiTempLabel (NULL);
4547 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4548 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4549 IS_AOP_PREG (IC_RESULT (ic)))
4550 emitcode ("cjne", "%s,#0xff,%05d$"
4551 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4555 emitcode ("mov", "a,#0xff");
4556 emitcode ("cjne", "a,%s,%05d$"
4557 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4560 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4563 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4564 IS_AOP_PREG (IC_RESULT (ic)))
4565 emitcode ("cjne", "%s,#0xff,%05d$"
4566 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4570 emitcode ("cjne", "a,%s,%05d$"
4571 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4574 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4578 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4579 IS_AOP_PREG (IC_RESULT (ic)))
4580 emitcode ("cjne", "%s,#0xff,%05d$"
4581 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4585 emitcode ("cjne", "a,%s,%05d$"
4586 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4589 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4598 /* if the sizes are greater than 1 then we cannot */
4599 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4600 AOP_SIZE (IC_LEFT (ic)) > 1)
4603 /* we can if the aops of the left & result match or
4604 if they are in registers and the registers are the
4606 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4610 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4612 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4617 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4622 emitcode ("dec", "%s", l);
4625 if (AOP_NEEDSACC (IC_RESULT (ic)))
4626 aopPut (IC_RESULT (ic), "a", 0);
4634 /*-----------------------------------------------------------------*/
4635 /* addSign - complete with sign */
4636 /*-----------------------------------------------------------------*/
4638 addSign (operand * result, int offset, int sign)
4640 int size = (getDataSize (result) - offset);
4645 emitcode ("rlc", "a");
4646 emitcode ("subb", "a,acc");
4649 aopPut (result, "a", offset++);
4656 aopPut (result, zero, offset++);
4662 /*-----------------------------------------------------------------*/
4663 /* genMinusBits - generates code for subtraction of two bits */
4664 /*-----------------------------------------------------------------*/
4666 genMinusBits (iCode * ic)
4668 symbol *lbl = newiTempLabel (NULL);
4670 D (emitcode (";", "genMinusBits"));
4672 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4674 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4675 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4676 emitcode ("cpl", "c");
4678 outBitC (IC_RESULT (ic));
4682 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4683 emitcode ("subb", "a,acc");
4684 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4685 emitcode ("inc", "a");
4687 aopPut (IC_RESULT (ic), "a", 0);
4688 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4692 /*-----------------------------------------------------------------*/
4693 /* genMinus - generates code for subtraction */
4694 /*-----------------------------------------------------------------*/
4696 genMinus (iCode * ic)
4698 int size, offset = 0;
4700 D (emitcode (";", "genMinus"));
4702 aopOp (IC_LEFT (ic), ic, FALSE);
4703 aopOp (IC_RIGHT (ic), ic, FALSE);
4704 aopOp (IC_RESULT (ic), ic, TRUE);
4706 /* special cases :- */
4707 /* if both left & right are in bit space */
4708 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4709 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4715 /* if I can do an decrement instead
4716 of subtract then GOOD for ME */
4717 if (genMinusDec (ic) == TRUE)
4720 size = getDataSize (IC_RESULT (ic));
4722 /* if literal, add a,#-lit, else normal subb */
4723 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4725 unsigned long lit = 0L;
4726 bool useCarry = FALSE;
4728 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4733 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4735 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4736 if (!offset && !size && lit== (unsigned long) -1)
4738 emitcode ("dec", "a");
4742 /* first add without previous c */
4743 emitcode ("add", "a,#0x%02x",
4744 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4749 emitcode ("addc", "a,#0x%02x",
4750 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4752 aopPut (IC_RESULT (ic), "a", offset++);
4756 /* no need to add zeroes */
4757 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4759 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4768 operand *leftOp, *rightOp;
4770 leftOp = IC_LEFT(ic);
4771 rightOp = IC_RIGHT(ic);
4775 if (aopGetUsesAcc(rightOp, offset)) {
4776 if (aopGetUsesAcc(leftOp, offset)) {
4779 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4781 emitcode ("mov", "b,a");
4784 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4785 emitcode ("subb", "a,b");
4788 /* reverse subtraction with 2's complement */
4790 emitcode( "setb", "c");
4792 emitcode( "cpl", "c");
4793 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4794 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4795 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4796 emitcode("cpl", "a");
4797 if (size) /* skip if last byte */
4798 emitcode( "cpl", "c");
4801 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4804 emitcode ("subb", "a,%s",
4805 aopGet(rightOp, offset, FALSE, TRUE));
4808 aopPut (IC_RESULT (ic), "a", offset++);
4812 adjustArithmeticResult (ic);
4815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4816 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4821 /*-----------------------------------------------------------------*/
4822 /* genMultbits :- multiplication of bits */
4823 /*-----------------------------------------------------------------*/
4825 genMultbits (operand * left,
4829 D (emitcode (";", "genMultbits"));
4831 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4836 /*-----------------------------------------------------------------*/
4837 /* genMultOneByte : 8*8=8/16 bit multiplication */
4838 /*-----------------------------------------------------------------*/
4840 genMultOneByte (operand * left,
4845 int size = AOP_SIZE (result);
4846 bool runtimeSign, compiletimeSign;
4847 bool lUnsigned, rUnsigned, pushedB;
4849 D (emitcode (";", "genMultOneByte"));
4851 if (size < 1 || size > 2)
4853 /* this should never happen */
4854 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4855 AOP_SIZE(result), __FILE__, lineno);
4859 /* (if two literals: the value is computed before) */
4860 /* if one literal, literal on the right */
4861 if (AOP_TYPE (left) == AOP_LIT)
4866 /* emitcode (";", "swapped left and right"); */
4868 /* if no literal, unsigned on the right: shorter code */
4869 if ( AOP_TYPE (right) != AOP_LIT
4870 && SPEC_USIGN (getSpec (operandType (left))))
4877 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4878 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4882 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4883 no need to take care about the signedness! */
4884 || (lUnsigned && rUnsigned))
4886 /* just an unsigned 8 * 8 = 8 multiply
4888 /* emitcode (";","unsigned"); */
4889 /* TODO: check for accumulator clash between left & right aops? */
4891 if (AOP_TYPE (right) == AOP_LIT)
4893 /* moving to accumulator first helps peepholes */
4894 MOVA (aopGet (left, 0, FALSE, FALSE));
4895 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4900 MOVA (aopGet (left, 0, FALSE, FALSE));
4903 emitcode ("mul", "ab");
4904 aopPut (result, "a", 0);
4906 aopPut (result, "b", 1);
4912 /* we have to do a signed multiply */
4913 /* emitcode (";", "signed"); */
4915 /* now sign adjust for both left & right */
4917 /* let's see what's needed: */
4918 /* apply negative sign during runtime */
4919 runtimeSign = FALSE;
4920 /* negative sign from literals */
4921 compiletimeSign = FALSE;
4925 if (AOP_TYPE(left) == AOP_LIT)
4927 /* signed literal */
4928 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4930 compiletimeSign = TRUE;
4933 /* signed but not literal */
4939 if (AOP_TYPE(right) == AOP_LIT)
4941 /* signed literal */
4942 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4944 compiletimeSign ^= TRUE;
4947 /* signed but not literal */
4951 /* initialize F0, which stores the runtime sign */
4954 if (compiletimeSign)
4955 emitcode ("setb", "F0"); /* set sign flag */
4957 emitcode ("clr", "F0"); /* reset sign flag */
4960 /* save the signs of the operands */
4961 if (AOP_TYPE(right) == AOP_LIT)
4963 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4965 if (!rUnsigned && val < 0)
4966 emitcode ("mov", "b,#0x%02x", -val);
4968 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4970 else /* ! literal */
4972 if (rUnsigned) /* emitcode (";", "signed"); */
4973 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4976 MOVA (aopGet (right, 0, FALSE, FALSE));
4977 lbl = newiTempLabel (NULL);
4978 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4979 emitcode ("cpl", "F0"); /* complement sign flag */
4980 emitcode ("cpl", "a"); /* 2's complement */
4981 emitcode ("inc", "a");
4983 emitcode ("mov", "b,a");
4987 if (AOP_TYPE(left) == AOP_LIT)
4989 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4991 if (!lUnsigned && val < 0)
4992 emitcode ("mov", "a,#0x%02x", -val);
4994 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4996 else /* ! literal */
4998 MOVA (aopGet (left, 0, FALSE, FALSE));
5002 lbl = newiTempLabel (NULL);
5003 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5004 emitcode ("cpl", "F0"); /* complement sign flag */
5005 emitcode ("cpl", "a"); /* 2's complement */
5006 emitcode ("inc", "a");
5011 /* now the multiplication */
5012 emitcode ("mul", "ab");
5013 if (runtimeSign || compiletimeSign)
5015 lbl = newiTempLabel (NULL);
5017 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5018 emitcode ("cpl", "a"); /* lsb 2's complement */
5020 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5023 emitcode ("add", "a,#1"); /* this sets carry flag */
5024 emitcode ("xch", "a,b");
5025 emitcode ("cpl", "a"); /* msb 2's complement */
5026 emitcode ("addc", "a,#0");
5027 emitcode ("xch", "a,b");
5031 aopPut (result, "a", 0);
5033 aopPut (result, "b", 1);
5038 /*-----------------------------------------------------------------*/
5039 /* genMult - generates code for multiplication */
5040 /*-----------------------------------------------------------------*/
5042 genMult (iCode * ic)
5044 operand *left = IC_LEFT (ic);
5045 operand *right = IC_RIGHT (ic);
5046 operand *result = IC_RESULT (ic);
5048 D (emitcode (";", "genMult"));
5050 /* assign the asmops */
5051 aopOp (left, ic, FALSE);
5052 aopOp (right, ic, FALSE);
5053 aopOp (result, ic, TRUE);
5055 /* special cases first */
5057 if (AOP_TYPE (left) == AOP_CRY &&
5058 AOP_TYPE (right) == AOP_CRY)
5060 genMultbits (left, right, result);
5064 /* if both are of size == 1 */
5065 #if 0 // one of them can be a sloc shared with the result
5066 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5068 if (getSize(operandType(left)) == 1 &&
5069 getSize(operandType(right)) == 1)
5072 genMultOneByte (left, right, result);
5076 /* should have been converted to function call */
5077 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5078 getSize(OP_SYMBOL(right)->type));
5082 freeAsmop (result, NULL, ic, TRUE);
5083 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5084 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5087 /*-----------------------------------------------------------------*/
5088 /* genDivbits :- division of bits */
5089 /*-----------------------------------------------------------------*/
5091 genDivbits (operand * left,
5098 D(emitcode ("; genDivbits",""));
5102 /* the result must be bit */
5103 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5104 l = aopGet (left, 0, FALSE, FALSE);
5108 emitcode ("div", "ab");
5109 emitcode ("rrc", "a");
5113 aopPut (result, "c", 0);
5116 /*-----------------------------------------------------------------*/
5117 /* genDivOneByte : 8 bit division */
5118 /*-----------------------------------------------------------------*/
5120 genDivOneByte (operand * left,
5124 bool lUnsigned, rUnsigned, pushedB;
5125 bool runtimeSign, compiletimeSign;
5126 bool accuse = FALSE;
5127 bool pushedA = FALSE;
5131 D(emitcode ("; genDivOneByte",""));
5133 /* Why is it necessary that genDivOneByte() can return an int result?
5136 volatile unsigned char uc;
5137 volatile signed char sc1, sc2;
5150 In all cases a one byte result would overflow, the following cast to int
5151 would return the wrong result.
5153 Two possible solution:
5154 a) cast operands to int, if ((unsigned) / (signed)) or
5155 ((signed) / (signed))
5156 b) return an 16 bit signed int; this is what we're doing here!
5159 size = AOP_SIZE (result) - 1;
5161 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5162 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5166 /* signed or unsigned */
5167 if (lUnsigned && rUnsigned)
5169 /* unsigned is easy */
5170 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5171 MOVA (aopGet (left, 0, FALSE, FALSE));
5172 emitcode ("div", "ab");
5173 aopPut (result, "a", 0);
5175 aopPut (result, zero, offset++);
5181 /* signed is a little bit more difficult */
5183 /* now sign adjust for both left & right */
5185 /* let's see what's needed: */
5186 /* apply negative sign during runtime */
5187 runtimeSign = FALSE;
5188 /* negative sign from literals */
5189 compiletimeSign = FALSE;
5193 if (AOP_TYPE(left) == AOP_LIT)
5195 /* signed literal */
5196 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5198 compiletimeSign = TRUE;
5201 /* signed but not literal */
5207 if (AOP_TYPE(right) == AOP_LIT)
5209 /* signed literal */
5210 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5212 compiletimeSign ^= TRUE;
5215 /* signed but not literal */
5219 /* initialize F0, which stores the runtime sign */
5222 if (compiletimeSign)
5223 emitcode ("setb", "F0"); /* set sign flag */
5225 emitcode ("clr", "F0"); /* reset sign flag */
5228 /* save the signs of the operands */
5229 if (AOP_TYPE(right) == AOP_LIT)
5231 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5233 if (!rUnsigned && val < 0)
5234 emitcode ("mov", "b,#0x%02x", -val);
5236 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5238 else /* ! literal */
5241 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5244 MOVA (aopGet (right, 0, FALSE, FALSE));
5245 lbl = newiTempLabel (NULL);
5246 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5247 emitcode ("cpl", "F0"); /* complement sign flag */
5248 emitcode ("cpl", "a"); /* 2's complement */
5249 emitcode ("inc", "a");
5251 emitcode ("mov", "b,a");
5255 if (AOP_TYPE(left) == AOP_LIT)
5257 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5259 if (!lUnsigned && val < 0)
5260 emitcode ("mov", "a,#0x%02x", -val);
5262 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5264 else /* ! literal */
5266 MOVA (aopGet (left, 0, FALSE, FALSE));
5270 lbl = newiTempLabel (NULL);
5271 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5272 emitcode ("cpl", "F0"); /* complement sign flag */
5273 emitcode ("cpl", "a"); /* 2's complement */
5274 emitcode ("inc", "a");
5279 /* now the division */
5280 emitcode ("div", "ab");
5282 if (runtimeSign || compiletimeSign)
5284 lbl = newiTempLabel (NULL);
5286 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5287 emitcode ("cpl", "a"); /* lsb 2's complement */
5288 emitcode ("inc", "a");
5291 accuse = aopPut (result, "a", 0);
5294 /* msb is 0x00 or 0xff depending on the sign */
5299 emitcode ("push", "acc");
5302 emitcode ("mov", "c,F0");
5303 emitcode ("subb", "a,acc");
5305 aopPut (result, "a", offset++);
5307 else /* compiletimeSign */
5309 if (aopPutUsesAcc (result, "#0xFF", offset))
5311 emitcode ("push", "acc");
5315 aopPut (result, "#0xff", offset++);
5321 aopPut (result, "a", 0);
5323 aopPut (result, zero, offset++);
5327 emitcode ("pop", "acc");
5331 /*-----------------------------------------------------------------*/
5332 /* genDiv - generates code for division */
5333 /*-----------------------------------------------------------------*/
5337 operand *left = IC_LEFT (ic);
5338 operand *right = IC_RIGHT (ic);
5339 operand *result = IC_RESULT (ic);
5341 D (emitcode (";", "genDiv"));
5343 /* assign the amsops */
5344 aopOp (left, ic, FALSE);
5345 aopOp (right, ic, FALSE);
5346 aopOp (result, ic, TRUE);
5348 /* special cases first */
5350 if (AOP_TYPE (left) == AOP_CRY &&
5351 AOP_TYPE (right) == AOP_CRY)
5353 genDivbits (left, right, result);
5357 /* if both are of size == 1 */
5358 if (AOP_SIZE (left) == 1 &&
5359 AOP_SIZE (right) == 1)
5361 genDivOneByte (left, right, result);
5365 /* should have been converted to function call */
5368 freeAsmop (result, NULL, ic, TRUE);
5369 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373 /*-----------------------------------------------------------------*/
5374 /* genModbits :- modulus of bits */
5375 /*-----------------------------------------------------------------*/
5377 genModbits (operand * left,
5384 D (emitcode (";", "genModbits"));
5388 /* the result must be bit */
5389 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5390 l = aopGet (left, 0, FALSE, FALSE);
5394 emitcode ("div", "ab");
5395 emitcode ("mov", "a,b");
5396 emitcode ("rrc", "a");
5400 aopPut (result, "c", 0);
5403 /*-----------------------------------------------------------------*/
5404 /* genModOneByte : 8 bit modulus */
5405 /*-----------------------------------------------------------------*/
5407 genModOneByte (operand * left,
5411 bool lUnsigned, rUnsigned, pushedB;
5412 bool runtimeSign, compiletimeSign;
5416 D (emitcode (";", "genModOneByte"));
5418 size = AOP_SIZE (result) - 1;
5420 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5421 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5423 /* if right is a literal, check it for 2^n */
5424 if (AOP_TYPE(right) == AOP_LIT)
5426 unsigned char val = abs((int) operandLitValue(right));
5427 symbol *lbl2 = NULL;
5431 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5441 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5442 /* because iCode should have been changed to genAnd */
5443 /* see file "SDCCopt.c", function "convertToFcall()" */
5445 MOVA (aopGet (left, 0, FALSE, FALSE));
5446 emitcode ("mov", "c,acc.7");
5447 emitcode ("anl", "a,#0x%02x", val - 1);
5448 lbl = newiTempLabel (NULL);
5449 emitcode ("jz", "%05d$", (lbl->key + 100));
5450 emitcode ("jnc", "%05d$", (lbl->key + 100));
5451 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5457 aopPut (result, "a", 0);
5459 aopPut (result, "#0xff", offs2++);
5460 lbl2 = newiTempLabel (NULL);
5461 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5464 aopPut (result, "a", 0);
5466 aopPut (result, zero, offset++);
5480 /* signed or unsigned */
5481 if (lUnsigned && rUnsigned)
5483 /* unsigned is easy */
5484 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5485 MOVA (aopGet (left, 0, FALSE, FALSE));
5486 emitcode ("div", "ab");
5487 aopPut (result, "b", 0);
5489 aopPut (result, zero, offset++);
5495 /* signed is a little bit more difficult */
5497 /* now sign adjust for both left & right */
5499 /* modulus: sign of the right operand has no influence on the result! */
5500 if (AOP_TYPE(right) == AOP_LIT)
5502 signed char val = (char) operandLitValue(right);
5504 if (!rUnsigned && val < 0)
5505 emitcode ("mov", "b,#0x%02x", -val);
5507 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5509 else /* not literal */
5512 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5515 MOVA (aopGet (right, 0, FALSE, FALSE));
5516 lbl = newiTempLabel (NULL);
5517 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5518 emitcode ("cpl", "a"); /* 2's complement */
5519 emitcode ("inc", "a");
5521 emitcode ("mov", "b,a");
5525 /* let's see what's needed: */
5526 /* apply negative sign during runtime */
5527 runtimeSign = FALSE;
5528 /* negative sign from literals */
5529 compiletimeSign = FALSE;
5531 /* sign adjust left side */
5532 if (AOP_TYPE(left) == AOP_LIT)
5534 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5536 if (!lUnsigned && val < 0)
5538 compiletimeSign = TRUE; /* set sign flag */
5539 emitcode ("mov", "a,#0x%02x", -val);
5542 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5544 else /* ! literal */
5546 MOVA (aopGet (left, 0, FALSE, FALSE));
5551 emitcode ("clr", "F0"); /* clear sign flag */
5553 lbl = newiTempLabel (NULL);
5554 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5555 emitcode ("setb", "F0"); /* set sign flag */
5556 emitcode ("cpl", "a"); /* 2's complement */
5557 emitcode ("inc", "a");
5562 /* now the modulus */
5563 emitcode ("div", "ab");
5565 if (runtimeSign || compiletimeSign)
5567 emitcode ("mov", "a,b");
5568 lbl = newiTempLabel (NULL);
5570 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5571 emitcode ("cpl", "a"); /* 2's complement */
5572 emitcode ("inc", "a");
5575 aopPut (result, "a", 0);
5578 /* msb is 0x00 or 0xff depending on the sign */
5581 emitcode ("mov", "c,F0");
5582 emitcode ("subb", "a,acc");
5584 aopPut (result, "a", offset++);
5586 else /* compiletimeSign */
5588 aopPut (result, "#0xff", offset++);
5593 aopPut (result, "b", 0);
5595 aopPut (result, zero, offset++);
5601 /*-----------------------------------------------------------------*/
5602 /* genMod - generates code for division */
5603 /*-----------------------------------------------------------------*/
5607 operand *left = IC_LEFT (ic);
5608 operand *right = IC_RIGHT (ic);
5609 operand *result = IC_RESULT (ic);
5611 D (emitcode (";", "genMod"));
5613 /* assign the asmops */
5614 aopOp (left, ic, FALSE);
5615 aopOp (right, ic, FALSE);
5616 aopOp (result, ic, TRUE);
5618 /* special cases first */
5620 if (AOP_TYPE (left) == AOP_CRY &&
5621 AOP_TYPE (right) == AOP_CRY)
5623 genModbits (left, right, result);
5627 /* if both are of size == 1 */
5628 if (AOP_SIZE (left) == 1 &&
5629 AOP_SIZE (right) == 1)
5631 genModOneByte (left, right, result);
5635 /* should have been converted to function call */
5639 freeAsmop (result, NULL, ic, TRUE);
5640 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5644 /*-----------------------------------------------------------------*/
5645 /* genIfxJump :- will create a jump depending on the ifx */
5646 /*-----------------------------------------------------------------*/
5648 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5651 symbol *tlbl = newiTempLabel (NULL);
5654 D (emitcode (";", "genIfxJump"));
5656 /* if true label then we jump if condition
5660 jlbl = IC_TRUE (ic);
5661 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5662 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5666 /* false label is present */
5667 jlbl = IC_FALSE (ic);
5668 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5669 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5671 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5672 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5674 emitcode (inst, "%05d$", tlbl->key + 100);
5675 freeForBranchAsmop (result);
5676 freeForBranchAsmop (right);
5677 freeForBranchAsmop (left);
5678 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5681 /* mark the icode as generated */
5685 /*-----------------------------------------------------------------*/
5686 /* genCmp :- greater or less than comparison */
5687 /*-----------------------------------------------------------------*/
5689 genCmp (operand * left, operand * right,
5690 operand * result, iCode * ifx, int sign, iCode *ic)
5692 int size, offset = 0;
5693 unsigned long lit = 0L;
5696 D (emitcode (";", "genCmp"));
5698 /* if left & right are bit variables */
5699 if (AOP_TYPE (left) == AOP_CRY &&
5700 AOP_TYPE (right) == AOP_CRY)
5702 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5703 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5707 /* subtract right from left if at the
5708 end the carry flag is set then we know that
5709 left is greater than right */
5710 size = max (AOP_SIZE (left), AOP_SIZE (right));
5712 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5713 if ((size == 1) && !sign &&
5714 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5716 symbol *lbl = newiTempLabel (NULL);
5717 emitcode ("cjne", "%s,%s,%05d$",
5718 aopGet (left, offset, FALSE, FALSE),
5719 aopGet (right, offset, FALSE, FALSE),
5725 if (AOP_TYPE (right) == AOP_LIT)
5727 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5728 /* optimize if(x < 0) or if(x >= 0) */
5737 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5738 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5740 genIfxJump (ifx, "acc.7", left, right, result);
5741 freeAsmop (right, NULL, ic, TRUE);
5742 freeAsmop (left, NULL, ic, TRUE);
5748 emitcode ("rlc", "a");
5755 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5756 while (size && (bytelit == 0))
5759 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5765 MOVA (aopGet (left, offset, FALSE, FALSE));
5766 if (sign && size == 0)
5768 emitcode ("xrl", "a,#0x80");
5769 emitcode ("subb", "a,#0x%02x",
5770 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5774 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5784 bool pushedB = FALSE;
5785 rightInB = aopGetUsesAcc(right, offset);
5789 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5791 MOVA (aopGet (left, offset, FALSE, FALSE));
5792 if (sign && size == 0)
5794 emitcode ("xrl", "a,#0x80");
5799 MOVB (aopGet (right, offset, FALSE, FALSE));
5801 emitcode ("xrl", "b,#0x80");
5802 emitcode ("subb", "a,b");
5807 emitcode ("subb", "a,b");
5809 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5819 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5820 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5821 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5827 /* if the result is used in the next
5828 ifx conditional branch then generate
5829 code a little differently */
5832 genIfxJump (ifx, "c", NULL, NULL, result);
5838 /* leave the result in acc */
5842 /*-----------------------------------------------------------------*/
5843 /* genCmpGt :- greater than comparison */
5844 /*-----------------------------------------------------------------*/
5846 genCmpGt (iCode * ic, iCode * ifx)
5848 operand *left, *right, *result;
5849 sym_link *letype, *retype;
5852 D (emitcode (";", "genCmpGt"));
5854 left = IC_LEFT (ic);
5855 right = IC_RIGHT (ic);
5856 result = IC_RESULT (ic);
5858 letype = getSpec (operandType (left));
5859 retype = getSpec (operandType (right));
5860 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5861 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5862 /* assign the amsops */
5863 aopOp (result, ic, TRUE);
5864 aopOp (left, ic, FALSE);
5865 aopOp (right, ic, FALSE);
5867 genCmp (right, left, result, ifx, sign, ic);
5869 freeAsmop (result, NULL, ic, TRUE);
5872 /*-----------------------------------------------------------------*/
5873 /* genCmpLt - less than comparisons */
5874 /*-----------------------------------------------------------------*/
5876 genCmpLt (iCode * ic, iCode * ifx)
5878 operand *left, *right, *result;
5879 sym_link *letype, *retype;
5882 D (emitcode (";", "genCmpLt"));
5884 left = IC_LEFT (ic);
5885 right = IC_RIGHT (ic);
5886 result = IC_RESULT (ic);
5888 letype = getSpec (operandType (left));
5889 retype = getSpec (operandType (right));
5890 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5891 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5892 /* assign the amsops */
5893 aopOp (result, ic, TRUE);
5894 aopOp (left, ic, FALSE);
5895 aopOp (right, ic, FALSE);
5897 genCmp (left, right, result, ifx, sign, ic);
5899 freeAsmop (result, NULL, ic, TRUE);
5902 /*-----------------------------------------------------------------*/
5903 /* gencjneshort - compare and jump if not equal */
5904 /*-----------------------------------------------------------------*/
5906 gencjneshort (operand * left, operand * right, symbol * lbl)
5908 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5910 unsigned long lit = 0L;
5912 D (emitcode (";", "gencjneshort"));
5914 /* if the left side is a literal or
5915 if the right is in a pointer register and left
5917 if ((AOP_TYPE (left) == AOP_LIT) ||
5918 (AOP_TYPE (left) == AOP_IMMD) ||
5919 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5926 if (AOP_TYPE (right) == AOP_LIT)
5927 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5929 /* if the right side is a literal then anything goes */
5930 if (AOP_TYPE (right) == AOP_LIT &&
5931 AOP_TYPE (left) != AOP_DIR &&
5932 AOP_TYPE (left) != AOP_IMMD)
5936 emitcode ("cjne", "%s,%s,%05d$",
5937 aopGet (left, offset, FALSE, FALSE),
5938 aopGet (right, offset, FALSE, FALSE),
5944 /* if the right side is in a register or in direct space or
5945 if the left is a pointer register & right is not */
5946 else if (AOP_TYPE (right) == AOP_REG ||
5947 AOP_TYPE (right) == AOP_DIR ||
5948 AOP_TYPE (right) == AOP_LIT ||
5949 AOP_TYPE (right) == AOP_IMMD ||
5950 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5951 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5955 MOVA (aopGet (left, offset, FALSE, FALSE));
5956 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5957 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5958 emitcode ("jnz", "%05d$", lbl->key + 100);
5960 emitcode ("cjne", "a,%s,%05d$",
5961 aopGet (right, offset, FALSE, TRUE),
5968 /* right is a pointer reg need both a & b */
5971 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5972 wassertl(!BINUSE, "B was in use");
5973 MOVB (aopGet (left, offset, FALSE, FALSE));
5974 MOVA (aopGet (right, offset, FALSE, FALSE));
5975 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5981 /*-----------------------------------------------------------------*/
5982 /* gencjne - compare and jump if not equal */
5983 /*-----------------------------------------------------------------*/
5985 gencjne (operand * left, operand * right, symbol * lbl)
5987 symbol *tlbl = newiTempLabel (NULL);
5989 D (emitcode (";", "gencjne"));
5991 gencjneshort (left, right, lbl);
5993 emitcode ("mov", "a,%s", one);
5994 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5996 emitcode ("clr", "a");
6000 /*-----------------------------------------------------------------*/
6001 /* genCmpEq - generates code for equal to */
6002 /*-----------------------------------------------------------------*/
6004 genCmpEq (iCode * ic, iCode * ifx)
6006 bool swappedLR = FALSE;
6007 operand *left, *right, *result;
6009 D (emitcode (";", "genCmpEq"));
6011 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6012 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6013 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6015 /* if literal, literal on the right or
6016 if the right is in a pointer register and left
6018 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6019 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6021 operand *t = IC_RIGHT (ic);
6022 IC_RIGHT (ic) = IC_LEFT (ic);
6027 if (ifx && !AOP_SIZE (result))
6030 /* if they are both bit variables */
6031 if (AOP_TYPE (left) == AOP_CRY &&
6032 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6034 if (AOP_TYPE (right) == AOP_LIT)
6036 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6039 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6040 emitcode ("cpl", "c");
6044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6048 emitcode ("clr", "c");
6050 /* AOP_TYPE(right) == AOP_CRY */
6054 symbol *lbl = newiTempLabel (NULL);
6055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6056 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6057 emitcode ("cpl", "c");
6060 /* if true label then we jump if condition
6062 tlbl = newiTempLabel (NULL);
6065 emitcode ("jnc", "%05d$", tlbl->key + 100);
6066 freeForBranchAsmop (result);
6067 freeForBranchAsmop (right);
6068 freeForBranchAsmop (left);
6069 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6073 emitcode ("jc", "%05d$", tlbl->key + 100);
6074 freeForBranchAsmop (result);
6075 freeForBranchAsmop (right);
6076 freeForBranchAsmop (left);
6077 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6083 tlbl = newiTempLabel (NULL);
6084 gencjneshort (left, right, tlbl);
6087 freeForBranchAsmop (result);
6088 freeForBranchAsmop (right);
6089 freeForBranchAsmop (left);
6090 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6095 symbol *lbl = newiTempLabel (NULL);
6096 emitcode ("sjmp", "%05d$", lbl->key + 100);
6098 freeForBranchAsmop (result);
6099 freeForBranchAsmop (right);
6100 freeForBranchAsmop (left);
6101 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6105 /* mark the icode as generated */
6110 /* if they are both bit variables */
6111 if (AOP_TYPE (left) == AOP_CRY &&
6112 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6114 if (AOP_TYPE (right) == AOP_LIT)
6116 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6119 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6120 emitcode ("cpl", "c");
6124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6128 emitcode ("clr", "c");
6130 /* AOP_TYPE(right) == AOP_CRY */
6134 symbol *lbl = newiTempLabel (NULL);
6135 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6136 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6137 emitcode ("cpl", "c");
6141 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6148 genIfxJump (ifx, "c", left, right, result);
6151 /* if the result is used in an arithmetic operation
6152 then put the result in place */
6157 gencjne (left, right, newiTempLabel (NULL));
6158 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6160 aopPut (result, "a", 0);
6165 genIfxJump (ifx, "a", left, right, result);
6168 /* if the result is used in an arithmetic operation
6169 then put the result in place */
6170 if (AOP_TYPE (result) != AOP_CRY)
6172 /* leave the result in acc */
6176 freeAsmop (result, NULL, ic, TRUE);
6179 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6180 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6184 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6185 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6189 /*-----------------------------------------------------------------*/
6190 /* ifxForOp - returns the icode containing the ifx for operand */
6191 /*-----------------------------------------------------------------*/
6193 ifxForOp (operand * op, iCode * ic)
6195 /* if true symbol then needs to be assigned */
6196 if (IS_TRUE_SYMOP (op))
6199 /* if this has register type condition and
6200 the next instruction is ifx with the same operand
6201 and live to of the operand is upto the ifx only then */
6203 ic->next->op == IFX &&
6204 IC_COND (ic->next)->key == op->key &&
6205 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6211 /*-----------------------------------------------------------------*/
6212 /* hasInc - operand is incremented before any other use */
6213 /*-----------------------------------------------------------------*/
6215 hasInc (operand *op, iCode *ic, int osize)
6217 sym_link *type = operandType(op);
6218 sym_link *retype = getSpec (type);
6219 iCode *lic = ic->next;
6222 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6223 if (!IS_SYMOP(op)) return NULL;
6225 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6226 if (IS_AGGREGATE(type->next)) return NULL;
6227 if (osize != (isize = getSize(type->next))) return NULL;
6230 /* if operand of the form op = op + <sizeof *op> */
6231 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6232 isOperandEqual(IC_RESULT(lic),op) &&
6233 isOperandLiteral(IC_RIGHT(lic)) &&
6234 operandLitValue(IC_RIGHT(lic)) == isize) {
6237 /* if the operand used or deffed */
6238 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6241 /* if GOTO or IFX */
6242 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6248 /*-----------------------------------------------------------------*/
6249 /* genAndOp - for && operation */
6250 /*-----------------------------------------------------------------*/
6252 genAndOp (iCode * ic)
6254 operand *left, *right, *result;
6257 D (emitcode (";", "genAndOp"));
6259 /* note here that && operations that are in an
6260 if statement are taken away by backPatchLabels
6261 only those used in arthmetic operations remain */
6262 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6263 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6264 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6266 /* if both are bit variables */
6267 if (AOP_TYPE (left) == AOP_CRY &&
6268 AOP_TYPE (right) == AOP_CRY)
6270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6271 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6276 tlbl = newiTempLabel (NULL);
6278 emitcode ("jz", "%05d$", tlbl->key + 100);
6284 freeAsmop (result, NULL, ic, TRUE);
6285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6286 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6290 /*-----------------------------------------------------------------*/
6291 /* genOrOp - for || operation */
6292 /*-----------------------------------------------------------------*/
6294 genOrOp (iCode * ic)
6296 operand *left, *right, *result;
6299 D (emitcode (";", "genOrOp"));
6301 /* note here that || operations that are in an
6302 if statement are taken away by backPatchLabels
6303 only those used in arthmetic operations remain */
6304 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6305 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6306 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6308 /* if both are bit variables */
6309 if (AOP_TYPE (left) == AOP_CRY &&
6310 AOP_TYPE (right) == AOP_CRY)
6312 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6313 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6318 tlbl = newiTempLabel (NULL);
6320 emitcode ("jnz", "%05d$", tlbl->key + 100);
6326 freeAsmop (result, NULL, ic, TRUE);
6327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6328 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6331 /*-----------------------------------------------------------------*/
6332 /* isLiteralBit - test if lit == 2^n */
6333 /*-----------------------------------------------------------------*/
6335 isLiteralBit (unsigned long lit)
6337 unsigned long pw[32] =
6338 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6339 0x100L, 0x200L, 0x400L, 0x800L,
6340 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6341 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6342 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6343 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6344 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6347 for (idx = 0; idx < 32; idx++)
6353 /*-----------------------------------------------------------------*/
6354 /* continueIfTrue - */
6355 /*-----------------------------------------------------------------*/
6357 continueIfTrue (iCode * ic)
6360 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6364 /*-----------------------------------------------------------------*/
6366 /*-----------------------------------------------------------------*/
6368 jumpIfTrue (iCode * ic)
6371 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6375 /*-----------------------------------------------------------------*/
6376 /* jmpTrueOrFalse - */
6377 /*-----------------------------------------------------------------*/
6379 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6381 // ugly but optimized by peephole
6384 symbol *nlbl = newiTempLabel (NULL);
6385 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6387 freeForBranchAsmop (result);
6388 freeForBranchAsmop (right);
6389 freeForBranchAsmop (left);
6390 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6395 freeForBranchAsmop (result);
6396 freeForBranchAsmop (right);
6397 freeForBranchAsmop (left);
6398 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6404 /*-----------------------------------------------------------------*/
6405 /* genAnd - code for and */
6406 /*-----------------------------------------------------------------*/
6408 genAnd (iCode * ic, iCode * ifx)
6410 operand *left, *right, *result;
6411 int size, offset = 0;
6412 unsigned long lit = 0L;
6416 D (emitcode (";", "genAnd"));
6418 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6419 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6420 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6423 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6425 AOP_TYPE (left), AOP_TYPE (right));
6426 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6428 AOP_SIZE (left), AOP_SIZE (right));
6431 /* if left is a literal & right is not then exchange them */
6432 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6433 AOP_NEEDSACC (left))
6435 operand *tmp = right;
6440 /* if result = right then exchange left and right */
6441 if (sameRegs (AOP (result), AOP (right)))
6443 operand *tmp = right;
6448 /* if right is bit then exchange them */
6449 if (AOP_TYPE (right) == AOP_CRY &&
6450 AOP_TYPE (left) != AOP_CRY)
6452 operand *tmp = right;
6456 if (AOP_TYPE (right) == AOP_LIT)
6457 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6459 size = AOP_SIZE (result);
6462 // result = bit & yy;
6463 if (AOP_TYPE (left) == AOP_CRY)
6465 // c = bit & literal;
6466 if (AOP_TYPE (right) == AOP_LIT)
6470 if (size && sameRegs (AOP (result), AOP (left)))
6473 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6478 if (size && (AOP_TYPE (result) == AOP_CRY))
6480 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6483 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6488 emitcode ("clr", "c");
6493 if (AOP_TYPE (right) == AOP_CRY)
6496 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6497 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6502 MOVA (aopGet (right, 0, FALSE, FALSE));
6504 emitcode ("rrc", "a");
6505 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6513 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6514 genIfxJump (ifx, "c", left, right, result);
6518 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6519 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6520 if ((AOP_TYPE (right) == AOP_LIT) &&
6521 (AOP_TYPE (result) == AOP_CRY) &&
6522 (AOP_TYPE (left) != AOP_CRY))
6524 int posbit = isLiteralBit (lit);
6529 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6533 switch (posbit & 0x07)
6535 case 0: emitcode ("rrc", "a");
6537 case 7: emitcode ("rlc", "a");
6539 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6548 SNPRINTF (buffer, sizeof(buffer),
6549 "acc.%d", posbit & 0x07);
6550 genIfxJump (ifx, buffer, left, right, result);
6553 {// what is this case? just found it in ds390/gen.c
6554 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6561 symbol *tlbl = newiTempLabel (NULL);
6562 int sizel = AOP_SIZE (left);
6564 emitcode ("setb", "c");
6567 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6569 MOVA (aopGet (left, offset, FALSE, FALSE));
6571 if ((posbit = isLiteralBit (bytelit)) != 0)
6572 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6575 if (bytelit != 0x0FFL)
6576 emitcode ("anl", "a,%s",
6577 aopGet (right, offset, FALSE, TRUE));
6578 emitcode ("jnz", "%05d$", tlbl->key + 100);
6583 // bit = left & literal
6586 emitcode ("clr", "c");
6589 // if(left & literal)
6593 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6603 /* if left is same as result */
6604 if (sameRegs (AOP (result), AOP (left)))
6606 for (; size--; offset++)
6608 if (AOP_TYPE (right) == AOP_LIT)
6610 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6611 if (bytelit == 0x0FF)
6613 /* dummy read of volatile operand */
6614 if (isOperandVolatile (left, FALSE))
6615 MOVA (aopGet (left, offset, FALSE, FALSE));
6619 else if (bytelit == 0)
6621 aopPut (result, zero, offset);
6623 else if (IS_AOP_PREG (result))
6625 MOVA (aopGet (left, offset, FALSE, TRUE));
6626 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6627 aopPut (result, "a", offset);
6630 emitcode ("anl", "%s,%s",
6631 aopGet (left, offset, FALSE, TRUE),
6632 aopGet (right, offset, FALSE, FALSE));
6636 if (AOP_TYPE (left) == AOP_ACC)
6639 emitcode("mov", "a,b");
6640 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6642 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6644 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6645 MOVA (aopGet (right, offset, FALSE, FALSE));
6646 emitcode ("anl", "a,b");
6647 aopPut (result, "a", offset);
6649 else if (aopGetUsesAcc (left, offset))
6651 MOVA (aopGet (left, offset, FALSE, FALSE));
6652 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6653 aopPut (result, "a", offset);
6657 MOVA (aopGet (right, offset, FALSE, FALSE));
6658 if (IS_AOP_PREG (result))
6660 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6661 aopPut (result, "a", offset);
6664 emitcode ("anl", "%s,a",
6665 aopGet (left, offset, FALSE, TRUE));
6672 // left & result in different registers
6673 if (AOP_TYPE (result) == AOP_CRY)
6676 // if(size), result in bit
6677 // if(!size && ifx), conditional oper: if(left & right)
6678 symbol *tlbl = newiTempLabel (NULL);
6679 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6681 emitcode ("setb", "c");
6684 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6685 && AOP_TYPE(left)==AOP_ACC)
6688 emitcode("mov", "a,b");
6689 emitcode ("anl", "a,%s",
6690 aopGet (right, offset, FALSE, FALSE));
6692 if (AOP_TYPE(left)==AOP_ACC)
6696 bool pushedB = pushB ();
6697 emitcode("mov", "b,a");
6698 MOVA (aopGet (right, offset, FALSE, FALSE));
6699 emitcode("anl", "a,b");
6704 MOVA (aopGet (right, offset, FALSE, FALSE));
6705 emitcode("anl", "a,b");
6708 MOVA (aopGet (right, offset, FALSE, FALSE));
6709 emitcode ("anl", "a,%s",
6710 aopGet (left, offset, FALSE, FALSE));
6713 emitcode ("jnz", "%05d$", tlbl->key + 100);
6723 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6729 for (; (size--); offset++)
6732 // result = left & right
6733 if (AOP_TYPE (right) == AOP_LIT)
6735 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6736 if (bytelit == 0x0FF)
6739 aopGet (left, offset, FALSE, FALSE),
6743 else if (bytelit == 0)
6745 /* dummy read of volatile operand */
6746 if (isOperandVolatile (left, FALSE))
6747 MOVA (aopGet (left, offset, FALSE, FALSE));
6748 aopPut (result, zero, offset);
6751 else if (AOP_TYPE (left) == AOP_ACC)
6755 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6756 aopPut (result, "a", offset);
6761 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6762 aopPut (result, "b", offset);
6767 // faster than result <- left, anl result,right
6768 // and better if result is SFR
6769 if (AOP_TYPE (left) == AOP_ACC)
6772 emitcode("mov", "a,b");
6773 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6775 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6777 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6778 MOVA (aopGet (right, offset, FALSE, FALSE));
6779 emitcode ("anl", "a,b");
6781 else if (aopGetUsesAcc (left, offset))
6783 MOVA (aopGet (left, offset, FALSE, FALSE));
6784 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6788 MOVA (aopGet (right, offset, FALSE, FALSE));
6789 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6791 aopPut (result, "a", offset);
6797 freeAsmop (result, NULL, ic, TRUE);
6798 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6799 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6802 /*-----------------------------------------------------------------*/
6803 /* genOr - code for or */
6804 /*-----------------------------------------------------------------*/
6806 genOr (iCode * ic, iCode * ifx)
6808 operand *left, *right, *result;
6809 int size, offset = 0;
6810 unsigned long lit = 0L;
6813 D (emitcode (";", "genOr"));
6815 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6816 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6817 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6820 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6822 AOP_TYPE (left), AOP_TYPE (right));
6823 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6825 AOP_SIZE (left), AOP_SIZE (right));
6828 /* if left is a literal & right is not then exchange them */
6829 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6830 AOP_NEEDSACC (left))
6832 operand *tmp = right;
6837 /* if result = right then exchange them */
6838 if (sameRegs (AOP (result), AOP (right)))
6840 operand *tmp = right;
6845 /* if right is bit then exchange them */
6846 if (AOP_TYPE (right) == AOP_CRY &&
6847 AOP_TYPE (left) != AOP_CRY)
6849 operand *tmp = right;
6853 if (AOP_TYPE (right) == AOP_LIT)
6854 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6856 size = AOP_SIZE (result);
6860 if (AOP_TYPE (left) == AOP_CRY)
6862 if (AOP_TYPE (right) == AOP_LIT)
6864 // c = bit | literal;
6867 // lit != 0 => result = 1
6868 if (AOP_TYPE (result) == AOP_CRY)
6871 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6873 continueIfTrue (ifx);
6876 emitcode ("setb", "c");
6880 // lit == 0 => result = left
6881 if (size && sameRegs (AOP (result), AOP (left)))
6883 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6888 if (AOP_TYPE (right) == AOP_CRY)
6891 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6892 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6897 symbol *tlbl = newiTempLabel (NULL);
6898 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6899 emitcode ("setb", "c");
6900 emitcode ("jb", "%s,%05d$",
6901 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6903 emitcode ("jnz", "%05d$", tlbl->key + 100);
6904 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6906 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6921 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6922 genIfxJump (ifx, "c", left, right, result);
6926 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6927 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6928 if ((AOP_TYPE (right) == AOP_LIT) &&
6929 (AOP_TYPE (result) == AOP_CRY) &&
6930 (AOP_TYPE (left) != AOP_CRY))
6936 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6938 continueIfTrue (ifx);
6943 // lit = 0, result = boolean(left)
6945 emitcode ("setb", "c");
6949 symbol *tlbl = newiTempLabel (NULL);
6950 emitcode ("jnz", "%05d$", tlbl->key + 100);
6956 genIfxJump (ifx, "a", left, right, result);
6964 /* if left is same as result */
6965 if (sameRegs (AOP (result), AOP (left)))
6967 for (; size--; offset++)
6969 if (AOP_TYPE (right) == AOP_LIT)
6971 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6974 /* dummy read of volatile operand */
6975 if (isOperandVolatile (left, FALSE))
6976 MOVA (aopGet (left, offset, FALSE, FALSE));
6980 else if (bytelit == 0x0FF)
6982 aopPut (result, "#0xFF", offset);
6984 else if (IS_AOP_PREG (left))
6986 MOVA (aopGet (left, offset, FALSE, TRUE));
6987 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6988 aopPut (result, "a", offset);
6992 emitcode ("orl", "%s,%s",
6993 aopGet (left, offset, FALSE, TRUE),
6994 aopGet (right, offset, FALSE, FALSE));
6999 if (AOP_TYPE (left) == AOP_ACC)
7002 emitcode("mov", "a,b");
7003 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7005 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7007 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7008 MOVA (aopGet (right, offset, FALSE, FALSE));
7009 emitcode ("orl", "a,b");
7010 aopPut (result, "a", offset);
7012 else if (aopGetUsesAcc (left, offset))
7014 MOVA (aopGet (left, offset, FALSE, FALSE));
7015 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016 aopPut (result, "a", offset);
7020 MOVA (aopGet (right, offset, FALSE, FALSE));
7021 if (IS_AOP_PREG (left))
7023 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7024 aopPut (result, "a", offset);
7028 emitcode ("orl", "%s,a",
7029 aopGet (left, offset, FALSE, TRUE));
7037 // left & result in different registers
7038 if (AOP_TYPE (result) == AOP_CRY)
7041 // if(size), result in bit
7042 // if(!size && ifx), conditional oper: if(left | right)
7043 symbol *tlbl = newiTempLabel (NULL);
7044 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7046 emitcode ("setb", "c");
7049 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7051 emitcode("mov", "a,b");
7052 emitcode ("orl", "a,%s",
7053 aopGet (right, offset, FALSE, FALSE));
7055 MOVA (aopGet (right, offset, FALSE, FALSE));
7056 emitcode ("orl", "a,%s",
7057 aopGet (left, offset, FALSE, FALSE));
7059 emitcode ("jnz", "%05d$", tlbl->key + 100);
7069 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7075 for (; (size--); offset++)
7078 // result = left | right
7079 if (AOP_TYPE (right) == AOP_LIT)
7081 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7085 aopGet (left, offset, FALSE, FALSE),
7089 else if (bytelit == 0x0FF)
7091 /* dummy read of volatile operand */
7092 if (isOperandVolatile (left, FALSE))
7093 MOVA (aopGet (left, offset, FALSE, FALSE));
7094 aopPut (result, "#0xFF", offset);
7098 // faster than result <- left, anl result,right
7099 // and better if result is SFR
7100 if (AOP_TYPE (left) == AOP_ACC)
7103 emitcode("mov", "a,b");
7104 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7106 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7108 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7109 MOVA (aopGet (right, offset, FALSE, FALSE));
7110 emitcode ("orl", "a,b");
7112 else if (aopGetUsesAcc (left, offset))
7114 MOVA (aopGet (left, offset, FALSE, FALSE));
7115 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7119 MOVA (aopGet (right, offset, FALSE, FALSE));
7120 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7122 aopPut (result, "a", offset);
7128 freeAsmop (result, NULL, ic, TRUE);
7129 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7130 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7133 /*-----------------------------------------------------------------*/
7134 /* genXor - code for xclusive or */
7135 /*-----------------------------------------------------------------*/
7137 genXor (iCode * ic, iCode * ifx)
7139 operand *left, *right, *result;
7140 int size, offset = 0;
7141 unsigned long lit = 0L;
7144 D (emitcode (";", "genXor"));
7146 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7147 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7148 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7151 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7153 AOP_TYPE (left), AOP_TYPE (right));
7154 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7156 AOP_SIZE (left), AOP_SIZE (right));
7159 /* if left is a literal & right is not ||
7160 if left needs acc & right does not */
7161 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7162 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7164 operand *tmp = right;
7169 /* if result = right then exchange them */
7170 if (sameRegs (AOP (result), AOP (right)))
7172 operand *tmp = right;
7177 /* if right is bit then exchange them */
7178 if (AOP_TYPE (right) == AOP_CRY &&
7179 AOP_TYPE (left) != AOP_CRY)
7181 operand *tmp = right;
7185 if (AOP_TYPE (right) == AOP_LIT)
7186 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7188 size = AOP_SIZE (result);
7192 if (AOP_TYPE (left) == AOP_CRY)
7194 if (AOP_TYPE (right) == AOP_LIT)
7196 // c = bit & literal;
7199 // lit>>1 != 0 => result = 1
7200 if (AOP_TYPE (result) == AOP_CRY)
7203 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7205 continueIfTrue (ifx);
7208 emitcode ("setb", "c");
7215 // lit == 0, result = left
7216 if (size && sameRegs (AOP (result), AOP (left)))
7218 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7222 // lit == 1, result = not(left)
7223 if (size && sameRegs (AOP (result), AOP (left)))
7225 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7230 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7231 emitcode ("cpl", "c");
7240 symbol *tlbl = newiTempLabel (NULL);
7241 if (AOP_TYPE (right) == AOP_CRY)
7244 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7248 int sizer = AOP_SIZE (right);
7250 // if val>>1 != 0, result = 1
7251 emitcode ("setb", "c");
7254 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7256 // test the msb of the lsb
7257 emitcode ("anl", "a,#0xfe");
7258 emitcode ("jnz", "%05d$", tlbl->key + 100);
7262 emitcode ("rrc", "a");
7264 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7265 emitcode ("cpl", "c");
7273 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7274 genIfxJump (ifx, "c", left, right, result);
7278 /* if left is same as result */
7279 if (sameRegs (AOP (result), AOP (left)))
7281 for (; size--; offset++)
7283 if (AOP_TYPE (right) == AOP_LIT)
7285 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7288 /* dummy read of volatile operand */
7289 if (isOperandVolatile (left, FALSE))
7290 MOVA (aopGet (left, offset, FALSE, FALSE));
7294 else if (IS_AOP_PREG (left))
7296 MOVA (aopGet (left, offset, FALSE, TRUE));
7297 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7298 aopPut (result, "a", offset);
7302 emitcode ("xrl", "%s,%s",
7303 aopGet (left, offset, FALSE, TRUE),
7304 aopGet (right, offset, FALSE, FALSE));
7309 if (AOP_TYPE (left) == AOP_ACC)
7312 emitcode("mov", "a,b");
7313 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7315 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7317 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7318 MOVA (aopGet (right, offset, FALSE, FALSE));
7319 emitcode ("xrl", "a,b");
7320 aopPut (result, "a", offset);
7322 else if (aopGetUsesAcc (left, offset))
7324 MOVA (aopGet (left, offset, FALSE, FALSE));
7325 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7326 aopPut (result, "a", offset);
7330 MOVA (aopGet (right, offset, FALSE, FALSE));
7331 if (IS_AOP_PREG (left))
7333 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7334 aopPut (result, "a", offset);
7337 emitcode ("xrl", "%s,a",
7338 aopGet (left, offset, FALSE, TRUE));
7345 // left & result in different registers
7346 if (AOP_TYPE (result) == AOP_CRY)
7349 // if(size), result in bit
7350 // if(!size && ifx), conditional oper: if(left ^ right)
7351 symbol *tlbl = newiTempLabel (NULL);
7352 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7355 emitcode ("setb", "c");
7358 if ((AOP_TYPE (right) == AOP_LIT) &&
7359 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7361 MOVA (aopGet (left, offset, FALSE, FALSE));
7365 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7367 emitcode("mov", "a,b");
7368 emitcode ("xrl", "a,%s",
7369 aopGet (right, offset, FALSE, FALSE));
7371 MOVA (aopGet (right, offset, FALSE, FALSE));
7372 emitcode ("xrl", "a,%s",
7373 aopGet (left, offset, FALSE, FALSE));
7376 emitcode ("jnz", "%05d$", tlbl->key + 100);
7386 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7390 for (; (size--); offset++)
7393 // result = left ^ right
7394 if (AOP_TYPE (right) == AOP_LIT)
7396 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7400 aopGet (left, offset, FALSE, FALSE),
7405 // faster than result <- left, anl result,right
7406 // and better if result is SFR
7407 if (AOP_TYPE (left) == AOP_ACC)
7410 emitcode("mov", "a,b");
7411 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7413 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7415 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7416 MOVA (aopGet (right, offset, FALSE, FALSE));
7417 emitcode ("xrl", "a,b");
7419 else if (aopGetUsesAcc (left, offset))
7421 MOVA (aopGet (left, offset, FALSE, FALSE));
7422 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7426 MOVA (aopGet (right, offset, FALSE, FALSE));
7427 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7429 aopPut (result, "a", offset);
7435 freeAsmop (result, NULL, ic, TRUE);
7436 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7437 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7440 /*-----------------------------------------------------------------*/
7441 /* genInline - write the inline code out */
7442 /*-----------------------------------------------------------------*/
7444 genInline (iCode * ic)
7446 char *buffer, *bp, *bp1;
7448 D (emitcode (";", "genInline"));
7450 _G.inLine += (!options.asmpeep);
7452 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7454 /* emit each line as a code */
7465 /* Add \n for labels, not dirs such as c:\mydir */
7466 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7480 /* emitcode("",buffer); */
7481 _G.inLine -= (!options.asmpeep);
7484 /*-----------------------------------------------------------------*/
7485 /* genRRC - rotate right with carry */
7486 /*-----------------------------------------------------------------*/
7490 operand *left, *result;
7494 D (emitcode (";", "genRRC"));
7496 /* rotate right with carry */
7497 left = IC_LEFT (ic);
7498 result = IC_RESULT (ic);
7499 aopOp (left, ic, FALSE);
7500 aopOp (result, ic, FALSE);
7502 /* move it to the result */
7503 size = AOP_SIZE (result);
7505 if (size == 1) { /* special case for 1 byte */
7506 l = aopGet (left, offset, FALSE, FALSE);
7508 emitcode ("rr", "a");
7511 /* no need to clear carry, bit7 will be written later */
7514 l = aopGet (left, offset, FALSE, FALSE);
7516 emitcode ("rrc", "a");
7517 if (AOP_SIZE (result) > 1)
7518 aopPut (result, "a", offset--);
7520 /* now we need to put the carry into the
7521 highest order byte of the result */
7522 if (AOP_SIZE (result) > 1)
7524 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7527 emitcode ("mov", "acc.7,c");
7529 aopPut (result, "a", AOP_SIZE (result) - 1);
7530 freeAsmop (result, NULL, ic, TRUE);
7531 freeAsmop (left, NULL, ic, TRUE);
7534 /*-----------------------------------------------------------------*/
7535 /* genRLC - generate code for rotate left with carry */
7536 /*-----------------------------------------------------------------*/
7540 operand *left, *result;
7544 D (emitcode (";", "genRLC"));
7546 /* rotate right with carry */
7547 left = IC_LEFT (ic);
7548 result = IC_RESULT (ic);
7549 aopOp (left, ic, FALSE);
7550 aopOp (result, ic, FALSE);
7552 /* move it to the result */
7553 size = AOP_SIZE (result);
7557 l = aopGet (left, offset, FALSE, FALSE);
7559 if (size == 0) { /* special case for 1 byte */
7563 emitcode("rlc","a"); /* bit0 will be written later */
7564 if (AOP_SIZE (result) > 1)
7566 aopPut (result, "a", offset++);
7571 l = aopGet (left, offset, FALSE, FALSE);
7573 emitcode ("rlc", "a");
7574 if (AOP_SIZE (result) > 1)
7575 aopPut (result, "a", offset++);
7578 /* now we need to put the carry into the
7579 highest order byte of the result */
7580 if (AOP_SIZE (result) > 1)
7582 l = aopGet (result, 0, FALSE, FALSE);
7585 emitcode ("mov", "acc.0,c");
7587 aopPut (result, "a", 0);
7588 freeAsmop (result, NULL, ic, TRUE);
7589 freeAsmop (left, NULL, ic, TRUE);
7592 /*-----------------------------------------------------------------*/
7593 /* genGetHbit - generates code get highest order bit */
7594 /*-----------------------------------------------------------------*/
7596 genGetHbit (iCode * ic)
7598 operand *left, *result;
7600 D (emitcode (";", "genGetHbit"));
7602 left = IC_LEFT (ic);
7603 result = IC_RESULT (ic);
7604 aopOp (left, ic, FALSE);
7605 aopOp (result, ic, FALSE);
7607 /* get the highest order byte into a */
7608 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7609 if (AOP_TYPE (result) == AOP_CRY)
7611 emitcode ("rlc", "a");
7616 emitcode ("rl", "a");
7617 emitcode ("anl", "a,#0x01");
7621 freeAsmop (result, NULL, ic, TRUE);
7622 freeAsmop (left, NULL, ic, TRUE);
7625 /*-----------------------------------------------------------------*/
7626 /* genGetAbit - generates code get a single bit */
7627 /*-----------------------------------------------------------------*/
7629 genGetAbit (iCode * ic)
7631 operand *left, *right, *result;
7634 D (emitcode (";", "genGetAbit"));
7636 left = IC_LEFT (ic);
7637 right = IC_RIGHT (ic);
7638 result = IC_RESULT (ic);
7639 aopOp (left, ic, FALSE);
7640 aopOp (right, ic, FALSE);
7641 aopOp (result, ic, FALSE);
7643 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7645 /* get the needed byte into a */
7646 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7648 if (AOP_TYPE (result) == AOP_CRY)
7651 emitcode ("rlc", "a");
7652 else if ((shCount) == 0)
7653 emitcode ("rrc", "a");
7655 emitcode ("mov", "c,acc[%d]", shCount);
7663 emitcode ("rr", "a");
7666 emitcode ("rr", "a");
7669 emitcode ("anl", "a,#0x01");
7673 emitcode ("mov", "c,acc[%d]", shCount);
7674 emitcode ("clr", "a");
7675 emitcode ("rlc", "a");
7678 emitcode ("swap", "a");
7679 emitcode ("anl", "a,#0x01");
7682 emitcode ("rl", "a");
7685 emitcode ("rl", "a");
7686 emitcode ("anl", "a,#0x01");
7692 freeAsmop (result, NULL, ic, TRUE);
7693 freeAsmop (right, NULL, ic, TRUE);
7694 freeAsmop (left, NULL, ic, TRUE);
7697 /*-----------------------------------------------------------------*/
7698 /* genGetByte - generates code get a single byte */
7699 /*-----------------------------------------------------------------*/
7701 genGetByte (iCode * ic)
7703 operand *left, *right, *result;
7706 D (emitcode (";", "genGetByte"));
7708 left = IC_LEFT (ic);
7709 right = IC_RIGHT (ic);
7710 result = IC_RESULT (ic);
7711 aopOp (left, ic, FALSE);
7712 aopOp (right, ic, FALSE);
7713 aopOp (result, ic, FALSE);
7715 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7717 aopGet (left, offset, FALSE, FALSE),
7720 freeAsmop (result, NULL, ic, TRUE);
7721 freeAsmop (right, NULL, ic, TRUE);
7722 freeAsmop (left, NULL, ic, TRUE);
7725 /*-----------------------------------------------------------------*/
7726 /* genGetWord - generates code get two bytes */
7727 /*-----------------------------------------------------------------*/
7729 genGetWord (iCode * ic)
7731 operand *left, *right, *result;
7734 D (emitcode (";", "genGetWord"));
7736 left = IC_LEFT (ic);
7737 right = IC_RIGHT (ic);
7738 result = IC_RESULT (ic);
7739 aopOp (left, ic, FALSE);
7740 aopOp (right, ic, FALSE);
7741 aopOp (result, ic, FALSE);
7743 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7745 aopGet (left, offset, FALSE, FALSE),
7748 aopGet (left, offset+1, FALSE, FALSE),
7751 freeAsmop (result, NULL, ic, TRUE);
7752 freeAsmop (right, NULL, ic, TRUE);
7753 freeAsmop (left, NULL, ic, TRUE);
7756 /*-----------------------------------------------------------------*/
7757 /* genSwap - generates code to swap nibbles or bytes */
7758 /*-----------------------------------------------------------------*/
7760 genSwap (iCode * ic)
7762 operand *left, *result;
7764 D(emitcode ("; genSwap",""));
7766 left = IC_LEFT (ic);
7767 result = IC_RESULT (ic);
7768 aopOp (left, ic, FALSE);
7769 aopOp (result, ic, FALSE);
7771 switch (AOP_SIZE (left))
7773 case 1: /* swap nibbles in byte */
7774 MOVA (aopGet (left, 0, FALSE, FALSE));
7775 emitcode ("swap", "a");
7776 aopPut (result, "a", 0);
7778 case 2: /* swap bytes in word */
7779 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7781 MOVA (aopGet (left, 0, FALSE, FALSE));
7782 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7783 aopPut (result, "a", 1);
7785 else if (operandsEqu (left, result))
7788 bool pushedB = FALSE, leftInB = FALSE;
7790 MOVA (aopGet (left, 0, FALSE, FALSE));
7791 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7794 emitcode ("mov", "b,a");
7798 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7799 aopPut (result, reg, 1);
7806 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7807 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7811 wassertl(FALSE, "unsupported SWAP operand size");
7814 freeAsmop (result, NULL, ic, TRUE);
7815 freeAsmop (left, NULL, ic, TRUE);
7818 /*-----------------------------------------------------------------*/
7819 /* AccRol - rotate left accumulator by known count */
7820 /*-----------------------------------------------------------------*/
7822 AccRol (int shCount)
7824 shCount &= 0x0007; // shCount : 0..7
7831 emitcode ("rl", "a");
7834 emitcode ("rl", "a");
7835 emitcode ("rl", "a");
7838 emitcode ("swap", "a");
7839 emitcode ("rr", "a");
7842 emitcode ("swap", "a");
7845 emitcode ("swap", "a");
7846 emitcode ("rl", "a");
7849 emitcode ("rr", "a");
7850 emitcode ("rr", "a");
7853 emitcode ("rr", "a");
7858 /*-----------------------------------------------------------------*/
7859 /* AccLsh - left shift accumulator by known count */
7860 /*-----------------------------------------------------------------*/
7862 AccLsh (int shCount)
7867 emitcode ("add", "a,acc");
7868 else if (shCount == 2)
7870 emitcode ("add", "a,acc");
7871 emitcode ("add", "a,acc");
7875 /* rotate left accumulator */
7877 /* and kill the lower order bits */
7878 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7883 /*-----------------------------------------------------------------*/
7884 /* AccRsh - right shift accumulator by known count */
7885 /*-----------------------------------------------------------------*/
7887 AccRsh (int shCount)
7894 emitcode ("rrc", "a");
7898 /* rotate right accumulator */
7899 AccRol (8 - shCount);
7900 /* and kill the higher order bits */
7901 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7906 /*-----------------------------------------------------------------*/
7907 /* AccSRsh - signed right shift accumulator by known count */
7908 /*-----------------------------------------------------------------*/
7910 AccSRsh (int shCount)
7917 emitcode ("mov", "c,acc.7");
7918 emitcode ("rrc", "a");
7920 else if (shCount == 2)
7922 emitcode ("mov", "c,acc.7");
7923 emitcode ("rrc", "a");
7924 emitcode ("mov", "c,acc.7");
7925 emitcode ("rrc", "a");
7929 tlbl = newiTempLabel (NULL);
7930 /* rotate right accumulator */
7931 AccRol (8 - shCount);
7932 /* and kill the higher order bits */
7933 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7934 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7935 emitcode ("orl", "a,#0x%02x",
7936 (unsigned char) ~SRMask[shCount]);
7942 /*-----------------------------------------------------------------*/
7943 /* shiftR1Left2Result - shift right one byte from left to result */
7944 /*-----------------------------------------------------------------*/
7946 shiftR1Left2Result (operand * left, int offl,
7947 operand * result, int offr,
7948 int shCount, int sign)
7950 MOVA (aopGet (left, offl, FALSE, FALSE));
7951 /* shift right accumulator */
7956 aopPut (result, "a", offr);
7959 /*-----------------------------------------------------------------*/
7960 /* shiftL1Left2Result - shift left one byte from left to result */
7961 /*-----------------------------------------------------------------*/
7963 shiftL1Left2Result (operand * left, int offl,
7964 operand * result, int offr, int shCount)
7967 l = aopGet (left, offl, FALSE, FALSE);
7969 /* shift left accumulator */
7971 aopPut (result, "a", offr);
7974 /*-----------------------------------------------------------------*/
7975 /* movLeft2Result - move byte from left to result */
7976 /*-----------------------------------------------------------------*/
7978 movLeft2Result (operand * left, int offl,
7979 operand * result, int offr, int sign)
7982 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7984 l = aopGet (left, offl, FALSE, FALSE);
7986 if (*l == '@' && (IS_AOP_PREG (result)))
7988 emitcode ("mov", "a,%s", l);
7989 aopPut (result, "a", offr);
7995 aopPut (result, l, offr);
7999 /* MSB sign in acc.7 ! */
8000 if (getDataSize (left) == offl + 1)
8003 aopPut (result, "a", offr);
8010 /*-----------------------------------------------------------------*/
8011 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8012 /*-----------------------------------------------------------------*/
8016 emitcode ("rrc", "a");
8017 emitcode ("xch", "a,%s", x);
8018 emitcode ("rrc", "a");
8019 emitcode ("xch", "a,%s", x);
8022 /*-----------------------------------------------------------------*/
8023 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8024 /*-----------------------------------------------------------------*/
8028 emitcode ("xch", "a,%s", x);
8029 emitcode ("rlc", "a");
8030 emitcode ("xch", "a,%s", x);
8031 emitcode ("rlc", "a");
8034 /*-----------------------------------------------------------------*/
8035 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8036 /*-----------------------------------------------------------------*/
8040 emitcode ("xch", "a,%s", x);
8041 emitcode ("add", "a,acc");
8042 emitcode ("xch", "a,%s", x);
8043 emitcode ("rlc", "a");
8046 /*-----------------------------------------------------------------*/
8047 /* AccAXLsh - left shift a:x by known count (0..7) */
8048 /*-----------------------------------------------------------------*/
8050 AccAXLsh (char *x, int shCount)
8065 case 5: // AAAAABBB:CCCCCDDD
8067 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8069 emitcode ("anl", "a,#0x%02x",
8070 SLMask[shCount]); // BBB00000:CCCCCDDD
8072 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8074 AccRol (shCount); // DDDCCCCC:BBB00000
8076 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8078 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8080 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8082 emitcode ("anl", "a,#0x%02x",
8083 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8085 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8087 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8090 case 6: // AAAAAABB:CCCCCCDD
8091 emitcode ("anl", "a,#0x%02x",
8092 SRMask[shCount]); // 000000BB:CCCCCCDD
8093 emitcode ("mov", "c,acc.0"); // c = B
8094 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8096 AccAXRrl1 (x); // BCCCCCCD:D000000B
8097 AccAXRrl1 (x); // BBCCCCCC:DD000000
8099 emitcode("rrc","a");
8100 emitcode("xch","a,%s", x);
8101 emitcode("rrc","a");
8102 emitcode("mov","c,acc.0"); //<< get correct bit
8103 emitcode("xch","a,%s", x);
8105 emitcode("rrc","a");
8106 emitcode("xch","a,%s", x);
8107 emitcode("rrc","a");
8108 emitcode("xch","a,%s", x);
8111 case 7: // a:x <<= 7
8113 emitcode ("anl", "a,#0x%02x",
8114 SRMask[shCount]); // 0000000B:CCCCCCCD
8116 emitcode ("mov", "c,acc.0"); // c = B
8118 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8120 AccAXRrl1 (x); // BCCCCCCC:D0000000
8128 /*-----------------------------------------------------------------*/
8129 /* AccAXRsh - right shift a:x known count (0..7) */
8130 /*-----------------------------------------------------------------*/
8132 AccAXRsh (char *x, int shCount)
8140 AccAXRrl1 (x); // 0->a:x
8145 AccAXRrl1 (x); // 0->a:x
8148 AccAXRrl1 (x); // 0->a:x
8153 case 5: // AAAAABBB:CCCCCDDD = a:x
8155 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8157 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8159 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8161 emitcode ("anl", "a,#0x%02x",
8162 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8164 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8166 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8168 emitcode ("anl", "a,#0x%02x",
8169 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8171 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8173 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8175 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8178 case 6: // AABBBBBB:CCDDDDDD
8180 emitcode ("mov", "c,acc.7");
8181 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8183 emitcode ("mov", "c,acc.7");
8184 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8186 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8188 emitcode ("anl", "a,#0x%02x",
8189 SRMask[shCount]); // 000000AA:BBBBBBCC
8192 case 7: // ABBBBBBB:CDDDDDDD
8194 emitcode ("mov", "c,acc.7"); // c = A
8196 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8198 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8200 emitcode ("anl", "a,#0x%02x",
8201 SRMask[shCount]); // 0000000A:BBBBBBBC
8209 /*-----------------------------------------------------------------*/
8210 /* AccAXRshS - right shift signed a:x known count (0..7) */
8211 /*-----------------------------------------------------------------*/
8213 AccAXRshS (char *x, int shCount)
8221 emitcode ("mov", "c,acc.7");
8222 AccAXRrl1 (x); // s->a:x
8226 emitcode ("mov", "c,acc.7");
8227 AccAXRrl1 (x); // s->a:x
8229 emitcode ("mov", "c,acc.7");
8230 AccAXRrl1 (x); // s->a:x
8235 case 5: // AAAAABBB:CCCCCDDD = a:x
8237 tlbl = newiTempLabel (NULL);
8238 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8240 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8242 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8244 emitcode ("anl", "a,#0x%02x",
8245 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8247 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8249 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8251 emitcode ("anl", "a,#0x%02x",
8252 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8254 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8256 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8258 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8260 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8261 emitcode ("orl", "a,#0x%02x",
8262 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8265 break; // SSSSAAAA:BBBCCCCC
8267 case 6: // AABBBBBB:CCDDDDDD
8269 tlbl = newiTempLabel (NULL);
8270 emitcode ("mov", "c,acc.7");
8271 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8273 emitcode ("mov", "c,acc.7");
8274 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8276 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8278 emitcode ("anl", "a,#0x%02x",
8279 SRMask[shCount]); // 000000AA:BBBBBBCC
8281 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8282 emitcode ("orl", "a,#0x%02x",
8283 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8287 case 7: // ABBBBBBB:CDDDDDDD
8289 tlbl = newiTempLabel (NULL);
8290 emitcode ("mov", "c,acc.7"); // c = A
8292 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8294 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8296 emitcode ("anl", "a,#0x%02x",
8297 SRMask[shCount]); // 0000000A:BBBBBBBC
8299 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8300 emitcode ("orl", "a,#0x%02x",
8301 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8310 /*-----------------------------------------------------------------*/
8311 /* shiftL2Left2Result - shift left two bytes from left to result */
8312 /*-----------------------------------------------------------------*/
8314 shiftL2Left2Result (operand * left, int offl,
8315 operand * result, int offr, int shCount)
8318 bool pushedB = FALSE;
8321 if (sameRegs (AOP (result), AOP (left)) &&
8322 ((offl + MSB16) == offr))
8324 /* don't crash result[offr] */
8325 MOVA (aopGet (left, offl, FALSE, FALSE));
8326 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8327 x = aopGet (result, offr, FALSE, FALSE);
8329 else if (aopGetUsesAcc (result, offr))
8331 movLeft2Result (left, offl, result, offr, 0);
8334 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8335 MOVA (aopGet (result, offr, FALSE, FALSE));
8336 emitcode ("xch", "a,b");
8341 movLeft2Result (left, offl, result, offr, 0);
8342 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8343 x = aopGet (result, offr, FALSE, FALSE);
8345 /* ax << shCount (x = lsb(result)) */
8346 AccAXLsh (x, shCount);
8349 emitcode ("xch", "a,b");
8350 aopPut (result, "a", offr);
8351 aopPut (result, "b", offr + MSB16);
8356 aopPut (result, "a", offr + MSB16);
8361 /*-----------------------------------------------------------------*/
8362 /* shiftR2Left2Result - shift right two bytes from left to result */
8363 /*-----------------------------------------------------------------*/
8365 shiftR2Left2Result (operand * left, int offl,
8366 operand * result, int offr,
8367 int shCount, int sign)
8370 bool pushedB = FALSE;
8373 if (sameRegs (AOP (result), AOP (left)) &&
8374 ((offl + MSB16) == offr))
8376 /* don't crash result[offr] */
8377 MOVA (aopGet (left, offl, FALSE, FALSE));
8378 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8379 x = aopGet (result, offr, FALSE, FALSE);
8381 else if (aopGetUsesAcc (result, offr))
8383 movLeft2Result (left, offl, result, offr, 0);
8386 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8387 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8392 movLeft2Result (left, offl, result, offr, 0);
8393 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8394 x = aopGet (result, offr, FALSE, FALSE);
8396 /* a:x >> shCount (x = lsb(result)) */
8398 AccAXRshS (x, shCount);
8400 AccAXRsh (x, shCount);
8403 emitcode ("xch", "a,b");
8404 aopPut (result, "a", offr);
8405 emitcode ("xch", "a,b");
8408 if (getDataSize (result) > 1)
8409 aopPut (result, "a", offr + MSB16);
8412 /*-----------------------------------------------------------------*/
8413 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8414 /*-----------------------------------------------------------------*/
8416 shiftLLeftOrResult (operand * left, int offl,
8417 operand * result, int offr, int shCount)
8419 MOVA (aopGet (left, offl, FALSE, FALSE));
8420 /* shift left accumulator */
8422 /* or with result */
8423 if (aopGetUsesAcc (result, offr))
8425 emitcode ("xch", "a,b");
8426 MOVA (aopGet (result, offr, FALSE, FALSE));
8427 emitcode ("orl", "a,b");
8431 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8433 /* back to result */
8434 aopPut (result, "a", offr);
8437 /*-----------------------------------------------------------------*/
8438 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8439 /*-----------------------------------------------------------------*/
8441 shiftRLeftOrResult (operand * left, int offl,
8442 operand * result, int offr, int shCount)
8444 MOVA (aopGet (left, offl, FALSE, FALSE));
8445 /* shift right accumulator */
8447 /* or with result */
8448 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8449 /* back to result */
8450 aopPut (result, "a", offr);
8453 /*-----------------------------------------------------------------*/
8454 /* genlshOne - left shift a one byte quantity by known count */
8455 /*-----------------------------------------------------------------*/
8457 genlshOne (operand * result, operand * left, int shCount)
8459 D (emitcode (";", "genlshOne"));
8461 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8464 /*-----------------------------------------------------------------*/
8465 /* genlshTwo - left shift two bytes by known amount != 0 */
8466 /*-----------------------------------------------------------------*/
8468 genlshTwo (operand * result, operand * left, int shCount)
8472 D (emitcode (";", "genlshTwo"));
8474 size = getDataSize (result);
8476 /* if shCount >= 8 */
8484 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8486 movLeft2Result (left, LSB, result, MSB16, 0);
8488 aopPut (result, zero, LSB);
8491 /* 1 <= shCount <= 7 */
8495 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8497 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8501 /*-----------------------------------------------------------------*/
8502 /* shiftLLong - shift left one long from left to result */
8503 /* offl = LSB or MSB16 */
8504 /*-----------------------------------------------------------------*/
8506 shiftLLong (operand * left, operand * result, int offr)
8509 int size = AOP_SIZE (result);
8511 if (size >= LSB + offr)
8513 l = aopGet (left, LSB, FALSE, FALSE);
8515 emitcode ("add", "a,acc");
8516 if (sameRegs (AOP (left), AOP (result)) &&
8517 size >= MSB16 + offr && offr != LSB)
8518 emitcode ("xch", "a,%s",
8519 aopGet (left, LSB + offr, FALSE, FALSE));
8521 aopPut (result, "a", LSB + offr);
8524 if (size >= MSB16 + offr)
8526 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8528 l = aopGet (left, MSB16, FALSE, FALSE);
8531 emitcode ("rlc", "a");
8532 if (sameRegs (AOP (left), AOP (result)) &&
8533 size >= MSB24 + offr && offr != LSB)
8534 emitcode ("xch", "a,%s",
8535 aopGet (left, MSB16 + offr, FALSE, FALSE));
8537 aopPut (result, "a", MSB16 + offr);
8540 if (size >= MSB24 + offr)
8542 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8544 l = aopGet (left, MSB24, FALSE, FALSE);
8547 emitcode ("rlc", "a");
8548 if (sameRegs (AOP (left), AOP (result)) &&
8549 size >= MSB32 + offr && offr != LSB)
8550 emitcode ("xch", "a,%s",
8551 aopGet (left, MSB24 + offr, FALSE, FALSE));
8553 aopPut (result, "a", MSB24 + offr);
8556 if (size > MSB32 + offr)
8558 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8560 l = aopGet (left, MSB32, FALSE, FALSE);
8563 emitcode ("rlc", "a");
8564 aopPut (result, "a", MSB32 + offr);
8567 aopPut (result, zero, LSB);
8570 /*-----------------------------------------------------------------*/
8571 /* genlshFour - shift four byte by a known amount != 0 */
8572 /*-----------------------------------------------------------------*/
8574 genlshFour (operand * result, operand * left, int shCount)
8578 D (emitcode (";", "genlshFour"));
8580 size = AOP_SIZE (result);
8582 /* if shifting more that 3 bytes */
8587 /* lowest order of left goes to the highest
8588 order of the destination */
8589 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8591 movLeft2Result (left, LSB, result, MSB32, 0);
8592 aopPut (result, zero, LSB);
8593 aopPut (result, zero, MSB16);
8594 aopPut (result, zero, MSB24);
8598 /* more than two bytes */
8599 else if (shCount >= 16)
8601 /* lower order two bytes goes to higher order two bytes */
8603 /* if some more remaining */
8605 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8608 movLeft2Result (left, MSB16, result, MSB32, 0);
8609 movLeft2Result (left, LSB, result, MSB24, 0);
8611 aopPut (result, zero, MSB16);
8612 aopPut (result, zero, LSB);
8616 /* if more than 1 byte */
8617 else if (shCount >= 8)
8619 /* lower order three bytes goes to higher order three bytes */
8624 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8626 movLeft2Result (left, LSB, result, MSB16, 0);
8632 movLeft2Result (left, MSB24, result, MSB32, 0);
8633 movLeft2Result (left, MSB16, result, MSB24, 0);
8634 movLeft2Result (left, LSB, result, MSB16, 0);
8635 aopPut (result, zero, LSB);
8637 else if (shCount == 1)
8638 shiftLLong (left, result, MSB16);
8641 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8642 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8643 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8644 aopPut (result, zero, LSB);
8649 /* 1 <= shCount <= 7 */
8650 else if (shCount <= 2)
8652 shiftLLong (left, result, LSB);
8654 shiftLLong (result, result, LSB);
8656 /* 3 <= shCount <= 7, optimize */
8659 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8660 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8661 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8665 /*-----------------------------------------------------------------*/
8666 /* genLeftShiftLiteral - left shifting by known count */
8667 /*-----------------------------------------------------------------*/
8669 genLeftShiftLiteral (operand * left,
8674 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8677 D (emitcode (";", "genLeftShiftLiteral"));
8679 freeAsmop (right, NULL, ic, TRUE);
8681 aopOp (left, ic, FALSE);
8682 aopOp (result, ic, FALSE);
8684 size = getSize (operandType (result));
8687 emitcode ("; shift left ", "result %d, left %d", size,
8691 /* I suppose that the left size >= result size */
8696 movLeft2Result (left, size, result, size, 0);
8699 else if (shCount >= (size * 8))
8703 aopPut (result, zero, size);
8711 genlshOne (result, left, shCount);
8715 genlshTwo (result, left, shCount);
8719 genlshFour (result, left, shCount);
8722 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8723 "*** ack! mystery literal shift!\n");
8727 freeAsmop (result, NULL, ic, TRUE);
8728 freeAsmop (left, NULL, ic, TRUE);
8731 /*-----------------------------------------------------------------*/
8732 /* genLeftShift - generates code for left shifting */
8733 /*-----------------------------------------------------------------*/
8735 genLeftShift (iCode * ic)
8737 operand *left, *right, *result;
8740 symbol *tlbl, *tlbl1;
8743 D (emitcode (";", "genLeftShift"));
8745 right = IC_RIGHT (ic);
8746 left = IC_LEFT (ic);
8747 result = IC_RESULT (ic);
8749 aopOp (right, ic, FALSE);
8751 /* if the shift count is known then do it
8752 as efficiently as possible */
8753 if (AOP_TYPE (right) == AOP_LIT)
8755 genLeftShiftLiteral (left, right, result, ic);
8759 /* shift count is unknown then we have to form
8760 a loop get the loop count in B : Note: we take
8761 only the lower order byte since shifting
8762 more that 32 bits make no sense anyway, ( the
8763 largest size of an object can be only 32 bits ) */
8766 MOVB (aopGet (right, 0, FALSE, FALSE));
8767 emitcode ("inc", "b");
8768 freeAsmop (right, NULL, ic, TRUE);
8769 aopOp (left, ic, FALSE);
8770 aopOp (result, ic, FALSE);
8772 /* now move the left to the result if they are not the same */
8773 if (!sameRegs (AOP (left), AOP (result)) &&
8774 AOP_SIZE (result) > 1)
8777 size = AOP_SIZE (result);
8781 l = aopGet (left, offset, FALSE, TRUE);
8782 if (*l == '@' && (IS_AOP_PREG (result)))
8785 emitcode ("mov", "a,%s", l);
8786 aopPut (result, "a", offset);
8789 aopPut (result, l, offset);
8794 tlbl = newiTempLabel (NULL);
8795 size = AOP_SIZE (result);
8797 tlbl1 = newiTempLabel (NULL);
8799 /* if it is only one byte then */
8802 symbol *tlbl1 = newiTempLabel (NULL);
8804 l = aopGet (left, 0, FALSE, FALSE);
8806 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8808 emitcode ("add", "a,acc");
8810 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8812 aopPut (result, "a", 0);
8816 reAdjustPreg (AOP (result));
8818 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8820 l = aopGet (result, offset, FALSE, FALSE);
8822 emitcode ("add", "a,acc");
8823 aopPut (result, "a", offset++);
8826 l = aopGet (result, offset, FALSE, FALSE);
8828 emitcode ("rlc", "a");
8829 aopPut (result, "a", offset++);
8831 reAdjustPreg (AOP (result));
8834 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8837 freeAsmop (result, NULL, ic, TRUE);
8838 freeAsmop (left, NULL, ic, TRUE);
8841 /*-----------------------------------------------------------------*/
8842 /* genrshOne - right shift a one byte quantity by known count */
8843 /*-----------------------------------------------------------------*/
8845 genrshOne (operand * result, operand * left,
8846 int shCount, int sign)
8848 D (emitcode (";", "genrshOne"));
8850 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8853 /*-----------------------------------------------------------------*/
8854 /* genrshTwo - right shift two bytes by known amount != 0 */
8855 /*-----------------------------------------------------------------*/
8857 genrshTwo (operand * result, operand * left,
8858 int shCount, int sign)
8860 D (emitcode (";", "genrshTwo"));
8862 /* if shCount >= 8 */
8867 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8869 movLeft2Result (left, MSB16, result, LSB, sign);
8870 addSign (result, MSB16, sign);
8873 /* 1 <= shCount <= 7 */
8875 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8878 /*-----------------------------------------------------------------*/
8879 /* shiftRLong - shift right one long from left to result */
8880 /* offl = LSB or MSB16 */
8881 /*-----------------------------------------------------------------*/
8883 shiftRLong (operand * left, int offl,
8884 operand * result, int sign)
8886 bool useSameRegs = regsInCommon (left, result);
8888 if (useSameRegs && offl>1)
8890 // we are in big trouble, but this shouldn't happen
8891 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8894 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8901 emitcode ("rlc", "a");
8902 emitcode ("subb", "a,acc");
8903 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8905 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8909 aopPut (result, "a", MSB32);
8910 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8915 aopPut (result, zero, MSB32);
8921 emitcode ("clr", "c");
8925 emitcode ("mov", "c,acc.7");
8928 emitcode ("rrc", "a");
8930 if (useSameRegs && offl==MSB16 &&
8931 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8933 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8937 aopPut (result, "a", MSB32-offl);
8938 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8941 emitcode ("rrc", "a");
8942 if (useSameRegs && offl==1 &&
8943 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8945 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8949 aopPut (result, "a", MSB24-offl);
8950 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8952 emitcode ("rrc", "a");
8955 aopPut (result, "a", MSB16 - offl);
8960 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8962 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8966 aopPut (result, "a", MSB16 - offl);
8967 MOVA (aopGet (left, LSB, FALSE, FALSE));
8969 emitcode ("rrc", "a");
8970 aopPut (result, "a", LSB);
8974 /*-----------------------------------------------------------------*/
8975 /* genrshFour - shift four byte by a known amount != 0 */
8976 /*-----------------------------------------------------------------*/
8978 genrshFour (operand * result, operand * left,
8979 int shCount, int sign)
8981 D (emitcode (";", "genrshFour"));
8983 /* if shifting more that 3 bytes */
8988 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8990 movLeft2Result (left, MSB32, result, LSB, sign);
8991 addSign (result, MSB16, sign);
8993 else if (shCount >= 16)
8997 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9000 movLeft2Result (left, MSB24, result, LSB, 0);
9001 movLeft2Result (left, MSB32, result, MSB16, sign);
9003 addSign (result, MSB24, sign);
9005 else if (shCount >= 8)
9010 shiftRLong (left, MSB16, result, sign);
9012 else if (shCount == 0)
9014 movLeft2Result (left, MSB16, result, LSB, 0);
9015 movLeft2Result (left, MSB24, result, MSB16, 0);
9016 movLeft2Result (left, MSB32, result, MSB24, sign);
9017 addSign (result, MSB32, sign);
9021 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9022 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9023 /* the last shift is signed */
9024 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9025 addSign (result, MSB32, sign);
9030 /* 1 <= shCount <= 7 */
9033 shiftRLong (left, LSB, result, sign);
9035 shiftRLong (result, LSB, result, sign);
9039 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9040 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9041 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9046 /*-----------------------------------------------------------------*/
9047 /* genRightShiftLiteral - right shifting by known count */
9048 /*-----------------------------------------------------------------*/
9050 genRightShiftLiteral (operand * left,
9056 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9059 D (emitcode (";", "genRightShiftLiteral"));
9061 freeAsmop (right, NULL, ic, TRUE);
9063 aopOp (left, ic, FALSE);
9064 aopOp (result, ic, FALSE);
9067 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9071 size = getDataSize (left);
9072 /* test the LEFT size !!! */
9074 /* I suppose that the left size >= result size */
9077 size = getDataSize (result);
9079 movLeft2Result (left, size, result, size, 0);
9082 else if (shCount >= (size * 8))
9086 /* get sign in acc.7 */
9087 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9089 addSign (result, LSB, sign);
9096 genrshOne (result, left, shCount, sign);
9100 genrshTwo (result, left, shCount, sign);
9104 genrshFour (result, left, shCount, sign);
9110 freeAsmop (result, NULL, ic, TRUE);
9111 freeAsmop (left, NULL, ic, TRUE);
9114 /*-----------------------------------------------------------------*/
9115 /* genSignedRightShift - right shift of signed number */
9116 /*-----------------------------------------------------------------*/
9118 genSignedRightShift (iCode * ic)
9120 operand *right, *left, *result;
9123 symbol *tlbl, *tlbl1;
9126 D (emitcode (";", "genSignedRightShift"));
9128 /* we do it the hard way put the shift count in b
9129 and loop thru preserving the sign */
9131 right = IC_RIGHT (ic);
9132 left = IC_LEFT (ic);
9133 result = IC_RESULT (ic);
9135 aopOp (right, ic, FALSE);
9138 if (AOP_TYPE (right) == AOP_LIT)
9140 genRightShiftLiteral (left, right, result, ic, 1);
9143 /* shift count is unknown then we have to form
9144 a loop get the loop count in B : Note: we take
9145 only the lower order byte since shifting
9146 more that 32 bits make no sense anyway, ( the
9147 largest size of an object can be only 32 bits ) */
9150 MOVB (aopGet (right, 0, FALSE, FALSE));
9151 emitcode ("inc", "b");
9152 freeAsmop (right, NULL, ic, TRUE);
9153 aopOp (left, ic, FALSE);
9154 aopOp (result, ic, FALSE);
9156 /* now move the left to the result if they are not the
9158 if (!sameRegs (AOP (left), AOP (result)) &&
9159 AOP_SIZE (result) > 1)
9162 size = AOP_SIZE (result);
9166 l = aopGet (left, offset, FALSE, TRUE);
9167 if (*l == '@' && IS_AOP_PREG (result))
9170 emitcode ("mov", "a,%s", l);
9171 aopPut (result, "a", offset);
9174 aopPut (result, l, offset);
9179 /* mov the highest order bit to OVR */
9180 tlbl = newiTempLabel (NULL);
9181 tlbl1 = newiTempLabel (NULL);
9183 size = AOP_SIZE (result);
9185 MOVA (aopGet (left, offset, FALSE, FALSE));
9186 emitcode ("rlc", "a");
9187 emitcode ("mov", "ov,c");
9188 /* if it is only one byte then */
9191 l = aopGet (left, 0, FALSE, FALSE);
9193 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9195 emitcode ("mov", "c,ov");
9196 emitcode ("rrc", "a");
9198 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9200 aopPut (result, "a", 0);
9204 reAdjustPreg (AOP (result));
9205 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9207 emitcode ("mov", "c,ov");
9210 l = aopGet (result, offset, FALSE, FALSE);
9212 emitcode ("rrc", "a");
9213 aopPut (result, "a", offset--);
9215 reAdjustPreg (AOP (result));
9217 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9221 freeAsmop (result, NULL, ic, TRUE);
9222 freeAsmop (left, NULL, ic, TRUE);
9225 /*-----------------------------------------------------------------*/
9226 /* genRightShift - generate code for right shifting */
9227 /*-----------------------------------------------------------------*/
9229 genRightShift (iCode * ic)
9231 operand *right, *left, *result;
9235 symbol *tlbl, *tlbl1;
9238 D (emitcode (";", "genRightShift"));
9240 /* if signed then we do it the hard way preserve the
9241 sign bit moving it inwards */
9242 letype = getSpec (operandType (IC_LEFT (ic)));
9244 if (!SPEC_USIGN (letype))
9246 genSignedRightShift (ic);
9250 /* signed & unsigned types are treated the same : i.e. the
9251 signed is NOT propagated inwards : quoting from the
9252 ANSI - standard : "for E1 >> E2, is equivalent to division
9253 by 2**E2 if unsigned or if it has a non-negative value,
9254 otherwise the result is implementation defined ", MY definition
9255 is that the sign does not get propagated */
9257 right = IC_RIGHT (ic);
9258 left = IC_LEFT (ic);
9259 result = IC_RESULT (ic);
9261 aopOp (right, ic, FALSE);
9263 /* if the shift count is known then do it
9264 as efficiently as possible */
9265 if (AOP_TYPE (right) == AOP_LIT)
9267 genRightShiftLiteral (left, right, result, ic, 0);
9271 /* shift count is unknown then we have to form
9272 a loop get the loop count in B : Note: we take
9273 only the lower order byte since shifting
9274 more that 32 bits make no sense anyway, ( the
9275 largest size of an object can be only 32 bits ) */
9278 MOVB (aopGet (right, 0, FALSE, FALSE));
9279 emitcode ("inc", "b");
9280 freeAsmop (right, NULL, ic, TRUE);
9281 aopOp (left, ic, FALSE);
9282 aopOp (result, ic, FALSE);
9284 /* now move the left to the result if they are not the
9286 if (!sameRegs (AOP (left), AOP (result)) &&
9287 AOP_SIZE (result) > 1)
9289 size = AOP_SIZE (result);
9293 l = aopGet (left, offset, FALSE, TRUE);
9294 if (*l == '@' && IS_AOP_PREG (result))
9297 emitcode ("mov", "a,%s", l);
9298 aopPut (result, "a", offset);
9301 aopPut (result, l, offset);
9306 tlbl = newiTempLabel (NULL);
9307 tlbl1 = newiTempLabel (NULL);
9308 size = AOP_SIZE (result);
9311 /* if it is only one byte then */
9314 l = aopGet (left, 0, FALSE, FALSE);
9316 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9319 emitcode ("rrc", "a");
9321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9323 aopPut (result, "a", 0);
9327 reAdjustPreg (AOP (result));
9328 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9333 l = aopGet (result, offset, FALSE, FALSE);
9335 emitcode ("rrc", "a");
9336 aopPut (result, "a", offset--);
9338 reAdjustPreg (AOP (result));
9341 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9345 freeAsmop (result, NULL, ic, TRUE);
9346 freeAsmop (left, NULL, ic, TRUE);
9349 /*-----------------------------------------------------------------*/
9350 /* emitPtrByteGet - emits code to get a byte into A through a */
9351 /* pointer register (R0, R1, or DPTR). The */
9352 /* original value of A can be preserved in B. */
9353 /*-----------------------------------------------------------------*/
9355 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9362 emitcode ("mov", "b,a");
9363 emitcode ("mov", "a,@%s", rname);
9368 emitcode ("mov", "b,a");
9369 emitcode ("movx", "a,@%s", rname);
9374 emitcode ("mov", "b,a");
9375 emitcode ("movx", "a,@dptr");
9380 emitcode ("mov", "b,a");
9381 emitcode ("clr", "a");
9382 emitcode ("movc", "a,@a+dptr");
9388 emitcode ("push", "b");
9389 emitcode ("push", "acc");
9391 emitcode ("lcall", "__gptrget");
9393 emitcode ("pop", "b");
9398 /*-----------------------------------------------------------------*/
9399 /* emitPtrByteSet - emits code to set a byte from src through a */
9400 /* pointer register (R0, R1, or DPTR). */
9401 /*-----------------------------------------------------------------*/
9403 emitPtrByteSet (char *rname, int p_type, char *src)
9412 emitcode ("mov", "@%s,a", rname);
9415 emitcode ("mov", "@%s,%s", rname, src);
9420 emitcode ("movx", "@%s,a", rname);
9425 emitcode ("movx", "@dptr,a");
9430 emitcode ("lcall", "__gptrput");
9435 /*-----------------------------------------------------------------*/
9436 /* genUnpackBits - generates code for unpacking bits */
9437 /*-----------------------------------------------------------------*/
9439 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9441 int offset = 0; /* result byte offset */
9442 int rsize; /* result size */
9443 int rlen = 0; /* remaining bitfield length */
9444 sym_link *etype; /* bitfield type information */
9445 int blen; /* bitfield length */
9446 int bstr; /* bitfield starting bit within byte */
9449 D(emitcode ("; genUnpackBits",""));
9451 etype = getSpec (operandType (result));
9452 rsize = getSize (operandType (result));
9453 blen = SPEC_BLEN (etype);
9454 bstr = SPEC_BSTR (etype);
9456 if (ifx && blen <= 8)
9458 emitPtrByteGet (rname, ptype, FALSE);
9461 SNPRINTF (buffer, sizeof(buffer),
9463 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9468 emitcode ("anl", "a,#0x%02x",
9469 (((unsigned char) -1) >> (8 - blen)) << bstr);
9470 genIfxJump (ifx, "a", NULL, NULL, NULL);
9476 /* If the bitfield length is less than a byte */
9479 emitPtrByteGet (rname, ptype, FALSE);
9481 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9482 if (!SPEC_USIGN (etype))
9484 /* signed bitfield */
9485 symbol *tlbl = newiTempLabel (NULL);
9487 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9488 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9491 aopPut (result, "a", offset++);
9495 /* Bit field did not fit in a byte. Copy all
9496 but the partial byte at the end. */
9497 for (rlen=blen;rlen>=8;rlen-=8)
9499 emitPtrByteGet (rname, ptype, FALSE);
9500 aopPut (result, "a", offset++);
9502 emitcode ("inc", "%s", rname);
9505 /* Handle the partial byte at the end */
9508 emitPtrByteGet (rname, ptype, FALSE);
9509 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9510 if (!SPEC_USIGN (etype))
9512 /* signed bitfield */
9513 symbol *tlbl = newiTempLabel (NULL);
9515 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9516 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9519 aopPut (result, "a", offset++);
9527 if (SPEC_USIGN (etype))
9531 /* signed bitfield: sign extension with 0x00 or 0xff */
9532 emitcode ("rlc", "a");
9533 emitcode ("subb", "a,acc");
9539 aopPut (result, source, offset++);
9544 /*-----------------------------------------------------------------*/
9545 /* genDataPointerGet - generates code when ptr offset is known */
9546 /*-----------------------------------------------------------------*/
9548 genDataPointerGet (operand * left,
9554 int size, offset = 0;
9556 D (emitcode (";", "genDataPointerGet"));
9558 aopOp (result, ic, TRUE);
9560 /* get the string representation of the name */
9561 l = aopGet (left, 0, FALSE, TRUE);
9562 size = AOP_SIZE (result);
9567 SNPRINTF (buffer, sizeof(buffer),
9568 "(%s + %d)", l + 1, offset);
9572 SNPRINTF (buffer, sizeof(buffer),
9575 aopPut (result, buffer, offset++);
9578 freeAsmop (result, NULL, ic, TRUE);
9579 freeAsmop (left, NULL, ic, TRUE);
9582 /*-----------------------------------------------------------------*/
9583 /* genNearPointerGet - emitcode for near pointer fetch */
9584 /*-----------------------------------------------------------------*/
9586 genNearPointerGet (operand * left,
9595 sym_link *rtype, *retype;
9596 sym_link *ltype = operandType (left);
9599 D (emitcode (";", "genNearPointerGet"));
9601 rtype = operandType (result);
9602 retype = getSpec (rtype);
9604 aopOp (left, ic, FALSE);
9606 /* if left is rematerialisable and
9607 result is not bitfield variable type and
9608 the left is pointer to data space i.e
9609 lower 128 bytes of space */
9610 if (AOP_TYPE (left) == AOP_IMMD &&
9611 !IS_BITFIELD (retype) &&
9612 DCL_TYPE (ltype) == POINTER)
9614 genDataPointerGet (left, result, ic);
9618 /* if the value is already in a pointer register
9619 then don't need anything more */
9620 if (!AOP_INPREG (AOP (left)))
9622 if (IS_AOP_PREG (left))
9624 // Aha, it is a pointer, just in disguise.
9625 rname = aopGet (left, 0, FALSE, FALSE);
9628 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9629 __FILE__, __LINE__);
9634 emitcode ("mov", "a%s,%s", rname + 1, rname);
9635 rname++; // skip the '@'.
9640 /* otherwise get a free pointer register */
9642 preg = getFreePtr (ic, &aop, FALSE);
9643 emitcode ("mov", "%s,%s",
9645 aopGet (left, 0, FALSE, TRUE));
9650 rname = aopGet (left, 0, FALSE, FALSE);
9652 //aopOp (result, ic, FALSE);
9653 aopOp (result, ic, result?TRUE:FALSE);
9655 /* if bitfield then unpack the bits */
9656 if (IS_BITFIELD (retype))
9657 genUnpackBits (result, rname, POINTER, ifx);
9660 /* we have can just get the values */
9661 int size = AOP_SIZE (result);
9666 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9669 emitcode ("mov", "a,@%s", rname);
9671 aopPut (result, "a", offset);
9675 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9676 aopPut (result, buffer, offset);
9680 emitcode ("inc", "%s", rname);
9684 /* now some housekeeping stuff */
9685 if (aop) /* we had to allocate for this iCode */
9687 if (pi) { /* post increment present */
9688 aopPut (left, rname, 0);
9690 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9694 /* we did not allocate which means left
9695 already in a pointer register, then
9696 if size > 0 && this could be used again
9697 we have to point it back to where it
9699 if ((AOP_SIZE (result) > 1 &&
9700 !OP_SYMBOL (left)->remat &&
9701 (OP_SYMBOL (left)->liveTo > ic->seq ||
9705 int size = AOP_SIZE (result) - 1;
9707 emitcode ("dec", "%s", rname);
9711 if (ifx && !ifx->generated)
9713 genIfxJump (ifx, "a", left, NULL, result);
9717 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9718 freeAsmop (left, NULL, ic, TRUE);
9719 if (pi) pi->generated = 1;
9722 /*-----------------------------------------------------------------*/
9723 /* genPagedPointerGet - emitcode for paged pointer fetch */
9724 /*-----------------------------------------------------------------*/
9726 genPagedPointerGet (operand * left,
9735 sym_link *rtype, *retype;
9737 D (emitcode (";", "genPagedPointerGet"));
9739 rtype = operandType (result);
9740 retype = getSpec (rtype);
9742 aopOp (left, ic, FALSE);
9744 /* if the value is already in a pointer register
9745 then don't need anything more */
9746 if (!AOP_INPREG (AOP (left)))
9748 /* otherwise get a free pointer register */
9750 preg = getFreePtr (ic, &aop, FALSE);
9751 emitcode ("mov", "%s,%s",
9753 aopGet (left, 0, FALSE, TRUE));
9757 rname = aopGet (left, 0, FALSE, FALSE);
9759 aopOp (result, ic, FALSE);
9761 /* if bitfield then unpack the bits */
9762 if (IS_BITFIELD (retype))
9763 genUnpackBits (result, rname, PPOINTER, ifx);
9766 /* we have can just get the values */
9767 int size = AOP_SIZE (result);
9773 emitcode ("movx", "a,@%s", rname);
9775 aopPut (result, "a", offset);
9780 emitcode ("inc", "%s", rname);
9784 /* now some housekeeping stuff */
9785 if (aop) /* we had to allocate for this iCode */
9788 aopPut (left, rname, 0);
9789 freeAsmop (NULL, aop, ic, TRUE);
9793 /* we did not allocate which means left
9794 already in a pointer register, then
9795 if size > 0 && this could be used again
9796 we have to point it back to where it
9798 if ((AOP_SIZE (result) > 1 &&
9799 !OP_SYMBOL (left)->remat &&
9800 (OP_SYMBOL (left)->liveTo > ic->seq ||
9804 int size = AOP_SIZE (result) - 1;
9806 emitcode ("dec", "%s", rname);
9810 if (ifx && !ifx->generated)
9812 genIfxJump (ifx, "a", left, NULL, result);
9816 freeAsmop (result, NULL, ic, TRUE);
9817 freeAsmop (left, NULL, ic, TRUE);
9818 if (pi) pi->generated = 1;
9821 /*--------------------------------------------------------------------*/
9822 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9823 /*--------------------------------------------------------------------*/
9825 loadDptrFromOperand (operand *op, bool loadBToo)
9827 if (AOP_TYPE (op) != AOP_STR)
9829 /* if this is rematerializable */
9830 if (AOP_TYPE (op) == AOP_IMMD)
9832 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9835 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9836 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9839 wassertl(FALSE, "need pointerCode");
9840 emitcode ("", "; mov b,???");
9841 /* genPointerGet and genPointerSet originally did different
9842 ** things for this case. Both seem wrong.
9843 ** from genPointerGet:
9844 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9845 ** from genPointerSet:
9846 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9851 else if (AOP_TYPE (op) == AOP_DPTR)
9855 MOVA (aopGet (op, 0, FALSE, FALSE));
9856 emitcode ("push", "acc");
9857 MOVA (aopGet (op, 1, FALSE, FALSE));
9858 emitcode ("push", "acc");
9859 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9860 emitcode ("pop", "dph");
9861 emitcode ("pop", "dpl");
9865 MOVA (aopGet (op, 0, FALSE, FALSE));
9866 emitcode ("push", "acc");
9867 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9868 emitcode ("pop", "dpl");
9872 { /* we need to get it byte by byte */
9873 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9874 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9876 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9881 /*-----------------------------------------------------------------*/
9882 /* genFarPointerGet - get value from far space */
9883 /*-----------------------------------------------------------------*/
9885 genFarPointerGet (operand * left,
9886 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9889 sym_link *retype = getSpec (operandType (result));
9891 D (emitcode (";", "genFarPointerGet"));
9893 aopOp (left, ic, FALSE);
9894 loadDptrFromOperand (left, FALSE);
9896 /* so dptr now contains the address */
9897 aopOp (result, ic, FALSE);
9899 /* if bit then unpack */
9900 if (IS_BITFIELD (retype))
9901 genUnpackBits (result, "dptr", FPOINTER, ifx);
9904 size = AOP_SIZE (result);
9909 emitcode ("movx", "a,@dptr");
9911 aopPut (result, "a", offset++);
9913 emitcode ("inc", "dptr");
9917 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9919 aopPut (left, "dpl", 0);
9920 aopPut (left, "dph", 1);
9924 if (ifx && !ifx->generated)
9926 genIfxJump (ifx, "a", left, NULL, result);
9929 freeAsmop (result, NULL, ic, TRUE);
9930 freeAsmop (left, NULL, ic, TRUE);
9933 /*-----------------------------------------------------------------*/
9934 /* genCodePointerGet - get value from code space */
9935 /*-----------------------------------------------------------------*/
9937 genCodePointerGet (operand * left,
9938 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9941 sym_link *retype = getSpec (operandType (result));
9943 D (emitcode (";", "genCodePointerGet"));
9945 aopOp (left, ic, FALSE);
9946 loadDptrFromOperand (left, FALSE);
9948 /* so dptr now contains the address */
9949 aopOp (result, ic, FALSE);
9951 /* if bit then unpack */
9952 if (IS_BITFIELD (retype))
9953 genUnpackBits (result, "dptr", CPOINTER, ifx);
9956 size = AOP_SIZE (result);
9961 emitcode ("clr", "a");
9962 emitcode ("movc", "a,@a+dptr");
9964 aopPut (result, "a", offset++);
9966 emitcode ("inc", "dptr");
9970 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9972 aopPut (left, "dpl", 0);
9973 aopPut (left, "dph", 1);
9977 if (ifx && !ifx->generated)
9979 genIfxJump (ifx, "a", left, NULL, result);
9982 freeAsmop (result, NULL, ic, TRUE);
9983 freeAsmop (left, NULL, ic, TRUE);
9986 /*-----------------------------------------------------------------*/
9987 /* genGenPointerGet - get value from generic pointer space */
9988 /*-----------------------------------------------------------------*/
9990 genGenPointerGet (operand * left,
9991 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9994 sym_link *retype = getSpec (operandType (result));
9996 D (emitcode (";", "genGenPointerGet"));
9998 aopOp (left, ic, FALSE);
9999 loadDptrFromOperand (left, TRUE);
10001 /* so dptr now contains the address */
10002 aopOp (result, ic, FALSE);
10004 /* if bit then unpack */
10005 if (IS_BITFIELD (retype))
10007 genUnpackBits (result, "dptr", GPOINTER, ifx);
10011 size = AOP_SIZE (result);
10016 emitcode ("lcall", "__gptrget");
10018 aopPut (result, "a", offset++);
10020 emitcode ("inc", "dptr");
10024 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10026 aopPut (left, "dpl", 0);
10027 aopPut (left, "dph", 1);
10031 if (ifx && !ifx->generated)
10033 genIfxJump (ifx, "a", left, NULL, result);
10036 freeAsmop (result, NULL, ic, TRUE);
10037 freeAsmop (left, NULL, ic, TRUE);
10040 /*-----------------------------------------------------------------*/
10041 /* genPointerGet - generate code for pointer get */
10042 /*-----------------------------------------------------------------*/
10044 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10046 operand *left, *result;
10047 sym_link *type, *etype;
10050 D (emitcode (";", "genPointerGet"));
10052 left = IC_LEFT (ic);
10053 result = IC_RESULT (ic);
10055 if (getSize (operandType (result))>1)
10058 /* depending on the type of pointer we need to
10059 move it to the correct pointer register */
10060 type = operandType (left);
10061 etype = getSpec (type);
10062 /* if left is of type of pointer then it is simple */
10063 if (IS_PTR (type) && !IS_FUNC (type->next))
10064 p_type = DCL_TYPE (type);
10067 /* we have to go by the storage class */
10068 p_type = PTR_TYPE (SPEC_OCLS (etype));
10071 /* special case when cast remat */
10072 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10073 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10075 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10076 type = operandType (left);
10077 p_type = DCL_TYPE (type);
10079 /* now that we have the pointer type we assign
10080 the pointer values */
10086 genNearPointerGet (left, result, ic, pi, ifx);
10090 genPagedPointerGet (left, result, ic, pi, ifx);
10094 genFarPointerGet (left, result, ic, pi, ifx);
10098 genCodePointerGet (left, result, ic, pi, ifx);
10102 genGenPointerGet (left, result, ic, pi, ifx);
10108 /*-----------------------------------------------------------------*/
10109 /* genPackBits - generates code for packed bit storage */
10110 /*-----------------------------------------------------------------*/
10112 genPackBits (sym_link * etype,
10114 char *rname, int p_type)
10116 int offset = 0; /* source byte offset */
10117 int rlen = 0; /* remaining bitfield length */
10118 int blen; /* bitfield length */
10119 int bstr; /* bitfield starting bit within byte */
10120 int litval; /* source literal value (if AOP_LIT) */
10121 unsigned char mask; /* bitmask within current byte */
10123 D(emitcode ("; genPackBits",""));
10125 blen = SPEC_BLEN (etype);
10126 bstr = SPEC_BSTR (etype);
10128 /* If the bitfield length is less than a byte */
10131 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10132 (unsigned char) (0xFF >> (8 - bstr)));
10134 if (AOP_TYPE (right) == AOP_LIT)
10136 /* Case with a bitfield length <8 and literal source
10138 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10140 litval &= (~mask) & 0xff;
10141 emitPtrByteGet (rname, p_type, FALSE);
10142 if ((mask|litval)!=0xff)
10143 emitcode ("anl","a,#0x%02x", mask);
10145 emitcode ("orl","a,#0x%02x", litval);
10149 if ((blen==1) && (p_type!=GPOINTER))
10151 /* Case with a bitfield length == 1 and no generic pointer
10153 if (AOP_TYPE (right) == AOP_CRY)
10154 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10157 MOVA (aopGet (right, 0, FALSE, FALSE));
10158 emitcode ("rrc","a");
10160 emitPtrByteGet (rname, p_type, FALSE);
10161 emitcode ("mov","acc.%d,c",bstr);
10166 /* Case with a bitfield length < 8 and arbitrary source
10168 MOVA (aopGet (right, 0, FALSE, FALSE));
10169 /* shift and mask source value */
10171 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10173 pushedB = pushB ();
10174 /* transfer A to B and get next byte */
10175 emitPtrByteGet (rname, p_type, TRUE);
10177 emitcode ("anl", "a,#0x%02x", mask);
10178 emitcode ("orl", "a,b");
10179 if (p_type == GPOINTER)
10180 emitcode ("pop", "b");
10186 emitPtrByteSet (rname, p_type, "a");
10190 /* Bit length is greater than 7 bits. In this case, copy */
10191 /* all except the partial byte at the end */
10192 for (rlen=blen;rlen>=8;rlen-=8)
10194 emitPtrByteSet (rname, p_type,
10195 aopGet (right, offset++, FALSE, TRUE) );
10197 emitcode ("inc", "%s", rname);
10200 /* If there was a partial byte at the end */
10203 mask = (((unsigned char) -1 << rlen) & 0xff);
10205 if (AOP_TYPE (right) == AOP_LIT)
10207 /* Case with partial byte and literal source
10209 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10210 litval >>= (blen-rlen);
10211 litval &= (~mask) & 0xff;
10212 emitPtrByteGet (rname, p_type, FALSE);
10213 if ((mask|litval)!=0xff)
10214 emitcode ("anl","a,#0x%02x", mask);
10216 emitcode ("orl","a,#0x%02x", litval);
10221 /* Case with partial byte and arbitrary source
10223 MOVA (aopGet (right, offset++, FALSE, FALSE));
10224 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10226 pushedB = pushB ();
10227 /* transfer A to B and get next byte */
10228 emitPtrByteGet (rname, p_type, TRUE);
10230 emitcode ("anl", "a,#0x%02x", mask);
10231 emitcode ("orl", "a,b");
10232 if (p_type == GPOINTER)
10233 emitcode ("pop", "b");
10237 emitPtrByteSet (rname, p_type, "a");
10242 /*-----------------------------------------------------------------*/
10243 /* genDataPointerSet - remat pointer to data space */
10244 /*-----------------------------------------------------------------*/
10246 genDataPointerSet (operand * right,
10250 int size, offset = 0;
10251 char *l, buffer[256];
10253 D (emitcode (";", "genDataPointerSet"));
10255 aopOp (right, ic, FALSE);
10257 l = aopGet (result, 0, FALSE, TRUE);
10258 size = AOP_SIZE (right);
10262 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10264 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10265 emitcode ("mov", "%s,%s", buffer,
10266 aopGet (right, offset++, FALSE, FALSE));
10269 freeAsmop (result, NULL, ic, TRUE);
10270 freeAsmop (right, NULL, ic, TRUE);
10273 /*-----------------------------------------------------------------*/
10274 /* genNearPointerSet - emitcode for near pointer put */
10275 /*-----------------------------------------------------------------*/
10277 genNearPointerSet (operand * right,
10285 sym_link *retype, *letype;
10286 sym_link *ptype = operandType (result);
10288 D (emitcode (";", "genNearPointerSet"));
10290 retype = getSpec (operandType (right));
10291 letype = getSpec (ptype);
10293 aopOp (result, ic, FALSE);
10295 /* if the result is rematerializable &
10296 in data space & not a bit variable */
10297 if (AOP_TYPE (result) == AOP_IMMD &&
10298 DCL_TYPE (ptype) == POINTER &&
10299 !IS_BITVAR (retype) &&
10300 !IS_BITVAR (letype))
10302 genDataPointerSet (right, result, ic);
10306 /* if the value is already in a pointer register
10307 then don't need anything more */
10308 if (!AOP_INPREG (AOP (result)))
10311 //AOP_TYPE (result) == AOP_STK
10312 IS_AOP_PREG(result)
10315 // Aha, it is a pointer, just in disguise.
10316 rname = aopGet (result, 0, FALSE, FALSE);
10319 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10320 __FILE__, __LINE__);
10325 emitcode ("mov", "a%s,%s", rname + 1, rname);
10326 rname++; // skip the '@'.
10331 /* otherwise get a free pointer register */
10332 aop = newAsmop (0);
10333 preg = getFreePtr (ic, &aop, FALSE);
10334 emitcode ("mov", "%s,%s",
10336 aopGet (result, 0, FALSE, TRUE));
10337 rname = preg->name;
10342 rname = aopGet (result, 0, FALSE, FALSE);
10345 aopOp (right, ic, FALSE);
10347 /* if bitfield then unpack the bits */
10348 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10349 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10352 /* we can just get the values */
10353 int size = AOP_SIZE (right);
10358 l = aopGet (right, offset, FALSE, TRUE);
10359 if ((*l == '@') || (strcmp (l, "acc") == 0))
10362 emitcode ("mov", "@%s,a", rname);
10365 emitcode ("mov", "@%s,%s", rname, l);
10367 emitcode ("inc", "%s", rname);
10372 /* now some housekeeping stuff */
10373 if (aop) /* we had to allocate for this iCode */
10376 aopPut (result, rname, 0);
10377 freeAsmop (NULL, aop, ic, TRUE);
10381 /* we did not allocate which means left
10382 already in a pointer register, then
10383 if size > 0 && this could be used again
10384 we have to point it back to where it
10386 if ((AOP_SIZE (right) > 1 &&
10387 !OP_SYMBOL (result)->remat &&
10388 (OP_SYMBOL (result)->liveTo > ic->seq ||
10392 int size = AOP_SIZE (right) - 1;
10394 emitcode ("dec", "%s", rname);
10399 if (pi) pi->generated = 1;
10400 freeAsmop (result, NULL, ic, TRUE);
10401 freeAsmop (right, NULL, ic, TRUE);
10404 /*-----------------------------------------------------------------*/
10405 /* genPagedPointerSet - emitcode for Paged pointer put */
10406 /*-----------------------------------------------------------------*/
10408 genPagedPointerSet (operand * right,
10416 sym_link *retype, *letype;
10418 D (emitcode (";", "genPagedPointerSet"));
10420 retype = getSpec (operandType (right));
10421 letype = getSpec (operandType (result));
10423 aopOp (result, ic, FALSE);
10425 /* if the value is already in a pointer register
10426 then don't need anything more */
10427 if (!AOP_INPREG (AOP (result)))
10429 /* otherwise get a free pointer register */
10430 aop = newAsmop (0);
10431 preg = getFreePtr (ic, &aop, FALSE);
10432 emitcode ("mov", "%s,%s",
10434 aopGet (result, 0, FALSE, TRUE));
10435 rname = preg->name;
10438 rname = aopGet (result, 0, FALSE, FALSE);
10440 aopOp (right, ic, FALSE);
10442 /* if bitfield then unpack the bits */
10443 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10444 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10447 /* we have can just get the values */
10448 int size = AOP_SIZE (right);
10453 l = aopGet (right, offset, FALSE, TRUE);
10455 emitcode ("movx", "@%s,a", rname);
10458 emitcode ("inc", "%s", rname);
10464 /* now some housekeeping stuff */
10465 if (aop) /* we had to allocate for this iCode */
10468 aopPut (result, rname, 0);
10469 freeAsmop (NULL, aop, ic, TRUE);
10473 /* we did not allocate which means left
10474 already in a pointer register, then
10475 if size > 0 && this could be used again
10476 we have to point it back to where it
10478 if (AOP_SIZE (right) > 1 &&
10479 !OP_SYMBOL (result)->remat &&
10480 (OP_SYMBOL (result)->liveTo > ic->seq ||
10483 int size = AOP_SIZE (right) - 1;
10485 emitcode ("dec", "%s", rname);
10490 if (pi) pi->generated = 1;
10491 freeAsmop (result, NULL, ic, TRUE);
10492 freeAsmop (right, NULL, ic, TRUE);
10495 /*-----------------------------------------------------------------*/
10496 /* genFarPointerSet - set value from far space */
10497 /*-----------------------------------------------------------------*/
10499 genFarPointerSet (operand * right,
10500 operand * result, iCode * ic, iCode * pi)
10503 sym_link *retype = getSpec (operandType (right));
10504 sym_link *letype = getSpec (operandType (result));
10506 D(emitcode ("; genFarPointerSet",""));
10508 aopOp (result, ic, FALSE);
10509 loadDptrFromOperand (result, FALSE);
10511 /* so dptr now contains the address */
10512 aopOp (right, ic, FALSE);
10514 /* if bit then unpack */
10515 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10516 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10519 size = AOP_SIZE (right);
10524 char *l = aopGet (right, offset++, FALSE, FALSE);
10526 emitcode ("movx", "@dptr,a");
10528 emitcode ("inc", "dptr");
10531 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10532 aopPut (result, "dpl", 0);
10533 aopPut (result, "dph", 1);
10536 freeAsmop (result, NULL, ic, TRUE);
10537 freeAsmop (right, NULL, ic, TRUE);
10540 /*-----------------------------------------------------------------*/
10541 /* genGenPointerSet - set value from generic pointer space */
10542 /*-----------------------------------------------------------------*/
10544 genGenPointerSet (operand * right,
10545 operand * result, iCode * ic, iCode * pi)
10548 sym_link *retype = getSpec (operandType (right));
10549 sym_link *letype = getSpec (operandType (result));
10551 D (emitcode (";", "genGenPointerSet"));
10553 aopOp (result, ic, FALSE);
10554 loadDptrFromOperand (result, TRUE);
10556 /* so dptr now contains the address */
10557 aopOp (right, ic, FALSE);
10559 /* if bit then unpack */
10560 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10562 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10566 size = AOP_SIZE (right);
10571 char *l = aopGet (right, offset++, FALSE, FALSE);
10573 emitcode ("lcall", "__gptrput");
10575 emitcode ("inc", "dptr");
10579 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10580 aopPut (result, "dpl", 0);
10581 aopPut (result, "dph", 1);
10584 freeAsmop (result, NULL, ic, TRUE);
10585 freeAsmop (right, NULL, ic, TRUE);
10588 /*-----------------------------------------------------------------*/
10589 /* genPointerSet - stores the value into a pointer location */
10590 /*-----------------------------------------------------------------*/
10592 genPointerSet (iCode * ic, iCode *pi)
10594 operand *right, *result;
10595 sym_link *type, *etype;
10598 D (emitcode (";", "genPointerSet"));
10600 right = IC_RIGHT (ic);
10601 result = IC_RESULT (ic);
10603 /* depending on the type of pointer we need to
10604 move it to the correct pointer register */
10605 type = operandType (result);
10606 etype = getSpec (type);
10607 /* if left is of type of pointer then it is simple */
10608 if (IS_PTR (type) && !IS_FUNC (type->next))
10610 p_type = DCL_TYPE (type);
10614 /* we have to go by the storage class */
10615 p_type = PTR_TYPE (SPEC_OCLS (etype));
10618 /* special case when cast remat */
10619 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10620 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10621 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10622 type = operandType (result);
10623 p_type = DCL_TYPE (type);
10626 /* now that we have the pointer type we assign
10627 the pointer values */
10633 genNearPointerSet (right, result, ic, pi);
10637 genPagedPointerSet (right, result, ic, pi);
10641 genFarPointerSet (right, result, ic, pi);
10645 genGenPointerSet (right, result, ic, pi);
10649 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10650 "genPointerSet: illegal pointer type");
10654 /*-----------------------------------------------------------------*/
10655 /* genIfx - generate code for Ifx statement */
10656 /*-----------------------------------------------------------------*/
10658 genIfx (iCode * ic, iCode * popIc)
10660 operand *cond = IC_COND (ic);
10664 D (emitcode (";", "genIfx"));
10666 aopOp (cond, ic, FALSE);
10668 /* get the value into acc */
10669 if (AOP_TYPE (cond) != AOP_CRY)
10676 if (AOP(cond)->aopu.aop_dir)
10677 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10680 /* the result is now in the accumulator or a directly addressable bit */
10681 freeAsmop (cond, NULL, ic, TRUE);
10683 /* if there was something to be popped then do it */
10687 /* if the condition is a bit variable */
10689 genIfxJump(ic, dup, NULL, NULL, NULL);
10690 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10691 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10692 else if (isbit && !IS_ITEMP (cond))
10693 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10695 genIfxJump (ic, "a", NULL, NULL, NULL);
10700 /*-----------------------------------------------------------------*/
10701 /* genAddrOf - generates code for address of */
10702 /*-----------------------------------------------------------------*/
10704 genAddrOf (iCode * ic)
10706 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10709 D (emitcode (";", "genAddrOf"));
10711 aopOp (IC_RESULT (ic), ic, FALSE);
10713 /* if the operand is on the stack then we
10714 need to get the stack offset of this
10718 /* if it has an offset then we need to compute it */
10721 emitcode ("mov", "a,%s", SYM_BP (sym));
10722 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10723 ((char) (sym->stack - _G.nRegsSaved)) :
10724 ((char) sym->stack)) & 0xff);
10725 aopPut (IC_RESULT (ic), "a", 0);
10729 /* we can just move _bp */
10730 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10732 /* fill the result with zero */
10733 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10738 aopPut (IC_RESULT (ic), zero, offset++);
10743 /* object not on stack then we need the name */
10744 size = AOP_SIZE (IC_RESULT (ic));
10749 char s[SDCC_NAME_MAX];
10751 sprintf (s, "#(%s >> %d)",
10755 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10756 aopPut (IC_RESULT (ic), s, offset++);
10760 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10764 /*-----------------------------------------------------------------*/
10765 /* genFarFarAssign - assignment when both are in far space */
10766 /*-----------------------------------------------------------------*/
10768 genFarFarAssign (operand * result, operand * right, iCode * ic)
10770 int size = AOP_SIZE (right);
10774 D (emitcode (";", "genFarFarAssign"));
10776 /* first push the right side on to the stack */
10779 l = aopGet (right, offset++, FALSE, FALSE);
10781 emitcode ("push", "acc");
10784 freeAsmop (right, NULL, ic, FALSE);
10785 /* now assign DPTR to result */
10786 aopOp (result, ic, FALSE);
10787 size = AOP_SIZE (result);
10790 emitcode ("pop", "acc");
10791 aopPut (result, "a", --offset);
10793 freeAsmop (result, NULL, ic, FALSE);
10796 /*-----------------------------------------------------------------*/
10797 /* genAssign - generate code for assignment */
10798 /*-----------------------------------------------------------------*/
10800 genAssign (iCode * ic)
10802 operand *result, *right;
10804 unsigned long lit = 0L;
10806 D (emitcode (";", "genAssign"));
10808 result = IC_RESULT (ic);
10809 right = IC_RIGHT (ic);
10811 /* if they are the same */
10812 if (operandsEqu (result, right) &&
10813 !isOperandVolatile (result, FALSE) &&
10814 !isOperandVolatile (right, FALSE))
10817 aopOp (right, ic, FALSE);
10819 /* special case both in far space */
10820 if (AOP_TYPE (right) == AOP_DPTR &&
10821 IS_TRUE_SYMOP (result) &&
10822 isOperandInFarSpace (result))
10824 genFarFarAssign (result, right, ic);
10828 aopOp (result, ic, TRUE);
10830 /* if they are the same registers */
10831 if (sameRegs (AOP (right), AOP (result)) &&
10832 !isOperandVolatile (result, FALSE) &&
10833 !isOperandVolatile (right, FALSE))
10836 /* if the result is a bit */
10837 if (AOP_TYPE (result) == AOP_CRY)
10839 /* if the right size is a literal then
10840 we know what the value is */
10841 if (AOP_TYPE (right) == AOP_LIT)
10843 if (((int) operandLitValue (right)))
10844 aopPut (result, one, 0);
10846 aopPut (result, zero, 0);
10850 /* the right is also a bit variable */
10851 if (AOP_TYPE (right) == AOP_CRY)
10853 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10854 aopPut (result, "c", 0);
10858 /* we need to or */
10860 aopPut (result, "a", 0);
10864 /* bit variables done */
10866 size = AOP_SIZE (result);
10868 if (AOP_TYPE (right) == AOP_LIT)
10869 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10872 (AOP_TYPE (result) != AOP_REG) &&
10873 (AOP_TYPE (right) == AOP_LIT) &&
10874 !IS_FLOAT (operandType (right)) &&
10877 while ((size) && (lit))
10880 aopGet (right, offset, FALSE, FALSE),
10886 /* And now fill the rest with zeros. */
10889 emitcode ("clr", "a");
10893 aopPut (result, "a", offset);
10902 aopGet (right, offset, FALSE, FALSE),
10909 freeAsmop (result, NULL, ic, TRUE);
10910 freeAsmop (right, NULL, ic, TRUE);
10913 /*-----------------------------------------------------------------*/
10914 /* genJumpTab - generates code for jump table */
10915 /*-----------------------------------------------------------------*/
10917 genJumpTab (iCode * ic)
10919 symbol *jtab,*jtablo,*jtabhi;
10921 unsigned int count;
10923 D (emitcode (";", "genJumpTab"));
10925 count = elementsInSet( IC_JTLABELS (ic) );
10929 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10930 if the switch argument is in a register.
10931 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10932 /* Peephole may not convert ljmp to sjmp or ret
10933 labelIsReturnOnly & labelInRange must check
10934 currPl->ic->op != JUMPTABLE */
10935 aopOp (IC_JTCOND (ic), ic, FALSE);
10936 /* get the condition into accumulator */
10937 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10939 /* multiply by three */
10940 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10942 emitcode ("mov", "b,#3");
10943 emitcode ("mul", "ab");
10947 emitcode ("add", "a,acc");
10948 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10950 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10952 jtab = newiTempLabel (NULL);
10953 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10954 emitcode ("jmp", "@a+dptr");
10956 /* now generate the jump labels */
10957 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10958 jtab = setNextItem (IC_JTLABELS (ic)))
10959 emitcode ("ljmp", "%05d$", jtab->key + 100);
10963 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10964 if the switch argument is in a register.
10965 For n>6 this algorithm may be more compact */
10966 jtablo = newiTempLabel (NULL);
10967 jtabhi = newiTempLabel (NULL);
10969 /* get the condition into accumulator.
10970 Using b as temporary storage, if register push/pop is needed */
10971 aopOp (IC_JTCOND (ic), ic, FALSE);
10972 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10973 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10974 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10976 // (MB) what if B is in use???
10977 wassertl(!BINUSE, "B was in use");
10978 emitcode ("mov", "b,%s", l);
10981 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10985 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10986 emitcode ("movc", "a,@a+pc");
10987 emitcode ("push", "acc");
10990 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10991 emitcode ("movc", "a,@a+pc");
10992 emitcode ("push", "acc");
10996 /* this scales up to n<=255, but needs two more bytes
10997 and changes dptr */
10998 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10999 emitcode ("movc", "a,@a+dptr");
11000 emitcode ("push", "acc");
11003 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11004 emitcode ("movc", "a,@a+dptr");
11005 emitcode ("push", "acc");
11008 emitcode ("ret", "");
11010 /* now generate jump table, LSB */
11011 emitLabel (jtablo);
11012 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11013 jtab = setNextItem (IC_JTLABELS (ic)))
11014 emitcode (".db", "%05d$", jtab->key + 100);
11016 /* now generate jump table, MSB */
11017 emitLabel (jtabhi);
11018 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11019 jtab = setNextItem (IC_JTLABELS (ic)))
11020 emitcode (".db", "%05d$>>8", jtab->key + 100);
11024 /*-----------------------------------------------------------------*/
11025 /* genCast - gen code for casting */
11026 /*-----------------------------------------------------------------*/
11028 genCast (iCode * ic)
11030 operand *result = IC_RESULT (ic);
11031 sym_link *ctype = operandType (IC_LEFT (ic));
11032 sym_link *rtype = operandType (IC_RIGHT (ic));
11033 operand *right = IC_RIGHT (ic);
11036 D (emitcode (";", "genCast"));
11038 /* if they are equivalent then do nothing */
11039 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11042 aopOp (right, ic, FALSE);
11043 aopOp (result, ic, FALSE);
11045 /* if the result is a bit (and not a bitfield) */
11046 if (IS_BIT (OP_SYMBOL (result)->type))
11048 /* if the right size is a literal then
11049 we know what the value is */
11050 if (AOP_TYPE (right) == AOP_LIT)
11052 if (((int) operandLitValue (right)))
11053 aopPut (result, one, 0);
11055 aopPut (result, zero, 0);
11060 /* the right is also a bit variable */
11061 if (AOP_TYPE (right) == AOP_CRY)
11063 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11064 aopPut (result, "c", 0);
11068 /* we need to or */
11070 aopPut (result, "a", 0);
11074 /* if they are the same size : or less */
11075 if (AOP_SIZE (result) <= AOP_SIZE (right))
11078 /* if they are in the same place */
11079 if (sameRegs (AOP (right), AOP (result)))
11082 /* if they in different places then copy */
11083 size = AOP_SIZE (result);
11088 aopGet (right, offset, FALSE, FALSE),
11095 /* if the result is of type pointer */
11096 if (IS_PTR (ctype))
11100 sym_link *type = operandType (right);
11101 sym_link *etype = getSpec (type);
11103 /* pointer to generic pointer */
11104 if (IS_GENPTR (ctype))
11108 p_type = DCL_TYPE (type);
11112 if (SPEC_SCLS(etype)==S_REGISTER) {
11113 // let's assume it is a generic pointer
11116 /* we have to go by the storage class */
11117 p_type = PTR_TYPE (SPEC_OCLS (etype));
11121 /* the first two bytes are known */
11122 size = GPTRSIZE - 1;
11127 aopGet (right, offset, FALSE, FALSE),
11131 /* the last byte depending on type */
11133 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11138 // pointerTypeToGPByte will have bitched.
11142 sprintf(gpValStr, "#0x%x", gpVal);
11143 aopPut (result, gpValStr, GPTRSIZE - 1);
11148 /* just copy the pointers */
11149 size = AOP_SIZE (result);
11154 aopGet (right, offset, FALSE, FALSE),
11161 /* so we now know that the size of destination is greater
11162 than the size of the source */
11163 /* we move to result for the size of source */
11164 size = AOP_SIZE (right);
11169 aopGet (right, offset, FALSE, FALSE),
11174 /* now depending on the sign of the source && destination */
11175 size = AOP_SIZE (result) - AOP_SIZE (right);
11176 /* if unsigned or not an integral type */
11177 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11180 aopPut (result, zero, offset++);
11184 /* we need to extend the sign :{ */
11185 char *l = aopGet (right, AOP_SIZE (right) - 1,
11188 emitcode ("rlc", "a");
11189 emitcode ("subb", "a,acc");
11191 aopPut (result, "a", offset++);
11194 /* we are done hurray !!!! */
11197 freeAsmop (result, NULL, ic, TRUE);
11198 freeAsmop (right, NULL, ic, TRUE);
11201 /*-----------------------------------------------------------------*/
11202 /* genDjnz - generate decrement & jump if not zero instrucion */
11203 /*-----------------------------------------------------------------*/
11205 genDjnz (iCode * ic, iCode * ifx)
11207 symbol *lbl, *lbl1;
11211 /* if the if condition has a false label
11212 then we cannot save */
11213 if (IC_FALSE (ifx))
11216 /* if the minus is not of the form a = a - 1 */
11217 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11218 !IS_OP_LITERAL (IC_RIGHT (ic)))
11221 if (operandLitValue (IC_RIGHT (ic)) != 1)
11224 /* if the size of this greater than one then no
11226 if (getSize (operandType (IC_RESULT (ic))) > 1)
11229 /* otherwise we can save BIG */
11231 D (emitcode (";", "genDjnz"));
11233 lbl = newiTempLabel (NULL);
11234 lbl1 = newiTempLabel (NULL);
11236 aopOp (IC_RESULT (ic), ic, FALSE);
11238 if (AOP_NEEDSACC(IC_RESULT(ic)))
11240 /* If the result is accessed indirectly via
11241 * the accumulator, we must explicitly write
11242 * it back after the decrement.
11244 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11246 if (strcmp(rByte, "a"))
11248 /* Something is hopelessly wrong */
11249 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11250 __FILE__, __LINE__);
11251 /* We can just give up; the generated code will be inefficient,
11252 * but what the hey.
11254 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11257 emitcode ("dec", "%s", rByte);
11258 aopPut (IC_RESULT (ic), rByte, 0);
11259 emitcode ("jnz", "%05d$", lbl->key + 100);
11261 else if (IS_AOP_PREG (IC_RESULT (ic)))
11263 emitcode ("dec", "%s",
11264 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11265 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11267 ifx->generated = 1;
11268 emitcode ("jnz", "%05d$", lbl->key + 100);
11272 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11275 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11277 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11280 if (!ifx->generated)
11281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11282 ifx->generated = 1;
11286 /*-----------------------------------------------------------------*/
11287 /* genReceive - generate code for a receive iCode */
11288 /*-----------------------------------------------------------------*/
11290 genReceive (iCode * ic)
11292 int size = getSize (operandType (IC_RESULT (ic)));
11295 D (emitcode (";", "genReceive"));
11297 if (ic->argreg == 1)
11298 { /* first parameter */
11299 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11300 isOperandInPagedSpace (IC_RESULT (ic))) &&
11301 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11302 IS_TRUE_SYMOP (IC_RESULT (ic))))
11305 int receivingA = 0;
11308 for (offset = 0; offset<size; offset++)
11309 if (!strcmp (fReturn[offset], "a"))
11314 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11316 for (offset = size-1; offset>0; offset--)
11317 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11318 emitcode("mov","a,%s", fReturn[0]);
11320 aopOp (IC_RESULT (ic), ic, FALSE);
11322 aopPut (IC_RESULT (ic), "a", offset);
11323 for (offset = 1; offset<size; offset++)
11324 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11330 if (getTempRegs(tempRegs, size, ic))
11332 for (offset = 0; offset<size; offset++)
11333 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11334 aopOp (IC_RESULT (ic), ic, FALSE);
11335 for (offset = 0; offset<size; offset++)
11336 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11341 offset = fReturnSizeMCS51 - size;
11344 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11345 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11348 aopOp (IC_RESULT (ic), ic, FALSE);
11349 size = AOP_SIZE (IC_RESULT (ic));
11353 emitcode ("pop", "acc");
11354 aopPut (IC_RESULT (ic), "a", offset++);
11360 aopOp (IC_RESULT (ic), ic, FALSE);
11362 assignResultValue (IC_RESULT (ic), NULL);
11365 else if (ic->argreg > 12)
11366 { /* bit parameters */
11367 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11369 aopOp (IC_RESULT (ic), ic, FALSE);
11370 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11371 outBitC(IC_RESULT (ic));
11375 { /* other parameters */
11377 aopOp (IC_RESULT (ic), ic, FALSE);
11378 rb1off = ic->argreg;
11381 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11389 /*-----------------------------------------------------------------*/
11390 /* genDummyRead - generate code for dummy read of volatiles */
11391 /*-----------------------------------------------------------------*/
11393 genDummyRead (iCode * ic)
11398 D (emitcode(";", "genDummyRead"));
11400 op = IC_RIGHT (ic);
11401 if (op && IS_SYMOP (op))
11403 aopOp (op, ic, FALSE);
11405 /* if the result is a bit */
11406 if (AOP_TYPE (op) == AOP_CRY)
11407 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11410 /* bit variables done */
11412 size = AOP_SIZE (op);
11416 MOVA (aopGet (op, offset, FALSE, FALSE));
11421 freeAsmop (op, NULL, ic, TRUE);
11425 if (op && IS_SYMOP (op))
11427 aopOp (op, ic, FALSE);
11429 /* if the result is a bit */
11430 if (AOP_TYPE (op) == AOP_CRY)
11431 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11434 /* bit variables done */
11436 size = AOP_SIZE (op);
11440 MOVA (aopGet (op, offset, FALSE, FALSE));
11445 freeAsmop (op, NULL, ic, TRUE);
11449 /*-----------------------------------------------------------------*/
11450 /* genCritical - generate code for start of a critical sequence */
11451 /*-----------------------------------------------------------------*/
11453 genCritical (iCode *ic)
11455 symbol *tlbl = newiTempLabel (NULL);
11457 D (emitcode(";", "genCritical"));
11459 if (IC_RESULT (ic))
11461 aopOp (IC_RESULT (ic), ic, TRUE);
11462 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11463 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11464 aopPut (IC_RESULT (ic), zero, 0);
11466 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11470 emitcode ("setb", "c");
11471 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11472 emitcode ("clr", "c");
11474 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11478 /*-----------------------------------------------------------------*/
11479 /* genEndCritical - generate code for end of a critical sequence */
11480 /*-----------------------------------------------------------------*/
11482 genEndCritical (iCode *ic)
11484 D(emitcode("; genEndCritical",""));
11488 aopOp (IC_RIGHT (ic), ic, FALSE);
11489 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11491 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11492 emitcode ("mov", "ea,c");
11496 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11497 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11498 emitcode ("rrc", "a");
11499 emitcode ("mov", "ea,c");
11501 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11505 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11506 emitcode ("mov", "ea,c");
11510 /*-----------------------------------------------------------------*/
11511 /* gen51Code - generate code for 8051 based controllers */
11512 /*-----------------------------------------------------------------*/
11514 gen51Code (iCode * lic)
11518 /* int cseq = 0; */
11520 _G.currentFunc = NULL;
11521 lineHead = lineCurr = NULL;
11523 /* print the allocation information */
11524 if (allocInfo && currFunc)
11525 printAllocInfo (currFunc, codeOutFile);
11526 /* if debug information required */
11527 if (options.debug && currFunc)
11529 debugFile->writeFunction (currFunc, lic);
11531 /* stack pointer name */
11532 if (options.useXstack)
11538 for (ic = lic; ic; ic = ic->next)
11540 _G.current_iCode = ic;
11542 if (ic->lineno && cln != ic->lineno)
11546 debugFile->writeCLine (ic);
11548 if (!options.noCcodeInAsm) {
11549 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11550 printCLine(ic->filename, ic->lineno));
11555 if (ic->seqPoint && ic->seqPoint != cseq)
11557 emitcode ("", "; sequence point %d", ic->seqPoint);
11558 cseq = ic->seqPoint;
11561 if (options.iCodeInAsm) {
11562 char regsInUse[80];
11566 for (i=0; i<8; i++) {
11567 sprintf (®sInUse[i],
11568 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11571 strcpy (regsInUse, "--------");
11572 for (i=0; i < 8; i++) {
11573 if (bitVectBitValue (ic->rMask, i))
11575 int offset = regs8051[i].offset;
11576 regsInUse[offset] = offset + '0'; /* show rMask */
11580 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11582 /* if the result is marked as
11583 spilt and rematerializable or code for
11584 this has already been generated then
11586 if (resultRemat (ic) || ic->generated)
11589 /* depending on the operation */
11609 /* IPOP happens only when trying to restore a
11610 spilt live range, if there is an ifx statement
11611 following this pop then the if statement might
11612 be using some of the registers being popped which
11613 would destory the contents of the register so
11614 we need to check for this condition and handle it */
11616 ic->next->op == IFX &&
11617 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11618 genIfx (ic->next, ic);
11636 genEndFunction (ic);
11656 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11673 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11677 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11684 /* note these two are xlated by algebraic equivalence
11685 in decorateType() in SDCCast.c */
11686 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11687 "got '>=' or '<=' shouldn't have come here");
11691 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11703 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11707 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11711 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11747 genRightShift (ic);
11750 case GET_VALUE_AT_ADDRESS:
11752 hasInc (IC_LEFT (ic), ic,
11753 getSize (operandType (IC_RESULT (ic)))),
11754 ifxForOp (IC_RESULT (ic), ic) );
11758 if (POINTER_SET (ic))
11760 hasInc (IC_RESULT (ic), ic,
11761 getSize (operandType (IC_RIGHT (ic)))));
11787 addSet (&_G.sendSet, ic);
11790 case DUMMY_READ_VOLATILE:
11799 genEndCritical (ic);
11811 _G.current_iCode = NULL;
11813 /* now we are ready to call the
11814 peep hole optimizer */
11815 if (!options.nopeep)
11816 peepHole (&lineHead);
11818 /* now do the actual printing */
11819 printLine (lineHead, codeOutFile);