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))
3682 emitcode ("mov", "sp,_bp");
3683 emitcode ("pop", "_bp");
3687 /* restore the register bank */
3688 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3690 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3691 || !options.useXstack)
3693 /* Special case of ISR using non-zero bank with useXstack
3696 emitcode ("pop", "psw");
3700 if (IFFUNC_ISISR (sym->type))
3703 /* now we need to restore the registers */
3704 /* if this isr has no bank i.e. is going to
3705 run with bank 0 , then we need to save more
3707 if (!FUNC_REGBANK (sym->type))
3710 /* if this function does not call any other
3711 function then we can be economical and
3712 save only those registers that are used */
3713 if (!IFFUNC_HASFCALL(sym->type))
3715 /* if any registers used */
3718 bool bits_popped = FALSE;
3719 /* save the registers used */
3720 for (i = sym->regsUsed->size; i >= 0; i--)
3722 if (bitVectBitValue (sym->regsUsed, i))
3723 bits_popped = popReg (i, bits_popped);
3729 if (options.parms_in_bank1) {
3730 for (i = 7 ; i >= 0 ; i-- ) {
3731 emitcode ("pop","%s",rb1regs[i]);
3734 /* this function has a function call cannot
3735 determines register usage so we will have to pop the
3737 unsaveRBank (0, ic, FALSE);
3742 /* This ISR uses a non-zero bank.
3744 * Restore any register banks saved by genFunction
3747 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3750 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3752 if (savedBanks & (1 << ix))
3754 unsaveRBank(ix, NULL, FALSE);
3758 if (options.useXstack)
3760 /* Restore bank AFTER calling unsaveRBank,
3761 * since it can trash r0.
3763 emitcode ("pop", "psw");
3767 if (!inExcludeList ("dph"))
3768 emitcode ("pop", "dph");
3769 if (!inExcludeList ("dpl"))
3770 emitcode ("pop", "dpl");
3771 if (!inExcludeList ("b"))
3772 emitcode ("pop", "b");
3773 if (!inExcludeList ("acc"))
3774 emitcode ("pop", "acc");
3776 /* if debug then send end of function */
3777 if (options.debug && currFunc)
3779 debugFile->writeEndFunction (currFunc, ic, 1);
3782 emitcode ("reti", "");
3786 if (IFFUNC_CALLEESAVES(sym->type))
3790 /* if any registers used */
3793 /* save the registers used */
3794 for (i = sym->regsUsed->size; i >= 0; i--)
3796 if (bitVectBitValue (sym->regsUsed, i) ||
3797 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3798 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3801 else if (mcs51_ptrRegReq)
3803 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3804 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3809 /* if debug then send end of function */
3810 if (options.debug && currFunc)
3812 debugFile->writeEndFunction (currFunc, ic, 1);
3815 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3817 emitcode ("ljmp", "__sdcc_banked_ret");
3821 emitcode ("ret", "");
3825 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3828 /* If this was an interrupt handler using bank 0 that called another */
3829 /* function, then all registers must be saved; nothing to optimized. */
3830 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3831 && !FUNC_REGBANK(sym->type))
3834 /* There are no push/pops to optimize if not callee-saves or ISR */
3835 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3838 /* If there were stack parameters, we cannot optimize without also */
3839 /* fixing all of the stack offsets; this is too dificult to consider. */
3840 if (FUNC_HASSTACKPARM(sym->type))
3843 /* Compute the registers actually used */
3844 regsUsed = newBitVect (mcs51_nRegs);
3845 regsUsedPrologue = newBitVect (mcs51_nRegs);
3848 if (lnp->ic && lnp->ic->op == FUNCTION)
3849 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3851 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3853 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3854 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3861 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3862 && !bitVectBitValue (regsUsed, CND_IDX))
3864 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3865 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3866 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3867 bitVectUnSetBit (regsUsed, CND_IDX);
3870 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3872 /* If this was an interrupt handler that called another function */
3873 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3874 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3876 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3877 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3878 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3879 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3880 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3883 /* Remove the unneeded push/pops */
3884 regsUnneeded = newBitVect (mcs51_nRegs);
3887 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3889 if (!strncmp(lnp->line, "push", 4))
3891 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3892 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3894 connectLine (lnp->prev, lnp->next);
3895 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3898 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3900 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3901 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3903 connectLine (lnp->prev, lnp->next);
3904 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3911 for (idx = 0; idx < regsUnneeded->size; idx++)
3912 if (bitVectBitValue (regsUnneeded, idx))
3913 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3915 freeBitVect (regsUnneeded);
3916 freeBitVect (regsUsed);
3917 freeBitVect (regsUsedPrologue);
3920 /*-----------------------------------------------------------------*/
3921 /* genRet - generate code for return statement */
3922 /*-----------------------------------------------------------------*/
3926 int size, offset = 0, pushed = 0;
3928 D (emitcode (";", "genRet"));
3930 /* if we have no return value then
3931 just generate the "ret" */
3935 /* we have something to return then
3936 move the return value into place */
3937 aopOp (IC_LEFT (ic), ic, FALSE);
3938 size = AOP_SIZE (IC_LEFT (ic));
3940 if (IS_BIT(_G.currentFunc->etype))
3942 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3949 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3952 l = aopGet (IC_LEFT (ic), offset++,
3954 emitcode ("push", "%s", l);
3959 l = aopGet (IC_LEFT (ic), offset,
3961 if (strcmp (fReturn[offset], l))
3962 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3969 if (strcmp (fReturn[pushed], "a"))
3970 emitcode ("pop", fReturn[pushed]);
3972 emitcode ("pop", "acc");
3974 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3977 /* generate a jump to the return label
3978 if the next is not the return statement */
3979 if (!(ic->next && ic->next->op == LABEL &&
3980 IC_LABEL (ic->next) == returnLabel))
3982 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3986 /*-----------------------------------------------------------------*/
3987 /* genLabel - generates a label */
3988 /*-----------------------------------------------------------------*/
3990 genLabel (iCode * ic)
3992 /* special case never generate */
3993 if (IC_LABEL (ic) == entryLabel)
3996 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3999 /*-----------------------------------------------------------------*/
4000 /* genGoto - generates a ljmp */
4001 /*-----------------------------------------------------------------*/
4003 genGoto (iCode * ic)
4005 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4008 /*-----------------------------------------------------------------*/
4009 /* findLabelBackwards: walks back through the iCode chain looking */
4010 /* for the given label. Returns number of iCode instructions */
4011 /* between that label and given ic. */
4012 /* Returns zero if label not found. */
4013 /*-----------------------------------------------------------------*/
4015 findLabelBackwards (iCode * ic, int key)
4024 /* If we have any pushes or pops, we cannot predict the distance.
4025 I don't like this at all, this should be dealt with in the
4027 if (ic->op == IPUSH || ic->op == IPOP) {
4031 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusIncr :- does addition with increment if possible */
4042 /*-----------------------------------------------------------------*/
4044 genPlusIncr (iCode * ic)
4046 unsigned int icount;
4047 unsigned int size = getDataSize (IC_RESULT (ic));
4049 /* will try to generate an increment */
4050 /* if the right side is not a literal
4052 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4055 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4057 D(emitcode ("; genPlusIncr",""));
4059 /* if increment >=16 bits in register or direct space */
4060 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4061 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4062 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4070 /* If the next instruction is a goto and the goto target
4071 * is < 10 instructions previous to this, we can generate
4072 * jumps straight to that target.
4074 if (ic->next && ic->next->op == GOTO
4075 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4076 && labelRange <= 10)
4078 emitcode (";", "tail increment optimized");
4079 tlbl = IC_LABEL (ic->next);
4084 tlbl = newiTempLabel (NULL);
4087 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4089 IS_AOP_PREG (IC_RESULT (ic)))
4090 emitcode ("cjne", "%s,#0x00,%05d$",
4091 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4095 emitcode ("clr", "a");
4096 emitcode ("cjne", "a,%s,%05d$",
4097 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4101 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4104 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4105 IS_AOP_PREG (IC_RESULT (ic)))
4106 emitcode ("cjne", "%s,#0x00,%05d$",
4107 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4110 emitcode ("cjne", "a,%s,%05d$",
4111 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4114 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4118 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119 IS_AOP_PREG (IC_RESULT (ic)))
4120 emitcode ("cjne", "%s,#0x00,%05d$",
4121 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4125 emitcode ("cjne", "a,%s,%05d$",
4126 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4129 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4139 /* if result is dptr */
4140 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4141 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4142 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4143 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4145 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4151 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4154 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4155 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4157 emitcode ("inc", "dptr");
4162 /* if the literal value of the right hand side
4163 is greater than 4 then it is not worth it */
4167 /* if the sizes are greater than 1 then we cannot */
4168 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4169 AOP_SIZE (IC_LEFT (ic)) > 1)
4172 /* we can if the aops of the left & result match or
4173 if they are in registers and the registers are the
4175 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4179 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4180 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4181 aopPut (IC_RESULT (ic), "a", 0);
4187 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4197 /*-----------------------------------------------------------------*/
4198 /* outBitAcc - output a bit in acc */
4199 /*-----------------------------------------------------------------*/
4201 outBitAcc (operand * result)
4203 symbol *tlbl = newiTempLabel (NULL);
4204 /* if the result is a bit */
4205 if (AOP_TYPE (result) == AOP_CRY)
4207 aopPut (result, "a", 0);
4211 emitcode ("jz", "%05d$", tlbl->key + 100);
4212 emitcode ("mov", "a,%s", one);
4218 /*-----------------------------------------------------------------*/
4219 /* genPlusBits - generates code for addition of two bits */
4220 /*-----------------------------------------------------------------*/
4222 genPlusBits (iCode * ic)
4224 D (emitcode (";", "genPlusBits"));
4226 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4228 symbol *lbl = newiTempLabel (NULL);
4229 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4230 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4231 emitcode ("cpl", "c");
4233 outBitC (IC_RESULT (ic));
4237 emitcode ("clr", "a");
4238 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4239 emitcode ("rlc", "a");
4240 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4241 emitcode ("addc", "a,#0x00");
4242 outAcc (IC_RESULT (ic));
4247 /* This is the original version of this code.
4249 * This is being kept around for reference,
4250 * because I am not entirely sure I got it right...
4253 adjustArithmeticResult (iCode * ic)
4255 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4256 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4257 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4258 aopPut (IC_RESULT (ic),
4259 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4262 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4263 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4264 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4265 aopPut (IC_RESULT (ic),
4266 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4269 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4270 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4271 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4272 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4273 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4276 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4277 aopPut (IC_RESULT (ic), buffer, 2);
4281 /* This is the pure and virtuous version of this code.
4282 * I'm pretty certain it's right, but not enough to toss the old
4286 adjustArithmeticResult (iCode * ic)
4288 if (opIsGptr (IC_RESULT (ic)) &&
4289 opIsGptr (IC_LEFT (ic)) &&
4290 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4292 aopPut (IC_RESULT (ic),
4293 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4297 if (opIsGptr (IC_RESULT (ic)) &&
4298 opIsGptr (IC_RIGHT (ic)) &&
4299 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4301 aopPut (IC_RESULT (ic),
4302 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4306 if (opIsGptr (IC_RESULT (ic)) &&
4307 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4308 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4309 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4313 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4314 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4319 /*-----------------------------------------------------------------*/
4320 /* genPlus - generates code for addition */
4321 /*-----------------------------------------------------------------*/
4323 genPlus (iCode * ic)
4325 int size, offset = 0;
4328 bool swappedLR = FALSE;
4329 operand *leftOp, *rightOp;
4332 D (emitcode (";", "genPlus"));
4334 /* special cases :- */
4336 aopOp (IC_LEFT (ic), ic, FALSE);
4337 aopOp (IC_RIGHT (ic), ic, FALSE);
4338 aopOp (IC_RESULT (ic), ic, TRUE);
4340 /* if literal, literal on the right or
4341 if left requires ACC or right is already
4343 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4344 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4345 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4347 operand *t = IC_RIGHT (ic);
4348 IC_RIGHT (ic) = IC_LEFT (ic);
4353 /* if both left & right are in bit
4355 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4356 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4362 /* if left in bit space & right literal */
4363 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4364 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4366 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4367 /* if result in bit space */
4368 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4370 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4371 emitcode ("cpl", "c");
4372 outBitC (IC_RESULT (ic));
4376 size = getDataSize (IC_RESULT (ic));
4379 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4380 emitcode ("addc", "a,#00");
4381 aopPut (IC_RESULT (ic), "a", offset++);
4387 /* if I can do an increment instead
4388 of add then GOOD for ME */
4389 if (genPlusIncr (ic) == TRUE)
4392 size = getDataSize (IC_RESULT (ic));
4393 leftOp = IC_LEFT(ic);
4394 rightOp = IC_RIGHT(ic);
4397 /* if this is an add for an array access
4398 at a 256 byte boundary */
4400 && AOP_TYPE (op) == AOP_IMMD
4402 && IS_SPEC (OP_SYM_ETYPE (op))
4403 && SPEC_ABSA (OP_SYM_ETYPE (op))
4404 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4407 D(emitcode ("; genPlus aligned array",""));
4408 aopPut (IC_RESULT (ic),
4409 aopGet (rightOp, 0, FALSE, FALSE),
4412 if( 1 == getDataSize (IC_RIGHT (ic)) )
4414 aopPut (IC_RESULT (ic),
4415 aopGet (leftOp, 1, FALSE, FALSE),
4420 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4421 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4422 aopPut (IC_RESULT (ic), "a", 1);
4427 /* if the lower bytes of a literal are zero skip the addition */
4428 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4430 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4431 (skip_bytes+1 < size))
4436 D(emitcode ("; genPlus shortcut",""));
4441 if( offset >= skip_bytes )
4443 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4446 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4448 emitcode("xch", "a,b");
4449 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4450 emitcode (add, "a,b");
4453 else if (aopGetUsesAcc (leftOp, offset))
4455 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4456 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4460 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4461 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4463 aopPut (IC_RESULT (ic), "a", offset);
4464 add = "addc"; /* further adds must propagate carry */
4468 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4469 isOperandVolatile (IC_RESULT (ic), FALSE))
4472 aopPut (IC_RESULT (ic),
4473 aopGet (leftOp, offset, FALSE, FALSE),
4480 adjustArithmeticResult (ic);
4483 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4486 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4487 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4491 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4492 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4496 /*-----------------------------------------------------------------*/
4497 /* genMinusDec :- does subtraction with decrement if possible */
4498 /*-----------------------------------------------------------------*/
4500 genMinusDec (iCode * ic)
4502 unsigned int icount;
4503 unsigned int size = getDataSize (IC_RESULT (ic));
4505 /* will try to generate an increment */
4506 /* if the right side is not a literal
4508 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4511 /* if the literal value of the right hand side
4512 is greater than 4 then it is not worth it */
4513 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4516 D(emitcode ("; genMinusDec",""));
4518 /* if decrement >=16 bits in register or direct space */
4519 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4520 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4528 /* If the next instruction is a goto and the goto target
4529 * is <= 10 instructions previous to this, we can generate
4530 * jumps straight to that target.
4532 if (ic->next && ic->next->op == GOTO
4533 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4534 && labelRange <= 10)
4536 emitcode (";", "tail decrement optimized");
4537 tlbl = IC_LABEL (ic->next);
4542 tlbl = newiTempLabel (NULL);
4546 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4547 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4548 IS_AOP_PREG (IC_RESULT (ic)))
4549 emitcode ("cjne", "%s,#0xff,%05d$"
4550 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4554 emitcode ("mov", "a,#0xff");
4555 emitcode ("cjne", "a,%s,%05d$"
4556 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4559 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4562 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4563 IS_AOP_PREG (IC_RESULT (ic)))
4564 emitcode ("cjne", "%s,#0xff,%05d$"
4565 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4569 emitcode ("cjne", "a,%s,%05d$"
4570 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4573 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4577 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4578 IS_AOP_PREG (IC_RESULT (ic)))
4579 emitcode ("cjne", "%s,#0xff,%05d$"
4580 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4584 emitcode ("cjne", "a,%s,%05d$"
4585 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4588 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4597 /* if the sizes are greater than 1 then we cannot */
4598 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4599 AOP_SIZE (IC_LEFT (ic)) > 1)
4602 /* we can if the aops of the left & result match or
4603 if they are in registers and the registers are the
4605 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4609 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4611 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4616 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4621 emitcode ("dec", "%s", l);
4624 if (AOP_NEEDSACC (IC_RESULT (ic)))
4625 aopPut (IC_RESULT (ic), "a", 0);
4633 /*-----------------------------------------------------------------*/
4634 /* addSign - complete with sign */
4635 /*-----------------------------------------------------------------*/
4637 addSign (operand * result, int offset, int sign)
4639 int size = (getDataSize (result) - offset);
4644 emitcode ("rlc", "a");
4645 emitcode ("subb", "a,acc");
4648 aopPut (result, "a", offset++);
4655 aopPut (result, zero, offset++);
4661 /*-----------------------------------------------------------------*/
4662 /* genMinusBits - generates code for subtraction of two bits */
4663 /*-----------------------------------------------------------------*/
4665 genMinusBits (iCode * ic)
4667 symbol *lbl = newiTempLabel (NULL);
4669 D (emitcode (";", "genMinusBits"));
4671 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4673 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4674 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4675 emitcode ("cpl", "c");
4677 outBitC (IC_RESULT (ic));
4681 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4682 emitcode ("subb", "a,acc");
4683 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4684 emitcode ("inc", "a");
4686 aopPut (IC_RESULT (ic), "a", 0);
4687 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4691 /*-----------------------------------------------------------------*/
4692 /* genMinus - generates code for subtraction */
4693 /*-----------------------------------------------------------------*/
4695 genMinus (iCode * ic)
4697 int size, offset = 0;
4699 D (emitcode (";", "genMinus"));
4701 aopOp (IC_LEFT (ic), ic, FALSE);
4702 aopOp (IC_RIGHT (ic), ic, FALSE);
4703 aopOp (IC_RESULT (ic), ic, TRUE);
4705 /* special cases :- */
4706 /* if both left & right are in bit space */
4707 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4708 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4714 /* if I can do an decrement instead
4715 of subtract then GOOD for ME */
4716 if (genMinusDec (ic) == TRUE)
4719 size = getDataSize (IC_RESULT (ic));
4721 /* if literal, add a,#-lit, else normal subb */
4722 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4724 unsigned long lit = 0L;
4725 bool useCarry = FALSE;
4727 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4732 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4734 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4735 if (!offset && !size && lit== (unsigned long) -1)
4737 emitcode ("dec", "a");
4741 /* first add without previous c */
4742 emitcode ("add", "a,#0x%02x",
4743 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4748 emitcode ("addc", "a,#0x%02x",
4749 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4751 aopPut (IC_RESULT (ic), "a", offset++);
4755 /* no need to add zeroes */
4756 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4758 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4767 operand *leftOp, *rightOp;
4769 leftOp = IC_LEFT(ic);
4770 rightOp = IC_RIGHT(ic);
4774 if (aopGetUsesAcc(rightOp, offset)) {
4775 if (aopGetUsesAcc(leftOp, offset)) {
4778 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4780 emitcode ("mov", "b,a");
4783 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4784 emitcode ("subb", "a,b");
4787 /* reverse subtraction with 2's complement */
4789 emitcode( "setb", "c");
4791 emitcode( "cpl", "c");
4792 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4793 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4794 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4795 emitcode("cpl", "a");
4796 if (size) /* skip if last byte */
4797 emitcode( "cpl", "c");
4800 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4803 emitcode ("subb", "a,%s",
4804 aopGet(rightOp, offset, FALSE, TRUE));
4807 aopPut (IC_RESULT (ic), "a", offset++);
4811 adjustArithmeticResult (ic);
4814 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4815 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4820 /*-----------------------------------------------------------------*/
4821 /* genMultbits :- multiplication of bits */
4822 /*-----------------------------------------------------------------*/
4824 genMultbits (operand * left,
4828 D (emitcode (";", "genMultbits"));
4830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4831 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4835 /*-----------------------------------------------------------------*/
4836 /* genMultOneByte : 8*8=8/16 bit multiplication */
4837 /*-----------------------------------------------------------------*/
4839 genMultOneByte (operand * left,
4844 int size = AOP_SIZE (result);
4845 bool runtimeSign, compiletimeSign;
4846 bool lUnsigned, rUnsigned, pushedB;
4848 D (emitcode (";", "genMultOneByte"));
4850 if (size < 1 || size > 2)
4852 /* this should never happen */
4853 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4854 AOP_SIZE(result), __FILE__, lineno);
4858 /* (if two literals: the value is computed before) */
4859 /* if one literal, literal on the right */
4860 if (AOP_TYPE (left) == AOP_LIT)
4865 /* emitcode (";", "swapped left and right"); */
4867 /* if no literal, unsigned on the right: shorter code */
4868 if ( AOP_TYPE (right) != AOP_LIT
4869 && SPEC_USIGN (getSpec (operandType (left))))
4876 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4877 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4881 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4882 no need to take care about the signedness! */
4883 || (lUnsigned && rUnsigned))
4885 /* just an unsigned 8 * 8 = 8 multiply
4887 /* emitcode (";","unsigned"); */
4888 /* TODO: check for accumulator clash between left & right aops? */
4890 if (AOP_TYPE (right) == AOP_LIT)
4892 /* moving to accumulator first helps peepholes */
4893 MOVA (aopGet (left, 0, FALSE, FALSE));
4894 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4898 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899 MOVA (aopGet (left, 0, FALSE, FALSE));
4902 emitcode ("mul", "ab");
4903 aopPut (result, "a", 0);
4905 aopPut (result, "b", 1);
4911 /* we have to do a signed multiply */
4912 /* emitcode (";", "signed"); */
4914 /* now sign adjust for both left & right */
4916 /* let's see what's needed: */
4917 /* apply negative sign during runtime */
4918 runtimeSign = FALSE;
4919 /* negative sign from literals */
4920 compiletimeSign = FALSE;
4924 if (AOP_TYPE(left) == AOP_LIT)
4926 /* signed literal */
4927 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4929 compiletimeSign = TRUE;
4932 /* signed but not literal */
4938 if (AOP_TYPE(right) == AOP_LIT)
4940 /* signed literal */
4941 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4943 compiletimeSign ^= TRUE;
4946 /* signed but not literal */
4950 /* initialize F0, which stores the runtime sign */
4953 if (compiletimeSign)
4954 emitcode ("setb", "F0"); /* set sign flag */
4956 emitcode ("clr", "F0"); /* reset sign flag */
4959 /* save the signs of the operands */
4960 if (AOP_TYPE(right) == AOP_LIT)
4962 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4964 if (!rUnsigned && val < 0)
4965 emitcode ("mov", "b,#0x%02x", -val);
4967 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4969 else /* ! literal */
4971 if (rUnsigned) /* emitcode (";", "signed"); */
4972 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4975 MOVA (aopGet (right, 0, FALSE, FALSE));
4976 lbl = newiTempLabel (NULL);
4977 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4978 emitcode ("cpl", "F0"); /* complement sign flag */
4979 emitcode ("cpl", "a"); /* 2's complement */
4980 emitcode ("inc", "a");
4982 emitcode ("mov", "b,a");
4986 if (AOP_TYPE(left) == AOP_LIT)
4988 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4990 if (!lUnsigned && val < 0)
4991 emitcode ("mov", "a,#0x%02x", -val);
4993 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4995 else /* ! literal */
4997 MOVA (aopGet (left, 0, FALSE, FALSE));
5001 lbl = newiTempLabel (NULL);
5002 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5003 emitcode ("cpl", "F0"); /* complement sign flag */
5004 emitcode ("cpl", "a"); /* 2's complement */
5005 emitcode ("inc", "a");
5010 /* now the multiplication */
5011 emitcode ("mul", "ab");
5012 if (runtimeSign || compiletimeSign)
5014 lbl = newiTempLabel (NULL);
5016 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5017 emitcode ("cpl", "a"); /* lsb 2's complement */
5019 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5022 emitcode ("add", "a,#1"); /* this sets carry flag */
5023 emitcode ("xch", "a,b");
5024 emitcode ("cpl", "a"); /* msb 2's complement */
5025 emitcode ("addc", "a,#0");
5026 emitcode ("xch", "a,b");
5030 aopPut (result, "a", 0);
5032 aopPut (result, "b", 1);
5037 /*-----------------------------------------------------------------*/
5038 /* genMult - generates code for multiplication */
5039 /*-----------------------------------------------------------------*/
5041 genMult (iCode * ic)
5043 operand *left = IC_LEFT (ic);
5044 operand *right = IC_RIGHT (ic);
5045 operand *result = IC_RESULT (ic);
5047 D (emitcode (";", "genMult"));
5049 /* assign the asmops */
5050 aopOp (left, ic, FALSE);
5051 aopOp (right, ic, FALSE);
5052 aopOp (result, ic, TRUE);
5054 /* special cases first */
5056 if (AOP_TYPE (left) == AOP_CRY &&
5057 AOP_TYPE (right) == AOP_CRY)
5059 genMultbits (left, right, result);
5063 /* if both are of size == 1 */
5064 #if 0 // one of them can be a sloc shared with the result
5065 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5067 if (getSize(operandType(left)) == 1 &&
5068 getSize(operandType(right)) == 1)
5071 genMultOneByte (left, right, result);
5075 /* should have been converted to function call */
5076 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5077 getSize(OP_SYMBOL(right)->type));
5081 freeAsmop (result, NULL, ic, TRUE);
5082 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5083 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086 /*-----------------------------------------------------------------*/
5087 /* genDivbits :- division of bits */
5088 /*-----------------------------------------------------------------*/
5090 genDivbits (operand * left,
5097 D(emitcode ("; genDivbits",""));
5101 /* the result must be bit */
5102 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5103 l = aopGet (left, 0, FALSE, FALSE);
5107 emitcode ("div", "ab");
5108 emitcode ("rrc", "a");
5112 aopPut (result, "c", 0);
5115 /*-----------------------------------------------------------------*/
5116 /* genDivOneByte : 8 bit division */
5117 /*-----------------------------------------------------------------*/
5119 genDivOneByte (operand * left,
5123 bool lUnsigned, rUnsigned, pushedB;
5124 bool runtimeSign, compiletimeSign;
5125 bool accuse = FALSE;
5126 bool pushedA = FALSE;
5130 D(emitcode ("; genDivOneByte",""));
5132 /* Why is it necessary that genDivOneByte() can return an int result?
5135 volatile unsigned char uc;
5136 volatile signed char sc1, sc2;
5149 In all cases a one byte result would overflow, the following cast to int
5150 would return the wrong result.
5152 Two possible solution:
5153 a) cast operands to int, if ((unsigned) / (signed)) or
5154 ((signed) / (signed))
5155 b) return an 16 bit signed int; this is what we're doing here!
5158 size = AOP_SIZE (result) - 1;
5160 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5161 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5165 /* signed or unsigned */
5166 if (lUnsigned && rUnsigned)
5168 /* unsigned is easy */
5169 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5170 MOVA (aopGet (left, 0, FALSE, FALSE));
5171 emitcode ("div", "ab");
5172 aopPut (result, "a", 0);
5174 aopPut (result, zero, offset++);
5180 /* signed is a little bit more difficult */
5182 /* now sign adjust for both left & right */
5184 /* let's see what's needed: */
5185 /* apply negative sign during runtime */
5186 runtimeSign = FALSE;
5187 /* negative sign from literals */
5188 compiletimeSign = FALSE;
5192 if (AOP_TYPE(left) == AOP_LIT)
5194 /* signed literal */
5195 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5197 compiletimeSign = TRUE;
5200 /* signed but not literal */
5206 if (AOP_TYPE(right) == AOP_LIT)
5208 /* signed literal */
5209 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5211 compiletimeSign ^= TRUE;
5214 /* signed but not literal */
5218 /* initialize F0, which stores the runtime sign */
5221 if (compiletimeSign)
5222 emitcode ("setb", "F0"); /* set sign flag */
5224 emitcode ("clr", "F0"); /* reset sign flag */
5227 /* save the signs of the operands */
5228 if (AOP_TYPE(right) == AOP_LIT)
5230 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5232 if (!rUnsigned && val < 0)
5233 emitcode ("mov", "b,#0x%02x", -val);
5235 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5237 else /* ! literal */
5240 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5243 MOVA (aopGet (right, 0, FALSE, FALSE));
5244 lbl = newiTempLabel (NULL);
5245 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5246 emitcode ("cpl", "F0"); /* complement sign flag */
5247 emitcode ("cpl", "a"); /* 2's complement */
5248 emitcode ("inc", "a");
5250 emitcode ("mov", "b,a");
5254 if (AOP_TYPE(left) == AOP_LIT)
5256 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5258 if (!lUnsigned && val < 0)
5259 emitcode ("mov", "a,#0x%02x", -val);
5261 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5263 else /* ! literal */
5265 MOVA (aopGet (left, 0, FALSE, FALSE));
5269 lbl = newiTempLabel (NULL);
5270 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5271 emitcode ("cpl", "F0"); /* complement sign flag */
5272 emitcode ("cpl", "a"); /* 2's complement */
5273 emitcode ("inc", "a");
5278 /* now the division */
5279 emitcode ("div", "ab");
5281 if (runtimeSign || compiletimeSign)
5283 lbl = newiTempLabel (NULL);
5285 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5286 emitcode ("cpl", "a"); /* lsb 2's complement */
5287 emitcode ("inc", "a");
5290 accuse = aopPut (result, "a", 0);
5293 /* msb is 0x00 or 0xff depending on the sign */
5298 emitcode ("push", "acc");
5301 emitcode ("mov", "c,F0");
5302 emitcode ("subb", "a,acc");
5304 aopPut (result, "a", offset++);
5306 else /* compiletimeSign */
5308 if (aopPutUsesAcc (result, "#0xFF", offset))
5310 emitcode ("push", "acc");
5314 aopPut (result, "#0xff", offset++);
5320 aopPut (result, "a", 0);
5322 aopPut (result, zero, offset++);
5326 emitcode ("pop", "acc");
5330 /*-----------------------------------------------------------------*/
5331 /* genDiv - generates code for division */
5332 /*-----------------------------------------------------------------*/
5336 operand *left = IC_LEFT (ic);
5337 operand *right = IC_RIGHT (ic);
5338 operand *result = IC_RESULT (ic);
5340 D (emitcode (";", "genDiv"));
5342 /* assign the amsops */
5343 aopOp (left, ic, FALSE);
5344 aopOp (right, ic, FALSE);
5345 aopOp (result, ic, TRUE);
5347 /* special cases first */
5349 if (AOP_TYPE (left) == AOP_CRY &&
5350 AOP_TYPE (right) == AOP_CRY)
5352 genDivbits (left, right, result);
5356 /* if both are of size == 1 */
5357 if (AOP_SIZE (left) == 1 &&
5358 AOP_SIZE (right) == 1)
5360 genDivOneByte (left, right, result);
5364 /* should have been converted to function call */
5367 freeAsmop (result, NULL, ic, TRUE);
5368 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5369 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372 /*-----------------------------------------------------------------*/
5373 /* genModbits :- modulus of bits */
5374 /*-----------------------------------------------------------------*/
5376 genModbits (operand * left,
5383 D(emitcode ("; genModbits",""));
5387 /* the result must be bit */
5388 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5389 l = aopGet (left, 0, FALSE, FALSE);
5393 emitcode ("div", "ab");
5394 emitcode ("mov", "a,b");
5395 emitcode ("rrc", "a");
5399 aopPut (result, "c", 0);
5402 /*-----------------------------------------------------------------*/
5403 /* genModOneByte : 8 bit modulus */
5404 /*-----------------------------------------------------------------*/
5406 genModOneByte (operand * left,
5410 bool lUnsigned, rUnsigned, pushedB;
5411 bool runtimeSign, compiletimeSign;
5415 D(emitcode ("; genModOneByte",""));
5417 size = AOP_SIZE (result) - 1;
5419 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5420 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5422 /* if right is a literal, check it for 2^n */
5423 if (AOP_TYPE(right) == AOP_LIT)
5425 unsigned char val = abs((int) operandLitValue(right));
5426 symbol *lbl2 = NULL;
5430 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5439 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5440 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5441 /* because iCode should have been changed to genAnd */
5442 /* see file "SDCCopt.c", function "convertToFcall()" */
5444 MOVA (aopGet (left, 0, FALSE, FALSE));
5445 emitcode ("mov", "c,acc.7");
5446 emitcode ("anl", "a,#0x%02x", val - 1);
5447 lbl = newiTempLabel (NULL);
5448 emitcode ("jz", "%05d$", (lbl->key + 100));
5449 emitcode ("jnc", "%05d$", (lbl->key + 100));
5450 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5456 aopPut (result, "a", 0);
5458 aopPut (result, "#0xff", offs2++);
5459 lbl2 = newiTempLabel (NULL);
5460 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5463 aopPut (result, "a", 0);
5465 aopPut (result, zero, offset++);
5479 /* signed or unsigned */
5480 if (lUnsigned && rUnsigned)
5482 /* unsigned is easy */
5483 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5484 MOVA (aopGet (left, 0, FALSE, FALSE));
5485 emitcode ("div", "ab");
5486 aopPut (result, "b", 0);
5488 aopPut (result, zero, offset++);
5494 /* signed is a little bit more difficult */
5496 /* now sign adjust for both left & right */
5498 /* modulus: sign of the right operand has no influence on the result! */
5499 if (AOP_TYPE(right) == AOP_LIT)
5501 signed char val = (char) operandLitValue(right);
5503 if (!rUnsigned && val < 0)
5504 emitcode ("mov", "b,#0x%02x", -val);
5506 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5508 else /* not literal */
5511 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5514 MOVA (aopGet (right, 0, FALSE, FALSE));
5515 lbl = newiTempLabel (NULL);
5516 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5517 emitcode ("cpl", "a"); /* 2's complement */
5518 emitcode ("inc", "a");
5520 emitcode ("mov", "b,a");
5524 /* let's see what's needed: */
5525 /* apply negative sign during runtime */
5526 runtimeSign = FALSE;
5527 /* negative sign from literals */
5528 compiletimeSign = FALSE;
5530 /* sign adjust left side */
5531 if (AOP_TYPE(left) == AOP_LIT)
5533 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5535 if (!lUnsigned && val < 0)
5537 compiletimeSign = TRUE; /* set sign flag */
5538 emitcode ("mov", "a,#0x%02x", -val);
5541 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5543 else /* ! literal */
5545 MOVA (aopGet (left, 0, FALSE, FALSE));
5550 emitcode ("clr", "F0"); /* clear sign flag */
5552 lbl = newiTempLabel (NULL);
5553 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5554 emitcode ("setb", "F0"); /* set sign flag */
5555 emitcode ("cpl", "a"); /* 2's complement */
5556 emitcode ("inc", "a");
5561 /* now the modulus */
5562 emitcode ("div", "ab");
5564 if (runtimeSign || compiletimeSign)
5566 emitcode ("mov", "a,b");
5567 lbl = newiTempLabel (NULL);
5569 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5570 emitcode ("cpl", "a"); /* 2's complement */
5571 emitcode ("inc", "a");
5574 aopPut (result, "a", 0);
5577 /* msb is 0x00 or 0xff depending on the sign */
5580 emitcode ("mov", "c,F0");
5581 emitcode ("subb", "a,acc");
5583 aopPut (result, "a", offset++);
5585 else /* compiletimeSign */
5587 aopPut (result, "#0xff", offset++);
5592 aopPut (result, "b", 0);
5594 aopPut (result, zero, offset++);
5600 /*-----------------------------------------------------------------*/
5601 /* genMod - generates code for division */
5602 /*-----------------------------------------------------------------*/
5606 operand *left = IC_LEFT (ic);
5607 operand *right = IC_RIGHT (ic);
5608 operand *result = IC_RESULT (ic);
5610 D (emitcode (";", "genMod"));
5612 /* assign the asmops */
5613 aopOp (left, ic, FALSE);
5614 aopOp (right, ic, FALSE);
5615 aopOp (result, ic, TRUE);
5617 /* special cases first */
5619 if (AOP_TYPE (left) == AOP_CRY &&
5620 AOP_TYPE (right) == AOP_CRY)
5622 genModbits (left, right, result);
5626 /* if both are of size == 1 */
5627 if (AOP_SIZE (left) == 1 &&
5628 AOP_SIZE (right) == 1)
5630 genModOneByte (left, right, result);
5634 /* should have been converted to function call */
5638 freeAsmop (result, NULL, ic, TRUE);
5639 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5640 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5643 /*-----------------------------------------------------------------*/
5644 /* genIfxJump :- will create a jump depending on the ifx */
5645 /*-----------------------------------------------------------------*/
5647 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5650 symbol *tlbl = newiTempLabel (NULL);
5653 D (emitcode (";", "genIfxJump"));
5655 /* if true label then we jump if condition
5659 jlbl = IC_TRUE (ic);
5660 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5661 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5665 /* false label is present */
5666 jlbl = IC_FALSE (ic);
5667 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5668 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5670 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5671 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5673 emitcode (inst, "%05d$", tlbl->key + 100);
5674 freeForBranchAsmop (result);
5675 freeForBranchAsmop (right);
5676 freeForBranchAsmop (left);
5677 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5680 /* mark the icode as generated */
5684 /*-----------------------------------------------------------------*/
5685 /* genCmp :- greater or less than comparison */
5686 /*-----------------------------------------------------------------*/
5688 genCmp (operand * left, operand * right,
5689 operand * result, iCode * ifx, int sign, iCode *ic)
5691 int size, offset = 0;
5692 unsigned long lit = 0L;
5695 D (emitcode (";", "genCmp"));
5697 /* if left & right are bit variables */
5698 if (AOP_TYPE (left) == AOP_CRY &&
5699 AOP_TYPE (right) == AOP_CRY)
5701 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5702 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5706 /* subtract right from left if at the
5707 end the carry flag is set then we know that
5708 left is greater than right */
5709 size = max (AOP_SIZE (left), AOP_SIZE (right));
5711 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5712 if ((size == 1) && !sign &&
5713 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5715 symbol *lbl = newiTempLabel (NULL);
5716 emitcode ("cjne", "%s,%s,%05d$",
5717 aopGet (left, offset, FALSE, FALSE),
5718 aopGet (right, offset, FALSE, FALSE),
5724 if (AOP_TYPE (right) == AOP_LIT)
5726 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5727 /* optimize if(x < 0) or if(x >= 0) */
5736 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5737 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5739 genIfxJump (ifx, "acc.7", left, right, result);
5740 freeAsmop (right, NULL, ic, TRUE);
5741 freeAsmop (left, NULL, ic, TRUE);
5747 emitcode ("rlc", "a");
5756 bool pushedB = FALSE;
5757 rightInB = aopGetUsesAcc(right, offset);
5761 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5763 MOVA (aopGet (left, offset, FALSE, FALSE));
5764 if (sign && size == 0)
5766 emitcode ("xrl", "a,#0x80");
5767 if (AOP_TYPE (right) == AOP_LIT)
5769 unsigned long lit = (unsigned long)
5770 floatFromVal (AOP (right)->aopu.aop_lit);
5771 emitcode ("subb", "a,#0x%02x",
5772 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5780 MOVB (aopGet (right, offset, FALSE, FALSE));
5782 emitcode ("xrl", "b,#0x80");
5783 emitcode ("subb", "a,b");
5789 emitcode ("subb", "a,b");
5791 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5801 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5803 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5809 /* if the result is used in the next
5810 ifx conditional branch then generate
5811 code a little differently */
5814 genIfxJump (ifx, "c", NULL, NULL, result);
5820 /* leave the result in acc */
5824 /*-----------------------------------------------------------------*/
5825 /* genCmpGt :- greater than comparison */
5826 /*-----------------------------------------------------------------*/
5828 genCmpGt (iCode * ic, iCode * ifx)
5830 operand *left, *right, *result;
5831 sym_link *letype, *retype;
5834 D (emitcode (";", "genCmpGt"));
5836 left = IC_LEFT (ic);
5837 right = IC_RIGHT (ic);
5838 result = IC_RESULT (ic);
5840 letype = getSpec (operandType (left));
5841 retype = getSpec (operandType (right));
5842 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5843 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5844 /* assign the amsops */
5845 aopOp (result, ic, TRUE);
5846 aopOp (left, ic, FALSE);
5847 aopOp (right, ic, FALSE);
5849 genCmp (right, left, result, ifx, sign, ic);
5851 freeAsmop (result, NULL, ic, TRUE);
5854 /*-----------------------------------------------------------------*/
5855 /* genCmpLt - less than comparisons */
5856 /*-----------------------------------------------------------------*/
5858 genCmpLt (iCode * ic, iCode * ifx)
5860 operand *left, *right, *result;
5861 sym_link *letype, *retype;
5864 D (emitcode (";", "genCmpLt"));
5866 left = IC_LEFT (ic);
5867 right = IC_RIGHT (ic);
5868 result = IC_RESULT (ic);
5870 letype = getSpec (operandType (left));
5871 retype = getSpec (operandType (right));
5872 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5873 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5874 /* assign the amsops */
5875 aopOp (result, ic, TRUE);
5876 aopOp (left, ic, FALSE);
5877 aopOp (right, ic, FALSE);
5879 genCmp (left, right, result, ifx, sign, ic);
5881 freeAsmop (result, NULL, ic, TRUE);
5884 /*-----------------------------------------------------------------*/
5885 /* gencjneshort - compare and jump if not equal */
5886 /*-----------------------------------------------------------------*/
5888 gencjneshort (operand * left, operand * right, symbol * lbl)
5890 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5892 unsigned long lit = 0L;
5894 D (emitcode (";", "gencjneshort"));
5896 /* if the left side is a literal or
5897 if the right is in a pointer register and left
5899 if ((AOP_TYPE (left) == AOP_LIT) ||
5900 (AOP_TYPE (left) == AOP_IMMD) ||
5901 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5908 if (AOP_TYPE (right) == AOP_LIT)
5909 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5911 /* if the right side is a literal then anything goes */
5912 if (AOP_TYPE (right) == AOP_LIT &&
5913 AOP_TYPE (left) != AOP_DIR &&
5914 AOP_TYPE (left) != AOP_IMMD)
5918 emitcode ("cjne", "%s,%s,%05d$",
5919 aopGet (left, offset, FALSE, FALSE),
5920 aopGet (right, offset, FALSE, FALSE),
5926 /* if the right side is in a register or in direct space or
5927 if the left is a pointer register & right is not */
5928 else if (AOP_TYPE (right) == AOP_REG ||
5929 AOP_TYPE (right) == AOP_DIR ||
5930 AOP_TYPE (right) == AOP_LIT ||
5931 AOP_TYPE (right) == AOP_IMMD ||
5932 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5933 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5937 MOVA (aopGet (left, offset, FALSE, FALSE));
5938 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5939 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5940 emitcode ("jnz", "%05d$", lbl->key + 100);
5942 emitcode ("cjne", "a,%s,%05d$",
5943 aopGet (right, offset, FALSE, TRUE),
5950 /* right is a pointer reg need both a & b */
5953 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5954 wassertl(!BINUSE, "B was in use");
5955 MOVB (aopGet (left, offset, FALSE, FALSE));
5956 MOVA (aopGet (right, offset, FALSE, FALSE));
5957 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5963 /*-----------------------------------------------------------------*/
5964 /* gencjne - compare and jump if not equal */
5965 /*-----------------------------------------------------------------*/
5967 gencjne (operand * left, operand * right, symbol * lbl)
5969 symbol *tlbl = newiTempLabel (NULL);
5971 D (emitcode (";", "gencjne"));
5973 gencjneshort (left, right, lbl);
5975 emitcode ("mov", "a,%s", one);
5976 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5978 emitcode ("clr", "a");
5982 /*-----------------------------------------------------------------*/
5983 /* genCmpEq - generates code for equal to */
5984 /*-----------------------------------------------------------------*/
5986 genCmpEq (iCode * ic, iCode * ifx)
5988 bool swappedLR = FALSE;
5989 operand *left, *right, *result;
5991 D (emitcode (";", "genCmpEq"));
5993 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5994 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5995 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5997 /* if literal, literal on the right or
5998 if the right is in a pointer register and left
6000 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6001 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6003 operand *t = IC_RIGHT (ic);
6004 IC_RIGHT (ic) = IC_LEFT (ic);
6009 if (ifx && !AOP_SIZE (result))
6012 /* if they are both bit variables */
6013 if (AOP_TYPE (left) == AOP_CRY &&
6014 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6016 if (AOP_TYPE (right) == AOP_LIT)
6018 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6021 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6022 emitcode ("cpl", "c");
6026 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6030 emitcode ("clr", "c");
6032 /* AOP_TYPE(right) == AOP_CRY */
6036 symbol *lbl = newiTempLabel (NULL);
6037 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6038 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6039 emitcode ("cpl", "c");
6042 /* if true label then we jump if condition
6044 tlbl = newiTempLabel (NULL);
6047 emitcode ("jnc", "%05d$", tlbl->key + 100);
6048 freeForBranchAsmop (result);
6049 freeForBranchAsmop (right);
6050 freeForBranchAsmop (left);
6051 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6055 emitcode ("jc", "%05d$", tlbl->key + 100);
6056 freeForBranchAsmop (result);
6057 freeForBranchAsmop (right);
6058 freeForBranchAsmop (left);
6059 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6065 tlbl = newiTempLabel (NULL);
6066 gencjneshort (left, right, tlbl);
6069 freeForBranchAsmop (result);
6070 freeForBranchAsmop (right);
6071 freeForBranchAsmop (left);
6072 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6077 symbol *lbl = newiTempLabel (NULL);
6078 emitcode ("sjmp", "%05d$", lbl->key + 100);
6080 freeForBranchAsmop (result);
6081 freeForBranchAsmop (right);
6082 freeForBranchAsmop (left);
6083 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6087 /* mark the icode as generated */
6092 /* if they are both bit variables */
6093 if (AOP_TYPE (left) == AOP_CRY &&
6094 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6096 if (AOP_TYPE (right) == AOP_LIT)
6098 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6101 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6102 emitcode ("cpl", "c");
6106 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6110 emitcode ("clr", "c");
6112 /* AOP_TYPE(right) == AOP_CRY */
6116 symbol *lbl = newiTempLabel (NULL);
6117 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6118 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6119 emitcode ("cpl", "c");
6123 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6130 genIfxJump (ifx, "c", left, right, result);
6133 /* if the result is used in an arithmetic operation
6134 then put the result in place */
6139 gencjne (left, right, newiTempLabel (NULL));
6140 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6142 aopPut (result, "a", 0);
6147 genIfxJump (ifx, "a", left, right, result);
6150 /* if the result is used in an arithmetic operation
6151 then put the result in place */
6152 if (AOP_TYPE (result) != AOP_CRY)
6154 /* leave the result in acc */
6158 freeAsmop (result, NULL, ic, TRUE);
6161 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6162 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6166 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6167 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6171 /*-----------------------------------------------------------------*/
6172 /* ifxForOp - returns the icode containing the ifx for operand */
6173 /*-----------------------------------------------------------------*/
6175 ifxForOp (operand * op, iCode * ic)
6177 /* if true symbol then needs to be assigned */
6178 if (IS_TRUE_SYMOP (op))
6181 /* if this has register type condition and
6182 the next instruction is ifx with the same operand
6183 and live to of the operand is upto the ifx only then */
6185 ic->next->op == IFX &&
6186 IC_COND (ic->next)->key == op->key &&
6187 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6193 /*-----------------------------------------------------------------*/
6194 /* hasInc - operand is incremented before any other use */
6195 /*-----------------------------------------------------------------*/
6197 hasInc (operand *op, iCode *ic, int osize)
6199 sym_link *type = operandType(op);
6200 sym_link *retype = getSpec (type);
6201 iCode *lic = ic->next;
6204 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6205 if (!IS_SYMOP(op)) return NULL;
6207 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6208 if (IS_AGGREGATE(type->next)) return NULL;
6209 if (osize != (isize = getSize(type->next))) return NULL;
6212 /* if operand of the form op = op + <sizeof *op> */
6213 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6214 isOperandEqual(IC_RESULT(lic),op) &&
6215 isOperandLiteral(IC_RIGHT(lic)) &&
6216 operandLitValue(IC_RIGHT(lic)) == isize) {
6219 /* if the operand used or deffed */
6220 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6223 /* if GOTO or IFX */
6224 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6230 /*-----------------------------------------------------------------*/
6231 /* genAndOp - for && operation */
6232 /*-----------------------------------------------------------------*/
6234 genAndOp (iCode * ic)
6236 operand *left, *right, *result;
6239 D (emitcode (";", "genAndOp"));
6241 /* note here that && operations that are in an
6242 if statement are taken away by backPatchLabels
6243 only those used in arthmetic operations remain */
6244 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6245 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6246 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6248 /* if both are bit variables */
6249 if (AOP_TYPE (left) == AOP_CRY &&
6250 AOP_TYPE (right) == AOP_CRY)
6252 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6253 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6258 tlbl = newiTempLabel (NULL);
6260 emitcode ("jz", "%05d$", tlbl->key + 100);
6266 freeAsmop (result, NULL, ic, TRUE);
6267 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6272 /*-----------------------------------------------------------------*/
6273 /* genOrOp - for || operation */
6274 /*-----------------------------------------------------------------*/
6276 genOrOp (iCode * ic)
6278 operand *left, *right, *result;
6281 D (emitcode (";", "genOrOp"));
6283 /* note here that || operations that are in an
6284 if statement are taken away by backPatchLabels
6285 only those used in arthmetic operations remain */
6286 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6287 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6288 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6290 /* if both are bit variables */
6291 if (AOP_TYPE (left) == AOP_CRY &&
6292 AOP_TYPE (right) == AOP_CRY)
6294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6295 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6300 tlbl = newiTempLabel (NULL);
6302 emitcode ("jnz", "%05d$", tlbl->key + 100);
6308 freeAsmop (result, NULL, ic, TRUE);
6309 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6313 /*-----------------------------------------------------------------*/
6314 /* isLiteralBit - test if lit == 2^n */
6315 /*-----------------------------------------------------------------*/
6317 isLiteralBit (unsigned long lit)
6319 unsigned long pw[32] =
6320 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6321 0x100L, 0x200L, 0x400L, 0x800L,
6322 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6323 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6324 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6325 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6326 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6329 for (idx = 0; idx < 32; idx++)
6335 /*-----------------------------------------------------------------*/
6336 /* continueIfTrue - */
6337 /*-----------------------------------------------------------------*/
6339 continueIfTrue (iCode * ic)
6342 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6346 /*-----------------------------------------------------------------*/
6348 /*-----------------------------------------------------------------*/
6350 jumpIfTrue (iCode * ic)
6353 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6357 /*-----------------------------------------------------------------*/
6358 /* jmpTrueOrFalse - */
6359 /*-----------------------------------------------------------------*/
6361 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6363 // ugly but optimized by peephole
6366 symbol *nlbl = newiTempLabel (NULL);
6367 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6369 freeForBranchAsmop (result);
6370 freeForBranchAsmop (right);
6371 freeForBranchAsmop (left);
6372 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6377 freeForBranchAsmop (result);
6378 freeForBranchAsmop (right);
6379 freeForBranchAsmop (left);
6380 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6386 /*-----------------------------------------------------------------*/
6387 /* genAnd - code for and */
6388 /*-----------------------------------------------------------------*/
6390 genAnd (iCode * ic, iCode * ifx)
6392 operand *left, *right, *result;
6393 int size, offset = 0;
6394 unsigned long lit = 0L;
6398 D (emitcode (";", "genAnd"));
6400 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6401 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6402 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6405 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6407 AOP_TYPE (left), AOP_TYPE (right));
6408 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6410 AOP_SIZE (left), AOP_SIZE (right));
6413 /* if left is a literal & right is not then exchange them */
6414 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6415 AOP_NEEDSACC (left))
6417 operand *tmp = right;
6422 /* if result = right then exchange left and right */
6423 if (sameRegs (AOP (result), AOP (right)))
6425 operand *tmp = right;
6430 /* if right is bit then exchange them */
6431 if (AOP_TYPE (right) == AOP_CRY &&
6432 AOP_TYPE (left) != AOP_CRY)
6434 operand *tmp = right;
6438 if (AOP_TYPE (right) == AOP_LIT)
6439 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6441 size = AOP_SIZE (result);
6444 // result = bit & yy;
6445 if (AOP_TYPE (left) == AOP_CRY)
6447 // c = bit & literal;
6448 if (AOP_TYPE (right) == AOP_LIT)
6452 if (size && sameRegs (AOP (result), AOP (left)))
6455 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6460 if (size && (AOP_TYPE (result) == AOP_CRY))
6462 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6465 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6470 emitcode ("clr", "c");
6475 if (AOP_TYPE (right) == AOP_CRY)
6478 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6479 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6484 MOVA (aopGet (right, 0, FALSE, FALSE));
6486 emitcode ("rrc", "a");
6487 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6495 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6496 genIfxJump (ifx, "c", left, right, result);
6500 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6501 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6502 if ((AOP_TYPE (right) == AOP_LIT) &&
6503 (AOP_TYPE (result) == AOP_CRY) &&
6504 (AOP_TYPE (left) != AOP_CRY))
6506 int posbit = isLiteralBit (lit);
6511 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6515 switch (posbit & 0x07)
6517 case 0: emitcode ("rrc", "a");
6519 case 7: emitcode ("rlc", "a");
6521 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6530 SNPRINTF (buffer, sizeof(buffer),
6531 "acc.%d", posbit & 0x07);
6532 genIfxJump (ifx, buffer, left, right, result);
6535 {// what is this case? just found it in ds390/gen.c
6536 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6543 symbol *tlbl = newiTempLabel (NULL);
6544 int sizel = AOP_SIZE (left);
6546 emitcode ("setb", "c");
6549 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6551 MOVA (aopGet (left, offset, FALSE, FALSE));
6553 if ((posbit = isLiteralBit (bytelit)) != 0)
6554 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6557 if (bytelit != 0x0FFL)
6558 emitcode ("anl", "a,%s",
6559 aopGet (right, offset, FALSE, TRUE));
6560 emitcode ("jnz", "%05d$", tlbl->key + 100);
6565 // bit = left & literal
6568 emitcode ("clr", "c");
6571 // if(left & literal)
6575 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6585 /* if left is same as result */
6586 if (sameRegs (AOP (result), AOP (left)))
6588 for (; size--; offset++)
6590 if (AOP_TYPE (right) == AOP_LIT)
6592 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6593 if (bytelit == 0x0FF)
6595 /* dummy read of volatile operand */
6596 if (isOperandVolatile (left, FALSE))
6597 MOVA (aopGet (left, offset, FALSE, FALSE));
6601 else if (bytelit == 0)
6603 aopPut (result, zero, offset);
6605 else if (IS_AOP_PREG (result))
6607 MOVA (aopGet (left, offset, FALSE, TRUE));
6608 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6609 aopPut (result, "a", offset);
6612 emitcode ("anl", "%s,%s",
6613 aopGet (left, offset, FALSE, TRUE),
6614 aopGet (right, offset, FALSE, FALSE));
6618 if (AOP_TYPE (left) == AOP_ACC)
6621 emitcode("mov", "a,b");
6622 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6624 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6626 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6627 MOVA (aopGet (right, offset, FALSE, FALSE));
6628 emitcode ("anl", "a,b");
6629 aopPut (result, "a", offset);
6631 else if (aopGetUsesAcc (left, offset))
6633 MOVA (aopGet (left, offset, FALSE, FALSE));
6634 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6635 aopPut (result, "a", offset);
6639 MOVA (aopGet (right, offset, FALSE, FALSE));
6640 if (IS_AOP_PREG (result))
6642 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6643 aopPut (result, "a", offset);
6646 emitcode ("anl", "%s,a",
6647 aopGet (left, offset, FALSE, TRUE));
6654 // left & result in different registers
6655 if (AOP_TYPE (result) == AOP_CRY)
6658 // if(size), result in bit
6659 // if(!size && ifx), conditional oper: if(left & right)
6660 symbol *tlbl = newiTempLabel (NULL);
6661 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6663 emitcode ("setb", "c");
6666 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6667 && AOP_TYPE(left)==AOP_ACC)
6670 emitcode("mov", "a,b");
6671 emitcode ("anl", "a,%s",
6672 aopGet (right, offset, FALSE, FALSE));
6674 if (AOP_TYPE(left)==AOP_ACC)
6678 bool pushedB = pushB ();
6679 emitcode("mov", "b,a");
6680 MOVA (aopGet (right, offset, FALSE, FALSE));
6681 emitcode("anl", "a,b");
6686 MOVA (aopGet (right, offset, FALSE, FALSE));
6687 emitcode("anl", "a,b");
6690 MOVA (aopGet (right, offset, FALSE, FALSE));
6691 emitcode ("anl", "a,%s",
6692 aopGet (left, offset, FALSE, FALSE));
6695 emitcode ("jnz", "%05d$", tlbl->key + 100);
6705 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6711 for (; (size--); offset++)
6714 // result = left & right
6715 if (AOP_TYPE (right) == AOP_LIT)
6717 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6718 if (bytelit == 0x0FF)
6721 aopGet (left, offset, FALSE, FALSE),
6725 else if (bytelit == 0)
6727 /* dummy read of volatile operand */
6728 if (isOperandVolatile (left, FALSE))
6729 MOVA (aopGet (left, offset, FALSE, FALSE));
6730 aopPut (result, zero, offset);
6733 else if (AOP_TYPE (left) == AOP_ACC)
6737 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6738 aopPut (result, "a", offset);
6743 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6744 aopPut (result, "b", offset);
6749 // faster than result <- left, anl result,right
6750 // and better if result is SFR
6751 if (AOP_TYPE (left) == AOP_ACC)
6754 emitcode("mov", "a,b");
6755 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6757 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6759 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6760 MOVA (aopGet (right, offset, FALSE, FALSE));
6761 emitcode ("anl", "a,b");
6763 else if (aopGetUsesAcc (left, offset))
6765 MOVA (aopGet (left, offset, FALSE, FALSE));
6766 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6770 MOVA (aopGet (right, offset, FALSE, FALSE));
6771 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6773 aopPut (result, "a", offset);
6779 freeAsmop (result, NULL, ic, TRUE);
6780 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6784 /*-----------------------------------------------------------------*/
6785 /* genOr - code for or */
6786 /*-----------------------------------------------------------------*/
6788 genOr (iCode * ic, iCode * ifx)
6790 operand *left, *right, *result;
6791 int size, offset = 0;
6792 unsigned long lit = 0L;
6795 D(emitcode ("; genOr",""));
6797 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6798 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6799 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6802 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6804 AOP_TYPE (left), AOP_TYPE (right));
6805 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6807 AOP_SIZE (left), AOP_SIZE (right));
6810 /* if left is a literal & right is not then exchange them */
6811 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6812 AOP_NEEDSACC (left))
6814 operand *tmp = right;
6819 /* if result = right then exchange them */
6820 if (sameRegs (AOP (result), AOP (right)))
6822 operand *tmp = right;
6827 /* if right is bit then exchange them */
6828 if (AOP_TYPE (right) == AOP_CRY &&
6829 AOP_TYPE (left) != AOP_CRY)
6831 operand *tmp = right;
6835 if (AOP_TYPE (right) == AOP_LIT)
6836 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6838 size = AOP_SIZE (result);
6842 if (AOP_TYPE (left) == AOP_CRY)
6844 if (AOP_TYPE (right) == AOP_LIT)
6846 // c = bit | literal;
6849 // lit != 0 => result = 1
6850 if (AOP_TYPE (result) == AOP_CRY)
6853 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6855 continueIfTrue (ifx);
6858 emitcode ("setb", "c");
6862 // lit == 0 => result = left
6863 if (size && sameRegs (AOP (result), AOP (left)))
6865 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6870 if (AOP_TYPE (right) == AOP_CRY)
6873 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6874 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6879 symbol *tlbl = newiTempLabel (NULL);
6880 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6881 emitcode ("setb", "c");
6882 emitcode ("jb", "%s,%05d$",
6883 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6885 emitcode ("jnz", "%05d$", tlbl->key + 100);
6886 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6888 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6903 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6904 genIfxJump (ifx, "c", left, right, result);
6908 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6909 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6910 if ((AOP_TYPE (right) == AOP_LIT) &&
6911 (AOP_TYPE (result) == AOP_CRY) &&
6912 (AOP_TYPE (left) != AOP_CRY))
6918 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6920 continueIfTrue (ifx);
6925 // lit = 0, result = boolean(left)
6927 emitcode ("setb", "c");
6931 symbol *tlbl = newiTempLabel (NULL);
6932 emitcode ("jnz", "%05d$", tlbl->key + 100);
6938 genIfxJump (ifx, "a", left, right, result);
6946 /* if left is same as result */
6947 if (sameRegs (AOP (result), AOP (left)))
6949 for (; size--; offset++)
6951 if (AOP_TYPE (right) == AOP_LIT)
6953 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6956 /* dummy read of volatile operand */
6957 if (isOperandVolatile (left, FALSE))
6958 MOVA (aopGet (left, offset, FALSE, FALSE));
6962 else if (bytelit == 0x0FF)
6964 aopPut (result, "#0xFF", offset);
6966 else if (IS_AOP_PREG (left))
6968 MOVA (aopGet (left, offset, FALSE, TRUE));
6969 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6970 aopPut (result, "a", offset);
6974 emitcode ("orl", "%s,%s",
6975 aopGet (left, offset, FALSE, TRUE),
6976 aopGet (right, offset, FALSE, FALSE));
6981 if (AOP_TYPE (left) == AOP_ACC)
6984 emitcode("mov", "a,b");
6985 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6987 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6989 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6990 MOVA (aopGet (right, offset, FALSE, FALSE));
6991 emitcode ("orl", "a,b");
6992 aopPut (result, "a", offset);
6994 else if (aopGetUsesAcc (left, offset))
6996 MOVA (aopGet (left, offset, FALSE, FALSE));
6997 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6998 aopPut (result, "a", offset);
7002 MOVA (aopGet (right, offset, FALSE, FALSE));
7003 if (IS_AOP_PREG (left))
7005 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7006 aopPut (result, "a", offset);
7010 emitcode ("orl", "%s,a",
7011 aopGet (left, offset, FALSE, TRUE));
7019 // left & result in different registers
7020 if (AOP_TYPE (result) == AOP_CRY)
7023 // if(size), result in bit
7024 // if(!size && ifx), conditional oper: if(left | right)
7025 symbol *tlbl = newiTempLabel (NULL);
7026 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7028 emitcode ("setb", "c");
7031 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7033 emitcode("mov", "a,b");
7034 emitcode ("orl", "a,%s",
7035 aopGet (right, offset, FALSE, FALSE));
7037 MOVA (aopGet (right, offset, FALSE, FALSE));
7038 emitcode ("orl", "a,%s",
7039 aopGet (left, offset, FALSE, FALSE));
7041 emitcode ("jnz", "%05d$", tlbl->key + 100);
7051 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7057 for (; (size--); offset++)
7060 // result = left | right
7061 if (AOP_TYPE (right) == AOP_LIT)
7063 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7067 aopGet (left, offset, FALSE, FALSE),
7071 else if (bytelit == 0x0FF)
7073 /* dummy read of volatile operand */
7074 if (isOperandVolatile (left, FALSE))
7075 MOVA (aopGet (left, offset, FALSE, FALSE));
7076 aopPut (result, "#0xFF", offset);
7080 // faster than result <- left, anl result,right
7081 // and better if result is SFR
7082 if (AOP_TYPE (left) == AOP_ACC)
7085 emitcode("mov", "a,b");
7086 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7088 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7090 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7091 MOVA (aopGet (right, offset, FALSE, FALSE));
7092 emitcode ("orl", "a,b");
7094 else if (aopGetUsesAcc (left, offset))
7096 MOVA (aopGet (left, offset, FALSE, FALSE));
7097 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7101 MOVA (aopGet (right, offset, FALSE, FALSE));
7102 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7104 aopPut (result, "a", offset);
7110 freeAsmop (result, NULL, ic, TRUE);
7111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7115 /*-----------------------------------------------------------------*/
7116 /* genXor - code for xclusive or */
7117 /*-----------------------------------------------------------------*/
7119 genXor (iCode * ic, iCode * ifx)
7121 operand *left, *right, *result;
7122 int size, offset = 0;
7123 unsigned long lit = 0L;
7126 D (emitcode (";", "genXor"));
7128 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7129 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7130 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7133 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7135 AOP_TYPE (left), AOP_TYPE (right));
7136 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7138 AOP_SIZE (left), AOP_SIZE (right));
7141 /* if left is a literal & right is not ||
7142 if left needs acc & right does not */
7143 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7144 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7146 operand *tmp = right;
7151 /* if result = right then exchange them */
7152 if (sameRegs (AOP (result), AOP (right)))
7154 operand *tmp = right;
7159 /* if right is bit then exchange them */
7160 if (AOP_TYPE (right) == AOP_CRY &&
7161 AOP_TYPE (left) != AOP_CRY)
7163 operand *tmp = right;
7167 if (AOP_TYPE (right) == AOP_LIT)
7168 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7170 size = AOP_SIZE (result);
7174 if (AOP_TYPE (left) == AOP_CRY)
7176 if (AOP_TYPE (right) == AOP_LIT)
7178 // c = bit & literal;
7181 // lit>>1 != 0 => result = 1
7182 if (AOP_TYPE (result) == AOP_CRY)
7185 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7187 continueIfTrue (ifx);
7190 emitcode ("setb", "c");
7197 // lit == 0, result = left
7198 if (size && sameRegs (AOP (result), AOP (left)))
7200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7204 // lit == 1, result = not(left)
7205 if (size && sameRegs (AOP (result), AOP (left)))
7207 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7213 emitcode ("cpl", "c");
7222 symbol *tlbl = newiTempLabel (NULL);
7223 if (AOP_TYPE (right) == AOP_CRY)
7226 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7230 int sizer = AOP_SIZE (right);
7232 // if val>>1 != 0, result = 1
7233 emitcode ("setb", "c");
7236 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7238 // test the msb of the lsb
7239 emitcode ("anl", "a,#0xfe");
7240 emitcode ("jnz", "%05d$", tlbl->key + 100);
7244 emitcode ("rrc", "a");
7246 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7247 emitcode ("cpl", "c");
7255 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7256 genIfxJump (ifx, "c", left, right, result);
7260 /* if left is same as result */
7261 if (sameRegs (AOP (result), AOP (left)))
7263 for (; size--; offset++)
7265 if (AOP_TYPE (right) == AOP_LIT)
7267 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7270 /* dummy read of volatile operand */
7271 if (isOperandVolatile (left, FALSE))
7272 MOVA (aopGet (left, offset, FALSE, FALSE));
7276 else if (IS_AOP_PREG (left))
7278 MOVA (aopGet (left, offset, FALSE, TRUE));
7279 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7280 aopPut (result, "a", offset);
7284 emitcode ("xrl", "%s,%s",
7285 aopGet (left, offset, FALSE, TRUE),
7286 aopGet (right, offset, FALSE, FALSE));
7291 if (AOP_TYPE (left) == AOP_ACC)
7294 emitcode("mov", "a,b");
7295 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7297 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7299 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7300 MOVA (aopGet (right, offset, FALSE, FALSE));
7301 emitcode ("xrl", "a,b");
7302 aopPut (result, "a", offset);
7304 else if (aopGetUsesAcc (left, offset))
7306 MOVA (aopGet (left, offset, FALSE, FALSE));
7307 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7308 aopPut (result, "a", offset);
7312 MOVA (aopGet (right, offset, FALSE, FALSE));
7313 if (IS_AOP_PREG (left))
7315 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7316 aopPut (result, "a", offset);
7319 emitcode ("xrl", "%s,a",
7320 aopGet (left, offset, FALSE, TRUE));
7327 // left & result in different registers
7328 if (AOP_TYPE (result) == AOP_CRY)
7331 // if(size), result in bit
7332 // if(!size && ifx), conditional oper: if(left ^ right)
7333 symbol *tlbl = newiTempLabel (NULL);
7334 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7337 emitcode ("setb", "c");
7340 if ((AOP_TYPE (right) == AOP_LIT) &&
7341 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7343 MOVA (aopGet (left, offset, FALSE, FALSE));
7347 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7349 emitcode("mov", "a,b");
7350 emitcode ("xrl", "a,%s",
7351 aopGet (right, offset, FALSE, FALSE));
7353 MOVA (aopGet (right, offset, FALSE, FALSE));
7354 emitcode ("xrl", "a,%s",
7355 aopGet (left, offset, FALSE, FALSE));
7358 emitcode ("jnz", "%05d$", tlbl->key + 100);
7368 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7372 for (; (size--); offset++)
7375 // result = left ^ right
7376 if (AOP_TYPE (right) == AOP_LIT)
7378 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7382 aopGet (left, offset, FALSE, FALSE),
7387 // faster than result <- left, anl result,right
7388 // and better if result is SFR
7389 if (AOP_TYPE (left) == AOP_ACC)
7392 emitcode("mov", "a,b");
7393 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7395 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7397 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7398 MOVA (aopGet (right, offset, FALSE, FALSE));
7399 emitcode ("xrl", "a,b");
7401 else if (aopGetUsesAcc (left, offset))
7403 MOVA (aopGet (left, offset, FALSE, FALSE));
7404 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7408 MOVA (aopGet (right, offset, FALSE, FALSE));
7409 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7411 aopPut (result, "a", offset);
7417 freeAsmop (result, NULL, ic, TRUE);
7418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7422 /*-----------------------------------------------------------------*/
7423 /* genInline - write the inline code out */
7424 /*-----------------------------------------------------------------*/
7426 genInline (iCode * ic)
7428 char *buffer, *bp, *bp1;
7430 D (emitcode (";", "genInline"));
7432 _G.inLine += (!options.asmpeep);
7434 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7436 /* emit each line as a code */
7447 /* Add \n for labels, not dirs such as c:\mydir */
7448 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7462 /* emitcode("",buffer); */
7463 _G.inLine -= (!options.asmpeep);
7466 /*-----------------------------------------------------------------*/
7467 /* genRRC - rotate right with carry */
7468 /*-----------------------------------------------------------------*/
7472 operand *left, *result;
7476 D (emitcode (";", "genRRC"));
7478 /* rotate right with carry */
7479 left = IC_LEFT (ic);
7480 result = IC_RESULT (ic);
7481 aopOp (left, ic, FALSE);
7482 aopOp (result, ic, FALSE);
7484 /* move it to the result */
7485 size = AOP_SIZE (result);
7487 if (size == 1) { /* special case for 1 byte */
7488 l = aopGet (left, offset, FALSE, FALSE);
7490 emitcode ("rr", "a");
7493 /* no need to clear carry, bit7 will be written later */
7496 l = aopGet (left, offset, FALSE, FALSE);
7498 emitcode ("rrc", "a");
7499 if (AOP_SIZE (result) > 1)
7500 aopPut (result, "a", offset--);
7502 /* now we need to put the carry into the
7503 highest order byte of the result */
7504 if (AOP_SIZE (result) > 1)
7506 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7509 emitcode ("mov", "acc.7,c");
7511 aopPut (result, "a", AOP_SIZE (result) - 1);
7512 freeAsmop (result, NULL, ic, TRUE);
7513 freeAsmop (left, NULL, ic, TRUE);
7516 /*-----------------------------------------------------------------*/
7517 /* genRLC - generate code for rotate left with carry */
7518 /*-----------------------------------------------------------------*/
7522 operand *left, *result;
7526 D (emitcode (";", "genRLC"));
7528 /* rotate right with carry */
7529 left = IC_LEFT (ic);
7530 result = IC_RESULT (ic);
7531 aopOp (left, ic, FALSE);
7532 aopOp (result, ic, FALSE);
7534 /* move it to the result */
7535 size = AOP_SIZE (result);
7539 l = aopGet (left, offset, FALSE, FALSE);
7541 if (size == 0) { /* special case for 1 byte */
7545 emitcode("rlc","a"); /* bit0 will be written later */
7546 if (AOP_SIZE (result) > 1)
7548 aopPut (result, "a", offset++);
7553 l = aopGet (left, offset, FALSE, FALSE);
7555 emitcode ("rlc", "a");
7556 if (AOP_SIZE (result) > 1)
7557 aopPut (result, "a", offset++);
7560 /* now we need to put the carry into the
7561 highest order byte of the result */
7562 if (AOP_SIZE (result) > 1)
7564 l = aopGet (result, 0, FALSE, FALSE);
7567 emitcode ("mov", "acc.0,c");
7569 aopPut (result, "a", 0);
7570 freeAsmop (result, NULL, ic, TRUE);
7571 freeAsmop (left, NULL, ic, TRUE);
7574 /*-----------------------------------------------------------------*/
7575 /* genGetHbit - generates code get highest order bit */
7576 /*-----------------------------------------------------------------*/
7578 genGetHbit (iCode * ic)
7580 operand *left, *result;
7582 D (emitcode (";", "genGetHbit"));
7584 left = IC_LEFT (ic);
7585 result = IC_RESULT (ic);
7586 aopOp (left, ic, FALSE);
7587 aopOp (result, ic, FALSE);
7589 /* get the highest order byte into a */
7590 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7591 if (AOP_TYPE (result) == AOP_CRY)
7593 emitcode ("rlc", "a");
7598 emitcode ("rl", "a");
7599 emitcode ("anl", "a,#0x01");
7603 freeAsmop (result, NULL, ic, TRUE);
7604 freeAsmop (left, NULL, ic, TRUE);
7607 /*-----------------------------------------------------------------*/
7608 /* genGetAbit - generates code get a single bit */
7609 /*-----------------------------------------------------------------*/
7611 genGetAbit (iCode * ic)
7613 operand *left, *right, *result;
7616 D (emitcode (";", "genGetAbit"));
7618 left = IC_LEFT (ic);
7619 right = IC_RIGHT (ic);
7620 result = IC_RESULT (ic);
7621 aopOp (left, ic, FALSE);
7622 aopOp (right, ic, FALSE);
7623 aopOp (result, ic, FALSE);
7625 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7627 /* get the needed byte into a */
7628 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7630 if (AOP_TYPE (result) == AOP_CRY)
7633 emitcode ("rlc", "a");
7634 else if ((shCount) == 0)
7635 emitcode ("rrc", "a");
7637 emitcode ("mov", "c,acc[%d]", shCount);
7645 emitcode ("rr", "a");
7648 emitcode ("rr", "a");
7651 emitcode ("anl", "a,#0x01");
7655 emitcode ("mov", "c,acc[%d]", shCount);
7656 emitcode ("clr", "a");
7657 emitcode ("rlc", "a");
7660 emitcode ("swap", "a");
7661 emitcode ("anl", "a,#0x01");
7664 emitcode ("rl", "a");
7667 emitcode ("rl", "a");
7668 emitcode ("anl", "a,#0x01");
7674 freeAsmop (result, NULL, ic, TRUE);
7675 freeAsmop (right, NULL, ic, TRUE);
7676 freeAsmop (left, NULL, ic, TRUE);
7679 /*-----------------------------------------------------------------*/
7680 /* genGetByte - generates code get a single byte */
7681 /*-----------------------------------------------------------------*/
7683 genGetByte (iCode * ic)
7685 operand *left, *right, *result;
7688 D (emitcode (";", "genGetByte"));
7690 left = IC_LEFT (ic);
7691 right = IC_RIGHT (ic);
7692 result = IC_RESULT (ic);
7693 aopOp (left, ic, FALSE);
7694 aopOp (right, ic, FALSE);
7695 aopOp (result, ic, FALSE);
7697 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7699 aopGet (left, offset, FALSE, FALSE),
7702 freeAsmop (result, NULL, ic, TRUE);
7703 freeAsmop (right, NULL, ic, TRUE);
7704 freeAsmop (left, NULL, ic, TRUE);
7707 /*-----------------------------------------------------------------*/
7708 /* genGetWord - generates code get two bytes */
7709 /*-----------------------------------------------------------------*/
7711 genGetWord (iCode * ic)
7713 operand *left, *right, *result;
7716 D (emitcode (";", "genGetWord"));
7718 left = IC_LEFT (ic);
7719 right = IC_RIGHT (ic);
7720 result = IC_RESULT (ic);
7721 aopOp (left, ic, FALSE);
7722 aopOp (right, ic, FALSE);
7723 aopOp (result, ic, FALSE);
7725 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7727 aopGet (left, offset, FALSE, FALSE),
7730 aopGet (left, offset+1, FALSE, FALSE),
7733 freeAsmop (result, NULL, ic, TRUE);
7734 freeAsmop (right, NULL, ic, TRUE);
7735 freeAsmop (left, NULL, ic, TRUE);
7738 /*-----------------------------------------------------------------*/
7739 /* genSwap - generates code to swap nibbles or bytes */
7740 /*-----------------------------------------------------------------*/
7742 genSwap (iCode * ic)
7744 operand *left, *result;
7746 D(emitcode ("; genSwap",""));
7748 left = IC_LEFT (ic);
7749 result = IC_RESULT (ic);
7750 aopOp (left, ic, FALSE);
7751 aopOp (result, ic, FALSE);
7753 switch (AOP_SIZE (left))
7755 case 1: /* swap nibbles in byte */
7756 MOVA (aopGet (left, 0, FALSE, FALSE));
7757 emitcode ("swap", "a");
7758 aopPut (result, "a", 0);
7760 case 2: /* swap bytes in word */
7761 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7763 MOVA (aopGet (left, 0, FALSE, FALSE));
7764 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7765 aopPut (result, "a", 1);
7767 else if (operandsEqu (left, result))
7770 bool pushedB = FALSE, leftInB = FALSE;
7772 MOVA (aopGet (left, 0, FALSE, FALSE));
7773 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7776 emitcode ("mov", "b,a");
7780 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7781 aopPut (result, reg, 1);
7788 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7789 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7793 wassertl(FALSE, "unsupported SWAP operand size");
7796 freeAsmop (result, NULL, ic, TRUE);
7797 freeAsmop (left, NULL, ic, TRUE);
7800 /*-----------------------------------------------------------------*/
7801 /* AccRol - rotate left accumulator by known count */
7802 /*-----------------------------------------------------------------*/
7804 AccRol (int shCount)
7806 shCount &= 0x0007; // shCount : 0..7
7813 emitcode ("rl", "a");
7816 emitcode ("rl", "a");
7817 emitcode ("rl", "a");
7820 emitcode ("swap", "a");
7821 emitcode ("rr", "a");
7824 emitcode ("swap", "a");
7827 emitcode ("swap", "a");
7828 emitcode ("rl", "a");
7831 emitcode ("rr", "a");
7832 emitcode ("rr", "a");
7835 emitcode ("rr", "a");
7840 /*-----------------------------------------------------------------*/
7841 /* AccLsh - left shift accumulator by known count */
7842 /*-----------------------------------------------------------------*/
7844 AccLsh (int shCount)
7849 emitcode ("add", "a,acc");
7850 else if (shCount == 2)
7852 emitcode ("add", "a,acc");
7853 emitcode ("add", "a,acc");
7857 /* rotate left accumulator */
7859 /* and kill the lower order bits */
7860 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7865 /*-----------------------------------------------------------------*/
7866 /* AccRsh - right shift accumulator by known count */
7867 /*-----------------------------------------------------------------*/
7869 AccRsh (int shCount)
7876 emitcode ("rrc", "a");
7880 /* rotate right accumulator */
7881 AccRol (8 - shCount);
7882 /* and kill the higher order bits */
7883 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7888 /*-----------------------------------------------------------------*/
7889 /* AccSRsh - signed right shift accumulator by known count */
7890 /*-----------------------------------------------------------------*/
7892 AccSRsh (int shCount)
7899 emitcode ("mov", "c,acc.7");
7900 emitcode ("rrc", "a");
7902 else if (shCount == 2)
7904 emitcode ("mov", "c,acc.7");
7905 emitcode ("rrc", "a");
7906 emitcode ("mov", "c,acc.7");
7907 emitcode ("rrc", "a");
7911 tlbl = newiTempLabel (NULL);
7912 /* rotate right accumulator */
7913 AccRol (8 - shCount);
7914 /* and kill the higher order bits */
7915 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7916 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7917 emitcode ("orl", "a,#0x%02x",
7918 (unsigned char) ~SRMask[shCount]);
7924 /*-----------------------------------------------------------------*/
7925 /* shiftR1Left2Result - shift right one byte from left to result */
7926 /*-----------------------------------------------------------------*/
7928 shiftR1Left2Result (operand * left, int offl,
7929 operand * result, int offr,
7930 int shCount, int sign)
7932 MOVA (aopGet (left, offl, FALSE, FALSE));
7933 /* shift right accumulator */
7938 aopPut (result, "a", offr);
7941 /*-----------------------------------------------------------------*/
7942 /* shiftL1Left2Result - shift left one byte from left to result */
7943 /*-----------------------------------------------------------------*/
7945 shiftL1Left2Result (operand * left, int offl,
7946 operand * result, int offr, int shCount)
7949 l = aopGet (left, offl, FALSE, FALSE);
7951 /* shift left accumulator */
7953 aopPut (result, "a", offr);
7956 /*-----------------------------------------------------------------*/
7957 /* movLeft2Result - move byte from left to result */
7958 /*-----------------------------------------------------------------*/
7960 movLeft2Result (operand * left, int offl,
7961 operand * result, int offr, int sign)
7964 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7966 l = aopGet (left, offl, FALSE, FALSE);
7968 if (*l == '@' && (IS_AOP_PREG (result)))
7970 emitcode ("mov", "a,%s", l);
7971 aopPut (result, "a", offr);
7977 aopPut (result, l, offr);
7981 /* MSB sign in acc.7 ! */
7982 if (getDataSize (left) == offl + 1)
7985 aopPut (result, "a", offr);
7992 /*-----------------------------------------------------------------*/
7993 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7994 /*-----------------------------------------------------------------*/
7998 emitcode ("rrc", "a");
7999 emitcode ("xch", "a,%s", x);
8000 emitcode ("rrc", "a");
8001 emitcode ("xch", "a,%s", x);
8004 /*-----------------------------------------------------------------*/
8005 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8006 /*-----------------------------------------------------------------*/
8010 emitcode ("xch", "a,%s", x);
8011 emitcode ("rlc", "a");
8012 emitcode ("xch", "a,%s", x);
8013 emitcode ("rlc", "a");
8016 /*-----------------------------------------------------------------*/
8017 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8018 /*-----------------------------------------------------------------*/
8022 emitcode ("xch", "a,%s", x);
8023 emitcode ("add", "a,acc");
8024 emitcode ("xch", "a,%s", x);
8025 emitcode ("rlc", "a");
8028 /*-----------------------------------------------------------------*/
8029 /* AccAXLsh - left shift a:x by known count (0..7) */
8030 /*-----------------------------------------------------------------*/
8032 AccAXLsh (char *x, int shCount)
8047 case 5: // AAAAABBB:CCCCCDDD
8049 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8051 emitcode ("anl", "a,#0x%02x",
8052 SLMask[shCount]); // BBB00000:CCCCCDDD
8054 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8056 AccRol (shCount); // DDDCCCCC:BBB00000
8058 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8060 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8062 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8064 emitcode ("anl", "a,#0x%02x",
8065 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8067 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8069 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8072 case 6: // AAAAAABB:CCCCCCDD
8073 emitcode ("anl", "a,#0x%02x",
8074 SRMask[shCount]); // 000000BB:CCCCCCDD
8075 emitcode ("mov", "c,acc.0"); // c = B
8076 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8078 AccAXRrl1 (x); // BCCCCCCD:D000000B
8079 AccAXRrl1 (x); // BBCCCCCC:DD000000
8081 emitcode("rrc","a");
8082 emitcode("xch","a,%s", x);
8083 emitcode("rrc","a");
8084 emitcode("mov","c,acc.0"); //<< get correct bit
8085 emitcode("xch","a,%s", x);
8087 emitcode("rrc","a");
8088 emitcode("xch","a,%s", x);
8089 emitcode("rrc","a");
8090 emitcode("xch","a,%s", x);
8093 case 7: // a:x <<= 7
8095 emitcode ("anl", "a,#0x%02x",
8096 SRMask[shCount]); // 0000000B:CCCCCCCD
8098 emitcode ("mov", "c,acc.0"); // c = B
8100 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8102 AccAXRrl1 (x); // BCCCCCCC:D0000000
8110 /*-----------------------------------------------------------------*/
8111 /* AccAXRsh - right shift a:x known count (0..7) */
8112 /*-----------------------------------------------------------------*/
8114 AccAXRsh (char *x, int shCount)
8122 AccAXRrl1 (x); // 0->a:x
8127 AccAXRrl1 (x); // 0->a:x
8130 AccAXRrl1 (x); // 0->a:x
8135 case 5: // AAAAABBB:CCCCCDDD = a:x
8137 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8139 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8141 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8143 emitcode ("anl", "a,#0x%02x",
8144 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8146 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8148 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8150 emitcode ("anl", "a,#0x%02x",
8151 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8153 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8155 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8157 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8160 case 6: // AABBBBBB:CCDDDDDD
8162 emitcode ("mov", "c,acc.7");
8163 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8165 emitcode ("mov", "c,acc.7");
8166 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8168 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8170 emitcode ("anl", "a,#0x%02x",
8171 SRMask[shCount]); // 000000AA:BBBBBBCC
8174 case 7: // ABBBBBBB:CDDDDDDD
8176 emitcode ("mov", "c,acc.7"); // c = A
8178 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8180 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8182 emitcode ("anl", "a,#0x%02x",
8183 SRMask[shCount]); // 0000000A:BBBBBBBC
8191 /*-----------------------------------------------------------------*/
8192 /* AccAXRshS - right shift signed a:x known count (0..7) */
8193 /*-----------------------------------------------------------------*/
8195 AccAXRshS (char *x, int shCount)
8203 emitcode ("mov", "c,acc.7");
8204 AccAXRrl1 (x); // s->a:x
8208 emitcode ("mov", "c,acc.7");
8209 AccAXRrl1 (x); // s->a:x
8211 emitcode ("mov", "c,acc.7");
8212 AccAXRrl1 (x); // s->a:x
8217 case 5: // AAAAABBB:CCCCCDDD = a:x
8219 tlbl = newiTempLabel (NULL);
8220 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8222 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8224 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8226 emitcode ("anl", "a,#0x%02x",
8227 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8229 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8231 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8233 emitcode ("anl", "a,#0x%02x",
8234 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8236 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8238 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8240 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8242 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8243 emitcode ("orl", "a,#0x%02x",
8244 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8247 break; // SSSSAAAA:BBBCCCCC
8249 case 6: // AABBBBBB:CCDDDDDD
8251 tlbl = newiTempLabel (NULL);
8252 emitcode ("mov", "c,acc.7");
8253 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8255 emitcode ("mov", "c,acc.7");
8256 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8258 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8260 emitcode ("anl", "a,#0x%02x",
8261 SRMask[shCount]); // 000000AA:BBBBBBCC
8263 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8264 emitcode ("orl", "a,#0x%02x",
8265 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8269 case 7: // ABBBBBBB:CDDDDDDD
8271 tlbl = newiTempLabel (NULL);
8272 emitcode ("mov", "c,acc.7"); // c = A
8274 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8276 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8278 emitcode ("anl", "a,#0x%02x",
8279 SRMask[shCount]); // 0000000A:BBBBBBBC
8281 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8282 emitcode ("orl", "a,#0x%02x",
8283 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8292 /*-----------------------------------------------------------------*/
8293 /* shiftL2Left2Result - shift left two bytes from left to result */
8294 /*-----------------------------------------------------------------*/
8296 shiftL2Left2Result (operand * left, int offl,
8297 operand * result, int offr, int shCount)
8300 bool pushedB = FALSE;
8303 if (sameRegs (AOP (result), AOP (left)) &&
8304 ((offl + MSB16) == offr))
8306 /* don't crash result[offr] */
8307 MOVA (aopGet (left, offl, FALSE, FALSE));
8308 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8309 x = aopGet (result, offr, FALSE, FALSE);
8311 else if (aopGetUsesAcc (result, offr))
8313 movLeft2Result (left, offl, result, offr, 0);
8316 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8317 MOVA (aopGet (result, offr, FALSE, FALSE));
8318 emitcode ("xch", "a,b");
8323 movLeft2Result (left, offl, result, offr, 0);
8324 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8325 x = aopGet (result, offr, FALSE, FALSE);
8327 /* ax << shCount (x = lsb(result)) */
8328 AccAXLsh (x, shCount);
8331 emitcode ("xch", "a,b");
8332 aopPut (result, "a", offr);
8333 aopPut (result, "b", offr + MSB16);
8338 aopPut (result, "a", offr + MSB16);
8343 /*-----------------------------------------------------------------*/
8344 /* shiftR2Left2Result - shift right two bytes from left to result */
8345 /*-----------------------------------------------------------------*/
8347 shiftR2Left2Result (operand * left, int offl,
8348 operand * result, int offr,
8349 int shCount, int sign)
8352 bool pushedB = FALSE;
8355 if (sameRegs (AOP (result), AOP (left)) &&
8356 ((offl + MSB16) == offr))
8358 /* don't crash result[offr] */
8359 MOVA (aopGet (left, offl, FALSE, FALSE));
8360 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8361 x = aopGet (result, offr, FALSE, FALSE);
8363 else if (aopGetUsesAcc (result, offr))
8365 movLeft2Result (left, offl, result, offr, 0);
8368 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8369 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8374 movLeft2Result (left, offl, result, offr, 0);
8375 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8376 x = aopGet (result, offr, FALSE, FALSE);
8378 /* a:x >> shCount (x = lsb(result)) */
8380 AccAXRshS (x, shCount);
8382 AccAXRsh (x, shCount);
8385 emitcode ("xch", "a,b");
8386 aopPut (result, "a", offr);
8387 emitcode ("xch", "a,b");
8390 if (getDataSize (result) > 1)
8391 aopPut (result, "a", offr + MSB16);
8394 /*-----------------------------------------------------------------*/
8395 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8396 /*-----------------------------------------------------------------*/
8398 shiftLLeftOrResult (operand * left, int offl,
8399 operand * result, int offr, int shCount)
8401 MOVA (aopGet (left, offl, FALSE, FALSE));
8402 /* shift left accumulator */
8404 /* or with result */
8405 if (aopGetUsesAcc (result, offr))
8407 emitcode ("xch", "a,b");
8408 MOVA (aopGet (result, offr, FALSE, FALSE));
8409 emitcode ("orl", "a,b");
8413 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8415 /* back to result */
8416 aopPut (result, "a", offr);
8419 /*-----------------------------------------------------------------*/
8420 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8421 /*-----------------------------------------------------------------*/
8423 shiftRLeftOrResult (operand * left, int offl,
8424 operand * result, int offr, int shCount)
8426 MOVA (aopGet (left, offl, FALSE, FALSE));
8427 /* shift right accumulator */
8429 /* or with result */
8430 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8431 /* back to result */
8432 aopPut (result, "a", offr);
8435 /*-----------------------------------------------------------------*/
8436 /* genlshOne - left shift a one byte quantity by known count */
8437 /*-----------------------------------------------------------------*/
8439 genlshOne (operand * result, operand * left, int shCount)
8441 D (emitcode (";", "genlshOne"));
8443 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8446 /*-----------------------------------------------------------------*/
8447 /* genlshTwo - left shift two bytes by known amount != 0 */
8448 /*-----------------------------------------------------------------*/
8450 genlshTwo (operand * result, operand * left, int shCount)
8454 D (emitcode (";", "genlshTwo"));
8456 size = getDataSize (result);
8458 /* if shCount >= 8 */
8466 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8468 movLeft2Result (left, LSB, result, MSB16, 0);
8470 aopPut (result, zero, LSB);
8473 /* 1 <= shCount <= 7 */
8477 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8479 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8483 /*-----------------------------------------------------------------*/
8484 /* shiftLLong - shift left one long from left to result */
8485 /* offl = LSB or MSB16 */
8486 /*-----------------------------------------------------------------*/
8488 shiftLLong (operand * left, operand * result, int offr)
8491 int size = AOP_SIZE (result);
8493 if (size >= LSB + offr)
8495 l = aopGet (left, LSB, FALSE, FALSE);
8497 emitcode ("add", "a,acc");
8498 if (sameRegs (AOP (left), AOP (result)) &&
8499 size >= MSB16 + offr && offr != LSB)
8500 emitcode ("xch", "a,%s",
8501 aopGet (left, LSB + offr, FALSE, FALSE));
8503 aopPut (result, "a", LSB + offr);
8506 if (size >= MSB16 + offr)
8508 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8510 l = aopGet (left, MSB16, FALSE, FALSE);
8513 emitcode ("rlc", "a");
8514 if (sameRegs (AOP (left), AOP (result)) &&
8515 size >= MSB24 + offr && offr != LSB)
8516 emitcode ("xch", "a,%s",
8517 aopGet (left, MSB16 + offr, FALSE, FALSE));
8519 aopPut (result, "a", MSB16 + offr);
8522 if (size >= MSB24 + offr)
8524 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8526 l = aopGet (left, MSB24, FALSE, FALSE);
8529 emitcode ("rlc", "a");
8530 if (sameRegs (AOP (left), AOP (result)) &&
8531 size >= MSB32 + offr && offr != LSB)
8532 emitcode ("xch", "a,%s",
8533 aopGet (left, MSB24 + offr, FALSE, FALSE));
8535 aopPut (result, "a", MSB24 + offr);
8538 if (size > MSB32 + offr)
8540 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8542 l = aopGet (left, MSB32, FALSE, FALSE);
8545 emitcode ("rlc", "a");
8546 aopPut (result, "a", MSB32 + offr);
8549 aopPut (result, zero, LSB);
8552 /*-----------------------------------------------------------------*/
8553 /* genlshFour - shift four byte by a known amount != 0 */
8554 /*-----------------------------------------------------------------*/
8556 genlshFour (operand * result, operand * left, int shCount)
8560 D (emitcode (";", "genlshFour"));
8562 size = AOP_SIZE (result);
8564 /* if shifting more that 3 bytes */
8569 /* lowest order of left goes to the highest
8570 order of the destination */
8571 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8573 movLeft2Result (left, LSB, result, MSB32, 0);
8574 aopPut (result, zero, LSB);
8575 aopPut (result, zero, MSB16);
8576 aopPut (result, zero, MSB24);
8580 /* more than two bytes */
8581 else if (shCount >= 16)
8583 /* lower order two bytes goes to higher order two bytes */
8585 /* if some more remaining */
8587 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8590 movLeft2Result (left, MSB16, result, MSB32, 0);
8591 movLeft2Result (left, LSB, result, MSB24, 0);
8593 aopPut (result, zero, MSB16);
8594 aopPut (result, zero, LSB);
8598 /* if more than 1 byte */
8599 else if (shCount >= 8)
8601 /* lower order three bytes goes to higher order three bytes */
8606 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8608 movLeft2Result (left, LSB, result, MSB16, 0);
8614 movLeft2Result (left, MSB24, result, MSB32, 0);
8615 movLeft2Result (left, MSB16, result, MSB24, 0);
8616 movLeft2Result (left, LSB, result, MSB16, 0);
8617 aopPut (result, zero, LSB);
8619 else if (shCount == 1)
8620 shiftLLong (left, result, MSB16);
8623 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8624 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8625 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8626 aopPut (result, zero, LSB);
8631 /* 1 <= shCount <= 7 */
8632 else if (shCount <= 2)
8634 shiftLLong (left, result, LSB);
8636 shiftLLong (result, result, LSB);
8638 /* 3 <= shCount <= 7, optimize */
8641 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8642 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8643 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8647 /*-----------------------------------------------------------------*/
8648 /* genLeftShiftLiteral - left shifting by known count */
8649 /*-----------------------------------------------------------------*/
8651 genLeftShiftLiteral (operand * left,
8656 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8659 D(emitcode ("; genLeftShiftLiteral",""));
8661 freeAsmop (right, NULL, ic, TRUE);
8663 aopOp (left, ic, FALSE);
8664 aopOp (result, ic, FALSE);
8666 size = getSize (operandType (result));
8669 emitcode ("; shift left ", "result %d, left %d", size,
8673 /* I suppose that the left size >= result size */
8678 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);
9012 { /* 1 <= shCount <= 7 */
9015 shiftRLong (left, LSB, result, sign);
9017 shiftRLong (result, LSB, result, sign);
9021 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9022 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9023 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9028 /*-----------------------------------------------------------------*/
9029 /* genRightShiftLiteral - right shifting by known count */
9030 /*-----------------------------------------------------------------*/
9032 genRightShiftLiteral (operand * left,
9038 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9041 D(emitcode ("; genRightShiftLiteral",""));
9043 freeAsmop (right, NULL, ic, TRUE);
9045 aopOp (left, ic, FALSE);
9046 aopOp (result, ic, FALSE);
9049 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9053 size = getDataSize (left);
9054 /* test the LEFT size !!! */
9056 /* I suppose that the left size >= result size */
9059 size = getDataSize (result);
9061 movLeft2Result (left, size, result, size, 0);
9064 else if (shCount >= (size * 8))
9067 /* get sign in acc.7 */
9068 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9070 addSign (result, LSB, sign);
9077 genrshOne (result, left, shCount, sign);
9081 genrshTwo (result, left, shCount, sign);
9085 genrshFour (result, left, shCount, sign);
9091 freeAsmop (result, NULL, ic, TRUE);
9092 freeAsmop (left, NULL, ic, TRUE);
9095 /*-----------------------------------------------------------------*/
9096 /* genSignedRightShift - right shift of signed number */
9097 /*-----------------------------------------------------------------*/
9099 genSignedRightShift (iCode * ic)
9101 operand *right, *left, *result;
9104 symbol *tlbl, *tlbl1;
9107 D (emitcode (";", "genSignedRightShift"));
9109 /* we do it the hard way put the shift count in b
9110 and loop thru preserving the sign */
9112 right = IC_RIGHT (ic);
9113 left = IC_LEFT (ic);
9114 result = IC_RESULT (ic);
9116 aopOp (right, ic, FALSE);
9119 if (AOP_TYPE (right) == AOP_LIT)
9121 genRightShiftLiteral (left, right, result, ic, 1);
9124 /* shift count is unknown then we have to form
9125 a loop get the loop count in B : Note: we take
9126 only the lower order byte since shifting
9127 more that 32 bits make no sense anyway, ( the
9128 largest size of an object can be only 32 bits ) */
9131 MOVB (aopGet (right, 0, FALSE, FALSE));
9132 emitcode ("inc", "b");
9133 freeAsmop (right, NULL, ic, TRUE);
9134 aopOp (left, ic, FALSE);
9135 aopOp (result, ic, FALSE);
9137 /* now move the left to the result if they are not the
9139 if (!sameRegs (AOP (left), AOP (result)) &&
9140 AOP_SIZE (result) > 1)
9143 size = AOP_SIZE (result);
9147 l = aopGet (left, offset, FALSE, TRUE);
9148 if (*l == '@' && IS_AOP_PREG (result))
9151 emitcode ("mov", "a,%s", l);
9152 aopPut (result, "a", offset);
9155 aopPut (result, l, offset);
9160 /* mov the highest order bit to OVR */
9161 tlbl = newiTempLabel (NULL);
9162 tlbl1 = newiTempLabel (NULL);
9164 size = AOP_SIZE (result);
9166 MOVA (aopGet (left, offset, FALSE, FALSE));
9167 emitcode ("rlc", "a");
9168 emitcode ("mov", "ov,c");
9169 /* if it is only one byte then */
9172 l = aopGet (left, 0, FALSE, FALSE);
9174 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9176 emitcode ("mov", "c,ov");
9177 emitcode ("rrc", "a");
9179 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9181 aopPut (result, "a", 0);
9185 reAdjustPreg (AOP (result));
9186 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9188 emitcode ("mov", "c,ov");
9191 l = aopGet (result, offset, FALSE, FALSE);
9193 emitcode ("rrc", "a");
9194 aopPut (result, "a", offset--);
9196 reAdjustPreg (AOP (result));
9198 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9202 freeAsmop (result, NULL, ic, TRUE);
9203 freeAsmop (left, NULL, ic, TRUE);
9206 /*-----------------------------------------------------------------*/
9207 /* genRightShift - generate code for right shifting */
9208 /*-----------------------------------------------------------------*/
9210 genRightShift (iCode * ic)
9212 operand *right, *left, *result;
9216 symbol *tlbl, *tlbl1;
9219 D (emitcode (";", "genRightShift"));
9221 /* if signed then we do it the hard way preserve the
9222 sign bit moving it inwards */
9223 letype = getSpec (operandType (IC_LEFT (ic)));
9225 if (!SPEC_USIGN (letype))
9227 genSignedRightShift (ic);
9231 /* signed & unsigned types are treated the same : i.e. the
9232 signed is NOT propagated inwards : quoting from the
9233 ANSI - standard : "for E1 >> E2, is equivalent to division
9234 by 2**E2 if unsigned or if it has a non-negative value,
9235 otherwise the result is implementation defined ", MY definition
9236 is that the sign does not get propagated */
9238 right = IC_RIGHT (ic);
9239 left = IC_LEFT (ic);
9240 result = IC_RESULT (ic);
9242 aopOp (right, ic, FALSE);
9244 /* if the shift count is known then do it
9245 as efficiently as possible */
9246 if (AOP_TYPE (right) == AOP_LIT)
9248 genRightShiftLiteral (left, right, result, ic, 0);
9252 /* shift count is unknown then we have to form
9253 a loop get the loop count in B : Note: we take
9254 only the lower order byte since shifting
9255 more that 32 bits make no sense anyway, ( the
9256 largest size of an object can be only 32 bits ) */
9259 MOVB (aopGet (right, 0, FALSE, FALSE));
9260 emitcode ("inc", "b");
9261 freeAsmop (right, NULL, ic, TRUE);
9262 aopOp (left, ic, FALSE);
9263 aopOp (result, ic, FALSE);
9265 /* now move the left to the result if they are not the
9267 if (!sameRegs (AOP (left), AOP (result)) &&
9268 AOP_SIZE (result) > 1)
9270 size = AOP_SIZE (result);
9274 l = aopGet (left, offset, FALSE, TRUE);
9275 if (*l == '@' && IS_AOP_PREG (result))
9278 emitcode ("mov", "a,%s", l);
9279 aopPut (result, "a", offset);
9282 aopPut (result, l, offset);
9287 tlbl = newiTempLabel (NULL);
9288 tlbl1 = newiTempLabel (NULL);
9289 size = AOP_SIZE (result);
9292 /* if it is only one byte then */
9295 l = aopGet (left, 0, FALSE, FALSE);
9297 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9300 emitcode ("rrc", "a");
9302 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9304 aopPut (result, "a", 0);
9308 reAdjustPreg (AOP (result));
9309 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9314 l = aopGet (result, offset, FALSE, FALSE);
9316 emitcode ("rrc", "a");
9317 aopPut (result, "a", offset--);
9319 reAdjustPreg (AOP (result));
9322 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9326 freeAsmop (result, NULL, ic, TRUE);
9327 freeAsmop (left, NULL, ic, TRUE);
9330 /*-----------------------------------------------------------------*/
9331 /* emitPtrByteGet - emits code to get a byte into A through a */
9332 /* pointer register (R0, R1, or DPTR). The */
9333 /* original value of A can be preserved in B. */
9334 /*-----------------------------------------------------------------*/
9336 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9343 emitcode ("mov", "b,a");
9344 emitcode ("mov", "a,@%s", rname);
9349 emitcode ("mov", "b,a");
9350 emitcode ("movx", "a,@%s", rname);
9355 emitcode ("mov", "b,a");
9356 emitcode ("movx", "a,@dptr");
9361 emitcode ("mov", "b,a");
9362 emitcode ("clr", "a");
9363 emitcode ("movc", "a,@a+dptr");
9369 emitcode ("push", "b");
9370 emitcode ("push", "acc");
9372 emitcode ("lcall", "__gptrget");
9374 emitcode ("pop", "b");
9379 /*-----------------------------------------------------------------*/
9380 /* emitPtrByteSet - emits code to set a byte from src through a */
9381 /* pointer register (R0, R1, or DPTR). */
9382 /*-----------------------------------------------------------------*/
9384 emitPtrByteSet (char *rname, int p_type, char *src)
9393 emitcode ("mov", "@%s,a", rname);
9396 emitcode ("mov", "@%s,%s", rname, src);
9401 emitcode ("movx", "@%s,a", rname);
9406 emitcode ("movx", "@dptr,a");
9411 emitcode ("lcall", "__gptrput");
9416 /*-----------------------------------------------------------------*/
9417 /* genUnpackBits - generates code for unpacking bits */
9418 /*-----------------------------------------------------------------*/
9420 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9422 int offset = 0; /* result byte offset */
9423 int rsize; /* result size */
9424 int rlen = 0; /* remaining bitfield length */
9425 sym_link *etype; /* bitfield type information */
9426 int blen; /* bitfield length */
9427 int bstr; /* bitfield starting bit within byte */
9430 D(emitcode ("; genUnpackBits",""));
9432 etype = getSpec (operandType (result));
9433 rsize = getSize (operandType (result));
9434 blen = SPEC_BLEN (etype);
9435 bstr = SPEC_BSTR (etype);
9437 if (ifx && blen <= 8)
9439 emitPtrByteGet (rname, ptype, FALSE);
9442 SNPRINTF (buffer, sizeof(buffer),
9444 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9449 emitcode ("anl", "a,#0x%02x",
9450 (((unsigned char) -1) >> (8 - blen)) << bstr);
9451 genIfxJump (ifx, "a", NULL, NULL, NULL);
9457 /* If the bitfield length is less than a byte */
9460 emitPtrByteGet (rname, ptype, FALSE);
9462 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9463 if (!SPEC_USIGN (etype))
9465 /* signed bitfield */
9466 symbol *tlbl = newiTempLabel (NULL);
9468 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9469 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9472 aopPut (result, "a", offset++);
9476 /* Bit field did not fit in a byte. Copy all
9477 but the partial byte at the end. */
9478 for (rlen=blen;rlen>=8;rlen-=8)
9480 emitPtrByteGet (rname, ptype, FALSE);
9481 aopPut (result, "a", offset++);
9483 emitcode ("inc", "%s", rname);
9486 /* Handle the partial byte at the end */
9489 emitPtrByteGet (rname, ptype, FALSE);
9490 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9491 if (!SPEC_USIGN (etype))
9493 /* signed bitfield */
9494 symbol *tlbl = newiTempLabel (NULL);
9496 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9497 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9500 aopPut (result, "a", offset++);
9508 if (SPEC_USIGN (etype))
9512 /* signed bitfield: sign extension with 0x00 or 0xff */
9513 emitcode ("rlc", "a");
9514 emitcode ("subb", "a,acc");
9520 aopPut (result, source, offset++);
9525 /*-----------------------------------------------------------------*/
9526 /* genDataPointerGet - generates code when ptr offset is known */
9527 /*-----------------------------------------------------------------*/
9529 genDataPointerGet (operand * left,
9535 int size, offset = 0;
9537 D(emitcode ("; genDataPointerGet",""));
9539 aopOp (result, ic, TRUE);
9541 /* get the string representation of the name */
9542 l = aopGet (left, 0, FALSE, TRUE);
9543 size = AOP_SIZE (result);
9548 SNPRINTF (buffer, sizeof(buffer),
9549 "(%s + %d)", l + 1, offset);
9552 sprintf (buffer, "%s", l + 1);
9553 aopPut (result, buffer, offset++);
9556 freeAsmop (result, NULL, ic, TRUE);
9557 freeAsmop (left, NULL, ic, TRUE);
9560 /*-----------------------------------------------------------------*/
9561 /* genNearPointerGet - emitcode for near pointer fetch */
9562 /*-----------------------------------------------------------------*/
9564 genNearPointerGet (operand * left,
9573 sym_link *rtype, *retype;
9574 sym_link *ltype = operandType (left);
9577 D(emitcode ("; genNearPointerGet",""));
9579 rtype = operandType (result);
9580 retype = getSpec (rtype);
9582 aopOp (left, ic, FALSE);
9584 /* if left is rematerialisable and
9585 result is not bitfield variable type and
9586 the left is pointer to data space i.e
9587 lower 128 bytes of space */
9588 if (AOP_TYPE (left) == AOP_IMMD &&
9589 !IS_BITFIELD (retype) &&
9590 DCL_TYPE (ltype) == POINTER)
9592 genDataPointerGet (left, result, ic);
9596 /* if the value is already in a pointer register
9597 then don't need anything more */
9598 if (!AOP_INPREG (AOP (left)))
9600 if (IS_AOP_PREG (left))
9602 // Aha, it is a pointer, just in disguise.
9603 rname = aopGet (left, 0, FALSE, FALSE);
9606 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9607 __FILE__, __LINE__);
9612 emitcode ("mov", "a%s,%s", rname + 1, rname);
9613 rname++; // skip the '@'.
9618 /* otherwise get a free pointer register */
9620 preg = getFreePtr (ic, &aop, FALSE);
9621 emitcode ("mov", "%s,%s",
9623 aopGet (left, 0, FALSE, TRUE));
9628 rname = aopGet (left, 0, FALSE, FALSE);
9630 //aopOp (result, ic, FALSE);
9631 aopOp (result, ic, result?TRUE:FALSE);
9633 /* if bitfield then unpack the bits */
9634 if (IS_BITFIELD (retype))
9635 genUnpackBits (result, rname, POINTER, ifx);
9638 /* we have can just get the values */
9639 int size = AOP_SIZE (result);
9644 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9647 emitcode ("mov", "a,@%s", rname);
9649 aopPut (result, "a", offset);
9653 sprintf (buffer, "@%s", rname);
9654 aopPut (result, buffer, offset);
9658 emitcode ("inc", "%s", rname);
9662 /* now some housekeeping stuff */
9663 if (aop) /* we had to allocate for this iCode */
9665 if (pi) { /* post increment present */
9666 aopPut (left, rname, 0);
9668 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9672 /* we did not allocate which means left
9673 already in a pointer register, then
9674 if size > 0 && this could be used again
9675 we have to point it back to where it
9677 if ((AOP_SIZE (result) > 1 &&
9678 !OP_SYMBOL (left)->remat &&
9679 (OP_SYMBOL (left)->liveTo > ic->seq ||
9683 int size = AOP_SIZE (result) - 1;
9685 emitcode ("dec", "%s", rname);
9689 if (ifx && !ifx->generated)
9691 genIfxJump (ifx, "a", left, NULL, result);
9695 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9696 freeAsmop (left, NULL, ic, TRUE);
9697 if (pi) pi->generated = 1;
9700 /*-----------------------------------------------------------------*/
9701 /* genPagedPointerGet - emitcode for paged pointer fetch */
9702 /*-----------------------------------------------------------------*/
9704 genPagedPointerGet (operand * left,
9713 sym_link *rtype, *retype;
9715 D(emitcode ("; genPagedPointerGet",""));
9717 rtype = operandType (result);
9718 retype = getSpec (rtype);
9720 aopOp (left, ic, FALSE);
9722 /* if the value is already in a pointer register
9723 then don't need anything more */
9724 if (!AOP_INPREG (AOP (left)))
9726 /* otherwise get a free pointer register */
9728 preg = getFreePtr (ic, &aop, FALSE);
9729 emitcode ("mov", "%s,%s",
9731 aopGet (left, 0, FALSE, TRUE));
9735 rname = aopGet (left, 0, FALSE, FALSE);
9737 aopOp (result, ic, FALSE);
9739 /* if bitfield then unpack the bits */
9740 if (IS_BITFIELD (retype))
9741 genUnpackBits (result, rname, PPOINTER, ifx);
9744 /* we have can just get the values */
9745 int size = AOP_SIZE (result);
9751 emitcode ("movx", "a,@%s", rname);
9753 aopPut (result, "a", offset);
9758 emitcode ("inc", "%s", rname);
9762 /* now some housekeeping stuff */
9763 if (aop) /* we had to allocate for this iCode */
9766 aopPut (left, rname, 0);
9767 freeAsmop (NULL, aop, ic, TRUE);
9771 /* we did not allocate which means left
9772 already in a pointer register, then
9773 if size > 0 && this could be used again
9774 we have to point it back to where it
9776 if ((AOP_SIZE (result) > 1 &&
9777 !OP_SYMBOL (left)->remat &&
9778 (OP_SYMBOL (left)->liveTo > ic->seq ||
9782 int size = AOP_SIZE (result) - 1;
9784 emitcode ("dec", "%s", rname);
9788 if (ifx && !ifx->generated)
9790 genIfxJump (ifx, "a", left, NULL, result);
9794 freeAsmop (result, NULL, ic, TRUE);
9795 freeAsmop (left, NULL, ic, TRUE);
9796 if (pi) pi->generated = 1;
9799 /*--------------------------------------------------------------------*/
9800 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9801 /*--------------------------------------------------------------------*/
9803 loadDptrFromOperand (operand *op, bool loadBToo)
9805 if (AOP_TYPE (op) != AOP_STR)
9807 /* if this is rematerializable */
9808 if (AOP_TYPE (op) == AOP_IMMD)
9810 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9813 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9814 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9817 wassertl(FALSE, "need pointerCode");
9818 emitcode ("", "; mov b,???");
9819 /* genPointerGet and genPointerSet originally did different
9820 ** things for this case. Both seem wrong.
9821 ** from genPointerGet:
9822 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9823 ** from genPointerSet:
9824 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9829 else if (AOP_TYPE (op) == AOP_DPTR)
9833 MOVA (aopGet (op, 0, FALSE, FALSE));
9834 emitcode ("push", "acc");
9835 MOVA (aopGet (op, 1, FALSE, FALSE));
9836 emitcode ("push", "acc");
9837 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9838 emitcode ("pop", "dph");
9839 emitcode ("pop", "dpl");
9843 MOVA (aopGet (op, 0, FALSE, FALSE));
9844 emitcode ("push", "acc");
9845 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9846 emitcode ("pop", "dpl");
9850 { /* we need to get it byte by byte */
9851 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9852 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9854 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9859 /*-----------------------------------------------------------------*/
9860 /* genFarPointerGet - get value from far space */
9861 /*-----------------------------------------------------------------*/
9863 genFarPointerGet (operand * left,
9864 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9867 sym_link *retype = getSpec (operandType (result));
9869 D(emitcode ("; genFarPointerGet",""));
9871 aopOp (left, ic, FALSE);
9872 loadDptrFromOperand (left, FALSE);
9874 /* so dptr now contains the address */
9875 aopOp (result, ic, FALSE);
9877 /* if bit then unpack */
9878 if (IS_BITFIELD (retype))
9879 genUnpackBits (result, "dptr", FPOINTER, ifx);
9882 size = AOP_SIZE (result);
9887 emitcode ("movx", "a,@dptr");
9889 aopPut (result, "a", offset++);
9891 emitcode ("inc", "dptr");
9895 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9897 aopPut (left, "dpl", 0);
9898 aopPut (left, "dph", 1);
9902 if (ifx && !ifx->generated)
9904 genIfxJump (ifx, "a", left, NULL, result);
9907 freeAsmop (result, NULL, ic, TRUE);
9908 freeAsmop (left, NULL, ic, TRUE);
9911 /*-----------------------------------------------------------------*/
9912 /* genCodePointerGet - get value from code space */
9913 /*-----------------------------------------------------------------*/
9915 genCodePointerGet (operand * left,
9916 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9919 sym_link *retype = getSpec (operandType (result));
9921 D(emitcode ("; genCodePointerGet",""));
9923 aopOp (left, ic, FALSE);
9924 loadDptrFromOperand (left, FALSE);
9926 /* so dptr now contains the address */
9927 aopOp (result, ic, FALSE);
9929 /* if bit then unpack */
9930 if (IS_BITFIELD (retype))
9931 genUnpackBits (result, "dptr", CPOINTER, ifx);
9934 size = AOP_SIZE (result);
9939 emitcode ("clr", "a");
9940 emitcode ("movc", "a,@a+dptr");
9942 aopPut (result, "a", offset++);
9944 emitcode ("inc", "dptr");
9948 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9950 aopPut (left, "dpl", 0);
9951 aopPut (left, "dph", 1);
9955 if (ifx && !ifx->generated)
9957 genIfxJump (ifx, "a", left, NULL, result);
9960 freeAsmop (result, NULL, ic, TRUE);
9961 freeAsmop (left, NULL, ic, TRUE);
9964 /*-----------------------------------------------------------------*/
9965 /* genGenPointerGet - get value from generic pointer space */
9966 /*-----------------------------------------------------------------*/
9968 genGenPointerGet (operand * left,
9969 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9972 sym_link *retype = getSpec (operandType (result));
9974 D (emitcode (";", "genGenPointerGet"));
9976 aopOp (left, ic, FALSE);
9977 loadDptrFromOperand (left, TRUE);
9979 /* so dptr now contains the address */
9980 aopOp (result, ic, FALSE);
9982 /* if bit then unpack */
9983 if (IS_BITFIELD (retype))
9985 genUnpackBits (result, "dptr", GPOINTER, ifx);
9989 size = AOP_SIZE (result);
9994 emitcode ("lcall", "__gptrget");
9996 aopPut (result, "a", offset++);
9998 emitcode ("inc", "dptr");
10002 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10004 aopPut (left, "dpl", 0);
10005 aopPut (left, "dph", 1);
10009 if (ifx && !ifx->generated)
10011 genIfxJump (ifx, "a", left, NULL, result);
10014 freeAsmop (result, NULL, ic, TRUE);
10015 freeAsmop (left, NULL, ic, TRUE);
10018 /*-----------------------------------------------------------------*/
10019 /* genPointerGet - generate code for pointer get */
10020 /*-----------------------------------------------------------------*/
10022 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10024 operand *left, *result;
10025 sym_link *type, *etype;
10028 D (emitcode (";", "genPointerGet"));
10030 left = IC_LEFT (ic);
10031 result = IC_RESULT (ic);
10033 if (getSize (operandType (result))>1)
10036 /* depending on the type of pointer we need to
10037 move it to the correct pointer register */
10038 type = operandType (left);
10039 etype = getSpec (type);
10040 /* if left is of type of pointer then it is simple */
10041 if (IS_PTR (type) && !IS_FUNC (type->next))
10042 p_type = DCL_TYPE (type);
10045 /* we have to go by the storage class */
10046 p_type = PTR_TYPE (SPEC_OCLS (etype));
10049 /* special case when cast remat */
10050 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10051 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10053 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10054 type = operandType (left);
10055 p_type = DCL_TYPE (type);
10057 /* now that we have the pointer type we assign
10058 the pointer values */
10064 genNearPointerGet (left, result, ic, pi, ifx);
10068 genPagedPointerGet (left, result, ic, pi, ifx);
10072 genFarPointerGet (left, result, ic, pi, ifx);
10076 genCodePointerGet (left, result, ic, pi, ifx);
10080 genGenPointerGet (left, result, ic, pi, ifx);
10086 /*-----------------------------------------------------------------*/
10087 /* genPackBits - generates code for packed bit storage */
10088 /*-----------------------------------------------------------------*/
10090 genPackBits (sym_link * etype,
10092 char *rname, int p_type)
10094 int offset = 0; /* source byte offset */
10095 int rlen = 0; /* remaining bitfield length */
10096 int blen; /* bitfield length */
10097 int bstr; /* bitfield starting bit within byte */
10098 int litval; /* source literal value (if AOP_LIT) */
10099 unsigned char mask; /* bitmask within current byte */
10101 D(emitcode ("; genPackBits",""));
10103 blen = SPEC_BLEN (etype);
10104 bstr = SPEC_BSTR (etype);
10106 /* If the bitfield length is less than a byte */
10109 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10110 (unsigned char) (0xFF >> (8 - bstr)));
10112 if (AOP_TYPE (right) == AOP_LIT)
10114 /* Case with a bitfield length <8 and literal source
10116 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10118 litval &= (~mask) & 0xff;
10119 emitPtrByteGet (rname, p_type, FALSE);
10120 if ((mask|litval)!=0xff)
10121 emitcode ("anl","a,#0x%02x", mask);
10123 emitcode ("orl","a,#0x%02x", litval);
10127 if ((blen==1) && (p_type!=GPOINTER))
10129 /* Case with a bitfield length == 1 and no generic pointer
10131 if (AOP_TYPE (right) == AOP_CRY)
10132 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10135 MOVA (aopGet (right, 0, FALSE, FALSE));
10136 emitcode ("rrc","a");
10138 emitPtrByteGet (rname, p_type, FALSE);
10139 emitcode ("mov","acc.%d,c",bstr);
10144 /* Case with a bitfield length < 8 and arbitrary source
10146 MOVA (aopGet (right, 0, FALSE, FALSE));
10147 /* shift and mask source value */
10149 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10151 pushedB = pushB ();
10152 /* transfer A to B and get next byte */
10153 emitPtrByteGet (rname, p_type, TRUE);
10155 emitcode ("anl", "a,#0x%02x", mask);
10156 emitcode ("orl", "a,b");
10157 if (p_type == GPOINTER)
10158 emitcode ("pop", "b");
10164 emitPtrByteSet (rname, p_type, "a");
10168 /* Bit length is greater than 7 bits. In this case, copy */
10169 /* all except the partial byte at the end */
10170 for (rlen=blen;rlen>=8;rlen-=8)
10172 emitPtrByteSet (rname, p_type,
10173 aopGet (right, offset++, FALSE, TRUE) );
10175 emitcode ("inc", "%s", rname);
10178 /* If there was a partial byte at the end */
10181 mask = (((unsigned char) -1 << rlen) & 0xff);
10183 if (AOP_TYPE (right) == AOP_LIT)
10185 /* Case with partial byte and literal source
10187 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10188 litval >>= (blen-rlen);
10189 litval &= (~mask) & 0xff;
10190 emitPtrByteGet (rname, p_type, FALSE);
10191 if ((mask|litval)!=0xff)
10192 emitcode ("anl","a,#0x%02x", mask);
10194 emitcode ("orl","a,#0x%02x", litval);
10199 /* Case with partial byte and arbitrary source
10201 MOVA (aopGet (right, offset++, FALSE, FALSE));
10202 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10204 pushedB = pushB ();
10205 /* transfer A to B and get next byte */
10206 emitPtrByteGet (rname, p_type, TRUE);
10208 emitcode ("anl", "a,#0x%02x", mask);
10209 emitcode ("orl", "a,b");
10210 if (p_type == GPOINTER)
10211 emitcode ("pop", "b");
10215 emitPtrByteSet (rname, p_type, "a");
10220 /*-----------------------------------------------------------------*/
10221 /* genDataPointerSet - remat pointer to data space */
10222 /*-----------------------------------------------------------------*/
10224 genDataPointerSet (operand * right,
10228 int size, offset = 0;
10229 char *l, buffer[256];
10231 D (emitcode (";", "genDataPointerSet"));
10233 aopOp (right, ic, FALSE);
10235 l = aopGet (result, 0, FALSE, TRUE);
10236 size = AOP_SIZE (right);
10240 sprintf (buffer, "(%s + %d)", l + 1, offset);
10242 sprintf (buffer, "%s", l + 1);
10243 emitcode ("mov", "%s,%s", buffer,
10244 aopGet (right, offset++, FALSE, FALSE));
10247 freeAsmop (result, NULL, ic, TRUE);
10248 freeAsmop (right, NULL, ic, TRUE);
10251 /*-----------------------------------------------------------------*/
10252 /* genNearPointerSet - emitcode for near pointer put */
10253 /*-----------------------------------------------------------------*/
10255 genNearPointerSet (operand * right,
10263 sym_link *retype, *letype;
10264 sym_link *ptype = operandType (result);
10266 D (emitcode (";", "genNearPointerSet"));
10268 retype = getSpec (operandType (right));
10269 letype = getSpec (ptype);
10271 aopOp (result, ic, FALSE);
10273 /* if the result is rematerializable &
10274 in data space & not a bit variable */
10275 if (AOP_TYPE (result) == AOP_IMMD &&
10276 DCL_TYPE (ptype) == POINTER &&
10277 !IS_BITVAR (retype) &&
10278 !IS_BITVAR (letype))
10280 genDataPointerSet (right, result, ic);
10284 /* if the value is already in a pointer register
10285 then don't need anything more */
10286 if (!AOP_INPREG (AOP (result)))
10289 //AOP_TYPE (result) == AOP_STK
10290 IS_AOP_PREG(result)
10293 // Aha, it is a pointer, just in disguise.
10294 rname = aopGet (result, 0, FALSE, FALSE);
10297 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10298 __FILE__, __LINE__);
10303 emitcode ("mov", "a%s,%s", rname + 1, rname);
10304 rname++; // skip the '@'.
10309 /* otherwise get a free pointer register */
10310 aop = newAsmop (0);
10311 preg = getFreePtr (ic, &aop, FALSE);
10312 emitcode ("mov", "%s,%s",
10314 aopGet (result, 0, FALSE, TRUE));
10315 rname = preg->name;
10320 rname = aopGet (result, 0, FALSE, FALSE);
10323 aopOp (right, ic, FALSE);
10325 /* if bitfield then unpack the bits */
10326 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10327 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10330 /* we can just get the values */
10331 int size = AOP_SIZE (right);
10336 l = aopGet (right, offset, FALSE, TRUE);
10337 if ((*l == '@') || (strcmp (l, "acc") == 0))
10340 emitcode ("mov", "@%s,a", rname);
10343 emitcode ("mov", "@%s,%s", rname, l);
10345 emitcode ("inc", "%s", rname);
10350 /* now some housekeeping stuff */
10351 if (aop) /* we had to allocate for this iCode */
10354 aopPut (result, rname, 0);
10355 freeAsmop (NULL, aop, ic, TRUE);
10359 /* we did not allocate which means left
10360 already in a pointer register, then
10361 if size > 0 && this could be used again
10362 we have to point it back to where it
10364 if ((AOP_SIZE (right) > 1 &&
10365 !OP_SYMBOL (result)->remat &&
10366 (OP_SYMBOL (result)->liveTo > ic->seq ||
10370 int size = AOP_SIZE (right) - 1;
10372 emitcode ("dec", "%s", rname);
10377 if (pi) pi->generated = 1;
10378 freeAsmop (result, NULL, ic, TRUE);
10379 freeAsmop (right, NULL, ic, TRUE);
10382 /*-----------------------------------------------------------------*/
10383 /* genPagedPointerSet - emitcode for Paged pointer put */
10384 /*-----------------------------------------------------------------*/
10386 genPagedPointerSet (operand * right,
10394 sym_link *retype, *letype;
10396 D (emitcode (";", "genPagedPointerSet"));
10398 retype = getSpec (operandType (right));
10399 letype = getSpec (operandType (result));
10401 aopOp (result, ic, FALSE);
10403 /* if the value is already in a pointer register
10404 then don't need anything more */
10405 if (!AOP_INPREG (AOP (result)))
10407 /* otherwise get a free pointer register */
10408 aop = newAsmop (0);
10409 preg = getFreePtr (ic, &aop, FALSE);
10410 emitcode ("mov", "%s,%s",
10412 aopGet (result, 0, FALSE, TRUE));
10413 rname = preg->name;
10416 rname = aopGet (result, 0, FALSE, FALSE);
10418 aopOp (right, ic, FALSE);
10420 /* if bitfield then unpack the bits */
10421 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10422 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10425 /* we have can just get the values */
10426 int size = AOP_SIZE (right);
10431 l = aopGet (right, offset, FALSE, TRUE);
10433 emitcode ("movx", "@%s,a", rname);
10436 emitcode ("inc", "%s", rname);
10442 /* now some housekeeping stuff */
10443 if (aop) /* we had to allocate for this iCode */
10446 aopPut (result, rname, 0);
10447 freeAsmop (NULL, aop, ic, TRUE);
10451 /* we did not allocate which means left
10452 already in a pointer register, then
10453 if size > 0 && this could be used again
10454 we have to point it back to where it
10456 if (AOP_SIZE (right) > 1 &&
10457 !OP_SYMBOL (result)->remat &&
10458 (OP_SYMBOL (result)->liveTo > ic->seq ||
10461 int size = AOP_SIZE (right) - 1;
10463 emitcode ("dec", "%s", rname);
10468 if (pi) pi->generated = 1;
10469 freeAsmop (result, NULL, ic, TRUE);
10470 freeAsmop (right, NULL, ic, TRUE);
10473 /*-----------------------------------------------------------------*/
10474 /* genFarPointerSet - set value from far space */
10475 /*-----------------------------------------------------------------*/
10477 genFarPointerSet (operand * right,
10478 operand * result, iCode * ic, iCode * pi)
10481 sym_link *retype = getSpec (operandType (right));
10482 sym_link *letype = getSpec (operandType (result));
10484 D(emitcode ("; genFarPointerSet",""));
10486 aopOp (result, ic, FALSE);
10487 loadDptrFromOperand (result, FALSE);
10489 /* so dptr know contains the address */
10490 aopOp (right, ic, FALSE);
10492 /* if bit then unpack */
10493 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10494 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10497 size = AOP_SIZE (right);
10502 char *l = aopGet (right, offset++, FALSE, FALSE);
10504 emitcode ("movx", "@dptr,a");
10506 emitcode ("inc", "dptr");
10509 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10510 aopPut (result, "dpl", 0);
10511 aopPut (result, "dph", 1);
10514 freeAsmop (result, NULL, ic, TRUE);
10515 freeAsmop (right, NULL, ic, TRUE);
10518 /*-----------------------------------------------------------------*/
10519 /* genGenPointerSet - set value from generic pointer space */
10520 /*-----------------------------------------------------------------*/
10522 genGenPointerSet (operand * right,
10523 operand * result, iCode * ic, iCode * pi)
10526 sym_link *retype = getSpec (operandType (right));
10527 sym_link *letype = getSpec (operandType (result));
10529 D(emitcode ("; genGenPointerSet",""));
10531 aopOp (result, ic, FALSE);
10532 loadDptrFromOperand (result, TRUE);
10534 /* so dptr know contains the address */
10535 aopOp (right, ic, FALSE);
10537 /* if bit then unpack */
10538 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10540 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10544 size = AOP_SIZE (right);
10549 char *l = aopGet (right, offset++, FALSE, FALSE);
10551 emitcode ("lcall", "__gptrput");
10553 emitcode ("inc", "dptr");
10557 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10558 aopPut (result, "dpl", 0);
10559 aopPut (result, "dph", 1);
10562 freeAsmop (result, NULL, ic, TRUE);
10563 freeAsmop (right, NULL, ic, TRUE);
10566 /*-----------------------------------------------------------------*/
10567 /* genPointerSet - stores the value into a pointer location */
10568 /*-----------------------------------------------------------------*/
10570 genPointerSet (iCode * ic, iCode *pi)
10572 operand *right, *result;
10573 sym_link *type, *etype;
10576 D (emitcode (";", "genPointerSet"));
10578 right = IC_RIGHT (ic);
10579 result = IC_RESULT (ic);
10581 /* depending on the type of pointer we need to
10582 move it to the correct pointer register */
10583 type = operandType (result);
10584 etype = getSpec (type);
10585 /* if left is of type of pointer then it is simple */
10586 if (IS_PTR (type) && !IS_FUNC (type->next))
10588 p_type = DCL_TYPE (type);
10592 /* we have to go by the storage class */
10593 p_type = PTR_TYPE (SPEC_OCLS (etype));
10596 /* special case when cast remat */
10597 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10598 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10599 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10600 type = operandType (result);
10601 p_type = DCL_TYPE (type);
10604 /* now that we have the pointer type we assign
10605 the pointer values */
10611 genNearPointerSet (right, result, ic, pi);
10615 genPagedPointerSet (right, result, ic, pi);
10619 genFarPointerSet (right, result, ic, pi);
10623 genGenPointerSet (right, result, ic, pi);
10627 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10628 "genPointerSet: illegal pointer type");
10632 /*-----------------------------------------------------------------*/
10633 /* genIfx - generate code for Ifx statement */
10634 /*-----------------------------------------------------------------*/
10636 genIfx (iCode * ic, iCode * popIc)
10638 operand *cond = IC_COND (ic);
10642 D (emitcode (";", "genIfx"));
10644 aopOp (cond, ic, FALSE);
10646 /* get the value into acc */
10647 if (AOP_TYPE (cond) != AOP_CRY)
10654 if (AOP(cond)->aopu.aop_dir)
10655 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10658 /* the result is now in the accumulator or a directly addressable bit */
10659 freeAsmop (cond, NULL, ic, TRUE);
10661 /* if there was something to be popped then do it */
10665 /* if the condition is a bit variable */
10667 genIfxJump(ic, dup, NULL, NULL, NULL);
10668 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10669 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10670 else if (isbit && !IS_ITEMP (cond))
10671 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10673 genIfxJump (ic, "a", NULL, NULL, NULL);
10678 /*-----------------------------------------------------------------*/
10679 /* genAddrOf - generates code for address of */
10680 /*-----------------------------------------------------------------*/
10682 genAddrOf (iCode * ic)
10684 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10687 D (emitcode (";", "genAddrOf"));
10689 aopOp (IC_RESULT (ic), ic, FALSE);
10691 /* if the operand is on the stack then we
10692 need to get the stack offset of this
10696 /* if it has an offset then we need to compute it */
10699 emitcode ("mov", "a,%s", SYM_BP (sym));
10700 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10701 ((char) (sym->stack - _G.nRegsSaved)) :
10702 ((char) sym->stack)) & 0xff);
10703 aopPut (IC_RESULT (ic), "a", 0);
10707 /* we can just move _bp */
10708 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10710 /* fill the result with zero */
10711 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10716 aopPut (IC_RESULT (ic), zero, offset++);
10721 /* object not on stack then we need the name */
10722 size = AOP_SIZE (IC_RESULT (ic));
10727 char s[SDCC_NAME_MAX];
10729 sprintf (s, "#(%s >> %d)",
10733 sprintf (s, "#%s", sym->rname);
10734 aopPut (IC_RESULT (ic), s, offset++);
10738 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10742 /*-----------------------------------------------------------------*/
10743 /* genFarFarAssign - assignment when both are in far space */
10744 /*-----------------------------------------------------------------*/
10746 genFarFarAssign (operand * result, operand * right, iCode * ic)
10748 int size = AOP_SIZE (right);
10752 D(emitcode ("; genFarFarAssign",""));
10754 /* first push the right side on to the stack */
10757 l = aopGet (right, offset++, FALSE, FALSE);
10759 emitcode ("push", "acc");
10762 freeAsmop (right, NULL, ic, FALSE);
10763 /* now assign DPTR to result */
10764 aopOp (result, ic, FALSE);
10765 size = AOP_SIZE (result);
10768 emitcode ("pop", "acc");
10769 aopPut (result, "a", --offset);
10771 freeAsmop (result, NULL, ic, FALSE);
10774 /*-----------------------------------------------------------------*/
10775 /* genAssign - generate code for assignment */
10776 /*-----------------------------------------------------------------*/
10778 genAssign (iCode * ic)
10780 operand *result, *right;
10782 unsigned long lit = 0L;
10784 D (emitcode (";", "genAssign"));
10786 result = IC_RESULT (ic);
10787 right = IC_RIGHT (ic);
10789 /* if they are the same */
10790 if (operandsEqu (result, right) &&
10791 !isOperandVolatile (result, FALSE) &&
10792 !isOperandVolatile (right, FALSE))
10795 aopOp (right, ic, FALSE);
10797 /* special case both in far space */
10798 if (AOP_TYPE (right) == AOP_DPTR &&
10799 IS_TRUE_SYMOP (result) &&
10800 isOperandInFarSpace (result))
10802 genFarFarAssign (result, right, ic);
10806 aopOp (result, ic, TRUE);
10808 /* if they are the same registers */
10809 if (sameRegs (AOP (right), AOP (result)) &&
10810 !isOperandVolatile (result, FALSE) &&
10811 !isOperandVolatile (right, FALSE))
10814 /* if the result is a bit */
10815 if (AOP_TYPE (result) == AOP_CRY)
10817 /* if the right size is a literal then
10818 we know what the value is */
10819 if (AOP_TYPE (right) == AOP_LIT)
10821 if (((int) operandLitValue (right)))
10822 aopPut (result, one, 0);
10824 aopPut (result, zero, 0);
10828 /* the right is also a bit variable */
10829 if (AOP_TYPE (right) == AOP_CRY)
10831 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10832 aopPut (result, "c", 0);
10836 /* we need to or */
10838 aopPut (result, "a", 0);
10842 /* bit variables done */
10844 size = AOP_SIZE (result);
10846 if (AOP_TYPE (right) == AOP_LIT)
10847 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10850 (AOP_TYPE (result) != AOP_REG) &&
10851 (AOP_TYPE (right) == AOP_LIT) &&
10852 !IS_FLOAT (operandType (right)) &&
10855 while ((size) && (lit))
10858 aopGet (right, offset, FALSE, FALSE),
10864 /* And now fill the rest with zeros. */
10867 emitcode ("clr", "a");
10871 aopPut (result, "a", offset);
10880 aopGet (right, offset, FALSE, FALSE),
10887 freeAsmop (result, NULL, ic, TRUE);
10888 freeAsmop (right, NULL, ic, TRUE);
10891 /*-----------------------------------------------------------------*/
10892 /* genJumpTab - generates code for jump table */
10893 /*-----------------------------------------------------------------*/
10895 genJumpTab (iCode * ic)
10897 symbol *jtab,*jtablo,*jtabhi;
10899 unsigned int count;
10901 D(emitcode ("; genJumpTab",""));
10903 count = elementsInSet( IC_JTLABELS (ic) );
10907 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10908 if the switch argument is in a register.
10909 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10910 /* Peephole may not convert ljmp to sjmp or ret
10911 labelIsReturnOnly & labelInRange must check
10912 currPl->ic->op != JUMPTABLE */
10913 aopOp (IC_JTCOND (ic), ic, FALSE);
10914 /* get the condition into accumulator */
10915 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10917 /* multiply by three */
10918 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10920 emitcode ("mov", "b,#3");
10921 emitcode ("mul", "ab");
10925 emitcode ("add", "a,acc");
10926 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10928 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10930 jtab = newiTempLabel (NULL);
10931 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10932 emitcode ("jmp", "@a+dptr");
10934 /* now generate the jump labels */
10935 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10936 jtab = setNextItem (IC_JTLABELS (ic)))
10937 emitcode ("ljmp", "%05d$", jtab->key + 100);
10941 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10942 if the switch argument is in a register.
10943 For n>6 this algorithm may be more compact */
10944 jtablo = newiTempLabel (NULL);
10945 jtabhi = newiTempLabel (NULL);
10947 /* get the condition into accumulator.
10948 Using b as temporary storage, if register push/pop is needed */
10949 aopOp (IC_JTCOND (ic), ic, FALSE);
10950 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10951 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10952 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10954 // (MB) what if B is in use???
10955 wassertl(!BINUSE, "B was in use");
10956 emitcode ("mov", "b,%s", l);
10959 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10963 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10964 emitcode ("movc", "a,@a+pc");
10965 emitcode ("push", "acc");
10968 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10969 emitcode ("movc", "a,@a+pc");
10970 emitcode ("push", "acc");
10974 /* this scales up to n<=255, but needs two more bytes
10975 and changes dptr */
10976 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10977 emitcode ("movc", "a,@a+dptr");
10978 emitcode ("push", "acc");
10981 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10982 emitcode ("movc", "a,@a+dptr");
10983 emitcode ("push", "acc");
10986 emitcode ("ret", "");
10988 /* now generate jump table, LSB */
10989 emitLabel (jtablo);
10990 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10991 jtab = setNextItem (IC_JTLABELS (ic)))
10992 emitcode (".db", "%05d$", jtab->key + 100);
10994 /* now generate jump table, MSB */
10995 emitLabel (jtabhi);
10996 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10997 jtab = setNextItem (IC_JTLABELS (ic)))
10998 emitcode (".db", "%05d$>>8", jtab->key + 100);
11002 /*-----------------------------------------------------------------*/
11003 /* genCast - gen code for casting */
11004 /*-----------------------------------------------------------------*/
11006 genCast (iCode * ic)
11008 operand *result = IC_RESULT (ic);
11009 sym_link *ctype = operandType (IC_LEFT (ic));
11010 sym_link *rtype = operandType (IC_RIGHT (ic));
11011 operand *right = IC_RIGHT (ic);
11014 D (emitcode (";", "genCast"));
11016 /* if they are equivalent then do nothing */
11017 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11020 aopOp (right, ic, FALSE);
11021 aopOp (result, ic, FALSE);
11023 /* if the result is a bit (and not a bitfield) */
11024 // if (AOP_TYPE (result) == AOP_CRY)
11025 if (IS_BIT (OP_SYMBOL (result)->type))
11026 /* not for bitfields */
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);
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 ("", ";%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))
11739 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11765 addSet (&_G.sendSet, ic);
11768 case DUMMY_READ_VOLATILE:
11777 genEndCritical (ic);
11789 _G.current_iCode = NULL;
11791 /* now we are ready to call the
11792 peep hole optimizer */
11793 if (!options.nopeep)
11794 peepHole (&lineHead);
11796 /* now do the actual printing */
11797 printLine (lineHead, codeOutFile);