1 /*-------------------------------------------------------------------------
2 SDCCgen51.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 AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72 AOP_TYPE(x) == AOP_R0))
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
75 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
78 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
82 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
84 #define R0INB _G.bu.bs.r0InB
85 #define R1INB _G.bu.bs.r1InB
86 #define OPINB _G.bu.bs.OpInB
87 #define BINUSE _G.bu.BInUse
97 short r0InB : 2;//2 so we can see it overflow
98 short r1InB : 2;//2 so we can see it overflow
99 short OpInB : 2;//2 so we can see it overflow
108 iCode *current_iCode;
113 static char *rb1regs[] = {
114 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
117 extern int mcs51_ptrRegReq;
118 extern int mcs51_nRegs;
119 extern FILE *codeOutFile;
120 static void saveRBank (int, iCode *, bool);
122 #define RESULTONSTACK(x) \
123 (IC_RESULT(x) && IC_RESULT(x)->aop && \
124 IC_RESULT(x)->aop->type == AOP_STK )
126 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
127 #define CLRC emitcode("clr","c")
128 #define SETC emitcode("setb","c")
130 static lineNode *lineHead = NULL;
131 static lineNode *lineCurr = NULL;
133 static unsigned char SLMask[] =
134 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
135 0xE0, 0xC0, 0x80, 0x00};
136 static unsigned char SRMask[] =
137 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
138 0x07, 0x03, 0x01, 0x00};
145 /*-----------------------------------------------------------------*/
146 /* emitcode - writes the code into a file : for now it is simple */
147 /*-----------------------------------------------------------------*/
149 emitcode (char *inst, const char *fmt,...)
152 char lb[INITIAL_INLINEASM];
160 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
162 SNPRINTF (lb, sizeof(lb), "%s", inst);
163 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
166 tvsprintf (lb, sizeof(lb), fmt, ap);
168 while (isspace (*lbp))
172 lineCurr = (lineCurr ?
173 connectLine (lineCurr, newLineNode (lb)) :
174 (lineHead = newLineNode (lb)));
175 lineCurr->isInline = _G.inLine;
176 lineCurr->isDebug = _G.debugLine;
177 lineCurr->ic = _G.current_iCode;
178 lineCurr->isComment = (*lbp==';');
182 /*-----------------------------------------------------------------*/
183 /* mcs51_emitDebuggerSymbol - associate the current code location */
184 /* with a debugger symbol */
185 /*-----------------------------------------------------------------*/
187 mcs51_emitDebuggerSymbol (char * debugSym)
190 emitcode ("", "%s ==.", debugSym);
194 /*-----------------------------------------------------------------*/
195 /* mova - moves specified value into accumulator */
196 /*-----------------------------------------------------------------*/
200 /* do some early peephole optimization */
201 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
204 emitcode("mov","a,%s", x);
207 /*-----------------------------------------------------------------*/
208 /* pushB - saves register B if necessary */
209 /*-----------------------------------------------------------------*/
213 bool pushedB = FALSE;
217 emitcode ("push", "b");
218 // printf("B was in use !\n");
228 /*-----------------------------------------------------------------*/
229 /* popB - restores value of register B if necessary */
230 /*-----------------------------------------------------------------*/
236 emitcode ("pop", "b");
244 /*-----------------------------------------------------------------*/
245 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
246 /*-----------------------------------------------------------------*/
248 getFreePtr (iCode * ic, asmop ** aopp, bool result)
253 /* the logic: if r0 & r1 used in the instruction
254 then we are in trouble otherwise */
256 /* first check if r0 & r1 are used by this
257 instruction, in which case we are in trouble */
258 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
259 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
264 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
265 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
267 /* if no usage of r0 then return it */
270 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
271 (*aopp)->type = AOP_R0;
273 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
276 /* if no usage of r1 then return it */
279 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
280 (*aopp)->type = AOP_R1;
282 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
285 /* now we know they both have usage */
286 /* if r0 not used in this instruction */
289 /* push it if not already pushed */
292 emitcode ("mov", "b,%s",
293 mcs51_regWithIdx (R0_IDX)->dname);
296 else if (!_G.r0Pushed)
298 emitcode ("push", "%s",
299 mcs51_regWithIdx (R0_IDX)->dname);
303 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
304 (*aopp)->type = AOP_R0;
306 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
309 /* if r1 not used then */
313 /* push it if not already pushed */
316 emitcode ("mov", "b,%s",
317 mcs51_regWithIdx (R1_IDX)->dname);
320 else if (!_G.r1Pushed)
322 emitcode ("push", "%s",
323 mcs51_regWithIdx (R1_IDX)->dname);
327 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
328 (*aopp)->type = AOP_R1;
329 return mcs51_regWithIdx (R1_IDX);
332 /* I said end of world, but not quite end of world yet */
334 /* we can push it on the stack */
335 (*aopp)->type = AOP_STK;
338 /* in the case that result AND left AND right needs a pointer reg
339 we can safely use the result's */
340 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
341 (*aopp)->type = AOP_R0;
342 return mcs51_regWithIdx (R0_IDX);
344 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
345 (*aopp)->type = AOP_R1;
346 return mcs51_regWithIdx (R1_IDX);
350 /* now this is REALLY the end of the world */
351 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
352 "getFreePtr should never reach here");
357 /*-----------------------------------------------------------------*/
358 /* getTempRegs - initialize an array of pointers to GPR registers */
359 /* that are not in use. Returns 1 if the requested */
360 /* number of registers were available, 0 otherwise. */
361 /*-----------------------------------------------------------------*/
363 getTempRegs(regs **tempRegs, int size, iCode *ic)
370 ic = _G.current_iCode;
376 freeRegs = newBitVect(8);
377 bitVectSetBit (freeRegs, R2_IDX);
378 bitVectSetBit (freeRegs, R3_IDX);
379 bitVectSetBit (freeRegs, R4_IDX);
380 bitVectSetBit (freeRegs, R5_IDX);
381 bitVectSetBit (freeRegs, R6_IDX);
382 bitVectSetBit (freeRegs, R7_IDX);
384 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
386 bitVect * newfreeRegs;
387 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
388 freeBitVect(freeRegs);
389 freeRegs = newfreeRegs;
391 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
394 for (i=0; i<freeRegs->size; i++)
396 if (bitVectBitValue(freeRegs,i))
397 tempRegs[offset++] = mcs51_regWithIdx(i);
400 freeBitVect(freeRegs);
405 freeBitVect(freeRegs);
410 /*-----------------------------------------------------------------*/
411 /* newAsmop - creates a new asmOp */
412 /*-----------------------------------------------------------------*/
414 newAsmop (short type)
418 aop = Safe_calloc (1, sizeof (asmop));
423 /*-----------------------------------------------------------------*/
424 /* pointerCode - returns the code for a pointer type */
425 /*-----------------------------------------------------------------*/
427 pointerCode (sym_link * etype)
430 return PTR_TYPE (SPEC_OCLS (etype));
434 /*-----------------------------------------------------------------*/
435 /* leftRightUseAcc - returns size of accumulator use by operands */
436 /*-----------------------------------------------------------------*/
438 leftRightUseAcc(iCode *ic)
447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
448 "null iCode pointer");
455 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
458 size = getSize (OP_SYMBOL (op)->type);
463 else if (ic->op == JUMPTABLE)
466 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
469 size = getSize (OP_SYMBOL (op)->type);
477 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
480 size = getSize (OP_SYMBOL (op)->type);
485 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488 size = getSize (OP_SYMBOL (op)->type);
500 /*-----------------------------------------------------------------*/
501 /* aopForSym - for a true symbol */
502 /*-----------------------------------------------------------------*/
504 aopForSym (iCode * ic, symbol * sym, bool result)
509 wassertl (ic != NULL, "Got a null iCode");
510 wassertl (sym != NULL, "Got a null symbol");
512 space = SPEC_OCLS (sym->etype);
514 /* if already has one */
518 /* assign depending on the storage class */
519 /* if it is on the stack or indirectly addressable */
520 /* space we need to assign either r0 or r1 to it */
521 if (sym->onStack || sym->iaccess)
523 sym->aop = aop = newAsmop (0);
524 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
525 aop->size = getSize (sym->type);
527 /* now assign the address of the variable to
528 the pointer register */
529 if (aop->type != AOP_STK)
534 char offset = ((sym->stack < 0) ?
535 ((char) (sym->stack - _G.nRegsSaved)) :
536 ((char) sym->stack)) & 0xff;
538 if ((offset >= -3) && (offset <= 3))
540 emitcode ("mov", "%s,%s",
541 aop->aopu.aop_ptr->name, SYM_BP (sym));
544 emitcode ("dec", aop->aopu.aop_ptr->name);
549 emitcode ("inc", aop->aopu.aop_ptr->name);
555 if (_G.accInUse || leftRightUseAcc (ic))
556 emitcode ("push", "acc");
557 emitcode ("mov", "a,%s", SYM_BP (sym));
558 emitcode ("add", "a,#0x%02x", offset);
559 emitcode ("mov", "%s,a",
560 aop->aopu.aop_ptr->name);
561 if (_G.accInUse || leftRightUseAcc (ic))
562 emitcode ("pop", "acc");
566 emitcode ("mov", "%s,#%s",
567 aop->aopu.aop_ptr->name,
569 aop->paged = space->paged;
572 aop->aopu.aop_stk = sym->stack;
576 /* if in bit space */
577 if (IN_BITSPACE (space))
579 sym->aop = aop = newAsmop (AOP_CRY);
580 aop->aopu.aop_dir = sym->rname;
581 aop->size = getSize (sym->type);
584 /* if it is in direct space */
585 if (IN_DIRSPACE (space))
587 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
588 //printTypeChainRaw(sym->type, NULL);
589 //printf("space = %s\n", space ? space->sname : "NULL");
590 sym->aop = aop = newAsmop (AOP_DIR);
591 aop->aopu.aop_dir = sym->rname;
592 aop->size = getSize (sym->type);
596 /* special case for a function */
597 if (IS_FUNC (sym->type))
599 sym->aop = aop = newAsmop (AOP_IMMD);
600 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
601 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
602 aop->size = getSize (sym->type);
606 /* only remaining is far space */
607 /* in which case DPTR gets the address */
608 sym->aop = aop = newAsmop (AOP_DPTR);
609 emitcode ("mov", "dptr,#%s", sym->rname);
610 aop->size = getSize (sym->type);
612 /* if it is in code space */
613 if (IN_CODESPACE (space))
619 /*-----------------------------------------------------------------*/
620 /* aopForRemat - rematerialzes an object */
621 /*-----------------------------------------------------------------*/
623 aopForRemat (symbol * sym)
625 iCode *ic = sym->rematiCode;
626 asmop *aop = newAsmop (AOP_IMMD);
633 val += (int) operandLitValue (IC_RIGHT (ic));
634 else if (ic->op == '-')
635 val -= (int) operandLitValue (IC_RIGHT (ic));
636 else if (IS_CAST_ICODE(ic)) {
637 sym_link *from_type = operandType(IC_RIGHT(ic));
638 aop->aopu.aop_immd.from_cast_remat = 1;
639 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
640 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
644 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
648 sprintf (buffer, "(%s %c 0x%04x)",
649 OP_SYMBOL (IC_LEFT (ic))->rname,
650 val >= 0 ? '+' : '-',
653 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
655 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
656 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
657 /* set immd2 field if required */
658 if (aop->aopu.aop_immd.from_cast_remat) {
659 sprintf(buffer,"#0x%02x",ptr_type);
660 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
661 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
667 /*-----------------------------------------------------------------*/
668 /* regsInCommon - two operands have some registers in common */
669 /*-----------------------------------------------------------------*/
671 regsInCommon (operand * op1, operand * op2)
676 /* if they have registers in common */
677 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
680 sym1 = OP_SYMBOL (op1);
681 sym2 = OP_SYMBOL (op2);
683 if (sym1->nRegs == 0 || sym2->nRegs == 0)
686 for (i = 0; i < sym1->nRegs; i++)
692 for (j = 0; j < sym2->nRegs; j++)
697 if (sym2->regs[j] == sym1->regs[i])
705 /*-----------------------------------------------------------------*/
706 /* operandsEqu - equivalent */
707 /*-----------------------------------------------------------------*/
709 operandsEqu (operand * op1, operand * op2)
713 /* if they're not symbols */
714 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
717 sym1 = OP_SYMBOL (op1);
718 sym2 = OP_SYMBOL (op2);
720 /* if both are itemps & one is spilt
721 and the other is not then false */
722 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
723 sym1->isspilt != sym2->isspilt)
726 /* if they are the same */
730 /* if they have the same rname */
731 if (sym1->rname[0] && sym2->rname[0]
732 && strcmp (sym1->rname, sym2->rname) == 0)
735 /* if left is a tmp & right is not */
736 if (IS_ITEMP (op1) &&
739 (sym1->usl.spillLoc == sym2))
742 if (IS_ITEMP (op2) &&
746 (sym2->usl.spillLoc == sym1))
752 /*-----------------------------------------------------------------*/
753 /* sameRegs - two asmops have the same registers */
754 /*-----------------------------------------------------------------*/
756 sameRegs (asmop * aop1, asmop * aop2)
763 if (aop1->type != AOP_REG ||
764 aop2->type != AOP_REG)
767 if (aop1->size != aop2->size)
770 for (i = 0; i < aop1->size; i++)
771 if (aop1->aopu.aop_reg[i] !=
772 aop2->aopu.aop_reg[i])
778 /*-----------------------------------------------------------------*/
779 /* aopOp - allocates an asmop for an operand : */
780 /*-----------------------------------------------------------------*/
782 aopOp (operand * op, iCode * ic, bool result)
791 /* if this a literal */
792 if (IS_OP_LITERAL (op))
794 op->aop = aop = newAsmop (AOP_LIT);
795 aop->aopu.aop_lit = op->operand.valOperand;
796 aop->size = getSize (operandType (op));
800 /* if already has a asmop then continue */
804 /* if the underlying symbol has a aop */
805 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
807 op->aop = OP_SYMBOL (op)->aop;
811 /* if this is a true symbol */
812 if (IS_TRUE_SYMOP (op))
814 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
818 /* this is a temporary : this has
824 e) can be a return use only */
826 sym = OP_SYMBOL (op);
828 /* if the type is a conditional */
829 if (sym->regType == REG_CND)
831 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
836 /* if it is spilt then two situations
838 b) has a spill location */
839 if (sym->isspilt || sym->nRegs == 0)
842 /* rematerialize it NOW */
845 sym->aop = op->aop = aop =
847 aop->size = getSize (sym->type);
854 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
855 aop->size = getSize (sym->type);
856 for (i = 0; i < 2; i++)
857 aop->aopu.aop_str[i] = accUse[i];
865 aop = op->aop = sym->aop = newAsmop (AOP_STR);
866 aop->size = getSize (sym->type);
867 for (i = 0; i < fReturnSizeMCS51; i++)
868 aop->aopu.aop_str[i] = fReturn[i];
872 if (sym->usl.spillLoc)
874 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
876 /* force a new aop if sizes differ */
877 sym->usl.spillLoc->aop = NULL;
879 sym->aop = op->aop = aop =
880 aopForSym (ic, sym->usl.spillLoc, result);
881 aop->size = getSize (sym->type);
885 /* else must be a dummy iTemp */
886 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
887 aop->size = getSize (sym->type);
891 /* must be in a register */
892 sym->aop = op->aop = aop = newAsmop (AOP_REG);
893 aop->size = sym->nRegs;
894 for (i = 0; i < sym->nRegs; i++)
895 aop->aopu.aop_reg[i] = sym->regs[i];
898 /*-----------------------------------------------------------------*/
899 /* freeAsmop - free up the asmop given to an operand */
900 /*----------------------------------------------------------------*/
902 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
919 /* depending on the asmop type only three cases need work AOP_RO
920 , AOP_R1 && AOP_STK */
926 emitcode ("mov", "r0,b");
929 else if (_G.r0Pushed)
933 emitcode ("pop", "ar0");
937 bitVectUnSetBit (ic->rUsed, R0_IDX);
943 emitcode ("mov", "r1,b");
950 emitcode ("pop", "ar1");
954 bitVectUnSetBit (ic->rUsed, R1_IDX);
960 int stk = aop->aopu.aop_stk + aop->size - 1;
961 bitVectUnSetBit (ic->rUsed, R0_IDX);
962 bitVectUnSetBit (ic->rUsed, R1_IDX);
964 getFreePtr (ic, &aop, FALSE);
968 emitcode ("mov", "a,_bp");
969 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
970 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
974 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
979 emitcode ("pop", "acc");
980 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
983 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
986 freeAsmop (op, NULL, ic, TRUE);
989 emitcode ("pop", "ar1");
995 emitcode ("pop", "ar0");
1002 /* all other cases just dealloc */
1008 OP_SYMBOL (op)->aop = NULL;
1009 /* if the symbol has a spill */
1011 SPIL_LOC (op)->aop = NULL;
1016 /*------------------------------------------------------------------*/
1017 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1018 /* pop r0 or r1 off stack if pushed */
1019 /*------------------------------------------------------------------*/
1021 freeForBranchAsmop (operand * op)
1041 emitcode ("mov", "r0,b");
1043 else if (_G.r0Pushed)
1045 emitcode ("pop", "ar0");
1052 emitcode ("mov", "r1,b");
1054 else if (_G.r1Pushed)
1056 emitcode ("pop", "ar1");
1063 int stk = aop->aopu.aop_stk + aop->size - 1;
1065 emitcode ("mov", "b,r0");
1068 emitcode ("mov", "a,_bp");
1069 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1070 emitcode ("mov", "r0,a");
1074 emitcode ("mov", "r0,_bp");
1079 emitcode ("pop", "acc");
1080 emitcode ("mov", "@r0,a");
1083 emitcode ("dec", "r0");
1085 emitcode ("mov", "r0,b");
1091 /*-----------------------------------------------------------------*/
1092 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1093 /* clobber the accumulator */
1094 /*-----------------------------------------------------------------*/
1096 aopGetUsesAcc (operand * oper, int offset)
1098 asmop * aop = AOP (oper);
1100 if (offset > (aop->size - 1))
1118 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1129 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1135 /* Error case --- will have been caught already */
1141 /*-----------------------------------------------------------------*/
1142 /* aopGet - for fetching value of the aop */
1143 /*-----------------------------------------------------------------*/
1145 aopGet (operand * oper, int offset, bool bit16, bool dname)
1149 asmop * aop = AOP (oper);
1151 /* offset is greater than
1153 if (offset > (aop->size - 1) &&
1154 aop->type != AOP_LIT)
1157 /* depending on type */
1165 /* if we need to increment it */
1166 while (offset > aop->coff)
1168 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1172 while (offset < aop->coff)
1174 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1181 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1182 return (dname ? "acc" : "a");
1184 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1185 rs = Safe_calloc (1, strlen (s) + 1);
1190 if (aop->code && aop->coff==0 && offset>=1) {
1191 emitcode ("mov", "a,#0x%02x", offset);
1192 emitcode ("movc", "a,@a+dptr");
1193 return (dname ? "acc" : "a");
1196 while (offset > aop->coff)
1198 emitcode ("inc", "dptr");
1202 while (offset < aop->coff)
1204 emitcode ("lcall", "__decdptr");
1211 emitcode ("clr", "a");
1212 emitcode ("movc", "a,@a+dptr");
1216 emitcode ("movx", "a,@dptr");
1218 return (dname ? "acc" : "a");
1222 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1223 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1225 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1227 sprintf (s, "#(%s >> %d)",
1228 aop->aopu.aop_immd.aop_immd1,
1232 aop->aopu.aop_immd.aop_immd1);
1233 rs = Safe_calloc (1, strlen (s) + 1);
1238 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1239 sprintf (s, "(%s >> %d)",
1240 aop->aopu.aop_dir, offset * 8);
1242 sprintf (s, "(%s + %d)",
1246 sprintf (s, "%s", aop->aopu.aop_dir);
1247 rs = Safe_calloc (1, strlen (s) + 1);
1253 return aop->aopu.aop_reg[offset]->dname;
1255 return aop->aopu.aop_reg[offset]->name;
1258 emitcode ("clr", "a");
1259 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1260 emitcode ("rlc", "a");
1261 return (dname ? "acc" : "a");
1264 if (!offset && dname)
1266 return aop->aopu.aop_str[offset];
1269 return aopLiteral (aop->aopu.aop_lit, offset);
1273 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1277 return aop->aopu.aop_str[offset];
1281 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1282 "aopget got unsupported aop->type");
1285 /*-----------------------------------------------------------------*/
1286 /* aopPut - puts a string for a aop and indicates if acc is in use */
1287 /*-----------------------------------------------------------------*/
1289 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1292 bool accuse = FALSE;
1293 asmop * aop = AOP (result);
1295 if (aop->size && offset > (aop->size - 1))
1297 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1298 "aopPut got offset > aop->size");
1302 /* will assign value to value */
1303 /* depending on where it is ofcourse */
1307 MOVA (s); /* read s in case it was volatile */
1312 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1313 sprintf (d, "(%s >> %d)",
1314 aop->aopu.aop_dir, offset * 8);
1316 sprintf (d, "(%s + %d)",
1317 aop->aopu.aop_dir, offset);
1319 sprintf (d, "%s", aop->aopu.aop_dir);
1321 if (strcmp (d, s) ||
1323 emitcode ("mov", "%s,%s", d, s);
1324 if (!strcmp (d, "acc"))
1330 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1331 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1334 strcmp (s, "r0") == 0 ||
1335 strcmp (s, "r1") == 0 ||
1336 strcmp (s, "r2") == 0 ||
1337 strcmp (s, "r3") == 0 ||
1338 strcmp (s, "r4") == 0 ||
1339 strcmp (s, "r5") == 0 ||
1340 strcmp (s, "r6") == 0 ||
1341 strcmp (s, "r7") == 0)
1342 emitcode ("mov", "%s,%s",
1343 aop->aopu.aop_reg[offset]->dname, s);
1345 emitcode ("mov", "%s,%s",
1346 aop->aopu.aop_reg[offset]->name, s);
1353 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1354 "aopPut writing to code space");
1358 while (offset > aop->coff)
1361 emitcode ("inc", "dptr");
1364 while (offset < aop->coff)
1367 emitcode ("lcall", "__decdptr");
1372 /* if not in accumulator */
1375 emitcode ("movx", "@dptr,a");
1380 while (offset > aop->coff)
1383 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1385 while (offset < aop->coff)
1388 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1395 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1401 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1403 else if (strcmp (s, "r0") == 0 ||
1404 strcmp (s, "r1") == 0 ||
1405 strcmp (s, "r2") == 0 ||
1406 strcmp (s, "r3") == 0 ||
1407 strcmp (s, "r4") == 0 ||
1408 strcmp (s, "r5") == 0 ||
1409 strcmp (s, "r6") == 0 ||
1410 strcmp (s, "r7") == 0)
1413 sprintf (buffer, "a%s", s);
1414 emitcode ("mov", "@%s,%s",
1415 aop->aopu.aop_ptr->name, buffer);
1418 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1423 if (strcmp (s, "a") == 0)
1424 emitcode ("push", "acc");
1428 emitcode ("push", "acc");
1430 emitcode ("push", s);
1436 /* if not bit variable */
1437 if (!aop->aopu.aop_dir)
1439 /* inefficient: move carry into A and use jz/jnz */
1440 emitcode ("clr", "a");
1441 emitcode ("rlc", "a");
1447 emitcode ("clr", "%s", aop->aopu.aop_dir);
1449 emitcode ("setb", "%s", aop->aopu.aop_dir);
1450 else if (!strcmp (s, "c"))
1451 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1455 /* set C, if a >= 1 */
1456 emitcode ("add", "a,#0xff");
1457 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1464 if (strcmp (aop->aopu.aop_str[offset], s) ||
1466 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1472 if (!offset && (strcmp (s, "acc") == 0) &&
1476 if (strcmp (aop->aopu.aop_str[offset], s) &&
1478 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1482 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1483 "aopPut got unsupported aop->type");
1492 /*-----------------------------------------------------------------*/
1493 /* pointToEnd :- points to the last byte of the operand */
1494 /*-----------------------------------------------------------------*/
1496 pointToEnd (asmop * aop)
1502 aop->coff = count = (aop->size - 1);
1508 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1512 emitcode ("inc", "dptr");
1519 /*-----------------------------------------------------------------*/
1520 /* reAdjustPreg - points a register back to where it should */
1521 /*-----------------------------------------------------------------*/
1523 reAdjustPreg (asmop * aop)
1525 if ((aop->coff==0) || aop->size <= 1)
1533 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1538 emitcode ("lcall", "__decdptr");
1545 /*-----------------------------------------------------------------*/
1546 /* opIsGptr: returns non-zero if the passed operand is */
1547 /* a generic pointer type. */
1548 /*-----------------------------------------------------------------*/
1550 opIsGptr (operand * op)
1552 sym_link *type = operandType (op);
1554 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1561 /*-----------------------------------------------------------------*/
1562 /* getDataSize - get the operand data size */
1563 /*-----------------------------------------------------------------*/
1565 getDataSize (operand * op)
1568 size = AOP_SIZE (op);
1569 if (size == GPTRSIZE)
1571 sym_link *type = operandType (op);
1572 if (IS_GENPTR (type))
1574 /* generic pointer; arithmetic operations
1575 * should ignore the high byte (pointer type).
1583 /*-----------------------------------------------------------------*/
1584 /* outAcc - output Acc */
1585 /*-----------------------------------------------------------------*/
1587 outAcc (operand * result)
1590 size = getDataSize (result);
1593 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1596 /* unsigned or positive */
1599 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1604 /*-----------------------------------------------------------------*/
1605 /* outBitC - output a bit C */
1606 /*-----------------------------------------------------------------*/
1608 outBitC (operand * result)
1610 /* if the result is bit */
1611 if (AOP_TYPE (result) == AOP_CRY)
1612 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1615 emitcode ("clr", "a");
1616 emitcode ("rlc", "a");
1621 /*-----------------------------------------------------------------*/
1622 /* toBoolean - emit code for orl a,operator(sizeop) */
1623 /*-----------------------------------------------------------------*/
1625 toBoolean (operand * oper)
1627 int size = AOP_SIZE (oper) - 1;
1629 bool AccUsed = FALSE;
1632 while (!AccUsed && size--)
1634 AccUsed |= aopGetUsesAcc(oper, offset++);
1637 size = AOP_SIZE (oper) - 1;
1639 MOVA (aopGet (oper, 0, FALSE, FALSE));
1640 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1643 emitcode("mov", "b,a");
1646 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1647 emitcode ("orl", "b,a");
1649 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1650 emitcode ("orl", "a,b");
1657 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1663 /*-----------------------------------------------------------------*/
1664 /* genNot - generate code for ! operation */
1665 /*-----------------------------------------------------------------*/
1671 D(emitcode ("; genNot",""));
1673 /* assign asmOps to operand & result */
1674 aopOp (IC_LEFT (ic), ic, FALSE);
1675 aopOp (IC_RESULT (ic), ic, TRUE);
1677 /* if in bit space then a special case */
1678 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1680 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1681 emitcode ("cpl", "c");
1682 outBitC (IC_RESULT (ic));
1686 toBoolean (IC_LEFT (ic));
1688 tlbl = newiTempLabel (NULL);
1689 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1690 emitcode ("", "%05d$:", tlbl->key + 100);
1691 outBitC (IC_RESULT (ic));
1694 /* release the aops */
1695 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1700 /*-----------------------------------------------------------------*/
1701 /* genCpl - generate code for complement */
1702 /*-----------------------------------------------------------------*/
1709 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1711 D(emitcode (";", "genCpl"));
1713 /* assign asmOps to operand & result */
1714 aopOp (IC_LEFT (ic), ic, FALSE);
1715 aopOp (IC_RESULT (ic), ic, TRUE);
1717 /* special case if in bit space */
1718 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1722 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1723 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1725 /* promotion rules are responsible for this strange result:
1726 bit -> int -> ~int -> bit
1727 uchar -> int -> ~int -> bit
1729 werror(W_COMPLEMENT);
1730 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1734 tlbl=newiTempLabel(NULL);
1735 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1736 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1737 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1738 IS_AOP_PREG (IC_LEFT (ic)))
1740 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1745 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1747 emitcode ("", "%05d$:", tlbl->key + 100);
1748 outBitC (IC_RESULT(ic));
1752 size = AOP_SIZE (IC_RESULT (ic));
1755 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1757 emitcode ("cpl", "a");
1758 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1763 /* release the aops */
1764 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1765 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* genUminusFloat - unary minus for floating points */
1770 /*-----------------------------------------------------------------*/
1772 genUminusFloat (operand * op, operand * result)
1774 int size, offset = 0;
1777 D(emitcode ("; genUminusFloat",""));
1779 /* for this we just copy and then flip the bit */
1781 size = AOP_SIZE (op) - 1;
1786 aopGet (op, offset, FALSE, FALSE),
1788 isOperandVolatile (result, FALSE));
1792 l = aopGet (op, offset, FALSE, FALSE);
1796 emitcode ("cpl", "acc.7");
1797 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1800 /*-----------------------------------------------------------------*/
1801 /* genUminus - unary minus code generation */
1802 /*-----------------------------------------------------------------*/
1804 genUminus (iCode * ic)
1807 sym_link *optype, *rtype;
1810 D(emitcode ("; genUminus",""));
1813 aopOp (IC_LEFT (ic), ic, FALSE);
1814 aopOp (IC_RESULT (ic), ic, TRUE);
1816 /* if both in bit space then special
1818 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1819 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1822 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1823 emitcode ("cpl", "c");
1824 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1828 optype = operandType (IC_LEFT (ic));
1829 rtype = operandType (IC_RESULT (ic));
1831 /* if float then do float stuff */
1832 if (IS_FLOAT (optype))
1834 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1838 /* otherwise subtract from zero */
1839 size = AOP_SIZE (IC_LEFT (ic));
1844 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1845 if (!strcmp (l, "a"))
1849 emitcode ("cpl", "a");
1850 emitcode ("addc", "a,#0");
1856 emitcode ("clr", "a");
1857 emitcode ("subb", "a,%s", l);
1859 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1862 /* if any remaining bytes in the result */
1863 /* we just need to propagate the sign */
1864 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1866 emitcode ("rlc", "a");
1867 emitcode ("subb", "a,acc");
1869 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1873 /* release the aops */
1874 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1875 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1878 /*-----------------------------------------------------------------*/
1879 /* saveRegisters - will look for a call and save the registers */
1880 /*-----------------------------------------------------------------*/
1882 saveRegisters (iCode * lic)
1889 for (ic = lic; ic; ic = ic->next)
1890 if (ic->op == CALL || ic->op == PCALL)
1895 fprintf (stderr, "found parameter push with no function call\n");
1899 /* if the registers have been saved already or don't need to be then
1903 if (IS_SYMOP(IC_LEFT(ic)) &&
1904 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1905 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1908 /* save the registers in use at this time but skip the
1909 ones for the result */
1910 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1911 mcs51_rUmaskForOp (IC_RESULT(ic)));
1914 if (options.useXstack)
1916 int count = bitVectnBitsOn (rsave);
1920 i = bitVectFirstBit (rsave);
1921 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1922 emitcode ("mov", "r0,%s", spname);
1923 emitcode ("inc", "%s", spname);// allocate before use
1924 emitcode ("movx", "@r0,a");
1925 if (bitVectBitValue (rsave, R0_IDX))
1926 emitcode ("mov", "r0,a");
1928 else if (count != 0)
1930 if (bitVectBitValue (rsave, R0_IDX))
1932 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1934 emitcode ("mov", "r0,%s", spname);
1936 emitcode ("add", "a,#%d", count);
1937 emitcode ("mov", "%s,a", spname);
1938 for (i = 0; i < mcs51_nRegs; i++)
1940 if (bitVectBitValue (rsave, i))
1944 emitcode ("pop", "acc");
1945 emitcode ("push", "acc");
1949 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1951 emitcode ("movx", "@r0,a");
1954 emitcode ("inc", "r0");
1958 if (bitVectBitValue (rsave, R0_IDX))
1960 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1965 for (i = 0; i < mcs51_nRegs; i++)
1967 if (bitVectBitValue (rsave, i))
1968 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1972 /*-----------------------------------------------------------------*/
1973 /* unsaveRegisters - pop the pushed registers */
1974 /*-----------------------------------------------------------------*/
1976 unsaveRegisters (iCode * ic)
1981 /* restore the registers in use at this time but skip the
1982 ones for the result */
1983 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1984 mcs51_rUmaskForOp (IC_RESULT(ic)));
1986 if (options.useXstack)
1988 int count = bitVectnBitsOn (rsave);
1992 emitcode ("mov", "r0,%s", spname);
1993 emitcode ("dec", "r0");
1994 emitcode ("movx", "a,@r0");
1995 i = bitVectFirstBit (rsave);
1996 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1997 emitcode ("dec", "%s", spname);
1999 else if (count != 0)
2001 emitcode ("mov", "r0,%s", spname);
2002 for (i = mcs51_nRegs; i >= 0; i--)
2004 if (bitVectBitValue (rsave, i))
2006 emitcode ("dec", "r0");
2007 emitcode ("movx", "a,@r0");
2009 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
2011 emitcode ("push", "acc");
2014 emitcode ("mov", "%s,r0", spname);
2015 if (bitVectBitValue (rsave, R0_IDX))
2017 emitcode ("pop", "ar0");
2022 for (i = mcs51_nRegs; i >= 0; i--)
2024 if (bitVectBitValue (rsave, i))
2025 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2030 /*-----------------------------------------------------------------*/
2032 /*-----------------------------------------------------------------*/
2034 pushSide (operand * oper, int size)
2039 char *l = aopGet (oper, offset++, FALSE, TRUE);
2040 if (AOP_TYPE (oper) != AOP_REG &&
2041 AOP_TYPE (oper) != AOP_DIR &&
2045 emitcode ("push", "acc");
2049 emitcode ("push", "%s", l);
2054 /*-----------------------------------------------------------------*/
2055 /* assignResultValue - also indicates if acc is in use afterwards */
2056 /*-----------------------------------------------------------------*/
2058 assignResultValue (operand * oper)
2061 int size = AOP_SIZE (oper);
2062 bool accuse = FALSE;
2066 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2073 /*-----------------------------------------------------------------*/
2074 /* genXpush - pushes onto the external stack */
2075 /*-----------------------------------------------------------------*/
2077 genXpush (iCode * ic)
2079 asmop *aop = newAsmop (0);
2081 int size, offset = 0;
2083 D(emitcode ("; genXpush",""));
2085 aopOp (IC_LEFT (ic), ic, FALSE);
2086 r = getFreePtr (ic, &aop, FALSE);
2088 size = AOP_SIZE (IC_LEFT (ic));
2092 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2093 emitcode ("mov", "%s,%s", r->name, spname);
2094 emitcode ("inc", "%s", spname); // allocate space first
2095 emitcode ("movx", "@%s,a", r->name);
2099 // allocate space first
2100 emitcode ("mov", "%s,%s", r->name, spname);
2102 emitcode ("add", "a,#%d", size);
2103 emitcode ("mov", "%s,a", spname);
2107 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2108 emitcode ("movx", "@%s,a", r->name);
2109 emitcode ("inc", "%s", r->name);
2113 freeAsmop (NULL, aop, ic, TRUE);
2114 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2117 /*-----------------------------------------------------------------*/
2118 /* genIpush - generate code for pushing this gets a little complex */
2119 /*-----------------------------------------------------------------*/
2121 genIpush (iCode * ic)
2123 int size, offset = 0;
2126 D(emitcode ("; genIpush",""));
2128 /* if this is not a parm push : ie. it is spill push
2129 and spill push is always done on the local stack */
2133 /* and the item is spilt then do nothing */
2134 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2137 aopOp (IC_LEFT (ic), ic, FALSE);
2138 size = AOP_SIZE (IC_LEFT (ic));
2139 /* push it on the stack */
2142 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2148 emitcode ("push", "%s", l);
2153 /* this is a paramter push: in this case we call
2154 the routine to find the call and save those
2155 registers that need to be saved */
2158 /* if use external stack then call the external
2159 stack pushing routine */
2160 if (options.useXstack)
2166 /* then do the push */
2167 aopOp (IC_LEFT (ic), ic, FALSE);
2169 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2170 size = AOP_SIZE (IC_LEFT (ic));
2174 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2175 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2176 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2180 emitcode ("push", "acc");
2183 emitcode ("push", "%s", l);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2189 /*-----------------------------------------------------------------*/
2190 /* genIpop - recover the registers: can happen only for spilling */
2191 /*-----------------------------------------------------------------*/
2193 genIpop (iCode * ic)
2197 D(emitcode ("; genIpop",""));
2199 /* if the temp was not pushed then */
2200 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2203 aopOp (IC_LEFT (ic), ic, FALSE);
2204 size = AOP_SIZE (IC_LEFT (ic));
2205 offset = (size - 1);
2207 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2210 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2213 /*-----------------------------------------------------------------*/
2214 /* saveRBank - saves an entire register bank on the stack */
2215 /*-----------------------------------------------------------------*/
2217 saveRBank (int bank, iCode * ic, bool pushPsw)
2220 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2224 if (options.useXstack)
2228 /* Assume r0 is available for use. */
2229 r = mcs51_regWithIdx (R0_IDX);;
2234 r = getFreePtr (ic, &aop, FALSE);
2236 // allocate space first
2237 emitcode ("mov", "%s,%s", r->name, spname);
2239 emitcode ("add", "a,#%d", count);
2240 emitcode ("mov", "%s,a", spname);
2243 for (i = 0; i < mcs51_nRegs; i++)
2245 if (options.useXstack)
2247 emitcode ("mov", "a,(%s+%d)",
2248 regs8051[i].base, 8 * bank + regs8051[i].offset);
2249 emitcode ("movx", "@%s,a", r->name);
2251 emitcode ("inc", "%s", r->name);
2254 emitcode ("push", "(%s+%d)",
2255 regs8051[i].base, 8 * bank + regs8051[i].offset);
2260 if (options.useXstack)
2262 emitcode ("mov", "a,psw");
2263 emitcode ("movx", "@%s,a", r->name);
2268 emitcode ("push", "psw");
2271 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2276 freeAsmop (NULL, aop, ic, TRUE);
2285 /*-----------------------------------------------------------------*/
2286 /* unsaveRBank - restores the register bank from stack */
2287 /*-----------------------------------------------------------------*/
2289 unsaveRBank (int bank, iCode * ic, bool popPsw)
2295 if (options.useXstack)
2299 /* Assume r0 is available for use. */
2300 r = mcs51_regWithIdx (R0_IDX);;
2305 r = getFreePtr (ic, &aop, FALSE);
2307 emitcode ("mov", "%s,%s", r->name, spname);
2312 if (options.useXstack)
2314 emitcode ("dec", "%s", r->name);
2315 emitcode ("movx", "a,@%s", r->name);
2316 emitcode ("mov", "psw,a");
2320 emitcode ("pop", "psw");
2324 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2326 if (options.useXstack)
2328 emitcode ("dec", "%s", r->name);
2329 emitcode ("movx", "a,@%s", r->name);
2330 emitcode ("mov", "(%s+%d),a",
2331 regs8051[i].base, 8 * bank + regs8051[i].offset);
2335 emitcode ("pop", "(%s+%d)",
2336 regs8051[i].base, 8 * bank + regs8051[i].offset);
2340 if (options.useXstack)
2342 emitcode ("mov", "%s,%s", spname, r->name);
2347 freeAsmop (NULL, aop, ic, TRUE);
2351 /*-----------------------------------------------------------------*/
2352 /* genSend - gen code for SEND */
2353 /*-----------------------------------------------------------------*/
2354 static void genSend(set *sendSet)
2359 for (sic = setFirstItem (sendSet); sic;
2360 sic = setNextItem (sendSet)) {
2361 int size, offset = 0;
2362 aopOp (IC_LEFT (sic), sic, FALSE);
2363 size = AOP_SIZE (IC_LEFT (sic));
2365 if (sic->argreg == 1) {
2367 char *l = aopGet (IC_LEFT (sic), offset,
2369 if (strcmp (l, fReturn[offset]))
2370 emitcode ("mov", "%s,%s", fReturn[offset], l);
2376 emitcode ("mov","b1_%d,%s",rb1_count++,
2377 aopGet (IC_LEFT (sic), offset++,FALSE, FALSE));
2380 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2384 /*-----------------------------------------------------------------*/
2385 /* genCall - generates a call statement */
2386 /*-----------------------------------------------------------------*/
2388 genCall (iCode * ic)
2391 // bool restoreBank = FALSE;
2392 bool swapBanks = FALSE;
2393 bool accuse = FALSE;
2394 bool accPushed = FALSE;
2396 D(emitcode("; genCall",""));
2398 dtype = operandType (IC_LEFT (ic));
2399 /* if send set is not empty then assign */
2402 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2403 genSend(reverseSet(_G.sendSet));
2405 genSend(_G.sendSet);
2411 /* if we are calling a not _naked function that is not using
2412 the same register bank then we need to save the
2413 destination registers on the stack */
2414 dtype = operandType (IC_LEFT (ic));
2415 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2416 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2417 !IFFUNC_ISISR (dtype))
2422 /* if caller saves & we have not saved then */
2428 emitcode ("mov", "psw,#0x%02x",
2429 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2433 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2435 if (IFFUNC_CALLEESAVES(dtype))
2437 werror (E_BANKED_WITH_CALLEESAVES);
2441 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2442 OP_SYMBOL (IC_LEFT (ic))->rname :
2443 OP_SYMBOL (IC_LEFT (ic))->name);
2445 emitcode ("mov", "r0,#%s", l);
2446 emitcode ("mov", "r1,#(%s >> 8)", l);
2447 emitcode ("mov", "r2,#(%s >> 16)", l);
2448 emitcode ("lcall", "__sdcc_banked_call");
2453 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2454 OP_SYMBOL (IC_LEFT (ic))->rname :
2455 OP_SYMBOL (IC_LEFT (ic))->name));
2460 emitcode ("mov", "psw,#0x%02x",
2461 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2464 /* if we need assign a result value */
2465 if ((IS_ITEMP (IC_RESULT (ic)) &&
2466 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2467 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2468 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2469 IS_TRUE_SYMOP (IC_RESULT (ic)))
2473 aopOp (IC_RESULT (ic), ic, FALSE);
2476 accuse = assignResultValue (IC_RESULT (ic));
2478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2481 /* adjust the stack for parameters if required */
2485 if (ic->parmBytes > 3)
2489 emitcode ("push", "acc");
2493 emitcode ("mov", "a,%s", spname);
2494 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2495 emitcode ("mov", "%s,a", spname);
2497 /* unsaveRegisters from xstack needs acc, but */
2498 /* unsaveRegisters from stack needs this popped */
2499 if (accPushed && !options.useXstack)
2501 emitcode ("pop", "acc");
2506 for (i = 0; i < ic->parmBytes; i++)
2507 emitcode ("dec", "%s", spname);
2510 /* if we hade saved some registers then unsave them */
2511 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2513 if (accuse && !accPushed && options.useXstack)
2515 /* xstack needs acc, but doesn't touch normal stack */
2516 emitcode ("push", "acc");
2519 unsaveRegisters (ic);
2522 // /* if register bank was saved then pop them */
2524 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2527 emitcode ("pop", "acc");
2530 /*-----------------------------------------------------------------*/
2531 /* -10l - generates a call by pointer statement */
2532 /*-----------------------------------------------------------------*/
2534 genPcall (iCode * ic)
2538 symbol *rlbl = newiTempLabel (NULL);
2539 // bool restoreBank=FALSE;
2540 bool swapBanks = FALSE;
2542 D(emitcode("; genPCall",""));
2544 /* if caller saves & we have not saved then */
2548 /* if we are calling a not _naked function that is not using
2549 the same register bank then we need to save the
2550 destination registers on the stack */
2551 dtype = operandType (IC_LEFT (ic))->next;
2552 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2553 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554 !IFFUNC_ISISR (dtype))
2556 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2557 // restoreBank=TRUE;
2559 // need caution message to user here
2562 etype = getSpec(dtype);
2563 if (IS_LITERAL(etype))
2565 /* if send set is not empty then assign */
2568 genSend(reverseSet(_G.sendSet));
2574 emitcode ("mov", "psw,#0x%02x",
2575 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2578 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2580 if (IFFUNC_CALLEESAVES(dtype))
2582 werror (E_BANKED_WITH_CALLEESAVES);
2586 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2588 emitcode ("mov", "r0,#%s", l);
2589 emitcode ("mov", "r1,#(%s >> 8)", l);
2590 emitcode ("mov", "r2,#(%s >> 16)", l);
2591 emitcode ("lcall", "__sdcc_banked_call");
2596 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2601 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2603 if (IFFUNC_CALLEESAVES(dtype))
2605 werror (E_BANKED_WITH_CALLEESAVES);
2609 aopOp (IC_LEFT (ic), ic, FALSE);
2613 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2614 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2615 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2619 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2620 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2621 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2622 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2625 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2627 /* if send set is not empty then assign */
2630 genSend(reverseSet(_G.sendSet));
2636 emitcode ("mov", "psw,#0x%02x",
2637 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2641 emitcode ("lcall", "__sdcc_banked_call");
2646 /* push the return address on to the stack */
2647 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2648 emitcode ("push", "acc");
2649 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2650 emitcode ("push", "acc");
2652 /* now push the calling address */
2653 aopOp (IC_LEFT (ic), ic, FALSE);
2655 pushSide (IC_LEFT (ic), FPTRSIZE);
2657 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2659 /* if send set is not empty the assign */
2662 genSend(reverseSet(_G.sendSet));
2668 emitcode ("mov", "psw,#0x%02x",
2669 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2673 emitcode ("ret", "");
2674 emitcode ("", "%05d$:", (rlbl->key + 100));
2679 emitcode ("mov", "psw,#0x%02x",
2680 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2683 /* if we need assign a result value */
2684 if ((IS_ITEMP (IC_RESULT (ic)) &&
2685 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2686 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2687 IS_TRUE_SYMOP (IC_RESULT (ic)))
2691 aopOp (IC_RESULT (ic), ic, FALSE);
2694 assignResultValue (IC_RESULT (ic));
2696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699 /* adjust the stack for parameters if
2704 if (ic->parmBytes > 3)
2706 emitcode ("mov", "a,%s", spname);
2707 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2708 emitcode ("mov", "%s,a", spname);
2711 for (i = 0; i < ic->parmBytes; i++)
2712 emitcode ("dec", "%s", spname);
2716 // /* if register bank was saved then unsave them */
2718 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2720 /* if we hade saved some registers then
2722 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2723 unsaveRegisters (ic);
2726 /*-----------------------------------------------------------------*/
2727 /* resultRemat - result is rematerializable */
2728 /*-----------------------------------------------------------------*/
2730 resultRemat (iCode * ic)
2732 if (SKIP_IC (ic) || ic->op == IFX)
2735 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2737 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2738 if (sym->remat && !POINTER_SET (ic))
2745 #if defined(__BORLANDC__) || defined(_MSC_VER)
2746 #define STRCASECMP stricmp
2748 #define STRCASECMP strcasecmp
2751 /*-----------------------------------------------------------------*/
2752 /* inExcludeList - return 1 if the string is in exclude Reg list */
2753 /*-----------------------------------------------------------------*/
2755 regsCmp(void *p1, void *p2)
2757 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2761 inExcludeList (char *s)
2763 const char *p = setFirstItem(options.excludeRegsSet);
2765 if (p == NULL || STRCASECMP(p, "none") == 0)
2769 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2772 /*-----------------------------------------------------------------*/
2773 /* genFunction - generated code for function entry */
2774 /*-----------------------------------------------------------------*/
2776 genFunction (iCode * ic)
2778 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2780 bool switchedPSW = FALSE;
2781 int calleesaves_saved_register = -1;
2782 int stackAdjust = sym->stack;
2783 int accIsFree = sym->recvSize < 4;
2784 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2785 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2788 /* create the function header */
2789 emitcode (";", "-----------------------------------------");
2790 emitcode (";", " function %s", sym->name);
2791 emitcode (";", "-----------------------------------------");
2793 emitcode ("", "%s:", sym->rname);
2794 ftype = operandType (IC_LEFT (ic));
2795 _G.currentFunc = sym;
2797 if (IFFUNC_ISNAKED(ftype))
2799 emitcode(";", "naked function: no prologue.");
2803 /* here we need to generate the equates for the
2804 register bank if required */
2805 if (FUNC_REGBANK (ftype) != rbank)
2809 rbank = FUNC_REGBANK (ftype);
2810 for (i = 0; i < mcs51_nRegs; i++)
2812 if (strcmp (regs8051[i].base, "0") == 0)
2813 emitcode ("", "%s = 0x%02x",
2815 8 * rbank + regs8051[i].offset);
2817 emitcode ("", "%s = %s + 0x%02x",
2820 8 * rbank + regs8051[i].offset);
2824 /* if this is an interrupt service routine then
2825 save acc, b, dpl, dph */
2826 if (IFFUNC_ISISR (sym->type))
2829 if (!inExcludeList ("acc"))
2830 emitcode ("push", "acc");
2831 if (!inExcludeList ("b"))
2832 emitcode ("push", "b");
2833 if (!inExcludeList ("dpl"))
2834 emitcode ("push", "dpl");
2835 if (!inExcludeList ("dph"))
2836 emitcode ("push", "dph");
2837 /* if this isr has no bank i.e. is going to
2838 run with bank 0 , then we need to save more
2840 if (!FUNC_REGBANK (sym->type))
2843 /* if this function does not call any other
2844 function then we can be economical and
2845 save only those registers that are used */
2846 if (!IFFUNC_HASFCALL(sym->type))
2850 /* if any registers used */
2853 /* save the registers used */
2854 for (i = 0; i < sym->regsUsed->size; i++)
2856 if (bitVectBitValue (sym->regsUsed, i))
2857 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2864 /* this function has a function call. We cannot
2865 determines register usage so we will have to push the
2867 saveRBank (0, ic, FALSE);
2868 if (options.parms_in_bank1) {
2870 for (i=0; i < 8 ; i++ ) {
2871 emitcode ("push","%s",rb1regs[i]);
2878 /* This ISR uses a non-zero bank.
2880 * We assume that the bank is available for our
2883 * However, if this ISR calls a function which uses some
2884 * other bank, we must save that bank entirely.
2886 unsigned long banksToSave = 0;
2888 if (IFFUNC_HASFCALL(sym->type))
2891 #define MAX_REGISTER_BANKS 4
2896 for (i = ic; i; i = i->next)
2898 if (i->op == ENDFUNCTION)
2900 /* we got to the end OK. */
2908 dtype = operandType (IC_LEFT(i));
2910 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2912 /* Mark this bank for saving. */
2913 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2915 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2919 banksToSave |= (1 << FUNC_REGBANK(dtype));
2922 /* And note that we don't need to do it in
2930 /* This is a mess; we have no idea what
2931 * register bank the called function might
2934 * The only thing I can think of to do is
2935 * throw a warning and hope.
2937 werror(W_FUNCPTR_IN_USING_ISR);
2941 if (banksToSave && options.useXstack)
2943 /* Since we aren't passing it an ic,
2944 * saveRBank will assume r0 is available to abuse.
2946 * So switch to our (trashable) bank now, so
2947 * the caller's R0 isn't trashed.
2949 emitcode ("push", "psw");
2950 emitcode ("mov", "psw,#0x%02x",
2951 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2955 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2957 if (banksToSave & (1 << ix))
2959 saveRBank(ix, NULL, FALSE);
2963 // TODO: this needs a closer look
2964 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2967 /* Set the register bank to the desired value if nothing else */
2968 /* has done so yet. */
2971 emitcode ("push", "psw");
2972 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2977 /* This is a non-ISR function. The caller has already switched register */
2978 /* banks, if necessary, so just handle the callee-saves option. */
2980 /* if callee-save to be used for this function
2981 then save the registers being used in this function */
2982 if (IFFUNC_CALLEESAVES(sym->type))
2986 /* if any registers used */
2989 /* save the registers used */
2990 for (i = 0; i < sym->regsUsed->size; i++)
2992 if (bitVectBitValue (sym->regsUsed, i))
2994 /* remember one saved register for later usage */
2995 if (calleesaves_saved_register < 0)
2996 calleesaves_saved_register = i;
2997 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
3008 if (options.useXstack)
3010 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3012 emitcode ("mov", "r0,%s", spname);
3013 emitcode ("inc", "%s", spname);
3014 emitcode ("xch", "a,_bpx");
3015 emitcode ("movx", "@r0,a");
3016 emitcode ("inc", "r0");
3017 emitcode ("mov", "a,r0");
3018 emitcode ("xch", "a,_bpx");
3022 emitcode ("push", "_bp"); /* save the callers stack */
3023 emitcode ("mov", "_bp,sp");
3028 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3030 /* set up the stack */
3031 emitcode ("push", "_bp"); /* save the callers stack */
3032 emitcode ("mov", "_bp,sp");
3037 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3038 /* before setting up the stack frame completely. */
3039 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3041 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3045 if (rsym && rsym->regType == REG_CND)
3047 if (rsym && (rsym->accuse || rsym->ruonly))
3049 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3050 rsym = rsym->usl.spillLoc;
3053 /* If the RECEIVE operand immediately spills to the first entry on the */
3054 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3055 /* rather than the usual @r0/r1 machinations. */
3056 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3060 _G.current_iCode = ric;
3061 D(emitcode ("; genReceive",""));
3062 for (ofs=0; ofs < sym->recvSize; ofs++)
3064 if (!strcmp (fReturn[ofs], "a"))
3065 emitcode ("push", "acc");
3067 emitcode ("push", fReturn[ofs]);
3069 stackAdjust -= sym->recvSize;
3072 assert (stackAdjust>=0);
3075 _G.current_iCode = ic;
3079 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3080 /* to free up the accumulator. */
3081 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3085 _G.current_iCode = ric;
3086 D(emitcode ("; genReceive",""));
3087 for (ofs=0; ofs < sym->recvSize; ofs++)
3089 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3091 _G.current_iCode = ic;
3097 /* adjust the stack for the function */
3100 int i = stackAdjust;
3102 werror (W_STACK_OVERFLOW, sym->name);
3104 if (i > 3 && accIsFree)
3106 emitcode ("mov", "a,sp");
3107 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3108 emitcode ("mov", "sp,a");
3112 /* The accumulator is not free, so we will need another register */
3113 /* to clobber. No need to worry about a possible conflict with */
3114 /* the above early RECEIVE optimizations since they would have */
3115 /* freed the accumulator if they were generated. */
3117 if (IFFUNC_CALLEESAVES(sym->type))
3119 /* if it's a callee-saves function we need a saved register */
3120 if (calleesaves_saved_register >= 0)
3122 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3123 emitcode ("mov", "a,sp");
3124 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3125 emitcode ("mov", "sp,a");
3126 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3129 /* do it the hard way */
3131 emitcode ("inc", "sp");
3135 /* not callee-saves, we can clobber r0 */
3136 emitcode ("mov", "r0,a");
3137 emitcode ("mov", "a,sp");
3138 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3139 emitcode ("mov", "sp,a");
3140 emitcode ("mov", "a,r0");
3145 emitcode ("inc", "sp");
3150 char i = ((char) sym->xstack & 0xff);
3152 if (i > 3 && accIsFree)
3154 emitcode ("mov", "a,_spx");
3155 emitcode ("add", "a,#0x%02x", i);
3156 emitcode ("mov", "_spx,a");
3160 emitcode ("push", "acc");
3161 emitcode ("mov", "a,_spx");
3162 emitcode ("add", "a,#0x%02x", i);
3163 emitcode ("mov", "_spx,a");
3164 emitcode ("pop", "acc");
3169 emitcode ("inc", "_spx");
3173 /* if critical function then turn interrupts off */
3174 if (IFFUNC_ISCRITICAL (ftype))
3176 symbol *tlbl = newiTempLabel (NULL);
3177 emitcode ("setb", "c");
3178 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3179 emitcode ("clr", "c");
3180 emitcode ("", "%05d$:", (tlbl->key + 100));
3181 emitcode ("push", "psw"); /* save old ea via c in psw */
3185 /*-----------------------------------------------------------------*/
3186 /* genEndFunction - generates epilogue for functions */
3187 /*-----------------------------------------------------------------*/
3189 genEndFunction (iCode * ic)
3191 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3192 lineNode *lnp = lineCurr;
3194 bitVect *regsUsedPrologue;
3195 bitVect *regsUnneeded;
3198 _G.currentFunc = NULL;
3199 if (IFFUNC_ISNAKED(sym->type))
3201 emitcode(";", "naked function: no epilogue.");
3202 if (options.debug && currFunc)
3203 debugFile->writeEndFunction (currFunc, ic, 0);
3207 if (IFFUNC_ISCRITICAL (sym->type))
3209 emitcode ("pop", "psw"); /* restore ea via c in psw */
3210 emitcode ("mov", "ea,c");
3213 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3215 if (options.useXstack)
3219 emitcode ("mov", "sp,_bp");
3220 emitcode ("pop", "_bp");
3222 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3224 emitcode ("xch", "a,_bpx");
3225 emitcode ("mov", "r0,a");
3226 emitcode ("dec", "r0");
3227 emitcode ("movx", "a,@r0");
3228 emitcode ("xch", "a,_bpx");
3229 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3232 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3234 emitcode ("mov", "sp,_bp");
3235 emitcode ("pop", "_bp");
3239 /* restore the register bank */
3240 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3242 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3243 || !options.useXstack)
3245 /* Special case of ISR using non-zero bank with useXstack
3248 emitcode ("pop", "psw");
3252 if (IFFUNC_ISISR (sym->type))
3255 /* now we need to restore the registers */
3256 /* if this isr has no bank i.e. is going to
3257 run with bank 0 , then we need to save more
3259 if (!FUNC_REGBANK (sym->type))
3261 /* if this function does not call any other
3262 function then we can be economical and
3263 save only those registers that are used */
3264 if (!IFFUNC_HASFCALL(sym->type))
3268 /* if any registers used */
3271 /* save the registers used */
3272 for (i = sym->regsUsed->size; i >= 0; i--)
3274 if (bitVectBitValue (sym->regsUsed, i))
3275 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3281 if (options.parms_in_bank1) {
3283 for (i = 7 ; i >= 0 ; i-- ) {
3284 emitcode ("pop","%s",rb1regs[i]);
3287 /* this function has a function call cannot
3288 determines register usage so we will have to pop the
3290 unsaveRBank (0, ic, FALSE);
3295 /* This ISR uses a non-zero bank.
3297 * Restore any register banks saved by genFunction
3300 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3303 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3305 if (savedBanks & (1 << ix))
3307 unsaveRBank(ix, NULL, FALSE);
3311 if (options.useXstack)
3313 /* Restore bank AFTER calling unsaveRBank,
3314 * since it can trash r0.
3316 emitcode ("pop", "psw");
3320 if (!inExcludeList ("dph"))
3321 emitcode ("pop", "dph");
3322 if (!inExcludeList ("dpl"))
3323 emitcode ("pop", "dpl");
3324 if (!inExcludeList ("b"))
3325 emitcode ("pop", "b");
3326 if (!inExcludeList ("acc"))
3327 emitcode ("pop", "acc");
3329 /* if debug then send end of function */
3330 if (options.debug && currFunc)
3332 debugFile->writeEndFunction (currFunc, ic, 1);
3335 emitcode ("reti", "");
3339 if (IFFUNC_CALLEESAVES(sym->type))
3343 /* if any registers used */
3346 /* save the registers used */
3347 for (i = sym->regsUsed->size; i >= 0; i--)
3349 if (bitVectBitValue (sym->regsUsed, i) ||
3350 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3351 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3354 else if (mcs51_ptrRegReq)
3356 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3357 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3362 /* if debug then send end of function */
3363 if (options.debug && currFunc)
3365 debugFile->writeEndFunction (currFunc, ic, 1);
3368 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3370 emitcode ("ljmp", "__sdcc_banked_ret");
3374 emitcode ("ret", "");
3378 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3381 /* If this was an interrupt handler using bank 0 that called another */
3382 /* function, then all registers must be saved; nothing to optimized. */
3383 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3384 && !FUNC_REGBANK(sym->type))
3387 /* There are no push/pops to optimize if not callee-saves or ISR */
3388 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3391 /* If there were stack parameters, we cannot optimize without also */
3392 /* fixing all of the stack offsets; this is too dificult to consider. */
3393 if (FUNC_HASSTACKPARM(sym->type))
3396 /* Compute the registers actually used */
3397 regsUsed = newBitVect (mcs51_nRegs);
3398 regsUsedPrologue = newBitVect (mcs51_nRegs);
3401 if (lnp->ic && lnp->ic->op == FUNCTION)
3402 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3404 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3406 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3407 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3414 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3415 && !bitVectBitValue (regsUsed, CND_IDX))
3417 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3418 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3419 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3420 bitVectUnSetBit (regsUsed, CND_IDX);
3423 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3425 /* If this was an interrupt handler that called another function */
3426 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3427 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3429 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3430 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3431 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3432 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3433 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3436 /* Remove the unneeded push/pops */
3437 regsUnneeded = newBitVect (mcs51_nRegs);
3440 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3442 if (!strncmp(lnp->line, "push", 4))
3444 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3445 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3447 connectLine (lnp->prev, lnp->next);
3448 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3451 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3453 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3454 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3456 connectLine (lnp->prev, lnp->next);
3457 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3464 for (idx = 0; idx < regsUnneeded->size; idx++)
3465 if (bitVectBitValue (regsUnneeded, idx))
3466 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3468 freeBitVect (regsUnneeded);
3469 freeBitVect (regsUsed);
3470 freeBitVect (regsUsedPrologue);
3473 /*-----------------------------------------------------------------*/
3474 /* genRet - generate code for return statement */
3475 /*-----------------------------------------------------------------*/
3479 int size, offset = 0, pushed = 0;
3481 D(emitcode ("; genRet",""));
3483 /* if we have no return value then
3484 just generate the "ret" */
3488 /* we have something to return then
3489 move the return value into place */
3490 aopOp (IC_LEFT (ic), ic, FALSE);
3491 size = AOP_SIZE (IC_LEFT (ic));
3496 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3499 l = aopGet (IC_LEFT (ic), offset++,
3501 emitcode ("push", "%s", l);
3506 l = aopGet (IC_LEFT (ic), offset,
3508 if (strcmp (fReturn[offset], l))
3509 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3518 if (strcmp (fReturn[pushed], "a"))
3519 emitcode ("pop", fReturn[pushed]);
3521 emitcode ("pop", "acc");
3524 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3527 /* generate a jump to the return label
3528 if the next is not the return statement */
3529 if (!(ic->next && ic->next->op == LABEL &&
3530 IC_LABEL (ic->next) == returnLabel))
3532 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3536 /*-----------------------------------------------------------------*/
3537 /* genLabel - generates a label */
3538 /*-----------------------------------------------------------------*/
3540 genLabel (iCode * ic)
3542 /* special case never generate */
3543 if (IC_LABEL (ic) == entryLabel)
3546 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3549 /*-----------------------------------------------------------------*/
3550 /* genGoto - generates a ljmp */
3551 /*-----------------------------------------------------------------*/
3553 genGoto (iCode * ic)
3555 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3558 /*-----------------------------------------------------------------*/
3559 /* findLabelBackwards: walks back through the iCode chain looking */
3560 /* for the given label. Returns number of iCode instructions */
3561 /* between that label and given ic. */
3562 /* Returns zero if label not found. */
3563 /*-----------------------------------------------------------------*/
3565 findLabelBackwards (iCode * ic, int key)
3574 /* If we have any pushes or pops, we cannot predict the distance.
3575 I don't like this at all, this should be dealt with in the
3577 if (ic->op == IPUSH || ic->op == IPOP) {
3581 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3590 /*-----------------------------------------------------------------*/
3591 /* genPlusIncr :- does addition with increment if possible */
3592 /*-----------------------------------------------------------------*/
3594 genPlusIncr (iCode * ic)
3596 unsigned int icount;
3597 unsigned int size = getDataSize (IC_RESULT (ic));
3599 /* will try to generate an increment */
3600 /* if the right side is not a literal
3602 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3605 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3607 D(emitcode ("; genPlusIncr",""));
3609 /* if increment >=16 bits in register or direct space */
3610 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3611 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3612 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3620 /* If the next instruction is a goto and the goto target
3621 * is < 10 instructions previous to this, we can generate
3622 * jumps straight to that target.
3624 if (ic->next && ic->next->op == GOTO
3625 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3626 && labelRange <= 10)
3628 emitcode (";", "tail increment optimized");
3629 tlbl = IC_LABEL (ic->next);
3634 tlbl = newiTempLabel (NULL);
3637 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3638 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3639 IS_AOP_PREG (IC_RESULT (ic)))
3640 emitcode ("cjne", "%s,#0x00,%05d$",
3641 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3645 emitcode ("clr", "a");
3646 emitcode ("cjne", "a,%s,%05d$",
3647 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3651 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3654 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3655 IS_AOP_PREG (IC_RESULT (ic)))
3656 emitcode ("cjne", "%s,#0x00,%05d$",
3657 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3660 emitcode ("cjne", "a,%s,%05d$",
3661 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3664 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3668 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3669 IS_AOP_PREG (IC_RESULT (ic)))
3670 emitcode ("cjne", "%s,#0x00,%05d$",
3671 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3675 emitcode ("cjne", "a,%s,%05d$",
3676 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3679 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3684 emitcode ("", "%05d$:", tlbl->key + 100);
3689 /* if result is dptr */
3690 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3691 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3692 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3693 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3695 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3701 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3704 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3705 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3707 emitcode ("inc", "dptr");
3712 /* if the literal value of the right hand side
3713 is greater than 4 then it is not worth it */
3717 /* if the sizes are greater than 1 then we cannot */
3718 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3719 AOP_SIZE (IC_LEFT (ic)) > 1)
3722 /* we can if the aops of the left & result match or
3723 if they are in registers and the registers are the
3725 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3730 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3731 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3732 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3738 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3747 /*-----------------------------------------------------------------*/
3748 /* outBitAcc - output a bit in acc */
3749 /*-----------------------------------------------------------------*/
3751 outBitAcc (operand * result)
3753 symbol *tlbl = newiTempLabel (NULL);
3754 /* if the result is a bit */
3755 if (AOP_TYPE (result) == AOP_CRY)
3757 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
3761 emitcode ("jz", "%05d$", tlbl->key + 100);
3762 emitcode ("mov", "a,%s", one);
3763 emitcode ("", "%05d$:", tlbl->key + 100);
3768 /*-----------------------------------------------------------------*/
3769 /* genPlusBits - generates code for addition of two bits */
3770 /*-----------------------------------------------------------------*/
3772 genPlusBits (iCode * ic)
3774 D(emitcode ("; genPlusBits",""));
3776 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3778 symbol *lbl = newiTempLabel (NULL);
3779 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3780 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3781 emitcode ("cpl", "c");
3782 emitcode ("", "%05d$:", (lbl->key + 100));
3783 outBitC (IC_RESULT (ic));
3787 emitcode ("clr", "a");
3788 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3789 emitcode ("rlc", "a");
3790 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3791 emitcode ("addc", "a,#0x00");
3792 outAcc (IC_RESULT (ic));
3797 /* This is the original version of this code.
3799 * This is being kept around for reference,
3800 * because I am not entirely sure I got it right...
3803 adjustArithmeticResult (iCode * ic)
3805 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3806 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3807 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3808 aopPut (IC_RESULT (ic),
3809 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
3811 isOperandVolatile (IC_RESULT (ic), FALSE));
3813 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3814 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3815 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3816 aopPut (IC_RESULT (ic),
3817 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
3819 isOperandVolatile (IC_RESULT (ic), FALSE));
3821 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3822 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3823 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3824 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3825 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3828 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3829 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3833 /* This is the pure and virtuous version of this code.
3834 * I'm pretty certain it's right, but not enough to toss the old
3838 adjustArithmeticResult (iCode * ic)
3840 if (opIsGptr (IC_RESULT (ic)) &&
3841 opIsGptr (IC_LEFT (ic)) &&
3842 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3844 aopPut (IC_RESULT (ic),
3845 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
3847 isOperandVolatile (IC_RESULT (ic), FALSE));
3850 if (opIsGptr (IC_RESULT (ic)) &&
3851 opIsGptr (IC_RIGHT (ic)) &&
3852 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3854 aopPut (IC_RESULT (ic),
3855 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
3857 isOperandVolatile (IC_RESULT (ic), FALSE));
3860 if (opIsGptr (IC_RESULT (ic)) &&
3861 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3862 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3863 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3864 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3867 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3868 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3873 /*-----------------------------------------------------------------*/
3874 /* genPlus - generates code for addition */
3875 /*-----------------------------------------------------------------*/
3877 genPlus (iCode * ic)
3879 int size, offset = 0;
3882 operand *leftOp, *rightOp;
3885 /* special cases :- */
3887 D(emitcode ("; genPlus",""));
3889 aopOp (IC_LEFT (ic), ic, FALSE);
3890 aopOp (IC_RIGHT (ic), ic, FALSE);
3891 aopOp (IC_RESULT (ic), ic, TRUE);
3893 /* if literal, literal on the right or
3894 if left requires ACC or right is already
3896 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3897 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3898 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3900 operand *t = IC_RIGHT (ic);
3901 IC_RIGHT (ic) = IC_LEFT (ic);
3905 /* if both left & right are in bit
3907 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3908 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3914 /* if left in bit space & right literal */
3915 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3916 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3918 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3919 /* if result in bit space */
3920 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3922 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3923 emitcode ("cpl", "c");
3924 outBitC (IC_RESULT (ic));
3928 size = getDataSize (IC_RESULT (ic));
3931 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
3932 emitcode ("addc", "a,#00");
3933 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3939 /* if I can do an increment instead
3940 of add then GOOD for ME */
3941 if (genPlusIncr (ic) == TRUE)
3944 size = getDataSize (IC_RESULT (ic));
3945 leftOp = IC_LEFT(ic);
3946 rightOp = IC_RIGHT(ic);
3949 /* if this is an add for an array access
3950 at a 256 byte boundary */
3952 && AOP_TYPE (op) == AOP_IMMD
3954 && IS_SPEC (OP_SYM_ETYPE (op))
3955 && SPEC_ABSA (OP_SYM_ETYPE (op))
3956 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3959 D(emitcode ("; genPlus aligned array",""));
3960 aopPut (IC_RESULT (ic),
3961 aopGet (rightOp, 0, FALSE, FALSE),
3963 isOperandVolatile (IC_RESULT (ic), FALSE));
3965 if( 1 == getDataSize (IC_RIGHT (ic)) )
3967 aopPut (IC_RESULT (ic),
3968 aopGet (leftOp, 1, FALSE, FALSE),
3970 isOperandVolatile (IC_RESULT (ic), FALSE));
3974 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
3975 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3976 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3981 /* if the lower bytes of a literal are zero skip the addition */
3982 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3984 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3985 (skip_bytes+1 < size))
3990 D(emitcode ("; genPlus shortcut",""));
3995 if( offset >= skip_bytes )
3997 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4000 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4002 emitcode("xch", "a,b");
4003 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4004 emitcode (add, "a,b");
4007 else if (aopGetUsesAcc (leftOp, offset))
4009 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4010 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4014 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4015 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4017 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4018 add = "addc"; /* further adds must propagate carry */
4022 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4023 isOperandVolatile (IC_RESULT (ic), FALSE))
4026 aopPut (IC_RESULT (ic),
4027 aopGet (leftOp, offset, FALSE, FALSE),
4029 isOperandVolatile (IC_RESULT (ic), FALSE));
4035 adjustArithmeticResult (ic);
4038 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4039 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4043 /*-----------------------------------------------------------------*/
4044 /* genMinusDec :- does subtraction with deccrement if possible */
4045 /*-----------------------------------------------------------------*/
4047 genMinusDec (iCode * ic)
4049 unsigned int icount;
4050 unsigned int size = getDataSize (IC_RESULT (ic));
4052 /* will try to generate an increment */
4053 /* if the right side is not a literal
4055 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4058 /* if the literal value of the right hand side
4059 is greater than 4 then it is not worth it */
4060 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4063 D(emitcode ("; genMinusDec",""));
4065 /* if decrement >=16 bits in register or direct space */
4066 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4067 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4075 /* If the next instruction is a goto and the goto target
4076 * is <= 10 instructions previous to this, we can generate
4077 * jumps straight to that target.
4079 if (ic->next && ic->next->op == GOTO
4080 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4081 && labelRange <= 10)
4083 emitcode (";", "tail decrement optimized");
4084 tlbl = IC_LABEL (ic->next);
4089 tlbl = newiTempLabel (NULL);
4093 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4094 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4095 IS_AOP_PREG (IC_RESULT (ic)))
4096 emitcode ("cjne", "%s,#0xff,%05d$"
4097 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4101 emitcode ("mov", "a,#0xff");
4102 emitcode ("cjne", "a,%s,%05d$"
4103 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4106 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4109 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4110 IS_AOP_PREG (IC_RESULT (ic)))
4111 emitcode ("cjne", "%s,#0xff,%05d$"
4112 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4116 emitcode ("cjne", "a,%s,%05d$"
4117 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4120 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4124 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4125 IS_AOP_PREG (IC_RESULT (ic)))
4126 emitcode ("cjne", "%s,#0xff,%05d$"
4127 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4131 emitcode ("cjne", "a,%s,%05d$"
4132 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4135 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4139 emitcode ("", "%05d$:", tlbl->key + 100);
4144 /* if the sizes are greater than 1 then we cannot */
4145 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4146 AOP_SIZE (IC_LEFT (ic)) > 1)
4149 /* we can if the aops of the left & result match or
4150 if they are in registers and the registers are the
4152 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4156 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4164 /*-----------------------------------------------------------------*/
4165 /* addSign - complete with sign */
4166 /*-----------------------------------------------------------------*/
4168 addSign (operand * result, int offset, int sign)
4170 int size = (getDataSize (result) - offset);
4175 emitcode ("rlc", "a");
4176 emitcode ("subb", "a,acc");
4178 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4182 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4186 /*-----------------------------------------------------------------*/
4187 /* genMinusBits - generates code for subtraction of two bits */
4188 /*-----------------------------------------------------------------*/
4190 genMinusBits (iCode * ic)
4192 symbol *lbl = newiTempLabel (NULL);
4194 D(emitcode ("; genMinusBits",""));
4196 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4198 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4199 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4200 emitcode ("cpl", "c");
4201 emitcode ("", "%05d$:", (lbl->key + 100));
4202 outBitC (IC_RESULT (ic));
4206 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4207 emitcode ("subb", "a,acc");
4208 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4209 emitcode ("inc", "a");
4210 emitcode ("", "%05d$:", (lbl->key + 100));
4211 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4212 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4216 /*-----------------------------------------------------------------*/
4217 /* genMinus - generates code for subtraction */
4218 /*-----------------------------------------------------------------*/
4220 genMinus (iCode * ic)
4222 int size, offset = 0;
4224 D(emitcode ("; genMinus",""));
4226 aopOp (IC_LEFT (ic), ic, FALSE);
4227 aopOp (IC_RIGHT (ic), ic, FALSE);
4228 aopOp (IC_RESULT (ic), ic, TRUE);
4230 /* special cases :- */
4231 /* if both left & right are in bit space */
4232 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4233 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4239 /* if I can do an decrement instead
4240 of subtract then GOOD for ME */
4241 if (genMinusDec (ic) == TRUE)
4244 size = getDataSize (IC_RESULT (ic));
4246 /* if literal, add a,#-lit, else normal subb */
4247 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4249 unsigned long lit = 0L;
4250 bool useCarry = FALSE;
4252 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4257 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4258 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4259 if (!offset && !size && lit== (unsigned long) -1) {
4260 emitcode ("dec", "a");
4261 } else if (!useCarry) {
4262 /* first add without previous c */
4263 emitcode ("add", "a,#0x%02x",
4264 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4267 emitcode ("addc", "a,#0x%02x",
4268 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4270 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4272 /* no need to add zeroes */
4279 operand *leftOp, *rightOp;
4281 leftOp = IC_LEFT(ic);
4282 rightOp = IC_RIGHT(ic);
4286 if (aopGetUsesAcc(rightOp, offset)) {
4287 if (aopGetUsesAcc(leftOp, offset)) {
4290 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4292 emitcode ("mov", "b,a");
4295 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4296 emitcode ("subb", "a,b");
4299 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4300 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4302 emitcode( "setb", "c");
4304 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4305 emitcode("cpl", "a");
4308 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4311 emitcode ("subb", "a,%s",
4312 aopGet(rightOp, offset, FALSE, TRUE));
4315 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4320 adjustArithmeticResult (ic);
4323 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4324 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genMultbits :- multiplication of bits */
4331 /*-----------------------------------------------------------------*/
4333 genMultbits (operand * left,
4337 D(emitcode ("; genMultbits",""));
4339 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4340 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4344 /*-----------------------------------------------------------------*/
4345 /* genMultOneByte : 8*8=8/16 bit multiplication */
4346 /*-----------------------------------------------------------------*/
4348 genMultOneByte (operand * left,
4353 int size = AOP_SIZE (result);
4354 bool runtimeSign, compiletimeSign;
4355 bool lUnsigned, rUnsigned, pushedB;
4357 D(emitcode ("; genMultOneByte",""));
4359 if (size < 1 || size > 2)
4361 /* this should never happen */
4362 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4363 AOP_SIZE(result), __FILE__, lineno);
4367 /* (if two literals: the value is computed before) */
4368 /* if one literal, literal on the right */
4369 if (AOP_TYPE (left) == AOP_LIT)
4374 /* emitcode (";", "swapped left and right"); */
4376 /* if no literal, unsigned on the right: shorter code */
4377 if ( AOP_TYPE (right) != AOP_LIT
4378 && SPEC_USIGN (getSpec (operandType (left))))
4385 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4386 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4390 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4391 no need to take care about the signedness! */
4392 || (lUnsigned && rUnsigned))
4394 /* just an unsigned 8 * 8 = 8 multiply
4396 /* emitcode (";","unsigned"); */
4397 /* TODO: check for accumulator clash between left & right aops? */
4399 if (AOP_TYPE (right) == AOP_LIT)
4401 /* moving to accumulator first helps peepholes */
4402 MOVA (aopGet (left, 0, FALSE, FALSE));
4403 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4407 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4408 MOVA (aopGet (left, 0, FALSE, FALSE));
4411 emitcode ("mul", "ab");
4412 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4414 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4420 /* we have to do a signed multiply */
4421 /* emitcode (";", "signed"); */
4423 /* now sign adjust for both left & right */
4425 /* let's see what's needed: */
4426 /* apply negative sign during runtime */
4427 runtimeSign = FALSE;
4428 /* negative sign from literals */
4429 compiletimeSign = FALSE;
4433 if (AOP_TYPE(left) == AOP_LIT)
4435 /* signed literal */
4436 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4438 compiletimeSign = TRUE;
4441 /* signed but not literal */
4447 if (AOP_TYPE(right) == AOP_LIT)
4449 /* signed literal */
4450 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4452 compiletimeSign ^= TRUE;
4455 /* signed but not literal */
4459 /* initialize F0, which stores the runtime sign */
4462 if (compiletimeSign)
4463 emitcode ("setb", "F0"); /* set sign flag */
4465 emitcode ("clr", "F0"); /* reset sign flag */
4468 /* save the signs of the operands */
4469 if (AOP_TYPE(right) == AOP_LIT)
4471 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4473 if (!rUnsigned && val < 0)
4474 emitcode ("mov", "b,#0x%02x", -val);
4476 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4478 else /* ! literal */
4480 if (rUnsigned) /* emitcode (";", "signed"); */
4482 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4485 MOVA (aopGet (right, 0, FALSE, FALSE));
4486 lbl = newiTempLabel (NULL);
4487 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4488 emitcode ("cpl", "F0"); /* complement sign flag */
4489 emitcode ("cpl", "a"); /* 2's complement */
4490 emitcode ("inc", "a");
4491 emitcode ("", "%05d$:", (lbl->key + 100));
4492 emitcode ("mov", "b,a");
4496 if (AOP_TYPE(left) == AOP_LIT)
4498 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4500 if (!lUnsigned && val < 0)
4501 emitcode ("mov", "a,#0x%02x", -val);
4503 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4505 else /* ! literal */
4507 MOVA (aopGet (left, 0, FALSE, FALSE));
4511 lbl = newiTempLabel (NULL);
4512 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4513 emitcode ("cpl", "F0"); /* complement sign flag */
4514 emitcode ("cpl", "a"); /* 2's complement */
4515 emitcode ("inc", "a");
4516 emitcode ("", "%05d$:", (lbl->key + 100));
4520 /* now the multiplication */
4521 emitcode ("mul", "ab");
4522 if (runtimeSign || compiletimeSign)
4524 lbl = newiTempLabel (NULL);
4526 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4527 emitcode ("cpl", "a"); /* lsb 2's complement */
4529 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4532 emitcode ("add", "a,#1"); /* this sets carry flag */
4533 emitcode ("xch", "a,b");
4534 emitcode ("cpl", "a"); /* msb 2's complement */
4535 emitcode ("addc", "a,#0");
4536 emitcode ("xch", "a,b");
4538 emitcode ("", "%05d$:", (lbl->key + 100));
4540 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4542 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4547 /*-----------------------------------------------------------------*/
4548 /* genMult - generates code for multiplication */
4549 /*-----------------------------------------------------------------*/
4551 genMult (iCode * ic)
4553 operand *left = IC_LEFT (ic);
4554 operand *right = IC_RIGHT (ic);
4555 operand *result = IC_RESULT (ic);
4557 D(emitcode ("; genMult",""));
4559 /* assign the amsops */
4560 aopOp (left, ic, FALSE);
4561 aopOp (right, ic, FALSE);
4562 aopOp (result, ic, TRUE);
4564 /* special cases first */
4566 if (AOP_TYPE (left) == AOP_CRY &&
4567 AOP_TYPE (right) == AOP_CRY)
4569 genMultbits (left, right, result);
4573 /* if both are of size == 1 */
4574 #if 0 // one of them can be a sloc shared with the result
4575 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4577 if (getSize(operandType(left)) == 1 &&
4578 getSize(operandType(right)) == 1)
4581 genMultOneByte (left, right, result);
4585 /* should have been converted to function call */
4586 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4587 getSize(OP_SYMBOL(right)->type));
4591 freeAsmop (result, NULL, ic, TRUE);
4592 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4593 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4596 /*-----------------------------------------------------------------*/
4597 /* genDivbits :- division of bits */
4598 /*-----------------------------------------------------------------*/
4600 genDivbits (operand * left,
4607 D(emitcode ("; genDivbits",""));
4611 /* the result must be bit */
4612 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4613 l = aopGet (left, 0, FALSE, FALSE);
4617 emitcode ("div", "ab");
4618 emitcode ("rrc", "a");
4622 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4625 /*-----------------------------------------------------------------*/
4626 /* genDivOneByte : 8 bit division */
4627 /*-----------------------------------------------------------------*/
4629 genDivOneByte (operand * left,
4633 bool lUnsigned, rUnsigned, pushedB;
4634 bool runtimeSign, compiletimeSign;
4638 D(emitcode ("; genDivOneByte",""));
4640 /* Why is it necessary that genDivOneByte() can return an int result?
4643 volatile unsigned char uc;
4644 volatile signed char sc1, sc2;
4657 In all cases a one byte result would overflow, the following cast to int
4658 would return the wrong result.
4660 Two possible solution:
4661 a) cast operands to int, if ((unsigned) / (signed)) or
4662 ((signed) / (signed))
4663 b) return an 16 bit signed int; this is what we're doing here!
4666 size = AOP_SIZE (result) - 1;
4668 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4669 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4673 /* signed or unsigned */
4674 if (lUnsigned && rUnsigned)
4676 /* unsigned is easy */
4677 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4678 MOVA (aopGet (left, 0, FALSE, FALSE));
4679 emitcode ("div", "ab");
4680 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4682 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4688 /* signed is a little bit more difficult */
4690 /* now sign adjust for both left & right */
4692 /* let's see what's needed: */
4693 /* apply negative sign during runtime */
4694 runtimeSign = FALSE;
4695 /* negative sign from literals */
4696 compiletimeSign = FALSE;
4700 if (AOP_TYPE(left) == AOP_LIT)
4702 /* signed literal */
4703 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4705 compiletimeSign = TRUE;
4708 /* signed but not literal */
4714 if (AOP_TYPE(right) == AOP_LIT)
4716 /* signed literal */
4717 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4719 compiletimeSign ^= TRUE;
4722 /* signed but not literal */
4726 /* initialize F0, which stores the runtime sign */
4729 if (compiletimeSign)
4730 emitcode ("setb", "F0"); /* set sign flag */
4732 emitcode ("clr", "F0"); /* reset sign flag */
4735 /* save the signs of the operands */
4736 if (AOP_TYPE(right) == AOP_LIT)
4738 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4740 if (!rUnsigned && val < 0)
4741 emitcode ("mov", "b,#0x%02x", -val);
4743 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4745 else /* ! literal */
4748 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4751 MOVA (aopGet (right, 0, FALSE, FALSE));
4752 lbl = newiTempLabel (NULL);
4753 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4754 emitcode ("cpl", "F0"); /* complement sign flag */
4755 emitcode ("cpl", "a"); /* 2's complement */
4756 emitcode ("inc", "a");
4757 emitcode ("", "%05d$:", (lbl->key + 100));
4758 emitcode ("mov", "b,a");
4762 if (AOP_TYPE(left) == AOP_LIT)
4764 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4766 if (!lUnsigned && val < 0)
4767 emitcode ("mov", "a,#0x%02x", -val);
4769 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4771 else /* ! literal */
4773 MOVA (aopGet (left, 0, FALSE, FALSE));
4777 lbl = newiTempLabel (NULL);
4778 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4779 emitcode ("cpl", "F0"); /* complement sign flag */
4780 emitcode ("cpl", "a"); /* 2's complement */
4781 emitcode ("inc", "a");
4782 emitcode ("", "%05d$:", (lbl->key + 100));
4786 /* now the division */
4787 emitcode ("div", "ab");
4789 if (runtimeSign || compiletimeSign)
4791 lbl = newiTempLabel (NULL);
4793 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4794 emitcode ("cpl", "a"); /* lsb 2's complement */
4795 emitcode ("inc", "a");
4796 emitcode ("", "%05d$:", (lbl->key + 100));
4798 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4801 /* msb is 0x00 or 0xff depending on the sign */
4804 emitcode ("mov", "c,F0");
4805 emitcode ("subb", "a,acc");
4807 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4809 else /* compiletimeSign */
4811 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4816 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4818 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4824 /*-----------------------------------------------------------------*/
4825 /* genDiv - generates code for division */
4826 /*-----------------------------------------------------------------*/
4830 operand *left = IC_LEFT (ic);
4831 operand *right = IC_RIGHT (ic);
4832 operand *result = IC_RESULT (ic);
4834 D(emitcode ("; genDiv",""));
4836 /* assign the amsops */
4837 aopOp (left, ic, FALSE);
4838 aopOp (right, ic, FALSE);
4839 aopOp (result, ic, TRUE);
4841 /* special cases first */
4843 if (AOP_TYPE (left) == AOP_CRY &&
4844 AOP_TYPE (right) == AOP_CRY)
4846 genDivbits (left, right, result);
4850 /* if both are of size == 1 */
4851 if (AOP_SIZE (left) == 1 &&
4852 AOP_SIZE (right) == 1)
4854 genDivOneByte (left, right, result);
4858 /* should have been converted to function call */
4861 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4862 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (result, NULL, ic, TRUE);
4866 /*-----------------------------------------------------------------*/
4867 /* genModbits :- modulus of bits */
4868 /*-----------------------------------------------------------------*/
4870 genModbits (operand * left,
4877 D(emitcode ("; genModbits",""));
4881 /* the result must be bit */
4882 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4883 l = aopGet (left, 0, FALSE, FALSE);
4887 emitcode ("div", "ab");
4888 emitcode ("mov", "a,b");
4889 emitcode ("rrc", "a");
4893 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4896 /*-----------------------------------------------------------------*/
4897 /* genModOneByte : 8 bit modulus */
4898 /*-----------------------------------------------------------------*/
4900 genModOneByte (operand * left,
4904 bool lUnsigned, rUnsigned, pushedB;
4905 bool runtimeSign, compiletimeSign;
4909 D(emitcode ("; genModOneByte",""));
4911 size = AOP_SIZE (result) - 1;
4913 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4914 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4916 /* if right is a literal, check it for 2^n */
4917 if (AOP_TYPE(right) == AOP_LIT)
4919 unsigned char val = abs((int) operandLitValue(right));
4920 symbol *lbl2 = NULL;
4924 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4934 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4935 /* because iCode should have been changed to genAnd */
4936 /* see file "SDCCopt.c", function "convertToFcall()" */
4938 MOVA (aopGet (left, 0, FALSE, FALSE));
4939 emitcode ("mov", "c,acc.7");
4940 emitcode ("anl", "a,#0x%02x", val - 1);
4941 lbl = newiTempLabel (NULL);
4942 emitcode ("jz", "%05d$", (lbl->key + 100));
4943 emitcode ("jnc", "%05d$", (lbl->key + 100));
4944 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4950 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4952 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
4953 lbl2 = newiTempLabel (NULL);
4954 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4956 emitcode ("", "%05d$:", (lbl->key + 100));
4957 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4959 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4962 emitcode ("", "%05d$:", (lbl2->key + 100));
4973 /* signed or unsigned */
4974 if (lUnsigned && rUnsigned)
4976 /* unsigned is easy */
4977 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4978 MOVA (aopGet (left, 0, FALSE, FALSE));
4979 emitcode ("div", "ab");
4980 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4982 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4988 /* signed is a little bit more difficult */
4990 /* now sign adjust for both left & right */
4992 /* modulus: sign of the right operand has no influence on the result! */
4993 if (AOP_TYPE(right) == AOP_LIT)
4995 signed char val = (char) operandLitValue(right);
4997 if (!rUnsigned && val < 0)
4998 emitcode ("mov", "b,#0x%02x", -val);
5000 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5002 else /* not literal */
5005 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5008 MOVA (aopGet (right, 0, FALSE, FALSE));
5009 lbl = newiTempLabel (NULL);
5010 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5011 emitcode ("cpl", "a"); /* 2's complement */
5012 emitcode ("inc", "a");
5013 emitcode ("", "%05d$:", (lbl->key + 100));
5014 emitcode ("mov", "b,a");
5018 /* let's see what's needed: */
5019 /* apply negative sign during runtime */
5020 runtimeSign = FALSE;
5021 /* negative sign from literals */
5022 compiletimeSign = FALSE;
5024 /* sign adjust left side */
5025 if (AOP_TYPE(left) == AOP_LIT)
5027 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5029 if (!lUnsigned && val < 0)
5031 compiletimeSign = TRUE; /* set sign flag */
5032 emitcode ("mov", "a,#0x%02x", -val);
5035 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5037 else /* ! literal */
5039 MOVA (aopGet (left, 0, FALSE, FALSE));
5044 emitcode ("clr", "F0"); /* clear sign flag */
5046 lbl = newiTempLabel (NULL);
5047 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5048 emitcode ("setb", "F0"); /* set sign flag */
5049 emitcode ("cpl", "a"); /* 2's complement */
5050 emitcode ("inc", "a");
5051 emitcode ("", "%05d$:", (lbl->key + 100));
5055 /* now the modulus */
5056 emitcode ("div", "ab");
5058 if (runtimeSign || compiletimeSign)
5060 emitcode ("mov", "a,b");
5061 lbl = newiTempLabel (NULL);
5063 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5064 emitcode ("cpl", "a"); /* 2's complement */
5065 emitcode ("inc", "a");
5066 emitcode ("", "%05d$:", (lbl->key + 100));
5068 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5071 /* msb is 0x00 or 0xff depending on the sign */
5074 emitcode ("mov", "c,F0");
5075 emitcode ("subb", "a,acc");
5077 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5079 else /* compiletimeSign */
5081 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5086 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5088 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5094 /*-----------------------------------------------------------------*/
5095 /* genMod - generates code for division */
5096 /*-----------------------------------------------------------------*/
5100 operand *left = IC_LEFT (ic);
5101 operand *right = IC_RIGHT (ic);
5102 operand *result = IC_RESULT (ic);
5104 D(emitcode ("; genMod",""));
5106 /* assign the asmops */
5107 aopOp (left, ic, FALSE);
5108 aopOp (right, ic, FALSE);
5109 aopOp (result, ic, TRUE);
5111 /* special cases first */
5113 if (AOP_TYPE (left) == AOP_CRY &&
5114 AOP_TYPE (right) == AOP_CRY)
5116 genModbits (left, right, result);
5120 /* if both are of size == 1 */
5121 if (AOP_SIZE (left) == 1 &&
5122 AOP_SIZE (right) == 1)
5124 genModOneByte (left, right, result);
5128 /* should have been converted to function call */
5132 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 freeAsmop (result, NULL, ic, TRUE);
5137 /*-----------------------------------------------------------------*/
5138 /* genIfxJump :- will create a jump depending on the ifx */
5139 /*-----------------------------------------------------------------*/
5141 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5144 symbol *tlbl = newiTempLabel (NULL);
5147 D(emitcode ("; genIfxJump",""));
5149 /* if true label then we jump if condition
5153 jlbl = IC_TRUE (ic);
5154 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5155 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5159 /* false label is present */
5160 jlbl = IC_FALSE (ic);
5161 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5162 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5164 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5165 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5167 emitcode (inst, "%05d$", tlbl->key + 100);
5168 freeForBranchAsmop (result);
5169 freeForBranchAsmop (right);
5170 freeForBranchAsmop (left);
5171 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5172 emitcode ("", "%05d$:", tlbl->key + 100);
5174 /* mark the icode as generated */
5178 /*-----------------------------------------------------------------*/
5179 /* genCmp :- greater or less than comparison */
5180 /*-----------------------------------------------------------------*/
5182 genCmp (operand * left, operand * right,
5183 operand * result, iCode * ifx, int sign, iCode *ic)
5185 int size, offset = 0;
5186 unsigned long lit = 0L;
5189 D(emitcode ("; genCmp",""));
5191 /* if left & right are bit variables */
5192 if (AOP_TYPE (left) == AOP_CRY &&
5193 AOP_TYPE (right) == AOP_CRY)
5195 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5196 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5200 /* subtract right from left if at the
5201 end the carry flag is set then we know that
5202 left is greater than right */
5203 size = max (AOP_SIZE (left), AOP_SIZE (right));
5205 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5206 if ((size == 1) && !sign &&
5207 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5209 symbol *lbl = newiTempLabel (NULL);
5210 emitcode ("cjne", "%s,%s,%05d$",
5211 aopGet (left, offset, FALSE, FALSE),
5212 aopGet (right, offset, FALSE, FALSE),
5214 emitcode ("", "%05d$:", lbl->key + 100);
5218 if (AOP_TYPE (right) == AOP_LIT)
5220 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5221 /* optimize if(x < 0) or if(x >= 0) */
5230 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5231 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5233 genIfxJump (ifx, "acc.7", left, right, result);
5234 freeAsmop (right, NULL, ic, TRUE);
5235 freeAsmop (left, NULL, ic, TRUE);
5240 emitcode ("rlc", "a");
5248 bool pushedB = FALSE;
5249 rightInB = aopGetUsesAcc(right, offset);
5253 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5255 MOVA (aopGet (left, offset, FALSE, FALSE));
5256 if (sign && size == 0)
5258 emitcode ("xrl", "a,#0x80");
5259 if (AOP_TYPE (right) == AOP_LIT)
5261 unsigned long lit = (unsigned long)
5262 floatFromVal (AOP (right)->aopu.aop_lit);
5263 emitcode ("subb", "a,#0x%02x",
5264 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5272 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5274 emitcode ("xrl", "b,#0x80");
5275 emitcode ("subb", "a,b");
5281 emitcode ("subb", "a,b");
5283 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5293 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5294 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5295 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5301 /* if the result is used in the next
5302 ifx conditional branch then generate
5303 code a little differently */
5305 genIfxJump (ifx, "c", NULL, NULL, result);
5308 /* leave the result in acc */
5312 /*-----------------------------------------------------------------*/
5313 /* genCmpGt :- greater than comparison */
5314 /*-----------------------------------------------------------------*/
5316 genCmpGt (iCode * ic, iCode * ifx)
5318 operand *left, *right, *result;
5319 sym_link *letype, *retype;
5322 D(emitcode ("; genCmpGt",""));
5324 left = IC_LEFT (ic);
5325 right = IC_RIGHT (ic);
5326 result = IC_RESULT (ic);
5328 letype = getSpec (operandType (left));
5329 retype = getSpec (operandType (right));
5330 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5331 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5332 /* assign the amsops */
5333 aopOp (left, ic, FALSE);
5334 aopOp (right, ic, FALSE);
5335 aopOp (result, ic, TRUE);
5337 genCmp (right, left, result, ifx, sign, ic);
5339 freeAsmop (result, NULL, ic, TRUE);
5342 /*-----------------------------------------------------------------*/
5343 /* genCmpLt - less than comparisons */
5344 /*-----------------------------------------------------------------*/
5346 genCmpLt (iCode * ic, iCode * ifx)
5348 operand *left, *right, *result;
5349 sym_link *letype, *retype;
5352 D(emitcode ("; genCmpLt",""));
5354 left = IC_LEFT (ic);
5355 right = IC_RIGHT (ic);
5356 result = IC_RESULT (ic);
5358 letype = getSpec (operandType (left));
5359 retype = getSpec (operandType (right));
5360 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5361 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5362 /* assign the amsops */
5363 aopOp (left, ic, FALSE);
5364 aopOp (right, ic, FALSE);
5365 aopOp (result, ic, TRUE);
5367 genCmp (left, right, result, ifx, sign,ic);
5369 freeAsmop (result, NULL, ic, TRUE);
5372 /*-----------------------------------------------------------------*/
5373 /* gencjneshort - compare and jump if not equal */
5374 /*-----------------------------------------------------------------*/
5376 gencjneshort (operand * left, operand * right, symbol * lbl)
5378 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5380 unsigned long lit = 0L;
5382 /* if the left side is a literal or
5383 if the right is in a pointer register and left
5385 if ((AOP_TYPE (left) == AOP_LIT) ||
5386 (AOP_TYPE (left) == AOP_IMMD) ||
5387 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5394 if (AOP_TYPE (right) == AOP_LIT)
5395 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5397 /* if the right side is a literal then anything goes */
5398 if (AOP_TYPE (right) == AOP_LIT &&
5399 AOP_TYPE (left) != AOP_DIR &&
5400 AOP_TYPE (left) != AOP_IMMD)
5404 emitcode ("cjne", "%s,%s,%05d$",
5405 aopGet (left, offset, FALSE, FALSE),
5406 aopGet (right, offset, FALSE, FALSE),
5412 /* if the right side is in a register or in direct space or
5413 if the left is a pointer register & right is not */
5414 else if (AOP_TYPE (right) == AOP_REG ||
5415 AOP_TYPE (right) == AOP_DIR ||
5416 AOP_TYPE (right) == AOP_LIT ||
5417 AOP_TYPE (right) == AOP_IMMD ||
5418 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5419 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5423 MOVA (aopGet (left, offset, FALSE, FALSE));
5424 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5425 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5426 emitcode ("jnz", "%05d$", lbl->key + 100);
5428 emitcode ("cjne", "a,%s,%05d$",
5429 aopGet (right, offset, FALSE, TRUE),
5436 /* right is a pointer reg need both a & b */
5440 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5441 wassertl(!BINUSE, "B was in use");
5442 l = aopGet (left, offset, FALSE, FALSE);
5443 if (strcmp (l, "b"))
5444 emitcode ("mov", "b,%s", l);
5445 MOVA (aopGet (right, offset, FALSE, FALSE));
5446 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5452 /*-----------------------------------------------------------------*/
5453 /* gencjne - compare and jump if not equal */
5454 /*-----------------------------------------------------------------*/
5456 gencjne (operand * left, operand * right, symbol * lbl)
5458 symbol *tlbl = newiTempLabel (NULL);
5460 gencjneshort (left, right, lbl);
5462 emitcode ("mov", "a,%s", one);
5463 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5464 emitcode ("", "%05d$:", lbl->key + 100);
5465 emitcode ("clr", "a");
5466 emitcode ("", "%05d$:", tlbl->key + 100);
5469 /*-----------------------------------------------------------------*/
5470 /* genCmpEq - generates code for equal to */
5471 /*-----------------------------------------------------------------*/
5473 genCmpEq (iCode * ic, iCode * ifx)
5475 operand *left, *right, *result;
5477 D(emitcode ("; genCmpEq",""));
5479 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5480 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5481 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5483 /* if literal, literal on the right or
5484 if the right is in a pointer register and left
5486 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5487 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5489 operand *t = IC_RIGHT (ic);
5490 IC_RIGHT (ic) = IC_LEFT (ic);
5494 if (ifx && !AOP_SIZE (result))
5497 /* if they are both bit variables */
5498 if (AOP_TYPE (left) == AOP_CRY &&
5499 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5501 if (AOP_TYPE (right) == AOP_LIT)
5503 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5506 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5507 emitcode ("cpl", "c");
5511 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5515 emitcode ("clr", "c");
5517 /* AOP_TYPE(right) == AOP_CRY */
5521 symbol *lbl = newiTempLabel (NULL);
5522 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5523 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5524 emitcode ("cpl", "c");
5525 emitcode ("", "%05d$:", (lbl->key + 100));
5527 /* if true label then we jump if condition
5529 tlbl = newiTempLabel (NULL);
5532 emitcode ("jnc", "%05d$", tlbl->key + 100);
5533 freeForBranchAsmop (result);
5534 freeForBranchAsmop (right);
5535 freeForBranchAsmop (left);
5536 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5540 emitcode ("jc", "%05d$", tlbl->key + 100);
5541 freeForBranchAsmop (result);
5542 freeForBranchAsmop (right);
5543 freeForBranchAsmop (left);
5544 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5546 emitcode ("", "%05d$:", tlbl->key + 100);
5550 tlbl = newiTempLabel (NULL);
5551 gencjneshort (left, right, tlbl);
5554 freeForBranchAsmop (result);
5555 freeForBranchAsmop (right);
5556 freeForBranchAsmop (left);
5557 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5558 emitcode ("", "%05d$:", tlbl->key + 100);
5562 symbol *lbl = newiTempLabel (NULL);
5563 emitcode ("sjmp", "%05d$", lbl->key + 100);
5564 emitcode ("", "%05d$:", tlbl->key + 100);
5565 freeForBranchAsmop (result);
5566 freeForBranchAsmop (right);
5567 freeForBranchAsmop (left);
5568 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5569 emitcode ("", "%05d$:", lbl->key + 100);
5572 /* mark the icode as generated */
5577 /* if they are both bit variables */
5578 if (AOP_TYPE (left) == AOP_CRY &&
5579 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5581 if (AOP_TYPE (right) == AOP_LIT)
5583 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5586 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5587 emitcode ("cpl", "c");
5591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5595 emitcode ("clr", "c");
5597 /* AOP_TYPE(right) == AOP_CRY */
5601 symbol *lbl = newiTempLabel (NULL);
5602 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5603 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5604 emitcode ("cpl", "c");
5605 emitcode ("", "%05d$:", (lbl->key + 100));
5608 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5615 genIfxJump (ifx, "c", left, right, result);
5618 /* if the result is used in an arithmetic operation
5619 then put the result in place */
5624 gencjne (left, right, newiTempLabel (NULL));
5625 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5627 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5632 genIfxJump (ifx, "a", left, right, result);
5635 /* if the result is used in an arithmetic operation
5636 then put the result in place */
5637 if (AOP_TYPE (result) != AOP_CRY)
5639 /* leave the result in acc */
5643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5644 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5645 freeAsmop (result, NULL, ic, TRUE);
5648 /*-----------------------------------------------------------------*/
5649 /* ifxForOp - returns the icode containing the ifx for operand */
5650 /*-----------------------------------------------------------------*/
5652 ifxForOp (operand * op, iCode * ic)
5654 /* if true symbol then needs to be assigned */
5655 if (IS_TRUE_SYMOP (op))
5658 /* if this has register type condition and
5659 the next instruction is ifx with the same operand
5660 and live to of the operand is upto the ifx only then */
5662 ic->next->op == IFX &&
5663 IC_COND (ic->next)->key == op->key &&
5664 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5670 /*-----------------------------------------------------------------*/
5671 /* hasInc - operand is incremented before any other use */
5672 /*-----------------------------------------------------------------*/
5674 hasInc (operand *op, iCode *ic,int osize)
5676 sym_link *type = operandType(op);
5677 sym_link *retype = getSpec (type);
5678 iCode *lic = ic->next;
5681 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5682 if (!IS_SYMOP(op)) return NULL;
5684 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5685 if (IS_AGGREGATE(type->next)) return NULL;
5686 if (osize != (isize = getSize(type->next))) return NULL;
5689 /* if operand of the form op = op + <sizeof *op> */
5690 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5691 isOperandEqual(IC_RESULT(lic),op) &&
5692 isOperandLiteral(IC_RIGHT(lic)) &&
5693 operandLitValue(IC_RIGHT(lic)) == isize) {
5696 /* if the operand used or deffed */
5697 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5700 /* if GOTO or IFX */
5701 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5707 /*-----------------------------------------------------------------*/
5708 /* genAndOp - for && operation */
5709 /*-----------------------------------------------------------------*/
5711 genAndOp (iCode * ic)
5713 operand *left, *right, *result;
5716 D(emitcode ("; genAndOp",""));
5718 /* note here that && operations that are in an
5719 if statement are taken away by backPatchLabels
5720 only those used in arthmetic operations remain */
5721 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5722 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5723 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5725 /* if both are bit variables */
5726 if (AOP_TYPE (left) == AOP_CRY &&
5727 AOP_TYPE (right) == AOP_CRY)
5729 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5730 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5735 tlbl = newiTempLabel (NULL);
5737 emitcode ("jz", "%05d$", tlbl->key + 100);
5739 emitcode ("", "%05d$:", tlbl->key + 100);
5743 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5744 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5745 freeAsmop (result, NULL, ic, TRUE);
5749 /*-----------------------------------------------------------------*/
5750 /* genOrOp - for || operation */
5751 /*-----------------------------------------------------------------*/
5753 genOrOp (iCode * ic)
5755 operand *left, *right, *result;
5758 D(emitcode ("; genOrOp",""));
5760 /* note here that || operations that are in an
5761 if statement are taken away by backPatchLabels
5762 only those used in arthmetic operations remain */
5763 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5764 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5765 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5767 /* if both are bit variables */
5768 if (AOP_TYPE (left) == AOP_CRY &&
5769 AOP_TYPE (right) == AOP_CRY)
5771 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5772 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5777 tlbl = newiTempLabel (NULL);
5779 emitcode ("jnz", "%05d$", tlbl->key + 100);
5781 emitcode ("", "%05d$:", tlbl->key + 100);
5785 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5787 freeAsmop (result, NULL, ic, TRUE);
5790 /*-----------------------------------------------------------------*/
5791 /* isLiteralBit - test if lit == 2^n */
5792 /*-----------------------------------------------------------------*/
5794 isLiteralBit (unsigned long lit)
5796 unsigned long pw[32] =
5797 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5798 0x100L, 0x200L, 0x400L, 0x800L,
5799 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5800 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5801 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5802 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5803 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5806 for (idx = 0; idx < 32; idx++)
5812 /*-----------------------------------------------------------------*/
5813 /* continueIfTrue - */
5814 /*-----------------------------------------------------------------*/
5816 continueIfTrue (iCode * ic)
5819 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5823 /*-----------------------------------------------------------------*/
5825 /*-----------------------------------------------------------------*/
5827 jumpIfTrue (iCode * ic)
5830 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5834 /*-----------------------------------------------------------------*/
5835 /* jmpTrueOrFalse - */
5836 /*-----------------------------------------------------------------*/
5838 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5840 // ugly but optimized by peephole
5843 symbol *nlbl = newiTempLabel (NULL);
5844 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5845 emitcode ("", "%05d$:", tlbl->key + 100);
5846 freeForBranchAsmop (result);
5847 freeForBranchAsmop (right);
5848 freeForBranchAsmop (left);
5849 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5850 emitcode ("", "%05d$:", nlbl->key + 100);
5854 freeForBranchAsmop (result);
5855 freeForBranchAsmop (right);
5856 freeForBranchAsmop (left);
5857 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5858 emitcode ("", "%05d$:", tlbl->key + 100);
5863 /*-----------------------------------------------------------------*/
5864 /* genAnd - code for and */
5865 /*-----------------------------------------------------------------*/
5867 genAnd (iCode * ic, iCode * ifx)
5869 operand *left, *right, *result;
5870 int size, offset = 0;
5871 unsigned long lit = 0L;
5875 D(emitcode ("; genAnd",""));
5877 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5878 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5879 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5882 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5884 AOP_TYPE (left), AOP_TYPE (right));
5885 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5887 AOP_SIZE (left), AOP_SIZE (right));
5890 /* if left is a literal & right is not then exchange them */
5891 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5892 AOP_NEEDSACC (left))
5894 operand *tmp = right;
5899 /* if result = right then exchange left and right */
5900 if (sameRegs (AOP (result), AOP (right)))
5902 operand *tmp = right;
5907 /* if right is bit then exchange them */
5908 if (AOP_TYPE (right) == AOP_CRY &&
5909 AOP_TYPE (left) != AOP_CRY)
5911 operand *tmp = right;
5915 if (AOP_TYPE (right) == AOP_LIT)
5916 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5918 size = AOP_SIZE (result);
5921 // result = bit & yy;
5922 if (AOP_TYPE (left) == AOP_CRY)
5924 // c = bit & literal;
5925 if (AOP_TYPE (right) == AOP_LIT)
5929 if (size && sameRegs (AOP (result), AOP (left)))
5932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5937 if (size && (AOP_TYPE (result) == AOP_CRY))
5939 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5942 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5947 emitcode ("clr", "c");
5952 if (AOP_TYPE (right) == AOP_CRY)
5955 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5956 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5961 MOVA (aopGet (right, 0, FALSE, FALSE));
5963 emitcode ("rrc", "a");
5964 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5972 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5973 genIfxJump (ifx, "c", left, right, result);
5977 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5978 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5979 if ((AOP_TYPE (right) == AOP_LIT) &&
5980 (AOP_TYPE (result) == AOP_CRY) &&
5981 (AOP_TYPE (left) != AOP_CRY))
5983 int posbit = isLiteralBit (lit);
5988 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
5992 switch (posbit & 0x07)
5994 case 0: emitcode ("rrc", "a");
5996 case 7: emitcode ("rlc", "a");
5998 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6007 SNPRINTF (buffer, sizeof(buffer),
6008 "acc.%d", posbit & 0x07);
6009 genIfxJump (ifx, buffer, left, right, result);
6012 {// what is this case? just found it in ds390/gen.c
6013 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6020 symbol *tlbl = newiTempLabel (NULL);
6021 int sizel = AOP_SIZE (left);
6023 emitcode ("setb", "c");
6026 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6028 MOVA (aopGet (left, offset, FALSE, FALSE));
6030 if ((posbit = isLiteralBit (bytelit)) != 0)
6031 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6034 if (bytelit != 0x0FFL)
6035 emitcode ("anl", "a,%s",
6036 aopGet (right, offset, FALSE, TRUE));
6037 emitcode ("jnz", "%05d$", tlbl->key + 100);
6042 // bit = left & literal
6045 emitcode ("clr", "c");
6046 emitcode ("", "%05d$:", tlbl->key + 100);
6048 // if(left & literal)
6052 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6054 emitcode ("", "%05d$:", tlbl->key + 100);
6062 /* if left is same as result */
6063 if (sameRegs (AOP (result), AOP (left)))
6065 for (; size--; offset++)
6067 if (AOP_TYPE (right) == AOP_LIT)
6069 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6070 if (bytelit == 0x0FF)
6072 /* dummy read of volatile operand */
6073 if (isOperandVolatile (left, FALSE))
6074 MOVA (aopGet (left, offset, FALSE, FALSE));
6078 else if (bytelit == 0)
6080 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6082 else if (IS_AOP_PREG (result))
6084 MOVA (aopGet (left, offset, FALSE, TRUE));
6085 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6086 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6089 emitcode ("anl", "%s,%s",
6090 aopGet (left, offset, FALSE, TRUE),
6091 aopGet (right, offset, FALSE, FALSE));
6095 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6097 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6101 MOVA (aopGet (right, offset, FALSE, FALSE));
6102 if (IS_AOP_PREG (result))
6104 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6105 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6108 emitcode ("anl", "%s,a",
6109 aopGet (left, offset, FALSE, TRUE));
6116 // left & result in different registers
6117 if (AOP_TYPE (result) == AOP_CRY)
6120 // if(size), result in bit
6121 // if(!size && ifx), conditional oper: if(left & right)
6122 symbol *tlbl = newiTempLabel (NULL);
6123 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6125 emitcode ("setb", "c");
6128 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6129 && AOP_TYPE(left)==AOP_ACC)
6132 emitcode("mov", "a,b");
6133 emitcode ("anl", "a,%s",
6134 aopGet (right, offset, FALSE, FALSE));
6136 if (AOP_TYPE(left)==AOP_ACC)
6140 bool pushedB = pushB ();
6141 emitcode("mov", "b,a");
6142 MOVA (aopGet (right, offset, FALSE, FALSE));
6143 emitcode("anl", "a,b");
6148 MOVA (aopGet (right, offset, FALSE, FALSE));
6149 emitcode("anl", "a,b");
6152 MOVA (aopGet (right, offset, FALSE, FALSE));
6153 emitcode ("anl", "a,%s",
6154 aopGet (left, offset, FALSE, FALSE));
6157 emitcode ("jnz", "%05d$", tlbl->key + 100);
6163 emitcode ("", "%05d$:", tlbl->key + 100);
6167 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6169 emitcode ("", "%05d$:", tlbl->key + 100);
6173 for (; (size--); offset++)
6176 // result = left & right
6177 if (AOP_TYPE (right) == AOP_LIT)
6179 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6180 if (bytelit == 0x0FF)
6183 aopGet (left, offset, FALSE, FALSE),
6185 isOperandVolatile (result, FALSE));
6188 else if (bytelit == 0)
6190 /* dummy read of volatile operand */
6191 if (isOperandVolatile (left, FALSE))
6192 MOVA (aopGet (left, offset, FALSE, FALSE));
6193 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6196 else if (AOP_TYPE (left) == AOP_ACC)
6200 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6201 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6206 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6207 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6212 // faster than result <- left, anl result,right
6213 // and better if result is SFR
6214 if (AOP_TYPE (left) == AOP_ACC)
6217 emitcode("mov", "a,b");
6218 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6222 MOVA (aopGet (right, offset, FALSE, FALSE));
6223 emitcode ("anl", "a,%s",
6224 aopGet (left, offset, FALSE, FALSE));
6226 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234 freeAsmop (result, NULL, ic, TRUE);
6237 /*-----------------------------------------------------------------*/
6238 /* genOr - code for or */
6239 /*-----------------------------------------------------------------*/
6241 genOr (iCode * ic, iCode * ifx)
6243 operand *left, *right, *result;
6244 int size, offset = 0;
6245 unsigned long lit = 0L;
6248 D(emitcode ("; genOr",""));
6250 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6251 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6252 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6255 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6257 AOP_TYPE (left), AOP_TYPE (right));
6258 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6260 AOP_SIZE (left), AOP_SIZE (right));
6263 /* if left is a literal & right is not then exchange them */
6264 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6265 AOP_NEEDSACC (left))
6267 operand *tmp = right;
6272 /* if result = right then exchange them */
6273 if (sameRegs (AOP (result), AOP (right)))
6275 operand *tmp = right;
6280 /* if right is bit then exchange them */
6281 if (AOP_TYPE (right) == AOP_CRY &&
6282 AOP_TYPE (left) != AOP_CRY)
6284 operand *tmp = right;
6288 if (AOP_TYPE (right) == AOP_LIT)
6289 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6291 size = AOP_SIZE (result);
6295 if (AOP_TYPE (left) == AOP_CRY)
6297 if (AOP_TYPE (right) == AOP_LIT)
6299 // c = bit | literal;
6302 // lit != 0 => result = 1
6303 if (AOP_TYPE (result) == AOP_CRY)
6306 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6308 continueIfTrue (ifx);
6311 emitcode ("setb", "c");
6315 // lit == 0 => result = left
6316 if (size && sameRegs (AOP (result), AOP (left)))
6318 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6323 if (AOP_TYPE (right) == AOP_CRY)
6326 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6327 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6332 symbol *tlbl = newiTempLabel (NULL);
6333 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6334 emitcode ("setb", "c");
6335 emitcode ("jb", "%s,%05d$",
6336 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6338 emitcode ("jnz", "%05d$", tlbl->key + 100);
6339 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6341 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6347 emitcode ("", "%05d$:", tlbl->key + 100);
6356 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6357 genIfxJump (ifx, "c", left, right, result);
6361 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6362 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6363 if ((AOP_TYPE (right) == AOP_LIT) &&
6364 (AOP_TYPE (result) == AOP_CRY) &&
6365 (AOP_TYPE (left) != AOP_CRY))
6371 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6373 continueIfTrue (ifx);
6378 // lit = 0, result = boolean(left)
6380 emitcode ("setb", "c");
6384 symbol *tlbl = newiTempLabel (NULL);
6385 emitcode ("jnz", "%05d$", tlbl->key + 100);
6387 emitcode ("", "%05d$:", tlbl->key + 100);
6391 genIfxJump (ifx, "a", left, right, result);
6399 /* if left is same as result */
6400 if (sameRegs (AOP (result), AOP (left)))
6402 for (; size--; offset++)
6404 if (AOP_TYPE (right) == AOP_LIT)
6406 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6409 /* dummy read of volatile operand */
6410 if (isOperandVolatile (left, FALSE))
6411 MOVA (aopGet (left, offset, FALSE, FALSE));
6415 else if (bytelit == 0x0FF)
6417 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6419 else if (IS_AOP_PREG (left))
6421 MOVA (aopGet (left, offset, FALSE, TRUE));
6422 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6423 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6427 emitcode ("orl", "%s,%s",
6428 aopGet (left, offset, FALSE, TRUE),
6429 aopGet (right, offset, FALSE, FALSE));
6434 if (AOP_TYPE (left) == AOP_ACC)
6437 emitcode("mov", "a,b");
6438 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6442 MOVA (aopGet (right, offset, FALSE, FALSE));
6443 if (IS_AOP_PREG (left))
6445 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6446 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6450 emitcode ("orl", "%s,a",
6451 aopGet (left, offset, FALSE, TRUE));
6459 // left & result in different registers
6460 if (AOP_TYPE (result) == AOP_CRY)
6463 // if(size), result in bit
6464 // if(!size && ifx), conditional oper: if(left | right)
6465 symbol *tlbl = newiTempLabel (NULL);
6466 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6468 emitcode ("setb", "c");
6471 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6473 emitcode("mov", "a,b");
6474 emitcode ("orl", "a,%s",
6475 aopGet (right, offset, FALSE, FALSE));
6477 MOVA (aopGet (right, offset, FALSE, FALSE));
6478 emitcode ("orl", "a,%s",
6479 aopGet (left, offset, FALSE, FALSE));
6481 emitcode ("jnz", "%05d$", tlbl->key + 100);
6487 emitcode ("", "%05d$:", tlbl->key + 100);
6491 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6493 emitcode ("", "%05d$:", tlbl->key + 100);
6497 for (; (size--); offset++)
6500 // result = left | right
6501 if (AOP_TYPE (right) == AOP_LIT)
6503 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6507 aopGet (left, offset, FALSE, FALSE),
6509 isOperandVolatile (result, FALSE));
6512 else if (bytelit == 0x0FF)
6514 /* dummy read of volatile operand */
6515 if (isOperandVolatile (left, FALSE))
6516 MOVA (aopGet (left, offset, FALSE, FALSE));
6517 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6521 // faster than result <- left, anl result,right
6522 // and better if result is SFR
6523 if (AOP_TYPE (left) == AOP_ACC)
6526 emitcode("mov", "a,b");
6527 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6531 MOVA (aopGet (right, offset, FALSE, FALSE));
6532 emitcode ("orl", "a,%s",
6533 aopGet (left, offset, FALSE, FALSE));
6535 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6541 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6542 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6543 freeAsmop (result, NULL, ic, TRUE);
6546 /*-----------------------------------------------------------------*/
6547 /* genXor - code for xclusive or */
6548 /*-----------------------------------------------------------------*/
6550 genXor (iCode * ic, iCode * ifx)
6552 operand *left, *right, *result;
6553 int size, offset = 0;
6554 unsigned long lit = 0L;
6557 D(emitcode ("; genXor",""));
6559 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6560 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6561 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6564 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6566 AOP_TYPE (left), AOP_TYPE (right));
6567 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6569 AOP_SIZE (left), AOP_SIZE (right));
6572 /* if left is a literal & right is not ||
6573 if left needs acc & right does not */
6574 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6575 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6577 operand *tmp = right;
6582 /* if result = right then exchange them */
6583 if (sameRegs (AOP (result), AOP (right)))
6585 operand *tmp = right;
6590 /* if right is bit then exchange them */
6591 if (AOP_TYPE (right) == AOP_CRY &&
6592 AOP_TYPE (left) != AOP_CRY)
6594 operand *tmp = right;
6598 if (AOP_TYPE (right) == AOP_LIT)
6599 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6601 size = AOP_SIZE (result);
6605 if (AOP_TYPE (left) == AOP_CRY)
6607 if (AOP_TYPE (right) == AOP_LIT)
6609 // c = bit & literal;
6612 // lit>>1 != 0 => result = 1
6613 if (AOP_TYPE (result) == AOP_CRY)
6616 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6618 continueIfTrue (ifx);
6621 emitcode ("setb", "c");
6628 // lit == 0, result = left
6629 if (size && sameRegs (AOP (result), AOP (left)))
6631 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6635 // lit == 1, result = not(left)
6636 if (size && sameRegs (AOP (result), AOP (left)))
6638 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6643 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6644 emitcode ("cpl", "c");
6653 symbol *tlbl = newiTempLabel (NULL);
6654 if (AOP_TYPE (right) == AOP_CRY)
6657 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6661 int sizer = AOP_SIZE (right);
6663 // if val>>1 != 0, result = 1
6664 emitcode ("setb", "c");
6667 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6669 // test the msb of the lsb
6670 emitcode ("anl", "a,#0xfe");
6671 emitcode ("jnz", "%05d$", tlbl->key + 100);
6675 emitcode ("rrc", "a");
6677 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6678 emitcode ("cpl", "c");
6679 emitcode ("", "%05d$:", (tlbl->key + 100));
6686 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6687 genIfxJump (ifx, "c", left, right, result);
6691 /* if left is same as result */
6692 if (sameRegs (AOP (result), AOP (left)))
6694 for (; size--; offset++)
6696 if (AOP_TYPE (right) == AOP_LIT)
6698 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6701 /* dummy read of volatile operand */
6702 if (isOperandVolatile (left, FALSE))
6703 MOVA (aopGet (left, offset, FALSE, FALSE));
6707 else if (IS_AOP_PREG (left))
6709 MOVA (aopGet (left, offset, FALSE, TRUE));
6710 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6711 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6715 emitcode ("xrl", "%s,%s",
6716 aopGet (left, offset, FALSE, TRUE),
6717 aopGet (right, offset, FALSE, FALSE));
6722 if (AOP_TYPE (left) == AOP_ACC)
6725 emitcode("mov", "a,b");
6726 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6730 MOVA (aopGet (right, offset, FALSE, FALSE));
6731 if (IS_AOP_PREG (left))
6733 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6734 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6737 emitcode ("xrl", "%s,a",
6738 aopGet (left, offset, FALSE, TRUE));
6745 // left & result in different registers
6746 if (AOP_TYPE (result) == AOP_CRY)
6749 // if(size), result in bit
6750 // if(!size && ifx), conditional oper: if(left ^ right)
6751 symbol *tlbl = newiTempLabel (NULL);
6752 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6754 emitcode ("setb", "c");
6757 if ((AOP_TYPE (right) == AOP_LIT) &&
6758 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6760 MOVA (aopGet (left, offset, FALSE, FALSE));
6764 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6766 emitcode("mov", "a,b");
6767 emitcode ("xrl", "a,%s",
6768 aopGet (right, offset, FALSE, FALSE));
6770 MOVA (aopGet (right, offset, FALSE, FALSE));
6771 emitcode ("xrl", "a,%s",
6772 aopGet (left, offset, FALSE, FALSE));
6775 emitcode ("jnz", "%05d$", tlbl->key + 100);
6781 emitcode ("", "%05d$:", tlbl->key + 100);
6785 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6789 for (; (size--); offset++)
6792 // result = left & right
6793 if (AOP_TYPE (right) == AOP_LIT)
6795 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6799 aopGet (left, offset, FALSE, FALSE),
6801 isOperandVolatile (result, FALSE));
6805 // faster than result <- left, anl result,right
6806 // and better if result is SFR
6807 if (AOP_TYPE (left) == AOP_ACC)
6810 emitcode("mov", "a,b");
6811 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6815 MOVA (aopGet (right, offset, FALSE, FALSE));
6816 emitcode ("xrl", "a,%s",
6817 aopGet (left, offset, FALSE, TRUE));
6819 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6825 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6826 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (result, NULL, ic, TRUE);
6830 /*-----------------------------------------------------------------*/
6831 /* genInline - write the inline code out */
6832 /*-----------------------------------------------------------------*/
6834 genInline (iCode * ic)
6836 char *buffer, *bp, *bp1;
6838 D(emitcode ("; genInline",""));
6840 _G.inLine += (!options.asmpeep);
6842 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6843 strcpy (buffer, IC_INLINE (ic));
6845 /* emit each line as a code */
6856 /* Add \n for labels, not dirs such as c:\mydir */
6857 if ( (*bp == ':') && (isspace(bp[1])) )
6871 /* emitcode("",buffer); */
6872 _G.inLine -= (!options.asmpeep);
6875 /*-----------------------------------------------------------------*/
6876 /* genRRC - rotate right with carry */
6877 /*-----------------------------------------------------------------*/
6881 operand *left, *result;
6882 int size, offset = 0;
6885 D(emitcode ("; genRRC",""));
6887 /* rotate right with carry */
6888 left = IC_LEFT (ic);
6889 result = IC_RESULT (ic);
6890 aopOp (left, ic, FALSE);
6891 aopOp (result, ic, FALSE);
6893 /* move it to the result */
6894 size = AOP_SIZE (result);
6896 if (size == 1) { /* special case for 1 byte */
6897 l = aopGet (left, offset, FALSE, FALSE);
6899 emitcode ("rr", "a");
6902 /* no need to clear carry, bit7 will be written later */
6905 l = aopGet (left, offset, FALSE, FALSE);
6907 emitcode ("rrc", "a");
6908 if (AOP_SIZE (result) > 1)
6909 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
6911 /* now we need to put the carry into the
6912 highest order byte of the result */
6913 if (AOP_SIZE (result) > 1)
6915 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
6918 emitcode ("mov", "acc.7,c");
6920 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6921 freeAsmop (left, NULL, ic, TRUE);
6922 freeAsmop (result, NULL, ic, TRUE);
6925 /*-----------------------------------------------------------------*/
6926 /* genRLC - generate code for rotate left with carry */
6927 /*-----------------------------------------------------------------*/
6931 operand *left, *result;
6932 int size, offset = 0;
6935 D(emitcode ("; genRLC",""));
6937 /* rotate right with carry */
6938 left = IC_LEFT (ic);
6939 result = IC_RESULT (ic);
6940 aopOp (left, ic, FALSE);
6941 aopOp (result, ic, FALSE);
6943 /* move it to the result */
6944 size = AOP_SIZE (result);
6948 l = aopGet (left, offset, FALSE, FALSE);
6950 if (size == 0) { /* special case for 1 byte */
6954 emitcode("rlc","a"); /* bit0 will be written later */
6955 if (AOP_SIZE (result) > 1)
6956 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6959 l = aopGet (left, offset, FALSE, FALSE);
6961 emitcode ("rlc", "a");
6962 if (AOP_SIZE (result) > 1)
6963 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6966 /* now we need to put the carry into the
6967 highest order byte of the result */
6968 if (AOP_SIZE (result) > 1)
6970 l = aopGet (result, 0, FALSE, FALSE);
6973 emitcode ("mov", "acc.0,c");
6975 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6976 freeAsmop (left, NULL, ic, TRUE);
6977 freeAsmop (result, NULL, ic, TRUE);
6980 /*-----------------------------------------------------------------*/
6981 /* genGetHbit - generates code get highest order bit */
6982 /*-----------------------------------------------------------------*/
6984 genGetHbit (iCode * ic)
6986 operand *left, *result;
6988 D(emitcode ("; genGetHbit",""));
6990 left = IC_LEFT (ic);
6991 result = IC_RESULT (ic);
6992 aopOp (left, ic, FALSE);
6993 aopOp (result, ic, FALSE);
6995 /* get the highest order byte into a */
6996 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
6997 if (AOP_TYPE (result) == AOP_CRY)
6999 emitcode ("rlc", "a");
7004 emitcode ("rl", "a");
7005 emitcode ("anl", "a,#0x01");
7010 freeAsmop (left, NULL, ic, TRUE);
7011 freeAsmop (result, NULL, ic, TRUE);
7014 /*-----------------------------------------------------------------*/
7015 /* genSwap - generates code to swap nibbles or bytes */
7016 /*-----------------------------------------------------------------*/
7018 genSwap (iCode * ic)
7020 operand *left, *result;
7022 D(emitcode ("; genSwap",""));
7024 left = IC_LEFT (ic);
7025 result = IC_RESULT (ic);
7026 aopOp (left, ic, FALSE);
7027 aopOp (result, ic, FALSE);
7029 switch (AOP_SIZE (left))
7031 case 1: /* swap nibbles in byte */
7032 MOVA (aopGet (left, 0, FALSE, FALSE));
7033 emitcode ("swap", "a");
7034 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7036 case 2: /* swap bytes in word */
7037 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7039 MOVA (aopGet (left, 0, FALSE, FALSE));
7040 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7041 0, isOperandVolatile (result, FALSE));
7042 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7044 else if (operandsEqu (left, result))
7047 bool pushedB = FALSE, leftInB = FALSE;
7049 MOVA (aopGet (left, 0, FALSE, FALSE));
7050 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7053 emitcode ("mov", "b,a");
7057 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7058 0, isOperandVolatile (result, FALSE));
7059 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7066 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7067 0, isOperandVolatile (result, FALSE));
7068 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7069 1, isOperandVolatile (result, FALSE));
7073 wassertl(FALSE, "unsupported SWAP operand size");
7076 freeAsmop (left, NULL, ic, TRUE);
7077 freeAsmop (result, NULL, ic, TRUE);
7081 /*-----------------------------------------------------------------*/
7082 /* AccRol - rotate left accumulator by known count */
7083 /*-----------------------------------------------------------------*/
7085 AccRol (int shCount)
7087 shCount &= 0x0007; // shCount : 0..7
7094 emitcode ("rl", "a");
7097 emitcode ("rl", "a");
7098 emitcode ("rl", "a");
7101 emitcode ("swap", "a");
7102 emitcode ("rr", "a");
7105 emitcode ("swap", "a");
7108 emitcode ("swap", "a");
7109 emitcode ("rl", "a");
7112 emitcode ("rr", "a");
7113 emitcode ("rr", "a");
7116 emitcode ("rr", "a");
7121 /*-----------------------------------------------------------------*/
7122 /* AccLsh - left shift accumulator by known count */
7123 /*-----------------------------------------------------------------*/
7125 AccLsh (int shCount)
7130 emitcode ("add", "a,acc");
7131 else if (shCount == 2)
7133 emitcode ("add", "a,acc");
7134 emitcode ("add", "a,acc");
7138 /* rotate left accumulator */
7140 /* and kill the lower order bits */
7141 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7146 /*-----------------------------------------------------------------*/
7147 /* AccRsh - right shift accumulator by known count */
7148 /*-----------------------------------------------------------------*/
7150 AccRsh (int shCount)
7157 emitcode ("rrc", "a");
7161 /* rotate right accumulator */
7162 AccRol (8 - shCount);
7163 /* and kill the higher order bits */
7164 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7169 /*-----------------------------------------------------------------*/
7170 /* AccSRsh - signed right shift accumulator by known count */
7171 /*-----------------------------------------------------------------*/
7173 AccSRsh (int shCount)
7180 emitcode ("mov", "c,acc.7");
7181 emitcode ("rrc", "a");
7183 else if (shCount == 2)
7185 emitcode ("mov", "c,acc.7");
7186 emitcode ("rrc", "a");
7187 emitcode ("mov", "c,acc.7");
7188 emitcode ("rrc", "a");
7192 tlbl = newiTempLabel (NULL);
7193 /* rotate right accumulator */
7194 AccRol (8 - shCount);
7195 /* and kill the higher order bits */
7196 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7197 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7198 emitcode ("orl", "a,#0x%02x",
7199 (unsigned char) ~SRMask[shCount]);
7200 emitcode ("", "%05d$:", tlbl->key + 100);
7205 /*-----------------------------------------------------------------*/
7206 /* shiftR1Left2Result - shift right one byte from left to result */
7207 /*-----------------------------------------------------------------*/
7209 shiftR1Left2Result (operand * left, int offl,
7210 operand * result, int offr,
7211 int shCount, int sign)
7213 MOVA (aopGet (left, offl, FALSE, FALSE));
7214 /* shift right accumulator */
7219 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7222 /*-----------------------------------------------------------------*/
7223 /* shiftL1Left2Result - shift left one byte from left to result */
7224 /*-----------------------------------------------------------------*/
7226 shiftL1Left2Result (operand * left, int offl,
7227 operand * result, int offr, int shCount)
7230 l = aopGet (left, offl, FALSE, FALSE);
7232 /* shift left accumulator */
7234 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7237 /*-----------------------------------------------------------------*/
7238 /* movLeft2Result - move byte from left to result */
7239 /*-----------------------------------------------------------------*/
7241 movLeft2Result (operand * left, int offl,
7242 operand * result, int offr, int sign)
7245 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7247 l = aopGet (left, offl, FALSE, FALSE);
7249 if (*l == '@' && (IS_AOP_PREG (result)))
7251 emitcode ("mov", "a,%s", l);
7252 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7257 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7260 /* MSB sign in acc.7 ! */
7261 if (getDataSize (left) == offl + 1)
7263 emitcode ("mov", "a,%s", l);
7264 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7273 /*-----------------------------------------------------------------*/
7277 emitcode ("rrc", "a");
7278 emitcode ("xch", "a,%s", x);
7279 emitcode ("rrc", "a");
7280 emitcode ("xch", "a,%s", x);
7283 /*-----------------------------------------------------------------*/
7284 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7285 /*-----------------------------------------------------------------*/
7289 emitcode ("xch", "a,%s", x);
7290 emitcode ("rlc", "a");
7291 emitcode ("xch", "a,%s", x);
7292 emitcode ("rlc", "a");
7295 /*-----------------------------------------------------------------*/
7296 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7297 /*-----------------------------------------------------------------*/
7301 emitcode ("xch", "a,%s", x);
7302 emitcode ("add", "a,acc");
7303 emitcode ("xch", "a,%s", x);
7304 emitcode ("rlc", "a");
7307 /*-----------------------------------------------------------------*/
7308 /* AccAXLsh - left shift a:x by known count (0..7) */
7309 /*-----------------------------------------------------------------*/
7311 AccAXLsh (char *x, int shCount)
7326 case 5: // AAAAABBB:CCCCCDDD
7328 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7330 emitcode ("anl", "a,#0x%02x",
7331 SLMask[shCount]); // BBB00000:CCCCCDDD
7333 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7335 AccRol (shCount); // DDDCCCCC:BBB00000
7337 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7339 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7341 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7343 emitcode ("anl", "a,#0x%02x",
7344 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7346 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7348 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7351 case 6: // AAAAAABB:CCCCCCDD
7352 emitcode ("anl", "a,#0x%02x",
7353 SRMask[shCount]); // 000000BB:CCCCCCDD
7354 emitcode ("mov", "c,acc.0"); // c = B
7355 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7357 AccAXRrl1 (x); // BCCCCCCD:D000000B
7358 AccAXRrl1 (x); // BBCCCCCC:DD000000
7360 emitcode("rrc","a");
7361 emitcode("xch","a,%s", x);
7362 emitcode("rrc","a");
7363 emitcode("mov","c,acc.0"); //<< get correct bit
7364 emitcode("xch","a,%s", x);
7366 emitcode("rrc","a");
7367 emitcode("xch","a,%s", x);
7368 emitcode("rrc","a");
7369 emitcode("xch","a,%s", x);
7372 case 7: // a:x <<= 7
7374 emitcode ("anl", "a,#0x%02x",
7375 SRMask[shCount]); // 0000000B:CCCCCCCD
7377 emitcode ("mov", "c,acc.0"); // c = B
7379 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7381 AccAXRrl1 (x); // BCCCCCCC:D0000000
7389 /*-----------------------------------------------------------------*/
7390 /* AccAXRsh - right shift a:x known count (0..7) */
7391 /*-----------------------------------------------------------------*/
7393 AccAXRsh (char *x, int shCount)
7401 AccAXRrl1 (x); // 0->a:x
7406 AccAXRrl1 (x); // 0->a:x
7409 AccAXRrl1 (x); // 0->a:x
7414 case 5: // AAAAABBB:CCCCCDDD = a:x
7416 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7418 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7420 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7422 emitcode ("anl", "a,#0x%02x",
7423 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7425 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7427 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7429 emitcode ("anl", "a,#0x%02x",
7430 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7432 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7434 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7436 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7439 case 6: // AABBBBBB:CCDDDDDD
7441 emitcode ("mov", "c,acc.7");
7442 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7444 emitcode ("mov", "c,acc.7");
7445 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7447 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7449 emitcode ("anl", "a,#0x%02x",
7450 SRMask[shCount]); // 000000AA:BBBBBBCC
7453 case 7: // ABBBBBBB:CDDDDDDD
7455 emitcode ("mov", "c,acc.7"); // c = A
7457 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7459 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7461 emitcode ("anl", "a,#0x%02x",
7462 SRMask[shCount]); // 0000000A:BBBBBBBC
7470 /*-----------------------------------------------------------------*/
7471 /* AccAXRshS - right shift signed a:x known count (0..7) */
7472 /*-----------------------------------------------------------------*/
7474 AccAXRshS (char *x, int shCount)
7482 emitcode ("mov", "c,acc.7");
7483 AccAXRrl1 (x); // s->a:x
7487 emitcode ("mov", "c,acc.7");
7488 AccAXRrl1 (x); // s->a:x
7490 emitcode ("mov", "c,acc.7");
7491 AccAXRrl1 (x); // s->a:x
7496 case 5: // AAAAABBB:CCCCCDDD = a:x
7498 tlbl = newiTempLabel (NULL);
7499 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7501 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7503 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7505 emitcode ("anl", "a,#0x%02x",
7506 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7508 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7510 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7512 emitcode ("anl", "a,#0x%02x",
7513 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7515 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7517 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7519 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7521 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7522 emitcode ("orl", "a,#0x%02x",
7523 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7525 emitcode ("", "%05d$:", tlbl->key + 100);
7526 break; // SSSSAAAA:BBBCCCCC
7528 case 6: // AABBBBBB:CCDDDDDD
7530 tlbl = newiTempLabel (NULL);
7531 emitcode ("mov", "c,acc.7");
7532 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7534 emitcode ("mov", "c,acc.7");
7535 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7537 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7539 emitcode ("anl", "a,#0x%02x",
7540 SRMask[shCount]); // 000000AA:BBBBBBCC
7542 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7543 emitcode ("orl", "a,#0x%02x",
7544 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7546 emitcode ("", "%05d$:", tlbl->key + 100);
7548 case 7: // ABBBBBBB:CDDDDDDD
7550 tlbl = newiTempLabel (NULL);
7551 emitcode ("mov", "c,acc.7"); // c = A
7553 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7555 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7557 emitcode ("anl", "a,#0x%02x",
7558 SRMask[shCount]); // 0000000A:BBBBBBBC
7560 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7561 emitcode ("orl", "a,#0x%02x",
7562 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7564 emitcode ("", "%05d$:", tlbl->key + 100);
7571 /*-----------------------------------------------------------------*/
7572 /* shiftL2Left2Result - shift left two bytes from left to result */
7573 /*-----------------------------------------------------------------*/
7575 shiftL2Left2Result (operand * left, int offl,
7576 operand * result, int offr, int shCount)
7578 if (sameRegs (AOP (result), AOP (left)) &&
7579 ((offl + MSB16) == offr))
7581 /* don't crash result[offr] */
7582 MOVA (aopGet (left, offl, FALSE, FALSE));
7583 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7587 movLeft2Result (left, offl, result, offr, 0);
7588 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7590 /* ax << shCount (x = lsb(result)) */
7591 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7592 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7596 /*-----------------------------------------------------------------*/
7597 /* shiftR2Left2Result - shift right two bytes from left to result */
7598 /*-----------------------------------------------------------------*/
7600 shiftR2Left2Result (operand * left, int offl,
7601 operand * result, int offr,
7602 int shCount, int sign)
7604 if (sameRegs (AOP (result), AOP (left)) &&
7605 ((offl + MSB16) == offr))
7607 /* don't crash result[offr] */
7608 MOVA (aopGet (left, offl, FALSE, FALSE));
7609 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7613 movLeft2Result (left, offl, result, offr, 0);
7614 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7616 /* a:x >> shCount (x = lsb(result)) */
7618 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7620 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7621 if (getDataSize (result) > 1)
7622 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7625 /*-----------------------------------------------------------------*/
7626 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7627 /*-----------------------------------------------------------------*/
7629 shiftLLeftOrResult (operand * left, int offl,
7630 operand * result, int offr, int shCount)
7632 MOVA (aopGet (left, offl, FALSE, FALSE));
7633 /* shift left accumulator */
7635 /* or with result */
7636 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7637 /* back to result */
7638 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7641 /*-----------------------------------------------------------------*/
7642 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7643 /*-----------------------------------------------------------------*/
7645 shiftRLeftOrResult (operand * left, int offl,
7646 operand * result, int offr, int shCount)
7648 MOVA (aopGet (left, offl, FALSE, FALSE));
7649 /* shift right accumulator */
7651 /* or with result */
7652 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7653 /* back to result */
7654 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7657 /*-----------------------------------------------------------------*/
7658 /* genlshOne - left shift a one byte quantity by known count */
7659 /*-----------------------------------------------------------------*/
7661 genlshOne (operand * result, operand * left, int shCount)
7663 D(emitcode ("; genlshOne",""));
7665 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7668 /*-----------------------------------------------------------------*/
7669 /* genlshTwo - left shift two bytes by known amount != 0 */
7670 /*-----------------------------------------------------------------*/
7672 genlshTwo (operand * result, operand * left, int shCount)
7676 D(emitcode ("; genlshTwo",""));
7678 size = getDataSize (result);
7680 /* if shCount >= 8 */
7688 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7690 movLeft2Result (left, LSB, result, MSB16, 0);
7692 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7695 /* 1 <= shCount <= 7 */
7699 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7701 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7705 /*-----------------------------------------------------------------*/
7706 /* shiftLLong - shift left one long from left to result */
7707 /* offl = LSB or MSB16 */
7708 /*-----------------------------------------------------------------*/
7710 shiftLLong (operand * left, operand * result, int offr)
7713 int size = AOP_SIZE (result);
7715 if (size >= LSB + offr)
7717 l = aopGet (left, LSB, FALSE, FALSE);
7719 emitcode ("add", "a,acc");
7720 if (sameRegs (AOP (left), AOP (result)) &&
7721 size >= MSB16 + offr && offr != LSB)
7722 emitcode ("xch", "a,%s",
7723 aopGet (left, LSB + offr, FALSE, FALSE));
7725 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7728 if (size >= MSB16 + offr)
7730 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7732 l = aopGet (left, MSB16, FALSE, FALSE);
7735 emitcode ("rlc", "a");
7736 if (sameRegs (AOP (left), AOP (result)) &&
7737 size >= MSB24 + offr && offr != LSB)
7738 emitcode ("xch", "a,%s",
7739 aopGet (left, MSB16 + offr, FALSE, FALSE));
7741 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7744 if (size >= MSB24 + offr)
7746 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7748 l = aopGet (left, MSB24, FALSE, FALSE);
7751 emitcode ("rlc", "a");
7752 if (sameRegs (AOP (left), AOP (result)) &&
7753 size >= MSB32 + offr && offr != LSB)
7754 emitcode ("xch", "a,%s",
7755 aopGet (left, MSB24 + offr, FALSE, FALSE));
7757 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7760 if (size > MSB32 + offr)
7762 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7764 l = aopGet (left, MSB32, FALSE, FALSE);
7767 emitcode ("rlc", "a");
7768 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7771 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7774 /*-----------------------------------------------------------------*/
7775 /* genlshFour - shift four byte by a known amount != 0 */
7776 /*-----------------------------------------------------------------*/
7778 genlshFour (operand * result, operand * left, int shCount)
7782 D(emitcode ("; genlshFour",""));
7784 size = AOP_SIZE (result);
7786 /* if shifting more that 3 bytes */
7791 /* lowest order of left goes to the highest
7792 order of the destination */
7793 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7795 movLeft2Result (left, LSB, result, MSB32, 0);
7796 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7797 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7798 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
7802 /* more than two bytes */
7803 else if (shCount >= 16)
7805 /* lower order two bytes goes to higher order two bytes */
7807 /* if some more remaining */
7809 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7812 movLeft2Result (left, MSB16, result, MSB32, 0);
7813 movLeft2Result (left, LSB, result, MSB24, 0);
7815 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7816 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7820 /* if more than 1 byte */
7821 else if (shCount >= 8)
7823 /* lower order three bytes goes to higher order three bytes */
7828 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7830 movLeft2Result (left, LSB, result, MSB16, 0);
7836 movLeft2Result (left, MSB24, result, MSB32, 0);
7837 movLeft2Result (left, MSB16, result, MSB24, 0);
7838 movLeft2Result (left, LSB, result, MSB16, 0);
7839 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7841 else if (shCount == 1)
7842 shiftLLong (left, result, MSB16);
7845 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7846 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7847 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7848 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7853 /* 1 <= shCount <= 7 */
7854 else if (shCount <= 2)
7856 shiftLLong (left, result, LSB);
7858 shiftLLong (result, result, LSB);
7860 /* 3 <= shCount <= 7, optimize */
7863 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7864 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7865 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7869 /*-----------------------------------------------------------------*/
7870 /* genLeftShiftLiteral - left shifting by known count */
7871 /*-----------------------------------------------------------------*/
7873 genLeftShiftLiteral (operand * left,
7878 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7881 D(emitcode ("; genLeftShiftLiteral",""));
7883 freeAsmop (right, NULL, ic, TRUE);
7885 aopOp (left, ic, FALSE);
7886 aopOp (result, ic, FALSE);
7888 size = getSize (operandType (result));
7891 emitcode ("; shift left ", "result %d, left %d", size,
7895 /* I suppose that the left size >= result size */
7900 movLeft2Result (left, size, result, size, 0);
7904 else if (shCount >= (size * 8))
7906 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
7912 genlshOne (result, left, shCount);
7916 genlshTwo (result, left, shCount);
7920 genlshFour (result, left, shCount);
7923 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7924 "*** ack! mystery literal shift!\n");
7928 freeAsmop (left, NULL, ic, TRUE);
7929 freeAsmop (result, NULL, ic, TRUE);
7932 /*-----------------------------------------------------------------*/
7933 /* genLeftShift - generates code for left shifting */
7934 /*-----------------------------------------------------------------*/
7936 genLeftShift (iCode * ic)
7938 operand *left, *right, *result;
7941 symbol *tlbl, *tlbl1;
7944 D(emitcode ("; genLeftShift",""));
7946 right = IC_RIGHT (ic);
7947 left = IC_LEFT (ic);
7948 result = IC_RESULT (ic);
7950 aopOp (right, ic, FALSE);
7952 /* if the shift count is known then do it
7953 as efficiently as possible */
7954 if (AOP_TYPE (right) == AOP_LIT)
7956 genLeftShiftLiteral (left, right, result, ic);
7960 /* shift count is unknown then we have to form
7961 a loop get the loop count in B : Note: we take
7962 only the lower order byte since shifting
7963 more that 32 bits make no sense anyway, ( the
7964 largest size of an object can be only 32 bits ) */
7967 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
7968 emitcode ("inc", "b");
7969 freeAsmop (right, NULL, ic, TRUE);
7970 aopOp (left, ic, FALSE);
7971 aopOp (result, ic, FALSE);
7973 /* now move the left to the result if they are not the same */
7974 if (!sameRegs (AOP (left), AOP (result)) &&
7975 AOP_SIZE (result) > 1)
7978 size = AOP_SIZE (result);
7982 l = aopGet (left, offset, FALSE, TRUE);
7983 if (*l == '@' && (IS_AOP_PREG (result)))
7986 emitcode ("mov", "a,%s", l);
7987 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7990 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
7995 tlbl = newiTempLabel (NULL);
7996 size = AOP_SIZE (result);
7998 tlbl1 = newiTempLabel (NULL);
8000 /* if it is only one byte then */
8003 symbol *tlbl1 = newiTempLabel (NULL);
8005 l = aopGet (left, 0, FALSE, FALSE);
8007 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8008 emitcode ("", "%05d$:", tlbl->key + 100);
8009 emitcode ("add", "a,acc");
8010 emitcode ("", "%05d$:", tlbl1->key + 100);
8011 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8013 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8017 reAdjustPreg (AOP (result));
8019 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8020 emitcode ("", "%05d$:", tlbl->key + 100);
8021 l = aopGet (result, offset, FALSE, FALSE);
8023 emitcode ("add", "a,acc");
8024 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8027 l = aopGet (result, offset, FALSE, FALSE);
8029 emitcode ("rlc", "a");
8030 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8032 reAdjustPreg (AOP (result));
8034 emitcode ("", "%05d$:", tlbl1->key + 100);
8035 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8038 freeAsmop (left, NULL, ic, TRUE);
8039 freeAsmop (result, NULL, ic, TRUE);
8042 /*-----------------------------------------------------------------*/
8043 /* genrshOne - right shift a one byte quantity by known count */
8044 /*-----------------------------------------------------------------*/
8046 genrshOne (operand * result, operand * left,
8047 int shCount, int sign)
8049 D(emitcode ("; genrshOne",""));
8051 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8054 /*-----------------------------------------------------------------*/
8055 /* genrshTwo - right shift two bytes by known amount != 0 */
8056 /*-----------------------------------------------------------------*/
8058 genrshTwo (operand * result, operand * left,
8059 int shCount, int sign)
8061 D(emitcode ("; genrshTwo",""));
8063 /* if shCount >= 8 */
8068 shiftR1Left2Result (left, MSB16, result, LSB,
8071 movLeft2Result (left, MSB16, result, LSB, sign);
8072 addSign (result, MSB16, sign);
8075 /* 1 <= shCount <= 7 */
8077 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8080 /*-----------------------------------------------------------------*/
8081 /* shiftRLong - shift right one long from left to result */
8082 /* offl = LSB or MSB16 */
8083 /*-----------------------------------------------------------------*/
8085 shiftRLong (operand * left, int offl,
8086 operand * result, int sign)
8088 int isSameRegs=sameRegs(AOP(left),AOP(result));
8090 if (isSameRegs && offl>1) {
8091 // we are in big trouble, but this shouldn't happen
8092 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8095 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8100 emitcode ("rlc", "a");
8101 emitcode ("subb", "a,acc");
8103 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8105 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8106 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8109 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8114 emitcode ("clr", "c");
8116 emitcode ("mov", "c,acc.7");
8119 emitcode ("rrc", "a");
8121 if (isSameRegs && offl==MSB16) {
8122 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8124 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8125 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8128 emitcode ("rrc", "a");
8129 if (isSameRegs && offl==1) {
8130 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8132 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8133 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8135 emitcode ("rrc", "a");
8136 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8140 MOVA (aopGet (left, LSB, FALSE, FALSE));
8141 emitcode ("rrc", "a");
8142 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8146 /*-----------------------------------------------------------------*/
8147 /* genrshFour - shift four byte by a known amount != 0 */
8148 /*-----------------------------------------------------------------*/
8150 genrshFour (operand * result, operand * left,
8151 int shCount, int sign)
8153 D(emitcode ("; genrshFour",""));
8155 /* if shifting more that 3 bytes */
8160 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8162 movLeft2Result (left, MSB32, result, LSB, sign);
8163 addSign (result, MSB16, sign);
8165 else if (shCount >= 16)
8169 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8172 movLeft2Result (left, MSB24, result, LSB, 0);
8173 movLeft2Result (left, MSB32, result, MSB16, sign);
8175 addSign (result, MSB24, sign);
8177 else if (shCount >= 8)
8181 shiftRLong (left, MSB16, result, sign);
8182 else if (shCount == 0)
8184 movLeft2Result (left, MSB16, result, LSB, 0);
8185 movLeft2Result (left, MSB24, result, MSB16, 0);
8186 movLeft2Result (left, MSB32, result, MSB24, sign);
8187 addSign (result, MSB32, sign);
8191 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8192 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8193 /* the last shift is signed */
8194 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8195 addSign (result, MSB32, sign);
8199 { /* 1 <= shCount <= 7 */
8202 shiftRLong (left, LSB, result, sign);
8204 shiftRLong (result, LSB, result, sign);
8208 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8209 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8210 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8215 /*-----------------------------------------------------------------*/
8216 /* genRightShiftLiteral - right shifting by known count */
8217 /*-----------------------------------------------------------------*/
8219 genRightShiftLiteral (operand * left,
8225 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8228 D(emitcode ("; genRightShiftLiteral",""));
8230 freeAsmop (right, NULL, ic, TRUE);
8232 aopOp (left, ic, FALSE);
8233 aopOp (result, ic, FALSE);
8236 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8240 size = getDataSize (left);
8241 /* test the LEFT size !!! */
8243 /* I suppose that the left size >= result size */
8246 size = getDataSize (result);
8248 movLeft2Result (left, size, result, size, 0);
8251 else if (shCount >= (size * 8))
8254 /* get sign in acc.7 */
8255 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8257 addSign (result, LSB, sign);
8264 genrshOne (result, left, shCount, sign);
8268 genrshTwo (result, left, shCount, sign);
8272 genrshFour (result, left, shCount, sign);
8278 freeAsmop (left, NULL, ic, TRUE);
8279 freeAsmop (result, NULL, ic, TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genSignedRightShift - right shift of signed number */
8284 /*-----------------------------------------------------------------*/
8286 genSignedRightShift (iCode * ic)
8288 operand *right, *left, *result;
8291 symbol *tlbl, *tlbl1;
8294 D(emitcode ("; genSignedRightShift",""));
8296 /* we do it the hard way put the shift count in b
8297 and loop thru preserving the sign */
8299 right = IC_RIGHT (ic);
8300 left = IC_LEFT (ic);
8301 result = IC_RESULT (ic);
8303 aopOp (right, ic, FALSE);
8306 if (AOP_TYPE (right) == AOP_LIT)
8308 genRightShiftLiteral (left, right, result, ic, 1);
8311 /* shift count is unknown then we have to form
8312 a loop get the loop count in B : Note: we take
8313 only the lower order byte since shifting
8314 more that 32 bits make no sense anyway, ( the
8315 largest size of an object can be only 32 bits ) */
8318 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8319 emitcode ("inc", "b");
8320 freeAsmop (right, NULL, ic, TRUE);
8321 aopOp (left, ic, FALSE);
8322 aopOp (result, ic, FALSE);
8324 /* now move the left to the result if they are not the
8326 if (!sameRegs (AOP (left), AOP (result)) &&
8327 AOP_SIZE (result) > 1)
8330 size = AOP_SIZE (result);
8334 l = aopGet (left, offset, FALSE, TRUE);
8335 if (*l == '@' && IS_AOP_PREG (result))
8338 emitcode ("mov", "a,%s", l);
8339 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8342 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8347 /* mov the highest order bit to OVR */
8348 tlbl = newiTempLabel (NULL);
8349 tlbl1 = newiTempLabel (NULL);
8351 size = AOP_SIZE (result);
8353 MOVA (aopGet (left, offset, FALSE, FALSE));
8354 emitcode ("rlc", "a");
8355 emitcode ("mov", "ov,c");
8356 /* if it is only one byte then */
8359 l = aopGet (left, 0, FALSE, FALSE);
8361 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8362 emitcode ("", "%05d$:", tlbl->key + 100);
8363 emitcode ("mov", "c,ov");
8364 emitcode ("rrc", "a");
8365 emitcode ("", "%05d$:", tlbl1->key + 100);
8366 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8368 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8372 reAdjustPreg (AOP (result));
8373 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8374 emitcode ("", "%05d$:", tlbl->key + 100);
8375 emitcode ("mov", "c,ov");
8378 l = aopGet (result, offset, FALSE, FALSE);
8380 emitcode ("rrc", "a");
8381 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8383 reAdjustPreg (AOP (result));
8384 emitcode ("", "%05d$:", tlbl1->key + 100);
8385 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8389 freeAsmop (left, NULL, ic, TRUE);
8390 freeAsmop (result, NULL, ic, TRUE);
8393 /*-----------------------------------------------------------------*/
8394 /* genRightShift - generate code for right shifting */
8395 /*-----------------------------------------------------------------*/
8397 genRightShift (iCode * ic)
8399 operand *right, *left, *result;
8403 symbol *tlbl, *tlbl1;
8406 D(emitcode ("; genRightShift",""));
8408 /* if signed then we do it the hard way preserve the
8409 sign bit moving it inwards */
8410 letype = getSpec (operandType (IC_LEFT (ic)));
8412 if (!SPEC_USIGN (letype))
8414 genSignedRightShift (ic);
8418 /* signed & unsigned types are treated the same : i.e. the
8419 signed is NOT propagated inwards : quoting from the
8420 ANSI - standard : "for E1 >> E2, is equivalent to division
8421 by 2**E2 if unsigned or if it has a non-negative value,
8422 otherwise the result is implementation defined ", MY definition
8423 is that the sign does not get propagated */
8425 right = IC_RIGHT (ic);
8426 left = IC_LEFT (ic);
8427 result = IC_RESULT (ic);
8429 aopOp (right, ic, FALSE);
8431 /* if the shift count is known then do it
8432 as efficiently as possible */
8433 if (AOP_TYPE (right) == AOP_LIT)
8435 genRightShiftLiteral (left, right, result, ic, 0);
8439 /* shift count is unknown then we have to form
8440 a loop get the loop count in B : Note: we take
8441 only the lower order byte since shifting
8442 more that 32 bits make no sense anyway, ( the
8443 largest size of an object can be only 32 bits ) */
8446 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8447 emitcode ("inc", "b");
8448 freeAsmop (right, NULL, ic, TRUE);
8449 aopOp (left, ic, FALSE);
8450 aopOp (result, ic, FALSE);
8452 /* now move the left to the result if they are not the
8454 if (!sameRegs (AOP (left), AOP (result)) &&
8455 AOP_SIZE (result) > 1)
8458 size = AOP_SIZE (result);
8462 l = aopGet (left, offset, FALSE, TRUE);
8463 if (*l == '@' && IS_AOP_PREG (result))
8466 emitcode ("mov", "a,%s", l);
8467 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8470 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8475 tlbl = newiTempLabel (NULL);
8476 tlbl1 = newiTempLabel (NULL);
8477 size = AOP_SIZE (result);
8480 /* if it is only one byte then */
8483 l = aopGet (left, 0, FALSE, FALSE);
8485 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8486 emitcode ("", "%05d$:", tlbl->key + 100);
8488 emitcode ("rrc", "a");
8489 emitcode ("", "%05d$:", tlbl1->key + 100);
8490 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8492 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8496 reAdjustPreg (AOP (result));
8497 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8498 emitcode ("", "%05d$:", tlbl->key + 100);
8502 l = aopGet (result, offset, FALSE, FALSE);
8504 emitcode ("rrc", "a");
8505 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8507 reAdjustPreg (AOP (result));
8509 emitcode ("", "%05d$:", tlbl1->key + 100);
8510 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8514 freeAsmop (left, NULL, ic, TRUE);
8515 freeAsmop (result, NULL, ic, TRUE);
8518 /*-----------------------------------------------------------------*/
8519 /* emitPtrByteGet - emits code to get a byte into A through a */
8520 /* pointer register (R0, R1, or DPTR). The */
8521 /* original value of A can be preserved in B. */
8522 /*-----------------------------------------------------------------*/
8524 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8531 emitcode ("mov", "b,a");
8532 emitcode ("mov", "a,@%s", rname);
8537 emitcode ("mov", "b,a");
8538 emitcode ("movx", "a,@%s", rname);
8543 emitcode ("mov", "b,a");
8544 emitcode ("movx", "a,@dptr");
8549 emitcode ("mov", "b,a");
8550 emitcode ("clr", "a");
8551 emitcode ("movc", "a,@a+dptr");
8557 emitcode ("push", "b");
8558 emitcode ("push", "acc");
8560 emitcode ("lcall", "__gptrget");
8562 emitcode ("pop", "b");
8567 /*-----------------------------------------------------------------*/
8568 /* emitPtrByteSet - emits code to set a byte from src through a */
8569 /* pointer register (R0, R1, or DPTR). */
8570 /*-----------------------------------------------------------------*/
8572 emitPtrByteSet (char *rname, int p_type, char *src)
8581 emitcode ("mov", "@%s,a", rname);
8584 emitcode ("mov", "@%s,%s", rname, src);
8589 emitcode ("movx", "@%s,a", rname);
8594 emitcode ("movx", "@dptr,a");
8599 emitcode ("lcall", "__gptrput");
8604 /*-----------------------------------------------------------------*/
8605 /* genUnpackBits - generates code for unpacking bits */
8606 /*-----------------------------------------------------------------*/
8608 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8610 int offset = 0; /* result byte offset */
8611 int rsize; /* result size */
8612 int rlen = 0; /* remaining bitfield length */
8613 sym_link *etype; /* bitfield type information */
8614 int blen; /* bitfield length */
8615 int bstr; /* bitfield starting bit within byte */
8618 D(emitcode ("; genUnpackBits",""));
8620 etype = getSpec (operandType (result));
8621 rsize = getSize (operandType (result));
8622 blen = SPEC_BLEN (etype);
8623 bstr = SPEC_BSTR (etype);
8625 if (ifx && blen <= 8)
8627 emitPtrByteGet (rname, ptype, FALSE);
8630 SNPRINTF (buffer, sizeof(buffer),
8632 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8637 emitcode ("anl", "a,#0x%02x",
8638 (((unsigned char) -1) >> (8 - blen)) << bstr);
8639 genIfxJump (ifx, "a", NULL, NULL, NULL);
8645 /* If the bitfield length is less than a byte */
8648 emitPtrByteGet (rname, ptype, FALSE);
8650 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8651 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8655 /* Bit field did not fit in a byte. Copy all
8656 but the partial byte at the end. */
8657 for (rlen=blen;rlen>=8;rlen-=8)
8659 emitPtrByteGet (rname, ptype, FALSE);
8660 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8662 emitcode ("inc", "%s", rname);
8665 /* Handle the partial byte at the end */
8668 emitPtrByteGet (rname, ptype, FALSE);
8669 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8670 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8678 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8683 /*-----------------------------------------------------------------*/
8684 /* genDataPointerGet - generates code when ptr offset is known */
8685 /*-----------------------------------------------------------------*/
8687 genDataPointerGet (operand * left,
8693 int size, offset = 0;
8695 D(emitcode ("; genDataPointerGet",""));
8697 aopOp (result, ic, TRUE);
8699 /* get the string representation of the name */
8700 l = aopGet (left, 0, FALSE, TRUE);
8701 size = AOP_SIZE (result);
8705 sprintf (buffer, "(%s + %d)", l + 1, offset);
8707 sprintf (buffer, "%s", l + 1);
8708 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8711 freeAsmop (left, NULL, ic, TRUE);
8712 freeAsmop (result, NULL, ic, TRUE);
8715 /*-----------------------------------------------------------------*/
8716 /* genNearPointerGet - emitcode for near pointer fetch */
8717 /*-----------------------------------------------------------------*/
8719 genNearPointerGet (operand * left,
8728 sym_link *rtype, *retype;
8729 sym_link *ltype = operandType (left);
8732 D(emitcode ("; genNearPointerGet",""));
8734 rtype = operandType (result);
8735 retype = getSpec (rtype);
8737 aopOp (left, ic, FALSE);
8739 /* if left is rematerialisable and
8740 result is not bitfield variable type and
8741 the left is pointer to data space i.e
8742 lower 128 bytes of space */
8743 if (AOP_TYPE (left) == AOP_IMMD &&
8744 !IS_BITFIELD (retype) &&
8745 DCL_TYPE (ltype) == POINTER)
8747 genDataPointerGet (left, result, ic);
8751 /* if the value is already in a pointer register
8752 then don't need anything more */
8753 if (!AOP_INPREG (AOP (left)))
8755 if (IS_AOP_PREG (left))
8757 // Aha, it is a pointer, just in disguise.
8758 rname = aopGet (left, 0, FALSE, FALSE);
8761 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8762 __FILE__, __LINE__);
8767 emitcode ("mov", "a%s,%s", rname + 1, rname);
8768 rname++; // skip the '@'.
8773 /* otherwise get a free pointer register */
8775 preg = getFreePtr (ic, &aop, FALSE);
8776 emitcode ("mov", "%s,%s",
8778 aopGet (left, 0, FALSE, TRUE));
8783 rname = aopGet (left, 0, FALSE, FALSE);
8785 //aopOp (result, ic, FALSE);
8786 aopOp (result, ic, result?TRUE:FALSE);
8788 /* if bitfield then unpack the bits */
8789 if (IS_BITFIELD (retype))
8790 genUnpackBits (result, rname, POINTER, ifx);
8793 /* we have can just get the values */
8794 int size = AOP_SIZE (result);
8799 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8802 emitcode ("mov", "a,@%s", rname);
8804 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8808 sprintf (buffer, "@%s", rname);
8809 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
8813 emitcode ("inc", "%s", rname);
8817 /* now some housekeeping stuff */
8818 if (aop) /* we had to allocate for this iCode */
8820 if (pi) { /* post increment present */
8821 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8823 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8827 /* we did not allocate which means left
8828 already in a pointer register, then
8829 if size > 0 && this could be used again
8830 we have to point it back to where it
8832 if ((AOP_SIZE (result) > 1 &&
8833 !OP_SYMBOL (left)->remat &&
8834 (OP_SYMBOL (left)->liveTo > ic->seq ||
8838 int size = AOP_SIZE (result) - 1;
8840 emitcode ("dec", "%s", rname);
8844 if (ifx && !ifx->generated)
8846 genIfxJump (ifx, "a", left, NULL, result);
8850 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8851 freeAsmop (left, NULL, ic, TRUE);
8852 if (pi) pi->generated = 1;
8855 /*-----------------------------------------------------------------*/
8856 /* genPagedPointerGet - emitcode for paged pointer fetch */
8857 /*-----------------------------------------------------------------*/
8859 genPagedPointerGet (operand * left,
8868 sym_link *rtype, *retype;
8870 D(emitcode ("; genPagedPointerGet",""));
8872 rtype = operandType (result);
8873 retype = getSpec (rtype);
8875 aopOp (left, ic, FALSE);
8877 /* if the value is already in a pointer register
8878 then don't need anything more */
8879 if (!AOP_INPREG (AOP (left)))
8881 /* otherwise get a free pointer register */
8883 preg = getFreePtr (ic, &aop, FALSE);
8884 emitcode ("mov", "%s,%s",
8886 aopGet (left, 0, FALSE, TRUE));
8890 rname = aopGet (left, 0, FALSE, FALSE);
8892 aopOp (result, ic, FALSE);
8894 /* if bitfield then unpack the bits */
8895 if (IS_BITFIELD (retype))
8896 genUnpackBits (result, rname, PPOINTER, ifx);
8899 /* we have can just get the values */
8900 int size = AOP_SIZE (result);
8906 emitcode ("movx", "a,@%s", rname);
8908 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8913 emitcode ("inc", "%s", rname);
8917 /* now some housekeeping stuff */
8918 if (aop) /* we had to allocate for this iCode */
8920 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8921 freeAsmop (NULL, aop, ic, TRUE);
8925 /* we did not allocate which means left
8926 already in a pointer register, then
8927 if size > 0 && this could be used again
8928 we have to point it back to where it
8930 if ((AOP_SIZE (result) > 1 &&
8931 !OP_SYMBOL (left)->remat &&
8932 (OP_SYMBOL (left)->liveTo > ic->seq ||
8936 int size = AOP_SIZE (result) - 1;
8938 emitcode ("dec", "%s", rname);
8942 if (ifx && !ifx->generated)
8944 genIfxJump (ifx, "a", left, NULL, result);
8948 freeAsmop (left, NULL, ic, TRUE);
8949 freeAsmop (result, NULL, ic, TRUE);
8950 if (pi) pi->generated = 1;
8954 /*--------------------------------------------------------------------*/
8955 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8956 /*--------------------------------------------------------------------*/
8958 loadDptrFromOperand (operand *op, bool loadBToo)
8960 if (AOP_TYPE (op) != AOP_STR)
8962 /* if this is rematerializable */
8963 if (AOP_TYPE (op) == AOP_IMMD)
8965 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
8968 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8969 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
8972 wassertl(FALSE, "need pointerCode");
8973 emitcode ("", "; mov b,???");
8974 /* genPointerGet and genPointerSet originally did different
8975 ** things for this case. Both seem wrong.
8976 ** from genPointerGet:
8977 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8978 ** from genPointerSet:
8979 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
8984 else if (AOP_TYPE (op) == AOP_DPTR)
8988 MOVA (aopGet (op, 0, FALSE, FALSE));
8989 emitcode ("push", "acc");
8990 MOVA (aopGet (op, 1, FALSE, FALSE));
8991 emitcode ("push", "acc");
8992 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8993 emitcode ("pop", "dph");
8994 emitcode ("pop", "dpl");
8998 MOVA (aopGet (op, 0, FALSE, FALSE));
8999 emitcode ("push", "acc");
9000 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9001 emitcode ("pop", "dpl");
9005 { /* we need to get it byte by byte */
9006 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9007 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9009 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9014 /*-----------------------------------------------------------------*/
9015 /* genFarPointerGet - gget value from far space */
9016 /*-----------------------------------------------------------------*/
9018 genFarPointerGet (operand * left,
9019 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9022 sym_link *retype = getSpec (operandType (result));
9024 D(emitcode ("; genFarPointerGet",""));
9026 aopOp (left, ic, FALSE);
9027 loadDptrFromOperand (left, FALSE);
9029 /* so dptr now contains the address */
9030 aopOp (result, ic, FALSE);
9032 /* if bit then unpack */
9033 if (IS_BITFIELD (retype))
9034 genUnpackBits (result, "dptr", FPOINTER, ifx);
9037 size = AOP_SIZE (result);
9042 emitcode ("movx", "a,@dptr");
9044 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9046 emitcode ("inc", "dptr");
9050 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9052 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9053 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9057 if (ifx && !ifx->generated)
9059 genIfxJump (ifx, "a", left, NULL, result);
9062 freeAsmop (left, NULL, ic, TRUE);
9063 freeAsmop (result, NULL, ic, TRUE);
9066 /*-----------------------------------------------------------------*/
9067 /* genCodePointerGet - gget value from code space */
9068 /*-----------------------------------------------------------------*/
9070 genCodePointerGet (operand * left,
9071 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9074 sym_link *retype = getSpec (operandType (result));
9076 D(emitcode ("; genCodePointerGet",""));
9078 aopOp (left, ic, FALSE);
9079 loadDptrFromOperand (left, FALSE);
9081 /* so dptr now contains the address */
9082 aopOp (result, ic, FALSE);
9084 /* if bit then unpack */
9085 if (IS_BITFIELD (retype))
9086 genUnpackBits (result, "dptr", CPOINTER, ifx);
9089 size = AOP_SIZE (result);
9096 emitcode ("clr", "a");
9097 emitcode ("movc", "a,@a+dptr");
9099 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9100 emitcode ("inc", "dptr");
9104 emitcode ("mov", "a,#0x%02x", offset);
9105 emitcode ("movc", "a,@a+dptr");
9107 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9112 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9114 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9115 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9119 if (ifx && !ifx->generated)
9121 genIfxJump (ifx, "a", left, NULL, result);
9124 freeAsmop (left, NULL, ic, TRUE);
9125 freeAsmop (result, NULL, ic, TRUE);
9128 /*-----------------------------------------------------------------*/
9129 /* genGenPointerGet - gget value from generic pointer space */
9130 /*-----------------------------------------------------------------*/
9132 genGenPointerGet (operand * left,
9133 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9136 sym_link *retype = getSpec (operandType (result));
9138 D(emitcode ("; genGenPointerGet",""));
9140 aopOp (left, ic, FALSE);
9141 loadDptrFromOperand (left, TRUE);
9143 /* so dptr know contains the address */
9144 aopOp (result, ic, FALSE);
9146 /* if bit then unpack */
9147 if (IS_BITFIELD (retype))
9148 genUnpackBits (result, "dptr", GPOINTER, ifx);
9151 size = AOP_SIZE (result);
9156 emitcode ("lcall", "__gptrget");
9158 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9160 emitcode ("inc", "dptr");
9164 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9166 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9167 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9171 if (ifx && !ifx->generated)
9173 genIfxJump (ifx, "a", left, NULL, result);
9177 freeAsmop (left, NULL, ic, TRUE);
9178 freeAsmop (result, NULL, ic, TRUE);
9181 /*-----------------------------------------------------------------*/
9182 /* genPointerGet - generate code for pointer get */
9183 /*-----------------------------------------------------------------*/
9185 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9187 operand *left, *result;
9188 sym_link *type, *etype;
9191 D(emitcode ("; genPointerGet",""));
9193 left = IC_LEFT (ic);
9194 result = IC_RESULT (ic);
9196 if (getSize (operandType (result))>1)
9199 /* depending on the type of pointer we need to
9200 move it to the correct pointer register */
9201 type = operandType (left);
9202 etype = getSpec (type);
9203 /* if left is of type of pointer then it is simple */
9204 if (IS_PTR (type) && !IS_FUNC (type->next))
9205 p_type = DCL_TYPE (type);
9208 /* we have to go by the storage class */
9209 p_type = PTR_TYPE (SPEC_OCLS (etype));
9212 /* special case when cast remat */
9213 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9214 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9215 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9216 type = operandType (left);
9217 p_type = DCL_TYPE (type);
9219 /* now that we have the pointer type we assign
9220 the pointer values */
9226 genNearPointerGet (left, result, ic, pi, ifx);
9230 genPagedPointerGet (left, result, ic, pi, ifx);
9234 genFarPointerGet (left, result, ic, pi, ifx);
9238 genCodePointerGet (left, result, ic, pi, ifx);
9242 genGenPointerGet (left, result, ic, pi, ifx);
9250 /*-----------------------------------------------------------------*/
9251 /* genPackBits - generates code for packed bit storage */
9252 /*-----------------------------------------------------------------*/
9254 genPackBits (sym_link * etype,
9256 char *rname, int p_type)
9258 int offset = 0; /* source byte offset */
9259 int rlen = 0; /* remaining bitfield length */
9260 int blen; /* bitfield length */
9261 int bstr; /* bitfield starting bit within byte */
9262 int litval; /* source literal value (if AOP_LIT) */
9263 unsigned char mask; /* bitmask within current byte */
9265 D(emitcode ("; genPackBits",""));
9267 blen = SPEC_BLEN (etype);
9268 bstr = SPEC_BSTR (etype);
9270 /* If the bitfield length is less than a byte */
9273 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9274 (unsigned char) (0xFF >> (8 - bstr)));
9276 if (AOP_TYPE (right) == AOP_LIT)
9278 /* Case with a bitfield length <8 and literal source
9280 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9282 litval &= (~mask) & 0xff;
9283 emitPtrByteGet (rname, p_type, FALSE);
9284 if ((mask|litval)!=0xff)
9285 emitcode ("anl","a,#0x%02x", mask);
9287 emitcode ("orl","a,#0x%02x", litval);
9291 if ((blen==1) && (p_type!=GPOINTER))
9293 /* Case with a bitfield length == 1 and no generic pointer
9295 if (AOP_TYPE (right) == AOP_CRY)
9296 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9299 MOVA (aopGet (right, 0, FALSE, FALSE));
9300 emitcode ("rrc","a");
9302 emitPtrByteGet (rname, p_type, FALSE);
9303 emitcode ("mov","acc.%d,c",bstr);
9308 /* Case with a bitfield length < 8 and arbitrary source
9310 MOVA (aopGet (right, 0, FALSE, FALSE));
9311 /* shift and mask source value */
9313 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9316 /* transfer A to B and get next byte */
9317 emitPtrByteGet (rname, p_type, TRUE);
9319 emitcode ("anl", "a,#0x%02x", mask);
9320 emitcode ("orl", "a,b");
9321 if (p_type == GPOINTER)
9322 emitcode ("pop", "b");
9328 emitPtrByteSet (rname, p_type, "a");
9332 /* Bit length is greater than 7 bits. In this case, copy */
9333 /* all except the partial byte at the end */
9334 for (rlen=blen;rlen>=8;rlen-=8)
9336 emitPtrByteSet (rname, p_type,
9337 aopGet (right, offset++, FALSE, TRUE) );
9339 emitcode ("inc", "%s", rname);
9342 /* If there was a partial byte at the end */
9345 mask = (((unsigned char) -1 << rlen) & 0xff);
9347 if (AOP_TYPE (right) == AOP_LIT)
9349 /* Case with partial byte and literal source
9351 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9352 litval >>= (blen-rlen);
9353 litval &= (~mask) & 0xff;
9354 emitPtrByteGet (rname, p_type, FALSE);
9355 if ((mask|litval)!=0xff)
9356 emitcode ("anl","a,#0x%02x", mask);
9358 emitcode ("orl","a,#0x%02x", litval);
9363 /* Case with partial byte and arbitrary source
9365 MOVA (aopGet (right, offset++, FALSE, FALSE));
9366 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9369 /* transfer A to B and get next byte */
9370 emitPtrByteGet (rname, p_type, TRUE);
9372 emitcode ("anl", "a,#0x%02x", mask);
9373 emitcode ("orl", "a,b");
9374 if (p_type == GPOINTER)
9375 emitcode ("pop", "b");
9379 emitPtrByteSet (rname, p_type, "a");
9385 /*-----------------------------------------------------------------*/
9386 /* genDataPointerSet - remat pointer to data space */
9387 /*-----------------------------------------------------------------*/
9389 genDataPointerSet (operand * right,
9393 int size, offset = 0;
9394 char *l, buffer[256];
9396 D(emitcode ("; genDataPointerSet",""));
9398 aopOp (right, ic, FALSE);
9400 l = aopGet (result, 0, FALSE, TRUE);
9401 size = AOP_SIZE (right);
9405 sprintf (buffer, "(%s + %d)", l + 1, offset);
9407 sprintf (buffer, "%s", l + 1);
9408 emitcode ("mov", "%s,%s", buffer,
9409 aopGet (right, offset++, FALSE, FALSE));
9412 freeAsmop (right, NULL, ic, TRUE);
9413 freeAsmop (result, NULL, ic, TRUE);
9416 /*-----------------------------------------------------------------*/
9417 /* genNearPointerSet - emitcode for near pointer put */
9418 /*-----------------------------------------------------------------*/
9420 genNearPointerSet (operand * right,
9428 sym_link *retype, *letype;
9429 sym_link *ptype = operandType (result);
9431 D(emitcode ("; genNearPointerSet",""));
9433 retype = getSpec (operandType (right));
9434 letype = getSpec (ptype);
9435 aopOp (result, ic, FALSE);
9437 /* if the result is rematerializable &
9438 in data space & not a bit variable */
9439 if (AOP_TYPE (result) == AOP_IMMD &&
9440 DCL_TYPE (ptype) == POINTER &&
9441 !IS_BITVAR (retype) &&
9442 !IS_BITVAR (letype))
9444 genDataPointerSet (right, result, ic);
9448 /* if the value is already in a pointer register
9449 then don't need anything more */
9450 if (!AOP_INPREG (AOP (result)))
9453 //AOP_TYPE (result) == AOP_STK
9457 // Aha, it is a pointer, just in disguise.
9458 rname = aopGet (result, 0, FALSE, FALSE);
9461 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9462 __FILE__, __LINE__);
9467 emitcode ("mov", "a%s,%s", rname + 1, rname);
9468 rname++; // skip the '@'.
9473 /* otherwise get a free pointer register */
9475 preg = getFreePtr (ic, &aop, FALSE);
9476 emitcode ("mov", "%s,%s",
9478 aopGet (result, 0, FALSE, TRUE));
9484 rname = aopGet (result, 0, FALSE, FALSE);
9487 aopOp (right, ic, FALSE);
9489 /* if bitfield then unpack the bits */
9490 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9491 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9494 /* we have can just get the values */
9495 int size = AOP_SIZE (right);
9500 l = aopGet (right, offset, FALSE, TRUE);
9504 emitcode ("mov", "@%s,a", rname);
9507 emitcode ("mov", "@%s,%s", rname, l);
9509 emitcode ("inc", "%s", rname);
9514 /* now some housekeeping stuff */
9515 if (aop) /* we had to allocate for this iCode */
9518 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9519 freeAsmop (NULL, aop, ic, TRUE);
9523 /* we did not allocate which means left
9524 already in a pointer register, then
9525 if size > 0 && this could be used again
9526 we have to point it back to where it
9528 if ((AOP_SIZE (right) > 1 &&
9529 !OP_SYMBOL (result)->remat &&
9530 (OP_SYMBOL (result)->liveTo > ic->seq ||
9534 int size = AOP_SIZE (right) - 1;
9536 emitcode ("dec", "%s", rname);
9541 if (pi) pi->generated = 1;
9542 freeAsmop (result, NULL, ic, TRUE);
9543 freeAsmop (right, NULL, ic, TRUE);
9546 /*-----------------------------------------------------------------*/
9547 /* genPagedPointerSet - emitcode for Paged pointer put */
9548 /*-----------------------------------------------------------------*/
9550 genPagedPointerSet (operand * right,
9558 sym_link *retype, *letype;
9560 D(emitcode ("; genPagedPointerSet",""));
9562 retype = getSpec (operandType (right));
9563 letype = getSpec (operandType (result));
9565 aopOp (result, ic, FALSE);
9567 /* if the value is already in a pointer register
9568 then don't need anything more */
9569 if (!AOP_INPREG (AOP (result)))
9571 /* otherwise get a free pointer register */
9573 preg = getFreePtr (ic, &aop, FALSE);
9574 emitcode ("mov", "%s,%s",
9576 aopGet (result, 0, FALSE, TRUE));
9580 rname = aopGet (result, 0, FALSE, FALSE);
9582 aopOp (right, ic, FALSE);
9584 /* if bitfield then unpack the bits */
9585 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9586 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9589 /* we have can just get the values */
9590 int size = AOP_SIZE (right);
9595 l = aopGet (right, offset, FALSE, TRUE);
9598 emitcode ("movx", "@%s,a", rname);
9601 emitcode ("inc", "%s", rname);
9607 /* now some housekeeping stuff */
9608 if (aop) /* we had to allocate for this iCode */
9611 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9612 freeAsmop (NULL, aop, ic, TRUE);
9616 /* we did not allocate which means left
9617 already in a pointer register, then
9618 if size > 0 && this could be used again
9619 we have to point it back to where it
9621 if (AOP_SIZE (right) > 1 &&
9622 !OP_SYMBOL (result)->remat &&
9623 (OP_SYMBOL (result)->liveTo > ic->seq ||
9626 int size = AOP_SIZE (right) - 1;
9628 emitcode ("dec", "%s", rname);
9633 if (pi) pi->generated = 1;
9634 freeAsmop (result, NULL, ic, TRUE);
9635 freeAsmop (right, NULL, ic, TRUE);
9640 /*-----------------------------------------------------------------*/
9641 /* genFarPointerSet - set value from far space */
9642 /*-----------------------------------------------------------------*/
9644 genFarPointerSet (operand * right,
9645 operand * result, iCode * ic, iCode * pi)
9648 sym_link *retype = getSpec (operandType (right));
9649 sym_link *letype = getSpec (operandType (result));
9651 D(emitcode ("; genFarPointerSet",""));
9653 aopOp (result, ic, FALSE);
9654 loadDptrFromOperand (result, FALSE);
9656 /* so dptr know contains the address */
9657 aopOp (right, ic, FALSE);
9659 /* if bit then unpack */
9660 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9661 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9664 size = AOP_SIZE (right);
9669 char *l = aopGet (right, offset++, FALSE, FALSE);
9671 emitcode ("movx", "@dptr,a");
9673 emitcode ("inc", "dptr");
9676 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9677 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9678 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9681 freeAsmop (result, NULL, ic, TRUE);
9682 freeAsmop (right, NULL, ic, TRUE);
9685 /*-----------------------------------------------------------------*/
9686 /* genGenPointerSet - set value from generic pointer space */
9687 /*-----------------------------------------------------------------*/
9689 genGenPointerSet (operand * right,
9690 operand * result, iCode * ic, iCode * pi)
9693 sym_link *retype = getSpec (operandType (right));
9694 sym_link *letype = getSpec (operandType (result));
9696 D(emitcode ("; genGenPointerSet",""));
9698 aopOp (result, ic, FALSE);
9699 loadDptrFromOperand (result, TRUE);
9701 /* so dptr know contains the address */
9702 aopOp (right, ic, FALSE);
9704 /* if bit then unpack */
9705 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9706 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9709 size = AOP_SIZE (right);
9714 char *l = aopGet (right, offset++, FALSE, FALSE);
9716 emitcode ("lcall", "__gptrput");
9718 emitcode ("inc", "dptr");
9722 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9723 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9724 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9727 freeAsmop (result, NULL, ic, TRUE);
9728 freeAsmop (right, NULL, ic, TRUE);
9731 /*-----------------------------------------------------------------*/
9732 /* genPointerSet - stores the value into a pointer location */
9733 /*-----------------------------------------------------------------*/
9735 genPointerSet (iCode * ic, iCode *pi)
9737 operand *right, *result;
9738 sym_link *type, *etype;
9741 D(emitcode ("; genPointerSet",""));
9743 right = IC_RIGHT (ic);
9744 result = IC_RESULT (ic);
9746 /* depending on the type of pointer we need to
9747 move it to the correct pointer register */
9748 type = operandType (result);
9749 etype = getSpec (type);
9750 /* if left is of type of pointer then it is simple */
9751 if (IS_PTR (type) && !IS_FUNC (type->next))
9753 p_type = DCL_TYPE (type);
9757 /* we have to go by the storage class */
9758 p_type = PTR_TYPE (SPEC_OCLS (etype));
9761 /* special case when cast remat */
9762 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9763 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9764 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9765 type = operandType (result);
9766 p_type = DCL_TYPE (type);
9768 /* now that we have the pointer type we assign
9769 the pointer values */
9775 genNearPointerSet (right, result, ic, pi);
9779 genPagedPointerSet (right, result, ic, pi);
9783 genFarPointerSet (right, result, ic, pi);
9787 genGenPointerSet (right, result, ic, pi);
9791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9792 "genPointerSet: illegal pointer type");
9797 /*-----------------------------------------------------------------*/
9798 /* genIfx - generate code for Ifx statement */
9799 /*-----------------------------------------------------------------*/
9801 genIfx (iCode * ic, iCode * popIc)
9803 operand *cond = IC_COND (ic);
9806 D(emitcode ("; genIfx",""));
9808 aopOp (cond, ic, FALSE);
9810 /* get the value into acc */
9811 if (AOP_TYPE (cond) != AOP_CRY)
9815 /* the result is now in the accumulator */
9816 freeAsmop (cond, NULL, ic, TRUE);
9818 /* if there was something to be popped then do it */
9822 /* if the condition is a bit variable */
9823 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9824 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9825 else if (isbit && !IS_ITEMP (cond))
9826 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9828 genIfxJump (ic, "a", NULL, NULL, NULL);
9833 /*-----------------------------------------------------------------*/
9834 /* genAddrOf - generates code for address of */
9835 /*-----------------------------------------------------------------*/
9837 genAddrOf (iCode * ic)
9839 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9842 D(emitcode ("; genAddrOf",""));
9844 aopOp (IC_RESULT (ic), ic, FALSE);
9846 /* if the operand is on the stack then we
9847 need to get the stack offset of this
9851 /* if it has an offset then we need to compute
9855 emitcode ("mov", "a,%s", SYM_BP (sym));
9856 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9857 ((char) (sym->stack - _G.nRegsSaved)) :
9858 ((char) sym->stack)) & 0xff);
9859 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9863 /* we can just move _bp */
9864 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9866 /* fill the result with zero */
9867 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9872 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9878 /* object not on stack then we need the name */
9879 size = AOP_SIZE (IC_RESULT (ic));
9884 char s[SDCC_NAME_MAX];
9886 sprintf (s, "#(%s >> %d)",
9890 sprintf (s, "#%s", sym->rname);
9891 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9895 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9899 /*-----------------------------------------------------------------*/
9900 /* genFarFarAssign - assignment when both are in far space */
9901 /*-----------------------------------------------------------------*/
9903 genFarFarAssign (operand * result, operand * right, iCode * ic)
9905 int size = AOP_SIZE (right);
9909 D(emitcode ("; genFarFarAssign",""));
9911 /* first push the right side on to the stack */
9914 l = aopGet (right, offset++, FALSE, FALSE);
9916 emitcode ("push", "acc");
9919 freeAsmop (right, NULL, ic, FALSE);
9920 /* now assign DPTR to result */
9921 aopOp (result, ic, FALSE);
9922 size = AOP_SIZE (result);
9925 emitcode ("pop", "acc");
9926 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
9928 freeAsmop (result, NULL, ic, FALSE);
9932 /*-----------------------------------------------------------------*/
9933 /* genAssign - generate code for assignment */
9934 /*-----------------------------------------------------------------*/
9936 genAssign (iCode * ic)
9938 operand *result, *right;
9940 unsigned long lit = 0L;
9942 D(emitcode("; genAssign",""));
9944 result = IC_RESULT (ic);
9945 right = IC_RIGHT (ic);
9947 /* if they are the same */
9948 if (operandsEqu (result, right) &&
9949 !isOperandVolatile (result, FALSE) &&
9950 !isOperandVolatile (right, FALSE))
9953 aopOp (right, ic, FALSE);
9955 /* special case both in far space */
9956 if (AOP_TYPE (right) == AOP_DPTR &&
9957 IS_TRUE_SYMOP (result) &&
9958 isOperandInFarSpace (result))
9961 genFarFarAssign (result, right, ic);
9965 aopOp (result, ic, TRUE);
9967 /* if they are the same registers */
9968 if (sameRegs (AOP (right), AOP (result)) &&
9969 !isOperandVolatile (result, FALSE) &&
9970 !isOperandVolatile (right, FALSE))
9973 /* if the result is a bit */
9974 if (AOP_TYPE (result) == AOP_CRY)
9977 /* if the right size is a literal then
9978 we know what the value is */
9979 if (AOP_TYPE (right) == AOP_LIT)
9981 if (((int) operandLitValue (right)))
9982 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
9984 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
9988 /* the right is also a bit variable */
9989 if (AOP_TYPE (right) == AOP_CRY)
9991 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9992 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
9998 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10002 /* bit variables done */
10004 size = AOP_SIZE (result);
10006 if (AOP_TYPE (right) == AOP_LIT)
10007 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10009 (AOP_TYPE (result) != AOP_REG) &&
10010 (AOP_TYPE (right) == AOP_LIT) &&
10011 !IS_FLOAT (operandType (right)) &&
10014 while ((size) && (lit))
10017 aopGet (right, offset, FALSE, FALSE),
10019 isOperandVolatile (result, FALSE));
10024 emitcode ("clr", "a");
10027 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10036 aopGet (right, offset, FALSE, FALSE),
10038 isOperandVolatile (result, FALSE));
10044 freeAsmop (right, NULL, ic, TRUE);
10045 freeAsmop (result, NULL, ic, TRUE);
10048 /*-----------------------------------------------------------------*/
10049 /* genJumpTab - generates code for jump table */
10050 /*-----------------------------------------------------------------*/
10052 genJumpTab (iCode * ic)
10054 symbol *jtab,*jtablo,*jtabhi;
10056 unsigned int count;
10058 D(emitcode ("; genJumpTab",""));
10060 count = elementsInSet( IC_JTLABELS (ic) );
10064 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10065 if the switch argument is in a register.
10066 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10067 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10068 How will multiply by three be updated ???*/
10069 aopOp (IC_JTCOND (ic), ic, FALSE);
10070 /* get the condition into accumulator */
10071 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10073 /* multiply by three */
10074 emitcode ("add", "a,acc");
10075 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10076 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10078 jtab = newiTempLabel (NULL);
10079 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10080 emitcode ("jmp", "@a+dptr");
10081 emitcode ("", "%05d$:", jtab->key + 100);
10082 /* now generate the jump labels */
10083 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10084 jtab = setNextItem (IC_JTLABELS (ic)))
10085 emitcode ("ljmp", "%05d$", jtab->key + 100);
10089 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10090 if the switch argument is in a register.
10091 For n>6 this algorithm may be more compact */
10092 jtablo = newiTempLabel (NULL);
10093 jtabhi = newiTempLabel (NULL);
10095 /* get the condition into accumulator.
10096 Using b as temporary storage, if register push/pop is needed */
10097 aopOp (IC_JTCOND (ic), ic, FALSE);
10098 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10099 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10100 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10102 // (MB) what if B is in use???
10103 wassertl(!BINUSE, "B was in use");
10104 emitcode ("mov", "b,%s", l);
10107 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10111 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10112 emitcode ("movc", "a,@a+pc");
10113 emitcode ("push", "acc");
10116 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10117 emitcode ("movc", "a,@a+pc");
10118 emitcode ("push", "acc");
10122 /* this scales up to n<=255, but needs two more bytes
10123 and changes dptr */
10124 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10125 emitcode ("movc", "a,@a+dptr");
10126 emitcode ("push", "acc");
10129 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10130 emitcode ("movc", "a,@a+dptr");
10131 emitcode ("push", "acc");
10134 emitcode ("ret", "");
10136 /* now generate jump table, LSB */
10137 emitcode ("", "%05d$:", jtablo->key + 100);
10138 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10139 jtab = setNextItem (IC_JTLABELS (ic)))
10140 emitcode (".db", "%05d$", jtab->key + 100);
10142 /* now generate jump table, MSB */
10143 emitcode ("", "%05d$:", jtabhi->key + 100);
10144 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10145 jtab = setNextItem (IC_JTLABELS (ic)))
10146 emitcode (".db", "%05d$>>8", jtab->key + 100);
10150 /*-----------------------------------------------------------------*/
10151 /* genCast - gen code for casting */
10152 /*-----------------------------------------------------------------*/
10154 genCast (iCode * ic)
10156 operand *result = IC_RESULT (ic);
10157 sym_link *ctype = operandType (IC_LEFT (ic));
10158 sym_link *rtype = operandType (IC_RIGHT (ic));
10159 operand *right = IC_RIGHT (ic);
10162 D(emitcode("; genCast",""));
10164 /* if they are equivalent then do nothing */
10165 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10168 aopOp (right, ic, FALSE);
10169 aopOp (result, ic, FALSE);
10171 /* if the result is a bit (and not a bitfield) */
10172 // if (AOP_TYPE (result) == AOP_CRY)
10173 if (IS_BITVAR (OP_SYMBOL (result)->type)
10174 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10176 /* if the right size is a literal then
10177 we know what the value is */
10178 if (AOP_TYPE (right) == AOP_LIT)
10180 if (((int) operandLitValue (right)))
10181 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10183 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10188 /* the right is also a bit variable */
10189 if (AOP_TYPE (right) == AOP_CRY)
10191 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10192 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10196 /* we need to or */
10198 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10203 /* if they are the same size : or less */
10204 if (AOP_SIZE (result) <= AOP_SIZE (right))
10207 /* if they are in the same place */
10208 if (sameRegs (AOP (right), AOP (result)))
10211 /* if they in different places then copy */
10212 size = AOP_SIZE (result);
10217 aopGet (right, offset, FALSE, FALSE),
10219 isOperandVolatile (result, FALSE));
10226 /* if the result is of type pointer */
10227 if (IS_PTR (ctype))
10231 sym_link *type = operandType (right);
10232 sym_link *etype = getSpec (type);
10234 /* pointer to generic pointer */
10235 if (IS_GENPTR (ctype))
10238 p_type = DCL_TYPE (type);
10241 if (SPEC_SCLS(etype)==S_REGISTER) {
10242 // let's assume it is a generic pointer
10245 /* we have to go by the storage class */
10246 p_type = PTR_TYPE (SPEC_OCLS (etype));
10250 /* the first two bytes are known */
10251 size = GPTRSIZE - 1;
10256 aopGet (right, offset, FALSE, FALSE),
10258 isOperandVolatile (result, FALSE));
10261 /* the last byte depending on type */
10263 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10268 // pointerTypeToGPByte will have bitched.
10272 sprintf(gpValStr, "#0x%x", gpVal);
10273 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10278 /* just copy the pointers */
10279 size = AOP_SIZE (result);
10284 aopGet (right, offset, FALSE, FALSE),
10286 isOperandVolatile (result, FALSE));
10292 /* so we now know that the size of destination is greater
10293 than the size of the source */
10294 /* we move to result for the size of source */
10295 size = AOP_SIZE (right);
10300 aopGet (right, offset, FALSE, FALSE),
10302 isOperandVolatile (result, FALSE));
10306 /* now depending on the sign of the source && destination */
10307 size = AOP_SIZE (result) - AOP_SIZE (right);
10308 /* if unsigned or not an integral type */
10309 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10312 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10316 /* we need to extend the sign :{ */
10317 char *l = aopGet (right, AOP_SIZE (right) - 1,
10320 emitcode ("rlc", "a");
10321 emitcode ("subb", "a,acc");
10323 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10326 /* we are done hurray !!!! */
10329 freeAsmop (right, NULL, ic, TRUE);
10330 freeAsmop (result, NULL, ic, TRUE);
10334 /*-----------------------------------------------------------------*/
10335 /* genDjnz - generate decrement & jump if not zero instrucion */
10336 /*-----------------------------------------------------------------*/
10338 genDjnz (iCode * ic, iCode * ifx)
10340 symbol *lbl, *lbl1;
10344 D(emitcode ("; genDjnz",""));
10346 /* if the if condition has a false label
10347 then we cannot save */
10348 if (IC_FALSE (ifx))
10351 /* if the minus is not of the form
10353 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10354 !IS_OP_LITERAL (IC_RIGHT (ic)))
10357 if (operandLitValue (IC_RIGHT (ic)) != 1)
10360 /* if the size of this greater than one then no
10362 if (getSize (operandType (IC_RESULT (ic))) > 1)
10365 /* otherwise we can save BIG */
10366 lbl = newiTempLabel (NULL);
10367 lbl1 = newiTempLabel (NULL);
10369 aopOp (IC_RESULT (ic), ic, FALSE);
10371 if (AOP_NEEDSACC(IC_RESULT(ic)))
10373 /* If the result is accessed indirectly via
10374 * the accumulator, we must explicitly write
10375 * it back after the decrement.
10377 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10379 if (strcmp(rByte, "a"))
10381 /* Something is hopelessly wrong */
10382 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10383 __FILE__, __LINE__);
10384 /* We can just give up; the generated code will be inefficient,
10385 * but what the hey.
10387 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10390 emitcode ("dec", "%s", rByte);
10391 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10392 emitcode ("jnz", "%05d$", lbl->key + 100);
10394 else if (IS_AOP_PREG (IC_RESULT (ic)))
10396 emitcode ("dec", "%s",
10397 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10398 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10399 emitcode ("jnz", "%05d$", lbl->key + 100);
10403 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10406 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10407 emitcode ("", "%05d$:", lbl->key + 100);
10408 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10409 emitcode ("", "%05d$:", lbl1->key + 100);
10411 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10412 ifx->generated = 1;
10416 /*-----------------------------------------------------------------*/
10417 /* genReceive - generate code for a receive iCode */
10418 /*-----------------------------------------------------------------*/
10420 genReceive (iCode * ic)
10422 int size = getSize (operandType (IC_RESULT (ic)));
10424 D(emitcode ("; genReceive",""));
10426 if (ic->argreg == 1) { /* first parameter */
10427 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10428 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10429 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10432 int receivingA = 0;
10435 for (offset = 0; offset<size; offset++)
10436 if (!strcmp (fReturn[offset], "a"))
10441 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10443 for (offset = size-1; offset>0; offset--)
10444 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10445 emitcode("mov","a,%s", fReturn[0]);
10447 aopOp (IC_RESULT (ic), ic, FALSE);
10449 aopPut (IC_RESULT (ic), "a", offset,
10450 isOperandVolatile (IC_RESULT (ic), FALSE));
10451 for (offset = 1; offset<size; offset++)
10452 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10453 isOperandVolatile (IC_RESULT (ic), FALSE));
10459 if (getTempRegs(tempRegs, size, ic))
10461 for (offset = 0; offset<size; offset++)
10462 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10463 aopOp (IC_RESULT (ic), ic, FALSE);
10464 for (offset = 0; offset<size; offset++)
10465 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10466 isOperandVolatile (IC_RESULT (ic), FALSE));
10471 offset = fReturnSizeMCS51 - size;
10473 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10474 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10477 aopOp (IC_RESULT (ic), ic, FALSE);
10478 size = AOP_SIZE (IC_RESULT (ic));
10481 emitcode ("pop", "acc");
10482 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10487 aopOp (IC_RESULT (ic), ic, FALSE);
10489 assignResultValue (IC_RESULT (ic));
10491 } else { /* second receive onwards */
10493 aopOp (IC_RESULT (ic), ic, FALSE);
10494 rb1off = ic->argreg;
10496 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10501 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10504 /*-----------------------------------------------------------------*/
10505 /* genDummyRead - generate code for dummy read of volatiles */
10506 /*-----------------------------------------------------------------*/
10508 genDummyRead (iCode * ic)
10513 D(emitcode("; genDummyRead",""));
10515 op = IC_RIGHT (ic);
10516 if (op && IS_SYMOP (op))
10518 aopOp (op, ic, FALSE);
10520 /* if the result is a bit */
10521 if (AOP_TYPE (op) == AOP_CRY)
10522 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10525 /* bit variables done */
10527 size = AOP_SIZE (op);
10531 MOVA (aopGet (op, offset, FALSE, FALSE));
10536 freeAsmop (op, NULL, ic, TRUE);
10540 if (op && IS_SYMOP (op))
10542 aopOp (op, ic, FALSE);
10544 /* if the result is a bit */
10545 if (AOP_TYPE (op) == AOP_CRY)
10546 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10549 /* bit variables done */
10551 size = AOP_SIZE (op);
10555 MOVA (aopGet (op, offset, FALSE, FALSE));
10560 freeAsmop (op, NULL, ic, TRUE);
10564 /*-----------------------------------------------------------------*/
10565 /* genCritical - generate code for start of a critical sequence */
10566 /*-----------------------------------------------------------------*/
10568 genCritical (iCode *ic)
10570 symbol *tlbl = newiTempLabel (NULL);
10572 D(emitcode("; genCritical",""));
10574 if (IC_RESULT (ic))
10576 aopOp (IC_RESULT (ic), ic, TRUE);
10577 aopPut (IC_RESULT (ic), one, 0, 0);
10578 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10579 aopPut (IC_RESULT (ic), zero, 0, 0);
10580 emitcode ("", "%05d$:", (tlbl->key + 100));
10581 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10585 emitcode ("setb", "c");
10586 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10587 emitcode ("clr", "c");
10588 emitcode ("", "%05d$:", (tlbl->key + 100));
10589 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10593 /*-----------------------------------------------------------------*/
10594 /* genEndCritical - generate code for end of a critical sequence */
10595 /*-----------------------------------------------------------------*/
10597 genEndCritical (iCode *ic)
10599 D(emitcode("; genEndCritical",""));
10603 aopOp (IC_RIGHT (ic), ic, FALSE);
10604 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10606 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10607 emitcode ("mov", "ea,c");
10611 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10612 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10613 emitcode ("rrc", "a");
10614 emitcode ("mov", "ea,c");
10616 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10620 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10621 emitcode ("mov", "ea,c");
10625 /*-----------------------------------------------------------------*/
10626 /* gen51Code - generate code for 8051 based controllers */
10627 /*-----------------------------------------------------------------*/
10629 gen51Code (iCode * lic)
10633 /* int cseq = 0; */
10635 _G.currentFunc = NULL;
10636 lineHead = lineCurr = NULL;
10638 /* print the allocation information */
10639 if (allocInfo && currFunc)
10640 printAllocInfo (currFunc, codeOutFile);
10641 /* if debug information required */
10642 if (options.debug && currFunc)
10644 debugFile->writeFunction (currFunc, lic);
10646 /* stack pointer name */
10647 if (options.useXstack)
10653 for (ic = lic; ic; ic = ic->next)
10655 _G.current_iCode = ic;
10657 if (ic->lineno && cln != ic->lineno)
10661 debugFile->writeCLine (ic);
10663 if (!options.noCcodeInAsm) {
10664 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10665 printCLine(ic->filename, ic->lineno));
10670 if (ic->seqPoint && ic->seqPoint != cseq)
10672 emitcode ("", "; sequence point %d", ic->seqPoint);
10673 cseq = ic->seqPoint;
10676 if (options.iCodeInAsm) {
10677 char regsInUse[80];
10680 for (i=0; i<8; i++) {
10681 sprintf (®sInUse[i],
10682 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10685 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10687 /* if the result is marked as
10688 spilt and rematerializable or code for
10689 this has already been generated then
10691 if (resultRemat (ic) || ic->generated)
10694 /* depending on the operation */
10714 /* IPOP happens only when trying to restore a
10715 spilt live range, if there is an ifx statement
10716 following this pop then the if statement might
10717 be using some of the registers being popped which
10718 would destory the contents of the register so
10719 we need to check for this condition and handle it */
10721 ic->next->op == IFX &&
10722 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10723 genIfx (ic->next, ic);
10741 genEndFunction (ic);
10761 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10778 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10782 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10789 /* note these two are xlated by algebraic equivalence
10790 during parsing SDCC.y */
10791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10792 "got '>=' or '<=' shouldn't have come here");
10796 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10808 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10812 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10816 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10840 genRightShift (ic);
10843 case GET_VALUE_AT_ADDRESS:
10845 hasInc (IC_LEFT (ic), ic,
10846 getSize (operandType (IC_RESULT (ic)))),
10847 ifxForOp (IC_RESULT (ic), ic) );
10851 if (POINTER_SET (ic))
10852 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10878 addSet (&_G.sendSet, ic);
10881 case DUMMY_READ_VOLATILE:
10890 genEndCritical (ic);
10902 _G.current_iCode = NULL;
10904 /* now we are ready to call the
10905 peep hole optimizer */
10906 if (!options.nopeep)
10907 peepHole (&lineHead);
10909 /* now do the actual printing */
10910 printLine (lineHead, codeOutFile);