1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define REG_WITH_INDEX mcs51_regWithIdx
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74 AOP_TYPE(x) == AOP_R0))
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
77 AOP_TYPE(x) == AOP_DPTR || \
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
81 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86 #define R0INB _G.bu.bs.r0InB
87 #define R1INB _G.bu.bs.r1InB
88 #define OPINB _G.bu.bs.OpInB
89 #define BINUSE _G.bu.BInUse
99 short r0InB : 2;//2 so we can see it overflow
100 short r1InB : 2;//2 so we can see it overflow
101 short OpInB : 2;//2 so we can see it overflow
110 iCode *current_iCode;
115 static char *rb1regs[] = {
116 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (char *inst, const char *fmt,...)
155 char lb[INITIAL_INLINEASM];
164 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
168 SNPRINTF (lb, sizeof(lb), "%s", inst);
171 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
175 tvsprintf (lb, sizeof(lb), fmt, ap);
178 while (isspace ((unsigned char)*lbp))
185 lineCurr = (lineCurr ?
186 connectLine (lineCurr, newLineNode (lb)) :
187 (lineHead = newLineNode (lb)));
190 lineCurr->isInline = _G.inLine;
191 lineCurr->isDebug = _G.debugLine;
192 lineCurr->ic = _G.current_iCode;
193 lineCurr->isComment = (*lbp==';');
198 emitLabel (symbol *tlbl)
200 emitcode ("", "%05d$:", tlbl->key + 100);
203 /*-----------------------------------------------------------------*/
204 /* mcs51_emitDebuggerSymbol - associate the current code location */
205 /* with a debugger symbol */
206 /*-----------------------------------------------------------------*/
208 mcs51_emitDebuggerSymbol (char * debugSym)
211 emitcode ("", "%s ==.", debugSym);
215 /*-----------------------------------------------------------------*/
216 /* mova - moves specified value into accumulator */
217 /*-----------------------------------------------------------------*/
221 /* do some early peephole optimization */
222 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
225 emitcode("mov", "a,%s", x);
228 /*-----------------------------------------------------------------*/
229 /* movb - moves specified value into register b */
230 /*-----------------------------------------------------------------*/
234 /* do some early peephole optimization */
235 if (!strncmp(x, "b", 2))
238 emitcode("mov","b,%s", x);
241 /*-----------------------------------------------------------------*/
242 /* movc - moves specified value into the carry */
243 /*-----------------------------------------------------------------*/
251 else if (strcmp (s, "c"))
252 {/* it's not in carry already */
254 /* set C, if a >= 1 */
255 emitcode ("add", "a,#0xff");
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary */
261 /*-----------------------------------------------------------------*/
265 bool pushedB = FALSE;
269 emitcode ("push", "b");
270 // printf("B was in use !\n");
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary */
282 /*-----------------------------------------------------------------*/
288 emitcode ("pop", "b");
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register */
298 /*-----------------------------------------------------------------*/
300 pushReg (int index, bool bits_pushed)
302 regs * reg = REG_WITH_INDEX (index);
303 if (reg->type == REG_BIT)
306 emitcode ("push", "%s", reg->base);
310 emitcode ("push", "%s", reg->dname);
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register */
316 /*-----------------------------------------------------------------*/
318 popReg (int index, bool bits_popped)
320 regs * reg = REG_WITH_INDEX (index);
321 if (reg->type == REG_BIT)
324 emitcode ("pop", "%s", reg->base);
328 emitcode ("pop", "%s", reg->dname);
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
341 /* the logic: if r0 & r1 used in the instruction
342 then we are in trouble otherwise */
344 /* first check if r0 & r1 are used by this
345 instruction, in which case we are in trouble */
346 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
352 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355 /* if no usage of r0 then return it */
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
364 /* if no usage of r1 then return it */
367 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368 (*aopp)->type = AOP_R1;
370 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
373 /* now we know they both have usage */
374 /* if r0 not used in this instruction */
377 /* push it if not already pushed */
380 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
383 else if (!_G.r0Pushed)
385 emitcode ("push", "%s",
386 REG_WITH_INDEX (R0_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391 (*aopp)->type = AOP_R0;
393 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
396 /* if r1 not used then */
400 /* push it if not already pushed */
403 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
406 else if (!_G.r1Pushed)
408 emitcode ("push", "%s",
409 REG_WITH_INDEX (R1_IDX)->dname);
413 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414 (*aopp)->type = AOP_R1;
415 return REG_WITH_INDEX (R1_IDX);
419 /* I said end of world, but not quite end of world yet */
420 /* if this is a result then we can push it on the stack */
423 (*aopp)->type = AOP_STK;
426 /* in the case that result AND left AND right needs a pointer reg
427 we can safely use the result's */
428 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430 (*aopp)->type = AOP_R0;
431 return REG_WITH_INDEX (R0_IDX);
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435 (*aopp)->type = AOP_R1;
436 return REG_WITH_INDEX (R1_IDX);
439 /* now this is REALLY the end of the world */
440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441 "getFreePtr should never reach here");
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /* that are not in use. Returns 1 if the requested */
449 /* number of registers were available, 0 otherwise. */
450 /*-----------------------------------------------------------------*/
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
459 ic = _G.current_iCode;
465 freeRegs = newBitVect(8);
466 bitVectSetBit (freeRegs, R2_IDX);
467 bitVectSetBit (freeRegs, R3_IDX);
468 bitVectSetBit (freeRegs, R4_IDX);
469 bitVectSetBit (freeRegs, R5_IDX);
470 bitVectSetBit (freeRegs, R6_IDX);
471 bitVectSetBit (freeRegs, R7_IDX);
473 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475 bitVect * newfreeRegs;
476 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477 freeBitVect(freeRegs);
478 freeRegs = newfreeRegs;
480 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
483 for (i=0; i<freeRegs->size; i++)
485 if (bitVectBitValue(freeRegs,i))
486 tempRegs[offset++] = REG_WITH_INDEX(i);
489 freeBitVect(freeRegs);
494 freeBitVect(freeRegs);
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp */
501 /*-----------------------------------------------------------------*/
503 newAsmop (short type)
507 aop = Safe_calloc (1, sizeof (asmop));
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type */
515 /*-----------------------------------------------------------------*/
517 pointerCode (sym_link * etype)
520 return PTR_TYPE (SPEC_OCLS (etype));
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands */
526 /*-----------------------------------------------------------------*/
528 leftRightUseAcc(iCode *ic)
537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538 "null iCode pointer");
545 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
548 size = getSize (OP_SYMBOL (op)->type);
553 else if (ic->op == JUMPTABLE)
556 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
559 size = getSize (OP_SYMBOL (op)->type);
567 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
570 size = getSize (OP_SYMBOL (op)->type);
575 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
578 size = getSize (OP_SYMBOL (op)->type);
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol */
592 /*-----------------------------------------------------------------*/
594 aopForSym (iCode * ic, symbol * sym, bool result)
598 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600 wassertl (ic != NULL, "Got a null iCode");
601 wassertl (sym != NULL, "Got a null symbol");
603 space = SPEC_OCLS (sym->etype);
605 /* if already has one */
608 sym->aop->allocated++;
612 /* assign depending on the storage class */
613 /* if it is on the stack or indirectly addressable */
614 /* space we need to assign either r0 or r1 to it */
615 if (sym->onStack || sym->iaccess)
617 sym->aop = aop = newAsmop (0);
618 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619 aop->size = getSize (sym->type);
621 /* now assign the address of the variable to
622 the pointer register */
623 if (aop->type != AOP_STK)
627 signed char offset = ((sym->stack < 0) ?
628 ((signed char) (sym->stack - _G.nRegsSaved)) :
629 ((signed char) sym->stack)) & 0xff;
631 if ((abs(offset) <= 3) ||
632 (accuse && (abs(offset) <= 7)))
634 emitcode ("mov", "%s,%s",
635 aop->aopu.aop_ptr->name, SYM_BP (sym));
638 emitcode ("dec", aop->aopu.aop_ptr->name);
643 emitcode ("inc", aop->aopu.aop_ptr->name);
650 emitcode ("push", "acc");
651 emitcode ("mov", "a,%s", SYM_BP (sym));
652 emitcode ("add", "a,#0x%02x", offset);
653 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655 emitcode ("pop", "acc");
660 emitcode ("mov", "%s,#%s",
661 aop->aopu.aop_ptr->name,
664 aop->paged = space->paged;
667 aop->aopu.aop_stk = sym->stack;
671 /* if in bit space */
672 if (IN_BITSPACE (space))
674 sym->aop = aop = newAsmop (AOP_CRY);
675 aop->aopu.aop_dir = sym->rname;
676 aop->size = getSize (sym->type);
679 /* if it is in direct space */
680 if (IN_DIRSPACE (space))
682 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683 //printTypeChainRaw(sym->type, NULL);
684 //printf("space = %s\n", space ? space->sname : "NULL");
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = getSize (sym->type);
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop (AOP_DPTR);
703 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
751 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
754 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755 /* set immd2 field if required */
756 if (aop->aopu.aop_immd.from_cast_remat)
758 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common */
767 /*-----------------------------------------------------------------*/
769 regsInCommon (operand * op1, operand * op2)
774 /* if they have registers in common */
775 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
778 sym1 = OP_SYMBOL (op1);
779 sym2 = OP_SYMBOL (op2);
781 if (sym1->nRegs == 0 || sym2->nRegs == 0)
784 for (i = 0; i < sym1->nRegs; i++)
790 for (j = 0; j < sym2->nRegs; j++)
795 if (sym2->regs[j] == sym1->regs[i])
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent */
805 /*-----------------------------------------------------------------*/
807 operandsEqu (operand * op1, operand * op2)
811 /* if they're not symbols */
812 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
815 sym1 = OP_SYMBOL (op1);
816 sym2 = OP_SYMBOL (op2);
818 /* if both are itemps & one is spilt
819 and the other is not then false */
820 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821 sym1->isspilt != sym2->isspilt)
824 /* if they are the same */
828 /* if they have the same rname */
829 if (sym1->rname[0] && sym2->rname[0] &&
830 strcmp (sym1->rname, sym2->rname) == 0 &&
831 !(IS_PARM (op2) && IS_ITEMP (op1)))
834 /* if left is a tmp & right is not */
835 if (IS_ITEMP (op1) &&
838 (sym1->usl.spillLoc == sym2))
841 if (IS_ITEMP (op2) &&
845 (sym2->usl.spillLoc == sym1))
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets */
853 /*-----------------------------------------------------------------*/
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
857 if (aop1 == aop2 && off1 == off2)
860 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
863 if (aop1->type != aop2->type)
866 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers */
874 /*-----------------------------------------------------------------*/
876 sameRegs (asmop * aop1, asmop * aop2)
883 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
886 if (aop1->type != aop2->type)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand : */
901 /*-----------------------------------------------------------------*/
903 aopOp (operand * op, iCode * ic, bool result)
912 /* if this a literal */
913 if (IS_OP_LITERAL (op))
915 op->aop = aop = newAsmop (AOP_LIT);
916 aop->aopu.aop_lit = op->operand.valOperand;
917 aop->size = getSize (operandType (op));
921 /* if already has a asmop then continue */
924 op->aop->allocated++;
928 /* if the underlying symbol has a aop */
929 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
931 op->aop = OP_SYMBOL (op)->aop;
932 op->aop->allocated++;
936 /* if this is a true symbol */
937 if (IS_TRUE_SYMOP (op))
939 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
943 /* this is a temporary : this has
949 e) can be a return use only */
951 sym = OP_SYMBOL (op);
953 /* if the type is a conditional */
954 if (sym->regType == REG_CND)
956 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
961 /* if it is spilt then two situations
963 b) has a spill location */
964 if (sym->isspilt || sym->nRegs == 0)
967 /* rematerialize it NOW */
970 sym->aop = op->aop = aop =
972 aop->size = getSize (sym->type);
979 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
980 aop->size = getSize (sym->type);
981 for (i = 0; i < 2; i++)
982 aop->aopu.aop_str[i] = accUse[i];
990 aop = op->aop = sym->aop = newAsmop (AOP_STR);
991 aop->size = getSize (sym->type);
992 for (i = 0; i < fReturnSizeMCS51; i++)
993 aop->aopu.aop_str[i] = fReturn[i];
997 if (sym->usl.spillLoc)
999 asmop *oldAsmOp = NULL;
1001 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1003 /* force a new aop if sizes differ */
1004 oldAsmOp = sym->usl.spillLoc->aop;
1005 sym->usl.spillLoc->aop = NULL;
1007 sym->aop = op->aop = aop =
1008 aopForSym (ic, sym->usl.spillLoc, result);
1009 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1011 /* Don't reuse the new aop, go with the last one */
1012 sym->usl.spillLoc->aop = oldAsmOp;
1014 aop->size = getSize (sym->type);
1018 /* else must be a dummy iTemp */
1019 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020 aop->size = getSize (sym->type);
1024 /* if the type is a bit register */
1025 if (sym->regType == REG_BIT)
1027 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028 aop->size = sym->nRegs;//1???
1029 aop->aopu.aop_reg[0] = sym->regs[0];
1030 aop->aopu.aop_dir = sym->regs[0]->name;
1034 /* must be in a register */
1035 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036 aop->size = sym->nRegs;
1037 for (i = 0; i < sym->nRegs; i++)
1038 aop->aopu.aop_reg[i] = sym->regs[i];
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand */
1043 /*----------------------------------------------------------------*/
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1062 /* depending on the asmop type only three cases need work
1063 AOP_R0, AOP_R1 & AOP_STK */
1069 emitcode ("mov", "r0,b");
1072 else if (_G.r0Pushed)
1076 emitcode ("pop", "ar0");
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1086 emitcode ("mov", "r1,b");
1089 else if (_G.r1Pushed)
1093 emitcode ("pop", "ar1");
1097 bitVectUnSetBit (ic->rUsed, R1_IDX);
1103 int stk = aop->aopu.aop_stk + aop->size - 1;
1104 bitVectUnSetBit (ic->rUsed, R0_IDX);
1105 bitVectUnSetBit (ic->rUsed, R1_IDX);
1107 getFreePtr (ic, &aop, FALSE);
1111 emitcode ("mov", "a,_bp");
1112 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1117 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122 emitcode ("pop", "acc");
1123 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1129 freeAsmop (op, NULL, ic, TRUE);
1132 emitcode ("pop", "ar1");
1137 emitcode ("pop", "ar0");
1145 /* all other cases just dealloc */
1151 OP_SYMBOL (op)->aop = NULL;
1152 /* if the symbol has a spill */
1154 SPIL_LOC (op)->aop = NULL;
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /* pop r0 or r1 off stack if pushed */
1162 /*------------------------------------------------------------------*/
1164 freeForBranchAsmop (operand * op)
1176 if (!aop->allocated)
1184 emitcode ("mov", "r0,b");
1186 else if (_G.r0Pushed)
1188 emitcode ("pop", "ar0");
1195 emitcode ("mov", "r1,b");
1197 else if (_G.r1Pushed)
1199 emitcode ("pop", "ar1");
1206 int stk = aop->aopu.aop_stk + aop->size - 1;
1208 emitcode ("mov", "b,r0");
1211 emitcode ("mov", "a,_bp");
1212 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213 emitcode ("mov", "r0,a");
1217 emitcode ("mov", "r0,_bp");
1222 emitcode ("pop", "acc");
1223 emitcode ("mov", "@r0,a");
1226 emitcode ("dec", "r0");
1228 emitcode ("mov", "r0,b");
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1236 /* clobber the accumulator */
1237 /*-----------------------------------------------------------------*/
1239 aopGetUsesAcc (operand * oper, int offset)
1241 asmop * aop = AOP (oper);
1243 if (offset > (aop->size - 1))
1261 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1272 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1278 /* Error case --- will have been caught already */
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop */
1286 /*-------------------------------------------------------------------*/
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1290 asmop * aop = AOP (oper);
1292 /* offset is greater than
1294 if (offset > (aop->size - 1) &&
1295 aop->type != AOP_LIT)
1298 /* depending on type */
1306 /* if we need to increment it */
1307 while (offset > aop->coff)
1309 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1313 while (offset < aop->coff)
1315 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1322 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323 return (dname ? "acc" : "a");
1325 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326 return Safe_strdup(buffer);
1329 if (aop->code && aop->coff==0 && offset>=1) {
1330 emitcode ("mov", "a,#0x%02x", offset);
1331 emitcode ("movc", "a,@a+dptr");
1332 return (dname ? "acc" : "a");
1335 while (offset > aop->coff)
1337 emitcode ("inc", "dptr");
1341 while (offset < aop->coff)
1343 emitcode ("lcall", "__decdptr");
1350 emitcode ("clr", "a");
1351 emitcode ("movc", "a,@a+dptr");
1355 emitcode ("movx", "a,@dptr");
1357 return (dname ? "acc" : "a");
1360 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1362 SNPRINTF(buffer, sizeof(buffer),
1363 "%s",aop->aopu.aop_immd.aop_immd2);
1367 SNPRINTF(buffer, sizeof(buffer),
1368 "#%s", aop->aopu.aop_immd.aop_immd1);
1372 SNPRINTF (buffer, sizeof(buffer),
1374 aop->aopu.aop_immd.aop_immd1,
1379 SNPRINTF (buffer, sizeof(buffer),
1381 aop->aopu.aop_immd.aop_immd1);
1383 return Safe_strdup(buffer);
1386 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1388 SNPRINTF (buffer, sizeof(buffer),
1390 aop->aopu.aop_dir, offset * 8);
1394 SNPRINTF (buffer, sizeof(buffer),
1401 SNPRINTF (buffer, sizeof(buffer),
1406 return Safe_strdup(buffer);
1410 return aop->aopu.aop_reg[offset]->dname;
1412 return aop->aopu.aop_reg[offset]->name;
1415 emitcode ("clr", "a");
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("rlc", "a");
1418 return (dname ? "acc" : "a");
1421 if (!offset && dname)
1423 return aop->aopu.aop_str[offset];
1426 return aopLiteral (aop->aopu.aop_lit, offset);
1430 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1434 return aop->aopu.aop_str[offset];
1438 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439 "aopget got unsupported aop->type");
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1445 /* clobber the accumulator */
1446 /*-----------------------------------------------------------------*/
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1450 asmop * aop = AOP (oper);
1452 if (offset > (aop->size - 1))
1462 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1468 return ((aop->paged) || (*s == '@'));
1472 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1480 /* Error case --- will have been caught already */
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1490 aopPut (operand * result, const char *s, int offset)
1492 bool bvolatile = isOperandVolatile (result, FALSE);
1493 bool accuse = FALSE;
1494 asmop * aop = AOP (result);
1496 if (aop->size && offset > (aop->size - 1))
1498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499 "aopPut got offset > aop->size");
1503 /* will assign value to value */
1504 /* depending on where it is ofcourse */
1508 MOVA (s); /* read s in case it was volatile */
1513 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1515 SNPRINTF (buffer, sizeof(buffer),
1517 aop->aopu.aop_dir, offset * 8);
1521 SNPRINTF (buffer, sizeof(buffer),
1523 aop->aopu.aop_dir, offset);
1527 SNPRINTF (buffer, sizeof(buffer),
1532 if (strcmp (buffer, s) || bvolatile)
1534 emitcode ("mov", "%s,%s", buffer, s);
1536 if (!strcmp (buffer, "acc"))
1543 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1547 strcmp (s, "r0") == 0 ||
1548 strcmp (s, "r1") == 0 ||
1549 strcmp (s, "r2") == 0 ||
1550 strcmp (s, "r3") == 0 ||
1551 strcmp (s, "r4") == 0 ||
1552 strcmp (s, "r5") == 0 ||
1553 strcmp (s, "r6") == 0 ||
1554 strcmp (s, "r7") == 0)
1556 emitcode ("mov", "%s,%s",
1557 aop->aopu.aop_reg[offset]->dname, s);
1561 emitcode ("mov", "%s,%s",
1562 aop->aopu.aop_reg[offset]->name, s);
1570 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571 "aopPut writing to code space");
1575 while (offset > aop->coff)
1578 emitcode ("inc", "dptr");
1581 while (offset < aop->coff)
1584 emitcode ("lcall", "__decdptr");
1589 /* if not in accumulator */
1592 emitcode ("movx", "@dptr,a");
1597 while (offset > aop->coff)
1600 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1602 while (offset < aop->coff)
1605 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1612 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1617 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1619 else if (strcmp (s, "r0") == 0 ||
1620 strcmp (s, "r1") == 0 ||
1621 strcmp (s, "r2") == 0 ||
1622 strcmp (s, "r3") == 0 ||
1623 strcmp (s, "r4") == 0 ||
1624 strcmp (s, "r5") == 0 ||
1625 strcmp (s, "r6") == 0 ||
1626 strcmp (s, "r7") == 0)
1629 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630 emitcode ("mov", "@%s,%s",
1631 aop->aopu.aop_ptr->name, buffer);
1635 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1640 if (strcmp (s, "a") == 0)
1641 emitcode ("push", "acc");
1645 emitcode ("push", "acc");
1647 emitcode ("push", s);
1653 /* if not bit variable */
1654 if (!aop->aopu.aop_dir)
1656 /* inefficient: move carry into A and use jz/jnz */
1657 emitcode ("clr", "a");
1658 emitcode ("rlc", "a");
1664 emitcode ("clr", "%s", aop->aopu.aop_dir);
1666 emitcode ("setb", "%s", aop->aopu.aop_dir);
1667 else if (!strcmp (s, "c"))
1668 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669 else if (strcmp (s, aop->aopu.aop_dir))
1672 /* set C, if a >= 1 */
1673 emitcode ("add", "a,#0xff");
1674 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1681 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1688 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1691 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1696 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697 "aopPut got unsupported aop->type");
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand */
1708 /*-----------------------------------------------------------------*/
1710 pointToEnd (asmop * aop)
1716 aop->coff = count = (aop->size - 1);
1722 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1726 emitcode ("inc", "dptr");
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should */
1735 /*-----------------------------------------------------------------*/
1737 reAdjustPreg (asmop * aop)
1739 if ((aop->coff==0) || (aop->size <= 1))
1747 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1752 emitcode ("lcall", "__decdptr");
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is */
1761 /* a generic pointer type. */
1762 /*-----------------------------------------------------------------*/
1764 opIsGptr (operand * op)
1766 sym_link *type = operandType (op);
1768 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size */
1777 /*-----------------------------------------------------------------*/
1779 getDataSize (operand * op)
1782 size = AOP_SIZE (op);
1783 if (size == GPTRSIZE)
1785 sym_link *type = operandType (op);
1786 if (IS_GENPTR (type))
1788 /* generic pointer; arithmetic operations
1789 * should ignore the high byte (pointer type).
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc */
1799 /*-----------------------------------------------------------------*/
1801 outAcc (operand * result)
1804 size = getDataSize (result);
1807 aopPut (result, "a", 0);
1810 /* unsigned or positive */
1813 aopPut (result, zero, offset++);
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C */
1820 /*-----------------------------------------------------------------*/
1822 outBitC (operand * result)
1824 /* if the result is bit */
1825 if (AOP_TYPE (result) == AOP_CRY)
1827 aopPut (result, "c", 0);
1831 emitcode ("clr", "a");
1832 emitcode ("rlc", "a");
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop) */
1839 /*-----------------------------------------------------------------*/
1841 toBoolean (operand * oper)
1843 int size = AOP_SIZE (oper) - 1;
1845 bool AccUsed = FALSE;
1848 while (!AccUsed && size--)
1850 AccUsed |= aopGetUsesAcc(oper, offset++);
1853 size = AOP_SIZE (oper) - 1;
1855 MOVA (aopGet (oper, 0, FALSE, FALSE));
1856 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1859 emitcode("mov", "b,a");
1862 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863 emitcode ("orl", "b,a");
1865 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866 emitcode ("orl", "a,b");
1873 emitcode ("orl", "a,%s",
1874 aopGet (oper, offset++, FALSE, FALSE));
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop */
1882 /*-------------------------------------------------------------------*/
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1888 if (aopGetUsesAcc (oper, offset))
1890 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset, bit16, dname));
1892 emitcode("xch", "a,b");
1893 aopPut (oper, "a", offset);
1894 emitcode("xch", "a,b");
1899 l = aopGet (oper, offset, bit16, dname);
1900 emitcode("xch", "a,%s", l);
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation */
1908 /*-----------------------------------------------------------------*/
1914 D (emitcode (";", "genNot"));
1916 /* assign asmOps to operand & result */
1917 aopOp (IC_LEFT (ic), ic, FALSE);
1918 aopOp (IC_RESULT (ic), ic, TRUE);
1920 /* if in bit space then a special case */
1921 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1923 /* if left==result then cpl bit */
1924 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1926 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1930 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931 emitcode ("cpl", "c");
1932 outBitC (IC_RESULT (ic));
1937 toBoolean (IC_LEFT (ic));
1939 /* set C, if a == 0 */
1940 tlbl = newiTempLabel (NULL);
1941 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1943 outBitC (IC_RESULT (ic));
1946 /* release the aops */
1947 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement */
1954 /*-----------------------------------------------------------------*/
1961 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1963 D(emitcode (";", "genCpl"));
1965 /* assign asmOps to operand & result */
1966 aopOp (IC_LEFT (ic), ic, FALSE);
1967 aopOp (IC_RESULT (ic), ic, TRUE);
1969 /* special case if in bit space */
1970 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1974 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1977 /* promotion rules are responsible for this strange result:
1978 bit -> int -> ~int -> bit
1979 uchar -> int -> ~int -> bit
1981 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1985 tlbl=newiTempLabel(NULL);
1986 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989 IS_AOP_PREG (IC_LEFT (ic)))
1991 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1996 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1999 outBitC (IC_RESULT(ic));
2003 size = AOP_SIZE (IC_RESULT (ic));
2006 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2008 emitcode ("cpl", "a");
2009 aopPut (IC_RESULT (ic), "a", offset++);
2014 /* release the aops */
2015 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2019 /*-----------------------------------------------------------------*/
2020 /* genUminusFloat - unary minus for floating points */
2021 /*-----------------------------------------------------------------*/
2023 genUminusFloat (operand * op, operand * result)
2025 int size, offset = 0;
2028 D (emitcode (";", "genUminusFloat"));
2030 /* for this we just copy and then flip the bit */
2032 size = AOP_SIZE (op) - 1;
2037 aopGet (op, offset, FALSE, FALSE),
2042 l = aopGet (op, offset, FALSE, FALSE);
2045 emitcode ("cpl", "acc.7");
2046 aopPut (result, "a", offset);
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation */
2051 /*-----------------------------------------------------------------*/
2053 genUminus (iCode * ic)
2058 D (emitcode (";", "genUminus"));
2061 aopOp (IC_LEFT (ic), ic, FALSE);
2062 aopOp (IC_RESULT (ic), ic, TRUE);
2064 /* if both in bit space then special
2066 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2070 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071 emitcode ("cpl", "c");
2072 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2076 optype = operandType (IC_LEFT (ic));
2078 /* if float then do float stuff */
2079 if (IS_FLOAT (optype))
2081 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2085 /* otherwise subtract from zero */
2086 size = AOP_SIZE (IC_LEFT (ic));
2090 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091 if (!strcmp (l, "a"))
2095 emitcode ("cpl", "a");
2096 emitcode ("addc", "a,#0");
2102 emitcode ("clr", "a");
2103 emitcode ("subb", "a,%s", l);
2105 aopPut (IC_RESULT (ic), "a", offset++);
2108 /* if any remaining bytes in the result */
2109 /* we just need to propagate the sign */
2110 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2112 emitcode ("rlc", "a");
2113 emitcode ("subb", "a,acc");
2115 aopPut (IC_RESULT (ic), "a", offset++);
2119 /* release the aops */
2120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers */
2126 /*-----------------------------------------------------------------*/
2128 saveRegisters (iCode * lic)
2135 for (ic = lic; ic; ic = ic->next)
2136 if (ic->op == CALL || ic->op == PCALL)
2141 fprintf (stderr, "found parameter push with no function call\n");
2145 /* if the registers have been saved already or don't need to be then
2149 if (IS_SYMOP(IC_LEFT(ic)) &&
2150 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2154 /* save the registers in use at this time but skip the
2155 ones for the result */
2156 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157 mcs51_rUmaskForOp (IC_RESULT(ic)));
2160 if (options.useXstack)
2162 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163 int nBits = bitVectnBitsOn (rsavebits);
2164 int count = bitVectnBitsOn (rsave);
2168 count = count - nBits + 1;
2169 /* remove all but the first bits as they are pushed all at once */
2170 rsave = bitVectCplAnd (rsave, rsavebits);
2171 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2176 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177 if (reg->type == REG_BIT)
2179 emitcode ("mov", "a,%s", reg->base);
2183 emitcode ("mov", "a,%s", reg->name);
2185 emitcode ("mov", "r0,%s", spname);
2186 emitcode ("inc", "%s", spname);// allocate before use
2187 emitcode ("movx", "@r0,a");
2188 if (bitVectBitValue (rsave, R0_IDX))
2189 emitcode ("mov", "r0,a");
2191 else if (count != 0)
2193 if (bitVectBitValue (rsave, R0_IDX))
2195 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2197 emitcode ("mov", "r0,%s", spname);
2199 emitcode ("add", "a,#%d", count);
2200 emitcode ("mov", "%s,a", spname);
2201 for (i = 0; i < mcs51_nRegs; i++)
2203 if (bitVectBitValue (rsave, i))
2205 regs * reg = REG_WITH_INDEX (i);
2208 emitcode ("pop", "acc");
2209 emitcode ("push", "acc");
2211 else if (reg->type == REG_BIT)
2213 emitcode ("mov", "a,%s", reg->base);
2217 emitcode ("mov", "a,%s", reg->name);
2219 emitcode ("movx", "@r0,a");
2222 emitcode ("inc", "r0");
2226 if (bitVectBitValue (rsave, R0_IDX))
2228 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2234 bool bits_pushed = FALSE;
2235 for (i = 0; i < mcs51_nRegs; i++)
2237 if (bitVectBitValue (rsave, i))
2239 bits_pushed = pushReg (i, bits_pushed);
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers */
2247 /*-----------------------------------------------------------------*/
2249 unsaveRegisters (iCode * ic)
2254 /* restore the registers in use at this time but skip the
2255 ones for the result */
2256 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257 mcs51_rUmaskForOp (IC_RESULT(ic)));
2259 if (options.useXstack)
2261 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262 int nBits = bitVectnBitsOn (rsavebits);
2263 int count = bitVectnBitsOn (rsave);
2267 count = count - nBits + 1;
2268 /* remove all but the first bits as they are popped all at once */
2269 rsave = bitVectCplAnd (rsave, rsavebits);
2270 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2275 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276 emitcode ("mov", "r0,%s", spname);
2277 emitcode ("dec", "r0");
2278 emitcode ("movx", "a,@r0");
2279 if (reg->type == REG_BIT)
2281 emitcode ("mov", "%s,a", reg->base);
2285 emitcode ("mov", "%s,a", reg->name);
2287 emitcode ("dec", "%s", spname);
2289 else if (count != 0)
2291 emitcode ("mov", "r0,%s", spname);
2292 for (i = mcs51_nRegs; i >= 0; i--)
2294 if (bitVectBitValue (rsave, i))
2296 regs * reg = REG_WITH_INDEX (i);
2297 emitcode ("dec", "r0");
2298 emitcode ("movx", "a,@r0");
2301 emitcode ("push", "acc");
2303 else if (reg->type == REG_BIT)
2305 emitcode ("mov", "%s,a", reg->base);
2309 emitcode ("mov", "%s,a", reg->name);
2313 emitcode ("mov", "%s,r0", spname);
2314 if (bitVectBitValue (rsave, R0_IDX))
2316 emitcode ("pop", "ar0");
2322 bool bits_popped = FALSE;
2323 for (i = mcs51_nRegs; i >= 0; i--)
2325 if (bitVectBitValue (rsave, i))
2327 bits_popped = popReg (i, bits_popped);
2334 /*-----------------------------------------------------------------*/
2336 /*-----------------------------------------------------------------*/
2338 pushSide (operand * oper, int size)
2343 char *l = aopGet (oper, offset++, FALSE, TRUE);
2344 if (AOP_TYPE (oper) != AOP_REG &&
2345 AOP_TYPE (oper) != AOP_DIR &&
2349 emitcode ("push", "acc");
2353 emitcode ("push", "%s", l);
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards */
2360 /*-----------------------------------------------------------------*/
2362 assignResultValue (operand * oper, operand * func)
2365 int size = AOP_SIZE (oper);
2366 bool accuse = FALSE;
2367 bool pushedA = FALSE;
2369 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2375 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2377 emitcode ("push", "acc");
2382 if ((offset == 3) && pushedA)
2383 emitcode ("pop", "acc");
2384 accuse |= aopPut (oper, fReturn[offset], offset);
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack */
2393 /*-----------------------------------------------------------------*/
2395 genXpush (iCode * ic)
2397 asmop *aop = newAsmop (0);
2399 int size, offset = 0;
2401 D (emitcode (";", "genXpush"));
2403 aopOp (IC_LEFT (ic), ic, FALSE);
2404 r = getFreePtr (ic, &aop, FALSE);
2406 size = AOP_SIZE (IC_LEFT (ic));
2410 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411 emitcode ("mov", "%s,%s", r->name, spname);
2412 emitcode ("inc", "%s", spname); // allocate space first
2413 emitcode ("movx", "@%s,a", r->name);
2417 // allocate space first
2418 emitcode ("mov", "%s,%s", r->name, spname);
2420 emitcode ("add", "a,#%d", size);
2421 emitcode ("mov", "%s,a", spname);
2425 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426 emitcode ("movx", "@%s,a", r->name);
2427 emitcode ("inc", "%s", r->name);
2431 freeAsmop (NULL, aop, ic, TRUE);
2432 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2439 genIpush (iCode * ic)
2441 int size, offset = 0;
2445 D (emitcode (";", "genIpush"));
2447 /* if this is not a parm push : ie. it is spill push
2448 and spill push is always done on the local stack */
2452 /* and the item is spilt then do nothing */
2453 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2456 aopOp (IC_LEFT (ic), ic, FALSE);
2457 size = AOP_SIZE (IC_LEFT (ic));
2458 /* push it on the stack */
2461 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2467 emitcode ("push", "%s", l);
2472 /* this is a parameter push: in this case we call
2473 the routine to find the call and save those
2474 registers that need to be saved */
2477 /* if use external stack then call the external
2478 stack pushing routine */
2479 if (options.useXstack)
2485 /* then do the push */
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2488 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489 size = AOP_SIZE (IC_LEFT (ic));
2493 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2497 if (strcmp (l, prev) || *l == '@')
2499 emitcode ("push", "acc");
2503 emitcode ("push", "%s", l);
2508 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling */
2513 /*-----------------------------------------------------------------*/
2515 genIpop (iCode * ic)
2519 D (emitcode (";", "genIpop"));
2521 /* if the temp was not pushed then */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2527 offset = (size - 1);
2530 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2534 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack */
2539 /*-----------------------------------------------------------------*/
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2544 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2548 if (options.useXstack)
2552 /* Assume r0 is available for use. */
2553 r = REG_WITH_INDEX (R0_IDX);;
2558 r = getFreePtr (ic, &aop, FALSE);
2560 // allocate space first
2561 emitcode ("mov", "%s,%s", r->name, spname);
2563 emitcode ("add", "a,#%d", count);
2564 emitcode ("mov", "%s,a", spname);
2567 for (i = 0; i < 8; i++)
2569 if (options.useXstack)
2571 emitcode ("mov", "a,(%s+%d)",
2572 regs8051[i].base, 8 * bank + regs8051[i].offset);
2573 emitcode ("movx", "@%s,a", r->name);
2575 emitcode ("inc", "%s", r->name);
2578 emitcode ("push", "(%s+%d)",
2579 regs8051[i].base, 8 * bank + regs8051[i].offset);
2582 if (mcs51_nRegs > 8)
2584 if (options.useXstack)
2586 emitcode ("mov", "a,bits");
2587 emitcode ("movx", "@%s,a", r->name);
2589 emitcode ("inc", "%s", r->name);
2593 emitcode ("push", "bits");
2600 if (options.useXstack)
2602 emitcode ("mov", "a,psw");
2603 emitcode ("movx", "@%s,a", r->name);
2607 emitcode ("push", "psw");
2610 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2615 freeAsmop (NULL, aop, ic, TRUE);
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack */
2626 /*-----------------------------------------------------------------*/
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2634 if (options.useXstack)
2638 /* Assume r0 is available for use. */
2639 r = REG_WITH_INDEX (R0_IDX);;
2644 r = getFreePtr (ic, &aop, FALSE);
2646 emitcode ("mov", "%s,%s", r->name, spname);
2651 if (options.useXstack)
2653 emitcode ("dec", "%s", r->name);
2654 emitcode ("movx", "a,@%s", r->name);
2655 emitcode ("mov", "psw,a");
2659 emitcode ("pop", "psw");
2663 if (mcs51_nRegs > 8)
2665 if (options.useXstack)
2667 emitcode ("dec", "%s", r->name);
2668 emitcode ("movx", "a,@%s", r->name);
2669 emitcode ("mov", "bits,a");
2673 emitcode ("pop", "bits");
2677 for (i = 7; i >= 0; i--)
2679 if (options.useXstack)
2681 emitcode ("dec", "%s", r->name);
2682 emitcode ("movx", "a,@%s", r->name);
2683 emitcode ("mov", "(%s+%d),a",
2684 regs8051[i].base, 8 * bank + regs8051[i].offset);
2688 emitcode ("pop", "(%s+%d)",
2689 regs8051[i].base, 8 * bank + regs8051[i].offset);
2693 if (options.useXstack)
2695 emitcode ("mov", "%s,%s", spname, r->name);
2700 freeAsmop (NULL, aop, ic, TRUE);
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2712 /* first we do all bit parameters */
2713 for (sic = setFirstItem (sendSet); sic;
2714 sic = setNextItem (sendSet))
2716 if (sic->argreg > 12)
2718 int bit = sic->argreg-13;
2720 aopOp (IC_LEFT (sic), sic, FALSE);
2722 /* if left is a literal then
2723 we know what the value is */
2724 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2726 if (((int) operandLitValue (IC_LEFT (sic))))
2727 emitcode ("setb", "b[%d]", bit);
2729 emitcode ("clr", "b[%d]", bit);
2731 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2733 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734 if (strcmp (l, "c"))
2735 emitcode ("mov", "c,%s", l);
2736 emitcode ("mov", "b[%d],c", bit);
2741 toBoolean (IC_LEFT (sic));
2742 /* set C, if a >= 1 */
2743 emitcode ("add", "a,#0xff");
2744 emitcode ("mov", "b[%d],c", bit);
2749 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2755 saveRegisters (setFirstItem (sendSet));
2756 emitcode ("mov", "bits,b");
2759 /* then we do all other parameters */
2760 for (sic = setFirstItem (sendSet); sic;
2761 sic = setNextItem (sendSet))
2763 if (sic->argreg <= 12)
2765 int size, offset = 0;
2766 aopOp (IC_LEFT (sic), sic, FALSE);
2767 size = AOP_SIZE (IC_LEFT (sic));
2769 if (sic->argreg == 1)
2773 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774 if (strcmp (l, fReturn[offset]))
2776 emitcode ("mov", "%s,%s", fReturn[offset], l);
2785 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2790 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank */
2797 /*-----------------------------------------------------------------*/
2799 selectRegBank (short bank, bool keepFlags)
2801 /* if f.e. result is in carry */
2804 emitcode ("anl", "psw,#0xE7");
2806 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2810 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement */
2816 /*-----------------------------------------------------------------*/
2818 genCall (iCode * ic)
2822 // bool restoreBank = FALSE;
2823 bool swapBanks = FALSE;
2824 bool accuse = FALSE;
2825 bool accPushed = FALSE;
2826 bool resultInF0 = FALSE;
2827 bool assignResultGenerated = FALSE;
2829 D (emitcode (";", "genCall"));
2831 dtype = operandType (IC_LEFT (ic));
2832 etype = getSpec(dtype);
2833 /* if send set is not empty then assign */
2836 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837 genSend(reverseSet(_G.sendSet));
2839 genSend(_G.sendSet);
2844 /* if we are calling a not _naked function that is not using
2845 the same register bank then we need to save the
2846 destination registers on the stack */
2847 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849 !IFFUNC_ISISR (dtype))
2854 /* if caller saves & we have not saved then */
2860 emitcode ("mov", "psw,#0x%02x",
2861 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2865 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2867 if (IFFUNC_CALLEESAVES(dtype))
2869 werror (E_BANKED_WITH_CALLEESAVES);
2873 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874 OP_SYMBOL (IC_LEFT (ic))->rname :
2875 OP_SYMBOL (IC_LEFT (ic))->name);
2877 emitcode ("mov", "r0,#%s", l);
2878 emitcode ("mov", "r1,#(%s >> 8)", l);
2879 emitcode ("mov", "r2,#(%s >> 16)", l);
2880 emitcode ("lcall", "__sdcc_banked_call");
2885 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886 OP_SYMBOL (IC_LEFT (ic))->rname :
2887 OP_SYMBOL (IC_LEFT (ic))->name));
2892 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2895 /* if we need assign a result value */
2896 if ((IS_ITEMP (IC_RESULT (ic)) &&
2897 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901 IS_TRUE_SYMOP (IC_RESULT (ic)))
2905 aopOp (IC_RESULT (ic), ic, FALSE);
2908 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909 assignResultGenerated = TRUE;
2911 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2914 /* adjust the stack for parameters if required */
2918 if (ic->parmBytes > 3)
2922 emitcode ("push", "acc");
2925 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927 !assignResultGenerated)
2929 emitcode ("mov", "F0,c");
2933 emitcode ("mov", "a,%s", spname);
2934 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935 emitcode ("mov", "%s,a", spname);
2937 /* unsaveRegisters from xstack needs acc, but */
2938 /* unsaveRegisters from stack needs this popped */
2939 if (accPushed && !options.useXstack)
2941 emitcode ("pop", "acc");
2946 for (i = 0; i < ic->parmBytes; i++)
2947 emitcode ("dec", "%s", spname);
2950 /* if we had saved some registers then unsave them */
2951 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2953 if (accuse && !accPushed && options.useXstack)
2955 /* xstack needs acc, but doesn't touch normal stack */
2956 emitcode ("push", "acc");
2959 unsaveRegisters (ic);
2962 // /* if register bank was saved then pop them */
2964 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2966 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2969 emitcode ("mov", "c,F0");
2971 aopOp (IC_RESULT (ic), ic, FALSE);
2972 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2977 emitcode ("pop", "acc");
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement */
2982 /*-----------------------------------------------------------------*/
2984 genPcall (iCode * ic)
2988 symbol *rlbl = newiTempLabel (NULL);
2989 // bool restoreBank=FALSE;
2990 bool swapBanks = FALSE;
2991 bool resultInF0 = FALSE;
2993 D (emitcode (";", "genPcall"));
2995 dtype = operandType (IC_LEFT (ic))->next;
2996 etype = getSpec(dtype);
2997 /* if caller saves & we have not saved then */
3001 /* if we are calling a not _naked function that is not using
3002 the same register bank then we need to save the
3003 destination registers on the stack */
3004 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006 !IFFUNC_ISISR (dtype))
3008 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 // restoreBank=TRUE;
3011 // need caution message to user here
3014 if (IS_LITERAL(etype))
3016 /* if send set is not empty then assign */
3019 genSend(reverseSet(_G.sendSet));
3025 emitcode ("mov", "psw,#0x%02x",
3026 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3029 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3031 if (IFFUNC_CALLEESAVES(dtype))
3033 werror (E_BANKED_WITH_CALLEESAVES);
3037 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3039 emitcode ("mov", "r0,#%s", l);
3040 emitcode ("mov", "r1,#(%s >> 8)", l);
3041 emitcode ("mov", "r2,#(%s >> 16)", l);
3042 emitcode ("lcall", "__sdcc_banked_call");
3047 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3052 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3054 if (IFFUNC_CALLEESAVES(dtype))
3056 werror (E_BANKED_WITH_CALLEESAVES);
3060 aopOp (IC_LEFT (ic), ic, FALSE);
3064 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3070 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3076 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3078 /* if send set is not empty then assign */
3081 genSend(reverseSet(_G.sendSet));
3087 emitcode ("mov", "psw,#0x%02x",
3088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3092 emitcode ("lcall", "__sdcc_banked_call");
3097 /* push the return address on to the stack */
3098 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099 emitcode ("push", "acc");
3100 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101 emitcode ("push", "acc");
3103 /* now push the calling address */
3104 aopOp (IC_LEFT (ic), ic, FALSE);
3106 pushSide (IC_LEFT (ic), FPTRSIZE);
3108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3110 /* if send set is not empty the assign */
3113 genSend(reverseSet(_G.sendSet));
3119 emitcode ("mov", "psw,#0x%02x",
3120 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3124 emitcode ("ret", "");
3130 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3133 /* if we need assign a result value */
3134 if ((IS_ITEMP (IC_RESULT (ic)) &&
3135 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138 IS_TRUE_SYMOP (IC_RESULT (ic)))
3142 aopOp (IC_RESULT (ic), ic, FALSE);
3145 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3147 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3150 /* adjust the stack for parameters if required */
3154 if (ic->parmBytes > 3)
3156 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3159 emitcode ("mov", "F0,c");
3163 emitcode ("mov", "a,%s", spname);
3164 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165 emitcode ("mov", "%s,a", spname);
3168 for (i = 0; i < ic->parmBytes; i++)
3169 emitcode ("dec", "%s", spname);
3172 // /* if register bank was saved then unsave them */
3174 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3176 /* if we had saved some registers then unsave them */
3177 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178 unsaveRegisters (ic);
3180 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3183 emitcode ("mov", "c,F0");
3185 aopOp (IC_RESULT (ic), ic, FALSE);
3186 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result is rematerializable */
3193 /*-----------------------------------------------------------------*/
3195 resultRemat (iCode * ic)
3197 if (SKIP_IC (ic) || ic->op == IFX)
3200 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3202 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203 if (sym->remat && !POINTER_SET (ic))
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3213 #define STRCASECMP strcasecmp
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list */
3218 /*-----------------------------------------------------------------*/
3220 regsCmp(void *p1, void *p2)
3222 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3226 inExcludeList (char *s)
3228 const char *p = setFirstItem(options.excludeRegsSet);
3230 if (p == NULL || STRCASECMP(p, "none") == 0)
3234 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry */
3239 /*-----------------------------------------------------------------*/
3241 genFunction (iCode * ic)
3243 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3245 bool switchedPSW = FALSE;
3246 int calleesaves_saved_register = -1;
3247 int stackAdjust = sym->stack;
3248 int accIsFree = sym->recvSize < 4;
3249 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3253 /* create the function header */
3254 emitcode (";", "-----------------------------------------");
3255 emitcode (";", " function %s", sym->name);
3256 emitcode (";", "-----------------------------------------");
3258 emitcode ("", "%s:", sym->rname);
3259 ftype = operandType (IC_LEFT (ic));
3260 _G.currentFunc = sym;
3262 if (IFFUNC_ISNAKED(ftype))
3264 emitcode(";", "naked function: no prologue.");
3268 /* here we need to generate the equates for the
3269 register bank if required */
3270 if (FUNC_REGBANK (ftype) != rbank)
3274 rbank = FUNC_REGBANK (ftype);
3275 for (i = 0; i < mcs51_nRegs; i++)
3277 if (regs8051[i].type != REG_BIT)
3279 if (strcmp (regs8051[i].base, "0") == 0)
3280 emitcode ("", "%s = 0x%02x",
3282 8 * rbank + regs8051[i].offset);
3284 emitcode ("", "%s = %s + 0x%02x",
3287 8 * rbank + regs8051[i].offset);
3292 /* if this is an interrupt service routine then
3293 save acc, b, dpl, dph */
3294 if (IFFUNC_ISISR (sym->type))
3296 if (!inExcludeList ("acc"))
3297 emitcode ("push", "acc");
3298 if (!inExcludeList ("b"))
3299 emitcode ("push", "b");
3300 if (!inExcludeList ("dpl"))
3301 emitcode ("push", "dpl");
3302 if (!inExcludeList ("dph"))
3303 emitcode ("push", "dph");
3304 /* if this isr has no bank i.e. is going to
3305 run with bank 0 , then we need to save more
3307 if (!FUNC_REGBANK (sym->type))
3311 /* if this function does not call any other
3312 function then we can be economical and
3313 save only those registers that are used */
3314 if (!IFFUNC_HASFCALL(sym->type))
3316 /* if any registers used */
3319 bool bits_pushed = FALSE;
3320 /* save the registers used */
3321 for (i = 0; i < sym->regsUsed->size; i++)
3323 if (bitVectBitValue (sym->regsUsed, i))
3324 bits_pushed = pushReg (i, bits_pushed);
3330 /* this function has a function call. We cannot
3331 determine register usage so we will have to push the
3333 saveRBank (0, ic, FALSE);
3334 if (options.parms_in_bank1) {
3335 for (i=0; i < 8 ; i++ ) {
3336 emitcode ("push","%s",rb1regs[i]);
3343 /* This ISR uses a non-zero bank.
3345 * We assume that the bank is available for our
3348 * However, if this ISR calls a function which uses some
3349 * other bank, we must save that bank entirely.
3351 unsigned long banksToSave = 0;
3353 if (IFFUNC_HASFCALL(sym->type))
3356 #define MAX_REGISTER_BANKS 4
3361 for (i = ic; i; i = i->next)
3363 if (i->op == ENDFUNCTION)
3365 /* we got to the end OK. */
3373 dtype = operandType (IC_LEFT(i));
3375 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3377 /* Mark this bank for saving. */
3378 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3380 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3384 banksToSave |= (1 << FUNC_REGBANK(dtype));
3387 /* And note that we don't need to do it in
3395 /* This is a mess; we have no idea what
3396 * register bank the called function might
3399 * The only thing I can think of to do is
3400 * throw a warning and hope.
3402 werror(W_FUNCPTR_IN_USING_ISR);
3406 if (banksToSave && options.useXstack)
3408 /* Since we aren't passing it an ic,
3409 * saveRBank will assume r0 is available to abuse.
3411 * So switch to our (trashable) bank now, so
3412 * the caller's R0 isn't trashed.
3414 emitcode ("push", "psw");
3415 emitcode ("mov", "psw,#0x%02x",
3416 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3420 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3422 if (banksToSave & (1 << ix))
3424 saveRBank(ix, NULL, FALSE);
3428 // TODO: this needs a closer look
3429 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3432 /* Set the register bank to the desired value if nothing else */
3433 /* has done so yet. */
3436 emitcode ("push", "psw");
3437 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3442 /* This is a non-ISR function. The caller has already switched register */
3443 /* banks, if necessary, so just handle the callee-saves option. */
3445 /* if callee-save to be used for this function
3446 then save the registers being used in this function */
3447 if (IFFUNC_CALLEESAVES(sym->type))
3451 /* if any registers used */
3454 bool bits_pushed = FALSE;
3455 /* save the registers used */
3456 for (i = 0; i < sym->regsUsed->size; i++)
3458 if (bitVectBitValue (sym->regsUsed, i))
3460 /* remember one saved register for later usage */
3461 if (calleesaves_saved_register < 0)
3462 calleesaves_saved_register = i;
3463 bits_pushed = pushReg (i, bits_pushed);
3473 if (options.useXstack)
3475 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3477 emitcode ("mov", "r0,%s", spname);
3478 emitcode ("inc", "%s", spname);
3479 emitcode ("xch", "a,_bpx");
3480 emitcode ("movx", "@r0,a");
3481 emitcode ("inc", "r0");
3482 emitcode ("mov", "a,r0");
3483 emitcode ("xch", "a,_bpx");
3487 emitcode ("push", "_bp"); /* save the callers stack */
3488 emitcode ("mov", "_bp,sp");
3493 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3495 /* set up the stack */
3496 emitcode ("push", "_bp"); /* save the callers stack */
3497 emitcode ("mov", "_bp,sp");
3502 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3503 /* before setting up the stack frame completely. */
3504 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3506 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3510 if (rsym && rsym->regType == REG_CND)
3512 if (rsym && (rsym->accuse || rsym->ruonly))
3514 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3515 rsym = rsym->usl.spillLoc;
3518 /* If the RECEIVE operand immediately spills to the first entry on the */
3519 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3520 /* rather than the usual @r0/r1 machinations. */
3521 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3525 _G.current_iCode = ric;
3526 D(emitcode ("; genReceive",""));
3527 for (ofs=0; ofs < sym->recvSize; ofs++)
3529 if (!strcmp (fReturn[ofs], "a"))
3530 emitcode ("push", "acc");
3532 emitcode ("push", fReturn[ofs]);
3534 stackAdjust -= sym->recvSize;
3537 assert (stackAdjust>=0);
3540 _G.current_iCode = ic;
3544 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3545 /* to free up the accumulator. */
3546 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3550 _G.current_iCode = ric;
3551 D(emitcode ("; genReceive",""));
3552 for (ofs=0; ofs < sym->recvSize; ofs++)
3554 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3556 _G.current_iCode = ic;
3562 /* adjust the stack for the function */
3565 int i = stackAdjust;
3567 werror (W_STACK_OVERFLOW, sym->name);
3569 if (i > 3 && accIsFree)
3571 emitcode ("mov", "a,sp");
3572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3573 emitcode ("mov", "sp,a");
3577 /* The accumulator is not free, so we will need another register */
3578 /* to clobber. No need to worry about a possible conflict with */
3579 /* the above early RECEIVE optimizations since they would have */
3580 /* freed the accumulator if they were generated. */
3582 if (IFFUNC_CALLEESAVES(sym->type))
3584 /* if it's a callee-saves function we need a saved register */
3585 if (calleesaves_saved_register >= 0)
3587 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3588 emitcode ("mov", "a,sp");
3589 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3590 emitcode ("mov", "sp,a");
3591 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3594 /* do it the hard way */
3596 emitcode ("inc", "sp");
3600 /* not callee-saves, we can clobber r0 */
3601 emitcode ("mov", "r0,a");
3602 emitcode ("mov", "a,sp");
3603 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604 emitcode ("mov", "sp,a");
3605 emitcode ("mov", "a,r0");
3610 emitcode ("inc", "sp");
3615 char i = ((char) sym->xstack & 0xff);
3617 if (i > 3 && accIsFree)
3619 emitcode ("mov", "a,_spx");
3620 emitcode ("add", "a,#0x%02x", i);
3621 emitcode ("mov", "_spx,a");
3625 emitcode ("push", "acc");
3626 emitcode ("mov", "a,_spx");
3627 emitcode ("add", "a,#0x%02x", i);
3628 emitcode ("mov", "_spx,a");
3629 emitcode ("pop", "acc");
3634 emitcode ("inc", "_spx");
3638 /* if critical function then turn interrupts off */
3639 if (IFFUNC_ISCRITICAL (ftype))
3641 symbol *tlbl = newiTempLabel (NULL);
3642 emitcode ("setb", "c");
3643 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3644 emitcode ("clr", "c");
3646 emitcode ("push", "psw"); /* save old ea via c in psw */
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions */
3652 /*-----------------------------------------------------------------*/
3654 genEndFunction (iCode * ic)
3656 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3657 lineNode *lnp = lineCurr;
3659 bitVect *regsUsedPrologue;
3660 bitVect *regsUnneeded;
3663 _G.currentFunc = NULL;
3664 if (IFFUNC_ISNAKED(sym->type))
3666 emitcode(";", "naked function: no epilogue.");
3667 if (options.debug && currFunc)
3668 debugFile->writeEndFunction (currFunc, ic, 0);
3672 if (IFFUNC_ISCRITICAL (sym->type))
3674 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3676 emitcode ("rlc", "a"); /* save c in a */
3677 emitcode ("pop", "psw"); /* restore ea via c in psw */
3678 emitcode ("mov", "ea,c");
3679 emitcode ("rrc", "a"); /* restore c from a */
3683 emitcode ("pop", "psw"); /* restore ea via c in psw */
3684 emitcode ("mov", "ea,c");
3688 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3690 if (options.useXstack)
3694 emitcode ("mov", "sp,_bp");
3695 emitcode ("pop", "_bp");
3697 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3699 emitcode ("xch", "a,_bpx");
3700 emitcode ("mov", "r0,a");
3701 emitcode ("dec", "r0");
3702 emitcode ("movx", "a,@r0");
3703 emitcode ("xch", "a,_bpx");
3704 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3707 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3710 emitcode ("mov", "sp,_bp");
3711 emitcode ("pop", "_bp");
3715 /* restore the register bank */
3716 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3718 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3719 || !options.useXstack)
3721 /* Special case of ISR using non-zero bank with useXstack
3724 emitcode ("pop", "psw");
3728 if (IFFUNC_ISISR (sym->type))
3731 /* now we need to restore the registers */
3732 /* if this isr has no bank i.e. is going to
3733 run with bank 0 , then we need to save more
3735 if (!FUNC_REGBANK (sym->type))
3738 /* if this function does not call any other
3739 function then we can be economical and
3740 save only those registers that are used */
3741 if (!IFFUNC_HASFCALL(sym->type))
3743 /* if any registers used */
3746 bool bits_popped = FALSE;
3747 /* save the registers used */
3748 for (i = sym->regsUsed->size; i >= 0; i--)
3750 if (bitVectBitValue (sym->regsUsed, i))
3751 bits_popped = popReg (i, bits_popped);
3757 if (options.parms_in_bank1) {
3758 for (i = 7 ; i >= 0 ; i-- ) {
3759 emitcode ("pop","%s",rb1regs[i]);
3762 /* this function has a function call cannot
3763 determines register usage so we will have to pop the
3765 unsaveRBank (0, ic, FALSE);
3770 /* This ISR uses a non-zero bank.
3772 * Restore any register banks saved by genFunction
3775 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3778 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3780 if (savedBanks & (1 << ix))
3782 unsaveRBank(ix, NULL, FALSE);
3786 if (options.useXstack)
3788 /* Restore bank AFTER calling unsaveRBank,
3789 * since it can trash r0.
3791 emitcode ("pop", "psw");
3795 if (!inExcludeList ("dph"))
3796 emitcode ("pop", "dph");
3797 if (!inExcludeList ("dpl"))
3798 emitcode ("pop", "dpl");
3799 if (!inExcludeList ("b"))
3800 emitcode ("pop", "b");
3801 if (!inExcludeList ("acc"))
3802 emitcode ("pop", "acc");
3804 /* if debug then send end of function */
3805 if (options.debug && currFunc)
3807 debugFile->writeEndFunction (currFunc, ic, 1);
3810 emitcode ("reti", "");
3814 if (IFFUNC_CALLEESAVES(sym->type))
3818 /* if any registers used */
3821 /* save the registers used */
3822 for (i = sym->regsUsed->size; i >= 0; i--)
3824 if (bitVectBitValue (sym->regsUsed, i) ||
3825 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3826 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3829 else if (mcs51_ptrRegReq)
3831 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3832 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3837 /* if debug then send end of function */
3838 if (options.debug && currFunc)
3840 debugFile->writeEndFunction (currFunc, ic, 1);
3843 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3845 emitcode ("ljmp", "__sdcc_banked_ret");
3849 emitcode ("ret", "");
3853 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3856 /* If this was an interrupt handler using bank 0 that called another */
3857 /* function, then all registers must be saved; nothing to optimized. */
3858 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3859 && !FUNC_REGBANK(sym->type))
3862 /* There are no push/pops to optimize if not callee-saves or ISR */
3863 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3866 /* If there were stack parameters, we cannot optimize without also */
3867 /* fixing all of the stack offsets; this is too dificult to consider. */
3868 if (FUNC_HASSTACKPARM(sym->type))
3871 /* Compute the registers actually used */
3872 regsUsed = newBitVect (mcs51_nRegs);
3873 regsUsedPrologue = newBitVect (mcs51_nRegs);
3876 if (lnp->ic && lnp->ic->op == FUNCTION)
3877 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3879 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3881 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3882 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3889 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3890 && !bitVectBitValue (regsUsed, CND_IDX))
3892 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3893 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3894 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3895 bitVectUnSetBit (regsUsed, CND_IDX);
3898 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3900 /* If this was an interrupt handler that called another function */
3901 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3902 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3904 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3905 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3906 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3907 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3908 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3911 /* Remove the unneeded push/pops */
3912 regsUnneeded = newBitVect (mcs51_nRegs);
3915 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3917 if (!strncmp(lnp->line, "push", 4))
3919 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3920 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3922 connectLine (lnp->prev, lnp->next);
3923 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3926 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3928 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3929 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3931 connectLine (lnp->prev, lnp->next);
3932 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3939 for (idx = 0; idx < regsUnneeded->size; idx++)
3940 if (bitVectBitValue (regsUnneeded, idx))
3941 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3943 freeBitVect (regsUnneeded);
3944 freeBitVect (regsUsed);
3945 freeBitVect (regsUsedPrologue);
3948 /*-----------------------------------------------------------------*/
3949 /* genRet - generate code for return statement */
3950 /*-----------------------------------------------------------------*/
3954 int size, offset = 0, pushed = 0;
3956 D (emitcode (";", "genRet"));
3958 /* if we have no return value then
3959 just generate the "ret" */
3963 /* we have something to return then
3964 move the return value into place */
3965 aopOp (IC_LEFT (ic), ic, FALSE);
3966 size = AOP_SIZE (IC_LEFT (ic));
3968 if (IS_BIT(_G.currentFunc->etype))
3970 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3977 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3980 l = aopGet (IC_LEFT (ic), offset++,
3982 emitcode ("push", "%s", l);
3987 l = aopGet (IC_LEFT (ic), offset,
3989 if (strcmp (fReturn[offset], l))
3990 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3997 if (strcmp (fReturn[pushed], "a"))
3998 emitcode ("pop", fReturn[pushed]);
4000 emitcode ("pop", "acc");
4002 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4005 /* generate a jump to the return label
4006 if the next is not the return statement */
4007 if (!(ic->next && ic->next->op == LABEL &&
4008 IC_LABEL (ic->next) == returnLabel))
4010 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4014 /*-----------------------------------------------------------------*/
4015 /* genLabel - generates a label */
4016 /*-----------------------------------------------------------------*/
4018 genLabel (iCode * ic)
4020 /* special case never generate */
4021 if (IC_LABEL (ic) == entryLabel)
4024 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4027 /*-----------------------------------------------------------------*/
4028 /* genGoto - generates a ljmp */
4029 /*-----------------------------------------------------------------*/
4031 genGoto (iCode * ic)
4033 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4036 /*-----------------------------------------------------------------*/
4037 /* findLabelBackwards: walks back through the iCode chain looking */
4038 /* for the given label. Returns number of iCode instructions */
4039 /* between that label and given ic. */
4040 /* Returns zero if label not found. */
4041 /*-----------------------------------------------------------------*/
4043 findLabelBackwards (iCode * ic, int key)
4052 /* If we have any pushes or pops, we cannot predict the distance.
4053 I don't like this at all, this should be dealt with in the
4055 if (ic->op == IPUSH || ic->op == IPOP) {
4059 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4068 /*-----------------------------------------------------------------*/
4069 /* genPlusIncr :- does addition with increment if possible */
4070 /*-----------------------------------------------------------------*/
4072 genPlusIncr (iCode * ic)
4074 unsigned int icount;
4075 unsigned int size = getDataSize (IC_RESULT (ic));
4077 /* will try to generate an increment */
4078 /* if the right side is not a literal
4080 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4083 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4085 D(emitcode ("; genPlusIncr",""));
4087 /* if increment >=16 bits in register or direct space */
4088 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4089 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4090 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4098 /* If the next instruction is a goto and the goto target
4099 * is < 10 instructions previous to this, we can generate
4100 * jumps straight to that target.
4102 if (ic->next && ic->next->op == GOTO
4103 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4104 && labelRange <= 10)
4106 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4107 tlbl = IC_LABEL (ic->next);
4112 tlbl = newiTempLabel (NULL);
4115 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4116 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4117 IS_AOP_PREG (IC_RESULT (ic)))
4118 emitcode ("cjne", "%s,#0x00,%05d$",
4119 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4123 emitcode ("clr", "a");
4124 emitcode ("cjne", "a,%s,%05d$",
4125 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4129 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4133 IS_AOP_PREG (IC_RESULT (ic)))
4134 emitcode ("cjne", "%s,#0x00,%05d$",
4135 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4138 emitcode ("cjne", "a,%s,%05d$",
4139 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4142 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4146 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4147 IS_AOP_PREG (IC_RESULT (ic)))
4148 emitcode ("cjne", "%s,#0x00,%05d$",
4149 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4153 emitcode ("cjne", "a,%s,%05d$",
4154 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4157 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4167 /* if result is dptr */
4168 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4169 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4170 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4171 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4173 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4179 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4182 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4183 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4185 emitcode ("inc", "dptr");
4190 /* if the literal value of the right hand side
4191 is greater than 4 then it is not worth it */
4195 /* if the sizes are greater than 1 then we cannot */
4196 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4197 AOP_SIZE (IC_LEFT (ic)) > 1)
4200 /* we can if the aops of the left & result match or
4201 if they are in registers and the registers are the
4203 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4207 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4208 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4209 aopPut (IC_RESULT (ic), "a", 0);
4215 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4225 /*-----------------------------------------------------------------*/
4226 /* outBitAcc - output a bit in acc */
4227 /*-----------------------------------------------------------------*/
4229 outBitAcc (operand * result)
4231 symbol *tlbl = newiTempLabel (NULL);
4232 /* if the result is a bit */
4233 if (AOP_TYPE (result) == AOP_CRY)
4235 aopPut (result, "a", 0);
4239 emitcode ("jz", "%05d$", tlbl->key + 100);
4240 emitcode ("mov", "a,%s", one);
4246 /*-----------------------------------------------------------------*/
4247 /* genPlusBits - generates code for addition of two bits */
4248 /*-----------------------------------------------------------------*/
4250 genPlusBits (iCode * ic)
4252 D (emitcode (";", "genPlusBits"));
4254 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4256 symbol *lbl = newiTempLabel (NULL);
4257 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4258 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4259 emitcode ("cpl", "c");
4261 outBitC (IC_RESULT (ic));
4265 emitcode ("clr", "a");
4266 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267 emitcode ("rlc", "a");
4268 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4269 emitcode ("addc", "a,%s", zero);
4270 outAcc (IC_RESULT (ic));
4275 /* This is the original version of this code.
4277 * This is being kept around for reference,
4278 * because I am not entirely sure I got it right...
4281 adjustArithmeticResult (iCode * ic)
4283 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4284 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4285 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4286 aopPut (IC_RESULT (ic),
4287 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4290 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4291 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4292 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4293 aopPut (IC_RESULT (ic),
4294 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4297 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4298 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4299 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4300 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4301 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4304 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4305 aopPut (IC_RESULT (ic), buffer, 2);
4309 /* This is the pure and virtuous version of this code.
4310 * I'm pretty certain it's right, but not enough to toss the old
4314 adjustArithmeticResult (iCode * ic)
4316 if (opIsGptr (IC_RESULT (ic)) &&
4317 opIsGptr (IC_LEFT (ic)) &&
4318 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4320 aopPut (IC_RESULT (ic),
4321 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4325 if (opIsGptr (IC_RESULT (ic)) &&
4326 opIsGptr (IC_RIGHT (ic)) &&
4327 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4329 aopPut (IC_RESULT (ic),
4330 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4334 if (opIsGptr (IC_RESULT (ic)) &&
4335 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4336 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4337 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4338 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4341 SNPRINTF (buffer, sizeof(buffer),
4342 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4343 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4348 /*-----------------------------------------------------------------*/
4349 /* genPlus - generates code for addition */
4350 /*-----------------------------------------------------------------*/
4352 genPlus (iCode * ic)
4354 int size, offset = 0;
4357 bool swappedLR = FALSE;
4358 operand *leftOp, *rightOp;
4361 D (emitcode (";", "genPlus"));
4363 /* special cases :- */
4365 aopOp (IC_LEFT (ic), ic, FALSE);
4366 aopOp (IC_RIGHT (ic), ic, FALSE);
4367 aopOp (IC_RESULT (ic), ic, TRUE);
4369 /* if literal, literal on the right or
4370 if left requires ACC or right is already
4372 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4373 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4374 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4376 operand *t = IC_RIGHT (ic);
4377 IC_RIGHT (ic) = IC_LEFT (ic);
4382 /* if both left & right are in bit
4384 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4385 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4391 /* if left in bit space & right literal */
4392 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4393 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4395 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396 /* if result in bit space */
4397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4399 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4400 emitcode ("cpl", "c");
4401 outBitC (IC_RESULT (ic));
4405 size = getDataSize (IC_RESULT (ic));
4408 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4409 emitcode ("addc", "a,%s", zero);
4410 aopPut (IC_RESULT (ic), "a", offset++);
4416 /* if I can do an increment instead
4417 of add then GOOD for ME */
4418 if (genPlusIncr (ic) == TRUE)
4421 size = getDataSize (IC_RESULT (ic));
4422 leftOp = IC_LEFT(ic);
4423 rightOp = IC_RIGHT(ic);
4426 /* if this is an add for an array access
4427 at a 256 byte boundary */
4429 && AOP_TYPE (op) == AOP_IMMD
4431 && IS_SPEC (OP_SYM_ETYPE (op))
4432 && SPEC_ABSA (OP_SYM_ETYPE (op))
4433 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4436 D(emitcode ("; genPlus aligned array",""));
4437 aopPut (IC_RESULT (ic),
4438 aopGet (rightOp, 0, FALSE, FALSE),
4441 if( 1 == getDataSize (IC_RIGHT (ic)) )
4443 aopPut (IC_RESULT (ic),
4444 aopGet (leftOp, 1, FALSE, FALSE),
4449 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4450 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4451 aopPut (IC_RESULT (ic), "a", 1);
4456 /* if the lower bytes of a literal are zero skip the addition */
4457 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4459 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4460 (skip_bytes+1 < size))
4465 D(emitcode ("; genPlus shortcut",""));
4470 if( offset >= skip_bytes )
4472 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4475 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4477 emitcode("xch", "a,b");
4478 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4479 emitcode (add, "a,b");
4482 else if (aopGetUsesAcc (leftOp, offset))
4484 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4485 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4489 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4492 aopPut (IC_RESULT (ic), "a", offset);
4493 add = "addc"; /* further adds must propagate carry */
4497 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4498 isOperandVolatile (IC_RESULT (ic), FALSE))
4501 aopPut (IC_RESULT (ic),
4502 aopGet (leftOp, offset, FALSE, FALSE),
4509 adjustArithmeticResult (ic);
4512 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4515 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525 /*-----------------------------------------------------------------*/
4526 /* genMinusDec :- does subtraction with decrement if possible */
4527 /*-----------------------------------------------------------------*/
4529 genMinusDec (iCode * ic)
4531 unsigned int icount;
4532 unsigned int size = getDataSize (IC_RESULT (ic));
4534 /* will try to generate an increment */
4535 /* if the right side is not a literal
4537 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4540 /* if the literal value of the right hand side
4541 is greater than 4 then it is not worth it */
4542 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4545 D (emitcode (";", "genMinusDec"));
4547 /* if decrement >=16 bits in register or direct space */
4548 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4549 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4557 /* If the next instruction is a goto and the goto target
4558 * is <= 10 instructions previous to this, we can generate
4559 * jumps straight to that target.
4561 if (ic->next && ic->next->op == GOTO
4562 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4563 && labelRange <= 10)
4565 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4566 tlbl = IC_LABEL (ic->next);
4571 tlbl = newiTempLabel (NULL);
4575 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4576 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4577 IS_AOP_PREG (IC_RESULT (ic)))
4578 emitcode ("cjne", "%s,#0xff,%05d$"
4579 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4583 emitcode ("mov", "a,#0xff");
4584 emitcode ("cjne", "a,%s,%05d$"
4585 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4588 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4591 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4592 IS_AOP_PREG (IC_RESULT (ic)))
4593 emitcode ("cjne", "%s,#0xff,%05d$"
4594 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4598 emitcode ("cjne", "a,%s,%05d$"
4599 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4602 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4606 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4607 IS_AOP_PREG (IC_RESULT (ic)))
4608 emitcode ("cjne", "%s,#0xff,%05d$"
4609 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4613 emitcode ("cjne", "a,%s,%05d$"
4614 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4617 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4626 /* if the sizes are greater than 1 then we cannot */
4627 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4628 AOP_SIZE (IC_LEFT (ic)) > 1)
4631 /* we can if the aops of the left & result match or
4632 if they are in registers and the registers are the
4634 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4638 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4640 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4645 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4650 emitcode ("dec", "%s", l);
4653 if (AOP_NEEDSACC (IC_RESULT (ic)))
4654 aopPut (IC_RESULT (ic), "a", 0);
4662 /*-----------------------------------------------------------------*/
4663 /* addSign - complete with sign */
4664 /*-----------------------------------------------------------------*/
4666 addSign (operand * result, int offset, int sign)
4668 int size = (getDataSize (result) - offset);
4673 emitcode ("rlc", "a");
4674 emitcode ("subb", "a,acc");
4677 aopPut (result, "a", offset++);
4684 aopPut (result, zero, offset++);
4690 /*-----------------------------------------------------------------*/
4691 /* genMinusBits - generates code for subtraction of two bits */
4692 /*-----------------------------------------------------------------*/
4694 genMinusBits (iCode * ic)
4696 symbol *lbl = newiTempLabel (NULL);
4698 D (emitcode (";", "genMinusBits"));
4700 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4702 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4703 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4704 emitcode ("cpl", "c");
4706 outBitC (IC_RESULT (ic));
4710 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4711 emitcode ("subb", "a,acc");
4712 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4713 emitcode ("inc", "a");
4715 aopPut (IC_RESULT (ic), "a", 0);
4716 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4720 /*-----------------------------------------------------------------*/
4721 /* genMinus - generates code for subtraction */
4722 /*-----------------------------------------------------------------*/
4724 genMinus (iCode * ic)
4726 int size, offset = 0;
4728 D (emitcode (";", "genMinus"));
4730 aopOp (IC_LEFT (ic), ic, FALSE);
4731 aopOp (IC_RIGHT (ic), ic, FALSE);
4732 aopOp (IC_RESULT (ic), ic, TRUE);
4734 /* special cases :- */
4735 /* if both left & right are in bit space */
4736 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4743 /* if I can do an decrement instead
4744 of subtract then GOOD for ME */
4745 if (genMinusDec (ic) == TRUE)
4748 size = getDataSize (IC_RESULT (ic));
4750 /* if literal, add a,#-lit, else normal subb */
4751 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4753 unsigned long lit = 0L;
4754 bool useCarry = FALSE;
4756 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4761 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4763 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4764 if (!offset && !size && lit== (unsigned long) -1)
4766 emitcode ("dec", "a");
4770 /* first add without previous c */
4771 emitcode ("add", "a,#0x%02x",
4772 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4777 emitcode ("addc", "a,#0x%02x",
4778 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4780 aopPut (IC_RESULT (ic), "a", offset++);
4784 /* no need to add zeroes */
4785 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4787 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4796 operand *leftOp, *rightOp;
4798 leftOp = IC_LEFT(ic);
4799 rightOp = IC_RIGHT(ic);
4803 if (aopGetUsesAcc(rightOp, offset)) {
4804 if (aopGetUsesAcc(leftOp, offset)) {
4807 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4809 emitcode ("mov", "b,a");
4812 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4813 emitcode ("subb", "a,b");
4816 /* reverse subtraction with 2's complement */
4818 emitcode( "setb", "c");
4820 emitcode( "cpl", "c");
4821 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4822 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4823 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4824 emitcode("cpl", "a");
4825 if (size) /* skip if last byte */
4826 emitcode( "cpl", "c");
4829 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4832 emitcode ("subb", "a,%s",
4833 aopGet(rightOp, offset, FALSE, TRUE));
4836 aopPut (IC_RESULT (ic), "a", offset++);
4840 adjustArithmeticResult (ic);
4843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4844 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 /*-----------------------------------------------------------------*/
4850 /* genMultbits :- multiplication of bits */
4851 /*-----------------------------------------------------------------*/
4853 genMultbits (operand * left,
4857 D (emitcode (";", "genMultbits"));
4859 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4860 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4864 /*-----------------------------------------------------------------*/
4865 /* genMultOneByte : 8*8=8/16 bit multiplication */
4866 /*-----------------------------------------------------------------*/
4868 genMultOneByte (operand * left,
4873 int size = AOP_SIZE (result);
4874 bool runtimeSign, compiletimeSign;
4875 bool lUnsigned, rUnsigned, pushedB;
4877 D (emitcode (";", "genMultOneByte"));
4879 if (size < 1 || size > 2)
4881 /* this should never happen */
4882 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4883 AOP_SIZE(result), __FILE__, lineno);
4887 /* (if two literals: the value is computed before) */
4888 /* if one literal, literal on the right */
4889 if (AOP_TYPE (left) == AOP_LIT)
4894 /* emitcode (";", "swapped left and right"); */
4896 /* if no literal, unsigned on the right: shorter code */
4897 if ( AOP_TYPE (right) != AOP_LIT
4898 && SPEC_USIGN (getSpec (operandType (left))))
4905 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4906 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4910 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4911 no need to take care about the signedness! */
4912 || (lUnsigned && rUnsigned))
4914 /* just an unsigned 8 * 8 = 8 multiply
4916 /* emitcode (";","unsigned"); */
4917 /* TODO: check for accumulator clash between left & right aops? */
4919 if (AOP_TYPE (right) == AOP_LIT)
4921 /* moving to accumulator first helps peepholes */
4922 MOVA (aopGet (left, 0, FALSE, FALSE));
4923 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4927 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4928 MOVA (aopGet (left, 0, FALSE, FALSE));
4931 emitcode ("mul", "ab");
4932 aopPut (result, "a", 0);
4934 aopPut (result, "b", 1);
4940 /* we have to do a signed multiply */
4941 /* emitcode (";", "signed"); */
4943 /* now sign adjust for both left & right */
4945 /* let's see what's needed: */
4946 /* apply negative sign during runtime */
4947 runtimeSign = FALSE;
4948 /* negative sign from literals */
4949 compiletimeSign = FALSE;
4953 if (AOP_TYPE(left) == AOP_LIT)
4955 /* signed literal */
4956 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4958 compiletimeSign = TRUE;
4961 /* signed but not literal */
4967 if (AOP_TYPE(right) == AOP_LIT)
4969 /* signed literal */
4970 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4972 compiletimeSign ^= TRUE;
4975 /* signed but not literal */
4979 /* initialize F0, which stores the runtime sign */
4982 if (compiletimeSign)
4983 emitcode ("setb", "F0"); /* set sign flag */
4985 emitcode ("clr", "F0"); /* reset sign flag */
4988 /* save the signs of the operands */
4989 if (AOP_TYPE(right) == AOP_LIT)
4991 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4993 if (!rUnsigned && val < 0)
4994 emitcode ("mov", "b,#0x%02x", -val);
4996 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4998 else /* ! literal */
5000 if (rUnsigned) /* emitcode (";", "signed"); */
5001 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5004 MOVA (aopGet (right, 0, FALSE, FALSE));
5005 lbl = newiTempLabel (NULL);
5006 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5007 emitcode ("cpl", "F0"); /* complement sign flag */
5008 emitcode ("cpl", "a"); /* 2's complement */
5009 emitcode ("inc", "a");
5011 emitcode ("mov", "b,a");
5015 if (AOP_TYPE(left) == AOP_LIT)
5017 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5019 if (!lUnsigned && val < 0)
5020 emitcode ("mov", "a,#0x%02x", -val);
5022 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5024 else /* ! literal */
5026 MOVA (aopGet (left, 0, FALSE, FALSE));
5030 lbl = newiTempLabel (NULL);
5031 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032 emitcode ("cpl", "F0"); /* complement sign flag */
5033 emitcode ("cpl", "a"); /* 2's complement */
5034 emitcode ("inc", "a");
5039 /* now the multiplication */
5040 emitcode ("mul", "ab");
5041 if (runtimeSign || compiletimeSign)
5043 lbl = newiTempLabel (NULL);
5045 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5046 emitcode ("cpl", "a"); /* lsb 2's complement */
5048 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5051 emitcode ("add", "a,#1"); /* this sets carry flag */
5052 emitcode ("xch", "a,b");
5053 emitcode ("cpl", "a"); /* msb 2's complement */
5054 emitcode ("addc", "a,#0");
5055 emitcode ("xch", "a,b");
5059 aopPut (result, "a", 0);
5061 aopPut (result, "b", 1);
5066 /*-----------------------------------------------------------------*/
5067 /* genMult - generates code for multiplication */
5068 /*-----------------------------------------------------------------*/
5070 genMult (iCode * ic)
5072 operand *left = IC_LEFT (ic);
5073 operand *right = IC_RIGHT (ic);
5074 operand *result = IC_RESULT (ic);
5076 D (emitcode (";", "genMult"));
5078 /* assign the asmops */
5079 aopOp (left, ic, FALSE);
5080 aopOp (right, ic, FALSE);
5081 aopOp (result, ic, TRUE);
5083 /* special cases first */
5085 if (AOP_TYPE (left) == AOP_CRY &&
5086 AOP_TYPE (right) == AOP_CRY)
5088 genMultbits (left, right, result);
5092 /* if both are of size == 1 */
5093 #if 0 // one of them can be a sloc shared with the result
5094 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5096 if (getSize(operandType(left)) == 1 &&
5097 getSize(operandType(right)) == 1)
5100 genMultOneByte (left, right, result);
5104 /* should have been converted to function call */
5105 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5106 getSize(OP_SYMBOL(right)->type));
5110 freeAsmop (result, NULL, ic, TRUE);
5111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115 /*-----------------------------------------------------------------*/
5116 /* genDivbits :- division of bits */
5117 /*-----------------------------------------------------------------*/
5119 genDivbits (operand * left,
5126 D(emitcode ("; genDivbits",""));
5130 /* the result must be bit */
5131 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5132 l = aopGet (left, 0, FALSE, FALSE);
5136 emitcode ("div", "ab");
5137 emitcode ("rrc", "a");
5141 aopPut (result, "c", 0);
5144 /*-----------------------------------------------------------------*/
5145 /* genDivOneByte : 8 bit division */
5146 /*-----------------------------------------------------------------*/
5148 genDivOneByte (operand * left,
5152 bool lUnsigned, rUnsigned, pushedB;
5153 bool runtimeSign, compiletimeSign;
5154 bool accuse = FALSE;
5155 bool pushedA = FALSE;
5159 D(emitcode ("; genDivOneByte",""));
5161 /* Why is it necessary that genDivOneByte() can return an int result?
5164 volatile unsigned char uc;
5165 volatile signed char sc1, sc2;
5178 In all cases a one byte result would overflow, the following cast to int
5179 would return the wrong result.
5181 Two possible solution:
5182 a) cast operands to int, if ((unsigned) / (signed)) or
5183 ((signed) / (signed))
5184 b) return an 16 bit signed int; this is what we're doing here!
5187 size = AOP_SIZE (result) - 1;
5189 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5190 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5194 /* signed or unsigned */
5195 if (lUnsigned && rUnsigned)
5197 /* unsigned is easy */
5198 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5199 MOVA (aopGet (left, 0, FALSE, FALSE));
5200 emitcode ("div", "ab");
5201 aopPut (result, "a", 0);
5203 aopPut (result, zero, offset++);
5209 /* signed is a little bit more difficult */
5211 /* now sign adjust for both left & right */
5213 /* let's see what's needed: */
5214 /* apply negative sign during runtime */
5215 runtimeSign = FALSE;
5216 /* negative sign from literals */
5217 compiletimeSign = FALSE;
5221 if (AOP_TYPE(left) == AOP_LIT)
5223 /* signed literal */
5224 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5226 compiletimeSign = TRUE;
5229 /* signed but not literal */
5235 if (AOP_TYPE(right) == AOP_LIT)
5237 /* signed literal */
5238 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5240 compiletimeSign ^= TRUE;
5243 /* signed but not literal */
5247 /* initialize F0, which stores the runtime sign */
5250 if (compiletimeSign)
5251 emitcode ("setb", "F0"); /* set sign flag */
5253 emitcode ("clr", "F0"); /* reset sign flag */
5256 /* save the signs of the operands */
5257 if (AOP_TYPE(right) == AOP_LIT)
5259 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5261 if (!rUnsigned && val < 0)
5262 emitcode ("mov", "b,#0x%02x", -val);
5264 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5266 else /* ! literal */
5269 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5272 MOVA (aopGet (right, 0, FALSE, FALSE));
5273 lbl = newiTempLabel (NULL);
5274 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5275 emitcode ("cpl", "F0"); /* complement sign flag */
5276 emitcode ("cpl", "a"); /* 2's complement */
5277 emitcode ("inc", "a");
5279 emitcode ("mov", "b,a");
5283 if (AOP_TYPE(left) == AOP_LIT)
5285 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5287 if (!lUnsigned && val < 0)
5288 emitcode ("mov", "a,#0x%02x", -val);
5290 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5292 else /* ! literal */
5294 MOVA (aopGet (left, 0, FALSE, FALSE));
5298 lbl = newiTempLabel (NULL);
5299 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300 emitcode ("cpl", "F0"); /* complement sign flag */
5301 emitcode ("cpl", "a"); /* 2's complement */
5302 emitcode ("inc", "a");
5307 /* now the division */
5308 emitcode ("div", "ab");
5310 if (runtimeSign || compiletimeSign)
5312 lbl = newiTempLabel (NULL);
5314 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5315 emitcode ("cpl", "a"); /* lsb 2's complement */
5316 emitcode ("inc", "a");
5319 accuse = aopPut (result, "a", 0);
5322 /* msb is 0x00 or 0xff depending on the sign */
5327 emitcode ("push", "acc");
5330 emitcode ("mov", "c,F0");
5331 emitcode ("subb", "a,acc");
5333 aopPut (result, "a", offset++);
5335 else /* compiletimeSign */
5337 if (aopPutUsesAcc (result, "#0xFF", offset))
5339 emitcode ("push", "acc");
5343 aopPut (result, "#0xff", offset++);
5349 aopPut (result, "a", 0);
5351 aopPut (result, zero, offset++);
5355 emitcode ("pop", "acc");
5359 /*-----------------------------------------------------------------*/
5360 /* genDiv - generates code for division */
5361 /*-----------------------------------------------------------------*/
5365 operand *left = IC_LEFT (ic);
5366 operand *right = IC_RIGHT (ic);
5367 operand *result = IC_RESULT (ic);
5369 D (emitcode (";", "genDiv"));
5371 /* assign the amsops */
5372 aopOp (left, ic, FALSE);
5373 aopOp (right, ic, FALSE);
5374 aopOp (result, ic, TRUE);
5376 /* special cases first */
5378 if (AOP_TYPE (left) == AOP_CRY &&
5379 AOP_TYPE (right) == AOP_CRY)
5381 genDivbits (left, right, result);
5385 /* if both are of size == 1 */
5386 if (AOP_SIZE (left) == 1 &&
5387 AOP_SIZE (right) == 1)
5389 genDivOneByte (left, right, result);
5393 /* should have been converted to function call */
5396 freeAsmop (result, NULL, ic, TRUE);
5397 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401 /*-----------------------------------------------------------------*/
5402 /* genModbits :- modulus of bits */
5403 /*-----------------------------------------------------------------*/
5405 genModbits (operand * left,
5412 D (emitcode (";", "genModbits"));
5416 /* the result must be bit */
5417 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5418 l = aopGet (left, 0, FALSE, FALSE);
5422 emitcode ("div", "ab");
5423 emitcode ("mov", "a,b");
5424 emitcode ("rrc", "a");
5428 aopPut (result, "c", 0);
5431 /*-----------------------------------------------------------------*/
5432 /* genModOneByte : 8 bit modulus */
5433 /*-----------------------------------------------------------------*/
5435 genModOneByte (operand * left,
5439 bool lUnsigned, rUnsigned, pushedB;
5440 bool runtimeSign, compiletimeSign;
5444 D (emitcode (";", "genModOneByte"));
5446 size = AOP_SIZE (result) - 1;
5448 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5449 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5451 /* if right is a literal, check it for 2^n */
5452 if (AOP_TYPE(right) == AOP_LIT)
5454 unsigned char val = abs((int) operandLitValue(right));
5455 symbol *lbl2 = NULL;
5459 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5468 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5469 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5470 /* because iCode should have been changed to genAnd */
5471 /* see file "SDCCopt.c", function "convertToFcall()" */
5473 MOVA (aopGet (left, 0, FALSE, FALSE));
5474 emitcode ("mov", "c,acc.7");
5475 emitcode ("anl", "a,#0x%02x", val - 1);
5476 lbl = newiTempLabel (NULL);
5477 emitcode ("jz", "%05d$", (lbl->key + 100));
5478 emitcode ("jnc", "%05d$", (lbl->key + 100));
5479 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5485 aopPut (result, "a", 0);
5487 aopPut (result, "#0xff", offs2++);
5488 lbl2 = newiTempLabel (NULL);
5489 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5492 aopPut (result, "a", 0);
5494 aopPut (result, zero, offset++);
5508 /* signed or unsigned */
5509 if (lUnsigned && rUnsigned)
5511 /* unsigned is easy */
5512 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513 MOVA (aopGet (left, 0, FALSE, FALSE));
5514 emitcode ("div", "ab");
5515 aopPut (result, "b", 0);
5517 aopPut (result, zero, offset++);
5523 /* signed is a little bit more difficult */
5525 /* now sign adjust for both left & right */
5527 /* modulus: sign of the right operand has no influence on the result! */
5528 if (AOP_TYPE(right) == AOP_LIT)
5530 signed char val = (char) operandLitValue(right);
5532 if (!rUnsigned && val < 0)
5533 emitcode ("mov", "b,#0x%02x", -val);
5535 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5537 else /* not literal */
5540 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5543 MOVA (aopGet (right, 0, FALSE, FALSE));
5544 lbl = newiTempLabel (NULL);
5545 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5546 emitcode ("cpl", "a"); /* 2's complement */
5547 emitcode ("inc", "a");
5549 emitcode ("mov", "b,a");
5553 /* let's see what's needed: */
5554 /* apply negative sign during runtime */
5555 runtimeSign = FALSE;
5556 /* negative sign from literals */
5557 compiletimeSign = FALSE;
5559 /* sign adjust left side */
5560 if (AOP_TYPE(left) == AOP_LIT)
5562 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5564 if (!lUnsigned && val < 0)
5566 compiletimeSign = TRUE; /* set sign flag */
5567 emitcode ("mov", "a,#0x%02x", -val);
5570 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5572 else /* ! literal */
5574 MOVA (aopGet (left, 0, FALSE, FALSE));
5579 emitcode ("clr", "F0"); /* clear sign flag */
5581 lbl = newiTempLabel (NULL);
5582 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5583 emitcode ("setb", "F0"); /* set sign flag */
5584 emitcode ("cpl", "a"); /* 2's complement */
5585 emitcode ("inc", "a");
5590 /* now the modulus */
5591 emitcode ("div", "ab");
5593 if (runtimeSign || compiletimeSign)
5595 emitcode ("mov", "a,b");
5596 lbl = newiTempLabel (NULL);
5598 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5599 emitcode ("cpl", "a"); /* 2's complement */
5600 emitcode ("inc", "a");
5603 aopPut (result, "a", 0);
5606 /* msb is 0x00 or 0xff depending on the sign */
5609 emitcode ("mov", "c,F0");
5610 emitcode ("subb", "a,acc");
5612 aopPut (result, "a", offset++);
5614 else /* compiletimeSign */
5616 aopPut (result, "#0xff", offset++);
5621 aopPut (result, "b", 0);
5623 aopPut (result, zero, offset++);
5629 /*-----------------------------------------------------------------*/
5630 /* genMod - generates code for division */
5631 /*-----------------------------------------------------------------*/
5635 operand *left = IC_LEFT (ic);
5636 operand *right = IC_RIGHT (ic);
5637 operand *result = IC_RESULT (ic);
5639 D (emitcode (";", "genMod"));
5641 /* assign the asmops */
5642 aopOp (left, ic, FALSE);
5643 aopOp (right, ic, FALSE);
5644 aopOp (result, ic, TRUE);
5646 /* special cases first */
5648 if (AOP_TYPE (left) == AOP_CRY &&
5649 AOP_TYPE (right) == AOP_CRY)
5651 genModbits (left, right, result);
5655 /* if both are of size == 1 */
5656 if (AOP_SIZE (left) == 1 &&
5657 AOP_SIZE (right) == 1)
5659 genModOneByte (left, right, result);
5663 /* should have been converted to function call */
5667 freeAsmop (result, NULL, ic, TRUE);
5668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5672 /*-----------------------------------------------------------------*/
5673 /* genIfxJump :- will create a jump depending on the ifx */
5674 /*-----------------------------------------------------------------*/
5676 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5679 symbol *tlbl = newiTempLabel (NULL);
5682 D (emitcode (";", "genIfxJump"));
5684 /* if true label then we jump if condition
5688 jlbl = IC_TRUE (ic);
5689 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5690 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5694 /* false label is present */
5695 jlbl = IC_FALSE (ic);
5696 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5697 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5699 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5700 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5702 emitcode (inst, "%05d$", tlbl->key + 100);
5703 freeForBranchAsmop (result);
5704 freeForBranchAsmop (right);
5705 freeForBranchAsmop (left);
5706 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5709 /* mark the icode as generated */
5713 /*-----------------------------------------------------------------*/
5714 /* genCmp :- greater or less than comparison */
5715 /*-----------------------------------------------------------------*/
5717 genCmp (operand * left, operand * right,
5718 operand * result, iCode * ifx, int sign, iCode *ic)
5720 int size, offset = 0;
5721 unsigned long lit = 0L;
5724 D (emitcode (";", "genCmp"));
5726 /* if left & right are bit variables */
5727 if (AOP_TYPE (left) == AOP_CRY &&
5728 AOP_TYPE (right) == AOP_CRY)
5730 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5731 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5735 /* subtract right from left if at the
5736 end the carry flag is set then we know that
5737 left is greater than right */
5738 size = max (AOP_SIZE (left), AOP_SIZE (right));
5740 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5741 if ((size == 1) && !sign &&
5742 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5744 symbol *lbl = newiTempLabel (NULL);
5745 emitcode ("cjne", "%s,%s,%05d$",
5746 aopGet (left, offset, FALSE, FALSE),
5747 aopGet (right, offset, FALSE, FALSE),
5753 if (AOP_TYPE (right) == AOP_LIT)
5755 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5756 /* optimize if(x < 0) or if(x >= 0) */
5765 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5766 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5768 genIfxJump (ifx, "acc.7", left, right, result);
5769 freeAsmop (right, NULL, ic, TRUE);
5770 freeAsmop (left, NULL, ic, TRUE);
5776 emitcode ("rlc", "a");
5783 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5784 while (size && (bytelit == 0))
5787 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5793 MOVA (aopGet (left, offset, FALSE, FALSE));
5794 if (sign && size == 0)
5796 emitcode ("xrl", "a,#0x80");
5797 emitcode ("subb", "a,#0x%02x",
5798 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5802 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5812 bool pushedB = FALSE;
5813 rightInB = aopGetUsesAcc(right, offset);
5817 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5819 MOVA (aopGet (left, offset, FALSE, FALSE));
5820 if (sign && size == 0)
5822 emitcode ("xrl", "a,#0x80");
5827 MOVB (aopGet (right, offset, FALSE, FALSE));
5829 emitcode ("xrl", "b,#0x80");
5830 emitcode ("subb", "a,b");
5835 emitcode ("subb", "a,b");
5837 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5849 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5855 /* if the result is used in the next
5856 ifx conditional branch then generate
5857 code a little differently */
5860 genIfxJump (ifx, "c", NULL, NULL, result);
5866 /* leave the result in acc */
5870 /*-----------------------------------------------------------------*/
5871 /* genCmpGt :- greater than comparison */
5872 /*-----------------------------------------------------------------*/
5874 genCmpGt (iCode * ic, iCode * ifx)
5876 operand *left, *right, *result;
5877 sym_link *letype, *retype;
5880 D (emitcode (";", "genCmpGt"));
5882 left = IC_LEFT (ic);
5883 right = IC_RIGHT (ic);
5884 result = IC_RESULT (ic);
5886 letype = getSpec (operandType (left));
5887 retype = getSpec (operandType (right));
5888 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5889 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5890 /* assign the amsops */
5891 aopOp (result, ic, TRUE);
5892 aopOp (left, ic, FALSE);
5893 aopOp (right, ic, FALSE);
5895 genCmp (right, left, result, ifx, sign, ic);
5897 freeAsmop (result, NULL, ic, TRUE);
5900 /*-----------------------------------------------------------------*/
5901 /* genCmpLt - less than comparisons */
5902 /*-----------------------------------------------------------------*/
5904 genCmpLt (iCode * ic, iCode * ifx)
5906 operand *left, *right, *result;
5907 sym_link *letype, *retype;
5910 D (emitcode (";", "genCmpLt"));
5912 left = IC_LEFT (ic);
5913 right = IC_RIGHT (ic);
5914 result = IC_RESULT (ic);
5916 letype = getSpec (operandType (left));
5917 retype = getSpec (operandType (right));
5918 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5919 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5920 /* assign the amsops */
5921 aopOp (result, ic, TRUE);
5922 aopOp (left, ic, FALSE);
5923 aopOp (right, ic, FALSE);
5925 genCmp (left, right, result, ifx, sign, ic);
5927 freeAsmop (result, NULL, ic, TRUE);
5930 /*-----------------------------------------------------------------*/
5931 /* gencjneshort - compare and jump if not equal */
5932 /*-----------------------------------------------------------------*/
5934 gencjneshort (operand * left, operand * right, symbol * lbl)
5936 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5938 unsigned long lit = 0L;
5940 D (emitcode (";", "gencjneshort"));
5942 /* if the left side is a literal or
5943 if the right is in a pointer register and left
5945 if ((AOP_TYPE (left) == AOP_LIT) ||
5946 (AOP_TYPE (left) == AOP_IMMD) ||
5947 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5954 if (AOP_TYPE (right) == AOP_LIT)
5955 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5957 /* if the right side is a literal then anything goes */
5958 if (AOP_TYPE (right) == AOP_LIT &&
5959 AOP_TYPE (left) != AOP_DIR &&
5960 AOP_TYPE (left) != AOP_IMMD)
5964 emitcode ("cjne", "%s,%s,%05d$",
5965 aopGet (left, offset, FALSE, FALSE),
5966 aopGet (right, offset, FALSE, FALSE),
5972 /* if the right side is in a register or in direct space or
5973 if the left is a pointer register & right is not */
5974 else if (AOP_TYPE (right) == AOP_REG ||
5975 AOP_TYPE (right) == AOP_DIR ||
5976 AOP_TYPE (right) == AOP_LIT ||
5977 AOP_TYPE (right) == AOP_IMMD ||
5978 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5979 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5983 MOVA (aopGet (left, offset, FALSE, FALSE));
5984 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5985 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5986 emitcode ("jnz", "%05d$", lbl->key + 100);
5988 emitcode ("cjne", "a,%s,%05d$",
5989 aopGet (right, offset, FALSE, TRUE),
5996 /* right is a pointer reg need both a & b */
5999 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6000 wassertl(!BINUSE, "B was in use");
6001 MOVB (aopGet (left, offset, FALSE, FALSE));
6002 MOVA (aopGet (right, offset, FALSE, FALSE));
6003 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6009 /*-----------------------------------------------------------------*/
6010 /* gencjne - compare and jump if not equal */
6011 /*-----------------------------------------------------------------*/
6013 gencjne (operand * left, operand * right, symbol * lbl)
6015 symbol *tlbl = newiTempLabel (NULL);
6017 D (emitcode (";", "gencjne"));
6019 gencjneshort (left, right, lbl);
6021 emitcode ("mov", "a,%s", one);
6022 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6024 emitcode ("clr", "a");
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpEq - generates code for equal to */
6030 /*-----------------------------------------------------------------*/
6032 genCmpEq (iCode * ic, iCode * ifx)
6034 bool swappedLR = FALSE;
6035 operand *left, *right, *result;
6037 D (emitcode (";", "genCmpEq"));
6039 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6040 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6041 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6043 /* if literal, literal on the right or
6044 if the right is in a pointer register and left
6046 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6047 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6049 operand *t = IC_RIGHT (ic);
6050 IC_RIGHT (ic) = IC_LEFT (ic);
6055 if (ifx && !AOP_SIZE (result))
6058 /* if they are both bit variables */
6059 if (AOP_TYPE (left) == AOP_CRY &&
6060 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6062 if (AOP_TYPE (right) == AOP_LIT)
6064 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6067 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6068 emitcode ("cpl", "c");
6072 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6076 emitcode ("clr", "c");
6078 /* AOP_TYPE(right) == AOP_CRY */
6082 symbol *lbl = newiTempLabel (NULL);
6083 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6084 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6085 emitcode ("cpl", "c");
6088 /* if true label then we jump if condition
6090 tlbl = newiTempLabel (NULL);
6093 emitcode ("jnc", "%05d$", tlbl->key + 100);
6094 freeForBranchAsmop (result);
6095 freeForBranchAsmop (right);
6096 freeForBranchAsmop (left);
6097 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6101 emitcode ("jc", "%05d$", tlbl->key + 100);
6102 freeForBranchAsmop (result);
6103 freeForBranchAsmop (right);
6104 freeForBranchAsmop (left);
6105 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6111 tlbl = newiTempLabel (NULL);
6112 gencjneshort (left, right, tlbl);
6115 freeForBranchAsmop (result);
6116 freeForBranchAsmop (right);
6117 freeForBranchAsmop (left);
6118 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6123 symbol *lbl = newiTempLabel (NULL);
6124 emitcode ("sjmp", "%05d$", lbl->key + 100);
6126 freeForBranchAsmop (result);
6127 freeForBranchAsmop (right);
6128 freeForBranchAsmop (left);
6129 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6133 /* mark the icode as generated */
6138 /* if they are both bit variables */
6139 if (AOP_TYPE (left) == AOP_CRY &&
6140 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6142 if (AOP_TYPE (right) == AOP_LIT)
6144 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6147 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6148 emitcode ("cpl", "c");
6152 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6156 emitcode ("clr", "c");
6158 /* AOP_TYPE(right) == AOP_CRY */
6162 symbol *lbl = newiTempLabel (NULL);
6163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6165 emitcode ("cpl", "c");
6169 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6176 genIfxJump (ifx, "c", left, right, result);
6179 /* if the result is used in an arithmetic operation
6180 then put the result in place */
6185 gencjne (left, right, newiTempLabel (NULL));
6186 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6188 aopPut (result, "a", 0);
6193 genIfxJump (ifx, "a", left, right, result);
6196 /* if the result is used in an arithmetic operation
6197 then put the result in place */
6198 if (AOP_TYPE (result) != AOP_CRY)
6200 /* leave the result in acc */
6204 freeAsmop (result, NULL, ic, TRUE);
6207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6208 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6217 /*-----------------------------------------------------------------*/
6218 /* ifxForOp - returns the icode containing the ifx for operand */
6219 /*-----------------------------------------------------------------*/
6221 ifxForOp (operand * op, iCode * ic)
6223 /* if true symbol then needs to be assigned */
6224 if (IS_TRUE_SYMOP (op))
6227 /* if this has register type condition and
6228 the next instruction is ifx with the same operand
6229 and live to of the operand is upto the ifx only then */
6231 ic->next->op == IFX &&
6232 IC_COND (ic->next)->key == op->key &&
6233 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6239 /*-----------------------------------------------------------------*/
6240 /* hasInc - operand is incremented before any other use */
6241 /*-----------------------------------------------------------------*/
6243 hasInc (operand *op, iCode *ic, int osize)
6245 sym_link *type = operandType(op);
6246 sym_link *retype = getSpec (type);
6247 iCode *lic = ic->next;
6250 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6251 if (!IS_SYMOP(op)) return NULL;
6253 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6254 if (IS_AGGREGATE(type->next)) return NULL;
6255 if (osize != (isize = getSize(type->next))) return NULL;
6258 /* if operand of the form op = op + <sizeof *op> */
6259 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6260 isOperandEqual(IC_RESULT(lic),op) &&
6261 isOperandLiteral(IC_RIGHT(lic)) &&
6262 operandLitValue(IC_RIGHT(lic)) == isize) {
6265 /* if the operand used or deffed */
6266 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6269 /* if GOTO or IFX */
6270 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6276 /*-----------------------------------------------------------------*/
6277 /* genAndOp - for && operation */
6278 /*-----------------------------------------------------------------*/
6280 genAndOp (iCode * ic)
6282 operand *left, *right, *result;
6285 D (emitcode (";", "genAndOp"));
6287 /* note here that && operations that are in an
6288 if statement are taken away by backPatchLabels
6289 only those used in arthmetic operations remain */
6290 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6291 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6292 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6294 /* if both are bit variables */
6295 if (AOP_TYPE (left) == AOP_CRY &&
6296 AOP_TYPE (right) == AOP_CRY)
6298 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6299 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6304 tlbl = newiTempLabel (NULL);
6306 emitcode ("jz", "%05d$", tlbl->key + 100);
6312 freeAsmop (result, NULL, ic, TRUE);
6313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318 /*-----------------------------------------------------------------*/
6319 /* genOrOp - for || operation */
6320 /*-----------------------------------------------------------------*/
6322 genOrOp (iCode * ic)
6324 operand *left, *right, *result;
6327 D (emitcode (";", "genOrOp"));
6329 /* note here that || operations that are in an
6330 if statement are taken away by backPatchLabels
6331 only those used in arthmetic operations remain */
6332 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6333 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6334 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6336 /* if both are bit variables */
6337 if (AOP_TYPE (left) == AOP_CRY &&
6338 AOP_TYPE (right) == AOP_CRY)
6340 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6341 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6346 tlbl = newiTempLabel (NULL);
6348 emitcode ("jnz", "%05d$", tlbl->key + 100);
6354 freeAsmop (result, NULL, ic, TRUE);
6355 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6356 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6359 /*-----------------------------------------------------------------*/
6360 /* isLiteralBit - test if lit == 2^n */
6361 /*-----------------------------------------------------------------*/
6363 isLiteralBit (unsigned long lit)
6365 unsigned long pw[32] =
6366 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6367 0x100L, 0x200L, 0x400L, 0x800L,
6368 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6369 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6370 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6371 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6372 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6375 for (idx = 0; idx < 32; idx++)
6381 /*-----------------------------------------------------------------*/
6382 /* continueIfTrue - */
6383 /*-----------------------------------------------------------------*/
6385 continueIfTrue (iCode * ic)
6388 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6392 /*-----------------------------------------------------------------*/
6394 /*-----------------------------------------------------------------*/
6396 jumpIfTrue (iCode * ic)
6399 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6403 /*-----------------------------------------------------------------*/
6404 /* jmpTrueOrFalse - */
6405 /*-----------------------------------------------------------------*/
6407 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6409 // ugly but optimized by peephole
6412 symbol *nlbl = newiTempLabel (NULL);
6413 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6415 freeForBranchAsmop (result);
6416 freeForBranchAsmop (right);
6417 freeForBranchAsmop (left);
6418 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6423 freeForBranchAsmop (result);
6424 freeForBranchAsmop (right);
6425 freeForBranchAsmop (left);
6426 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6432 /*-----------------------------------------------------------------*/
6433 /* genAnd - code for and */
6434 /*-----------------------------------------------------------------*/
6436 genAnd (iCode * ic, iCode * ifx)
6438 operand *left, *right, *result;
6439 int size, offset = 0;
6440 unsigned long lit = 0L;
6444 D (emitcode (";", "genAnd"));
6446 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6447 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6448 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6451 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6453 AOP_TYPE (left), AOP_TYPE (right));
6454 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6456 AOP_SIZE (left), AOP_SIZE (right));
6459 /* if left is a literal & right is not then exchange them */
6460 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6461 AOP_NEEDSACC (left))
6463 operand *tmp = right;
6468 /* if result = right then exchange left and right */
6469 if (sameRegs (AOP (result), AOP (right)))
6471 operand *tmp = right;
6476 /* if right is bit then exchange them */
6477 if (AOP_TYPE (right) == AOP_CRY &&
6478 AOP_TYPE (left) != AOP_CRY)
6480 operand *tmp = right;
6484 if (AOP_TYPE (right) == AOP_LIT)
6485 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6487 size = AOP_SIZE (result);
6490 // result = bit & yy;
6491 if (AOP_TYPE (left) == AOP_CRY)
6493 // c = bit & literal;
6494 if (AOP_TYPE (right) == AOP_LIT)
6498 if (size && sameRegs (AOP (result), AOP (left)))
6501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6506 if (size && (AOP_TYPE (result) == AOP_CRY))
6508 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6511 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6516 emitcode ("clr", "c");
6521 if (AOP_TYPE (right) == AOP_CRY)
6524 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6525 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6530 MOVA (aopGet (right, 0, FALSE, FALSE));
6532 emitcode ("rrc", "a");
6533 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6541 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542 genIfxJump (ifx, "c", left, right, result);
6546 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6547 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6548 if ((AOP_TYPE (right) == AOP_LIT) &&
6549 (AOP_TYPE (result) == AOP_CRY) &&
6550 (AOP_TYPE (left) != AOP_CRY))
6552 int posbit = isLiteralBit (lit);
6557 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6561 switch (posbit & 0x07)
6563 case 0: emitcode ("rrc", "a");
6565 case 7: emitcode ("rlc", "a");
6567 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6576 SNPRINTF (buffer, sizeof(buffer),
6577 "acc.%d", posbit & 0x07);
6578 genIfxJump (ifx, buffer, left, right, result);
6581 {// what is this case? just found it in ds390/gen.c
6582 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6589 symbol *tlbl = newiTempLabel (NULL);
6590 int sizel = AOP_SIZE (left);
6592 emitcode ("setb", "c");
6595 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6597 MOVA (aopGet (left, offset, FALSE, FALSE));
6599 if ((posbit = isLiteralBit (bytelit)) != 0)
6600 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6603 if (bytelit != 0x0FFL)
6604 emitcode ("anl", "a,%s",
6605 aopGet (right, offset, FALSE, TRUE));
6606 emitcode ("jnz", "%05d$", tlbl->key + 100);
6611 // bit = left & literal
6614 emitcode ("clr", "c");
6617 // if(left & literal)
6621 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6631 /* if left is same as result */
6632 if (sameRegs (AOP (result), AOP (left)))
6634 for (; size--; offset++)
6636 if (AOP_TYPE (right) == AOP_LIT)
6638 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6639 if (bytelit == 0x0FF)
6641 /* dummy read of volatile operand */
6642 if (isOperandVolatile (left, FALSE))
6643 MOVA (aopGet (left, offset, FALSE, FALSE));
6647 else if (bytelit == 0)
6649 aopPut (result, zero, offset);
6651 else if (IS_AOP_PREG (result))
6653 MOVA (aopGet (left, offset, FALSE, TRUE));
6654 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6655 aopPut (result, "a", offset);
6658 emitcode ("anl", "%s,%s",
6659 aopGet (left, offset, FALSE, TRUE),
6660 aopGet (right, offset, FALSE, FALSE));
6664 if (AOP_TYPE (left) == AOP_ACC)
6667 emitcode("mov", "a,b");
6668 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6670 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6672 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6673 MOVA (aopGet (right, offset, FALSE, FALSE));
6674 emitcode ("anl", "a,b");
6675 aopPut (result, "a", offset);
6677 else if (aopGetUsesAcc (left, offset))
6679 MOVA (aopGet (left, offset, FALSE, FALSE));
6680 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681 aopPut (result, "a", offset);
6685 MOVA (aopGet (right, offset, FALSE, FALSE));
6686 if (IS_AOP_PREG (result))
6688 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6689 aopPut (result, "a", offset);
6692 emitcode ("anl", "%s,a",
6693 aopGet (left, offset, FALSE, TRUE));
6700 // left & result in different registers
6701 if (AOP_TYPE (result) == AOP_CRY)
6704 // if(size), result in bit
6705 // if(!size && ifx), conditional oper: if(left & right)
6706 symbol *tlbl = newiTempLabel (NULL);
6707 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6709 emitcode ("setb", "c");
6712 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6713 && AOP_TYPE(left)==AOP_ACC)
6716 emitcode("mov", "a,b");
6717 emitcode ("anl", "a,%s",
6718 aopGet (right, offset, FALSE, FALSE));
6720 if (AOP_TYPE(left)==AOP_ACC)
6724 bool pushedB = pushB ();
6725 emitcode("mov", "b,a");
6726 MOVA (aopGet (right, offset, FALSE, FALSE));
6727 emitcode("anl", "a,b");
6732 MOVA (aopGet (right, offset, FALSE, FALSE));
6733 emitcode("anl", "a,b");
6736 MOVA (aopGet (right, offset, FALSE, FALSE));
6737 emitcode ("anl", "a,%s",
6738 aopGet (left, offset, FALSE, FALSE));
6741 emitcode ("jnz", "%05d$", tlbl->key + 100);
6751 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6757 for (; (size--); offset++)
6760 // result = left & right
6761 if (AOP_TYPE (right) == AOP_LIT)
6763 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6764 if (bytelit == 0x0FF)
6767 aopGet (left, offset, FALSE, FALSE),
6771 else if (bytelit == 0)
6773 /* dummy read of volatile operand */
6774 if (isOperandVolatile (left, FALSE))
6775 MOVA (aopGet (left, offset, FALSE, FALSE));
6776 aopPut (result, zero, offset);
6779 else if (AOP_TYPE (left) == AOP_ACC)
6783 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6784 aopPut (result, "a", offset);
6789 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6790 aopPut (result, "b", offset);
6795 // faster than result <- left, anl result,right
6796 // and better if result is SFR
6797 if (AOP_TYPE (left) == AOP_ACC)
6800 emitcode("mov", "a,b");
6801 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6803 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6805 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6806 MOVA (aopGet (right, offset, FALSE, FALSE));
6807 emitcode ("anl", "a,b");
6809 else if (aopGetUsesAcc (left, offset))
6811 MOVA (aopGet (left, offset, FALSE, FALSE));
6812 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6816 MOVA (aopGet (right, offset, FALSE, FALSE));
6817 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6819 aopPut (result, "a", offset);
6825 freeAsmop (result, NULL, ic, TRUE);
6826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6830 /*-----------------------------------------------------------------*/
6831 /* genOr - code for or */
6832 /*-----------------------------------------------------------------*/
6834 genOr (iCode * ic, iCode * ifx)
6836 operand *left, *right, *result;
6837 int size, offset = 0;
6838 unsigned long lit = 0L;
6841 D (emitcode (";", "genOr"));
6843 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6844 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6845 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6848 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6850 AOP_TYPE (left), AOP_TYPE (right));
6851 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6853 AOP_SIZE (left), AOP_SIZE (right));
6856 /* if left is a literal & right is not then exchange them */
6857 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6858 AOP_NEEDSACC (left))
6860 operand *tmp = right;
6865 /* if result = right then exchange them */
6866 if (sameRegs (AOP (result), AOP (right)))
6868 operand *tmp = right;
6873 /* if right is bit then exchange them */
6874 if (AOP_TYPE (right) == AOP_CRY &&
6875 AOP_TYPE (left) != AOP_CRY)
6877 operand *tmp = right;
6881 if (AOP_TYPE (right) == AOP_LIT)
6882 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6884 size = AOP_SIZE (result);
6888 if (AOP_TYPE (left) == AOP_CRY)
6890 if (AOP_TYPE (right) == AOP_LIT)
6892 // c = bit | literal;
6895 // lit != 0 => result = 1
6896 if (AOP_TYPE (result) == AOP_CRY)
6899 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6901 continueIfTrue (ifx);
6904 emitcode ("setb", "c");
6908 // lit == 0 => result = left
6909 if (size && sameRegs (AOP (result), AOP (left)))
6911 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6916 if (AOP_TYPE (right) == AOP_CRY)
6919 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6920 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6925 symbol *tlbl = newiTempLabel (NULL);
6926 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6927 emitcode ("setb", "c");
6928 emitcode ("jb", "%s,%05d$",
6929 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6931 emitcode ("jnz", "%05d$", tlbl->key + 100);
6932 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6934 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6949 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6950 genIfxJump (ifx, "c", left, right, result);
6954 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6955 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6956 if ((AOP_TYPE (right) == AOP_LIT) &&
6957 (AOP_TYPE (result) == AOP_CRY) &&
6958 (AOP_TYPE (left) != AOP_CRY))
6964 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6966 continueIfTrue (ifx);
6971 // lit = 0, result = boolean(left)
6973 emitcode ("setb", "c");
6977 symbol *tlbl = newiTempLabel (NULL);
6978 emitcode ("jnz", "%05d$", tlbl->key + 100);
6984 genIfxJump (ifx, "a", left, right, result);
6992 /* if left is same as result */
6993 if (sameRegs (AOP (result), AOP (left)))
6995 for (; size--; offset++)
6997 if (AOP_TYPE (right) == AOP_LIT)
6999 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7002 /* dummy read of volatile operand */
7003 if (isOperandVolatile (left, FALSE))
7004 MOVA (aopGet (left, offset, FALSE, FALSE));
7008 else if (bytelit == 0x0FF)
7010 aopPut (result, "#0xFF", offset);
7012 else if (IS_AOP_PREG (left))
7014 MOVA (aopGet (left, offset, FALSE, TRUE));
7015 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016 aopPut (result, "a", offset);
7020 emitcode ("orl", "%s,%s",
7021 aopGet (left, offset, FALSE, TRUE),
7022 aopGet (right, offset, FALSE, FALSE));
7027 if (AOP_TYPE (left) == AOP_ACC)
7030 emitcode("mov", "a,b");
7031 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7033 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7035 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7036 MOVA (aopGet (right, offset, FALSE, FALSE));
7037 emitcode ("orl", "a,b");
7038 aopPut (result, "a", offset);
7040 else if (aopGetUsesAcc (left, offset))
7042 MOVA (aopGet (left, offset, FALSE, FALSE));
7043 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7044 aopPut (result, "a", offset);
7048 MOVA (aopGet (right, offset, FALSE, FALSE));
7049 if (IS_AOP_PREG (left))
7051 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7052 aopPut (result, "a", offset);
7056 emitcode ("orl", "%s,a",
7057 aopGet (left, offset, FALSE, TRUE));
7065 // left & result in different registers
7066 if (AOP_TYPE (result) == AOP_CRY)
7069 // if(size), result in bit
7070 // if(!size && ifx), conditional oper: if(left | right)
7071 symbol *tlbl = newiTempLabel (NULL);
7072 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7074 emitcode ("setb", "c");
7077 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7079 emitcode("mov", "a,b");
7080 emitcode ("orl", "a,%s",
7081 aopGet (right, offset, FALSE, FALSE));
7083 MOVA (aopGet (right, offset, FALSE, FALSE));
7084 emitcode ("orl", "a,%s",
7085 aopGet (left, offset, FALSE, FALSE));
7087 emitcode ("jnz", "%05d$", tlbl->key + 100);
7097 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7103 for (; (size--); offset++)
7106 // result = left | right
7107 if (AOP_TYPE (right) == AOP_LIT)
7109 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7113 aopGet (left, offset, FALSE, FALSE),
7117 else if (bytelit == 0x0FF)
7119 /* dummy read of volatile operand */
7120 if (isOperandVolatile (left, FALSE))
7121 MOVA (aopGet (left, offset, FALSE, FALSE));
7122 aopPut (result, "#0xFF", offset);
7126 // faster than result <- left, anl result,right
7127 // and better if result is SFR
7128 if (AOP_TYPE (left) == AOP_ACC)
7131 emitcode("mov", "a,b");
7132 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7136 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7137 MOVA (aopGet (right, offset, FALSE, FALSE));
7138 emitcode ("orl", "a,b");
7140 else if (aopGetUsesAcc (left, offset))
7142 MOVA (aopGet (left, offset, FALSE, FALSE));
7143 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7147 MOVA (aopGet (right, offset, FALSE, FALSE));
7148 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7150 aopPut (result, "a", offset);
7156 freeAsmop (result, NULL, ic, TRUE);
7157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7158 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7161 /*-----------------------------------------------------------------*/
7162 /* genXor - code for xclusive or */
7163 /*-----------------------------------------------------------------*/
7165 genXor (iCode * ic, iCode * ifx)
7167 operand *left, *right, *result;
7168 int size, offset = 0;
7169 unsigned long lit = 0L;
7172 D (emitcode (";", "genXor"));
7174 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7175 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7176 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7179 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7181 AOP_TYPE (left), AOP_TYPE (right));
7182 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7184 AOP_SIZE (left), AOP_SIZE (right));
7187 /* if left is a literal & right is not ||
7188 if left needs acc & right does not */
7189 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7190 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7192 operand *tmp = right;
7197 /* if result = right then exchange them */
7198 if (sameRegs (AOP (result), AOP (right)))
7200 operand *tmp = right;
7205 /* if right is bit then exchange them */
7206 if (AOP_TYPE (right) == AOP_CRY &&
7207 AOP_TYPE (left) != AOP_CRY)
7209 operand *tmp = right;
7213 if (AOP_TYPE (right) == AOP_LIT)
7214 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7216 size = AOP_SIZE (result);
7220 if (AOP_TYPE (left) == AOP_CRY)
7222 if (AOP_TYPE (right) == AOP_LIT)
7224 // c = bit & literal;
7227 // lit>>1 != 0 => result = 1
7228 if (AOP_TYPE (result) == AOP_CRY)
7231 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7233 continueIfTrue (ifx);
7236 emitcode ("setb", "c");
7243 // lit == 0, result = left
7244 if (size && sameRegs (AOP (result), AOP (left)))
7246 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7250 // lit == 1, result = not(left)
7251 if (size && sameRegs (AOP (result), AOP (left)))
7253 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7258 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7259 emitcode ("cpl", "c");
7268 symbol *tlbl = newiTempLabel (NULL);
7269 if (AOP_TYPE (right) == AOP_CRY)
7272 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7276 int sizer = AOP_SIZE (right);
7278 // if val>>1 != 0, result = 1
7279 emitcode ("setb", "c");
7282 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7284 // test the msb of the lsb
7285 emitcode ("anl", "a,#0xfe");
7286 emitcode ("jnz", "%05d$", tlbl->key + 100);
7290 emitcode ("rrc", "a");
7292 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7293 emitcode ("cpl", "c");
7301 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7302 genIfxJump (ifx, "c", left, right, result);
7306 /* if left is same as result */
7307 if (sameRegs (AOP (result), AOP (left)))
7309 for (; size--; offset++)
7311 if (AOP_TYPE (right) == AOP_LIT)
7313 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7316 /* dummy read of volatile operand */
7317 if (isOperandVolatile (left, FALSE))
7318 MOVA (aopGet (left, offset, FALSE, FALSE));
7322 else if (IS_AOP_PREG (left))
7324 MOVA (aopGet (left, offset, FALSE, TRUE));
7325 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7326 aopPut (result, "a", offset);
7330 emitcode ("xrl", "%s,%s",
7331 aopGet (left, offset, FALSE, TRUE),
7332 aopGet (right, offset, FALSE, FALSE));
7337 if (AOP_TYPE (left) == AOP_ACC)
7340 emitcode("mov", "a,b");
7341 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7343 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7345 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7346 MOVA (aopGet (right, offset, FALSE, FALSE));
7347 emitcode ("xrl", "a,b");
7348 aopPut (result, "a", offset);
7350 else if (aopGetUsesAcc (left, offset))
7352 MOVA (aopGet (left, offset, FALSE, FALSE));
7353 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7354 aopPut (result, "a", offset);
7358 MOVA (aopGet (right, offset, FALSE, FALSE));
7359 if (IS_AOP_PREG (left))
7361 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7362 aopPut (result, "a", offset);
7365 emitcode ("xrl", "%s,a",
7366 aopGet (left, offset, FALSE, TRUE));
7373 // left & result in different registers
7374 if (AOP_TYPE (result) == AOP_CRY)
7377 // if(size), result in bit
7378 // if(!size && ifx), conditional oper: if(left ^ right)
7379 symbol *tlbl = newiTempLabel (NULL);
7380 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7383 emitcode ("setb", "c");
7386 if ((AOP_TYPE (right) == AOP_LIT) &&
7387 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7389 MOVA (aopGet (left, offset, FALSE, FALSE));
7393 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7395 emitcode("mov", "a,b");
7396 emitcode ("xrl", "a,%s",
7397 aopGet (right, offset, FALSE, FALSE));
7399 MOVA (aopGet (right, offset, FALSE, FALSE));
7400 emitcode ("xrl", "a,%s",
7401 aopGet (left, offset, FALSE, FALSE));
7404 emitcode ("jnz", "%05d$", tlbl->key + 100);
7414 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7418 for (; (size--); offset++)
7421 // result = left ^ right
7422 if (AOP_TYPE (right) == AOP_LIT)
7424 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7428 aopGet (left, offset, FALSE, FALSE),
7433 // faster than result <- left, anl result,right
7434 // and better if result is SFR
7435 if (AOP_TYPE (left) == AOP_ACC)
7438 emitcode("mov", "a,b");
7439 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7441 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7443 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7444 MOVA (aopGet (right, offset, FALSE, FALSE));
7445 emitcode ("xrl", "a,b");
7447 else if (aopGetUsesAcc (left, offset))
7449 MOVA (aopGet (left, offset, FALSE, FALSE));
7450 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7454 MOVA (aopGet (right, offset, FALSE, FALSE));
7455 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7457 aopPut (result, "a", offset);
7463 freeAsmop (result, NULL, ic, TRUE);
7464 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7465 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7468 /*-----------------------------------------------------------------*/
7469 /* genInline - write the inline code out */
7470 /*-----------------------------------------------------------------*/
7472 genInline (iCode * ic)
7474 char *buffer, *bp, *bp1;
7476 D (emitcode (";", "genInline"));
7478 _G.inLine += (!options.asmpeep);
7480 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7482 /* emit each line as a code */
7493 /* Add \n for labels, not dirs such as c:\mydir */
7494 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7508 /* emitcode("",buffer); */
7509 _G.inLine -= (!options.asmpeep);
7512 /*-----------------------------------------------------------------*/
7513 /* genRRC - rotate right with carry */
7514 /*-----------------------------------------------------------------*/
7518 operand *left, *result;
7522 D (emitcode (";", "genRRC"));
7524 /* rotate right with carry */
7525 left = IC_LEFT (ic);
7526 result = IC_RESULT (ic);
7527 aopOp (left, ic, FALSE);
7528 aopOp (result, ic, FALSE);
7530 /* move it to the result */
7531 size = AOP_SIZE (result);
7533 if (size == 1) { /* special case for 1 byte */
7534 l = aopGet (left, offset, FALSE, FALSE);
7536 emitcode ("rr", "a");
7539 /* no need to clear carry, bit7 will be written later */
7542 l = aopGet (left, offset, FALSE, FALSE);
7544 emitcode ("rrc", "a");
7545 if (AOP_SIZE (result) > 1)
7546 aopPut (result, "a", offset--);
7548 /* now we need to put the carry into the
7549 highest order byte of the result */
7550 if (AOP_SIZE (result) > 1)
7552 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7555 emitcode ("mov", "acc.7,c");
7557 aopPut (result, "a", AOP_SIZE (result) - 1);
7558 freeAsmop (result, NULL, ic, TRUE);
7559 freeAsmop (left, NULL, ic, TRUE);
7562 /*-----------------------------------------------------------------*/
7563 /* genRLC - generate code for rotate left with carry */
7564 /*-----------------------------------------------------------------*/
7568 operand *left, *result;
7572 D (emitcode (";", "genRLC"));
7574 /* rotate right with carry */
7575 left = IC_LEFT (ic);
7576 result = IC_RESULT (ic);
7577 aopOp (left, ic, FALSE);
7578 aopOp (result, ic, FALSE);
7580 /* move it to the result */
7581 size = AOP_SIZE (result);
7585 l = aopGet (left, offset, FALSE, FALSE);
7587 if (size == 0) { /* special case for 1 byte */
7591 emitcode("rlc","a"); /* bit0 will be written later */
7592 if (AOP_SIZE (result) > 1)
7594 aopPut (result, "a", offset++);
7599 l = aopGet (left, offset, FALSE, FALSE);
7601 emitcode ("rlc", "a");
7602 if (AOP_SIZE (result) > 1)
7603 aopPut (result, "a", offset++);
7606 /* now we need to put the carry into the
7607 highest order byte of the result */
7608 if (AOP_SIZE (result) > 1)
7610 l = aopGet (result, 0, FALSE, FALSE);
7613 emitcode ("mov", "acc.0,c");
7615 aopPut (result, "a", 0);
7616 freeAsmop (result, NULL, ic, TRUE);
7617 freeAsmop (left, NULL, ic, TRUE);
7620 /*-----------------------------------------------------------------*/
7621 /* genGetHbit - generates code get highest order bit */
7622 /*-----------------------------------------------------------------*/
7624 genGetHbit (iCode * ic)
7626 operand *left, *result;
7628 D (emitcode (";", "genGetHbit"));
7630 left = IC_LEFT (ic);
7631 result = IC_RESULT (ic);
7632 aopOp (left, ic, FALSE);
7633 aopOp (result, ic, FALSE);
7635 /* get the highest order byte into a */
7636 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7637 if (AOP_TYPE (result) == AOP_CRY)
7639 emitcode ("rlc", "a");
7644 emitcode ("rl", "a");
7645 emitcode ("anl", "a,#0x01");
7649 freeAsmop (result, NULL, ic, TRUE);
7650 freeAsmop (left, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* genGetAbit - generates code get a single bit */
7655 /*-----------------------------------------------------------------*/
7657 genGetAbit (iCode * ic)
7659 operand *left, *right, *result;
7662 D (emitcode (";", "genGetAbit"));
7664 left = IC_LEFT (ic);
7665 right = IC_RIGHT (ic);
7666 result = IC_RESULT (ic);
7667 aopOp (left, ic, FALSE);
7668 aopOp (right, ic, FALSE);
7669 aopOp (result, ic, FALSE);
7671 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7673 /* get the needed byte into a */
7674 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7676 if (AOP_TYPE (result) == AOP_CRY)
7679 emitcode ("rlc", "a");
7680 else if ((shCount) == 0)
7681 emitcode ("rrc", "a");
7683 emitcode ("mov", "c,acc[%d]", shCount);
7691 emitcode ("rr", "a");
7694 emitcode ("rr", "a");
7697 emitcode ("anl", "a,#0x01");
7701 emitcode ("mov", "c,acc[%d]", shCount);
7702 emitcode ("clr", "a");
7703 emitcode ("rlc", "a");
7706 emitcode ("swap", "a");
7707 emitcode ("anl", "a,#0x01");
7710 emitcode ("rl", "a");
7713 emitcode ("rl", "a");
7714 emitcode ("anl", "a,#0x01");
7720 freeAsmop (result, NULL, ic, TRUE);
7721 freeAsmop (right, NULL, ic, TRUE);
7722 freeAsmop (left, NULL, ic, TRUE);
7725 /*-----------------------------------------------------------------*/
7726 /* genGetByte - generates code get a single byte */
7727 /*-----------------------------------------------------------------*/
7729 genGetByte (iCode * ic)
7731 operand *left, *right, *result;
7734 D (emitcode (";", "genGetByte"));
7736 left = IC_LEFT (ic);
7737 right = IC_RIGHT (ic);
7738 result = IC_RESULT (ic);
7739 aopOp (left, ic, FALSE);
7740 aopOp (right, ic, FALSE);
7741 aopOp (result, ic, FALSE);
7743 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7745 aopGet (left, offset, FALSE, FALSE),
7748 freeAsmop (result, NULL, ic, TRUE);
7749 freeAsmop (right, NULL, ic, TRUE);
7750 freeAsmop (left, NULL, ic, TRUE);
7753 /*-----------------------------------------------------------------*/
7754 /* genGetWord - generates code get two bytes */
7755 /*-----------------------------------------------------------------*/
7757 genGetWord (iCode * ic)
7759 operand *left, *right, *result;
7762 D (emitcode (";", "genGetWord"));
7764 left = IC_LEFT (ic);
7765 right = IC_RIGHT (ic);
7766 result = IC_RESULT (ic);
7767 aopOp (left, ic, FALSE);
7768 aopOp (right, ic, FALSE);
7769 aopOp (result, ic, FALSE);
7771 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7773 aopGet (left, offset, FALSE, FALSE),
7776 aopGet (left, offset+1, FALSE, FALSE),
7779 freeAsmop (result, NULL, ic, TRUE);
7780 freeAsmop (right, NULL, ic, TRUE);
7781 freeAsmop (left, NULL, ic, TRUE);
7784 /*-----------------------------------------------------------------*/
7785 /* genSwap - generates code to swap nibbles or bytes */
7786 /*-----------------------------------------------------------------*/
7788 genSwap (iCode * ic)
7790 operand *left, *result;
7792 D(emitcode ("; genSwap",""));
7794 left = IC_LEFT (ic);
7795 result = IC_RESULT (ic);
7796 aopOp (left, ic, FALSE);
7797 aopOp (result, ic, FALSE);
7799 switch (AOP_SIZE (left))
7801 case 1: /* swap nibbles in byte */
7802 MOVA (aopGet (left, 0, FALSE, FALSE));
7803 emitcode ("swap", "a");
7804 aopPut (result, "a", 0);
7806 case 2: /* swap bytes in word */
7807 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7809 MOVA (aopGet (left, 0, FALSE, FALSE));
7810 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7811 aopPut (result, "a", 1);
7813 else if (operandsEqu (left, result))
7816 bool pushedB = FALSE, leftInB = FALSE;
7818 MOVA (aopGet (left, 0, FALSE, FALSE));
7819 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7822 emitcode ("mov", "b,a");
7826 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7827 aopPut (result, reg, 1);
7834 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7835 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7839 wassertl(FALSE, "unsupported SWAP operand size");
7842 freeAsmop (result, NULL, ic, TRUE);
7843 freeAsmop (left, NULL, ic, TRUE);
7846 /*-----------------------------------------------------------------*/
7847 /* AccRol - rotate left accumulator by known count */
7848 /*-----------------------------------------------------------------*/
7850 AccRol (int shCount)
7852 shCount &= 0x0007; // shCount : 0..7
7859 emitcode ("rl", "a");
7862 emitcode ("rl", "a");
7863 emitcode ("rl", "a");
7866 emitcode ("swap", "a");
7867 emitcode ("rr", "a");
7870 emitcode ("swap", "a");
7873 emitcode ("swap", "a");
7874 emitcode ("rl", "a");
7877 emitcode ("rr", "a");
7878 emitcode ("rr", "a");
7881 emitcode ("rr", "a");
7886 /*-----------------------------------------------------------------*/
7887 /* AccLsh - left shift accumulator by known count */
7888 /*-----------------------------------------------------------------*/
7890 AccLsh (int shCount)
7895 emitcode ("add", "a,acc");
7896 else if (shCount == 2)
7898 emitcode ("add", "a,acc");
7899 emitcode ("add", "a,acc");
7903 /* rotate left accumulator */
7905 /* and kill the lower order bits */
7906 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7911 /*-----------------------------------------------------------------*/
7912 /* AccRsh - right shift accumulator by known count */
7913 /*-----------------------------------------------------------------*/
7915 AccRsh (int shCount)
7922 emitcode ("rrc", "a");
7926 /* rotate right accumulator */
7927 AccRol (8 - shCount);
7928 /* and kill the higher order bits */
7929 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7934 /*-----------------------------------------------------------------*/
7935 /* AccSRsh - signed right shift accumulator by known count */
7936 /*-----------------------------------------------------------------*/
7938 AccSRsh (int shCount)
7945 emitcode ("mov", "c,acc.7");
7946 emitcode ("rrc", "a");
7948 else if (shCount == 2)
7950 emitcode ("mov", "c,acc.7");
7951 emitcode ("rrc", "a");
7952 emitcode ("mov", "c,acc.7");
7953 emitcode ("rrc", "a");
7957 tlbl = newiTempLabel (NULL);
7958 /* rotate right accumulator */
7959 AccRol (8 - shCount);
7960 /* and kill the higher order bits */
7961 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7962 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7963 emitcode ("orl", "a,#0x%02x",
7964 (unsigned char) ~SRMask[shCount]);
7970 /*-----------------------------------------------------------------*/
7971 /* shiftR1Left2Result - shift right one byte from left to result */
7972 /*-----------------------------------------------------------------*/
7974 shiftR1Left2Result (operand * left, int offl,
7975 operand * result, int offr,
7976 int shCount, int sign)
7978 MOVA (aopGet (left, offl, FALSE, FALSE));
7979 /* shift right accumulator */
7984 aopPut (result, "a", offr);
7987 /*-----------------------------------------------------------------*/
7988 /* shiftL1Left2Result - shift left one byte from left to result */
7989 /*-----------------------------------------------------------------*/
7991 shiftL1Left2Result (operand * left, int offl,
7992 operand * result, int offr, int shCount)
7995 l = aopGet (left, offl, FALSE, FALSE);
7997 /* shift left accumulator */
7999 aopPut (result, "a", offr);
8002 /*-----------------------------------------------------------------*/
8003 /* movLeft2Result - move byte from left to result */
8004 /*-----------------------------------------------------------------*/
8006 movLeft2Result (operand * left, int offl,
8007 operand * result, int offr, int sign)
8010 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8012 l = aopGet (left, offl, FALSE, FALSE);
8014 if (*l == '@' && (IS_AOP_PREG (result)))
8016 emitcode ("mov", "a,%s", l);
8017 aopPut (result, "a", offr);
8023 aopPut (result, l, offr);
8027 /* MSB sign in acc.7 ! */
8028 if (getDataSize (left) == offl + 1)
8031 aopPut (result, "a", offr);
8038 /*-----------------------------------------------------------------*/
8039 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8040 /*-----------------------------------------------------------------*/
8044 emitcode ("rrc", "a");
8045 emitcode ("xch", "a,%s", x);
8046 emitcode ("rrc", "a");
8047 emitcode ("xch", "a,%s", x);
8050 /*-----------------------------------------------------------------*/
8051 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8052 /*-----------------------------------------------------------------*/
8056 emitcode ("xch", "a,%s", x);
8057 emitcode ("rlc", "a");
8058 emitcode ("xch", "a,%s", x);
8059 emitcode ("rlc", "a");
8062 /*-----------------------------------------------------------------*/
8063 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8064 /*-----------------------------------------------------------------*/
8068 emitcode ("xch", "a,%s", x);
8069 emitcode ("add", "a,acc");
8070 emitcode ("xch", "a,%s", x);
8071 emitcode ("rlc", "a");
8074 /*-----------------------------------------------------------------*/
8075 /* AccAXLsh - left shift a:x by known count (0..7) */
8076 /*-----------------------------------------------------------------*/
8078 AccAXLsh (char *x, int shCount)
8093 case 5: // AAAAABBB:CCCCCDDD
8095 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8097 emitcode ("anl", "a,#0x%02x",
8098 SLMask[shCount]); // BBB00000:CCCCCDDD
8100 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8102 AccRol (shCount); // DDDCCCCC:BBB00000
8104 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8106 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8108 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8110 emitcode ("anl", "a,#0x%02x",
8111 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8113 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8115 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8118 case 6: // AAAAAABB:CCCCCCDD
8119 emitcode ("anl", "a,#0x%02x",
8120 SRMask[shCount]); // 000000BB:CCCCCCDD
8121 emitcode ("mov", "c,acc.0"); // c = B
8122 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8124 AccAXRrl1 (x); // BCCCCCCD:D000000B
8125 AccAXRrl1 (x); // BBCCCCCC:DD000000
8127 emitcode("rrc","a");
8128 emitcode("xch","a,%s", x);
8129 emitcode("rrc","a");
8130 emitcode("mov","c,acc.0"); //<< get correct bit
8131 emitcode("xch","a,%s", x);
8133 emitcode("rrc","a");
8134 emitcode("xch","a,%s", x);
8135 emitcode("rrc","a");
8136 emitcode("xch","a,%s", x);
8139 case 7: // a:x <<= 7
8141 emitcode ("anl", "a,#0x%02x",
8142 SRMask[shCount]); // 0000000B:CCCCCCCD
8144 emitcode ("mov", "c,acc.0"); // c = B
8146 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8148 AccAXRrl1 (x); // BCCCCCCC:D0000000
8156 /*-----------------------------------------------------------------*/
8157 /* AccAXRsh - right shift a:x known count (0..7) */
8158 /*-----------------------------------------------------------------*/
8160 AccAXRsh (char *x, int shCount)
8168 AccAXRrl1 (x); // 0->a:x
8173 AccAXRrl1 (x); // 0->a:x
8176 AccAXRrl1 (x); // 0->a:x
8181 case 5: // AAAAABBB:CCCCCDDD = a:x
8183 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8185 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8187 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8189 emitcode ("anl", "a,#0x%02x",
8190 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8192 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8194 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8196 emitcode ("anl", "a,#0x%02x",
8197 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8199 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8201 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8203 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8206 case 6: // AABBBBBB:CCDDDDDD
8208 emitcode ("mov", "c,acc.7");
8209 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8211 emitcode ("mov", "c,acc.7");
8212 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8214 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8216 emitcode ("anl", "a,#0x%02x",
8217 SRMask[shCount]); // 000000AA:BBBBBBCC
8220 case 7: // ABBBBBBB:CDDDDDDD
8222 emitcode ("mov", "c,acc.7"); // c = A
8224 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8226 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8228 emitcode ("anl", "a,#0x%02x",
8229 SRMask[shCount]); // 0000000A:BBBBBBBC
8237 /*-----------------------------------------------------------------*/
8238 /* AccAXRshS - right shift signed a:x known count (0..7) */
8239 /*-----------------------------------------------------------------*/
8241 AccAXRshS (char *x, int shCount)
8249 emitcode ("mov", "c,acc.7");
8250 AccAXRrl1 (x); // s->a:x
8254 emitcode ("mov", "c,acc.7");
8255 AccAXRrl1 (x); // s->a:x
8257 emitcode ("mov", "c,acc.7");
8258 AccAXRrl1 (x); // s->a:x
8263 case 5: // AAAAABBB:CCCCCDDD = a:x
8265 tlbl = newiTempLabel (NULL);
8266 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8268 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8270 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8272 emitcode ("anl", "a,#0x%02x",
8273 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8275 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8277 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8279 emitcode ("anl", "a,#0x%02x",
8280 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8282 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8284 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8286 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8288 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8289 emitcode ("orl", "a,#0x%02x",
8290 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8293 break; // SSSSAAAA:BBBCCCCC
8295 case 6: // AABBBBBB:CCDDDDDD
8297 tlbl = newiTempLabel (NULL);
8298 emitcode ("mov", "c,acc.7");
8299 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8301 emitcode ("mov", "c,acc.7");
8302 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8304 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8306 emitcode ("anl", "a,#0x%02x",
8307 SRMask[shCount]); // 000000AA:BBBBBBCC
8309 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8310 emitcode ("orl", "a,#0x%02x",
8311 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8315 case 7: // ABBBBBBB:CDDDDDDD
8317 tlbl = newiTempLabel (NULL);
8318 emitcode ("mov", "c,acc.7"); // c = A
8320 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8322 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8324 emitcode ("anl", "a,#0x%02x",
8325 SRMask[shCount]); // 0000000A:BBBBBBBC
8327 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8328 emitcode ("orl", "a,#0x%02x",
8329 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8338 /*-----------------------------------------------------------------*/
8339 /* shiftL2Left2Result - shift left two bytes from left to result */
8340 /*-----------------------------------------------------------------*/
8342 shiftL2Left2Result (operand * left, int offl,
8343 operand * result, int offr, int shCount)
8346 bool pushedB = FALSE;
8349 if (sameRegs (AOP (result), AOP (left)) &&
8350 ((offl + MSB16) == offr))
8352 /* don't crash result[offr] */
8353 MOVA (aopGet (left, offl, FALSE, FALSE));
8354 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8355 usedB = !strncmp(x, "b", 1);
8357 else if (aopGetUsesAcc (result, offr))
8359 movLeft2Result (left, offl, result, offr, 0);
8362 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8363 MOVA (aopGet (result, offr, FALSE, FALSE));
8364 emitcode ("xch", "a,b");
8369 movLeft2Result (left, offl, result, offr, 0);
8370 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8371 x = aopGet (result, offr, FALSE, FALSE);
8373 /* ax << shCount (x = lsb(result)) */
8374 AccAXLsh (x, shCount);
8377 emitcode ("xch", "a,b");
8378 aopPut (result, "a", offr);
8379 aopPut (result, "b", offr + MSB16);
8384 aopPut (result, "a", offr + MSB16);
8389 /*-----------------------------------------------------------------*/
8390 /* shiftR2Left2Result - shift right two bytes from left to result */
8391 /*-----------------------------------------------------------------*/
8393 shiftR2Left2Result (operand * left, int offl,
8394 operand * result, int offr,
8395 int shCount, int sign)
8398 bool pushedB = FALSE;
8401 if (sameRegs (AOP (result), AOP (left)) &&
8402 ((offl + MSB16) == offr))
8404 /* don't crash result[offr] */
8405 MOVA (aopGet (left, offl, FALSE, FALSE));
8406 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8407 usedB = !strncmp(x, "b", 1);
8409 else if (aopGetUsesAcc (result, offr))
8411 movLeft2Result (left, offl, result, offr, 0);
8414 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8415 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8420 movLeft2Result (left, offl, result, offr, 0);
8421 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8422 x = aopGet (result, offr, FALSE, FALSE);
8424 /* a:x >> shCount (x = lsb(result)) */
8426 AccAXRshS (x, shCount);
8428 AccAXRsh (x, shCount);
8431 emitcode ("xch", "a,b");
8432 aopPut (result, "a", offr);
8433 emitcode ("xch", "a,b");
8436 if (getDataSize (result) > 1)
8437 aopPut (result, "a", offr + MSB16);
8440 /*-----------------------------------------------------------------*/
8441 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8442 /*-----------------------------------------------------------------*/
8444 shiftLLeftOrResult (operand * left, int offl,
8445 operand * result, int offr, int shCount)
8447 MOVA (aopGet (left, offl, FALSE, FALSE));
8448 /* shift left accumulator */
8450 /* or with result */
8451 if (aopGetUsesAcc (result, offr))
8453 emitcode ("xch", "a,b");
8454 MOVA (aopGet (result, offr, FALSE, FALSE));
8455 emitcode ("orl", "a,b");
8459 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8461 /* back to result */
8462 aopPut (result, "a", offr);
8465 /*-----------------------------------------------------------------*/
8466 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8467 /*-----------------------------------------------------------------*/
8469 shiftRLeftOrResult (operand * left, int offl,
8470 operand * result, int offr, int shCount)
8472 MOVA (aopGet (left, offl, FALSE, FALSE));
8473 /* shift right accumulator */
8475 /* or with result */
8476 if (aopGetUsesAcc(result, offr))
8478 emitcode ("xch", "a,b");
8479 MOVA (aopGet (result, offr, FALSE, FALSE));
8480 emitcode ("orl", "a,b");
8484 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8486 /* back to result */
8487 aopPut (result, "a", offr);
8490 /*-----------------------------------------------------------------*/
8491 /* genlshOne - left shift a one byte quantity by known count */
8492 /*-----------------------------------------------------------------*/
8494 genlshOne (operand * result, operand * left, int shCount)
8496 D (emitcode (";", "genlshOne"));
8498 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8501 /*-----------------------------------------------------------------*/
8502 /* genlshTwo - left shift two bytes by known amount != 0 */
8503 /*-----------------------------------------------------------------*/
8505 genlshTwo (operand * result, operand * left, int shCount)
8509 D (emitcode (";", "genlshTwo"));
8511 size = getDataSize (result);
8513 /* if shCount >= 8 */
8521 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8523 movLeft2Result (left, LSB, result, MSB16, 0);
8525 aopPut (result, zero, LSB);
8528 /* 1 <= shCount <= 7 */
8532 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8534 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8538 /*-----------------------------------------------------------------*/
8539 /* shiftLLong - shift left one long from left to result */
8540 /* offl = LSB or MSB16 */
8541 /*-----------------------------------------------------------------*/
8543 shiftLLong (operand * left, operand * result, int offr)
8546 int size = AOP_SIZE (result);
8548 if (size >= LSB + offr)
8550 l = aopGet (left, LSB, FALSE, FALSE);
8552 emitcode ("add", "a,acc");
8553 if (sameRegs (AOP (left), AOP (result)) &&
8554 size >= MSB16 + offr && offr != LSB)
8555 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8557 aopPut (result, "a", LSB + offr);
8560 if (size >= MSB16 + offr)
8562 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8564 l = aopGet (left, MSB16, FALSE, FALSE);
8567 emitcode ("rlc", "a");
8568 if (sameRegs (AOP (left), AOP (result)) &&
8569 size >= MSB24 + offr && offr != LSB)
8570 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8572 aopPut (result, "a", MSB16 + offr);
8575 if (size >= MSB24 + offr)
8577 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8579 l = aopGet (left, MSB24, FALSE, FALSE);
8582 emitcode ("rlc", "a");
8583 if (sameRegs (AOP (left), AOP (result)) &&
8584 size >= MSB32 + offr && offr != LSB)
8585 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8587 aopPut (result, "a", MSB24 + offr);
8590 if (size > MSB32 + offr)
8592 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8594 l = aopGet (left, MSB32, FALSE, FALSE);
8597 emitcode ("rlc", "a");
8598 aopPut (result, "a", MSB32 + offr);
8601 aopPut (result, zero, LSB);
8604 /*-----------------------------------------------------------------*/
8605 /* genlshFour - shift four byte by a known amount != 0 */
8606 /*-----------------------------------------------------------------*/
8608 genlshFour (operand * result, operand * left, int shCount)
8612 D (emitcode (";", "genlshFour"));
8614 size = AOP_SIZE (result);
8616 /* if shifting more that 3 bytes */
8621 /* lowest order of left goes to the highest
8622 order of the destination */
8623 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8625 movLeft2Result (left, LSB, result, MSB32, 0);
8626 aopPut (result, zero, LSB);
8627 aopPut (result, zero, MSB16);
8628 aopPut (result, zero, MSB24);
8632 /* more than two bytes */
8633 else if (shCount >= 16)
8635 /* lower order two bytes goes to higher order two bytes */
8637 /* if some more remaining */
8639 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8642 movLeft2Result (left, MSB16, result, MSB32, 0);
8643 movLeft2Result (left, LSB, result, MSB24, 0);
8645 aopPut (result, zero, MSB16);
8646 aopPut (result, zero, LSB);
8650 /* if more than 1 byte */
8651 else if (shCount >= 8)
8653 /* lower order three bytes goes to higher order three bytes */
8658 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8660 movLeft2Result (left, LSB, result, MSB16, 0);
8666 movLeft2Result (left, MSB24, result, MSB32, 0);
8667 movLeft2Result (left, MSB16, result, MSB24, 0);
8668 movLeft2Result (left, LSB, result, MSB16, 0);
8669 aopPut (result, zero, LSB);
8671 else if (shCount == 1)
8672 shiftLLong (left, result, MSB16);
8675 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8676 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8677 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8678 aopPut (result, zero, LSB);
8683 /* 1 <= shCount <= 7 */
8684 else if (shCount <= 2)
8686 shiftLLong (left, result, LSB);
8688 shiftLLong (result, result, LSB);
8690 /* 3 <= shCount <= 7, optimize */
8693 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8694 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8695 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8699 /*-----------------------------------------------------------------*/
8700 /* genLeftShiftLiteral - left shifting by known count */
8701 /*-----------------------------------------------------------------*/
8703 genLeftShiftLiteral (operand * left,
8708 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8711 D (emitcode (";", "genLeftShiftLiteral"));
8713 freeAsmop (right, NULL, ic, TRUE);
8715 aopOp (left, ic, FALSE);
8716 aopOp (result, ic, FALSE);
8718 size = getSize (operandType (result));
8721 emitcode ("; shift left ", "result %d, left %d", size,
8725 /* I suppose that the left size >= result size */
8730 movLeft2Result (left, size, result, size, 0);
8733 else if (shCount >= (size * 8))
8737 aopPut (result, zero, size);
8745 genlshOne (result, left, shCount);
8749 genlshTwo (result, left, shCount);
8753 genlshFour (result, left, shCount);
8756 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8757 "*** ack! mystery literal shift!\n");
8761 freeAsmop (result, NULL, ic, TRUE);
8762 freeAsmop (left, NULL, ic, TRUE);
8765 /*-----------------------------------------------------------------*/
8766 /* genLeftShift - generates code for left shifting */
8767 /*-----------------------------------------------------------------*/
8769 genLeftShift (iCode * ic)
8771 operand *left, *right, *result;
8774 symbol *tlbl, *tlbl1;
8777 D (emitcode (";", "genLeftShift"));
8779 right = IC_RIGHT (ic);
8780 left = IC_LEFT (ic);
8781 result = IC_RESULT (ic);
8783 aopOp (right, ic, FALSE);
8785 /* if the shift count is known then do it
8786 as efficiently as possible */
8787 if (AOP_TYPE (right) == AOP_LIT)
8789 genLeftShiftLiteral (left, right, result, ic);
8793 /* shift count is unknown then we have to form
8794 a loop get the loop count in B : Note: we take
8795 only the lower order byte since shifting
8796 more that 32 bits make no sense anyway, ( the
8797 largest size of an object can be only 32 bits ) */
8800 MOVB (aopGet (right, 0, FALSE, FALSE));
8801 emitcode ("inc", "b");
8802 freeAsmop (right, NULL, ic, TRUE);
8803 aopOp (left, ic, FALSE);
8804 aopOp (result, ic, FALSE);
8806 /* now move the left to the result if they are not the same */
8807 if (!sameRegs (AOP (left), AOP (result)) &&
8808 AOP_SIZE (result) > 1)
8811 size = AOP_SIZE (result);
8815 l = aopGet (left, offset, FALSE, TRUE);
8816 if (*l == '@' && (IS_AOP_PREG (result)))
8819 emitcode ("mov", "a,%s", l);
8820 aopPut (result, "a", offset);
8823 aopPut (result, l, offset);
8828 tlbl = newiTempLabel (NULL);
8829 size = AOP_SIZE (result);
8831 tlbl1 = newiTempLabel (NULL);
8833 /* if it is only one byte then */
8836 symbol *tlbl1 = newiTempLabel (NULL);
8838 l = aopGet (left, 0, FALSE, FALSE);
8840 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8842 emitcode ("add", "a,acc");
8844 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8846 aopPut (result, "a", 0);
8850 reAdjustPreg (AOP (result));
8852 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8854 l = aopGet (result, offset, FALSE, FALSE);
8856 emitcode ("add", "a,acc");
8857 aopPut (result, "a", offset++);
8860 l = aopGet (result, offset, FALSE, FALSE);
8862 emitcode ("rlc", "a");
8863 aopPut (result, "a", offset++);
8865 reAdjustPreg (AOP (result));
8868 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8871 freeAsmop (result, NULL, ic, TRUE);
8872 freeAsmop (left, NULL, ic, TRUE);
8875 /*-----------------------------------------------------------------*/
8876 /* genrshOne - right shift a one byte quantity by known count */
8877 /*-----------------------------------------------------------------*/
8879 genrshOne (operand * result, operand * left,
8880 int shCount, int sign)
8882 D (emitcode (";", "genrshOne"));
8884 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8887 /*-----------------------------------------------------------------*/
8888 /* genrshTwo - right shift two bytes by known amount != 0 */
8889 /*-----------------------------------------------------------------*/
8891 genrshTwo (operand * result, operand * left,
8892 int shCount, int sign)
8894 D (emitcode (";", "genrshTwo"));
8896 /* if shCount >= 8 */
8901 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8903 movLeft2Result (left, MSB16, result, LSB, sign);
8904 addSign (result, MSB16, sign);
8907 /* 1 <= shCount <= 7 */
8909 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8912 /*-----------------------------------------------------------------*/
8913 /* shiftRLong - shift right one long from left to result */
8914 /* offl = LSB or MSB16 */
8915 /*-----------------------------------------------------------------*/
8917 shiftRLong (operand * left, int offl,
8918 operand * result, int sign)
8920 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
8922 if (overlapping && offl>1)
8924 // we are in big trouble, but this shouldn't happen
8925 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8928 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8935 emitcode ("rlc", "a");
8936 emitcode ("subb", "a,acc");
8937 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
8939 xch_a_aopGet (left, MSB32, FALSE, FALSE);
8943 aopPut (result, "a", MSB32);
8944 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8949 if (aopPutUsesAcc (result, zero, MSB32))
8951 emitcode("xch", "a,b");
8952 aopPut (result, zero, MSB32);
8953 emitcode("xch", "a,b");
8957 aopPut (result, zero, MSB32);
8964 emitcode ("clr", "c");
8968 emitcode ("mov", "c,acc.7");
8971 emitcode ("rrc", "a");
8973 if (overlapping && offl==MSB16 &&
8974 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
8976 xch_a_aopGet (left, MSB24, FALSE, FALSE);
8980 aopPut (result, "a", MSB32 - offl);
8981 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8984 emitcode ("rrc", "a");
8985 if (overlapping && offl==MSB16 &&
8986 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
8988 xch_a_aopGet (left, MSB16, FALSE, FALSE);
8992 aopPut (result, "a", MSB24 - offl);
8993 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8996 emitcode ("rrc", "a");
8999 aopPut (result, "a", MSB16 - offl);
9004 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9006 xch_a_aopGet (left, LSB, FALSE, FALSE);
9010 aopPut (result, "a", MSB16 - offl);
9011 MOVA (aopGet (left, LSB, FALSE, FALSE));
9013 emitcode ("rrc", "a");
9014 aopPut (result, "a", LSB);
9018 /*-----------------------------------------------------------------*/
9019 /* genrshFour - shift four byte by a known amount != 0 */
9020 /*-----------------------------------------------------------------*/
9022 genrshFour (operand * result, operand * left,
9023 int shCount, int sign)
9025 D (emitcode (";", "genrshFour"));
9027 /* if shifting more that 3 bytes */
9032 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9034 movLeft2Result (left, MSB32, result, LSB, sign);
9035 addSign (result, MSB16, sign);
9037 else if (shCount >= 16)
9041 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9044 movLeft2Result (left, MSB24, result, LSB, 0);
9045 movLeft2Result (left, MSB32, result, MSB16, sign);
9047 addSign (result, MSB24, sign);
9049 else if (shCount >= 8)
9054 shiftRLong (left, MSB16, result, sign);
9056 else if (shCount == 0)
9058 movLeft2Result (left, MSB16, result, LSB, 0);
9059 movLeft2Result (left, MSB24, result, MSB16, 0);
9060 movLeft2Result (left, MSB32, result, MSB24, sign);
9061 addSign (result, MSB32, sign);
9065 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9066 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9067 /* the last shift is signed */
9068 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9069 addSign (result, MSB32, sign);
9074 /* 1 <= shCount <= 7 */
9077 shiftRLong (left, LSB, result, sign);
9079 shiftRLong (result, LSB, result, sign);
9083 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9084 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9085 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9090 /*-----------------------------------------------------------------*/
9091 /* genRightShiftLiteral - right shifting by known count */
9092 /*-----------------------------------------------------------------*/
9094 genRightShiftLiteral (operand * left,
9100 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9103 D (emitcode (";", "genRightShiftLiteral"));
9105 freeAsmop (right, NULL, ic, TRUE);
9107 aopOp (left, ic, FALSE);
9108 aopOp (result, ic, FALSE);
9111 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9115 size = getDataSize (left);
9116 /* test the LEFT size !!! */
9118 /* I suppose that the left size >= result size */
9121 size = getDataSize (result);
9123 movLeft2Result (left, size, result, size, 0);
9126 else if (shCount >= (size * 8))
9130 /* get sign in acc.7 */
9131 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9133 addSign (result, LSB, sign);
9140 genrshOne (result, left, shCount, sign);
9144 genrshTwo (result, left, shCount, sign);
9148 genrshFour (result, left, shCount, sign);
9154 freeAsmop (result, NULL, ic, TRUE);
9155 freeAsmop (left, NULL, ic, TRUE);
9158 /*-----------------------------------------------------------------*/
9159 /* genSignedRightShift - right shift of signed number */
9160 /*-----------------------------------------------------------------*/
9162 genSignedRightShift (iCode * ic)
9164 operand *right, *left, *result;
9167 symbol *tlbl, *tlbl1;
9170 D (emitcode (";", "genSignedRightShift"));
9172 /* we do it the hard way put the shift count in b
9173 and loop thru preserving the sign */
9175 right = IC_RIGHT (ic);
9176 left = IC_LEFT (ic);
9177 result = IC_RESULT (ic);
9179 aopOp (right, ic, FALSE);
9182 if (AOP_TYPE (right) == AOP_LIT)
9184 genRightShiftLiteral (left, right, result, ic, 1);
9187 /* shift count is unknown then we have to form
9188 a loop get the loop count in B : Note: we take
9189 only the lower order byte since shifting
9190 more that 32 bits make no sense anyway, ( the
9191 largest size of an object can be only 32 bits ) */
9194 MOVB (aopGet (right, 0, FALSE, FALSE));
9195 emitcode ("inc", "b");
9196 freeAsmop (right, NULL, ic, TRUE);
9197 aopOp (left, ic, FALSE);
9198 aopOp (result, ic, FALSE);
9200 /* now move the left to the result if they are not the
9202 if (!sameRegs (AOP (left), AOP (result)) &&
9203 AOP_SIZE (result) > 1)
9206 size = AOP_SIZE (result);
9210 l = aopGet (left, offset, FALSE, TRUE);
9211 if (*l == '@' && IS_AOP_PREG (result))
9214 emitcode ("mov", "a,%s", l);
9215 aopPut (result, "a", offset);
9218 aopPut (result, l, offset);
9223 /* mov the highest order bit to OVR */
9224 tlbl = newiTempLabel (NULL);
9225 tlbl1 = newiTempLabel (NULL);
9227 size = AOP_SIZE (result);
9229 MOVA (aopGet (left, offset, FALSE, FALSE));
9230 emitcode ("rlc", "a");
9231 emitcode ("mov", "ov,c");
9232 /* if it is only one byte then */
9235 l = aopGet (left, 0, FALSE, FALSE);
9237 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9239 emitcode ("mov", "c,ov");
9240 emitcode ("rrc", "a");
9242 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9244 aopPut (result, "a", 0);
9248 reAdjustPreg (AOP (result));
9249 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9251 emitcode ("mov", "c,ov");
9254 l = aopGet (result, offset, FALSE, FALSE);
9256 emitcode ("rrc", "a");
9257 aopPut (result, "a", offset--);
9259 reAdjustPreg (AOP (result));
9261 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9265 freeAsmop (result, NULL, ic, TRUE);
9266 freeAsmop (left, NULL, ic, TRUE);
9269 /*-----------------------------------------------------------------*/
9270 /* genRightShift - generate code for right shifting */
9271 /*-----------------------------------------------------------------*/
9273 genRightShift (iCode * ic)
9275 operand *right, *left, *result;
9279 symbol *tlbl, *tlbl1;
9282 D (emitcode (";", "genRightShift"));
9284 /* if signed then we do it the hard way preserve the
9285 sign bit moving it inwards */
9286 letype = getSpec (operandType (IC_LEFT (ic)));
9288 if (!SPEC_USIGN (letype))
9290 genSignedRightShift (ic);
9294 /* signed & unsigned types are treated the same : i.e. the
9295 signed is NOT propagated inwards : quoting from the
9296 ANSI - standard : "for E1 >> E2, is equivalent to division
9297 by 2**E2 if unsigned or if it has a non-negative value,
9298 otherwise the result is implementation defined ", MY definition
9299 is that the sign does not get propagated */
9301 right = IC_RIGHT (ic);
9302 left = IC_LEFT (ic);
9303 result = IC_RESULT (ic);
9305 aopOp (right, ic, FALSE);
9307 /* if the shift count is known then do it
9308 as efficiently as possible */
9309 if (AOP_TYPE (right) == AOP_LIT)
9311 genRightShiftLiteral (left, right, result, ic, 0);
9315 /* shift count is unknown then we have to form
9316 a loop get the loop count in B : Note: we take
9317 only the lower order byte since shifting
9318 more that 32 bits make no sense anyway, ( the
9319 largest size of an object can be only 32 bits ) */
9322 MOVB (aopGet (right, 0, FALSE, FALSE));
9323 emitcode ("inc", "b");
9324 freeAsmop (right, NULL, ic, TRUE);
9325 aopOp (left, ic, FALSE);
9326 aopOp (result, ic, FALSE);
9328 /* now move the left to the result if they are not the
9330 if (!sameRegs (AOP (left), AOP (result)) &&
9331 AOP_SIZE (result) > 1)
9333 size = AOP_SIZE (result);
9337 l = aopGet (left, offset, FALSE, TRUE);
9338 if (*l == '@' && IS_AOP_PREG (result))
9341 emitcode ("mov", "a,%s", l);
9342 aopPut (result, "a", offset);
9345 aopPut (result, l, offset);
9350 tlbl = newiTempLabel (NULL);
9351 tlbl1 = newiTempLabel (NULL);
9352 size = AOP_SIZE (result);
9355 /* if it is only one byte then */
9358 l = aopGet (left, 0, FALSE, FALSE);
9360 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9363 emitcode ("rrc", "a");
9365 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9367 aopPut (result, "a", 0);
9371 reAdjustPreg (AOP (result));
9372 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9377 l = aopGet (result, offset, FALSE, FALSE);
9379 emitcode ("rrc", "a");
9380 aopPut (result, "a", offset--);
9382 reAdjustPreg (AOP (result));
9385 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9389 freeAsmop (result, NULL, ic, TRUE);
9390 freeAsmop (left, NULL, ic, TRUE);
9393 /*-----------------------------------------------------------------*/
9394 /* emitPtrByteGet - emits code to get a byte into A through a */
9395 /* pointer register (R0, R1, or DPTR). The */
9396 /* original value of A can be preserved in B. */
9397 /*-----------------------------------------------------------------*/
9399 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9406 emitcode ("mov", "b,a");
9407 emitcode ("mov", "a,@%s", rname);
9412 emitcode ("mov", "b,a");
9413 emitcode ("movx", "a,@%s", rname);
9418 emitcode ("mov", "b,a");
9419 emitcode ("movx", "a,@dptr");
9424 emitcode ("mov", "b,a");
9425 emitcode ("clr", "a");
9426 emitcode ("movc", "a,@a+dptr");
9432 emitcode ("push", "b");
9433 emitcode ("push", "acc");
9435 emitcode ("lcall", "__gptrget");
9437 emitcode ("pop", "b");
9442 /*-----------------------------------------------------------------*/
9443 /* emitPtrByteSet - emits code to set a byte from src through a */
9444 /* pointer register (R0, R1, or DPTR). */
9445 /*-----------------------------------------------------------------*/
9447 emitPtrByteSet (char *rname, int p_type, char *src)
9456 emitcode ("mov", "@%s,a", rname);
9459 emitcode ("mov", "@%s,%s", rname, src);
9464 emitcode ("movx", "@%s,a", rname);
9469 emitcode ("movx", "@dptr,a");
9474 emitcode ("lcall", "__gptrput");
9479 /*-----------------------------------------------------------------*/
9480 /* genUnpackBits - generates code for unpacking bits */
9481 /*-----------------------------------------------------------------*/
9483 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9485 int offset = 0; /* result byte offset */
9486 int rsize; /* result size */
9487 int rlen = 0; /* remaining bitfield length */
9488 sym_link *etype; /* bitfield type information */
9489 int blen; /* bitfield length */
9490 int bstr; /* bitfield starting bit within byte */
9493 D(emitcode ("; genUnpackBits",""));
9495 etype = getSpec (operandType (result));
9496 rsize = getSize (operandType (result));
9497 blen = SPEC_BLEN (etype);
9498 bstr = SPEC_BSTR (etype);
9500 if (ifx && blen <= 8)
9502 emitPtrByteGet (rname, ptype, FALSE);
9505 SNPRINTF (buffer, sizeof(buffer),
9507 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9512 emitcode ("anl", "a,#0x%02x",
9513 (((unsigned char) -1) >> (8 - blen)) << bstr);
9514 genIfxJump (ifx, "a", NULL, NULL, NULL);
9520 /* If the bitfield length is less than a byte */
9523 emitPtrByteGet (rname, ptype, FALSE);
9525 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9526 if (!SPEC_USIGN (etype))
9528 /* signed bitfield */
9529 symbol *tlbl = newiTempLabel (NULL);
9531 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9532 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9535 aopPut (result, "a", offset++);
9539 /* Bit field did not fit in a byte. Copy all
9540 but the partial byte at the end. */
9541 for (rlen=blen;rlen>=8;rlen-=8)
9543 emitPtrByteGet (rname, ptype, FALSE);
9544 aopPut (result, "a", offset++);
9546 emitcode ("inc", "%s", rname);
9549 /* Handle the partial byte at the end */
9552 emitPtrByteGet (rname, ptype, FALSE);
9553 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9554 if (!SPEC_USIGN (etype))
9556 /* signed bitfield */
9557 symbol *tlbl = newiTempLabel (NULL);
9559 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9560 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9563 aopPut (result, "a", offset++);
9571 if (SPEC_USIGN (etype))
9575 /* signed bitfield: sign extension with 0x00 or 0xff */
9576 emitcode ("rlc", "a");
9577 emitcode ("subb", "a,acc");
9583 aopPut (result, source, offset++);
9588 /*-----------------------------------------------------------------*/
9589 /* genDataPointerGet - generates code when ptr offset is known */
9590 /*-----------------------------------------------------------------*/
9592 genDataPointerGet (operand * left,
9598 int size, offset = 0;
9600 D (emitcode (";", "genDataPointerGet"));
9602 aopOp (result, ic, TRUE);
9604 /* get the string representation of the name */
9605 l = aopGet (left, 0, FALSE, TRUE);
9606 size = AOP_SIZE (result);
9611 SNPRINTF (buffer, sizeof(buffer),
9612 "(%s + %d)", l + 1, offset);
9616 SNPRINTF (buffer, sizeof(buffer),
9619 aopPut (result, buffer, offset++);
9622 freeAsmop (result, NULL, ic, TRUE);
9623 freeAsmop (left, NULL, ic, TRUE);
9626 /*-----------------------------------------------------------------*/
9627 /* genNearPointerGet - emitcode for near pointer fetch */
9628 /*-----------------------------------------------------------------*/
9630 genNearPointerGet (operand * left,
9639 sym_link *rtype, *retype;
9640 sym_link *ltype = operandType (left);
9643 D (emitcode (";", "genNearPointerGet"));
9645 rtype = operandType (result);
9646 retype = getSpec (rtype);
9648 aopOp (left, ic, FALSE);
9650 /* if left is rematerialisable and
9651 result is not bitfield variable type and
9652 the left is pointer to data space i.e
9653 lower 128 bytes of space */
9654 if (AOP_TYPE (left) == AOP_IMMD &&
9655 !IS_BITFIELD (retype) &&
9656 DCL_TYPE (ltype) == POINTER)
9658 genDataPointerGet (left, result, ic);
9662 /* if the value is already in a pointer register
9663 then don't need anything more */
9664 if (!AOP_INPREG (AOP (left)))
9666 if (IS_AOP_PREG (left))
9668 // Aha, it is a pointer, just in disguise.
9669 rname = aopGet (left, 0, FALSE, FALSE);
9672 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9673 __FILE__, __LINE__);
9678 emitcode ("mov", "a%s,%s", rname + 1, rname);
9679 rname++; // skip the '@'.
9684 /* otherwise get a free pointer register */
9686 preg = getFreePtr (ic, &aop, FALSE);
9687 emitcode ("mov", "%s,%s",
9689 aopGet (left, 0, FALSE, TRUE));
9694 rname = aopGet (left, 0, FALSE, FALSE);
9696 //aopOp (result, ic, FALSE);
9697 aopOp (result, ic, result?TRUE:FALSE);
9699 /* if bitfield then unpack the bits */
9700 if (IS_BITFIELD (retype))
9701 genUnpackBits (result, rname, POINTER, ifx);
9704 /* we have can just get the values */
9705 int size = AOP_SIZE (result);
9710 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9713 emitcode ("mov", "a,@%s", rname);
9715 aopPut (result, "a", offset);
9719 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9720 aopPut (result, buffer, offset);
9724 emitcode ("inc", "%s", rname);
9728 /* now some housekeeping stuff */
9729 if (aop) /* we had to allocate for this iCode */
9731 if (pi) { /* post increment present */
9732 aopPut (left, rname, 0);
9734 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9738 /* we did not allocate which means left
9739 already in a pointer register, then
9740 if size > 0 && this could be used again
9741 we have to point it back to where it
9743 if ((AOP_SIZE (result) > 1 &&
9744 !OP_SYMBOL (left)->remat &&
9745 (OP_SYMBOL (left)->liveTo > ic->seq ||
9749 int size = AOP_SIZE (result) - 1;
9751 emitcode ("dec", "%s", rname);
9755 if (ifx && !ifx->generated)
9757 genIfxJump (ifx, "a", left, NULL, result);
9761 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9762 freeAsmop (left, NULL, ic, TRUE);
9763 if (pi) pi->generated = 1;
9766 /*-----------------------------------------------------------------*/
9767 /* genPagedPointerGet - emitcode for paged pointer fetch */
9768 /*-----------------------------------------------------------------*/
9770 genPagedPointerGet (operand * left,
9779 sym_link *rtype, *retype;
9781 D (emitcode (";", "genPagedPointerGet"));
9783 rtype = operandType (result);
9784 retype = getSpec (rtype);
9786 aopOp (left, ic, FALSE);
9788 /* if the value is already in a pointer register
9789 then don't need anything more */
9790 if (!AOP_INPREG (AOP (left)))
9792 /* otherwise get a free pointer register */
9794 preg = getFreePtr (ic, &aop, FALSE);
9795 emitcode ("mov", "%s,%s",
9797 aopGet (left, 0, FALSE, TRUE));
9801 rname = aopGet (left, 0, FALSE, FALSE);
9803 aopOp (result, ic, FALSE);
9805 /* if bitfield then unpack the bits */
9806 if (IS_BITFIELD (retype))
9807 genUnpackBits (result, rname, PPOINTER, ifx);
9810 /* we have can just get the values */
9811 int size = AOP_SIZE (result);
9817 emitcode ("movx", "a,@%s", rname);
9819 aopPut (result, "a", offset);
9824 emitcode ("inc", "%s", rname);
9828 /* now some housekeeping stuff */
9829 if (aop) /* we had to allocate for this iCode */
9832 aopPut (left, rname, 0);
9833 freeAsmop (NULL, aop, ic, TRUE);
9837 /* we did not allocate which means left
9838 already in a pointer register, then
9839 if size > 0 && this could be used again
9840 we have to point it back to where it
9842 if ((AOP_SIZE (result) > 1 &&
9843 !OP_SYMBOL (left)->remat &&
9844 (OP_SYMBOL (left)->liveTo > ic->seq ||
9848 int size = AOP_SIZE (result) - 1;
9850 emitcode ("dec", "%s", rname);
9854 if (ifx && !ifx->generated)
9856 genIfxJump (ifx, "a", left, NULL, result);
9860 freeAsmop (result, NULL, ic, TRUE);
9861 freeAsmop (left, NULL, ic, TRUE);
9862 if (pi) pi->generated = 1;
9865 /*--------------------------------------------------------------------*/
9866 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9867 /*--------------------------------------------------------------------*/
9869 loadDptrFromOperand (operand *op, bool loadBToo)
9871 if (AOP_TYPE (op) != AOP_STR)
9873 /* if this is rematerializable */
9874 if (AOP_TYPE (op) == AOP_IMMD)
9876 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9879 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9880 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9883 wassertl(FALSE, "need pointerCode");
9884 emitcode ("", "; mov b,???");
9885 /* genPointerGet and genPointerSet originally did different
9886 ** things for this case. Both seem wrong.
9887 ** from genPointerGet:
9888 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9889 ** from genPointerSet:
9890 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9895 else if (AOP_TYPE (op) == AOP_DPTR)
9899 MOVA (aopGet (op, 0, FALSE, FALSE));
9900 emitcode ("push", "acc");
9901 MOVA (aopGet (op, 1, FALSE, FALSE));
9902 emitcode ("push", "acc");
9903 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9904 emitcode ("pop", "dph");
9905 emitcode ("pop", "dpl");
9909 MOVA (aopGet (op, 0, FALSE, FALSE));
9910 emitcode ("push", "acc");
9911 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9912 emitcode ("pop", "dpl");
9916 { /* we need to get it byte by byte */
9917 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9918 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9920 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9925 /*-----------------------------------------------------------------*/
9926 /* genFarPointerGet - get value from far space */
9927 /*-----------------------------------------------------------------*/
9929 genFarPointerGet (operand * left,
9930 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9933 sym_link *retype = getSpec (operandType (result));
9935 D (emitcode (";", "genFarPointerGet"));
9937 aopOp (left, ic, FALSE);
9938 loadDptrFromOperand (left, FALSE);
9940 /* so dptr now contains the address */
9941 aopOp (result, ic, FALSE);
9943 /* if bit then unpack */
9944 if (IS_BITFIELD (retype))
9945 genUnpackBits (result, "dptr", FPOINTER, ifx);
9948 size = AOP_SIZE (result);
9953 emitcode ("movx", "a,@dptr");
9955 aopPut (result, "a", offset++);
9957 emitcode ("inc", "dptr");
9961 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9963 aopPut (left, "dpl", 0);
9964 aopPut (left, "dph", 1);
9968 if (ifx && !ifx->generated)
9970 genIfxJump (ifx, "a", left, NULL, result);
9973 freeAsmop (result, NULL, ic, TRUE);
9974 freeAsmop (left, NULL, ic, TRUE);
9977 /*-----------------------------------------------------------------*/
9978 /* genCodePointerGet - get value from code space */
9979 /*-----------------------------------------------------------------*/
9981 genCodePointerGet (operand * left,
9982 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9985 sym_link *retype = getSpec (operandType (result));
9987 D (emitcode (";", "genCodePointerGet"));
9989 aopOp (left, ic, FALSE);
9990 loadDptrFromOperand (left, FALSE);
9992 /* so dptr now contains the address */
9993 aopOp (result, ic, FALSE);
9995 /* if bit then unpack */
9996 if (IS_BITFIELD (retype))
9997 genUnpackBits (result, "dptr", CPOINTER, ifx);
10000 size = AOP_SIZE (result);
10005 emitcode ("clr", "a");
10006 emitcode ("movc", "a,@a+dptr");
10008 aopPut (result, "a", offset++);
10010 emitcode ("inc", "dptr");
10014 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10016 aopPut (left, "dpl", 0);
10017 aopPut (left, "dph", 1);
10021 if (ifx && !ifx->generated)
10023 genIfxJump (ifx, "a", left, NULL, result);
10026 freeAsmop (result, NULL, ic, TRUE);
10027 freeAsmop (left, NULL, ic, TRUE);
10030 /*-----------------------------------------------------------------*/
10031 /* genGenPointerGet - get value from generic pointer space */
10032 /*-----------------------------------------------------------------*/
10034 genGenPointerGet (operand * left,
10035 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10038 sym_link *retype = getSpec (operandType (result));
10040 D (emitcode (";", "genGenPointerGet"));
10042 aopOp (left, ic, FALSE);
10043 loadDptrFromOperand (left, TRUE);
10045 /* so dptr now contains the address */
10046 aopOp (result, ic, FALSE);
10048 /* if bit then unpack */
10049 if (IS_BITFIELD (retype))
10051 genUnpackBits (result, "dptr", GPOINTER, ifx);
10055 size = AOP_SIZE (result);
10060 emitcode ("lcall", "__gptrget");
10062 aopPut (result, "a", offset++);
10064 emitcode ("inc", "dptr");
10068 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10070 aopPut (left, "dpl", 0);
10071 aopPut (left, "dph", 1);
10075 if (ifx && !ifx->generated)
10077 genIfxJump (ifx, "a", left, NULL, result);
10080 freeAsmop (result, NULL, ic, TRUE);
10081 freeAsmop (left, NULL, ic, TRUE);
10084 /*-----------------------------------------------------------------*/
10085 /* genPointerGet - generate code for pointer get */
10086 /*-----------------------------------------------------------------*/
10088 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10090 operand *left, *result;
10091 sym_link *type, *etype;
10094 D (emitcode (";", "genPointerGet"));
10096 left = IC_LEFT (ic);
10097 result = IC_RESULT (ic);
10099 if (getSize (operandType (result))>1)
10102 /* depending on the type of pointer we need to
10103 move it to the correct pointer register */
10104 type = operandType (left);
10105 etype = getSpec (type);
10106 /* if left is of type of pointer then it is simple */
10107 if (IS_PTR (type) && !IS_FUNC (type->next))
10108 p_type = DCL_TYPE (type);
10111 /* we have to go by the storage class */
10112 p_type = PTR_TYPE (SPEC_OCLS (etype));
10115 /* special case when cast remat */
10116 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10117 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10119 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10120 type = operandType (left);
10121 p_type = DCL_TYPE (type);
10123 /* now that we have the pointer type we assign
10124 the pointer values */
10130 genNearPointerGet (left, result, ic, pi, ifx);
10134 genPagedPointerGet (left, result, ic, pi, ifx);
10138 genFarPointerGet (left, result, ic, pi, ifx);
10142 genCodePointerGet (left, result, ic, pi, ifx);
10146 genGenPointerGet (left, result, ic, pi, ifx);
10152 /*-----------------------------------------------------------------*/
10153 /* genPackBits - generates code for packed bit storage */
10154 /*-----------------------------------------------------------------*/
10156 genPackBits (sym_link * etype,
10158 char *rname, int p_type)
10160 int offset = 0; /* source byte offset */
10161 int rlen = 0; /* remaining bitfield length */
10162 int blen; /* bitfield length */
10163 int bstr; /* bitfield starting bit within byte */
10164 int litval; /* source literal value (if AOP_LIT) */
10165 unsigned char mask; /* bitmask within current byte */
10167 D(emitcode ("; genPackBits",""));
10169 blen = SPEC_BLEN (etype);
10170 bstr = SPEC_BSTR (etype);
10172 /* If the bitfield length is less than a byte */
10175 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10176 (unsigned char) (0xFF >> (8 - bstr)));
10178 if (AOP_TYPE (right) == AOP_LIT)
10180 /* Case with a bitfield length <8 and literal source
10182 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10184 litval &= (~mask) & 0xff;
10185 emitPtrByteGet (rname, p_type, FALSE);
10186 if ((mask|litval)!=0xff)
10187 emitcode ("anl","a,#0x%02x", mask);
10189 emitcode ("orl","a,#0x%02x", litval);
10193 if ((blen==1) && (p_type!=GPOINTER))
10195 /* Case with a bitfield length == 1 and no generic pointer
10197 if (AOP_TYPE (right) == AOP_CRY)
10198 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10201 MOVA (aopGet (right, 0, FALSE, FALSE));
10202 emitcode ("rrc","a");
10204 emitPtrByteGet (rname, p_type, FALSE);
10205 emitcode ("mov","acc.%d,c",bstr);
10210 /* Case with a bitfield length < 8 and arbitrary source
10212 MOVA (aopGet (right, 0, FALSE, FALSE));
10213 /* shift and mask source value */
10215 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10217 pushedB = pushB ();
10218 /* transfer A to B and get next byte */
10219 emitPtrByteGet (rname, p_type, TRUE);
10221 emitcode ("anl", "a,#0x%02x", mask);
10222 emitcode ("orl", "a,b");
10223 if (p_type == GPOINTER)
10224 emitcode ("pop", "b");
10230 emitPtrByteSet (rname, p_type, "a");
10234 /* Bit length is greater than 7 bits. In this case, copy */
10235 /* all except the partial byte at the end */
10236 for (rlen=blen;rlen>=8;rlen-=8)
10238 emitPtrByteSet (rname, p_type,
10239 aopGet (right, offset++, FALSE, TRUE) );
10241 emitcode ("inc", "%s", rname);
10244 /* If there was a partial byte at the end */
10247 mask = (((unsigned char) -1 << rlen) & 0xff);
10249 if (AOP_TYPE (right) == AOP_LIT)
10251 /* Case with partial byte and literal source
10253 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10254 litval >>= (blen-rlen);
10255 litval &= (~mask) & 0xff;
10256 emitPtrByteGet (rname, p_type, FALSE);
10257 if ((mask|litval)!=0xff)
10258 emitcode ("anl","a,#0x%02x", mask);
10260 emitcode ("orl","a,#0x%02x", litval);
10265 /* Case with partial byte and arbitrary source
10267 MOVA (aopGet (right, offset++, FALSE, FALSE));
10268 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10270 pushedB = pushB ();
10271 /* transfer A to B and get next byte */
10272 emitPtrByteGet (rname, p_type, TRUE);
10274 emitcode ("anl", "a,#0x%02x", mask);
10275 emitcode ("orl", "a,b");
10276 if (p_type == GPOINTER)
10277 emitcode ("pop", "b");
10281 emitPtrByteSet (rname, p_type, "a");
10286 /*-----------------------------------------------------------------*/
10287 /* genDataPointerSet - remat pointer to data space */
10288 /*-----------------------------------------------------------------*/
10290 genDataPointerSet (operand * right,
10294 int size, offset = 0;
10295 char *l, buffer[256];
10297 D (emitcode (";", "genDataPointerSet"));
10299 aopOp (right, ic, FALSE);
10301 l = aopGet (result, 0, FALSE, TRUE);
10302 size = AOP_SIZE (right);
10306 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10308 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10309 emitcode ("mov", "%s,%s", buffer,
10310 aopGet (right, offset++, FALSE, FALSE));
10313 freeAsmop (result, NULL, ic, TRUE);
10314 freeAsmop (right, NULL, ic, TRUE);
10317 /*-----------------------------------------------------------------*/
10318 /* genNearPointerSet - emitcode for near pointer put */
10319 /*-----------------------------------------------------------------*/
10321 genNearPointerSet (operand * right,
10329 sym_link *retype, *letype;
10330 sym_link *ptype = operandType (result);
10332 D (emitcode (";", "genNearPointerSet"));
10334 retype = getSpec (operandType (right));
10335 letype = getSpec (ptype);
10337 aopOp (result, ic, FALSE);
10339 /* if the result is rematerializable &
10340 in data space & not a bit variable */
10341 if (AOP_TYPE (result) == AOP_IMMD &&
10342 DCL_TYPE (ptype) == POINTER &&
10343 !IS_BITVAR (retype) &&
10344 !IS_BITVAR (letype))
10346 genDataPointerSet (right, result, ic);
10350 /* if the value is already in a pointer register
10351 then don't need anything more */
10352 if (!AOP_INPREG (AOP (result)))
10355 //AOP_TYPE (result) == AOP_STK
10356 IS_AOP_PREG(result)
10359 // Aha, it is a pointer, just in disguise.
10360 rname = aopGet (result, 0, FALSE, FALSE);
10363 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10364 __FILE__, __LINE__);
10369 emitcode ("mov", "a%s,%s", rname + 1, rname);
10370 rname++; // skip the '@'.
10375 /* otherwise get a free pointer register */
10376 aop = newAsmop (0);
10377 preg = getFreePtr (ic, &aop, FALSE);
10378 emitcode ("mov", "%s,%s",
10380 aopGet (result, 0, FALSE, TRUE));
10381 rname = preg->name;
10386 rname = aopGet (result, 0, FALSE, FALSE);
10389 aopOp (right, ic, FALSE);
10391 /* if bitfield then unpack the bits */
10392 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10393 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10396 /* we can just get the values */
10397 int size = AOP_SIZE (right);
10402 l = aopGet (right, offset, FALSE, TRUE);
10403 if ((*l == '@') || (strcmp (l, "acc") == 0))
10406 emitcode ("mov", "@%s,a", rname);
10409 emitcode ("mov", "@%s,%s", rname, l);
10411 emitcode ("inc", "%s", rname);
10416 /* now some housekeeping stuff */
10417 if (aop) /* we had to allocate for this iCode */
10420 aopPut (result, rname, 0);
10421 freeAsmop (NULL, aop, ic, TRUE);
10425 /* we did not allocate which means left
10426 already in a pointer register, then
10427 if size > 0 && this could be used again
10428 we have to point it back to where it
10430 if ((AOP_SIZE (right) > 1 &&
10431 !OP_SYMBOL (result)->remat &&
10432 (OP_SYMBOL (result)->liveTo > ic->seq ||
10436 int size = AOP_SIZE (right) - 1;
10438 emitcode ("dec", "%s", rname);
10443 if (pi) pi->generated = 1;
10444 freeAsmop (result, NULL, ic, TRUE);
10445 freeAsmop (right, NULL, ic, TRUE);
10448 /*-----------------------------------------------------------------*/
10449 /* genPagedPointerSet - emitcode for Paged pointer put */
10450 /*-----------------------------------------------------------------*/
10452 genPagedPointerSet (operand * right,
10460 sym_link *retype, *letype;
10462 D (emitcode (";", "genPagedPointerSet"));
10464 retype = getSpec (operandType (right));
10465 letype = getSpec (operandType (result));
10467 aopOp (result, ic, FALSE);
10469 /* if the value is already in a pointer register
10470 then don't need anything more */
10471 if (!AOP_INPREG (AOP (result)))
10473 /* otherwise get a free pointer register */
10474 aop = newAsmop (0);
10475 preg = getFreePtr (ic, &aop, FALSE);
10476 emitcode ("mov", "%s,%s",
10478 aopGet (result, 0, FALSE, TRUE));
10479 rname = preg->name;
10482 rname = aopGet (result, 0, FALSE, FALSE);
10484 aopOp (right, ic, FALSE);
10486 /* if bitfield then unpack the bits */
10487 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10488 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10491 /* we have can just get the values */
10492 int size = AOP_SIZE (right);
10497 l = aopGet (right, offset, FALSE, TRUE);
10499 emitcode ("movx", "@%s,a", rname);
10502 emitcode ("inc", "%s", rname);
10508 /* now some housekeeping stuff */
10509 if (aop) /* we had to allocate for this iCode */
10512 aopPut (result, rname, 0);
10513 freeAsmop (NULL, aop, ic, TRUE);
10517 /* we did not allocate which means left
10518 already in a pointer register, then
10519 if size > 0 && this could be used again
10520 we have to point it back to where it
10522 if (AOP_SIZE (right) > 1 &&
10523 !OP_SYMBOL (result)->remat &&
10524 (OP_SYMBOL (result)->liveTo > ic->seq ||
10527 int size = AOP_SIZE (right) - 1;
10529 emitcode ("dec", "%s", rname);
10534 if (pi) pi->generated = 1;
10535 freeAsmop (result, NULL, ic, TRUE);
10536 freeAsmop (right, NULL, ic, TRUE);
10539 /*-----------------------------------------------------------------*/
10540 /* genFarPointerSet - set value from far space */
10541 /*-----------------------------------------------------------------*/
10543 genFarPointerSet (operand * right,
10544 operand * result, iCode * ic, iCode * pi)
10547 sym_link *retype = getSpec (operandType (right));
10548 sym_link *letype = getSpec (operandType (result));
10550 D(emitcode ("; genFarPointerSet",""));
10552 aopOp (result, ic, FALSE);
10553 loadDptrFromOperand (result, FALSE);
10555 /* so dptr now contains the address */
10556 aopOp (right, ic, FALSE);
10558 /* if bit then unpack */
10559 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10560 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10563 size = AOP_SIZE (right);
10568 char *l = aopGet (right, offset++, FALSE, FALSE);
10570 emitcode ("movx", "@dptr,a");
10572 emitcode ("inc", "dptr");
10575 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10576 aopPut (result, "dpl", 0);
10577 aopPut (result, "dph", 1);
10580 freeAsmop (result, NULL, ic, TRUE);
10581 freeAsmop (right, NULL, ic, TRUE);
10584 /*-----------------------------------------------------------------*/
10585 /* genGenPointerSet - set value from generic pointer space */
10586 /*-----------------------------------------------------------------*/
10588 genGenPointerSet (operand * right,
10589 operand * result, iCode * ic, iCode * pi)
10592 sym_link *retype = getSpec (operandType (right));
10593 sym_link *letype = getSpec (operandType (result));
10595 D (emitcode (";", "genGenPointerSet"));
10597 aopOp (result, ic, FALSE);
10598 loadDptrFromOperand (result, TRUE);
10600 /* so dptr now contains the address */
10601 aopOp (right, ic, FALSE);
10603 /* if bit then unpack */
10604 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10606 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10610 size = AOP_SIZE (right);
10615 char *l = aopGet (right, offset++, FALSE, FALSE);
10617 emitcode ("lcall", "__gptrput");
10619 emitcode ("inc", "dptr");
10623 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10624 aopPut (result, "dpl", 0);
10625 aopPut (result, "dph", 1);
10628 freeAsmop (result, NULL, ic, TRUE);
10629 freeAsmop (right, NULL, ic, TRUE);
10632 /*-----------------------------------------------------------------*/
10633 /* genPointerSet - stores the value into a pointer location */
10634 /*-----------------------------------------------------------------*/
10636 genPointerSet (iCode * ic, iCode *pi)
10638 operand *right, *result;
10639 sym_link *type, *etype;
10642 D (emitcode (";", "genPointerSet"));
10644 right = IC_RIGHT (ic);
10645 result = IC_RESULT (ic);
10647 /* depending on the type of pointer we need to
10648 move it to the correct pointer register */
10649 type = operandType (result);
10650 etype = getSpec (type);
10651 /* if left is of type of pointer then it is simple */
10652 if (IS_PTR (type) && !IS_FUNC (type->next))
10654 p_type = DCL_TYPE (type);
10658 /* we have to go by the storage class */
10659 p_type = PTR_TYPE (SPEC_OCLS (etype));
10662 /* special case when cast remat */
10663 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10664 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10665 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10666 type = operandType (result);
10667 p_type = DCL_TYPE (type);
10670 /* now that we have the pointer type we assign
10671 the pointer values */
10677 genNearPointerSet (right, result, ic, pi);
10681 genPagedPointerSet (right, result, ic, pi);
10685 genFarPointerSet (right, result, ic, pi);
10689 genGenPointerSet (right, result, ic, pi);
10693 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10694 "genPointerSet: illegal pointer type");
10698 /*-----------------------------------------------------------------*/
10699 /* genIfx - generate code for Ifx statement */
10700 /*-----------------------------------------------------------------*/
10702 genIfx (iCode * ic, iCode * popIc)
10704 operand *cond = IC_COND (ic);
10708 D (emitcode (";", "genIfx"));
10710 aopOp (cond, ic, FALSE);
10712 /* get the value into acc */
10713 if (AOP_TYPE (cond) != AOP_CRY)
10720 if (AOP(cond)->aopu.aop_dir)
10721 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10724 /* the result is now in the accumulator or a directly addressable bit */
10725 freeAsmop (cond, NULL, ic, TRUE);
10727 /* if there was something to be popped then do it */
10731 /* if the condition is a bit variable */
10733 genIfxJump(ic, dup, NULL, NULL, NULL);
10734 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10735 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10736 else if (isbit && !IS_ITEMP (cond))
10737 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10739 genIfxJump (ic, "a", NULL, NULL, NULL);
10744 /*-----------------------------------------------------------------*/
10745 /* genAddrOf - generates code for address of */
10746 /*-----------------------------------------------------------------*/
10748 genAddrOf (iCode * ic)
10750 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10753 D (emitcode (";", "genAddrOf"));
10755 aopOp (IC_RESULT (ic), ic, FALSE);
10757 /* if the operand is on the stack then we
10758 need to get the stack offset of this
10762 /* if it has an offset then we need to compute it */
10765 emitcode ("mov", "a,%s", SYM_BP (sym));
10766 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10767 ((char) (sym->stack - _G.nRegsSaved)) :
10768 ((char) sym->stack)) & 0xff);
10769 aopPut (IC_RESULT (ic), "a", 0);
10773 /* we can just move _bp */
10774 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10776 /* fill the result with zero */
10777 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10782 aopPut (IC_RESULT (ic), zero, offset++);
10787 /* object not on stack then we need the name */
10788 size = AOP_SIZE (IC_RESULT (ic));
10793 char s[SDCC_NAME_MAX];
10795 sprintf (s, "#(%s >> %d)",
10799 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10800 aopPut (IC_RESULT (ic), s, offset++);
10804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10808 /*-----------------------------------------------------------------*/
10809 /* genFarFarAssign - assignment when both are in far space */
10810 /*-----------------------------------------------------------------*/
10812 genFarFarAssign (operand * result, operand * right, iCode * ic)
10814 int size = AOP_SIZE (right);
10818 D (emitcode (";", "genFarFarAssign"));
10820 /* first push the right side on to the stack */
10823 l = aopGet (right, offset++, FALSE, FALSE);
10825 emitcode ("push", "acc");
10828 freeAsmop (right, NULL, ic, FALSE);
10829 /* now assign DPTR to result */
10830 aopOp (result, ic, FALSE);
10831 size = AOP_SIZE (result);
10834 emitcode ("pop", "acc");
10835 aopPut (result, "a", --offset);
10837 freeAsmop (result, NULL, ic, FALSE);
10840 /*-----------------------------------------------------------------*/
10841 /* genAssign - generate code for assignment */
10842 /*-----------------------------------------------------------------*/
10844 genAssign (iCode * ic)
10846 operand *result, *right;
10848 unsigned long lit = 0L;
10850 D (emitcode (";", "genAssign"));
10852 result = IC_RESULT (ic);
10853 right = IC_RIGHT (ic);
10855 /* if they are the same */
10856 if (operandsEqu (result, right) &&
10857 !isOperandVolatile (result, FALSE) &&
10858 !isOperandVolatile (right, FALSE))
10861 aopOp (right, ic, FALSE);
10863 /* special case both in far space */
10864 if (AOP_TYPE (right) == AOP_DPTR &&
10865 IS_TRUE_SYMOP (result) &&
10866 isOperandInFarSpace (result))
10868 genFarFarAssign (result, right, ic);
10872 aopOp (result, ic, TRUE);
10874 /* if they are the same registers */
10875 if (sameRegs (AOP (right), AOP (result)) &&
10876 !isOperandVolatile (result, FALSE) &&
10877 !isOperandVolatile (right, FALSE))
10880 /* if the result is a bit */
10881 if (AOP_TYPE (result) == AOP_CRY)
10883 /* if the right size is a literal then
10884 we know what the value is */
10885 if (AOP_TYPE (right) == AOP_LIT)
10887 if (((int) operandLitValue (right)))
10888 aopPut (result, one, 0);
10890 aopPut (result, zero, 0);
10894 /* the right is also a bit variable */
10895 if (AOP_TYPE (right) == AOP_CRY)
10897 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10898 aopPut (result, "c", 0);
10902 /* we need to or */
10904 aopPut (result, "a", 0);
10908 /* bit variables done */
10910 size = AOP_SIZE (result);
10912 if (AOP_TYPE (right) == AOP_LIT)
10913 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10916 (AOP_TYPE (result) != AOP_REG) &&
10917 (AOP_TYPE (right) == AOP_LIT) &&
10918 !IS_FLOAT (operandType (right)) &&
10921 while ((size) && (lit))
10924 aopGet (right, offset, FALSE, FALSE),
10930 /* And now fill the rest with zeros. */
10933 emitcode ("clr", "a");
10937 aopPut (result, "a", offset);
10946 aopGet (right, offset, FALSE, FALSE),
10953 freeAsmop (result, NULL, ic, TRUE);
10954 freeAsmop (right, NULL, ic, TRUE);
10957 /*-----------------------------------------------------------------*/
10958 /* genJumpTab - generates code for jump table */
10959 /*-----------------------------------------------------------------*/
10961 genJumpTab (iCode * ic)
10963 symbol *jtab,*jtablo,*jtabhi;
10965 unsigned int count;
10967 D (emitcode (";", "genJumpTab"));
10969 count = elementsInSet( IC_JTLABELS (ic) );
10973 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10974 if the switch argument is in a register.
10975 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10976 /* Peephole may not convert ljmp to sjmp or ret
10977 labelIsReturnOnly & labelInRange must check
10978 currPl->ic->op != JUMPTABLE */
10979 aopOp (IC_JTCOND (ic), ic, FALSE);
10980 /* get the condition into accumulator */
10981 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10983 /* multiply by three */
10984 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10986 emitcode ("mov", "b,#3");
10987 emitcode ("mul", "ab");
10991 emitcode ("add", "a,acc");
10992 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10994 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10996 jtab = newiTempLabel (NULL);
10997 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10998 emitcode ("jmp", "@a+dptr");
11000 /* now generate the jump labels */
11001 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11002 jtab = setNextItem (IC_JTLABELS (ic)))
11003 emitcode ("ljmp", "%05d$", jtab->key + 100);
11007 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11008 if the switch argument is in a register.
11009 For n>6 this algorithm may be more compact */
11010 jtablo = newiTempLabel (NULL);
11011 jtabhi = newiTempLabel (NULL);
11013 /* get the condition into accumulator.
11014 Using b as temporary storage, if register push/pop is needed */
11015 aopOp (IC_JTCOND (ic), ic, FALSE);
11016 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11017 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11018 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11020 // (MB) what if B is in use???
11021 wassertl(!BINUSE, "B was in use");
11022 emitcode ("mov", "b,%s", l);
11025 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11029 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11030 emitcode ("movc", "a,@a+pc");
11031 emitcode ("push", "acc");
11034 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11035 emitcode ("movc", "a,@a+pc");
11036 emitcode ("push", "acc");
11040 /* this scales up to n<=255, but needs two more bytes
11041 and changes dptr */
11042 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11043 emitcode ("movc", "a,@a+dptr");
11044 emitcode ("push", "acc");
11047 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11048 emitcode ("movc", "a,@a+dptr");
11049 emitcode ("push", "acc");
11052 emitcode ("ret", "");
11054 /* now generate jump table, LSB */
11055 emitLabel (jtablo);
11056 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11057 jtab = setNextItem (IC_JTLABELS (ic)))
11058 emitcode (".db", "%05d$", jtab->key + 100);
11060 /* now generate jump table, MSB */
11061 emitLabel (jtabhi);
11062 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11063 jtab = setNextItem (IC_JTLABELS (ic)))
11064 emitcode (".db", "%05d$>>8", jtab->key + 100);
11068 /*-----------------------------------------------------------------*/
11069 /* genCast - gen code for casting */
11070 /*-----------------------------------------------------------------*/
11072 genCast (iCode * ic)
11074 operand *result = IC_RESULT (ic);
11075 sym_link *ctype = operandType (IC_LEFT (ic));
11076 sym_link *rtype = operandType (IC_RIGHT (ic));
11077 operand *right = IC_RIGHT (ic);
11080 D (emitcode (";", "genCast"));
11082 /* if they are equivalent then do nothing */
11083 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11086 aopOp (right, ic, FALSE);
11087 aopOp (result, ic, FALSE);
11089 /* if the result is a bit (and not a bitfield) */
11090 if (IS_BIT (OP_SYMBOL (result)->type))
11092 /* if the right size is a literal then
11093 we know what the value is */
11094 if (AOP_TYPE (right) == AOP_LIT)
11096 if (((int) operandLitValue (right)))
11097 aopPut (result, one, 0);
11099 aopPut (result, zero, 0);
11104 /* the right is also a bit variable */
11105 if (AOP_TYPE (right) == AOP_CRY)
11107 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11108 aopPut (result, "c", 0);
11112 /* we need to or */
11114 aopPut (result, "a", 0);
11118 /* if they are the same size : or less */
11119 if (AOP_SIZE (result) <= AOP_SIZE (right))
11122 /* if they are in the same place */
11123 if (sameRegs (AOP (right), AOP (result)))
11126 /* if they in different places then copy */
11127 size = AOP_SIZE (result);
11132 aopGet (right, offset, FALSE, FALSE),
11139 /* if the result is of type pointer */
11140 if (IS_PTR (ctype))
11144 sym_link *type = operandType (right);
11145 sym_link *etype = getSpec (type);
11147 /* pointer to generic pointer */
11148 if (IS_GENPTR (ctype))
11152 p_type = DCL_TYPE (type);
11156 if (SPEC_SCLS(etype)==S_REGISTER) {
11157 // let's assume it is a generic pointer
11160 /* we have to go by the storage class */
11161 p_type = PTR_TYPE (SPEC_OCLS (etype));
11165 /* the first two bytes are known */
11166 size = GPTRSIZE - 1;
11171 aopGet (right, offset, FALSE, FALSE),
11175 /* the last byte depending on type */
11177 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11182 // pointerTypeToGPByte will have bitched.
11186 sprintf(gpValStr, "#0x%x", gpVal);
11187 aopPut (result, gpValStr, GPTRSIZE - 1);
11192 /* just copy the pointers */
11193 size = AOP_SIZE (result);
11198 aopGet (right, offset, FALSE, FALSE),
11205 /* so we now know that the size of destination is greater
11206 than the size of the source */
11207 /* we move to result for the size of source */
11208 size = AOP_SIZE (right);
11213 aopGet (right, offset, FALSE, FALSE),
11218 /* now depending on the sign of the source && destination */
11219 size = AOP_SIZE (result) - AOP_SIZE (right);
11220 /* if unsigned or not an integral type */
11221 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11224 aopPut (result, zero, offset++);
11228 /* we need to extend the sign :{ */
11229 char *l = aopGet (right, AOP_SIZE (right) - 1,
11232 emitcode ("rlc", "a");
11233 emitcode ("subb", "a,acc");
11235 aopPut (result, "a", offset++);
11238 /* we are done hurray !!!! */
11241 freeAsmop (result, NULL, ic, TRUE);
11242 freeAsmop (right, NULL, ic, TRUE);
11245 /*-----------------------------------------------------------------*/
11246 /* genDjnz - generate decrement & jump if not zero instrucion */
11247 /*-----------------------------------------------------------------*/
11249 genDjnz (iCode * ic, iCode * ifx)
11251 symbol *lbl, *lbl1;
11255 /* if the if condition has a false label
11256 then we cannot save */
11257 if (IC_FALSE (ifx))
11260 /* if the minus is not of the form a = a - 1 */
11261 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11262 !IS_OP_LITERAL (IC_RIGHT (ic)))
11265 if (operandLitValue (IC_RIGHT (ic)) != 1)
11268 /* if the size of this greater than one then no
11270 if (getSize (operandType (IC_RESULT (ic))) > 1)
11273 /* otherwise we can save BIG */
11275 D (emitcode (";", "genDjnz"));
11277 lbl = newiTempLabel (NULL);
11278 lbl1 = newiTempLabel (NULL);
11280 aopOp (IC_RESULT (ic), ic, FALSE);
11282 if (AOP_NEEDSACC(IC_RESULT(ic)))
11284 /* If the result is accessed indirectly via
11285 * the accumulator, we must explicitly write
11286 * it back after the decrement.
11288 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11290 if (strcmp(rByte, "a"))
11292 /* Something is hopelessly wrong */
11293 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11294 __FILE__, __LINE__);
11295 /* We can just give up; the generated code will be inefficient,
11296 * but what the hey.
11298 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11301 emitcode ("dec", "%s", rByte);
11302 aopPut (IC_RESULT (ic), rByte, 0);
11303 emitcode ("jnz", "%05d$", lbl->key + 100);
11305 else if (IS_AOP_PREG (IC_RESULT (ic)))
11307 emitcode ("dec", "%s",
11308 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11309 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11310 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11311 ifx->generated = 1;
11312 emitcode ("jnz", "%05d$", lbl->key + 100);
11316 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11319 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11321 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11324 if (!ifx->generated)
11325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11326 ifx->generated = 1;
11330 /*-----------------------------------------------------------------*/
11331 /* genReceive - generate code for a receive iCode */
11332 /*-----------------------------------------------------------------*/
11334 genReceive (iCode * ic)
11336 int size = getSize (operandType (IC_RESULT (ic)));
11339 D (emitcode (";", "genReceive"));
11341 if (ic->argreg == 1)
11342 { /* first parameter */
11343 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11344 isOperandInPagedSpace (IC_RESULT (ic))) &&
11345 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11346 IS_TRUE_SYMOP (IC_RESULT (ic))))
11349 int receivingA = 0;
11352 for (offset = 0; offset<size; offset++)
11353 if (!strcmp (fReturn[offset], "a"))
11358 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11360 for (offset = size-1; offset>0; offset--)
11361 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11362 emitcode("mov","a,%s", fReturn[0]);
11364 aopOp (IC_RESULT (ic), ic, FALSE);
11366 aopPut (IC_RESULT (ic), "a", offset);
11367 for (offset = 1; offset<size; offset++)
11368 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11374 if (getTempRegs(tempRegs, size, ic))
11376 for (offset = 0; offset<size; offset++)
11377 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11378 aopOp (IC_RESULT (ic), ic, FALSE);
11379 for (offset = 0; offset<size; offset++)
11380 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11385 offset = fReturnSizeMCS51 - size;
11388 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11389 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11392 aopOp (IC_RESULT (ic), ic, FALSE);
11393 size = AOP_SIZE (IC_RESULT (ic));
11397 emitcode ("pop", "acc");
11398 aopPut (IC_RESULT (ic), "a", offset++);
11404 aopOp (IC_RESULT (ic), ic, FALSE);
11406 assignResultValue (IC_RESULT (ic), NULL);
11409 else if (ic->argreg > 12)
11410 { /* bit parameters */
11411 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11413 aopOp (IC_RESULT (ic), ic, FALSE);
11414 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11415 outBitC(IC_RESULT (ic));
11419 { /* other parameters */
11421 aopOp (IC_RESULT (ic), ic, FALSE);
11422 rb1off = ic->argreg;
11425 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11430 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11433 /*-----------------------------------------------------------------*/
11434 /* genDummyRead - generate code for dummy read of volatiles */
11435 /*-----------------------------------------------------------------*/
11437 genDummyRead (iCode * ic)
11442 D (emitcode(";", "genDummyRead"));
11444 op = IC_RIGHT (ic);
11445 if (op && IS_SYMOP (op))
11447 aopOp (op, ic, FALSE);
11449 /* if the result is a bit */
11450 if (AOP_TYPE (op) == AOP_CRY)
11451 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11454 /* bit variables done */
11456 size = AOP_SIZE (op);
11460 MOVA (aopGet (op, offset, FALSE, FALSE));
11465 freeAsmop (op, NULL, ic, TRUE);
11469 if (op && IS_SYMOP (op))
11471 aopOp (op, ic, FALSE);
11473 /* if the result is a bit */
11474 if (AOP_TYPE (op) == AOP_CRY)
11475 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11478 /* bit variables done */
11480 size = AOP_SIZE (op);
11484 MOVA (aopGet (op, offset, FALSE, FALSE));
11489 freeAsmop (op, NULL, ic, TRUE);
11493 /*-----------------------------------------------------------------*/
11494 /* genCritical - generate code for start of a critical sequence */
11495 /*-----------------------------------------------------------------*/
11497 genCritical (iCode *ic)
11499 symbol *tlbl = newiTempLabel (NULL);
11501 D (emitcode(";", "genCritical"));
11503 if (IC_RESULT (ic))
11505 aopOp (IC_RESULT (ic), ic, TRUE);
11506 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11507 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11508 aopPut (IC_RESULT (ic), zero, 0);
11510 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11514 emitcode ("setb", "c");
11515 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11516 emitcode ("clr", "c");
11518 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11522 /*-----------------------------------------------------------------*/
11523 /* genEndCritical - generate code for end of a critical sequence */
11524 /*-----------------------------------------------------------------*/
11526 genEndCritical (iCode *ic)
11528 D(emitcode("; genEndCritical",""));
11532 aopOp (IC_RIGHT (ic), ic, FALSE);
11533 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11535 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11536 emitcode ("mov", "ea,c");
11540 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11541 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11542 emitcode ("rrc", "a");
11543 emitcode ("mov", "ea,c");
11545 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11549 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11550 emitcode ("mov", "ea,c");
11554 /*-----------------------------------------------------------------*/
11555 /* gen51Code - generate code for 8051 based controllers */
11556 /*-----------------------------------------------------------------*/
11558 gen51Code (iCode * lic)
11562 /* int cseq = 0; */
11564 _G.currentFunc = NULL;
11565 lineHead = lineCurr = NULL;
11567 /* print the allocation information */
11568 if (allocInfo && currFunc)
11569 printAllocInfo (currFunc, codeOutFile);
11570 /* if debug information required */
11571 if (options.debug && currFunc)
11573 debugFile->writeFunction (currFunc, lic);
11575 /* stack pointer name */
11576 if (options.useXstack)
11582 for (ic = lic; ic; ic = ic->next)
11584 _G.current_iCode = ic;
11586 if (ic->lineno && cln != ic->lineno)
11590 debugFile->writeCLine (ic);
11592 if (!options.noCcodeInAsm) {
11593 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11594 printCLine(ic->filename, ic->lineno));
11599 if (ic->seqPoint && ic->seqPoint != cseq)
11601 emitcode ("", "; sequence point %d", ic->seqPoint);
11602 cseq = ic->seqPoint;
11605 if (options.iCodeInAsm) {
11606 char regsInUse[80];
11610 for (i=0; i<8; i++) {
11611 sprintf (®sInUse[i],
11612 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11615 strcpy (regsInUse, "--------");
11616 for (i=0; i < 8; i++) {
11617 if (bitVectBitValue (ic->rMask, i))
11619 int offset = regs8051[i].offset;
11620 regsInUse[offset] = offset + '0'; /* show rMask */
11624 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11626 /* if the result is marked as
11627 spilt and rematerializable or code for
11628 this has already been generated then
11630 if (resultRemat (ic) || ic->generated)
11633 /* depending on the operation */
11653 /* IPOP happens only when trying to restore a
11654 spilt live range, if there is an ifx statement
11655 following this pop then the if statement might
11656 be using some of the registers being popped which
11657 would destory the contents of the register so
11658 we need to check for this condition and handle it */
11660 ic->next->op == IFX &&
11661 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11662 genIfx (ic->next, ic);
11680 genEndFunction (ic);
11700 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11717 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11721 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11728 /* note these two are xlated by algebraic equivalence
11729 in decorateType() in SDCCast.c */
11730 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11731 "got '>=' or '<=' shouldn't have come here");
11735 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11747 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11751 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11755 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11791 genRightShift (ic);
11794 case GET_VALUE_AT_ADDRESS:
11796 hasInc (IC_LEFT (ic), ic,
11797 getSize (operandType (IC_RESULT (ic)))),
11798 ifxForOp (IC_RESULT (ic), ic) );
11802 if (POINTER_SET (ic))
11804 hasInc (IC_RESULT (ic), ic,
11805 getSize (operandType (IC_RIGHT (ic)))));
11831 addSet (&_G.sendSet, ic);
11834 case DUMMY_READ_VOLATILE:
11843 genEndCritical (ic);
11855 _G.current_iCode = NULL;
11857 /* now we are ready to call the
11858 peep hole optimizer */
11859 if (!options.nopeep)
11860 peepHole (&lineHead);
11862 /* now do the actual printing */
11863 printLine (lineHead, codeOutFile);