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 sprintf(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");
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");
1135 emitcode ("pop", "ar0");
1143 /* all other cases just dealloc */
1149 OP_SYMBOL (op)->aop = NULL;
1150 /* if the symbol has a spill */
1152 SPIL_LOC (op)->aop = NULL;
1157 /*------------------------------------------------------------------*/
1158 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1159 /* pop r0 or r1 off stack if pushed */
1160 /*------------------------------------------------------------------*/
1162 freeForBranchAsmop (operand * op)
1174 if (!aop->allocated)
1182 emitcode ("mov", "r0,b");
1184 else if (_G.r0Pushed)
1186 emitcode ("pop", "ar0");
1193 emitcode ("mov", "r1,b");
1195 else if (_G.r1Pushed)
1197 emitcode ("pop", "ar1");
1204 int stk = aop->aopu.aop_stk + aop->size - 1;
1206 emitcode ("mov", "b,r0");
1209 emitcode ("mov", "a,_bp");
1210 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1211 emitcode ("mov", "r0,a");
1215 emitcode ("mov", "r0,_bp");
1220 emitcode ("pop", "acc");
1221 emitcode ("mov", "@r0,a");
1224 emitcode ("dec", "r0");
1226 emitcode ("mov", "r0,b");
1232 /*-----------------------------------------------------------------*/
1233 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1234 /* clobber the accumulator */
1235 /*-----------------------------------------------------------------*/
1237 aopGetUsesAcc (operand * oper, int offset)
1239 asmop * aop = AOP (oper);
1241 if (offset > (aop->size - 1))
1259 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1270 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1276 /* Error case --- will have been caught already */
1282 /*-------------------------------------------------------------------*/
1283 /* aopGet - for fetching value of the aop */
1284 /*-------------------------------------------------------------------*/
1286 aopGet (operand * oper, int offset, bool bit16, bool dname)
1288 asmop * aop = AOP (oper);
1290 /* offset is greater than
1292 if (offset > (aop->size - 1) &&
1293 aop->type != AOP_LIT)
1296 /* depending on type */
1304 /* if we need to increment it */
1305 while (offset > aop->coff)
1307 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1311 while (offset < aop->coff)
1313 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1320 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1321 return (dname ? "acc" : "a");
1323 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1324 return Safe_strdup(buffer);
1327 if (aop->code && aop->coff==0 && offset>=1) {
1328 emitcode ("mov", "a,#0x%02x", offset);
1329 emitcode ("movc", "a,@a+dptr");
1330 return (dname ? "acc" : "a");
1333 while (offset > aop->coff)
1335 emitcode ("inc", "dptr");
1339 while (offset < aop->coff)
1341 emitcode ("lcall", "__decdptr");
1348 emitcode ("clr", "a");
1349 emitcode ("movc", "a,@a+dptr");
1353 emitcode ("movx", "a,@dptr");
1355 return (dname ? "acc" : "a");
1358 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1360 SNPRINTF(buffer, sizeof(buffer),
1361 "%s",aop->aopu.aop_immd.aop_immd2);
1365 SNPRINTF(buffer, sizeof(buffer),
1366 "#%s", aop->aopu.aop_immd.aop_immd1);
1370 SNPRINTF (buffer, sizeof(buffer),
1372 aop->aopu.aop_immd.aop_immd1,
1377 SNPRINTF (buffer, sizeof(buffer),
1379 aop->aopu.aop_immd.aop_immd1);
1381 return Safe_strdup(buffer);
1384 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1386 SNPRINTF (buffer, sizeof(buffer),
1388 aop->aopu.aop_dir, offset * 8);
1392 SNPRINTF (buffer, sizeof(buffer),
1399 SNPRINTF (buffer, sizeof(buffer),
1404 return Safe_strdup(buffer);
1408 return aop->aopu.aop_reg[offset]->dname;
1410 return aop->aopu.aop_reg[offset]->name;
1413 emitcode ("clr", "a");
1414 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415 emitcode ("rlc", "a");
1416 return (dname ? "acc" : "a");
1419 if (!offset && dname)
1421 return aop->aopu.aop_str[offset];
1424 return aopLiteral (aop->aopu.aop_lit, offset);
1428 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1432 return aop->aopu.aop_str[offset];
1436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437 "aopget got unsupported aop->type");
1441 /*-----------------------------------------------------------------*/
1442 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1443 /* clobber the accumulator */
1444 /*-----------------------------------------------------------------*/
1446 aopPutUsesAcc (operand * oper, const char *s, int offset)
1448 asmop * aop = AOP (oper);
1450 if (offset > (aop->size - 1))
1460 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1466 return ((aop->paged) || (*s == '@'));
1470 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1478 /* Error case --- will have been caught already */
1484 /*-----------------------------------------------------------------*/
1485 /* aopPut - puts a string for a aop and indicates if acc is in use */
1486 /*-----------------------------------------------------------------*/
1488 aopPut (operand * result, const char *s, int offset)
1490 bool bvolatile = isOperandVolatile (result, FALSE);
1491 bool accuse = FALSE;
1492 asmop * aop = AOP (result);
1494 if (aop->size && offset > (aop->size - 1))
1496 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1497 "aopPut got offset > aop->size");
1501 /* will assign value to value */
1502 /* depending on where it is ofcourse */
1506 MOVA (s); /* read s in case it was volatile */
1511 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1513 SNPRINTF (buffer, sizeof(buffer),
1515 aop->aopu.aop_dir, offset * 8);
1519 SNPRINTF (buffer, sizeof(buffer),
1521 aop->aopu.aop_dir, offset);
1525 SNPRINTF (buffer, sizeof(buffer),
1530 if (strcmp (buffer, s) || bvolatile)
1532 emitcode ("mov", "%s,%s", buffer, s);
1534 if (!strcmp (buffer, "acc"))
1541 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1542 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1545 strcmp (s, "r0") == 0 ||
1546 strcmp (s, "r1") == 0 ||
1547 strcmp (s, "r2") == 0 ||
1548 strcmp (s, "r3") == 0 ||
1549 strcmp (s, "r4") == 0 ||
1550 strcmp (s, "r5") == 0 ||
1551 strcmp (s, "r6") == 0 ||
1552 strcmp (s, "r7") == 0)
1554 emitcode ("mov", "%s,%s",
1555 aop->aopu.aop_reg[offset]->dname, s);
1559 emitcode ("mov", "%s,%s",
1560 aop->aopu.aop_reg[offset]->name, s);
1568 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1569 "aopPut writing to code space");
1573 while (offset > aop->coff)
1576 emitcode ("inc", "dptr");
1579 while (offset < aop->coff)
1582 emitcode ("lcall", "__decdptr");
1587 /* if not in accumulator */
1590 emitcode ("movx", "@dptr,a");
1595 while (offset > aop->coff)
1598 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1600 while (offset < aop->coff)
1603 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1610 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1615 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1617 else if (strcmp (s, "r0") == 0 ||
1618 strcmp (s, "r1") == 0 ||
1619 strcmp (s, "r2") == 0 ||
1620 strcmp (s, "r3") == 0 ||
1621 strcmp (s, "r4") == 0 ||
1622 strcmp (s, "r5") == 0 ||
1623 strcmp (s, "r6") == 0 ||
1624 strcmp (s, "r7") == 0)
1627 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1628 emitcode ("mov", "@%s,%s",
1629 aop->aopu.aop_ptr->name, buffer);
1633 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1638 if (strcmp (s, "a") == 0)
1639 emitcode ("push", "acc");
1643 emitcode ("push", "acc");
1645 emitcode ("push", s);
1651 /* if not bit variable */
1652 if (!aop->aopu.aop_dir)
1654 /* inefficient: move carry into A and use jz/jnz */
1655 emitcode ("clr", "a");
1656 emitcode ("rlc", "a");
1662 emitcode ("clr", "%s", aop->aopu.aop_dir);
1664 emitcode ("setb", "%s", aop->aopu.aop_dir);
1665 else if (!strcmp (s, "c"))
1666 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1667 else if (strcmp (s, aop->aopu.aop_dir))
1670 /* set C, if a >= 1 */
1671 emitcode ("add", "a,#0xff");
1672 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1679 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1680 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1686 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1689 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1690 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1694 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1695 "aopPut got unsupported aop->type");
1704 /*-----------------------------------------------------------------*/
1705 /* pointToEnd :- points to the last byte of the operand */
1706 /*-----------------------------------------------------------------*/
1708 pointToEnd (asmop * aop)
1714 aop->coff = count = (aop->size - 1);
1720 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1724 emitcode ("inc", "dptr");
1731 /*-----------------------------------------------------------------*/
1732 /* reAdjustPreg - points a register back to where it should */
1733 /*-----------------------------------------------------------------*/
1735 reAdjustPreg (asmop * aop)
1737 if ((aop->coff==0) || (aop->size <= 1))
1745 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1750 emitcode ("lcall", "__decdptr");
1757 /*-----------------------------------------------------------------*/
1758 /* opIsGptr: returns non-zero if the passed operand is */
1759 /* a generic pointer type. */
1760 /*-----------------------------------------------------------------*/
1762 opIsGptr (operand * op)
1764 sym_link *type = operandType (op);
1766 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1773 /*-----------------------------------------------------------------*/
1774 /* getDataSize - get the operand data size */
1775 /*-----------------------------------------------------------------*/
1777 getDataSize (operand * op)
1780 size = AOP_SIZE (op);
1781 if (size == GPTRSIZE)
1783 sym_link *type = operandType (op);
1784 if (IS_GENPTR (type))
1786 /* generic pointer; arithmetic operations
1787 * should ignore the high byte (pointer type).
1795 /*-----------------------------------------------------------------*/
1796 /* outAcc - output Acc */
1797 /*-----------------------------------------------------------------*/
1799 outAcc (operand * result)
1802 size = getDataSize (result);
1805 aopPut (result, "a", 0);
1808 /* unsigned or positive */
1811 aopPut (result, zero, offset++);
1816 /*-----------------------------------------------------------------*/
1817 /* outBitC - output a bit C */
1818 /*-----------------------------------------------------------------*/
1820 outBitC (operand * result)
1822 /* if the result is bit */
1823 if (AOP_TYPE (result) == AOP_CRY)
1825 aopPut (result, "c", 0);
1829 emitcode ("clr", "a");
1830 emitcode ("rlc", "a");
1835 /*-----------------------------------------------------------------*/
1836 /* toBoolean - emit code for orl a,operator(sizeop) */
1837 /*-----------------------------------------------------------------*/
1839 toBoolean (operand * oper)
1841 int size = AOP_SIZE (oper) - 1;
1843 bool AccUsed = FALSE;
1846 while (!AccUsed && size--)
1848 AccUsed |= aopGetUsesAcc(oper, offset++);
1851 size = AOP_SIZE (oper) - 1;
1853 MOVA (aopGet (oper, 0, FALSE, FALSE));
1854 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1857 emitcode("mov", "b,a");
1860 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1861 emitcode ("orl", "b,a");
1863 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1864 emitcode ("orl", "a,b");
1871 emitcode ("orl", "a,%s",
1872 aopGet (oper, offset++, FALSE, FALSE));
1878 /*-----------------------------------------------------------------*/
1879 /* genNot - generate code for ! operation */
1880 /*-----------------------------------------------------------------*/
1886 D (emitcode (";", "genNot"));
1888 /* assign asmOps to operand & result */
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1890 aopOp (IC_RESULT (ic), ic, TRUE);
1892 /* if in bit space then a special case */
1893 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1895 /* if left==result then cpl bit */
1896 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1898 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1902 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1903 emitcode ("cpl", "c");
1904 outBitC (IC_RESULT (ic));
1909 toBoolean (IC_LEFT (ic));
1911 /* set C, if a == 0 */
1912 tlbl = newiTempLabel (NULL);
1913 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1915 outBitC (IC_RESULT (ic));
1918 /* release the aops */
1919 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1920 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1924 /*-----------------------------------------------------------------*/
1925 /* genCpl - generate code for complement */
1926 /*-----------------------------------------------------------------*/
1933 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1935 D(emitcode (";", "genCpl"));
1937 /* assign asmOps to operand & result */
1938 aopOp (IC_LEFT (ic), ic, FALSE);
1939 aopOp (IC_RESULT (ic), ic, TRUE);
1941 /* special case if in bit space */
1942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1946 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1947 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1949 /* promotion rules are responsible for this strange result:
1950 bit -> int -> ~int -> bit
1951 uchar -> int -> ~int -> bit
1953 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1957 tlbl=newiTempLabel(NULL);
1958 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1959 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1960 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1961 IS_AOP_PREG (IC_LEFT (ic)))
1963 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1968 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1971 outBitC (IC_RESULT(ic));
1975 size = AOP_SIZE (IC_RESULT (ic));
1978 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1980 emitcode ("cpl", "a");
1981 aopPut (IC_RESULT (ic), "a", offset++);
1986 /* release the aops */
1987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1988 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1991 /*-----------------------------------------------------------------*/
1992 /* genUminusFloat - unary minus for floating points */
1993 /*-----------------------------------------------------------------*/
1995 genUminusFloat (operand * op, operand * result)
1997 int size, offset = 0;
2000 D (emitcode (";", "genUminusFloat"));
2002 /* for this we just copy and then flip the bit */
2004 size = AOP_SIZE (op) - 1;
2009 aopGet (op, offset, FALSE, FALSE),
2014 l = aopGet (op, offset, FALSE, FALSE);
2017 emitcode ("cpl", "acc.7");
2018 aopPut (result, "a", offset);
2021 /*-----------------------------------------------------------------*/
2022 /* genUminus - unary minus code generation */
2023 /*-----------------------------------------------------------------*/
2025 genUminus (iCode * ic)
2030 D (emitcode (";", "genUminus"));
2033 aopOp (IC_LEFT (ic), ic, FALSE);
2034 aopOp (IC_RESULT (ic), ic, TRUE);
2036 /* if both in bit space then special
2038 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2039 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2042 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2043 emitcode ("cpl", "c");
2044 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2048 optype = operandType (IC_LEFT (ic));
2050 /* if float then do float stuff */
2051 if (IS_FLOAT (optype))
2053 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2057 /* otherwise subtract from zero */
2058 size = AOP_SIZE (IC_LEFT (ic));
2062 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2063 if (!strcmp (l, "a"))
2067 emitcode ("cpl", "a");
2068 emitcode ("addc", "a,#0");
2074 emitcode ("clr", "a");
2075 emitcode ("subb", "a,%s", l);
2077 aopPut (IC_RESULT (ic), "a", offset++);
2080 /* if any remaining bytes in the result */
2081 /* we just need to propagate the sign */
2082 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2084 emitcode ("rlc", "a");
2085 emitcode ("subb", "a,acc");
2087 aopPut (IC_RESULT (ic), "a", offset++);
2091 /* release the aops */
2092 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2093 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2096 /*-----------------------------------------------------------------*/
2097 /* saveRegisters - will look for a call and save the registers */
2098 /*-----------------------------------------------------------------*/
2100 saveRegisters (iCode * lic)
2107 for (ic = lic; ic; ic = ic->next)
2108 if (ic->op == CALL || ic->op == PCALL)
2113 fprintf (stderr, "found parameter push with no function call\n");
2117 /* if the registers have been saved already or don't need to be then
2121 if (IS_SYMOP(IC_LEFT(ic)) &&
2122 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2123 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2126 /* save the registers in use at this time but skip the
2127 ones for the result */
2128 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2129 mcs51_rUmaskForOp (IC_RESULT(ic)));
2132 if (options.useXstack)
2134 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2135 int nBits = bitVectnBitsOn (rsavebits);
2136 int count = bitVectnBitsOn (rsave);
2140 count = count - nBits + 1;
2141 /* remove all but the first bits as they are pushed all at once */
2142 rsave = bitVectCplAnd (rsave, rsavebits);
2143 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2148 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2149 if (reg->type == REG_BIT)
2151 emitcode ("mov", "a,%s", reg->base);
2155 emitcode ("mov", "a,%s", reg->name);
2157 emitcode ("mov", "r0,%s", spname);
2158 emitcode ("inc", "%s", spname);// allocate before use
2159 emitcode ("movx", "@r0,a");
2160 if (bitVectBitValue (rsave, R0_IDX))
2161 emitcode ("mov", "r0,a");
2163 else if (count != 0)
2165 if (bitVectBitValue (rsave, R0_IDX))
2167 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2169 emitcode ("mov", "r0,%s", spname);
2171 emitcode ("add", "a,#%d", count);
2172 emitcode ("mov", "%s,a", spname);
2173 for (i = 0; i < mcs51_nRegs; i++)
2175 if (bitVectBitValue (rsave, i))
2177 regs * reg = REG_WITH_INDEX (i);
2180 emitcode ("pop", "acc");
2181 emitcode ("push", "acc");
2183 else if (reg->type == REG_BIT)
2185 emitcode ("mov", "a,%s", reg->base);
2189 emitcode ("mov", "a,%s", reg->name);
2191 emitcode ("movx", "@r0,a");
2194 emitcode ("inc", "r0");
2198 if (bitVectBitValue (rsave, R0_IDX))
2200 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2206 bool bits_pushed = FALSE;
2207 for (i = 0; i < mcs51_nRegs; i++)
2209 if (bitVectBitValue (rsave, i))
2211 bits_pushed = pushReg (i, bits_pushed);
2217 /*-----------------------------------------------------------------*/
2218 /* unsaveRegisters - pop the pushed registers */
2219 /*-----------------------------------------------------------------*/
2221 unsaveRegisters (iCode * ic)
2226 /* restore the registers in use at this time but skip the
2227 ones for the result */
2228 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2229 mcs51_rUmaskForOp (IC_RESULT(ic)));
2231 if (options.useXstack)
2233 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2234 int nBits = bitVectnBitsOn (rsavebits);
2235 int count = bitVectnBitsOn (rsave);
2239 count = count - nBits + 1;
2240 /* remove all but the first bits as they are popped all at once */
2241 rsave = bitVectCplAnd (rsave, rsavebits);
2242 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2247 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2248 emitcode ("mov", "r0,%s", spname);
2249 emitcode ("dec", "r0");
2250 emitcode ("movx", "a,@r0");
2251 if (reg->type == REG_BIT)
2253 emitcode ("mov", "%s,a", reg->base);
2257 emitcode ("mov", "%s,a", reg->name);
2259 emitcode ("dec", "%s", spname);
2261 else if (count != 0)
2263 emitcode ("mov", "r0,%s", spname);
2264 for (i = mcs51_nRegs; i >= 0; i--)
2266 if (bitVectBitValue (rsave, i))
2268 regs * reg = REG_WITH_INDEX (i);
2269 emitcode ("dec", "r0");
2270 emitcode ("movx", "a,@r0");
2273 emitcode ("push", "acc");
2275 else if (reg->type == REG_BIT)
2277 emitcode ("mov", "%s,a", reg->base);
2281 emitcode ("mov", "%s,a", reg->name);
2285 emitcode ("mov", "%s,r0", spname);
2286 if (bitVectBitValue (rsave, R0_IDX))
2288 emitcode ("pop", "ar0");
2294 bool bits_popped = FALSE;
2295 for (i = mcs51_nRegs; i >= 0; i--)
2297 if (bitVectBitValue (rsave, i))
2299 bits_popped = popReg (i, bits_popped);
2306 /*-----------------------------------------------------------------*/
2308 /*-----------------------------------------------------------------*/
2310 pushSide (operand * oper, int size)
2315 char *l = aopGet (oper, offset++, FALSE, TRUE);
2316 if (AOP_TYPE (oper) != AOP_REG &&
2317 AOP_TYPE (oper) != AOP_DIR &&
2321 emitcode ("push", "acc");
2325 emitcode ("push", "%s", l);
2330 /*-----------------------------------------------------------------*/
2331 /* assignResultValue - also indicates if acc is in use afterwards */
2332 /*-----------------------------------------------------------------*/
2334 assignResultValue (operand * oper, operand * func)
2337 int size = AOP_SIZE (oper);
2338 bool accuse = FALSE;
2339 bool pushedA = FALSE;
2341 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2347 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2349 emitcode ("push", "acc");
2354 if ((offset == 3) && pushedA)
2355 emitcode ("pop", "acc");
2356 accuse |= aopPut (oper, fReturn[offset], offset);
2363 /*-----------------------------------------------------------------*/
2364 /* genXpush - pushes onto the external stack */
2365 /*-----------------------------------------------------------------*/
2367 genXpush (iCode * ic)
2369 asmop *aop = newAsmop (0);
2371 int size, offset = 0;
2373 D (emitcode (";", "genXpush"));
2375 aopOp (IC_LEFT (ic), ic, FALSE);
2376 r = getFreePtr (ic, &aop, FALSE);
2378 size = AOP_SIZE (IC_LEFT (ic));
2382 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2383 emitcode ("mov", "%s,%s", r->name, spname);
2384 emitcode ("inc", "%s", spname); // allocate space first
2385 emitcode ("movx", "@%s,a", r->name);
2389 // allocate space first
2390 emitcode ("mov", "%s,%s", r->name, spname);
2392 emitcode ("add", "a,#%d", size);
2393 emitcode ("mov", "%s,a", spname);
2397 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2398 emitcode ("movx", "@%s,a", r->name);
2399 emitcode ("inc", "%s", r->name);
2403 freeAsmop (NULL, aop, ic, TRUE);
2404 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* genIpush - generate code for pushing this gets a little complex */
2409 /*-----------------------------------------------------------------*/
2411 genIpush (iCode * ic)
2413 int size, offset = 0;
2417 D (emitcode (";", "genIpush"));
2419 /* if this is not a parm push : ie. it is spill push
2420 and spill push is always done on the local stack */
2424 /* and the item is spilt then do nothing */
2425 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2428 aopOp (IC_LEFT (ic), ic, FALSE);
2429 size = AOP_SIZE (IC_LEFT (ic));
2430 /* push it on the stack */
2433 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2439 emitcode ("push", "%s", l);
2444 /* this is a parameter push: in this case we call
2445 the routine to find the call and save those
2446 registers that need to be saved */
2449 /* if use external stack then call the external
2450 stack pushing routine */
2451 if (options.useXstack)
2457 /* then do the push */
2458 aopOp (IC_LEFT (ic), ic, FALSE);
2460 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2461 size = AOP_SIZE (IC_LEFT (ic));
2465 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2466 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2467 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2469 if (strcmp (l, prev) || *l == '@')
2471 emitcode ("push", "acc");
2475 emitcode ("push", "%s", l);
2480 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2483 /*-----------------------------------------------------------------*/
2484 /* genIpop - recover the registers: can happen only for spilling */
2485 /*-----------------------------------------------------------------*/
2487 genIpop (iCode * ic)
2491 D (emitcode (";", "genIpop"));
2493 /* if the temp was not pushed then */
2494 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2497 aopOp (IC_LEFT (ic), ic, FALSE);
2498 size = AOP_SIZE (IC_LEFT (ic));
2499 offset = (size - 1);
2502 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2506 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2509 /*-----------------------------------------------------------------*/
2510 /* saveRBank - saves an entire register bank on the stack */
2511 /*-----------------------------------------------------------------*/
2513 saveRBank (int bank, iCode * ic, bool pushPsw)
2516 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2520 if (options.useXstack)
2524 /* Assume r0 is available for use. */
2525 r = REG_WITH_INDEX (R0_IDX);;
2530 r = getFreePtr (ic, &aop, FALSE);
2532 // allocate space first
2533 emitcode ("mov", "%s,%s", r->name, spname);
2535 emitcode ("add", "a,#%d", count);
2536 emitcode ("mov", "%s,a", spname);
2539 for (i = 0; i < 8; i++)
2541 if (options.useXstack)
2543 emitcode ("mov", "a,(%s+%d)",
2544 regs8051[i].base, 8 * bank + regs8051[i].offset);
2545 emitcode ("movx", "@%s,a", r->name);
2547 emitcode ("inc", "%s", r->name);
2550 emitcode ("push", "(%s+%d)",
2551 regs8051[i].base, 8 * bank + regs8051[i].offset);
2554 if (mcs51_nRegs > 8)
2556 if (options.useXstack)
2558 emitcode ("mov", "a,bits");
2559 emitcode ("movx", "@%s,a", r->name);
2561 emitcode ("inc", "%s", r->name);
2565 emitcode ("push", "bits");
2572 if (options.useXstack)
2574 emitcode ("mov", "a,psw");
2575 emitcode ("movx", "@%s,a", r->name);
2579 emitcode ("push", "psw");
2582 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2587 freeAsmop (NULL, aop, ic, TRUE);
2596 /*-----------------------------------------------------------------*/
2597 /* unsaveRBank - restores the register bank from stack */
2598 /*-----------------------------------------------------------------*/
2600 unsaveRBank (int bank, iCode * ic, bool popPsw)
2606 if (options.useXstack)
2610 /* Assume r0 is available for use. */
2611 r = REG_WITH_INDEX (R0_IDX);;
2616 r = getFreePtr (ic, &aop, FALSE);
2618 emitcode ("mov", "%s,%s", r->name, spname);
2623 if (options.useXstack)
2625 emitcode ("dec", "%s", r->name);
2626 emitcode ("movx", "a,@%s", r->name);
2627 emitcode ("mov", "psw,a");
2631 emitcode ("pop", "psw");
2635 if (mcs51_nRegs > 8)
2637 if (options.useXstack)
2639 emitcode ("dec", "%s", r->name);
2640 emitcode ("movx", "a,@%s", r->name);
2641 emitcode ("mov", "bits,a");
2645 emitcode ("pop", "bits");
2649 for (i = 7; i >= 0; i--)
2651 if (options.useXstack)
2653 emitcode ("dec", "%s", r->name);
2654 emitcode ("movx", "a,@%s", r->name);
2655 emitcode ("mov", "(%s+%d),a",
2656 regs8051[i].base, 8 * bank + regs8051[i].offset);
2660 emitcode ("pop", "(%s+%d)",
2661 regs8051[i].base, 8 * bank + regs8051[i].offset);
2665 if (options.useXstack)
2667 emitcode ("mov", "%s,%s", spname, r->name);
2672 freeAsmop (NULL, aop, ic, TRUE);
2676 /*-----------------------------------------------------------------*/
2677 /* genSend - gen code for SEND */
2678 /*-----------------------------------------------------------------*/
2679 static void genSend(set *sendSet)
2684 /* first we do all bit parameters */
2685 for (sic = setFirstItem (sendSet); sic;
2686 sic = setNextItem (sendSet))
2688 if (sic->argreg > 12)
2690 int bit = sic->argreg-13;
2692 aopOp (IC_LEFT (sic), sic, FALSE);
2694 /* if left is a literal then
2695 we know what the value is */
2696 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2698 if (((int) operandLitValue (IC_LEFT (sic))))
2699 emitcode ("setb", "b[%d]", bit);
2701 emitcode ("clr", "b[%d]", bit);
2703 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2705 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2706 if (strcmp (l, "c"))
2707 emitcode ("mov", "c,%s", l);
2708 emitcode ("mov", "b[%d],c", bit);
2713 toBoolean (IC_LEFT (sic));
2714 /* set C, if a >= 1 */
2715 emitcode ("add", "a,#0xff");
2716 emitcode ("mov", "b[%d],c", bit);
2721 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2727 saveRegisters (setFirstItem (sendSet));
2728 emitcode ("mov", "bits,b");
2731 /* then we do all other parameters */
2732 for (sic = setFirstItem (sendSet); sic;
2733 sic = setNextItem (sendSet))
2735 if (sic->argreg <= 12)
2737 int size, offset = 0;
2738 aopOp (IC_LEFT (sic), sic, FALSE);
2739 size = AOP_SIZE (IC_LEFT (sic));
2741 if (sic->argreg == 1)
2745 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2746 if (strcmp (l, fReturn[offset]))
2748 emitcode ("mov", "%s,%s", fReturn[offset], l);
2757 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2758 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2762 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2767 /*-----------------------------------------------------------------*/
2768 /* selectRegBank - emit code to select the register bank */
2769 /*-----------------------------------------------------------------*/
2771 selectRegBank (short bank, bool keepFlags)
2773 /* if f.e. result is in carry */
2776 emitcode ("anl", "psw,#0xE7");
2778 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2782 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2786 /*-----------------------------------------------------------------*/
2787 /* genCall - generates a call statement */
2788 /*-----------------------------------------------------------------*/
2790 genCall (iCode * ic)
2794 // bool restoreBank = FALSE;
2795 bool swapBanks = FALSE;
2796 bool accuse = FALSE;
2797 bool accPushed = FALSE;
2798 bool resultInF0 = FALSE;
2799 bool assignResultGenerated = FALSE;
2801 D (emitcode (";", "genCall"));
2803 dtype = operandType (IC_LEFT (ic));
2804 etype = getSpec(dtype);
2805 /* if send set is not empty then assign */
2808 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2809 genSend(reverseSet(_G.sendSet));
2811 genSend(_G.sendSet);
2816 /* if we are calling a not _naked function that is not using
2817 the same register bank then we need to save the
2818 destination registers on the stack */
2819 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2820 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2821 !IFFUNC_ISISR (dtype))
2826 /* if caller saves & we have not saved then */
2832 emitcode ("mov", "psw,#0x%02x",
2833 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2837 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2839 if (IFFUNC_CALLEESAVES(dtype))
2841 werror (E_BANKED_WITH_CALLEESAVES);
2845 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2846 OP_SYMBOL (IC_LEFT (ic))->rname :
2847 OP_SYMBOL (IC_LEFT (ic))->name);
2849 emitcode ("mov", "r0,#%s", l);
2850 emitcode ("mov", "r1,#(%s >> 8)", l);
2851 emitcode ("mov", "r2,#(%s >> 16)", l);
2852 emitcode ("lcall", "__sdcc_banked_call");
2857 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2858 OP_SYMBOL (IC_LEFT (ic))->rname :
2859 OP_SYMBOL (IC_LEFT (ic))->name));
2864 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2867 /* if we need assign a result value */
2868 if ((IS_ITEMP (IC_RESULT (ic)) &&
2869 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2870 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2871 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2872 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2873 IS_TRUE_SYMOP (IC_RESULT (ic)))
2877 aopOp (IC_RESULT (ic), ic, FALSE);
2880 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2881 assignResultGenerated = TRUE;
2883 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2886 /* adjust the stack for parameters if required */
2890 if (ic->parmBytes > 3)
2894 emitcode ("push", "acc");
2897 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2898 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2899 !assignResultGenerated)
2901 emitcode ("mov", "F0,c");
2905 emitcode ("mov", "a,%s", spname);
2906 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2907 emitcode ("mov", "%s,a", spname);
2909 /* unsaveRegisters from xstack needs acc, but */
2910 /* unsaveRegisters from stack needs this popped */
2911 if (accPushed && !options.useXstack)
2913 emitcode ("pop", "acc");
2918 for (i = 0; i < ic->parmBytes; i++)
2919 emitcode ("dec", "%s", spname);
2922 /* if we had saved some registers then unsave them */
2923 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2925 if (accuse && !accPushed && options.useXstack)
2927 /* xstack needs acc, but doesn't touch normal stack */
2928 emitcode ("push", "acc");
2931 unsaveRegisters (ic);
2934 // /* if register bank was saved then pop them */
2936 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2938 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2941 emitcode ("mov", "c,F0");
2943 aopOp (IC_RESULT (ic), ic, FALSE);
2944 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2949 emitcode ("pop", "acc");
2952 /*-----------------------------------------------------------------*/
2953 /* genPcall - generates a call by pointer statement */
2954 /*-----------------------------------------------------------------*/
2956 genPcall (iCode * ic)
2960 symbol *rlbl = newiTempLabel (NULL);
2961 // bool restoreBank=FALSE;
2962 bool swapBanks = FALSE;
2963 bool resultInF0 = FALSE;
2965 D (emitcode (";", "genPcall"));
2967 dtype = operandType (IC_LEFT (ic))->next;
2968 etype = getSpec(dtype);
2969 /* if caller saves & we have not saved then */
2973 /* if we are calling a not _naked function that is not using
2974 the same register bank then we need to save the
2975 destination registers on the stack */
2976 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2977 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2978 !IFFUNC_ISISR (dtype))
2980 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2981 // restoreBank=TRUE;
2983 // need caution message to user here
2986 if (IS_LITERAL(etype))
2988 /* if send set is not empty then assign */
2991 genSend(reverseSet(_G.sendSet));
2997 emitcode ("mov", "psw,#0x%02x",
2998 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3001 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3003 if (IFFUNC_CALLEESAVES(dtype))
3005 werror (E_BANKED_WITH_CALLEESAVES);
3009 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3011 emitcode ("mov", "r0,#%s", l);
3012 emitcode ("mov", "r1,#(%s >> 8)", l);
3013 emitcode ("mov", "r2,#(%s >> 16)", l);
3014 emitcode ("lcall", "__sdcc_banked_call");
3019 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3024 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3026 if (IFFUNC_CALLEESAVES(dtype))
3028 werror (E_BANKED_WITH_CALLEESAVES);
3032 aopOp (IC_LEFT (ic), ic, FALSE);
3036 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3037 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3038 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3042 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3043 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3044 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3045 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3048 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3050 /* if send set is not empty then assign */
3053 genSend(reverseSet(_G.sendSet));
3059 emitcode ("mov", "psw,#0x%02x",
3060 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3064 emitcode ("lcall", "__sdcc_banked_call");
3069 /* push the return address on to the stack */
3070 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3071 emitcode ("push", "acc");
3072 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3073 emitcode ("push", "acc");
3075 /* now push the calling address */
3076 aopOp (IC_LEFT (ic), ic, FALSE);
3078 pushSide (IC_LEFT (ic), FPTRSIZE);
3080 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3082 /* if send set is not empty the assign */
3085 genSend(reverseSet(_G.sendSet));
3091 emitcode ("mov", "psw,#0x%02x",
3092 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3096 emitcode ("ret", "");
3102 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3105 /* if we need assign a result value */
3106 if ((IS_ITEMP (IC_RESULT (ic)) &&
3107 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3108 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3109 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3110 IS_TRUE_SYMOP (IC_RESULT (ic)))
3114 aopOp (IC_RESULT (ic), ic, FALSE);
3117 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3119 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3122 /* adjust the stack for parameters if required */
3126 if (ic->parmBytes > 3)
3128 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3129 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3131 emitcode ("mov", "F0,c");
3135 emitcode ("mov", "a,%s", spname);
3136 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3137 emitcode ("mov", "%s,a", spname);
3140 for (i = 0; i < ic->parmBytes; i++)
3141 emitcode ("dec", "%s", spname);
3144 // /* if register bank was saved then unsave them */
3146 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3148 /* if we had saved some registers then unsave them */
3149 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3150 unsaveRegisters (ic);
3152 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3155 emitcode ("mov", "c,F0");
3157 aopOp (IC_RESULT (ic), ic, FALSE);
3158 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3159 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3163 /*-----------------------------------------------------------------*/
3164 /* resultRemat - result is rematerializable */
3165 /*-----------------------------------------------------------------*/
3167 resultRemat (iCode * ic)
3169 if (SKIP_IC (ic) || ic->op == IFX)
3172 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3174 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3175 if (sym->remat && !POINTER_SET (ic))
3182 #if defined(__BORLANDC__) || defined(_MSC_VER)
3183 #define STRCASECMP stricmp
3185 #define STRCASECMP strcasecmp
3188 /*-----------------------------------------------------------------*/
3189 /* inExcludeList - return 1 if the string is in exclude Reg list */
3190 /*-----------------------------------------------------------------*/
3192 regsCmp(void *p1, void *p2)
3194 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3198 inExcludeList (char *s)
3200 const char *p = setFirstItem(options.excludeRegsSet);
3202 if (p == NULL || STRCASECMP(p, "none") == 0)
3206 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3209 /*-----------------------------------------------------------------*/
3210 /* genFunction - generated code for function entry */
3211 /*-----------------------------------------------------------------*/
3213 genFunction (iCode * ic)
3215 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3217 bool switchedPSW = FALSE;
3218 int calleesaves_saved_register = -1;
3219 int stackAdjust = sym->stack;
3220 int accIsFree = sym->recvSize < 4;
3221 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3222 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3225 /* create the function header */
3226 emitcode (";", "-----------------------------------------");
3227 emitcode (";", " function %s", sym->name);
3228 emitcode (";", "-----------------------------------------");
3230 emitcode ("", "%s:", sym->rname);
3231 ftype = operandType (IC_LEFT (ic));
3232 _G.currentFunc = sym;
3234 if (IFFUNC_ISNAKED(ftype))
3236 emitcode(";", "naked function: no prologue.");
3240 /* here we need to generate the equates for the
3241 register bank if required */
3242 if (FUNC_REGBANK (ftype) != rbank)
3246 rbank = FUNC_REGBANK (ftype);
3247 for (i = 0; i < mcs51_nRegs; i++)
3249 if (regs8051[i].type != REG_BIT)
3251 if (strcmp (regs8051[i].base, "0") == 0)
3252 emitcode ("", "%s = 0x%02x",
3254 8 * rbank + regs8051[i].offset);
3256 emitcode ("", "%s = %s + 0x%02x",
3259 8 * rbank + regs8051[i].offset);
3264 /* if this is an interrupt service routine then
3265 save acc, b, dpl, dph */
3266 if (IFFUNC_ISISR (sym->type))
3268 if (!inExcludeList ("acc"))
3269 emitcode ("push", "acc");
3270 if (!inExcludeList ("b"))
3271 emitcode ("push", "b");
3272 if (!inExcludeList ("dpl"))
3273 emitcode ("push", "dpl");
3274 if (!inExcludeList ("dph"))
3275 emitcode ("push", "dph");
3276 /* if this isr has no bank i.e. is going to
3277 run with bank 0 , then we need to save more
3279 if (!FUNC_REGBANK (sym->type))
3283 /* if this function does not call any other
3284 function then we can be economical and
3285 save only those registers that are used */
3286 if (!IFFUNC_HASFCALL(sym->type))
3288 /* if any registers used */
3291 bool bits_pushed = FALSE;
3292 /* save the registers used */
3293 for (i = 0; i < sym->regsUsed->size; i++)
3295 if (bitVectBitValue (sym->regsUsed, i))
3296 bits_pushed = pushReg (i, bits_pushed);
3302 /* this function has a function call. We cannot
3303 determine register usage so we will have to push the
3305 saveRBank (0, ic, FALSE);
3306 if (options.parms_in_bank1) {
3307 for (i=0; i < 8 ; i++ ) {
3308 emitcode ("push","%s",rb1regs[i]);
3315 /* This ISR uses a non-zero bank.
3317 * We assume that the bank is available for our
3320 * However, if this ISR calls a function which uses some
3321 * other bank, we must save that bank entirely.
3323 unsigned long banksToSave = 0;
3325 if (IFFUNC_HASFCALL(sym->type))
3328 #define MAX_REGISTER_BANKS 4
3333 for (i = ic; i; i = i->next)
3335 if (i->op == ENDFUNCTION)
3337 /* we got to the end OK. */
3345 dtype = operandType (IC_LEFT(i));
3347 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3349 /* Mark this bank for saving. */
3350 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3352 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3356 banksToSave |= (1 << FUNC_REGBANK(dtype));
3359 /* And note that we don't need to do it in
3367 /* This is a mess; we have no idea what
3368 * register bank the called function might
3371 * The only thing I can think of to do is
3372 * throw a warning and hope.
3374 werror(W_FUNCPTR_IN_USING_ISR);
3378 if (banksToSave && options.useXstack)
3380 /* Since we aren't passing it an ic,
3381 * saveRBank will assume r0 is available to abuse.
3383 * So switch to our (trashable) bank now, so
3384 * the caller's R0 isn't trashed.
3386 emitcode ("push", "psw");
3387 emitcode ("mov", "psw,#0x%02x",
3388 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3392 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3394 if (banksToSave & (1 << ix))
3396 saveRBank(ix, NULL, FALSE);
3400 // TODO: this needs a closer look
3401 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3404 /* Set the register bank to the desired value if nothing else */
3405 /* has done so yet. */
3408 emitcode ("push", "psw");
3409 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3414 /* This is a non-ISR function. The caller has already switched register */
3415 /* banks, if necessary, so just handle the callee-saves option. */
3417 /* if callee-save to be used for this function
3418 then save the registers being used in this function */
3419 if (IFFUNC_CALLEESAVES(sym->type))
3423 /* if any registers used */
3426 bool bits_pushed = FALSE;
3427 /* save the registers used */
3428 for (i = 0; i < sym->regsUsed->size; i++)
3430 if (bitVectBitValue (sym->regsUsed, i))
3432 /* remember one saved register for later usage */
3433 if (calleesaves_saved_register < 0)
3434 calleesaves_saved_register = i;
3435 bits_pushed = pushReg (i, bits_pushed);
3446 if (options.useXstack)
3448 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3450 emitcode ("mov", "r0,%s", spname);
3451 emitcode ("inc", "%s", spname);
3452 emitcode ("xch", "a,_bpx");
3453 emitcode ("movx", "@r0,a");
3454 emitcode ("inc", "r0");
3455 emitcode ("mov", "a,r0");
3456 emitcode ("xch", "a,_bpx");
3460 emitcode ("push", "_bp"); /* save the callers stack */
3461 emitcode ("mov", "_bp,sp");
3466 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3468 /* set up the stack */
3469 emitcode ("push", "_bp"); /* save the callers stack */
3470 emitcode ("mov", "_bp,sp");
3475 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3476 /* before setting up the stack frame completely. */
3477 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3479 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3483 if (rsym && rsym->regType == REG_CND)
3485 if (rsym && (rsym->accuse || rsym->ruonly))
3487 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3488 rsym = rsym->usl.spillLoc;
3491 /* If the RECEIVE operand immediately spills to the first entry on the */
3492 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3493 /* rather than the usual @r0/r1 machinations. */
3494 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3498 _G.current_iCode = ric;
3499 D(emitcode ("; genReceive",""));
3500 for (ofs=0; ofs < sym->recvSize; ofs++)
3502 if (!strcmp (fReturn[ofs], "a"))
3503 emitcode ("push", "acc");
3505 emitcode ("push", fReturn[ofs]);
3507 stackAdjust -= sym->recvSize;
3510 assert (stackAdjust>=0);
3513 _G.current_iCode = ic;
3517 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3518 /* to free up the accumulator. */
3519 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3523 _G.current_iCode = ric;
3524 D(emitcode ("; genReceive",""));
3525 for (ofs=0; ofs < sym->recvSize; ofs++)
3527 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3529 _G.current_iCode = ic;
3535 /* adjust the stack for the function */
3538 int i = stackAdjust;
3540 werror (W_STACK_OVERFLOW, sym->name);
3542 if (i > 3 && accIsFree)
3544 emitcode ("mov", "a,sp");
3545 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3546 emitcode ("mov", "sp,a");
3550 /* The accumulator is not free, so we will need another register */
3551 /* to clobber. No need to worry about a possible conflict with */
3552 /* the above early RECEIVE optimizations since they would have */
3553 /* freed the accumulator if they were generated. */
3555 if (IFFUNC_CALLEESAVES(sym->type))
3557 /* if it's a callee-saves function we need a saved register */
3558 if (calleesaves_saved_register >= 0)
3560 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3561 emitcode ("mov", "a,sp");
3562 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3563 emitcode ("mov", "sp,a");
3564 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3567 /* do it the hard way */
3569 emitcode ("inc", "sp");
3573 /* not callee-saves, we can clobber r0 */
3574 emitcode ("mov", "r0,a");
3575 emitcode ("mov", "a,sp");
3576 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3577 emitcode ("mov", "sp,a");
3578 emitcode ("mov", "a,r0");
3583 emitcode ("inc", "sp");
3588 char i = ((char) sym->xstack & 0xff);
3590 if (i > 3 && accIsFree)
3592 emitcode ("mov", "a,_spx");
3593 emitcode ("add", "a,#0x%02x", i);
3594 emitcode ("mov", "_spx,a");
3598 emitcode ("push", "acc");
3599 emitcode ("mov", "a,_spx");
3600 emitcode ("add", "a,#0x%02x", i);
3601 emitcode ("mov", "_spx,a");
3602 emitcode ("pop", "acc");
3607 emitcode ("inc", "_spx");
3611 /* if critical function then turn interrupts off */
3612 if (IFFUNC_ISCRITICAL (ftype))
3614 symbol *tlbl = newiTempLabel (NULL);
3615 emitcode ("setb", "c");
3616 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3617 emitcode ("clr", "c");
3619 emitcode ("push", "psw"); /* save old ea via c in psw */
3623 /*-----------------------------------------------------------------*/
3624 /* genEndFunction - generates epilogue for functions */
3625 /*-----------------------------------------------------------------*/
3627 genEndFunction (iCode * ic)
3629 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3630 lineNode *lnp = lineCurr;
3632 bitVect *regsUsedPrologue;
3633 bitVect *regsUnneeded;
3636 _G.currentFunc = NULL;
3637 if (IFFUNC_ISNAKED(sym->type))
3639 emitcode(";", "naked function: no epilogue.");
3640 if (options.debug && currFunc)
3641 debugFile->writeEndFunction (currFunc, ic, 0);
3645 if (IFFUNC_ISCRITICAL (sym->type))
3647 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3649 emitcode ("rlc", "a"); /* save c in a */
3650 emitcode ("pop", "psw"); /* restore ea via c in psw */
3651 emitcode ("mov", "ea,c");
3652 emitcode ("rrc", "a"); /* restore c from a */
3656 emitcode ("pop", "psw"); /* restore ea via c in psw */
3657 emitcode ("mov", "ea,c");
3661 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3663 if (options.useXstack)
3667 emitcode ("mov", "sp,_bp");
3668 emitcode ("pop", "_bp");
3670 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3672 emitcode ("xch", "a,_bpx");
3673 emitcode ("mov", "r0,a");
3674 emitcode ("dec", "r0");
3675 emitcode ("movx", "a,@r0");
3676 emitcode ("xch", "a,_bpx");
3677 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3680 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3683 emitcode ("mov", "sp,_bp");
3684 emitcode ("pop", "_bp");
3688 /* restore the register bank */
3689 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3691 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3692 || !options.useXstack)
3694 /* Special case of ISR using non-zero bank with useXstack
3697 emitcode ("pop", "psw");
3701 if (IFFUNC_ISISR (sym->type))
3704 /* now we need to restore the registers */
3705 /* if this isr has no bank i.e. is going to
3706 run with bank 0 , then we need to save more
3708 if (!FUNC_REGBANK (sym->type))
3711 /* if this function does not call any other
3712 function then we can be economical and
3713 save only those registers that are used */
3714 if (!IFFUNC_HASFCALL(sym->type))
3716 /* if any registers used */
3719 bool bits_popped = FALSE;
3720 /* save the registers used */
3721 for (i = sym->regsUsed->size; i >= 0; i--)
3723 if (bitVectBitValue (sym->regsUsed, i))
3724 bits_popped = popReg (i, bits_popped);
3730 if (options.parms_in_bank1) {
3731 for (i = 7 ; i >= 0 ; i-- ) {
3732 emitcode ("pop","%s",rb1regs[i]);
3735 /* this function has a function call cannot
3736 determines register usage so we will have to pop the
3738 unsaveRBank (0, ic, FALSE);
3743 /* This ISR uses a non-zero bank.
3745 * Restore any register banks saved by genFunction
3748 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3751 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3753 if (savedBanks & (1 << ix))
3755 unsaveRBank(ix, NULL, FALSE);
3759 if (options.useXstack)
3761 /* Restore bank AFTER calling unsaveRBank,
3762 * since it can trash r0.
3764 emitcode ("pop", "psw");
3768 if (!inExcludeList ("dph"))
3769 emitcode ("pop", "dph");
3770 if (!inExcludeList ("dpl"))
3771 emitcode ("pop", "dpl");
3772 if (!inExcludeList ("b"))
3773 emitcode ("pop", "b");
3774 if (!inExcludeList ("acc"))
3775 emitcode ("pop", "acc");
3777 /* if debug then send end of function */
3778 if (options.debug && currFunc)
3780 debugFile->writeEndFunction (currFunc, ic, 1);
3783 emitcode ("reti", "");
3787 if (IFFUNC_CALLEESAVES(sym->type))
3791 /* if any registers used */
3794 /* save the registers used */
3795 for (i = sym->regsUsed->size; i >= 0; i--)
3797 if (bitVectBitValue (sym->regsUsed, i) ||
3798 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3799 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3802 else if (mcs51_ptrRegReq)
3804 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3805 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3810 /* if debug then send end of function */
3811 if (options.debug && currFunc)
3813 debugFile->writeEndFunction (currFunc, ic, 1);
3816 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3818 emitcode ("ljmp", "__sdcc_banked_ret");
3822 emitcode ("ret", "");
3826 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3829 /* If this was an interrupt handler using bank 0 that called another */
3830 /* function, then all registers must be saved; nothing to optimized. */
3831 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3832 && !FUNC_REGBANK(sym->type))
3835 /* There are no push/pops to optimize if not callee-saves or ISR */
3836 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3839 /* If there were stack parameters, we cannot optimize without also */
3840 /* fixing all of the stack offsets; this is too dificult to consider. */
3841 if (FUNC_HASSTACKPARM(sym->type))
3844 /* Compute the registers actually used */
3845 regsUsed = newBitVect (mcs51_nRegs);
3846 regsUsedPrologue = newBitVect (mcs51_nRegs);
3849 if (lnp->ic && lnp->ic->op == FUNCTION)
3850 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3852 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3854 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3855 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3862 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3863 && !bitVectBitValue (regsUsed, CND_IDX))
3865 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3866 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3867 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3868 bitVectUnSetBit (regsUsed, CND_IDX);
3871 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3873 /* If this was an interrupt handler that called another function */
3874 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3875 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3877 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3878 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3879 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3880 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3881 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3884 /* Remove the unneeded push/pops */
3885 regsUnneeded = newBitVect (mcs51_nRegs);
3888 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3890 if (!strncmp(lnp->line, "push", 4))
3892 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3893 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3895 connectLine (lnp->prev, lnp->next);
3896 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3899 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3901 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3902 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3904 connectLine (lnp->prev, lnp->next);
3905 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3912 for (idx = 0; idx < regsUnneeded->size; idx++)
3913 if (bitVectBitValue (regsUnneeded, idx))
3914 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3916 freeBitVect (regsUnneeded);
3917 freeBitVect (regsUsed);
3918 freeBitVect (regsUsedPrologue);
3921 /*-----------------------------------------------------------------*/
3922 /* genRet - generate code for return statement */
3923 /*-----------------------------------------------------------------*/
3927 int size, offset = 0, pushed = 0;
3929 D (emitcode (";", "genRet"));
3931 /* if we have no return value then
3932 just generate the "ret" */
3936 /* we have something to return then
3937 move the return value into place */
3938 aopOp (IC_LEFT (ic), ic, FALSE);
3939 size = AOP_SIZE (IC_LEFT (ic));
3941 if (IS_BIT(_G.currentFunc->etype))
3943 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3950 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3953 l = aopGet (IC_LEFT (ic), offset++,
3955 emitcode ("push", "%s", l);
3960 l = aopGet (IC_LEFT (ic), offset,
3962 if (strcmp (fReturn[offset], l))
3963 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3970 if (strcmp (fReturn[pushed], "a"))
3971 emitcode ("pop", fReturn[pushed]);
3973 emitcode ("pop", "acc");
3975 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3978 /* generate a jump to the return label
3979 if the next is not the return statement */
3980 if (!(ic->next && ic->next->op == LABEL &&
3981 IC_LABEL (ic->next) == returnLabel))
3983 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3987 /*-----------------------------------------------------------------*/
3988 /* genLabel - generates a label */
3989 /*-----------------------------------------------------------------*/
3991 genLabel (iCode * ic)
3993 /* special case never generate */
3994 if (IC_LABEL (ic) == entryLabel)
3997 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4000 /*-----------------------------------------------------------------*/
4001 /* genGoto - generates a ljmp */
4002 /*-----------------------------------------------------------------*/
4004 genGoto (iCode * ic)
4006 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4009 /*-----------------------------------------------------------------*/
4010 /* findLabelBackwards: walks back through the iCode chain looking */
4011 /* for the given label. Returns number of iCode instructions */
4012 /* between that label and given ic. */
4013 /* Returns zero if label not found. */
4014 /*-----------------------------------------------------------------*/
4016 findLabelBackwards (iCode * ic, int key)
4025 /* If we have any pushes or pops, we cannot predict the distance.
4026 I don't like this at all, this should be dealt with in the
4028 if (ic->op == IPUSH || ic->op == IPOP) {
4032 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusIncr :- does addition with increment if possible */
4043 /*-----------------------------------------------------------------*/
4045 genPlusIncr (iCode * ic)
4047 unsigned int icount;
4048 unsigned int size = getDataSize (IC_RESULT (ic));
4050 /* will try to generate an increment */
4051 /* if the right side is not a literal
4053 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4056 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4058 D(emitcode ("; genPlusIncr",""));
4060 /* if increment >=16 bits in register or direct space */
4061 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4062 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4063 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4071 /* If the next instruction is a goto and the goto target
4072 * is < 10 instructions previous to this, we can generate
4073 * jumps straight to that target.
4075 if (ic->next && ic->next->op == GOTO
4076 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4077 && labelRange <= 10)
4079 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4080 tlbl = IC_LABEL (ic->next);
4085 tlbl = newiTempLabel (NULL);
4088 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4089 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4090 IS_AOP_PREG (IC_RESULT (ic)))
4091 emitcode ("cjne", "%s,#0x00,%05d$",
4092 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4096 emitcode ("clr", "a");
4097 emitcode ("cjne", "a,%s,%05d$",
4098 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4102 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4105 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4106 IS_AOP_PREG (IC_RESULT (ic)))
4107 emitcode ("cjne", "%s,#0x00,%05d$",
4108 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4111 emitcode ("cjne", "a,%s,%05d$",
4112 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4115 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4119 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4120 IS_AOP_PREG (IC_RESULT (ic)))
4121 emitcode ("cjne", "%s,#0x00,%05d$",
4122 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4126 emitcode ("cjne", "a,%s,%05d$",
4127 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4130 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4140 /* if result is dptr */
4141 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4142 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4143 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4144 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4146 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4152 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4155 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4156 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4158 emitcode ("inc", "dptr");
4163 /* if the literal value of the right hand side
4164 is greater than 4 then it is not worth it */
4168 /* if the sizes are greater than 1 then we cannot */
4169 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4170 AOP_SIZE (IC_LEFT (ic)) > 1)
4173 /* we can if the aops of the left & result match or
4174 if they are in registers and the registers are the
4176 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4180 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4181 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4182 aopPut (IC_RESULT (ic), "a", 0);
4188 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4198 /*-----------------------------------------------------------------*/
4199 /* outBitAcc - output a bit in acc */
4200 /*-----------------------------------------------------------------*/
4202 outBitAcc (operand * result)
4204 symbol *tlbl = newiTempLabel (NULL);
4205 /* if the result is a bit */
4206 if (AOP_TYPE (result) == AOP_CRY)
4208 aopPut (result, "a", 0);
4212 emitcode ("jz", "%05d$", tlbl->key + 100);
4213 emitcode ("mov", "a,%s", one);
4219 /*-----------------------------------------------------------------*/
4220 /* genPlusBits - generates code for addition of two bits */
4221 /*-----------------------------------------------------------------*/
4223 genPlusBits (iCode * ic)
4225 D (emitcode (";", "genPlusBits"));
4227 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4229 symbol *lbl = newiTempLabel (NULL);
4230 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4231 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4232 emitcode ("cpl", "c");
4234 outBitC (IC_RESULT (ic));
4238 emitcode ("clr", "a");
4239 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4240 emitcode ("rlc", "a");
4241 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4242 emitcode ("addc", "a,#0x00");
4243 outAcc (IC_RESULT (ic));
4248 /* This is the original version of this code.
4250 * This is being kept around for reference,
4251 * because I am not entirely sure I got it right...
4254 adjustArithmeticResult (iCode * ic)
4256 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4257 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4258 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4259 aopPut (IC_RESULT (ic),
4260 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4263 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4264 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4265 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4266 aopPut (IC_RESULT (ic),
4267 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4270 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4271 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4272 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4273 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4274 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4277 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4278 aopPut (IC_RESULT (ic), buffer, 2);
4282 /* This is the pure and virtuous version of this code.
4283 * I'm pretty certain it's right, but not enough to toss the old
4287 adjustArithmeticResult (iCode * ic)
4289 if (opIsGptr (IC_RESULT (ic)) &&
4290 opIsGptr (IC_LEFT (ic)) &&
4291 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4293 aopPut (IC_RESULT (ic),
4294 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4298 if (opIsGptr (IC_RESULT (ic)) &&
4299 opIsGptr (IC_RIGHT (ic)) &&
4300 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302 aopPut (IC_RESULT (ic),
4303 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4307 if (opIsGptr (IC_RESULT (ic)) &&
4308 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4309 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4310 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4311 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4314 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315 aopPut (IC_RESULT (ic), buffer, 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,#00");
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");
5757 bool pushedB = FALSE;
5758 rightInB = aopGetUsesAcc(right, offset);
5762 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5764 MOVA (aopGet (left, offset, FALSE, FALSE));
5765 if (sign && size == 0)
5767 emitcode ("xrl", "a,#0x80");
5768 if (AOP_TYPE (right) == AOP_LIT)
5770 unsigned long lit = (unsigned long)
5771 floatFromVal (AOP (right)->aopu.aop_lit);
5772 emitcode ("subb", "a,#0x%02x",
5773 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5781 MOVB (aopGet (right, offset, FALSE, FALSE));
5783 emitcode ("xrl", "b,#0x80");
5784 emitcode ("subb", "a,b");
5790 emitcode ("subb", "a,b");
5792 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5802 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5803 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5804 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5810 /* if the result is used in the next
5811 ifx conditional branch then generate
5812 code a little differently */
5815 genIfxJump (ifx, "c", NULL, NULL, result);
5821 /* leave the result in acc */
5825 /*-----------------------------------------------------------------*/
5826 /* genCmpGt :- greater than comparison */
5827 /*-----------------------------------------------------------------*/
5829 genCmpGt (iCode * ic, iCode * ifx)
5831 operand *left, *right, *result;
5832 sym_link *letype, *retype;
5835 D (emitcode (";", "genCmpGt"));
5837 left = IC_LEFT (ic);
5838 right = IC_RIGHT (ic);
5839 result = IC_RESULT (ic);
5841 letype = getSpec (operandType (left));
5842 retype = getSpec (operandType (right));
5843 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5844 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5845 /* assign the amsops */
5846 aopOp (result, ic, TRUE);
5847 aopOp (left, ic, FALSE);
5848 aopOp (right, ic, FALSE);
5850 genCmp (right, left, result, ifx, sign, ic);
5852 freeAsmop (result, NULL, ic, TRUE);
5855 /*-----------------------------------------------------------------*/
5856 /* genCmpLt - less than comparisons */
5857 /*-----------------------------------------------------------------*/
5859 genCmpLt (iCode * ic, iCode * ifx)
5861 operand *left, *right, *result;
5862 sym_link *letype, *retype;
5865 D (emitcode (";", "genCmpLt"));
5867 left = IC_LEFT (ic);
5868 right = IC_RIGHT (ic);
5869 result = IC_RESULT (ic);
5871 letype = getSpec (operandType (left));
5872 retype = getSpec (operandType (right));
5873 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5874 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5875 /* assign the amsops */
5876 aopOp (result, ic, TRUE);
5877 aopOp (left, ic, FALSE);
5878 aopOp (right, ic, FALSE);
5880 genCmp (left, right, result, ifx, sign, ic);
5882 freeAsmop (result, NULL, ic, TRUE);
5885 /*-----------------------------------------------------------------*/
5886 /* gencjneshort - compare and jump if not equal */
5887 /*-----------------------------------------------------------------*/
5889 gencjneshort (operand * left, operand * right, symbol * lbl)
5891 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5893 unsigned long lit = 0L;
5895 D (emitcode (";", "gencjneshort"));
5897 /* if the left side is a literal or
5898 if the right is in a pointer register and left
5900 if ((AOP_TYPE (left) == AOP_LIT) ||
5901 (AOP_TYPE (left) == AOP_IMMD) ||
5902 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5909 if (AOP_TYPE (right) == AOP_LIT)
5910 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5912 /* if the right side is a literal then anything goes */
5913 if (AOP_TYPE (right) == AOP_LIT &&
5914 AOP_TYPE (left) != AOP_DIR &&
5915 AOP_TYPE (left) != AOP_IMMD)
5919 emitcode ("cjne", "%s,%s,%05d$",
5920 aopGet (left, offset, FALSE, FALSE),
5921 aopGet (right, offset, FALSE, FALSE),
5927 /* if the right side is in a register or in direct space or
5928 if the left is a pointer register & right is not */
5929 else if (AOP_TYPE (right) == AOP_REG ||
5930 AOP_TYPE (right) == AOP_DIR ||
5931 AOP_TYPE (right) == AOP_LIT ||
5932 AOP_TYPE (right) == AOP_IMMD ||
5933 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5934 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5938 MOVA (aopGet (left, offset, FALSE, FALSE));
5939 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5940 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5941 emitcode ("jnz", "%05d$", lbl->key + 100);
5943 emitcode ("cjne", "a,%s,%05d$",
5944 aopGet (right, offset, FALSE, TRUE),
5951 /* right is a pointer reg need both a & b */
5954 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5955 wassertl(!BINUSE, "B was in use");
5956 MOVB (aopGet (left, offset, FALSE, FALSE));
5957 MOVA (aopGet (right, offset, FALSE, FALSE));
5958 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5964 /*-----------------------------------------------------------------*/
5965 /* gencjne - compare and jump if not equal */
5966 /*-----------------------------------------------------------------*/
5968 gencjne (operand * left, operand * right, symbol * lbl)
5970 symbol *tlbl = newiTempLabel (NULL);
5972 D (emitcode (";", "gencjne"));
5974 gencjneshort (left, right, lbl);
5976 emitcode ("mov", "a,%s", one);
5977 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5979 emitcode ("clr", "a");
5983 /*-----------------------------------------------------------------*/
5984 /* genCmpEq - generates code for equal to */
5985 /*-----------------------------------------------------------------*/
5987 genCmpEq (iCode * ic, iCode * ifx)
5989 bool swappedLR = FALSE;
5990 operand *left, *right, *result;
5992 D (emitcode (";", "genCmpEq"));
5994 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5995 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5996 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5998 /* if literal, literal on the right or
5999 if the right is in a pointer register and left
6001 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6002 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6004 operand *t = IC_RIGHT (ic);
6005 IC_RIGHT (ic) = IC_LEFT (ic);
6010 if (ifx && !AOP_SIZE (result))
6013 /* if they are both bit variables */
6014 if (AOP_TYPE (left) == AOP_CRY &&
6015 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6017 if (AOP_TYPE (right) == AOP_LIT)
6019 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6022 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6023 emitcode ("cpl", "c");
6027 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6031 emitcode ("clr", "c");
6033 /* AOP_TYPE(right) == AOP_CRY */
6037 symbol *lbl = newiTempLabel (NULL);
6038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6039 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6040 emitcode ("cpl", "c");
6043 /* if true label then we jump if condition
6045 tlbl = newiTempLabel (NULL);
6048 emitcode ("jnc", "%05d$", tlbl->key + 100);
6049 freeForBranchAsmop (result);
6050 freeForBranchAsmop (right);
6051 freeForBranchAsmop (left);
6052 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6056 emitcode ("jc", "%05d$", tlbl->key + 100);
6057 freeForBranchAsmop (result);
6058 freeForBranchAsmop (right);
6059 freeForBranchAsmop (left);
6060 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6066 tlbl = newiTempLabel (NULL);
6067 gencjneshort (left, right, tlbl);
6070 freeForBranchAsmop (result);
6071 freeForBranchAsmop (right);
6072 freeForBranchAsmop (left);
6073 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6078 symbol *lbl = newiTempLabel (NULL);
6079 emitcode ("sjmp", "%05d$", lbl->key + 100);
6081 freeForBranchAsmop (result);
6082 freeForBranchAsmop (right);
6083 freeForBranchAsmop (left);
6084 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6088 /* mark the icode as generated */
6093 /* if they are both bit variables */
6094 if (AOP_TYPE (left) == AOP_CRY &&
6095 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6097 if (AOP_TYPE (right) == AOP_LIT)
6099 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6102 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6103 emitcode ("cpl", "c");
6107 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6111 emitcode ("clr", "c");
6113 /* AOP_TYPE(right) == AOP_CRY */
6117 symbol *lbl = newiTempLabel (NULL);
6118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6119 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6120 emitcode ("cpl", "c");
6124 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6131 genIfxJump (ifx, "c", left, right, result);
6134 /* if the result is used in an arithmetic operation
6135 then put the result in place */
6140 gencjne (left, right, newiTempLabel (NULL));
6141 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6143 aopPut (result, "a", 0);
6148 genIfxJump (ifx, "a", left, right, result);
6151 /* if the result is used in an arithmetic operation
6152 then put the result in place */
6153 if (AOP_TYPE (result) != AOP_CRY)
6155 /* leave the result in acc */
6159 freeAsmop (result, NULL, ic, TRUE);
6162 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6163 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6167 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6168 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6172 /*-----------------------------------------------------------------*/
6173 /* ifxForOp - returns the icode containing the ifx for operand */
6174 /*-----------------------------------------------------------------*/
6176 ifxForOp (operand * op, iCode * ic)
6178 /* if true symbol then needs to be assigned */
6179 if (IS_TRUE_SYMOP (op))
6182 /* if this has register type condition and
6183 the next instruction is ifx with the same operand
6184 and live to of the operand is upto the ifx only then */
6186 ic->next->op == IFX &&
6187 IC_COND (ic->next)->key == op->key &&
6188 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6194 /*-----------------------------------------------------------------*/
6195 /* hasInc - operand is incremented before any other use */
6196 /*-----------------------------------------------------------------*/
6198 hasInc (operand *op, iCode *ic, int osize)
6200 sym_link *type = operandType(op);
6201 sym_link *retype = getSpec (type);
6202 iCode *lic = ic->next;
6205 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6206 if (!IS_SYMOP(op)) return NULL;
6208 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6209 if (IS_AGGREGATE(type->next)) return NULL;
6210 if (osize != (isize = getSize(type->next))) return NULL;
6213 /* if operand of the form op = op + <sizeof *op> */
6214 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6215 isOperandEqual(IC_RESULT(lic),op) &&
6216 isOperandLiteral(IC_RIGHT(lic)) &&
6217 operandLitValue(IC_RIGHT(lic)) == isize) {
6220 /* if the operand used or deffed */
6221 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6224 /* if GOTO or IFX */
6225 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6231 /*-----------------------------------------------------------------*/
6232 /* genAndOp - for && operation */
6233 /*-----------------------------------------------------------------*/
6235 genAndOp (iCode * ic)
6237 operand *left, *right, *result;
6240 D (emitcode (";", "genAndOp"));
6242 /* note here that && operations that are in an
6243 if statement are taken away by backPatchLabels
6244 only those used in arthmetic operations remain */
6245 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6246 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6247 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6249 /* if both are bit variables */
6250 if (AOP_TYPE (left) == AOP_CRY &&
6251 AOP_TYPE (right) == AOP_CRY)
6253 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6254 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6259 tlbl = newiTempLabel (NULL);
6261 emitcode ("jz", "%05d$", tlbl->key + 100);
6267 freeAsmop (result, NULL, ic, TRUE);
6268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6269 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6273 /*-----------------------------------------------------------------*/
6274 /* genOrOp - for || operation */
6275 /*-----------------------------------------------------------------*/
6277 genOrOp (iCode * ic)
6279 operand *left, *right, *result;
6282 D (emitcode (";", "genOrOp"));
6284 /* note here that || operations that are in an
6285 if statement are taken away by backPatchLabels
6286 only those used in arthmetic operations remain */
6287 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6288 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6289 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6291 /* if both are bit variables */
6292 if (AOP_TYPE (left) == AOP_CRY &&
6293 AOP_TYPE (right) == AOP_CRY)
6295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6301 tlbl = newiTempLabel (NULL);
6303 emitcode ("jnz", "%05d$", tlbl->key + 100);
6309 freeAsmop (result, NULL, ic, TRUE);
6310 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6311 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 /*-----------------------------------------------------------------*/
6315 /* isLiteralBit - test if lit == 2^n */
6316 /*-----------------------------------------------------------------*/
6318 isLiteralBit (unsigned long lit)
6320 unsigned long pw[32] =
6321 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6322 0x100L, 0x200L, 0x400L, 0x800L,
6323 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6324 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6325 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6326 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6327 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6330 for (idx = 0; idx < 32; idx++)
6336 /*-----------------------------------------------------------------*/
6337 /* continueIfTrue - */
6338 /*-----------------------------------------------------------------*/
6340 continueIfTrue (iCode * ic)
6343 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6347 /*-----------------------------------------------------------------*/
6349 /*-----------------------------------------------------------------*/
6351 jumpIfTrue (iCode * ic)
6354 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6358 /*-----------------------------------------------------------------*/
6359 /* jmpTrueOrFalse - */
6360 /*-----------------------------------------------------------------*/
6362 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6364 // ugly but optimized by peephole
6367 symbol *nlbl = newiTempLabel (NULL);
6368 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6370 freeForBranchAsmop (result);
6371 freeForBranchAsmop (right);
6372 freeForBranchAsmop (left);
6373 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6378 freeForBranchAsmop (result);
6379 freeForBranchAsmop (right);
6380 freeForBranchAsmop (left);
6381 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6387 /*-----------------------------------------------------------------*/
6388 /* genAnd - code for and */
6389 /*-----------------------------------------------------------------*/
6391 genAnd (iCode * ic, iCode * ifx)
6393 operand *left, *right, *result;
6394 int size, offset = 0;
6395 unsigned long lit = 0L;
6399 D (emitcode (";", "genAnd"));
6401 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6402 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6403 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6406 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6408 AOP_TYPE (left), AOP_TYPE (right));
6409 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6411 AOP_SIZE (left), AOP_SIZE (right));
6414 /* if left is a literal & right is not then exchange them */
6415 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6416 AOP_NEEDSACC (left))
6418 operand *tmp = right;
6423 /* if result = right then exchange left and right */
6424 if (sameRegs (AOP (result), AOP (right)))
6426 operand *tmp = right;
6431 /* if right is bit then exchange them */
6432 if (AOP_TYPE (right) == AOP_CRY &&
6433 AOP_TYPE (left) != AOP_CRY)
6435 operand *tmp = right;
6439 if (AOP_TYPE (right) == AOP_LIT)
6440 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6442 size = AOP_SIZE (result);
6445 // result = bit & yy;
6446 if (AOP_TYPE (left) == AOP_CRY)
6448 // c = bit & literal;
6449 if (AOP_TYPE (right) == AOP_LIT)
6453 if (size && sameRegs (AOP (result), AOP (left)))
6456 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6461 if (size && (AOP_TYPE (result) == AOP_CRY))
6463 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6466 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6471 emitcode ("clr", "c");
6476 if (AOP_TYPE (right) == AOP_CRY)
6479 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6480 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6485 MOVA (aopGet (right, 0, FALSE, FALSE));
6487 emitcode ("rrc", "a");
6488 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6496 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6497 genIfxJump (ifx, "c", left, right, result);
6501 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6502 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6503 if ((AOP_TYPE (right) == AOP_LIT) &&
6504 (AOP_TYPE (result) == AOP_CRY) &&
6505 (AOP_TYPE (left) != AOP_CRY))
6507 int posbit = isLiteralBit (lit);
6512 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6516 switch (posbit & 0x07)
6518 case 0: emitcode ("rrc", "a");
6520 case 7: emitcode ("rlc", "a");
6522 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6531 SNPRINTF (buffer, sizeof(buffer),
6532 "acc.%d", posbit & 0x07);
6533 genIfxJump (ifx, buffer, left, right, result);
6536 {// what is this case? just found it in ds390/gen.c
6537 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6544 symbol *tlbl = newiTempLabel (NULL);
6545 int sizel = AOP_SIZE (left);
6547 emitcode ("setb", "c");
6550 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6552 MOVA (aopGet (left, offset, FALSE, FALSE));
6554 if ((posbit = isLiteralBit (bytelit)) != 0)
6555 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6558 if (bytelit != 0x0FFL)
6559 emitcode ("anl", "a,%s",
6560 aopGet (right, offset, FALSE, TRUE));
6561 emitcode ("jnz", "%05d$", tlbl->key + 100);
6566 // bit = left & literal
6569 emitcode ("clr", "c");
6572 // if(left & literal)
6576 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6586 /* if left is same as result */
6587 if (sameRegs (AOP (result), AOP (left)))
6589 for (; size--; offset++)
6591 if (AOP_TYPE (right) == AOP_LIT)
6593 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6594 if (bytelit == 0x0FF)
6596 /* dummy read of volatile operand */
6597 if (isOperandVolatile (left, FALSE))
6598 MOVA (aopGet (left, offset, FALSE, FALSE));
6602 else if (bytelit == 0)
6604 aopPut (result, zero, offset);
6606 else if (IS_AOP_PREG (result))
6608 MOVA (aopGet (left, offset, FALSE, TRUE));
6609 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6610 aopPut (result, "a", offset);
6613 emitcode ("anl", "%s,%s",
6614 aopGet (left, offset, FALSE, TRUE),
6615 aopGet (right, offset, FALSE, FALSE));
6619 if (AOP_TYPE (left) == AOP_ACC)
6622 emitcode("mov", "a,b");
6623 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6625 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6627 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6628 MOVA (aopGet (right, offset, FALSE, FALSE));
6629 emitcode ("anl", "a,b");
6630 aopPut (result, "a", offset);
6632 else if (aopGetUsesAcc (left, offset))
6634 MOVA (aopGet (left, offset, FALSE, FALSE));
6635 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6636 aopPut (result, "a", offset);
6640 MOVA (aopGet (right, offset, FALSE, FALSE));
6641 if (IS_AOP_PREG (result))
6643 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6644 aopPut (result, "a", offset);
6647 emitcode ("anl", "%s,a",
6648 aopGet (left, offset, FALSE, TRUE));
6655 // left & result in different registers
6656 if (AOP_TYPE (result) == AOP_CRY)
6659 // if(size), result in bit
6660 // if(!size && ifx), conditional oper: if(left & right)
6661 symbol *tlbl = newiTempLabel (NULL);
6662 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6664 emitcode ("setb", "c");
6667 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6668 && AOP_TYPE(left)==AOP_ACC)
6671 emitcode("mov", "a,b");
6672 emitcode ("anl", "a,%s",
6673 aopGet (right, offset, FALSE, FALSE));
6675 if (AOP_TYPE(left)==AOP_ACC)
6679 bool pushedB = pushB ();
6680 emitcode("mov", "b,a");
6681 MOVA (aopGet (right, offset, FALSE, FALSE));
6682 emitcode("anl", "a,b");
6687 MOVA (aopGet (right, offset, FALSE, FALSE));
6688 emitcode("anl", "a,b");
6691 MOVA (aopGet (right, offset, FALSE, FALSE));
6692 emitcode ("anl", "a,%s",
6693 aopGet (left, offset, FALSE, FALSE));
6696 emitcode ("jnz", "%05d$", tlbl->key + 100);
6706 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6712 for (; (size--); offset++)
6715 // result = left & right
6716 if (AOP_TYPE (right) == AOP_LIT)
6718 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6719 if (bytelit == 0x0FF)
6722 aopGet (left, offset, FALSE, FALSE),
6726 else if (bytelit == 0)
6728 /* dummy read of volatile operand */
6729 if (isOperandVolatile (left, FALSE))
6730 MOVA (aopGet (left, offset, FALSE, FALSE));
6731 aopPut (result, zero, offset);
6734 else if (AOP_TYPE (left) == AOP_ACC)
6738 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6739 aopPut (result, "a", offset);
6744 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6745 aopPut (result, "b", offset);
6750 // faster than result <- left, anl result,right
6751 // and better if result is SFR
6752 if (AOP_TYPE (left) == AOP_ACC)
6755 emitcode("mov", "a,b");
6756 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6758 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6760 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6761 MOVA (aopGet (right, offset, FALSE, FALSE));
6762 emitcode ("anl", "a,b");
6764 else if (aopGetUsesAcc (left, offset))
6766 MOVA (aopGet (left, offset, FALSE, FALSE));
6767 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6771 MOVA (aopGet (right, offset, FALSE, FALSE));
6772 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6774 aopPut (result, "a", offset);
6780 freeAsmop (result, NULL, ic, TRUE);
6781 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6785 /*-----------------------------------------------------------------*/
6786 /* genOr - code for or */
6787 /*-----------------------------------------------------------------*/
6789 genOr (iCode * ic, iCode * ifx)
6791 operand *left, *right, *result;
6792 int size, offset = 0;
6793 unsigned long lit = 0L;
6796 D (emitcode (";", "genOr"));
6798 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6799 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6800 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6803 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6805 AOP_TYPE (left), AOP_TYPE (right));
6806 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6808 AOP_SIZE (left), AOP_SIZE (right));
6811 /* if left is a literal & right is not then exchange them */
6812 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6813 AOP_NEEDSACC (left))
6815 operand *tmp = right;
6820 /* if result = right then exchange them */
6821 if (sameRegs (AOP (result), AOP (right)))
6823 operand *tmp = right;
6828 /* if right is bit then exchange them */
6829 if (AOP_TYPE (right) == AOP_CRY &&
6830 AOP_TYPE (left) != AOP_CRY)
6832 operand *tmp = right;
6836 if (AOP_TYPE (right) == AOP_LIT)
6837 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6839 size = AOP_SIZE (result);
6843 if (AOP_TYPE (left) == AOP_CRY)
6845 if (AOP_TYPE (right) == AOP_LIT)
6847 // c = bit | literal;
6850 // lit != 0 => result = 1
6851 if (AOP_TYPE (result) == AOP_CRY)
6854 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6856 continueIfTrue (ifx);
6859 emitcode ("setb", "c");
6863 // lit == 0 => result = left
6864 if (size && sameRegs (AOP (result), AOP (left)))
6866 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6871 if (AOP_TYPE (right) == AOP_CRY)
6874 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6875 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6880 symbol *tlbl = newiTempLabel (NULL);
6881 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6882 emitcode ("setb", "c");
6883 emitcode ("jb", "%s,%05d$",
6884 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6886 emitcode ("jnz", "%05d$", tlbl->key + 100);
6887 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6889 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6904 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6905 genIfxJump (ifx, "c", left, right, result);
6909 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6910 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6911 if ((AOP_TYPE (right) == AOP_LIT) &&
6912 (AOP_TYPE (result) == AOP_CRY) &&
6913 (AOP_TYPE (left) != AOP_CRY))
6919 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6921 continueIfTrue (ifx);
6926 // lit = 0, result = boolean(left)
6928 emitcode ("setb", "c");
6932 symbol *tlbl = newiTempLabel (NULL);
6933 emitcode ("jnz", "%05d$", tlbl->key + 100);
6939 genIfxJump (ifx, "a", left, right, result);
6947 /* if left is same as result */
6948 if (sameRegs (AOP (result), AOP (left)))
6950 for (; size--; offset++)
6952 if (AOP_TYPE (right) == AOP_LIT)
6954 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6957 /* dummy read of volatile operand */
6958 if (isOperandVolatile (left, FALSE))
6959 MOVA (aopGet (left, offset, FALSE, FALSE));
6963 else if (bytelit == 0x0FF)
6965 aopPut (result, "#0xFF", offset);
6967 else if (IS_AOP_PREG (left))
6969 MOVA (aopGet (left, offset, FALSE, TRUE));
6970 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6971 aopPut (result, "a", offset);
6975 emitcode ("orl", "%s,%s",
6976 aopGet (left, offset, FALSE, TRUE),
6977 aopGet (right, offset, FALSE, FALSE));
6982 if (AOP_TYPE (left) == AOP_ACC)
6985 emitcode("mov", "a,b");
6986 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6988 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6990 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6991 MOVA (aopGet (right, offset, FALSE, FALSE));
6992 emitcode ("orl", "a,b");
6993 aopPut (result, "a", offset);
6995 else if (aopGetUsesAcc (left, offset))
6997 MOVA (aopGet (left, offset, FALSE, FALSE));
6998 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6999 aopPut (result, "a", offset);
7003 MOVA (aopGet (right, offset, FALSE, FALSE));
7004 if (IS_AOP_PREG (left))
7006 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7007 aopPut (result, "a", offset);
7011 emitcode ("orl", "%s,a",
7012 aopGet (left, offset, FALSE, TRUE));
7020 // left & result in different registers
7021 if (AOP_TYPE (result) == AOP_CRY)
7024 // if(size), result in bit
7025 // if(!size && ifx), conditional oper: if(left | right)
7026 symbol *tlbl = newiTempLabel (NULL);
7027 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7029 emitcode ("setb", "c");
7032 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7034 emitcode("mov", "a,b");
7035 emitcode ("orl", "a,%s",
7036 aopGet (right, offset, FALSE, FALSE));
7038 MOVA (aopGet (right, offset, FALSE, FALSE));
7039 emitcode ("orl", "a,%s",
7040 aopGet (left, offset, FALSE, FALSE));
7042 emitcode ("jnz", "%05d$", tlbl->key + 100);
7052 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7058 for (; (size--); offset++)
7061 // result = left | right
7062 if (AOP_TYPE (right) == AOP_LIT)
7064 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7068 aopGet (left, offset, FALSE, FALSE),
7072 else if (bytelit == 0x0FF)
7074 /* dummy read of volatile operand */
7075 if (isOperandVolatile (left, FALSE))
7076 MOVA (aopGet (left, offset, FALSE, FALSE));
7077 aopPut (result, "#0xFF", offset);
7081 // faster than result <- left, anl result,right
7082 // and better if result is SFR
7083 if (AOP_TYPE (left) == AOP_ACC)
7086 emitcode("mov", "a,b");
7087 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7089 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7091 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7092 MOVA (aopGet (right, offset, FALSE, FALSE));
7093 emitcode ("orl", "a,b");
7095 else if (aopGetUsesAcc (left, offset))
7097 MOVA (aopGet (left, offset, FALSE, FALSE));
7098 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7102 MOVA (aopGet (right, offset, FALSE, FALSE));
7103 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7105 aopPut (result, "a", offset);
7111 freeAsmop (result, NULL, ic, TRUE);
7112 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7116 /*-----------------------------------------------------------------*/
7117 /* genXor - code for xclusive or */
7118 /*-----------------------------------------------------------------*/
7120 genXor (iCode * ic, iCode * ifx)
7122 operand *left, *right, *result;
7123 int size, offset = 0;
7124 unsigned long lit = 0L;
7127 D (emitcode (";", "genXor"));
7129 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7130 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7131 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7134 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7136 AOP_TYPE (left), AOP_TYPE (right));
7137 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7139 AOP_SIZE (left), AOP_SIZE (right));
7142 /* if left is a literal & right is not ||
7143 if left needs acc & right does not */
7144 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7145 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7147 operand *tmp = right;
7152 /* if result = right then exchange them */
7153 if (sameRegs (AOP (result), AOP (right)))
7155 operand *tmp = right;
7160 /* if right is bit then exchange them */
7161 if (AOP_TYPE (right) == AOP_CRY &&
7162 AOP_TYPE (left) != AOP_CRY)
7164 operand *tmp = right;
7168 if (AOP_TYPE (right) == AOP_LIT)
7169 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7171 size = AOP_SIZE (result);
7175 if (AOP_TYPE (left) == AOP_CRY)
7177 if (AOP_TYPE (right) == AOP_LIT)
7179 // c = bit & literal;
7182 // lit>>1 != 0 => result = 1
7183 if (AOP_TYPE (result) == AOP_CRY)
7186 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7188 continueIfTrue (ifx);
7191 emitcode ("setb", "c");
7198 // lit == 0, result = left
7199 if (size && sameRegs (AOP (result), AOP (left)))
7201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7205 // lit == 1, result = not(left)
7206 if (size && sameRegs (AOP (result), AOP (left)))
7208 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7214 emitcode ("cpl", "c");
7223 symbol *tlbl = newiTempLabel (NULL);
7224 if (AOP_TYPE (right) == AOP_CRY)
7227 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7231 int sizer = AOP_SIZE (right);
7233 // if val>>1 != 0, result = 1
7234 emitcode ("setb", "c");
7237 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7239 // test the msb of the lsb
7240 emitcode ("anl", "a,#0xfe");
7241 emitcode ("jnz", "%05d$", tlbl->key + 100);
7245 emitcode ("rrc", "a");
7247 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7248 emitcode ("cpl", "c");
7256 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7257 genIfxJump (ifx, "c", left, right, result);
7261 /* if left is same as result */
7262 if (sameRegs (AOP (result), AOP (left)))
7264 for (; size--; offset++)
7266 if (AOP_TYPE (right) == AOP_LIT)
7268 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7271 /* dummy read of volatile operand */
7272 if (isOperandVolatile (left, FALSE))
7273 MOVA (aopGet (left, offset, FALSE, FALSE));
7277 else if (IS_AOP_PREG (left))
7279 MOVA (aopGet (left, offset, FALSE, TRUE));
7280 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281 aopPut (result, "a", offset);
7285 emitcode ("xrl", "%s,%s",
7286 aopGet (left, offset, FALSE, TRUE),
7287 aopGet (right, offset, FALSE, FALSE));
7292 if (AOP_TYPE (left) == AOP_ACC)
7295 emitcode("mov", "a,b");
7296 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7298 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7300 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7301 MOVA (aopGet (right, offset, FALSE, FALSE));
7302 emitcode ("xrl", "a,b");
7303 aopPut (result, "a", offset);
7305 else if (aopGetUsesAcc (left, offset))
7307 MOVA (aopGet (left, offset, FALSE, FALSE));
7308 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7309 aopPut (result, "a", offset);
7313 MOVA (aopGet (right, offset, FALSE, FALSE));
7314 if (IS_AOP_PREG (left))
7316 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7317 aopPut (result, "a", offset);
7320 emitcode ("xrl", "%s,a",
7321 aopGet (left, offset, FALSE, TRUE));
7328 // left & result in different registers
7329 if (AOP_TYPE (result) == AOP_CRY)
7332 // if(size), result in bit
7333 // if(!size && ifx), conditional oper: if(left ^ right)
7334 symbol *tlbl = newiTempLabel (NULL);
7335 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7338 emitcode ("setb", "c");
7341 if ((AOP_TYPE (right) == AOP_LIT) &&
7342 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7344 MOVA (aopGet (left, offset, FALSE, FALSE));
7348 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7350 emitcode("mov", "a,b");
7351 emitcode ("xrl", "a,%s",
7352 aopGet (right, offset, FALSE, FALSE));
7354 MOVA (aopGet (right, offset, FALSE, FALSE));
7355 emitcode ("xrl", "a,%s",
7356 aopGet (left, offset, FALSE, FALSE));
7359 emitcode ("jnz", "%05d$", tlbl->key + 100);
7369 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7373 for (; (size--); offset++)
7376 // result = left ^ right
7377 if (AOP_TYPE (right) == AOP_LIT)
7379 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7383 aopGet (left, offset, FALSE, FALSE),
7388 // faster than result <- left, anl result,right
7389 // and better if result is SFR
7390 if (AOP_TYPE (left) == AOP_ACC)
7393 emitcode("mov", "a,b");
7394 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7396 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7398 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7399 MOVA (aopGet (right, offset, FALSE, FALSE));
7400 emitcode ("xrl", "a,b");
7402 else if (aopGetUsesAcc (left, offset))
7404 MOVA (aopGet (left, offset, FALSE, FALSE));
7405 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7409 MOVA (aopGet (right, offset, FALSE, FALSE));
7410 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7412 aopPut (result, "a", offset);
7418 freeAsmop (result, NULL, ic, TRUE);
7419 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7420 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7423 /*-----------------------------------------------------------------*/
7424 /* genInline - write the inline code out */
7425 /*-----------------------------------------------------------------*/
7427 genInline (iCode * ic)
7429 char *buffer, *bp, *bp1;
7431 D (emitcode (";", "genInline"));
7433 _G.inLine += (!options.asmpeep);
7435 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7437 /* emit each line as a code */
7448 /* Add \n for labels, not dirs such as c:\mydir */
7449 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7463 /* emitcode("",buffer); */
7464 _G.inLine -= (!options.asmpeep);
7467 /*-----------------------------------------------------------------*/
7468 /* genRRC - rotate right with carry */
7469 /*-----------------------------------------------------------------*/
7473 operand *left, *result;
7477 D (emitcode (";", "genRRC"));
7479 /* rotate right with carry */
7480 left = IC_LEFT (ic);
7481 result = IC_RESULT (ic);
7482 aopOp (left, ic, FALSE);
7483 aopOp (result, ic, FALSE);
7485 /* move it to the result */
7486 size = AOP_SIZE (result);
7488 if (size == 1) { /* special case for 1 byte */
7489 l = aopGet (left, offset, FALSE, FALSE);
7491 emitcode ("rr", "a");
7494 /* no need to clear carry, bit7 will be written later */
7497 l = aopGet (left, offset, FALSE, FALSE);
7499 emitcode ("rrc", "a");
7500 if (AOP_SIZE (result) > 1)
7501 aopPut (result, "a", offset--);
7503 /* now we need to put the carry into the
7504 highest order byte of the result */
7505 if (AOP_SIZE (result) > 1)
7507 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7510 emitcode ("mov", "acc.7,c");
7512 aopPut (result, "a", AOP_SIZE (result) - 1);
7513 freeAsmop (result, NULL, ic, TRUE);
7514 freeAsmop (left, NULL, ic, TRUE);
7517 /*-----------------------------------------------------------------*/
7518 /* genRLC - generate code for rotate left with carry */
7519 /*-----------------------------------------------------------------*/
7523 operand *left, *result;
7527 D (emitcode (";", "genRLC"));
7529 /* rotate right with carry */
7530 left = IC_LEFT (ic);
7531 result = IC_RESULT (ic);
7532 aopOp (left, ic, FALSE);
7533 aopOp (result, ic, FALSE);
7535 /* move it to the result */
7536 size = AOP_SIZE (result);
7540 l = aopGet (left, offset, FALSE, FALSE);
7542 if (size == 0) { /* special case for 1 byte */
7546 emitcode("rlc","a"); /* bit0 will be written later */
7547 if (AOP_SIZE (result) > 1)
7549 aopPut (result, "a", offset++);
7554 l = aopGet (left, offset, FALSE, FALSE);
7556 emitcode ("rlc", "a");
7557 if (AOP_SIZE (result) > 1)
7558 aopPut (result, "a", offset++);
7561 /* now we need to put the carry into the
7562 highest order byte of the result */
7563 if (AOP_SIZE (result) > 1)
7565 l = aopGet (result, 0, FALSE, FALSE);
7568 emitcode ("mov", "acc.0,c");
7570 aopPut (result, "a", 0);
7571 freeAsmop (result, NULL, ic, TRUE);
7572 freeAsmop (left, NULL, ic, TRUE);
7575 /*-----------------------------------------------------------------*/
7576 /* genGetHbit - generates code get highest order bit */
7577 /*-----------------------------------------------------------------*/
7579 genGetHbit (iCode * ic)
7581 operand *left, *result;
7583 D (emitcode (";", "genGetHbit"));
7585 left = IC_LEFT (ic);
7586 result = IC_RESULT (ic);
7587 aopOp (left, ic, FALSE);
7588 aopOp (result, ic, FALSE);
7590 /* get the highest order byte into a */
7591 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7592 if (AOP_TYPE (result) == AOP_CRY)
7594 emitcode ("rlc", "a");
7599 emitcode ("rl", "a");
7600 emitcode ("anl", "a,#0x01");
7604 freeAsmop (result, NULL, ic, TRUE);
7605 freeAsmop (left, NULL, ic, TRUE);
7608 /*-----------------------------------------------------------------*/
7609 /* genGetAbit - generates code get a single bit */
7610 /*-----------------------------------------------------------------*/
7612 genGetAbit (iCode * ic)
7614 operand *left, *right, *result;
7617 D (emitcode (";", "genGetAbit"));
7619 left = IC_LEFT (ic);
7620 right = IC_RIGHT (ic);
7621 result = IC_RESULT (ic);
7622 aopOp (left, ic, FALSE);
7623 aopOp (right, ic, FALSE);
7624 aopOp (result, ic, FALSE);
7626 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7628 /* get the needed byte into a */
7629 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7631 if (AOP_TYPE (result) == AOP_CRY)
7634 emitcode ("rlc", "a");
7635 else if ((shCount) == 0)
7636 emitcode ("rrc", "a");
7638 emitcode ("mov", "c,acc[%d]", shCount);
7646 emitcode ("rr", "a");
7649 emitcode ("rr", "a");
7652 emitcode ("anl", "a,#0x01");
7656 emitcode ("mov", "c,acc[%d]", shCount);
7657 emitcode ("clr", "a");
7658 emitcode ("rlc", "a");
7661 emitcode ("swap", "a");
7662 emitcode ("anl", "a,#0x01");
7665 emitcode ("rl", "a");
7668 emitcode ("rl", "a");
7669 emitcode ("anl", "a,#0x01");
7675 freeAsmop (result, NULL, ic, TRUE);
7676 freeAsmop (right, NULL, ic, TRUE);
7677 freeAsmop (left, NULL, ic, TRUE);
7680 /*-----------------------------------------------------------------*/
7681 /* genGetByte - generates code get a single byte */
7682 /*-----------------------------------------------------------------*/
7684 genGetByte (iCode * ic)
7686 operand *left, *right, *result;
7689 D (emitcode (";", "genGetByte"));
7691 left = IC_LEFT (ic);
7692 right = IC_RIGHT (ic);
7693 result = IC_RESULT (ic);
7694 aopOp (left, ic, FALSE);
7695 aopOp (right, ic, FALSE);
7696 aopOp (result, ic, FALSE);
7698 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7700 aopGet (left, offset, FALSE, FALSE),
7703 freeAsmop (result, NULL, ic, TRUE);
7704 freeAsmop (right, NULL, ic, TRUE);
7705 freeAsmop (left, NULL, ic, TRUE);
7708 /*-----------------------------------------------------------------*/
7709 /* genGetWord - generates code get two bytes */
7710 /*-----------------------------------------------------------------*/
7712 genGetWord (iCode * ic)
7714 operand *left, *right, *result;
7717 D (emitcode (";", "genGetWord"));
7719 left = IC_LEFT (ic);
7720 right = IC_RIGHT (ic);
7721 result = IC_RESULT (ic);
7722 aopOp (left, ic, FALSE);
7723 aopOp (right, ic, FALSE);
7724 aopOp (result, ic, FALSE);
7726 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7728 aopGet (left, offset, FALSE, FALSE),
7731 aopGet (left, offset+1, FALSE, FALSE),
7734 freeAsmop (result, NULL, ic, TRUE);
7735 freeAsmop (right, NULL, ic, TRUE);
7736 freeAsmop (left, NULL, ic, TRUE);
7739 /*-----------------------------------------------------------------*/
7740 /* genSwap - generates code to swap nibbles or bytes */
7741 /*-----------------------------------------------------------------*/
7743 genSwap (iCode * ic)
7745 operand *left, *result;
7747 D(emitcode ("; genSwap",""));
7749 left = IC_LEFT (ic);
7750 result = IC_RESULT (ic);
7751 aopOp (left, ic, FALSE);
7752 aopOp (result, ic, FALSE);
7754 switch (AOP_SIZE (left))
7756 case 1: /* swap nibbles in byte */
7757 MOVA (aopGet (left, 0, FALSE, FALSE));
7758 emitcode ("swap", "a");
7759 aopPut (result, "a", 0);
7761 case 2: /* swap bytes in word */
7762 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7764 MOVA (aopGet (left, 0, FALSE, FALSE));
7765 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7766 aopPut (result, "a", 1);
7768 else if (operandsEqu (left, result))
7771 bool pushedB = FALSE, leftInB = FALSE;
7773 MOVA (aopGet (left, 0, FALSE, FALSE));
7774 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7777 emitcode ("mov", "b,a");
7781 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7782 aopPut (result, reg, 1);
7789 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7790 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7794 wassertl(FALSE, "unsupported SWAP operand size");
7797 freeAsmop (result, NULL, ic, TRUE);
7798 freeAsmop (left, NULL, ic, TRUE);
7801 /*-----------------------------------------------------------------*/
7802 /* AccRol - rotate left accumulator by known count */
7803 /*-----------------------------------------------------------------*/
7805 AccRol (int shCount)
7807 shCount &= 0x0007; // shCount : 0..7
7814 emitcode ("rl", "a");
7817 emitcode ("rl", "a");
7818 emitcode ("rl", "a");
7821 emitcode ("swap", "a");
7822 emitcode ("rr", "a");
7825 emitcode ("swap", "a");
7828 emitcode ("swap", "a");
7829 emitcode ("rl", "a");
7832 emitcode ("rr", "a");
7833 emitcode ("rr", "a");
7836 emitcode ("rr", "a");
7841 /*-----------------------------------------------------------------*/
7842 /* AccLsh - left shift accumulator by known count */
7843 /*-----------------------------------------------------------------*/
7845 AccLsh (int shCount)
7850 emitcode ("add", "a,acc");
7851 else if (shCount == 2)
7853 emitcode ("add", "a,acc");
7854 emitcode ("add", "a,acc");
7858 /* rotate left accumulator */
7860 /* and kill the lower order bits */
7861 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7866 /*-----------------------------------------------------------------*/
7867 /* AccRsh - right shift accumulator by known count */
7868 /*-----------------------------------------------------------------*/
7870 AccRsh (int shCount)
7877 emitcode ("rrc", "a");
7881 /* rotate right accumulator */
7882 AccRol (8 - shCount);
7883 /* and kill the higher order bits */
7884 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7889 /*-----------------------------------------------------------------*/
7890 /* AccSRsh - signed right shift accumulator by known count */
7891 /*-----------------------------------------------------------------*/
7893 AccSRsh (int shCount)
7900 emitcode ("mov", "c,acc.7");
7901 emitcode ("rrc", "a");
7903 else if (shCount == 2)
7905 emitcode ("mov", "c,acc.7");
7906 emitcode ("rrc", "a");
7907 emitcode ("mov", "c,acc.7");
7908 emitcode ("rrc", "a");
7912 tlbl = newiTempLabel (NULL);
7913 /* rotate right accumulator */
7914 AccRol (8 - shCount);
7915 /* and kill the higher order bits */
7916 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7917 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7918 emitcode ("orl", "a,#0x%02x",
7919 (unsigned char) ~SRMask[shCount]);
7925 /*-----------------------------------------------------------------*/
7926 /* shiftR1Left2Result - shift right one byte from left to result */
7927 /*-----------------------------------------------------------------*/
7929 shiftR1Left2Result (operand * left, int offl,
7930 operand * result, int offr,
7931 int shCount, int sign)
7933 MOVA (aopGet (left, offl, FALSE, FALSE));
7934 /* shift right accumulator */
7939 aopPut (result, "a", offr);
7942 /*-----------------------------------------------------------------*/
7943 /* shiftL1Left2Result - shift left one byte from left to result */
7944 /*-----------------------------------------------------------------*/
7946 shiftL1Left2Result (operand * left, int offl,
7947 operand * result, int offr, int shCount)
7950 l = aopGet (left, offl, FALSE, FALSE);
7952 /* shift left accumulator */
7954 aopPut (result, "a", offr);
7957 /*-----------------------------------------------------------------*/
7958 /* movLeft2Result - move byte from left to result */
7959 /*-----------------------------------------------------------------*/
7961 movLeft2Result (operand * left, int offl,
7962 operand * result, int offr, int sign)
7965 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7967 l = aopGet (left, offl, FALSE, FALSE);
7969 if (*l == '@' && (IS_AOP_PREG (result)))
7971 emitcode ("mov", "a,%s", l);
7972 aopPut (result, "a", offr);
7978 aopPut (result, l, offr);
7982 /* MSB sign in acc.7 ! */
7983 if (getDataSize (left) == offl + 1)
7986 aopPut (result, "a", offr);
7993 /*-----------------------------------------------------------------*/
7994 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7995 /*-----------------------------------------------------------------*/
7999 emitcode ("rrc", "a");
8000 emitcode ("xch", "a,%s", x);
8001 emitcode ("rrc", "a");
8002 emitcode ("xch", "a,%s", x);
8005 /*-----------------------------------------------------------------*/
8006 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8007 /*-----------------------------------------------------------------*/
8011 emitcode ("xch", "a,%s", x);
8012 emitcode ("rlc", "a");
8013 emitcode ("xch", "a,%s", x);
8014 emitcode ("rlc", "a");
8017 /*-----------------------------------------------------------------*/
8018 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8019 /*-----------------------------------------------------------------*/
8023 emitcode ("xch", "a,%s", x);
8024 emitcode ("add", "a,acc");
8025 emitcode ("xch", "a,%s", x);
8026 emitcode ("rlc", "a");
8029 /*-----------------------------------------------------------------*/
8030 /* AccAXLsh - left shift a:x by known count (0..7) */
8031 /*-----------------------------------------------------------------*/
8033 AccAXLsh (char *x, int shCount)
8048 case 5: // AAAAABBB:CCCCCDDD
8050 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8052 emitcode ("anl", "a,#0x%02x",
8053 SLMask[shCount]); // BBB00000:CCCCCDDD
8055 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8057 AccRol (shCount); // DDDCCCCC:BBB00000
8059 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8061 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8063 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8065 emitcode ("anl", "a,#0x%02x",
8066 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8068 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8070 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8073 case 6: // AAAAAABB:CCCCCCDD
8074 emitcode ("anl", "a,#0x%02x",
8075 SRMask[shCount]); // 000000BB:CCCCCCDD
8076 emitcode ("mov", "c,acc.0"); // c = B
8077 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8079 AccAXRrl1 (x); // BCCCCCCD:D000000B
8080 AccAXRrl1 (x); // BBCCCCCC:DD000000
8082 emitcode("rrc","a");
8083 emitcode("xch","a,%s", x);
8084 emitcode("rrc","a");
8085 emitcode("mov","c,acc.0"); //<< get correct bit
8086 emitcode("xch","a,%s", x);
8088 emitcode("rrc","a");
8089 emitcode("xch","a,%s", x);
8090 emitcode("rrc","a");
8091 emitcode("xch","a,%s", x);
8094 case 7: // a:x <<= 7
8096 emitcode ("anl", "a,#0x%02x",
8097 SRMask[shCount]); // 0000000B:CCCCCCCD
8099 emitcode ("mov", "c,acc.0"); // c = B
8101 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8103 AccAXRrl1 (x); // BCCCCCCC:D0000000
8111 /*-----------------------------------------------------------------*/
8112 /* AccAXRsh - right shift a:x known count (0..7) */
8113 /*-----------------------------------------------------------------*/
8115 AccAXRsh (char *x, int shCount)
8123 AccAXRrl1 (x); // 0->a:x
8128 AccAXRrl1 (x); // 0->a:x
8131 AccAXRrl1 (x); // 0->a:x
8136 case 5: // AAAAABBB:CCCCCDDD = a:x
8138 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8140 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8142 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8144 emitcode ("anl", "a,#0x%02x",
8145 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8147 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8149 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8151 emitcode ("anl", "a,#0x%02x",
8152 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8154 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8156 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8158 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8161 case 6: // AABBBBBB:CCDDDDDD
8163 emitcode ("mov", "c,acc.7");
8164 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8166 emitcode ("mov", "c,acc.7");
8167 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8169 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8171 emitcode ("anl", "a,#0x%02x",
8172 SRMask[shCount]); // 000000AA:BBBBBBCC
8175 case 7: // ABBBBBBB:CDDDDDDD
8177 emitcode ("mov", "c,acc.7"); // c = A
8179 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8181 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8183 emitcode ("anl", "a,#0x%02x",
8184 SRMask[shCount]); // 0000000A:BBBBBBBC
8192 /*-----------------------------------------------------------------*/
8193 /* AccAXRshS - right shift signed a:x known count (0..7) */
8194 /*-----------------------------------------------------------------*/
8196 AccAXRshS (char *x, int shCount)
8204 emitcode ("mov", "c,acc.7");
8205 AccAXRrl1 (x); // s->a:x
8209 emitcode ("mov", "c,acc.7");
8210 AccAXRrl1 (x); // s->a:x
8212 emitcode ("mov", "c,acc.7");
8213 AccAXRrl1 (x); // s->a:x
8218 case 5: // AAAAABBB:CCCCCDDD = a:x
8220 tlbl = newiTempLabel (NULL);
8221 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8223 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8225 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8227 emitcode ("anl", "a,#0x%02x",
8228 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8230 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8232 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8234 emitcode ("anl", "a,#0x%02x",
8235 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8237 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8239 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8241 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8243 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8244 emitcode ("orl", "a,#0x%02x",
8245 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8248 break; // SSSSAAAA:BBBCCCCC
8250 case 6: // AABBBBBB:CCDDDDDD
8252 tlbl = newiTempLabel (NULL);
8253 emitcode ("mov", "c,acc.7");
8254 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8256 emitcode ("mov", "c,acc.7");
8257 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8259 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8261 emitcode ("anl", "a,#0x%02x",
8262 SRMask[shCount]); // 000000AA:BBBBBBCC
8264 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8265 emitcode ("orl", "a,#0x%02x",
8266 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8270 case 7: // ABBBBBBB:CDDDDDDD
8272 tlbl = newiTempLabel (NULL);
8273 emitcode ("mov", "c,acc.7"); // c = A
8275 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8277 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8279 emitcode ("anl", "a,#0x%02x",
8280 SRMask[shCount]); // 0000000A:BBBBBBBC
8282 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8283 emitcode ("orl", "a,#0x%02x",
8284 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8293 /*-----------------------------------------------------------------*/
8294 /* shiftL2Left2Result - shift left two bytes from left to result */
8295 /*-----------------------------------------------------------------*/
8297 shiftL2Left2Result (operand * left, int offl,
8298 operand * result, int offr, int shCount)
8301 bool pushedB = FALSE;
8304 if (sameRegs (AOP (result), AOP (left)) &&
8305 ((offl + MSB16) == offr))
8307 /* don't crash result[offr] */
8308 MOVA (aopGet (left, offl, FALSE, FALSE));
8309 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8310 x = aopGet (result, offr, FALSE, FALSE);
8312 else if (aopGetUsesAcc (result, offr))
8314 movLeft2Result (left, offl, result, offr, 0);
8317 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8318 MOVA (aopGet (result, offr, FALSE, FALSE));
8319 emitcode ("xch", "a,b");
8324 movLeft2Result (left, offl, result, offr, 0);
8325 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8326 x = aopGet (result, offr, FALSE, FALSE);
8328 /* ax << shCount (x = lsb(result)) */
8329 AccAXLsh (x, shCount);
8332 emitcode ("xch", "a,b");
8333 aopPut (result, "a", offr);
8334 aopPut (result, "b", offr + MSB16);
8339 aopPut (result, "a", offr + MSB16);
8344 /*-----------------------------------------------------------------*/
8345 /* shiftR2Left2Result - shift right two bytes from left to result */
8346 /*-----------------------------------------------------------------*/
8348 shiftR2Left2Result (operand * left, int offl,
8349 operand * result, int offr,
8350 int shCount, int sign)
8353 bool pushedB = FALSE;
8356 if (sameRegs (AOP (result), AOP (left)) &&
8357 ((offl + MSB16) == offr))
8359 /* don't crash result[offr] */
8360 MOVA (aopGet (left, offl, FALSE, FALSE));
8361 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8362 x = aopGet (result, offr, FALSE, FALSE);
8364 else if (aopGetUsesAcc (result, offr))
8366 movLeft2Result (left, offl, result, offr, 0);
8369 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8370 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8375 movLeft2Result (left, offl, result, offr, 0);
8376 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8377 x = aopGet (result, offr, FALSE, FALSE);
8379 /* a:x >> shCount (x = lsb(result)) */
8381 AccAXRshS (x, shCount);
8383 AccAXRsh (x, shCount);
8386 emitcode ("xch", "a,b");
8387 aopPut (result, "a", offr);
8388 emitcode ("xch", "a,b");
8391 if (getDataSize (result) > 1)
8392 aopPut (result, "a", offr + MSB16);
8395 /*-----------------------------------------------------------------*/
8396 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8397 /*-----------------------------------------------------------------*/
8399 shiftLLeftOrResult (operand * left, int offl,
8400 operand * result, int offr, int shCount)
8402 MOVA (aopGet (left, offl, FALSE, FALSE));
8403 /* shift left accumulator */
8405 /* or with result */
8406 if (aopGetUsesAcc (result, offr))
8408 emitcode ("xch", "a,b");
8409 MOVA (aopGet (result, offr, FALSE, FALSE));
8410 emitcode ("orl", "a,b");
8414 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8416 /* back to result */
8417 aopPut (result, "a", offr);
8420 /*-----------------------------------------------------------------*/
8421 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8422 /*-----------------------------------------------------------------*/
8424 shiftRLeftOrResult (operand * left, int offl,
8425 operand * result, int offr, int shCount)
8427 MOVA (aopGet (left, offl, FALSE, FALSE));
8428 /* shift right accumulator */
8430 /* or with result */
8431 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8432 /* back to result */
8433 aopPut (result, "a", offr);
8436 /*-----------------------------------------------------------------*/
8437 /* genlshOne - left shift a one byte quantity by known count */
8438 /*-----------------------------------------------------------------*/
8440 genlshOne (operand * result, operand * left, int shCount)
8442 D (emitcode (";", "genlshOne"));
8444 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8447 /*-----------------------------------------------------------------*/
8448 /* genlshTwo - left shift two bytes by known amount != 0 */
8449 /*-----------------------------------------------------------------*/
8451 genlshTwo (operand * result, operand * left, int shCount)
8455 D (emitcode (";", "genlshTwo"));
8457 size = getDataSize (result);
8459 /* if shCount >= 8 */
8467 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8469 movLeft2Result (left, LSB, result, MSB16, 0);
8471 aopPut (result, zero, LSB);
8474 /* 1 <= shCount <= 7 */
8478 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8480 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8484 /*-----------------------------------------------------------------*/
8485 /* shiftLLong - shift left one long from left to result */
8486 /* offl = LSB or MSB16 */
8487 /*-----------------------------------------------------------------*/
8489 shiftLLong (operand * left, operand * result, int offr)
8492 int size = AOP_SIZE (result);
8494 if (size >= LSB + offr)
8496 l = aopGet (left, LSB, FALSE, FALSE);
8498 emitcode ("add", "a,acc");
8499 if (sameRegs (AOP (left), AOP (result)) &&
8500 size >= MSB16 + offr && offr != LSB)
8501 emitcode ("xch", "a,%s",
8502 aopGet (left, LSB + offr, FALSE, FALSE));
8504 aopPut (result, "a", LSB + offr);
8507 if (size >= MSB16 + offr)
8509 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8511 l = aopGet (left, MSB16, FALSE, FALSE);
8514 emitcode ("rlc", "a");
8515 if (sameRegs (AOP (left), AOP (result)) &&
8516 size >= MSB24 + offr && offr != LSB)
8517 emitcode ("xch", "a,%s",
8518 aopGet (left, MSB16 + offr, FALSE, FALSE));
8520 aopPut (result, "a", MSB16 + offr);
8523 if (size >= MSB24 + offr)
8525 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8527 l = aopGet (left, MSB24, FALSE, FALSE);
8530 emitcode ("rlc", "a");
8531 if (sameRegs (AOP (left), AOP (result)) &&
8532 size >= MSB32 + offr && offr != LSB)
8533 emitcode ("xch", "a,%s",
8534 aopGet (left, MSB24 + offr, FALSE, FALSE));
8536 aopPut (result, "a", MSB24 + offr);
8539 if (size > MSB32 + offr)
8541 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8543 l = aopGet (left, MSB32, FALSE, FALSE);
8546 emitcode ("rlc", "a");
8547 aopPut (result, "a", MSB32 + offr);
8550 aopPut (result, zero, LSB);
8553 /*-----------------------------------------------------------------*/
8554 /* genlshFour - shift four byte by a known amount != 0 */
8555 /*-----------------------------------------------------------------*/
8557 genlshFour (operand * result, operand * left, int shCount)
8561 D (emitcode (";", "genlshFour"));
8563 size = AOP_SIZE (result);
8565 /* if shifting more that 3 bytes */
8570 /* lowest order of left goes to the highest
8571 order of the destination */
8572 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8574 movLeft2Result (left, LSB, result, MSB32, 0);
8575 aopPut (result, zero, LSB);
8576 aopPut (result, zero, MSB16);
8577 aopPut (result, zero, MSB24);
8581 /* more than two bytes */
8582 else if (shCount >= 16)
8584 /* lower order two bytes goes to higher order two bytes */
8586 /* if some more remaining */
8588 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8591 movLeft2Result (left, MSB16, result, MSB32, 0);
8592 movLeft2Result (left, LSB, result, MSB24, 0);
8594 aopPut (result, zero, MSB16);
8595 aopPut (result, zero, LSB);
8599 /* if more than 1 byte */
8600 else if (shCount >= 8)
8602 /* lower order three bytes goes to higher order three bytes */
8607 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8609 movLeft2Result (left, LSB, result, MSB16, 0);
8615 movLeft2Result (left, MSB24, result, MSB32, 0);
8616 movLeft2Result (left, MSB16, result, MSB24, 0);
8617 movLeft2Result (left, LSB, result, MSB16, 0);
8618 aopPut (result, zero, LSB);
8620 else if (shCount == 1)
8621 shiftLLong (left, result, MSB16);
8624 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8625 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8626 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8627 aopPut (result, zero, LSB);
8632 /* 1 <= shCount <= 7 */
8633 else if (shCount <= 2)
8635 shiftLLong (left, result, LSB);
8637 shiftLLong (result, result, LSB);
8639 /* 3 <= shCount <= 7, optimize */
8642 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8643 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8644 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8648 /*-----------------------------------------------------------------*/
8649 /* genLeftShiftLiteral - left shifting by known count */
8650 /*-----------------------------------------------------------------*/
8652 genLeftShiftLiteral (operand * left,
8657 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8660 D (emitcode (";", "genLeftShiftLiteral"));
8662 freeAsmop (right, NULL, ic, TRUE);
8664 aopOp (left, ic, FALSE);
8665 aopOp (result, ic, FALSE);
8667 size = getSize (operandType (result));
8670 emitcode ("; shift left ", "result %d, left %d", size,
8674 /* I suppose that the left size >= result size */
8679 movLeft2Result (left, size, result, size, 0);
8682 else if (shCount >= (size * 8))
8686 aopPut (result, zero, size);
8694 genlshOne (result, left, shCount);
8698 genlshTwo (result, left, shCount);
8702 genlshFour (result, left, shCount);
8705 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8706 "*** ack! mystery literal shift!\n");
8710 freeAsmop (result, NULL, ic, TRUE);
8711 freeAsmop (left, NULL, ic, TRUE);
8714 /*-----------------------------------------------------------------*/
8715 /* genLeftShift - generates code for left shifting */
8716 /*-----------------------------------------------------------------*/
8718 genLeftShift (iCode * ic)
8720 operand *left, *right, *result;
8723 symbol *tlbl, *tlbl1;
8726 D (emitcode (";", "genLeftShift"));
8728 right = IC_RIGHT (ic);
8729 left = IC_LEFT (ic);
8730 result = IC_RESULT (ic);
8732 aopOp (right, ic, FALSE);
8734 /* if the shift count is known then do it
8735 as efficiently as possible */
8736 if (AOP_TYPE (right) == AOP_LIT)
8738 genLeftShiftLiteral (left, right, result, ic);
8742 /* shift count is unknown then we have to form
8743 a loop get the loop count in B : Note: we take
8744 only the lower order byte since shifting
8745 more that 32 bits make no sense anyway, ( the
8746 largest size of an object can be only 32 bits ) */
8749 MOVB (aopGet (right, 0, FALSE, FALSE));
8750 emitcode ("inc", "b");
8751 freeAsmop (right, NULL, ic, TRUE);
8752 aopOp (left, ic, FALSE);
8753 aopOp (result, ic, FALSE);
8755 /* now move the left to the result if they are not the same */
8756 if (!sameRegs (AOP (left), AOP (result)) &&
8757 AOP_SIZE (result) > 1)
8760 size = AOP_SIZE (result);
8764 l = aopGet (left, offset, FALSE, TRUE);
8765 if (*l == '@' && (IS_AOP_PREG (result)))
8768 emitcode ("mov", "a,%s", l);
8769 aopPut (result, "a", offset);
8772 aopPut (result, l, offset);
8777 tlbl = newiTempLabel (NULL);
8778 size = AOP_SIZE (result);
8780 tlbl1 = newiTempLabel (NULL);
8782 /* if it is only one byte then */
8785 symbol *tlbl1 = newiTempLabel (NULL);
8787 l = aopGet (left, 0, FALSE, FALSE);
8789 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8791 emitcode ("add", "a,acc");
8793 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8795 aopPut (result, "a", 0);
8799 reAdjustPreg (AOP (result));
8801 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8803 l = aopGet (result, offset, FALSE, FALSE);
8805 emitcode ("add", "a,acc");
8806 aopPut (result, "a", offset++);
8809 l = aopGet (result, offset, FALSE, FALSE);
8811 emitcode ("rlc", "a");
8812 aopPut (result, "a", offset++);
8814 reAdjustPreg (AOP (result));
8817 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8820 freeAsmop (result, NULL, ic, TRUE);
8821 freeAsmop (left, NULL, ic, TRUE);
8824 /*-----------------------------------------------------------------*/
8825 /* genrshOne - right shift a one byte quantity by known count */
8826 /*-----------------------------------------------------------------*/
8828 genrshOne (operand * result, operand * left,
8829 int shCount, int sign)
8831 D (emitcode (";", "genrshOne"));
8833 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8836 /*-----------------------------------------------------------------*/
8837 /* genrshTwo - right shift two bytes by known amount != 0 */
8838 /*-----------------------------------------------------------------*/
8840 genrshTwo (operand * result, operand * left,
8841 int shCount, int sign)
8843 D (emitcode (";", "genrshTwo"));
8845 /* if shCount >= 8 */
8850 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8852 movLeft2Result (left, MSB16, result, LSB, sign);
8853 addSign (result, MSB16, sign);
8856 /* 1 <= shCount <= 7 */
8858 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8861 /*-----------------------------------------------------------------*/
8862 /* shiftRLong - shift right one long from left to result */
8863 /* offl = LSB or MSB16 */
8864 /*-----------------------------------------------------------------*/
8866 shiftRLong (operand * left, int offl,
8867 operand * result, int sign)
8869 bool useSameRegs = regsInCommon (left, result);
8871 if (useSameRegs && offl>1)
8873 // we are in big trouble, but this shouldn't happen
8874 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8877 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8884 emitcode ("rlc", "a");
8885 emitcode ("subb", "a,acc");
8886 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8888 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8892 aopPut (result, "a", MSB32);
8893 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8898 aopPut (result, zero, MSB32);
8904 emitcode ("clr", "c");
8908 emitcode ("mov", "c,acc.7");
8911 emitcode ("rrc", "a");
8913 if (useSameRegs && offl==MSB16 &&
8914 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8916 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8920 aopPut (result, "a", MSB32-offl);
8921 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8924 emitcode ("rrc", "a");
8925 if (useSameRegs && offl==1 &&
8926 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8928 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8932 aopPut (result, "a", MSB24-offl);
8933 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8935 emitcode ("rrc", "a");
8938 aopPut (result, "a", MSB16 - offl);
8943 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8945 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8949 aopPut (result, "a", MSB16 - offl);
8950 MOVA (aopGet (left, LSB, FALSE, FALSE));
8952 emitcode ("rrc", "a");
8953 aopPut (result, "a", LSB);
8957 /*-----------------------------------------------------------------*/
8958 /* genrshFour - shift four byte by a known amount != 0 */
8959 /*-----------------------------------------------------------------*/
8961 genrshFour (operand * result, operand * left,
8962 int shCount, int sign)
8964 D (emitcode (";", "genrshFour"));
8966 /* if shifting more that 3 bytes */
8971 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8973 movLeft2Result (left, MSB32, result, LSB, sign);
8974 addSign (result, MSB16, sign);
8976 else if (shCount >= 16)
8980 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8983 movLeft2Result (left, MSB24, result, LSB, 0);
8984 movLeft2Result (left, MSB32, result, MSB16, sign);
8986 addSign (result, MSB24, sign);
8988 else if (shCount >= 8)
8993 shiftRLong (left, MSB16, result, sign);
8995 else if (shCount == 0)
8997 movLeft2Result (left, MSB16, result, LSB, 0);
8998 movLeft2Result (left, MSB24, result, MSB16, 0);
8999 movLeft2Result (left, MSB32, result, MSB24, sign);
9000 addSign (result, MSB32, sign);
9004 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9005 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9006 /* the last shift is signed */
9007 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9008 addSign (result, MSB32, sign);
9013 /* 1 <= shCount <= 7 */
9016 shiftRLong (left, LSB, result, sign);
9018 shiftRLong (result, LSB, result, sign);
9022 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9023 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9024 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9029 /*-----------------------------------------------------------------*/
9030 /* genRightShiftLiteral - right shifting by known count */
9031 /*-----------------------------------------------------------------*/
9033 genRightShiftLiteral (operand * left,
9039 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9042 D (emitcode (";", "genRightShiftLiteral"));
9044 freeAsmop (right, NULL, ic, TRUE);
9046 aopOp (left, ic, FALSE);
9047 aopOp (result, ic, FALSE);
9050 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9054 size = getDataSize (left);
9055 /* test the LEFT size !!! */
9057 /* I suppose that the left size >= result size */
9060 size = getDataSize (result);
9062 movLeft2Result (left, size, result, size, 0);
9065 else if (shCount >= (size * 8))
9069 /* get sign in acc.7 */
9070 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9072 addSign (result, LSB, sign);
9079 genrshOne (result, left, shCount, sign);
9083 genrshTwo (result, left, shCount, sign);
9087 genrshFour (result, left, shCount, sign);
9093 freeAsmop (result, NULL, ic, TRUE);
9094 freeAsmop (left, NULL, ic, TRUE);
9097 /*-----------------------------------------------------------------*/
9098 /* genSignedRightShift - right shift of signed number */
9099 /*-----------------------------------------------------------------*/
9101 genSignedRightShift (iCode * ic)
9103 operand *right, *left, *result;
9106 symbol *tlbl, *tlbl1;
9109 D (emitcode (";", "genSignedRightShift"));
9111 /* we do it the hard way put the shift count in b
9112 and loop thru preserving the sign */
9114 right = IC_RIGHT (ic);
9115 left = IC_LEFT (ic);
9116 result = IC_RESULT (ic);
9118 aopOp (right, ic, FALSE);
9121 if (AOP_TYPE (right) == AOP_LIT)
9123 genRightShiftLiteral (left, right, result, ic, 1);
9126 /* shift count is unknown then we have to form
9127 a loop get the loop count in B : Note: we take
9128 only the lower order byte since shifting
9129 more that 32 bits make no sense anyway, ( the
9130 largest size of an object can be only 32 bits ) */
9133 MOVB (aopGet (right, 0, FALSE, FALSE));
9134 emitcode ("inc", "b");
9135 freeAsmop (right, NULL, ic, TRUE);
9136 aopOp (left, ic, FALSE);
9137 aopOp (result, ic, FALSE);
9139 /* now move the left to the result if they are not the
9141 if (!sameRegs (AOP (left), AOP (result)) &&
9142 AOP_SIZE (result) > 1)
9145 size = AOP_SIZE (result);
9149 l = aopGet (left, offset, FALSE, TRUE);
9150 if (*l == '@' && IS_AOP_PREG (result))
9153 emitcode ("mov", "a,%s", l);
9154 aopPut (result, "a", offset);
9157 aopPut (result, l, offset);
9162 /* mov the highest order bit to OVR */
9163 tlbl = newiTempLabel (NULL);
9164 tlbl1 = newiTempLabel (NULL);
9166 size = AOP_SIZE (result);
9168 MOVA (aopGet (left, offset, FALSE, FALSE));
9169 emitcode ("rlc", "a");
9170 emitcode ("mov", "ov,c");
9171 /* if it is only one byte then */
9174 l = aopGet (left, 0, FALSE, FALSE);
9176 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9178 emitcode ("mov", "c,ov");
9179 emitcode ("rrc", "a");
9181 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9183 aopPut (result, "a", 0);
9187 reAdjustPreg (AOP (result));
9188 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9190 emitcode ("mov", "c,ov");
9193 l = aopGet (result, offset, FALSE, FALSE);
9195 emitcode ("rrc", "a");
9196 aopPut (result, "a", offset--);
9198 reAdjustPreg (AOP (result));
9200 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9204 freeAsmop (result, NULL, ic, TRUE);
9205 freeAsmop (left, NULL, ic, TRUE);
9208 /*-----------------------------------------------------------------*/
9209 /* genRightShift - generate code for right shifting */
9210 /*-----------------------------------------------------------------*/
9212 genRightShift (iCode * ic)
9214 operand *right, *left, *result;
9218 symbol *tlbl, *tlbl1;
9221 D (emitcode (";", "genRightShift"));
9223 /* if signed then we do it the hard way preserve the
9224 sign bit moving it inwards */
9225 letype = getSpec (operandType (IC_LEFT (ic)));
9227 if (!SPEC_USIGN (letype))
9229 genSignedRightShift (ic);
9233 /* signed & unsigned types are treated the same : i.e. the
9234 signed is NOT propagated inwards : quoting from the
9235 ANSI - standard : "for E1 >> E2, is equivalent to division
9236 by 2**E2 if unsigned or if it has a non-negative value,
9237 otherwise the result is implementation defined ", MY definition
9238 is that the sign does not get propagated */
9240 right = IC_RIGHT (ic);
9241 left = IC_LEFT (ic);
9242 result = IC_RESULT (ic);
9244 aopOp (right, ic, FALSE);
9246 /* if the shift count is known then do it
9247 as efficiently as possible */
9248 if (AOP_TYPE (right) == AOP_LIT)
9250 genRightShiftLiteral (left, right, result, ic, 0);
9254 /* shift count is unknown then we have to form
9255 a loop get the loop count in B : Note: we take
9256 only the lower order byte since shifting
9257 more that 32 bits make no sense anyway, ( the
9258 largest size of an object can be only 32 bits ) */
9261 MOVB (aopGet (right, 0, FALSE, FALSE));
9262 emitcode ("inc", "b");
9263 freeAsmop (right, NULL, ic, TRUE);
9264 aopOp (left, ic, FALSE);
9265 aopOp (result, ic, FALSE);
9267 /* now move the left to the result if they are not the
9269 if (!sameRegs (AOP (left), AOP (result)) &&
9270 AOP_SIZE (result) > 1)
9272 size = AOP_SIZE (result);
9276 l = aopGet (left, offset, FALSE, TRUE);
9277 if (*l == '@' && IS_AOP_PREG (result))
9280 emitcode ("mov", "a,%s", l);
9281 aopPut (result, "a", offset);
9284 aopPut (result, l, offset);
9289 tlbl = newiTempLabel (NULL);
9290 tlbl1 = newiTempLabel (NULL);
9291 size = AOP_SIZE (result);
9294 /* if it is only one byte then */
9297 l = aopGet (left, 0, FALSE, FALSE);
9299 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9302 emitcode ("rrc", "a");
9304 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9306 aopPut (result, "a", 0);
9310 reAdjustPreg (AOP (result));
9311 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9316 l = aopGet (result, offset, FALSE, FALSE);
9318 emitcode ("rrc", "a");
9319 aopPut (result, "a", offset--);
9321 reAdjustPreg (AOP (result));
9324 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9328 freeAsmop (result, NULL, ic, TRUE);
9329 freeAsmop (left, NULL, ic, TRUE);
9332 /*-----------------------------------------------------------------*/
9333 /* emitPtrByteGet - emits code to get a byte into A through a */
9334 /* pointer register (R0, R1, or DPTR). The */
9335 /* original value of A can be preserved in B. */
9336 /*-----------------------------------------------------------------*/
9338 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9345 emitcode ("mov", "b,a");
9346 emitcode ("mov", "a,@%s", rname);
9351 emitcode ("mov", "b,a");
9352 emitcode ("movx", "a,@%s", rname);
9357 emitcode ("mov", "b,a");
9358 emitcode ("movx", "a,@dptr");
9363 emitcode ("mov", "b,a");
9364 emitcode ("clr", "a");
9365 emitcode ("movc", "a,@a+dptr");
9371 emitcode ("push", "b");
9372 emitcode ("push", "acc");
9374 emitcode ("lcall", "__gptrget");
9376 emitcode ("pop", "b");
9381 /*-----------------------------------------------------------------*/
9382 /* emitPtrByteSet - emits code to set a byte from src through a */
9383 /* pointer register (R0, R1, or DPTR). */
9384 /*-----------------------------------------------------------------*/
9386 emitPtrByteSet (char *rname, int p_type, char *src)
9395 emitcode ("mov", "@%s,a", rname);
9398 emitcode ("mov", "@%s,%s", rname, src);
9403 emitcode ("movx", "@%s,a", rname);
9408 emitcode ("movx", "@dptr,a");
9413 emitcode ("lcall", "__gptrput");
9418 /*-----------------------------------------------------------------*/
9419 /* genUnpackBits - generates code for unpacking bits */
9420 /*-----------------------------------------------------------------*/
9422 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9424 int offset = 0; /* result byte offset */
9425 int rsize; /* result size */
9426 int rlen = 0; /* remaining bitfield length */
9427 sym_link *etype; /* bitfield type information */
9428 int blen; /* bitfield length */
9429 int bstr; /* bitfield starting bit within byte */
9432 D(emitcode ("; genUnpackBits",""));
9434 etype = getSpec (operandType (result));
9435 rsize = getSize (operandType (result));
9436 blen = SPEC_BLEN (etype);
9437 bstr = SPEC_BSTR (etype);
9439 if (ifx && blen <= 8)
9441 emitPtrByteGet (rname, ptype, FALSE);
9444 SNPRINTF (buffer, sizeof(buffer),
9446 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9451 emitcode ("anl", "a,#0x%02x",
9452 (((unsigned char) -1) >> (8 - blen)) << bstr);
9453 genIfxJump (ifx, "a", NULL, NULL, NULL);
9459 /* If the bitfield length is less than a byte */
9462 emitPtrByteGet (rname, ptype, FALSE);
9464 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9465 if (!SPEC_USIGN (etype))
9467 /* signed bitfield */
9468 symbol *tlbl = newiTempLabel (NULL);
9470 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9471 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9474 aopPut (result, "a", offset++);
9478 /* Bit field did not fit in a byte. Copy all
9479 but the partial byte at the end. */
9480 for (rlen=blen;rlen>=8;rlen-=8)
9482 emitPtrByteGet (rname, ptype, FALSE);
9483 aopPut (result, "a", offset++);
9485 emitcode ("inc", "%s", rname);
9488 /* Handle the partial byte at the end */
9491 emitPtrByteGet (rname, ptype, FALSE);
9492 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9493 if (!SPEC_USIGN (etype))
9495 /* signed bitfield */
9496 symbol *tlbl = newiTempLabel (NULL);
9498 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9499 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9502 aopPut (result, "a", offset++);
9510 if (SPEC_USIGN (etype))
9514 /* signed bitfield: sign extension with 0x00 or 0xff */
9515 emitcode ("rlc", "a");
9516 emitcode ("subb", "a,acc");
9522 aopPut (result, source, offset++);
9527 /*-----------------------------------------------------------------*/
9528 /* genDataPointerGet - generates code when ptr offset is known */
9529 /*-----------------------------------------------------------------*/
9531 genDataPointerGet (operand * left,
9537 int size, offset = 0;
9539 D (emitcode (";", "genDataPointerGet"));
9541 aopOp (result, ic, TRUE);
9543 /* get the string representation of the name */
9544 l = aopGet (left, 0, FALSE, TRUE);
9545 size = AOP_SIZE (result);
9550 SNPRINTF (buffer, sizeof(buffer),
9551 "(%s + %d)", l + 1, offset);
9554 sprintf (buffer, "%s", l + 1);
9555 aopPut (result, buffer, offset++);
9558 freeAsmop (result, NULL, ic, TRUE);
9559 freeAsmop (left, NULL, ic, TRUE);
9562 /*-----------------------------------------------------------------*/
9563 /* genNearPointerGet - emitcode for near pointer fetch */
9564 /*-----------------------------------------------------------------*/
9566 genNearPointerGet (operand * left,
9575 sym_link *rtype, *retype;
9576 sym_link *ltype = operandType (left);
9579 D (emitcode (";", "genNearPointerGet"));
9581 rtype = operandType (result);
9582 retype = getSpec (rtype);
9584 aopOp (left, ic, FALSE);
9586 /* if left is rematerialisable and
9587 result is not bitfield variable type and
9588 the left is pointer to data space i.e
9589 lower 128 bytes of space */
9590 if (AOP_TYPE (left) == AOP_IMMD &&
9591 !IS_BITFIELD (retype) &&
9592 DCL_TYPE (ltype) == POINTER)
9594 genDataPointerGet (left, result, ic);
9598 /* if the value is already in a pointer register
9599 then don't need anything more */
9600 if (!AOP_INPREG (AOP (left)))
9602 if (IS_AOP_PREG (left))
9604 // Aha, it is a pointer, just in disguise.
9605 rname = aopGet (left, 0, FALSE, FALSE);
9608 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9609 __FILE__, __LINE__);
9614 emitcode ("mov", "a%s,%s", rname + 1, rname);
9615 rname++; // skip the '@'.
9620 /* otherwise get a free pointer register */
9622 preg = getFreePtr (ic, &aop, FALSE);
9623 emitcode ("mov", "%s,%s",
9625 aopGet (left, 0, FALSE, TRUE));
9630 rname = aopGet (left, 0, FALSE, FALSE);
9632 //aopOp (result, ic, FALSE);
9633 aopOp (result, ic, result?TRUE:FALSE);
9635 /* if bitfield then unpack the bits */
9636 if (IS_BITFIELD (retype))
9637 genUnpackBits (result, rname, POINTER, ifx);
9640 /* we have can just get the values */
9641 int size = AOP_SIZE (result);
9646 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9649 emitcode ("mov", "a,@%s", rname);
9651 aopPut (result, "a", offset);
9655 sprintf (buffer, "@%s", rname);
9656 aopPut (result, buffer, offset);
9660 emitcode ("inc", "%s", rname);
9664 /* now some housekeeping stuff */
9665 if (aop) /* we had to allocate for this iCode */
9667 if (pi) { /* post increment present */
9668 aopPut (left, rname, 0);
9670 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9674 /* we did not allocate which means left
9675 already in a pointer register, then
9676 if size > 0 && this could be used again
9677 we have to point it back to where it
9679 if ((AOP_SIZE (result) > 1 &&
9680 !OP_SYMBOL (left)->remat &&
9681 (OP_SYMBOL (left)->liveTo > ic->seq ||
9685 int size = AOP_SIZE (result) - 1;
9687 emitcode ("dec", "%s", rname);
9691 if (ifx && !ifx->generated)
9693 genIfxJump (ifx, "a", left, NULL, result);
9697 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9698 freeAsmop (left, NULL, ic, TRUE);
9699 if (pi) pi->generated = 1;
9702 /*-----------------------------------------------------------------*/
9703 /* genPagedPointerGet - emitcode for paged pointer fetch */
9704 /*-----------------------------------------------------------------*/
9706 genPagedPointerGet (operand * left,
9715 sym_link *rtype, *retype;
9717 D (emitcode (";", "genPagedPointerGet"));
9719 rtype = operandType (result);
9720 retype = getSpec (rtype);
9722 aopOp (left, ic, FALSE);
9724 /* if the value is already in a pointer register
9725 then don't need anything more */
9726 if (!AOP_INPREG (AOP (left)))
9728 /* otherwise get a free pointer register */
9730 preg = getFreePtr (ic, &aop, FALSE);
9731 emitcode ("mov", "%s,%s",
9733 aopGet (left, 0, FALSE, TRUE));
9737 rname = aopGet (left, 0, FALSE, FALSE);
9739 aopOp (result, ic, FALSE);
9741 /* if bitfield then unpack the bits */
9742 if (IS_BITFIELD (retype))
9743 genUnpackBits (result, rname, PPOINTER, ifx);
9746 /* we have can just get the values */
9747 int size = AOP_SIZE (result);
9753 emitcode ("movx", "a,@%s", rname);
9755 aopPut (result, "a", offset);
9760 emitcode ("inc", "%s", rname);
9764 /* now some housekeeping stuff */
9765 if (aop) /* we had to allocate for this iCode */
9768 aopPut (left, rname, 0);
9769 freeAsmop (NULL, aop, ic, TRUE);
9773 /* we did not allocate which means left
9774 already in a pointer register, then
9775 if size > 0 && this could be used again
9776 we have to point it back to where it
9778 if ((AOP_SIZE (result) > 1 &&
9779 !OP_SYMBOL (left)->remat &&
9780 (OP_SYMBOL (left)->liveTo > ic->seq ||
9784 int size = AOP_SIZE (result) - 1;
9786 emitcode ("dec", "%s", rname);
9790 if (ifx && !ifx->generated)
9792 genIfxJump (ifx, "a", left, NULL, result);
9796 freeAsmop (result, NULL, ic, TRUE);
9797 freeAsmop (left, NULL, ic, TRUE);
9798 if (pi) pi->generated = 1;
9801 /*--------------------------------------------------------------------*/
9802 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9803 /*--------------------------------------------------------------------*/
9805 loadDptrFromOperand (operand *op, bool loadBToo)
9807 if (AOP_TYPE (op) != AOP_STR)
9809 /* if this is rematerializable */
9810 if (AOP_TYPE (op) == AOP_IMMD)
9812 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9815 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9816 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9819 wassertl(FALSE, "need pointerCode");
9820 emitcode ("", "; mov b,???");
9821 /* genPointerGet and genPointerSet originally did different
9822 ** things for this case. Both seem wrong.
9823 ** from genPointerGet:
9824 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9825 ** from genPointerSet:
9826 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9831 else if (AOP_TYPE (op) == AOP_DPTR)
9835 MOVA (aopGet (op, 0, FALSE, FALSE));
9836 emitcode ("push", "acc");
9837 MOVA (aopGet (op, 1, FALSE, FALSE));
9838 emitcode ("push", "acc");
9839 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9840 emitcode ("pop", "dph");
9841 emitcode ("pop", "dpl");
9845 MOVA (aopGet (op, 0, FALSE, FALSE));
9846 emitcode ("push", "acc");
9847 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9848 emitcode ("pop", "dpl");
9852 { /* we need to get it byte by byte */
9853 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9854 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9856 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9861 /*-----------------------------------------------------------------*/
9862 /* genFarPointerGet - get value from far space */
9863 /*-----------------------------------------------------------------*/
9865 genFarPointerGet (operand * left,
9866 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9869 sym_link *retype = getSpec (operandType (result));
9871 D (emitcode (";", "genFarPointerGet"));
9873 aopOp (left, ic, FALSE);
9874 loadDptrFromOperand (left, FALSE);
9876 /* so dptr now contains the address */
9877 aopOp (result, ic, FALSE);
9879 /* if bit then unpack */
9880 if (IS_BITFIELD (retype))
9881 genUnpackBits (result, "dptr", FPOINTER, ifx);
9884 size = AOP_SIZE (result);
9889 emitcode ("movx", "a,@dptr");
9891 aopPut (result, "a", offset++);
9893 emitcode ("inc", "dptr");
9897 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9899 aopPut (left, "dpl", 0);
9900 aopPut (left, "dph", 1);
9904 if (ifx && !ifx->generated)
9906 genIfxJump (ifx, "a", left, NULL, result);
9909 freeAsmop (result, NULL, ic, TRUE);
9910 freeAsmop (left, NULL, ic, TRUE);
9913 /*-----------------------------------------------------------------*/
9914 /* genCodePointerGet - get value from code space */
9915 /*-----------------------------------------------------------------*/
9917 genCodePointerGet (operand * left,
9918 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9921 sym_link *retype = getSpec (operandType (result));
9923 D (emitcode (";", "genCodePointerGet"));
9925 aopOp (left, ic, FALSE);
9926 loadDptrFromOperand (left, FALSE);
9928 /* so dptr now contains the address */
9929 aopOp (result, ic, FALSE);
9931 /* if bit then unpack */
9932 if (IS_BITFIELD (retype))
9933 genUnpackBits (result, "dptr", CPOINTER, ifx);
9936 size = AOP_SIZE (result);
9941 emitcode ("clr", "a");
9942 emitcode ("movc", "a,@a+dptr");
9944 aopPut (result, "a", offset++);
9946 emitcode ("inc", "dptr");
9950 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9952 aopPut (left, "dpl", 0);
9953 aopPut (left, "dph", 1);
9957 if (ifx && !ifx->generated)
9959 genIfxJump (ifx, "a", left, NULL, result);
9962 freeAsmop (result, NULL, ic, TRUE);
9963 freeAsmop (left, NULL, ic, TRUE);
9966 /*-----------------------------------------------------------------*/
9967 /* genGenPointerGet - get value from generic pointer space */
9968 /*-----------------------------------------------------------------*/
9970 genGenPointerGet (operand * left,
9971 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9974 sym_link *retype = getSpec (operandType (result));
9976 D (emitcode (";", "genGenPointerGet"));
9978 aopOp (left, ic, FALSE);
9979 loadDptrFromOperand (left, TRUE);
9981 /* so dptr now contains the address */
9982 aopOp (result, ic, FALSE);
9984 /* if bit then unpack */
9985 if (IS_BITFIELD (retype))
9987 genUnpackBits (result, "dptr", GPOINTER, ifx);
9991 size = AOP_SIZE (result);
9996 emitcode ("lcall", "__gptrget");
9998 aopPut (result, "a", offset++);
10000 emitcode ("inc", "dptr");
10004 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10006 aopPut (left, "dpl", 0);
10007 aopPut (left, "dph", 1);
10011 if (ifx && !ifx->generated)
10013 genIfxJump (ifx, "a", left, NULL, result);
10016 freeAsmop (result, NULL, ic, TRUE);
10017 freeAsmop (left, NULL, ic, TRUE);
10020 /*-----------------------------------------------------------------*/
10021 /* genPointerGet - generate code for pointer get */
10022 /*-----------------------------------------------------------------*/
10024 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10026 operand *left, *result;
10027 sym_link *type, *etype;
10030 D (emitcode (";", "genPointerGet"));
10032 left = IC_LEFT (ic);
10033 result = IC_RESULT (ic);
10035 if (getSize (operandType (result))>1)
10038 /* depending on the type of pointer we need to
10039 move it to the correct pointer register */
10040 type = operandType (left);
10041 etype = getSpec (type);
10042 /* if left is of type of pointer then it is simple */
10043 if (IS_PTR (type) && !IS_FUNC (type->next))
10044 p_type = DCL_TYPE (type);
10047 /* we have to go by the storage class */
10048 p_type = PTR_TYPE (SPEC_OCLS (etype));
10051 /* special case when cast remat */
10052 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10053 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10055 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10056 type = operandType (left);
10057 p_type = DCL_TYPE (type);
10059 /* now that we have the pointer type we assign
10060 the pointer values */
10066 genNearPointerGet (left, result, ic, pi, ifx);
10070 genPagedPointerGet (left, result, ic, pi, ifx);
10074 genFarPointerGet (left, result, ic, pi, ifx);
10078 genCodePointerGet (left, result, ic, pi, ifx);
10082 genGenPointerGet (left, result, ic, pi, ifx);
10088 /*-----------------------------------------------------------------*/
10089 /* genPackBits - generates code for packed bit storage */
10090 /*-----------------------------------------------------------------*/
10092 genPackBits (sym_link * etype,
10094 char *rname, int p_type)
10096 int offset = 0; /* source byte offset */
10097 int rlen = 0; /* remaining bitfield length */
10098 int blen; /* bitfield length */
10099 int bstr; /* bitfield starting bit within byte */
10100 int litval; /* source literal value (if AOP_LIT) */
10101 unsigned char mask; /* bitmask within current byte */
10103 D(emitcode ("; genPackBits",""));
10105 blen = SPEC_BLEN (etype);
10106 bstr = SPEC_BSTR (etype);
10108 /* If the bitfield length is less than a byte */
10111 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10112 (unsigned char) (0xFF >> (8 - bstr)));
10114 if (AOP_TYPE (right) == AOP_LIT)
10116 /* Case with a bitfield length <8 and literal source
10118 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10120 litval &= (~mask) & 0xff;
10121 emitPtrByteGet (rname, p_type, FALSE);
10122 if ((mask|litval)!=0xff)
10123 emitcode ("anl","a,#0x%02x", mask);
10125 emitcode ("orl","a,#0x%02x", litval);
10129 if ((blen==1) && (p_type!=GPOINTER))
10131 /* Case with a bitfield length == 1 and no generic pointer
10133 if (AOP_TYPE (right) == AOP_CRY)
10134 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10137 MOVA (aopGet (right, 0, FALSE, FALSE));
10138 emitcode ("rrc","a");
10140 emitPtrByteGet (rname, p_type, FALSE);
10141 emitcode ("mov","acc.%d,c",bstr);
10146 /* Case with a bitfield length < 8 and arbitrary source
10148 MOVA (aopGet (right, 0, FALSE, FALSE));
10149 /* shift and mask source value */
10151 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10153 pushedB = pushB ();
10154 /* transfer A to B and get next byte */
10155 emitPtrByteGet (rname, p_type, TRUE);
10157 emitcode ("anl", "a,#0x%02x", mask);
10158 emitcode ("orl", "a,b");
10159 if (p_type == GPOINTER)
10160 emitcode ("pop", "b");
10166 emitPtrByteSet (rname, p_type, "a");
10170 /* Bit length is greater than 7 bits. In this case, copy */
10171 /* all except the partial byte at the end */
10172 for (rlen=blen;rlen>=8;rlen-=8)
10174 emitPtrByteSet (rname, p_type,
10175 aopGet (right, offset++, FALSE, TRUE) );
10177 emitcode ("inc", "%s", rname);
10180 /* If there was a partial byte at the end */
10183 mask = (((unsigned char) -1 << rlen) & 0xff);
10185 if (AOP_TYPE (right) == AOP_LIT)
10187 /* Case with partial byte and literal source
10189 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10190 litval >>= (blen-rlen);
10191 litval &= (~mask) & 0xff;
10192 emitPtrByteGet (rname, p_type, FALSE);
10193 if ((mask|litval)!=0xff)
10194 emitcode ("anl","a,#0x%02x", mask);
10196 emitcode ("orl","a,#0x%02x", litval);
10201 /* Case with partial byte and arbitrary source
10203 MOVA (aopGet (right, offset++, FALSE, FALSE));
10204 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10206 pushedB = pushB ();
10207 /* transfer A to B and get next byte */
10208 emitPtrByteGet (rname, p_type, TRUE);
10210 emitcode ("anl", "a,#0x%02x", mask);
10211 emitcode ("orl", "a,b");
10212 if (p_type == GPOINTER)
10213 emitcode ("pop", "b");
10217 emitPtrByteSet (rname, p_type, "a");
10222 /*-----------------------------------------------------------------*/
10223 /* genDataPointerSet - remat pointer to data space */
10224 /*-----------------------------------------------------------------*/
10226 genDataPointerSet (operand * right,
10230 int size, offset = 0;
10231 char *l, buffer[256];
10233 D (emitcode (";", "genDataPointerSet"));
10235 aopOp (right, ic, FALSE);
10237 l = aopGet (result, 0, FALSE, TRUE);
10238 size = AOP_SIZE (right);
10242 sprintf (buffer, "(%s + %d)", l + 1, offset);
10244 sprintf (buffer, "%s", l + 1);
10245 emitcode ("mov", "%s,%s", buffer,
10246 aopGet (right, offset++, FALSE, FALSE));
10249 freeAsmop (result, NULL, ic, TRUE);
10250 freeAsmop (right, NULL, ic, TRUE);
10253 /*-----------------------------------------------------------------*/
10254 /* genNearPointerSet - emitcode for near pointer put */
10255 /*-----------------------------------------------------------------*/
10257 genNearPointerSet (operand * right,
10265 sym_link *retype, *letype;
10266 sym_link *ptype = operandType (result);
10268 D (emitcode (";", "genNearPointerSet"));
10270 retype = getSpec (operandType (right));
10271 letype = getSpec (ptype);
10273 aopOp (result, ic, FALSE);
10275 /* if the result is rematerializable &
10276 in data space & not a bit variable */
10277 if (AOP_TYPE (result) == AOP_IMMD &&
10278 DCL_TYPE (ptype) == POINTER &&
10279 !IS_BITVAR (retype) &&
10280 !IS_BITVAR (letype))
10282 genDataPointerSet (right, result, ic);
10286 /* if the value is already in a pointer register
10287 then don't need anything more */
10288 if (!AOP_INPREG (AOP (result)))
10291 //AOP_TYPE (result) == AOP_STK
10292 IS_AOP_PREG(result)
10295 // Aha, it is a pointer, just in disguise.
10296 rname = aopGet (result, 0, FALSE, FALSE);
10299 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10300 __FILE__, __LINE__);
10305 emitcode ("mov", "a%s,%s", rname + 1, rname);
10306 rname++; // skip the '@'.
10311 /* otherwise get a free pointer register */
10312 aop = newAsmop (0);
10313 preg = getFreePtr (ic, &aop, FALSE);
10314 emitcode ("mov", "%s,%s",
10316 aopGet (result, 0, FALSE, TRUE));
10317 rname = preg->name;
10322 rname = aopGet (result, 0, FALSE, FALSE);
10325 aopOp (right, ic, FALSE);
10327 /* if bitfield then unpack the bits */
10328 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10329 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10332 /* we can just get the values */
10333 int size = AOP_SIZE (right);
10338 l = aopGet (right, offset, FALSE, TRUE);
10339 if ((*l == '@') || (strcmp (l, "acc") == 0))
10342 emitcode ("mov", "@%s,a", rname);
10345 emitcode ("mov", "@%s,%s", rname, l);
10347 emitcode ("inc", "%s", rname);
10352 /* now some housekeeping stuff */
10353 if (aop) /* we had to allocate for this iCode */
10356 aopPut (result, rname, 0);
10357 freeAsmop (NULL, aop, ic, TRUE);
10361 /* we did not allocate which means left
10362 already in a pointer register, then
10363 if size > 0 && this could be used again
10364 we have to point it back to where it
10366 if ((AOP_SIZE (right) > 1 &&
10367 !OP_SYMBOL (result)->remat &&
10368 (OP_SYMBOL (result)->liveTo > ic->seq ||
10372 int size = AOP_SIZE (right) - 1;
10374 emitcode ("dec", "%s", rname);
10379 if (pi) pi->generated = 1;
10380 freeAsmop (result, NULL, ic, TRUE);
10381 freeAsmop (right, NULL, ic, TRUE);
10384 /*-----------------------------------------------------------------*/
10385 /* genPagedPointerSet - emitcode for Paged pointer put */
10386 /*-----------------------------------------------------------------*/
10388 genPagedPointerSet (operand * right,
10396 sym_link *retype, *letype;
10398 D (emitcode (";", "genPagedPointerSet"));
10400 retype = getSpec (operandType (right));
10401 letype = getSpec (operandType (result));
10403 aopOp (result, ic, FALSE);
10405 /* if the value is already in a pointer register
10406 then don't need anything more */
10407 if (!AOP_INPREG (AOP (result)))
10409 /* otherwise get a free pointer register */
10410 aop = newAsmop (0);
10411 preg = getFreePtr (ic, &aop, FALSE);
10412 emitcode ("mov", "%s,%s",
10414 aopGet (result, 0, FALSE, TRUE));
10415 rname = preg->name;
10418 rname = aopGet (result, 0, FALSE, FALSE);
10420 aopOp (right, ic, FALSE);
10422 /* if bitfield then unpack the bits */
10423 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10424 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10427 /* we have can just get the values */
10428 int size = AOP_SIZE (right);
10433 l = aopGet (right, offset, FALSE, TRUE);
10435 emitcode ("movx", "@%s,a", rname);
10438 emitcode ("inc", "%s", rname);
10444 /* now some housekeeping stuff */
10445 if (aop) /* we had to allocate for this iCode */
10448 aopPut (result, rname, 0);
10449 freeAsmop (NULL, aop, ic, TRUE);
10453 /* we did not allocate which means left
10454 already in a pointer register, then
10455 if size > 0 && this could be used again
10456 we have to point it back to where it
10458 if (AOP_SIZE (right) > 1 &&
10459 !OP_SYMBOL (result)->remat &&
10460 (OP_SYMBOL (result)->liveTo > ic->seq ||
10463 int size = AOP_SIZE (right) - 1;
10465 emitcode ("dec", "%s", rname);
10470 if (pi) pi->generated = 1;
10471 freeAsmop (result, NULL, ic, TRUE);
10472 freeAsmop (right, NULL, ic, TRUE);
10475 /*-----------------------------------------------------------------*/
10476 /* genFarPointerSet - set value from far space */
10477 /*-----------------------------------------------------------------*/
10479 genFarPointerSet (operand * right,
10480 operand * result, iCode * ic, iCode * pi)
10483 sym_link *retype = getSpec (operandType (right));
10484 sym_link *letype = getSpec (operandType (result));
10486 D(emitcode ("; genFarPointerSet",""));
10488 aopOp (result, ic, FALSE);
10489 loadDptrFromOperand (result, FALSE);
10491 /* so dptr now contains the address */
10492 aopOp (right, ic, FALSE);
10494 /* if bit then unpack */
10495 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10496 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10499 size = AOP_SIZE (right);
10504 char *l = aopGet (right, offset++, FALSE, FALSE);
10506 emitcode ("movx", "@dptr,a");
10508 emitcode ("inc", "dptr");
10511 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10512 aopPut (result, "dpl", 0);
10513 aopPut (result, "dph", 1);
10516 freeAsmop (result, NULL, ic, TRUE);
10517 freeAsmop (right, NULL, ic, TRUE);
10520 /*-----------------------------------------------------------------*/
10521 /* genGenPointerSet - set value from generic pointer space */
10522 /*-----------------------------------------------------------------*/
10524 genGenPointerSet (operand * right,
10525 operand * result, iCode * ic, iCode * pi)
10528 sym_link *retype = getSpec (operandType (right));
10529 sym_link *letype = getSpec (operandType (result));
10531 D (emitcode (";", "genGenPointerSet"));
10533 aopOp (result, ic, FALSE);
10534 loadDptrFromOperand (result, TRUE);
10536 /* so dptr now contains the address */
10537 aopOp (right, ic, FALSE);
10539 /* if bit then unpack */
10540 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10542 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10546 size = AOP_SIZE (right);
10551 char *l = aopGet (right, offset++, FALSE, FALSE);
10553 emitcode ("lcall", "__gptrput");
10555 emitcode ("inc", "dptr");
10559 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10560 aopPut (result, "dpl", 0);
10561 aopPut (result, "dph", 1);
10564 freeAsmop (result, NULL, ic, TRUE);
10565 freeAsmop (right, NULL, ic, TRUE);
10568 /*-----------------------------------------------------------------*/
10569 /* genPointerSet - stores the value into a pointer location */
10570 /*-----------------------------------------------------------------*/
10572 genPointerSet (iCode * ic, iCode *pi)
10574 operand *right, *result;
10575 sym_link *type, *etype;
10578 D (emitcode (";", "genPointerSet"));
10580 right = IC_RIGHT (ic);
10581 result = IC_RESULT (ic);
10583 /* depending on the type of pointer we need to
10584 move it to the correct pointer register */
10585 type = operandType (result);
10586 etype = getSpec (type);
10587 /* if left is of type of pointer then it is simple */
10588 if (IS_PTR (type) && !IS_FUNC (type->next))
10590 p_type = DCL_TYPE (type);
10594 /* we have to go by the storage class */
10595 p_type = PTR_TYPE (SPEC_OCLS (etype));
10598 /* special case when cast remat */
10599 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10600 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10601 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10602 type = operandType (result);
10603 p_type = DCL_TYPE (type);
10606 /* now that we have the pointer type we assign
10607 the pointer values */
10613 genNearPointerSet (right, result, ic, pi);
10617 genPagedPointerSet (right, result, ic, pi);
10621 genFarPointerSet (right, result, ic, pi);
10625 genGenPointerSet (right, result, ic, pi);
10629 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10630 "genPointerSet: illegal pointer type");
10634 /*-----------------------------------------------------------------*/
10635 /* genIfx - generate code for Ifx statement */
10636 /*-----------------------------------------------------------------*/
10638 genIfx (iCode * ic, iCode * popIc)
10640 operand *cond = IC_COND (ic);
10644 D (emitcode (";", "genIfx"));
10646 aopOp (cond, ic, FALSE);
10648 /* get the value into acc */
10649 if (AOP_TYPE (cond) != AOP_CRY)
10656 if (AOP(cond)->aopu.aop_dir)
10657 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10660 /* the result is now in the accumulator or a directly addressable bit */
10661 freeAsmop (cond, NULL, ic, TRUE);
10663 /* if there was something to be popped then do it */
10667 /* if the condition is a bit variable */
10669 genIfxJump(ic, dup, NULL, NULL, NULL);
10670 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10671 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10672 else if (isbit && !IS_ITEMP (cond))
10673 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10675 genIfxJump (ic, "a", NULL, NULL, NULL);
10680 /*-----------------------------------------------------------------*/
10681 /* genAddrOf - generates code for address of */
10682 /*-----------------------------------------------------------------*/
10684 genAddrOf (iCode * ic)
10686 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10689 D (emitcode (";", "genAddrOf"));
10691 aopOp (IC_RESULT (ic), ic, FALSE);
10693 /* if the operand is on the stack then we
10694 need to get the stack offset of this
10698 /* if it has an offset then we need to compute it */
10701 emitcode ("mov", "a,%s", SYM_BP (sym));
10702 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10703 ((char) (sym->stack - _G.nRegsSaved)) :
10704 ((char) sym->stack)) & 0xff);
10705 aopPut (IC_RESULT (ic), "a", 0);
10709 /* we can just move _bp */
10710 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10712 /* fill the result with zero */
10713 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10718 aopPut (IC_RESULT (ic), zero, offset++);
10723 /* object not on stack then we need the name */
10724 size = AOP_SIZE (IC_RESULT (ic));
10729 char s[SDCC_NAME_MAX];
10731 sprintf (s, "#(%s >> %d)",
10735 sprintf (s, "#%s", sym->rname);
10736 aopPut (IC_RESULT (ic), s, offset++);
10740 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10744 /*-----------------------------------------------------------------*/
10745 /* genFarFarAssign - assignment when both are in far space */
10746 /*-----------------------------------------------------------------*/
10748 genFarFarAssign (operand * result, operand * right, iCode * ic)
10750 int size = AOP_SIZE (right);
10754 D (emitcode (";", "genFarFarAssign"));
10756 /* first push the right side on to the stack */
10759 l = aopGet (right, offset++, FALSE, FALSE);
10761 emitcode ("push", "acc");
10764 freeAsmop (right, NULL, ic, FALSE);
10765 /* now assign DPTR to result */
10766 aopOp (result, ic, FALSE);
10767 size = AOP_SIZE (result);
10770 emitcode ("pop", "acc");
10771 aopPut (result, "a", --offset);
10773 freeAsmop (result, NULL, ic, FALSE);
10776 /*-----------------------------------------------------------------*/
10777 /* genAssign - generate code for assignment */
10778 /*-----------------------------------------------------------------*/
10780 genAssign (iCode * ic)
10782 operand *result, *right;
10784 unsigned long lit = 0L;
10786 D (emitcode (";", "genAssign"));
10788 result = IC_RESULT (ic);
10789 right = IC_RIGHT (ic);
10791 /* if they are the same */
10792 if (operandsEqu (result, right) &&
10793 !isOperandVolatile (result, FALSE) &&
10794 !isOperandVolatile (right, FALSE))
10797 aopOp (right, ic, FALSE);
10799 /* special case both in far space */
10800 if (AOP_TYPE (right) == AOP_DPTR &&
10801 IS_TRUE_SYMOP (result) &&
10802 isOperandInFarSpace (result))
10804 genFarFarAssign (result, right, ic);
10808 aopOp (result, ic, TRUE);
10810 /* if they are the same registers */
10811 if (sameRegs (AOP (right), AOP (result)) &&
10812 !isOperandVolatile (result, FALSE) &&
10813 !isOperandVolatile (right, FALSE))
10816 /* if the result is a bit */
10817 if (AOP_TYPE (result) == AOP_CRY)
10819 /* if the right size is a literal then
10820 we know what the value is */
10821 if (AOP_TYPE (right) == AOP_LIT)
10823 if (((int) operandLitValue (right)))
10824 aopPut (result, one, 0);
10826 aopPut (result, zero, 0);
10830 /* the right is also a bit variable */
10831 if (AOP_TYPE (right) == AOP_CRY)
10833 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10834 aopPut (result, "c", 0);
10838 /* we need to or */
10840 aopPut (result, "a", 0);
10844 /* bit variables done */
10846 size = AOP_SIZE (result);
10848 if (AOP_TYPE (right) == AOP_LIT)
10849 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10852 (AOP_TYPE (result) != AOP_REG) &&
10853 (AOP_TYPE (right) == AOP_LIT) &&
10854 !IS_FLOAT (operandType (right)) &&
10857 while ((size) && (lit))
10860 aopGet (right, offset, FALSE, FALSE),
10866 /* And now fill the rest with zeros. */
10869 emitcode ("clr", "a");
10873 aopPut (result, "a", offset);
10882 aopGet (right, offset, FALSE, FALSE),
10889 freeAsmop (result, NULL, ic, TRUE);
10890 freeAsmop (right, NULL, ic, TRUE);
10893 /*-----------------------------------------------------------------*/
10894 /* genJumpTab - generates code for jump table */
10895 /*-----------------------------------------------------------------*/
10897 genJumpTab (iCode * ic)
10899 symbol *jtab,*jtablo,*jtabhi;
10901 unsigned int count;
10903 D (emitcode (";", "genJumpTab"));
10905 count = elementsInSet( IC_JTLABELS (ic) );
10909 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10910 if the switch argument is in a register.
10911 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10912 /* Peephole may not convert ljmp to sjmp or ret
10913 labelIsReturnOnly & labelInRange must check
10914 currPl->ic->op != JUMPTABLE */
10915 aopOp (IC_JTCOND (ic), ic, FALSE);
10916 /* get the condition into accumulator */
10917 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10919 /* multiply by three */
10920 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10922 emitcode ("mov", "b,#3");
10923 emitcode ("mul", "ab");
10927 emitcode ("add", "a,acc");
10928 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10930 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10932 jtab = newiTempLabel (NULL);
10933 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10934 emitcode ("jmp", "@a+dptr");
10936 /* now generate the jump labels */
10937 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10938 jtab = setNextItem (IC_JTLABELS (ic)))
10939 emitcode ("ljmp", "%05d$", jtab->key + 100);
10943 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10944 if the switch argument is in a register.
10945 For n>6 this algorithm may be more compact */
10946 jtablo = newiTempLabel (NULL);
10947 jtabhi = newiTempLabel (NULL);
10949 /* get the condition into accumulator.
10950 Using b as temporary storage, if register push/pop is needed */
10951 aopOp (IC_JTCOND (ic), ic, FALSE);
10952 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10953 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10954 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10956 // (MB) what if B is in use???
10957 wassertl(!BINUSE, "B was in use");
10958 emitcode ("mov", "b,%s", l);
10961 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10965 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10966 emitcode ("movc", "a,@a+pc");
10967 emitcode ("push", "acc");
10970 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10971 emitcode ("movc", "a,@a+pc");
10972 emitcode ("push", "acc");
10976 /* this scales up to n<=255, but needs two more bytes
10977 and changes dptr */
10978 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10979 emitcode ("movc", "a,@a+dptr");
10980 emitcode ("push", "acc");
10983 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10984 emitcode ("movc", "a,@a+dptr");
10985 emitcode ("push", "acc");
10988 emitcode ("ret", "");
10990 /* now generate jump table, LSB */
10991 emitLabel (jtablo);
10992 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10993 jtab = setNextItem (IC_JTLABELS (ic)))
10994 emitcode (".db", "%05d$", jtab->key + 100);
10996 /* now generate jump table, MSB */
10997 emitLabel (jtabhi);
10998 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10999 jtab = setNextItem (IC_JTLABELS (ic)))
11000 emitcode (".db", "%05d$>>8", jtab->key + 100);
11004 /*-----------------------------------------------------------------*/
11005 /* genCast - gen code for casting */
11006 /*-----------------------------------------------------------------*/
11008 genCast (iCode * ic)
11010 operand *result = IC_RESULT (ic);
11011 sym_link *ctype = operandType (IC_LEFT (ic));
11012 sym_link *rtype = operandType (IC_RIGHT (ic));
11013 operand *right = IC_RIGHT (ic);
11016 D (emitcode (";", "genCast"));
11018 /* if they are equivalent then do nothing */
11019 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11022 aopOp (right, ic, FALSE);
11023 aopOp (result, ic, FALSE);
11025 /* if the result is a bit (and not a bitfield) */
11026 if (IS_BIT (OP_SYMBOL (result)->type))
11028 /* if the right size is a literal then
11029 we know what the value is */
11030 if (AOP_TYPE (right) == AOP_LIT)
11032 if (((int) operandLitValue (right)))
11033 aopPut (result, one, 0);
11035 aopPut (result, zero, 0);
11040 /* the right is also a bit variable */
11041 if (AOP_TYPE (right) == AOP_CRY)
11043 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11044 aopPut (result, "c", 0);
11048 /* we need to or */
11050 aopPut (result, "a", 0);
11054 /* if they are the same size : or less */
11055 if (AOP_SIZE (result) <= AOP_SIZE (right))
11058 /* if they are in the same place */
11059 if (sameRegs (AOP (right), AOP (result)))
11062 /* if they in different places then copy */
11063 size = AOP_SIZE (result);
11068 aopGet (right, offset, FALSE, FALSE),
11075 /* if the result is of type pointer */
11076 if (IS_PTR (ctype))
11080 sym_link *type = operandType (right);
11081 sym_link *etype = getSpec (type);
11083 /* pointer to generic pointer */
11084 if (IS_GENPTR (ctype))
11088 p_type = DCL_TYPE (type);
11092 if (SPEC_SCLS(etype)==S_REGISTER) {
11093 // let's assume it is a generic pointer
11096 /* we have to go by the storage class */
11097 p_type = PTR_TYPE (SPEC_OCLS (etype));
11101 /* the first two bytes are known */
11102 size = GPTRSIZE - 1;
11107 aopGet (right, offset, FALSE, FALSE),
11111 /* the last byte depending on type */
11113 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11118 // pointerTypeToGPByte will have bitched.
11122 sprintf(gpValStr, "#0x%x", gpVal);
11123 aopPut (result, gpValStr, GPTRSIZE - 1);
11128 /* just copy the pointers */
11129 size = AOP_SIZE (result);
11134 aopGet (right, offset, FALSE, FALSE),
11141 /* so we now know that the size of destination is greater
11142 than the size of the source */
11143 /* we move to result for the size of source */
11144 size = AOP_SIZE (right);
11149 aopGet (right, offset, FALSE, FALSE),
11154 /* now depending on the sign of the source && destination */
11155 size = AOP_SIZE (result) - AOP_SIZE (right);
11156 /* if unsigned or not an integral type */
11157 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11160 aopPut (result, zero, offset++);
11164 /* we need to extend the sign :{ */
11165 char *l = aopGet (right, AOP_SIZE (right) - 1,
11168 emitcode ("rlc", "a");
11169 emitcode ("subb", "a,acc");
11171 aopPut (result, "a", offset++);
11174 /* we are done hurray !!!! */
11177 freeAsmop (result, NULL, ic, TRUE);
11178 freeAsmop (right, NULL, ic, TRUE);
11181 /*-----------------------------------------------------------------*/
11182 /* genDjnz - generate decrement & jump if not zero instrucion */
11183 /*-----------------------------------------------------------------*/
11185 genDjnz (iCode * ic, iCode * ifx)
11187 symbol *lbl, *lbl1;
11191 /* if the if condition has a false label
11192 then we cannot save */
11193 if (IC_FALSE (ifx))
11196 /* if the minus is not of the form a = a - 1 */
11197 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11198 !IS_OP_LITERAL (IC_RIGHT (ic)))
11201 if (operandLitValue (IC_RIGHT (ic)) != 1)
11204 /* if the size of this greater than one then no
11206 if (getSize (operandType (IC_RESULT (ic))) > 1)
11209 /* otherwise we can save BIG */
11211 D (emitcode (";", "genDjnz"));
11213 lbl = newiTempLabel (NULL);
11214 lbl1 = newiTempLabel (NULL);
11216 aopOp (IC_RESULT (ic), ic, FALSE);
11218 if (AOP_NEEDSACC(IC_RESULT(ic)))
11220 /* If the result is accessed indirectly via
11221 * the accumulator, we must explicitly write
11222 * it back after the decrement.
11224 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11226 if (strcmp(rByte, "a"))
11228 /* Something is hopelessly wrong */
11229 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11230 __FILE__, __LINE__);
11231 /* We can just give up; the generated code will be inefficient,
11232 * but what the hey.
11234 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11237 emitcode ("dec", "%s", rByte);
11238 aopPut (IC_RESULT (ic), rByte, 0);
11239 emitcode ("jnz", "%05d$", lbl->key + 100);
11241 else if (IS_AOP_PREG (IC_RESULT (ic)))
11243 emitcode ("dec", "%s",
11244 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11245 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11246 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11247 ifx->generated = 1;
11248 emitcode ("jnz", "%05d$", lbl->key + 100);
11252 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11255 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11257 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11260 if (!ifx->generated)
11261 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11262 ifx->generated = 1;
11266 /*-----------------------------------------------------------------*/
11267 /* genReceive - generate code for a receive iCode */
11268 /*-----------------------------------------------------------------*/
11270 genReceive (iCode * ic)
11272 int size = getSize (operandType (IC_RESULT (ic)));
11275 D (emitcode (";", "genReceive"));
11277 if (ic->argreg == 1)
11278 { /* first parameter */
11279 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11280 isOperandInPagedSpace (IC_RESULT (ic))) &&
11281 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11282 IS_TRUE_SYMOP (IC_RESULT (ic))))
11285 int receivingA = 0;
11288 for (offset = 0; offset<size; offset++)
11289 if (!strcmp (fReturn[offset], "a"))
11294 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11296 for (offset = size-1; offset>0; offset--)
11297 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11298 emitcode("mov","a,%s", fReturn[0]);
11300 aopOp (IC_RESULT (ic), ic, FALSE);
11302 aopPut (IC_RESULT (ic), "a", offset);
11303 for (offset = 1; offset<size; offset++)
11304 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11310 if (getTempRegs(tempRegs, size, ic))
11312 for (offset = 0; offset<size; offset++)
11313 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11314 aopOp (IC_RESULT (ic), ic, FALSE);
11315 for (offset = 0; offset<size; offset++)
11316 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11321 offset = fReturnSizeMCS51 - size;
11324 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11325 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11328 aopOp (IC_RESULT (ic), ic, FALSE);
11329 size = AOP_SIZE (IC_RESULT (ic));
11333 emitcode ("pop", "acc");
11334 aopPut (IC_RESULT (ic), "a", offset++);
11340 aopOp (IC_RESULT (ic), ic, FALSE);
11342 assignResultValue (IC_RESULT (ic), NULL);
11345 else if (ic->argreg > 12)
11346 { /* bit parameters */
11347 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11349 aopOp (IC_RESULT (ic), ic, FALSE);
11350 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11351 outBitC(IC_RESULT (ic));
11355 { /* other parameters */
11357 aopOp (IC_RESULT (ic), ic, FALSE);
11358 rb1off = ic->argreg;
11361 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11366 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11369 /*-----------------------------------------------------------------*/
11370 /* genDummyRead - generate code for dummy read of volatiles */
11371 /*-----------------------------------------------------------------*/
11373 genDummyRead (iCode * ic)
11378 D (emitcode(";", "genDummyRead"));
11380 op = IC_RIGHT (ic);
11381 if (op && IS_SYMOP (op))
11383 aopOp (op, ic, FALSE);
11385 /* if the result is a bit */
11386 if (AOP_TYPE (op) == AOP_CRY)
11387 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11390 /* bit variables done */
11392 size = AOP_SIZE (op);
11396 MOVA (aopGet (op, offset, FALSE, FALSE));
11401 freeAsmop (op, NULL, ic, TRUE);
11405 if (op && IS_SYMOP (op))
11407 aopOp (op, ic, FALSE);
11409 /* if the result is a bit */
11410 if (AOP_TYPE (op) == AOP_CRY)
11411 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11414 /* bit variables done */
11416 size = AOP_SIZE (op);
11420 MOVA (aopGet (op, offset, FALSE, FALSE));
11425 freeAsmop (op, NULL, ic, TRUE);
11429 /*-----------------------------------------------------------------*/
11430 /* genCritical - generate code for start of a critical sequence */
11431 /*-----------------------------------------------------------------*/
11433 genCritical (iCode *ic)
11435 symbol *tlbl = newiTempLabel (NULL);
11437 D (emitcode(";", "genCritical"));
11439 if (IC_RESULT (ic))
11441 aopOp (IC_RESULT (ic), ic, TRUE);
11442 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11443 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11444 aopPut (IC_RESULT (ic), zero, 0);
11446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11450 emitcode ("setb", "c");
11451 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11452 emitcode ("clr", "c");
11454 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11458 /*-----------------------------------------------------------------*/
11459 /* genEndCritical - generate code for end of a critical sequence */
11460 /*-----------------------------------------------------------------*/
11462 genEndCritical (iCode *ic)
11464 D(emitcode("; genEndCritical",""));
11468 aopOp (IC_RIGHT (ic), ic, FALSE);
11469 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11471 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11472 emitcode ("mov", "ea,c");
11476 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11477 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11478 emitcode ("rrc", "a");
11479 emitcode ("mov", "ea,c");
11481 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11485 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11486 emitcode ("mov", "ea,c");
11490 /*-----------------------------------------------------------------*/
11491 /* gen51Code - generate code for 8051 based controllers */
11492 /*-----------------------------------------------------------------*/
11494 gen51Code (iCode * lic)
11498 /* int cseq = 0; */
11500 _G.currentFunc = NULL;
11501 lineHead = lineCurr = NULL;
11503 /* print the allocation information */
11504 if (allocInfo && currFunc)
11505 printAllocInfo (currFunc, codeOutFile);
11506 /* if debug information required */
11507 if (options.debug && currFunc)
11509 debugFile->writeFunction (currFunc, lic);
11511 /* stack pointer name */
11512 if (options.useXstack)
11518 for (ic = lic; ic; ic = ic->next)
11520 _G.current_iCode = ic;
11522 if (ic->lineno && cln != ic->lineno)
11526 debugFile->writeCLine (ic);
11528 if (!options.noCcodeInAsm) {
11529 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11530 printCLine(ic->filename, ic->lineno));
11535 if (ic->seqPoint && ic->seqPoint != cseq)
11537 emitcode ("", "; sequence point %d", ic->seqPoint);
11538 cseq = ic->seqPoint;
11541 if (options.iCodeInAsm) {
11542 char regsInUse[80];
11546 for (i=0; i<8; i++) {
11547 sprintf (®sInUse[i],
11548 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11551 strcpy (regsInUse, "--------");
11552 for (i=0; i < 8; i++) {
11553 if (bitVectBitValue (ic->rMask, i))
11555 int offset = regs8051[i].offset;
11556 regsInUse[offset] = offset + '0'; /* show rMask */
11560 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11562 /* if the result is marked as
11563 spilt and rematerializable or code for
11564 this has already been generated then
11566 if (resultRemat (ic) || ic->generated)
11569 /* depending on the operation */
11589 /* IPOP happens only when trying to restore a
11590 spilt live range, if there is an ifx statement
11591 following this pop then the if statement might
11592 be using some of the registers being popped which
11593 would destory the contents of the register so
11594 we need to check for this condition and handle it */
11596 ic->next->op == IFX &&
11597 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11598 genIfx (ic->next, ic);
11616 genEndFunction (ic);
11636 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11653 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11657 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11664 /* note these two are xlated by algebraic equivalence
11665 during parsing SDCC.y */
11666 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11667 "got '>=' or '<=' shouldn't have come here");
11671 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11683 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11687 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11691 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11727 genRightShift (ic);
11730 case GET_VALUE_AT_ADDRESS:
11732 hasInc (IC_LEFT (ic), ic,
11733 getSize (operandType (IC_RESULT (ic)))),
11734 ifxForOp (IC_RESULT (ic), ic) );
11738 if (POINTER_SET (ic))
11740 hasInc (IC_RESULT (ic), ic,
11741 getSize (operandType (IC_RIGHT (ic)))));
11767 addSet (&_G.sendSet, ic);
11770 case DUMMY_READ_VOLATILE:
11779 genEndCritical (ic);
11791 _G.current_iCode = NULL;
11793 /* now we are ready to call the
11794 peep hole optimizer */
11795 if (!options.nopeep)
11796 peepHole (&lineHead);
11798 /* now do the actual printing */
11799 printLine (lineHead, codeOutFile);