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);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
67 #define AOP(op) op->aop
68 #define AOP_TYPE(op) AOP(op)->type
69 #define AOP_SIZE(op) AOP(op)->size
70 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
71 AOP_TYPE(x) == AOP_R0))
73 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
74 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
76 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
77 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
78 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
81 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
83 #define R0INB _G.bu.bs.r0InB
84 #define R1INB _G.bu.bs.r1InB
85 #define OPINB _G.bu.bs.OpInB
86 #define BINUSE _G.bu.BInUse
96 short r0InB : 2;//2 so we can see it overflow
97 short r1InB : 2;//2 so we can see it overflow
98 short OpInB : 2;//2 so we can see it overflow
107 iCode *current_iCode;
112 static char *rb1regs[] = {
113 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
116 extern int mcs51_ptrRegReq;
117 extern int mcs51_nRegs;
118 extern FILE *codeOutFile;
119 static void saveRBank (int, iCode *, bool);
121 #define RESULTONSTACK(x) \
122 (IC_RESULT(x) && IC_RESULT(x)->aop && \
123 IC_RESULT(x)->aop->type == AOP_STK )
125 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
126 #define CLRC emitcode("clr","c")
127 #define SETC emitcode("setb","c")
129 static lineNode *lineHead = NULL;
130 static lineNode *lineCurr = NULL;
132 static unsigned char SLMask[] =
133 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
134 0xE0, 0xC0, 0x80, 0x00};
135 static unsigned char SRMask[] =
136 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
137 0x07, 0x03, 0x01, 0x00};
144 /*-----------------------------------------------------------------*/
145 /* emitcode - writes the code into a file : for now it is simple */
146 /*-----------------------------------------------------------------*/
148 emitcode (char *inst, const char *fmt,...)
151 char lb[INITIAL_INLINEASM];
159 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
161 SNPRINTF (lb, sizeof(lb), "%s", inst);
162 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
165 tvsprintf (lb, sizeof(lb), fmt, ap);
167 while (isspace (*lbp))
171 lineCurr = (lineCurr ?
172 connectLine (lineCurr, newLineNode (lb)) :
173 (lineHead = newLineNode (lb)));
174 lineCurr->isInline = _G.inLine;
175 lineCurr->isDebug = _G.debugLine;
176 lineCurr->ic = _G.current_iCode;
177 lineCurr->isComment = (*lbp==';');
181 /*-----------------------------------------------------------------*/
182 /* mcs51_emitDebuggerSymbol - associate the current code location */
183 /* with a debugger symbol */
184 /*-----------------------------------------------------------------*/
186 mcs51_emitDebuggerSymbol (char * debugSym)
189 emitcode ("", "%s ==.", debugSym);
193 /*-----------------------------------------------------------------*/
194 /* mova - moves specified value into accumulator */
195 /*-----------------------------------------------------------------*/
199 /* do some early peephole optimization */
200 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
203 emitcode("mov","a,%s", x);
206 /*-----------------------------------------------------------------*/
207 /* pushB - saves register B if necessary */
208 /*-----------------------------------------------------------------*/
212 bool pushedB = FALSE;
216 emitcode ("push", "b");
217 // printf("B was in use !\n");
227 /*-----------------------------------------------------------------*/
228 /* popB - restores value of register B if necessary */
229 /*-----------------------------------------------------------------*/
235 emitcode ("pop", "b");
243 /*-----------------------------------------------------------------*/
244 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
245 /*-----------------------------------------------------------------*/
247 getFreePtr (iCode * ic, asmop ** aopp, bool result)
252 /* the logic: if r0 & r1 used in the instruction
253 then we are in trouble otherwise */
255 /* first check if r0 & r1 are used by this
256 instruction, in which case we are in trouble */
257 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
258 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
263 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
264 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
266 /* if no usage of r0 then return it */
269 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
270 (*aopp)->type = AOP_R0;
272 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
275 /* if no usage of r1 then return it */
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
281 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
284 /* now we know they both have usage */
285 /* if r0 not used in this instruction */
288 /* push it if not already pushed */
291 emitcode ("mov", "b,%s",
292 mcs51_regWithIdx (R0_IDX)->dname);
295 else if (!_G.r0Pushed)
297 emitcode ("push", "%s",
298 mcs51_regWithIdx (R0_IDX)->dname);
302 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
303 (*aopp)->type = AOP_R0;
305 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
308 /* if r1 not used then */
312 /* push it if not already pushed */
315 emitcode ("mov", "b,%s",
316 mcs51_regWithIdx (R1_IDX)->dname);
319 else if (!_G.r1Pushed)
321 emitcode ("push", "%s",
322 mcs51_regWithIdx (R1_IDX)->dname);
326 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
327 (*aopp)->type = AOP_R1;
328 return mcs51_regWithIdx (R1_IDX);
331 /* I said end of world, but not quite end of world yet */
333 /* we can push it on the stack */
334 (*aopp)->type = AOP_STK;
337 /* in the case that result AND left AND right needs a pointer reg
338 we can safely use the result's */
339 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
340 (*aopp)->type = AOP_R0;
341 return mcs51_regWithIdx (R0_IDX);
343 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
344 (*aopp)->type = AOP_R1;
345 return mcs51_regWithIdx (R1_IDX);
349 /* now this is REALLY the end of the world */
350 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
351 "getFreePtr should never reach here");
356 /*-----------------------------------------------------------------*/
357 /* getTempRegs - initialize an array of pointers to GPR registers */
358 /* that are not in use. Returns 1 if the requested */
359 /* number of registers were available, 0 otherwise. */
360 /*-----------------------------------------------------------------*/
362 getTempRegs(regs **tempRegs, int size, iCode *ic)
369 ic = _G.current_iCode;
375 freeRegs = newBitVect(8);
376 bitVectSetBit (freeRegs, R2_IDX);
377 bitVectSetBit (freeRegs, R3_IDX);
378 bitVectSetBit (freeRegs, R4_IDX);
379 bitVectSetBit (freeRegs, R5_IDX);
380 bitVectSetBit (freeRegs, R6_IDX);
381 bitVectSetBit (freeRegs, R7_IDX);
383 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
385 bitVect * newfreeRegs;
386 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
387 freeBitVect(freeRegs);
388 freeRegs = newfreeRegs;
390 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
393 for (i=0; i<freeRegs->size; i++)
395 if (bitVectBitValue(freeRegs,i))
396 tempRegs[offset++] = mcs51_regWithIdx(i);
399 freeBitVect(freeRegs);
404 freeBitVect(freeRegs);
409 /*-----------------------------------------------------------------*/
410 /* newAsmop - creates a new asmOp */
411 /*-----------------------------------------------------------------*/
413 newAsmop (short type)
417 aop = Safe_calloc (1, sizeof (asmop));
422 /*-----------------------------------------------------------------*/
423 /* pointerCode - returns the code for a pointer type */
424 /*-----------------------------------------------------------------*/
426 pointerCode (sym_link * etype)
429 return PTR_TYPE (SPEC_OCLS (etype));
433 /*-----------------------------------------------------------------*/
434 /* leftRightUseAcc - returns size of accumulator use by operands */
435 /*-----------------------------------------------------------------*/
437 leftRightUseAcc(iCode *ic)
446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
447 "null iCode pointer");
454 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
457 size = getSize (OP_SYMBOL (op)->type);
462 else if (ic->op == JUMPTABLE)
465 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
468 size = getSize (OP_SYMBOL (op)->type);
476 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
479 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
499 /*-----------------------------------------------------------------*/
500 /* aopForSym - for a true symbol */
501 /*-----------------------------------------------------------------*/
503 aopForSym (iCode * ic, symbol * sym, bool result)
508 wassertl (ic != NULL, "Got a null iCode");
509 wassertl (sym != NULL, "Got a null symbol");
511 space = SPEC_OCLS (sym->etype);
513 /* if already has one */
517 /* assign depending on the storage class */
518 /* if it is on the stack or indirectly addressable */
519 /* space we need to assign either r0 or r1 to it */
520 if (sym->onStack || sym->iaccess)
522 sym->aop = aop = newAsmop (0);
523 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
524 aop->size = getSize (sym->type);
526 /* now assign the address of the variable to
527 the pointer register */
528 if (aop->type != AOP_STK)
533 char offset = ((sym->stack < 0) ?
534 ((char) (sym->stack - _G.nRegsSaved)) :
535 ((char) sym->stack)) & 0xff;
537 if ((offset >= -3) && (offset <= 3))
539 emitcode ("mov", "%s,%s",
540 aop->aopu.aop_ptr->name, SYM_BP (sym));
543 emitcode ("dec", aop->aopu.aop_ptr->name);
548 emitcode ("inc", aop->aopu.aop_ptr->name);
554 if (_G.accInUse || leftRightUseAcc (ic))
555 emitcode ("push", "acc");
556 emitcode ("mov", "a,%s", SYM_BP (sym));
557 emitcode ("add", "a,#0x%02x", offset);
558 emitcode ("mov", "%s,a",
559 aop->aopu.aop_ptr->name);
560 if (_G.accInUse || leftRightUseAcc (ic))
561 emitcode ("pop", "acc");
565 emitcode ("mov", "%s,#%s",
566 aop->aopu.aop_ptr->name,
568 aop->paged = space->paged;
571 aop->aopu.aop_stk = sym->stack;
575 /* if in bit space */
576 if (IN_BITSPACE (space))
578 sym->aop = aop = newAsmop (AOP_CRY);
579 aop->aopu.aop_dir = sym->rname;
580 aop->size = getSize (sym->type);
583 /* if it is in direct space */
584 if (IN_DIRSPACE (space))
586 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
587 //printTypeChainRaw(sym->type, NULL);
588 //printf("space = %s\n", space ? space->sname : "NULL");
589 sym->aop = aop = newAsmop (AOP_DIR);
590 aop->aopu.aop_dir = sym->rname;
591 aop->size = getSize (sym->type);
595 /* special case for a function */
596 if (IS_FUNC (sym->type))
598 sym->aop = aop = newAsmop (AOP_IMMD);
599 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
600 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
601 aop->size = FPTRSIZE;
605 /* only remaining is far space */
606 /* in which case DPTR gets the address */
607 sym->aop = aop = newAsmop (AOP_DPTR);
608 emitcode ("mov", "dptr,#%s", sym->rname);
609 aop->size = getSize (sym->type);
611 /* if it is in code space */
612 if (IN_CODESPACE (space))
618 /*-----------------------------------------------------------------*/
619 /* aopForRemat - rematerialzes an object */
620 /*-----------------------------------------------------------------*/
622 aopForRemat (symbol * sym)
624 iCode *ic = sym->rematiCode;
625 asmop *aop = newAsmop (AOP_IMMD);
632 val += (int) operandLitValue (IC_RIGHT (ic));
633 else if (ic->op == '-')
634 val -= (int) operandLitValue (IC_RIGHT (ic));
635 else if (IS_CAST_ICODE(ic)) {
636 sym_link *from_type = operandType(IC_RIGHT(ic));
637 aop->aopu.aop_immd.from_cast_remat = 1;
638 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
639 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
643 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
647 sprintf (buffer, "(%s %c 0x%04x)",
648 OP_SYMBOL (IC_LEFT (ic))->rname,
649 val >= 0 ? '+' : '-',
652 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
654 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
655 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
656 /* set immd2 field if required */
657 if (aop->aopu.aop_immd.from_cast_remat) {
658 sprintf(buffer,"#0x%02x",ptr_type);
659 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
660 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
666 /*-----------------------------------------------------------------*/
667 /* regsInCommon - two operands have some registers in common */
668 /*-----------------------------------------------------------------*/
670 regsInCommon (operand * op1, operand * op2)
675 /* if they have registers in common */
676 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
679 sym1 = OP_SYMBOL (op1);
680 sym2 = OP_SYMBOL (op2);
682 if (sym1->nRegs == 0 || sym2->nRegs == 0)
685 for (i = 0; i < sym1->nRegs; i++)
691 for (j = 0; j < sym2->nRegs; j++)
696 if (sym2->regs[j] == sym1->regs[i])
704 /*-----------------------------------------------------------------*/
705 /* operandsEqu - equivalent */
706 /*-----------------------------------------------------------------*/
708 operandsEqu (operand * op1, operand * op2)
712 /* if they're not symbols */
713 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
716 sym1 = OP_SYMBOL (op1);
717 sym2 = OP_SYMBOL (op2);
719 /* if both are itemps & one is spilt
720 and the other is not then false */
721 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
722 sym1->isspilt != sym2->isspilt)
725 /* if they are the same */
729 /* if they have the same rname */
730 if (sym1->rname[0] && sym2->rname[0]
731 && strcmp (sym1->rname, sym2->rname) == 0)
734 /* if left is a tmp & right is not */
735 if (IS_ITEMP (op1) &&
738 (sym1->usl.spillLoc == sym2))
741 if (IS_ITEMP (op2) &&
745 (sym2->usl.spillLoc == sym1))
751 /*-----------------------------------------------------------------*/
752 /* sameRegs - two asmops have the same registers */
753 /*-----------------------------------------------------------------*/
755 sameRegs (asmop * aop1, asmop * aop2)
762 if (aop1->type != AOP_REG ||
763 aop2->type != AOP_REG)
766 if (aop1->size != aop2->size)
769 for (i = 0; i < aop1->size; i++)
770 if (aop1->aopu.aop_reg[i] !=
771 aop2->aopu.aop_reg[i])
777 /*-----------------------------------------------------------------*/
778 /* aopOp - allocates an asmop for an operand : */
779 /*-----------------------------------------------------------------*/
781 aopOp (operand * op, iCode * ic, bool result)
790 /* if this a literal */
791 if (IS_OP_LITERAL (op))
793 op->aop = aop = newAsmop (AOP_LIT);
794 aop->aopu.aop_lit = op->operand.valOperand;
795 aop->size = getSize (operandType (op));
799 /* if already has a asmop then continue */
803 /* if the underlying symbol has a aop */
804 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
806 op->aop = OP_SYMBOL (op)->aop;
810 /* if this is a true symbol */
811 if (IS_TRUE_SYMOP (op))
813 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
817 /* this is a temporary : this has
823 e) can be a return use only */
825 sym = OP_SYMBOL (op);
827 /* if the type is a conditional */
828 if (sym->regType == REG_CND)
830 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
835 /* if it is spilt then two situations
837 b) has a spill location */
838 if (sym->isspilt || sym->nRegs == 0)
841 /* rematerialize it NOW */
844 sym->aop = op->aop = aop =
846 aop->size = getSize (sym->type);
853 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
854 aop->size = getSize (sym->type);
855 for (i = 0; i < 2; i++)
856 aop->aopu.aop_str[i] = accUse[i];
864 aop = op->aop = sym->aop = newAsmop (AOP_STR);
865 aop->size = getSize (sym->type);
866 for (i = 0; i < fReturnSizeMCS51; i++)
867 aop->aopu.aop_str[i] = fReturn[i];
871 if (sym->usl.spillLoc)
873 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
875 /* force a new aop if sizes differ */
876 sym->usl.spillLoc->aop = NULL;
878 sym->aop = op->aop = aop =
879 aopForSym (ic, sym->usl.spillLoc, result);
880 aop->size = getSize (sym->type);
884 /* else must be a dummy iTemp */
885 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
886 aop->size = getSize (sym->type);
890 /* must be in a register */
891 sym->aop = op->aop = aop = newAsmop (AOP_REG);
892 aop->size = sym->nRegs;
893 for (i = 0; i < sym->nRegs; i++)
894 aop->aopu.aop_reg[i] = sym->regs[i];
897 /*-----------------------------------------------------------------*/
898 /* freeAsmop - free up the asmop given to an operand */
899 /*----------------------------------------------------------------*/
901 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
918 /* depending on the asmop type only three cases need work AOP_RO
919 , AOP_R1 && AOP_STK */
925 emitcode ("mov", "r0,b");
928 else if (_G.r0Pushed)
932 emitcode ("pop", "ar0");
936 bitVectUnSetBit (ic->rUsed, R0_IDX);
942 emitcode ("mov", "r1,b");
949 emitcode ("pop", "ar1");
953 bitVectUnSetBit (ic->rUsed, R1_IDX);
959 int stk = aop->aopu.aop_stk + aop->size - 1;
960 bitVectUnSetBit (ic->rUsed, R0_IDX);
961 bitVectUnSetBit (ic->rUsed, R1_IDX);
963 getFreePtr (ic, &aop, FALSE);
967 emitcode ("mov", "a,_bp");
968 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
969 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
973 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
978 emitcode ("pop", "acc");
979 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
982 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
985 freeAsmop (op, NULL, ic, TRUE);
988 emitcode ("pop", "ar1");
994 emitcode ("pop", "ar0");
1001 /* all other cases just dealloc */
1007 OP_SYMBOL (op)->aop = NULL;
1008 /* if the symbol has a spill */
1010 SPIL_LOC (op)->aop = NULL;
1015 /*------------------------------------------------------------------*/
1016 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1017 /* pop r0 or r1 off stack if pushed */
1018 /*------------------------------------------------------------------*/
1020 freeForBranchAsmop (operand * op)
1040 emitcode ("mov", "r0,b");
1042 else if (_G.r0Pushed)
1044 emitcode ("pop", "ar0");
1051 emitcode ("mov", "r1,b");
1053 else if (_G.r1Pushed)
1055 emitcode ("pop", "ar1");
1062 int stk = aop->aopu.aop_stk + aop->size - 1;
1064 emitcode ("mov", "b,r0");
1067 emitcode ("mov", "a,_bp");
1068 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1069 emitcode ("mov", "r0,a");
1073 emitcode ("mov", "r0,_bp");
1078 emitcode ("pop", "acc");
1079 emitcode ("mov", "@r0,a");
1082 emitcode ("dec", "r0");
1084 emitcode ("mov", "r0,b");
1090 /*-----------------------------------------------------------------*/
1091 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1092 /* clobber the accumulator */
1093 /*-----------------------------------------------------------------*/
1095 aopGetUsesAcc (operand * oper, int offset)
1097 asmop * aop = AOP (oper);
1099 if (offset > (aop->size - 1))
1117 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1128 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1134 /* Error case --- will have been caught already */
1140 /*-----------------------------------------------------------------*/
1141 /* aopGet - for fetching value of the aop */
1142 /*-----------------------------------------------------------------*/
1144 aopGet (operand * oper, int offset, bool bit16, bool dname)
1148 asmop * aop = AOP (oper);
1150 /* offset is greater than
1152 if (offset > (aop->size - 1) &&
1153 aop->type != AOP_LIT)
1156 /* depending on type */
1164 /* if we need to increment it */
1165 while (offset > aop->coff)
1167 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1171 while (offset < aop->coff)
1173 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1180 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1181 return (dname ? "acc" : "a");
1183 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1184 rs = Safe_calloc (1, strlen (s) + 1);
1189 if (aop->code && aop->coff==0 && offset>=1) {
1190 emitcode ("mov", "a,#0x%02x", offset);
1191 emitcode ("movc", "a,@a+dptr");
1192 return (dname ? "acc" : "a");
1195 while (offset > aop->coff)
1197 emitcode ("inc", "dptr");
1201 while (offset < aop->coff)
1203 emitcode ("lcall", "__decdptr");
1210 emitcode ("clr", "a");
1211 emitcode ("movc", "a,@a+dptr");
1215 emitcode ("movx", "a,@dptr");
1217 return (dname ? "acc" : "a");
1221 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1222 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1224 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1226 sprintf (s, "#(%s >> %d)",
1227 aop->aopu.aop_immd.aop_immd1,
1231 aop->aopu.aop_immd.aop_immd1);
1232 rs = Safe_calloc (1, strlen (s) + 1);
1237 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1238 sprintf (s, "(%s >> %d)",
1239 aop->aopu.aop_dir, offset * 8);
1241 sprintf (s, "(%s + %d)",
1245 sprintf (s, "%s", aop->aopu.aop_dir);
1246 rs = Safe_calloc (1, strlen (s) + 1);
1252 return aop->aopu.aop_reg[offset]->dname;
1254 return aop->aopu.aop_reg[offset]->name;
1257 emitcode ("clr", "a");
1258 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1259 emitcode ("rlc", "a");
1260 return (dname ? "acc" : "a");
1263 if (!offset && dname)
1265 return aop->aopu.aop_str[offset];
1268 return aopLiteral (aop->aopu.aop_lit, offset);
1272 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1276 return aop->aopu.aop_str[offset];
1280 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1281 "aopget got unsupported aop->type");
1284 /*-----------------------------------------------------------------*/
1285 /* aopPut - puts a string for a aop and indicates if acc is in use */
1286 /*-----------------------------------------------------------------*/
1288 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1291 bool accuse = FALSE;
1292 asmop * aop = AOP (result);
1294 if (aop->size && offset > (aop->size - 1))
1296 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1297 "aopPut got offset > aop->size");
1301 /* will assign value to value */
1302 /* depending on where it is ofcourse */
1306 MOVA (s); /* read s in case it was volatile */
1311 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1312 sprintf (d, "(%s >> %d)",
1313 aop->aopu.aop_dir, offset * 8);
1315 sprintf (d, "(%s + %d)",
1316 aop->aopu.aop_dir, offset);
1318 sprintf (d, "%s", aop->aopu.aop_dir);
1320 if (strcmp (d, s) ||
1322 emitcode ("mov", "%s,%s", d, s);
1323 if (!strcmp (d, "acc"))
1329 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1330 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1333 strcmp (s, "r0") == 0 ||
1334 strcmp (s, "r1") == 0 ||
1335 strcmp (s, "r2") == 0 ||
1336 strcmp (s, "r3") == 0 ||
1337 strcmp (s, "r4") == 0 ||
1338 strcmp (s, "r5") == 0 ||
1339 strcmp (s, "r6") == 0 ||
1340 strcmp (s, "r7") == 0)
1341 emitcode ("mov", "%s,%s",
1342 aop->aopu.aop_reg[offset]->dname, s);
1344 emitcode ("mov", "%s,%s",
1345 aop->aopu.aop_reg[offset]->name, s);
1352 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1353 "aopPut writing to code space");
1357 while (offset > aop->coff)
1360 emitcode ("inc", "dptr");
1363 while (offset < aop->coff)
1366 emitcode ("lcall", "__decdptr");
1371 /* if not in accumulator */
1374 emitcode ("movx", "@dptr,a");
1379 while (offset > aop->coff)
1382 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1384 while (offset < aop->coff)
1387 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1394 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1400 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1402 else if (strcmp (s, "r0") == 0 ||
1403 strcmp (s, "r1") == 0 ||
1404 strcmp (s, "r2") == 0 ||
1405 strcmp (s, "r3") == 0 ||
1406 strcmp (s, "r4") == 0 ||
1407 strcmp (s, "r5") == 0 ||
1408 strcmp (s, "r6") == 0 ||
1409 strcmp (s, "r7") == 0)
1412 sprintf (buffer, "a%s", s);
1413 emitcode ("mov", "@%s,%s",
1414 aop->aopu.aop_ptr->name, buffer);
1417 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1422 if (strcmp (s, "a") == 0)
1423 emitcode ("push", "acc");
1427 emitcode ("push", "acc");
1429 emitcode ("push", s);
1435 /* if not bit variable */
1436 if (!aop->aopu.aop_dir)
1438 /* inefficient: move carry into A and use jz/jnz */
1439 emitcode ("clr", "a");
1440 emitcode ("rlc", "a");
1446 emitcode ("clr", "%s", aop->aopu.aop_dir);
1448 emitcode ("setb", "%s", aop->aopu.aop_dir);
1449 else if (!strcmp (s, "c"))
1450 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1454 /* set C, if a >= 1 */
1455 emitcode ("add", "a,#0xff");
1456 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1463 if (strcmp (aop->aopu.aop_str[offset], s) ||
1465 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1471 if (!offset && (strcmp (s, "acc") == 0) &&
1475 if (strcmp (aop->aopu.aop_str[offset], s) &&
1477 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1481 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1482 "aopPut got unsupported aop->type");
1491 /*-----------------------------------------------------------------*/
1492 /* pointToEnd :- points to the last byte of the operand */
1493 /*-----------------------------------------------------------------*/
1495 pointToEnd (asmop * aop)
1501 aop->coff = count = (aop->size - 1);
1507 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1511 emitcode ("inc", "dptr");
1518 /*-----------------------------------------------------------------*/
1519 /* reAdjustPreg - points a register back to where it should */
1520 /*-----------------------------------------------------------------*/
1522 reAdjustPreg (asmop * aop)
1524 if ((aop->coff==0) || aop->size <= 1)
1532 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1537 emitcode ("lcall", "__decdptr");
1544 /*-----------------------------------------------------------------*/
1545 /* opIsGptr: returns non-zero if the passed operand is */
1546 /* a generic pointer type. */
1547 /*-----------------------------------------------------------------*/
1549 opIsGptr (operand * op)
1551 sym_link *type = operandType (op);
1553 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1560 /*-----------------------------------------------------------------*/
1561 /* getDataSize - get the operand data size */
1562 /*-----------------------------------------------------------------*/
1564 getDataSize (operand * op)
1567 size = AOP_SIZE (op);
1568 if (size == GPTRSIZE)
1570 sym_link *type = operandType (op);
1571 if (IS_GENPTR (type))
1573 /* generic pointer; arithmetic operations
1574 * should ignore the high byte (pointer type).
1582 /*-----------------------------------------------------------------*/
1583 /* outAcc - output Acc */
1584 /*-----------------------------------------------------------------*/
1586 outAcc (operand * result)
1589 size = getDataSize (result);
1592 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1595 /* unsigned or positive */
1598 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1603 /*-----------------------------------------------------------------*/
1604 /* outBitC - output a bit C */
1605 /*-----------------------------------------------------------------*/
1607 outBitC (operand * result)
1609 /* if the result is bit */
1610 if (AOP_TYPE (result) == AOP_CRY)
1611 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1614 emitcode ("clr", "a");
1615 emitcode ("rlc", "a");
1620 /*-----------------------------------------------------------------*/
1621 /* toBoolean - emit code for orl a,operator(sizeop) */
1622 /*-----------------------------------------------------------------*/
1624 toBoolean (operand * oper)
1626 int size = AOP_SIZE (oper) - 1;
1628 bool AccUsed = FALSE;
1631 while (!AccUsed && size--)
1633 AccUsed |= aopGetUsesAcc(oper, offset++);
1636 size = AOP_SIZE (oper) - 1;
1638 MOVA (aopGet (oper, 0, FALSE, FALSE));
1639 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1642 emitcode("mov", "b,a");
1645 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1646 emitcode ("orl", "b,a");
1648 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1649 emitcode ("orl", "a,b");
1656 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1662 /*-----------------------------------------------------------------*/
1663 /* genNot - generate code for ! operation */
1664 /*-----------------------------------------------------------------*/
1670 D(emitcode ("; genNot",""));
1672 /* assign asmOps to operand & result */
1673 aopOp (IC_LEFT (ic), ic, FALSE);
1674 aopOp (IC_RESULT (ic), ic, TRUE);
1676 /* if in bit space then a special case */
1677 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1679 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1680 emitcode ("cpl", "c");
1681 outBitC (IC_RESULT (ic));
1685 toBoolean (IC_LEFT (ic));
1687 tlbl = newiTempLabel (NULL);
1688 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1689 emitcode ("", "%05d$:", tlbl->key + 100);
1690 outBitC (IC_RESULT (ic));
1693 /* release the aops */
1694 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1699 /*-----------------------------------------------------------------*/
1700 /* genCpl - generate code for complement */
1701 /*-----------------------------------------------------------------*/
1708 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1710 D(emitcode (";", "genCpl"));
1712 /* assign asmOps to operand & result */
1713 aopOp (IC_LEFT (ic), ic, FALSE);
1714 aopOp (IC_RESULT (ic), ic, TRUE);
1716 /* special case if in bit space */
1717 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1721 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1722 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1724 /* promotion rules are responsible for this strange result:
1725 bit -> int -> ~int -> bit
1726 uchar -> int -> ~int -> bit
1728 werror(W_COMPLEMENT);
1729 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1733 tlbl=newiTempLabel(NULL);
1734 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1735 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1736 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1737 IS_AOP_PREG (IC_LEFT (ic)))
1739 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1744 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1746 emitcode ("", "%05d$:", tlbl->key + 100);
1747 outBitC (IC_RESULT(ic));
1751 size = AOP_SIZE (IC_RESULT (ic));
1754 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1756 emitcode ("cpl", "a");
1757 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1762 /* release the aops */
1763 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1764 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1767 /*-----------------------------------------------------------------*/
1768 /* genUminusFloat - unary minus for floating points */
1769 /*-----------------------------------------------------------------*/
1771 genUminusFloat (operand * op, operand * result)
1773 int size, offset = 0;
1776 D(emitcode ("; genUminusFloat",""));
1778 /* for this we just copy and then flip the bit */
1780 size = AOP_SIZE (op) - 1;
1785 aopGet (op, offset, FALSE, FALSE),
1787 isOperandVolatile (result, FALSE));
1791 l = aopGet (op, offset, FALSE, FALSE);
1795 emitcode ("cpl", "acc.7");
1796 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1799 /*-----------------------------------------------------------------*/
1800 /* genUminus - unary minus code generation */
1801 /*-----------------------------------------------------------------*/
1803 genUminus (iCode * ic)
1806 sym_link *optype, *rtype;
1809 D(emitcode ("; genUminus",""));
1812 aopOp (IC_LEFT (ic), ic, FALSE);
1813 aopOp (IC_RESULT (ic), ic, TRUE);
1815 /* if both in bit space then special
1817 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1818 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1821 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1822 emitcode ("cpl", "c");
1823 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1827 optype = operandType (IC_LEFT (ic));
1828 rtype = operandType (IC_RESULT (ic));
1830 /* if float then do float stuff */
1831 if (IS_FLOAT (optype))
1833 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1837 /* otherwise subtract from zero */
1838 size = AOP_SIZE (IC_LEFT (ic));
1843 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1844 if (!strcmp (l, "a"))
1848 emitcode ("cpl", "a");
1849 emitcode ("addc", "a,#0");
1855 emitcode ("clr", "a");
1856 emitcode ("subb", "a,%s", l);
1858 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1861 /* if any remaining bytes in the result */
1862 /* we just need to propagate the sign */
1863 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1865 emitcode ("rlc", "a");
1866 emitcode ("subb", "a,acc");
1868 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1872 /* release the aops */
1873 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1877 /*-----------------------------------------------------------------*/
1878 /* saveRegisters - will look for a call and save the registers */
1879 /*-----------------------------------------------------------------*/
1881 saveRegisters (iCode * lic)
1888 for (ic = lic; ic; ic = ic->next)
1889 if (ic->op == CALL || ic->op == PCALL)
1894 fprintf (stderr, "found parameter push with no function call\n");
1898 /* if the registers have been saved already or don't need to be then
1902 if (IS_SYMOP(IC_LEFT(ic)) &&
1903 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1904 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1907 /* save the registers in use at this time but skip the
1908 ones for the result */
1909 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1910 mcs51_rUmaskForOp (IC_RESULT(ic)));
1913 if (options.useXstack)
1915 int count = bitVectnBitsOn (rsave);
1919 i = bitVectFirstBit (rsave);
1920 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1921 emitcode ("mov", "r0,%s", spname);
1922 emitcode ("inc", "%s", spname);// allocate before use
1923 emitcode ("movx", "@r0,a");
1924 if (bitVectBitValue (rsave, R0_IDX))
1925 emitcode ("mov", "r0,a");
1927 else if (count != 0)
1929 if (bitVectBitValue (rsave, R0_IDX))
1931 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1933 emitcode ("mov", "r0,%s", spname);
1935 emitcode ("add", "a,#%d", count);
1936 emitcode ("mov", "%s,a", spname);
1937 for (i = 0; i < mcs51_nRegs; i++)
1939 if (bitVectBitValue (rsave, i))
1943 emitcode ("pop", "acc");
1944 emitcode ("push", "acc");
1948 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1950 emitcode ("movx", "@r0,a");
1953 emitcode ("inc", "r0");
1957 if (bitVectBitValue (rsave, R0_IDX))
1959 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1964 for (i = 0; i < mcs51_nRegs; i++)
1966 if (bitVectBitValue (rsave, i))
1967 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1971 /*-----------------------------------------------------------------*/
1972 /* unsaveRegisters - pop the pushed registers */
1973 /*-----------------------------------------------------------------*/
1975 unsaveRegisters (iCode * ic)
1980 /* restore the registers in use at this time but skip the
1981 ones for the result */
1982 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1983 mcs51_rUmaskForOp (IC_RESULT(ic)));
1985 if (options.useXstack)
1987 int count = bitVectnBitsOn (rsave);
1991 emitcode ("mov", "r0,%s", spname);
1992 emitcode ("dec", "r0");
1993 emitcode ("movx", "a,@r0");
1994 i = bitVectFirstBit (rsave);
1995 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1996 emitcode ("dec", "%s", spname);
1998 else if (count != 0)
2000 emitcode ("mov", "r0,%s", spname);
2001 for (i = mcs51_nRegs; i >= 0; i--)
2003 if (bitVectBitValue (rsave, i))
2005 emitcode ("dec", "r0");
2006 emitcode ("movx", "a,@r0");
2008 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
2010 emitcode ("push", "acc");
2013 emitcode ("mov", "%s,r0", spname);
2014 if (bitVectBitValue (rsave, R0_IDX))
2016 emitcode ("pop", "ar0");
2021 for (i = mcs51_nRegs; i >= 0; i--)
2023 if (bitVectBitValue (rsave, i))
2024 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2029 /*-----------------------------------------------------------------*/
2031 /*-----------------------------------------------------------------*/
2033 pushSide (operand * oper, int size)
2038 char *l = aopGet (oper, offset++, FALSE, TRUE);
2039 if (AOP_TYPE (oper) != AOP_REG &&
2040 AOP_TYPE (oper) != AOP_DIR &&
2044 emitcode ("push", "acc");
2047 emitcode ("push", "%s", l);
2051 /*-----------------------------------------------------------------*/
2052 /* assignResultValue - also indicates if acc is in use afterwards */
2053 /*-----------------------------------------------------------------*/
2055 assignResultValue (operand * oper)
2058 int size = AOP_SIZE (oper);
2059 bool accuse = FALSE;
2063 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2070 /*-----------------------------------------------------------------*/
2071 /* genXpush - pushes onto the external stack */
2072 /*-----------------------------------------------------------------*/
2074 genXpush (iCode * ic)
2076 asmop *aop = newAsmop (0);
2078 int size, offset = 0;
2080 D(emitcode ("; genXpush",""));
2082 aopOp (IC_LEFT (ic), ic, FALSE);
2083 r = getFreePtr (ic, &aop, FALSE);
2085 size = AOP_SIZE (IC_LEFT (ic));
2089 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2090 emitcode ("mov", "%s,%s", r->name, spname);
2091 emitcode ("inc", "%s", spname); // allocate space first
2092 emitcode ("movx", "@%s,a", r->name);
2096 // allocate space first
2097 emitcode ("mov", "%s,%s", r->name, spname);
2099 emitcode ("add", "a,#%d", size);
2100 emitcode ("mov", "%s,a", spname);
2104 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2105 emitcode ("movx", "@%s,a", r->name);
2106 emitcode ("inc", "%s", r->name);
2110 freeAsmop (NULL, aop, ic, TRUE);
2111 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2114 /*-----------------------------------------------------------------*/
2115 /* genIpush - generate code for pushing this gets a little complex */
2116 /*-----------------------------------------------------------------*/
2118 genIpush (iCode * ic)
2120 int size, offset = 0;
2123 D(emitcode ("; genIpush",""));
2125 /* if this is not a parm push : ie. it is spill push
2126 and spill push is always done on the local stack */
2130 /* and the item is spilt then do nothing */
2131 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2134 aopOp (IC_LEFT (ic), ic, FALSE);
2135 size = AOP_SIZE (IC_LEFT (ic));
2136 /* push it on the stack */
2139 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2145 emitcode ("push", "%s", l);
2150 /* this is a paramter push: in this case we call
2151 the routine to find the call and save those
2152 registers that need to be saved */
2155 /* if use external stack then call the external
2156 stack pushing routine */
2157 if (options.useXstack)
2163 /* then do the push */
2164 aopOp (IC_LEFT (ic), ic, FALSE);
2166 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2167 size = AOP_SIZE (IC_LEFT (ic));
2171 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2172 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2173 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2177 emitcode ("push", "acc");
2180 emitcode ("push", "%s", l);
2183 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2186 /*-----------------------------------------------------------------*/
2187 /* genIpop - recover the registers: can happen only for spilling */
2188 /*-----------------------------------------------------------------*/
2190 genIpop (iCode * ic)
2194 D(emitcode ("; genIpop",""));
2196 /* if the temp was not pushed then */
2197 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2200 aopOp (IC_LEFT (ic), ic, FALSE);
2201 size = AOP_SIZE (IC_LEFT (ic));
2202 offset = (size - 1);
2204 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2207 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2210 /*-----------------------------------------------------------------*/
2211 /* saveRBank - saves an entire register bank on the stack */
2212 /*-----------------------------------------------------------------*/
2214 saveRBank (int bank, iCode * ic, bool pushPsw)
2217 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2221 if (options.useXstack)
2225 /* Assume r0 is available for use. */
2226 r = mcs51_regWithIdx (R0_IDX);;
2231 r = getFreePtr (ic, &aop, FALSE);
2233 // allocate space first
2234 emitcode ("mov", "%s,%s", r->name, spname);
2236 emitcode ("add", "a,#%d", count);
2237 emitcode ("mov", "%s,a", spname);
2240 for (i = 0; i < mcs51_nRegs; i++)
2242 if (options.useXstack)
2244 emitcode ("mov", "a,(%s+%d)",
2245 regs8051[i].base, 8 * bank + regs8051[i].offset);
2246 emitcode ("movx", "@%s,a", r->name);
2248 emitcode ("inc", "%s", r->name);
2251 emitcode ("push", "(%s+%d)",
2252 regs8051[i].base, 8 * bank + regs8051[i].offset);
2257 if (options.useXstack)
2259 emitcode ("mov", "a,psw");
2260 emitcode ("movx", "@%s,a", r->name);
2265 emitcode ("push", "psw");
2268 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2273 freeAsmop (NULL, aop, ic, TRUE);
2282 /*-----------------------------------------------------------------*/
2283 /* unsaveRBank - restores the register bank from stack */
2284 /*-----------------------------------------------------------------*/
2286 unsaveRBank (int bank, iCode * ic, bool popPsw)
2292 if (options.useXstack)
2296 /* Assume r0 is available for use. */
2297 r = mcs51_regWithIdx (R0_IDX);;
2302 r = getFreePtr (ic, &aop, FALSE);
2304 emitcode ("mov", "%s,%s", r->name, spname);
2309 if (options.useXstack)
2311 emitcode ("dec", "%s", r->name);
2312 emitcode ("movx", "a,@%s", r->name);
2313 emitcode ("mov", "psw,a");
2317 emitcode ("pop", "psw");
2321 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2323 if (options.useXstack)
2325 emitcode ("dec", "%s", r->name);
2326 emitcode ("movx", "a,@%s", r->name);
2327 emitcode ("mov", "(%s+%d),a",
2328 regs8051[i].base, 8 * bank + regs8051[i].offset);
2332 emitcode ("pop", "(%s+%d)",
2333 regs8051[i].base, 8 * bank + regs8051[i].offset);
2337 if (options.useXstack)
2339 emitcode ("mov", "%s,%s", spname, r->name);
2344 freeAsmop (NULL, aop, ic, TRUE);
2348 /*-----------------------------------------------------------------*/
2349 /* genSend - gen code for SEND */
2350 /*-----------------------------------------------------------------*/
2351 static void genSend(set *sendSet)
2356 for (sic = setFirstItem (sendSet); sic;
2357 sic = setNextItem (sendSet)) {
2358 int size, offset = 0;
2359 aopOp (IC_LEFT (sic), sic, FALSE);
2360 size = AOP_SIZE (IC_LEFT (sic));
2362 if (sic->argreg == 1) {
2364 char *l = aopGet (IC_LEFT (sic), offset,
2366 if (strcmp (l, fReturn[offset]))
2367 emitcode ("mov", "%s,%s", fReturn[offset], l);
2373 emitcode ("mov","b1_%d,%s",rb1_count++,
2374 aopGet (IC_LEFT (sic), offset++,FALSE, FALSE));
2377 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2381 /*-----------------------------------------------------------------*/
2382 /* genCall - generates a call statement */
2383 /*-----------------------------------------------------------------*/
2385 genCall (iCode * ic)
2388 // bool restoreBank = FALSE;
2389 bool swapBanks = FALSE;
2390 bool accuse = FALSE;
2391 bool accPushed = FALSE;
2393 D(emitcode("; genCall",""));
2395 dtype = operandType (IC_LEFT (ic));
2396 /* if send set is not empty then assign */
2399 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2400 genSend(reverseSet(_G.sendSet));
2402 genSend(_G.sendSet);
2408 /* if we are calling a not _naked function that is not using
2409 the same register bank then we need to save the
2410 destination registers on the stack */
2411 dtype = operandType (IC_LEFT (ic));
2412 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2413 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2414 !IFFUNC_ISISR (dtype))
2419 /* if caller saves & we have not saved then */
2425 emitcode ("mov", "psw,#0x%02x",
2426 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2430 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2431 OP_SYMBOL (IC_LEFT (ic))->rname :
2432 OP_SYMBOL (IC_LEFT (ic))->name));
2436 emitcode ("mov", "psw,#0x%02x",
2437 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2440 /* if we need assign a result value */
2441 if ((IS_ITEMP (IC_RESULT (ic)) &&
2442 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2443 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2444 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2445 IS_TRUE_SYMOP (IC_RESULT (ic)))
2449 aopOp (IC_RESULT (ic), ic, FALSE);
2452 accuse = assignResultValue (IC_RESULT (ic));
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2457 /* adjust the stack for parameters if required */
2461 if (ic->parmBytes > 3)
2465 emitcode ("push", "acc");
2469 emitcode ("mov", "a,%s", spname);
2470 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2471 emitcode ("mov", "%s,a", spname);
2473 /* unsaveRegisters from xstack needs acc, but */
2474 /* unsaveRegisters from stack needs this popped */
2475 if (accPushed && !options.useXstack)
2477 emitcode ("pop", "acc");
2482 for (i = 0; i < ic->parmBytes; i++)
2483 emitcode ("dec", "%s", spname);
2486 /* if we hade saved some registers then unsave them */
2487 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2489 if (accuse && !accPushed && options.useXstack)
2491 /* xstack needs acc, but doesn't touch normal stack */
2492 emitcode ("push", "acc");
2495 unsaveRegisters (ic);
2498 // /* if register bank was saved then pop them */
2500 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2503 emitcode ("pop", "acc");
2506 /*-----------------------------------------------------------------*/
2507 /* -10l - generates a call by pointer statement */
2508 /*-----------------------------------------------------------------*/
2510 genPcall (iCode * ic)
2513 symbol *rlbl = newiTempLabel (NULL);
2514 // bool restoreBank=FALSE;
2515 bool swapBanks = FALSE;
2517 D(emitcode("; genPCall",""));
2519 /* if caller saves & we have not saved then */
2523 /* if we are calling a not _naked function that is not using
2524 the same register bank then we need to save the
2525 destination registers on the stack */
2526 dtype = operandType (IC_LEFT (ic))->next;
2527 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2528 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2529 !IFFUNC_ISISR (dtype))
2531 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2532 // restoreBank=TRUE;
2534 // need caution message to user here
2537 /* push the return address on to the stack */
2538 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2539 emitcode ("push", "acc");
2540 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2541 emitcode ("push", "acc");
2543 /* now push the calling address */
2544 aopOp (IC_LEFT (ic), ic, FALSE);
2546 pushSide (IC_LEFT (ic), FPTRSIZE);
2548 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2550 /* if send set is not empty the assign */
2553 genSend(reverseSet(_G.sendSet));
2559 emitcode ("mov", "psw,#0x%02x",
2560 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2564 emitcode ("ret", "");
2565 emitcode ("", "%05d$:", (rlbl->key + 100));
2570 emitcode ("mov", "psw,#0x%02x",
2571 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2574 /* if we need assign a result value */
2575 if ((IS_ITEMP (IC_RESULT (ic)) &&
2576 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2577 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2578 IS_TRUE_SYMOP (IC_RESULT (ic)))
2582 aopOp (IC_RESULT (ic), ic, FALSE);
2585 assignResultValue (IC_RESULT (ic));
2587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2590 /* adjust the stack for parameters if
2595 if (ic->parmBytes > 3)
2597 emitcode ("mov", "a,%s", spname);
2598 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2599 emitcode ("mov", "%s,a", spname);
2602 for (i = 0; i < ic->parmBytes; i++)
2603 emitcode ("dec", "%s", spname);
2607 // /* if register bank was saved then unsave them */
2609 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2611 /* if we hade saved some registers then
2613 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2614 unsaveRegisters (ic);
2617 /*-----------------------------------------------------------------*/
2618 /* resultRemat - result is rematerializable */
2619 /*-----------------------------------------------------------------*/
2621 resultRemat (iCode * ic)
2623 if (SKIP_IC (ic) || ic->op == IFX)
2626 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2628 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2629 if (sym->remat && !POINTER_SET (ic))
2636 #if defined(__BORLANDC__) || defined(_MSC_VER)
2637 #define STRCASECMP stricmp
2639 #define STRCASECMP strcasecmp
2642 /*-----------------------------------------------------------------*/
2643 /* inExcludeList - return 1 if the string is in exclude Reg list */
2644 /*-----------------------------------------------------------------*/
2646 regsCmp(void *p1, void *p2)
2648 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2652 inExcludeList (char *s)
2654 const char *p = setFirstItem(options.excludeRegsSet);
2656 if (p == NULL || STRCASECMP(p, "none") == 0)
2660 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2663 /*-----------------------------------------------------------------*/
2664 /* genFunction - generated code for function entry */
2665 /*-----------------------------------------------------------------*/
2667 genFunction (iCode * ic)
2669 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2671 bool switchedPSW = FALSE;
2672 int calleesaves_saved_register = -1;
2673 int stackAdjust = sym->stack;
2674 int accIsFree = sym->recvSize < 4;
2675 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2676 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2679 /* create the function header */
2680 emitcode (";", "-----------------------------------------");
2681 emitcode (";", " function %s", sym->name);
2682 emitcode (";", "-----------------------------------------");
2684 emitcode ("", "%s:", sym->rname);
2685 ftype = operandType (IC_LEFT (ic));
2686 _G.currentFunc = sym;
2688 if (IFFUNC_ISNAKED(ftype))
2690 emitcode(";", "naked function: no prologue.");
2694 /* here we need to generate the equates for the
2695 register bank if required */
2696 if (FUNC_REGBANK (ftype) != rbank)
2700 rbank = FUNC_REGBANK (ftype);
2701 for (i = 0; i < mcs51_nRegs; i++)
2703 if (strcmp (regs8051[i].base, "0") == 0)
2704 emitcode ("", "%s = 0x%02x",
2706 8 * rbank + regs8051[i].offset);
2708 emitcode ("", "%s = %s + 0x%02x",
2711 8 * rbank + regs8051[i].offset);
2715 /* if this is an interrupt service routine then
2716 save acc, b, dpl, dph */
2717 if (IFFUNC_ISISR (sym->type))
2720 if (!inExcludeList ("acc"))
2721 emitcode ("push", "acc");
2722 if (!inExcludeList ("b"))
2723 emitcode ("push", "b");
2724 if (!inExcludeList ("dpl"))
2725 emitcode ("push", "dpl");
2726 if (!inExcludeList ("dph"))
2727 emitcode ("push", "dph");
2728 /* if this isr has no bank i.e. is going to
2729 run with bank 0 , then we need to save more
2731 if (!FUNC_REGBANK (sym->type))
2734 /* if this function does not call any other
2735 function then we can be economical and
2736 save only those registers that are used */
2737 if (!IFFUNC_HASFCALL(sym->type))
2741 /* if any registers used */
2744 /* save the registers used */
2745 for (i = 0; i < sym->regsUsed->size; i++)
2747 if (bitVectBitValue (sym->regsUsed, i))
2748 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2755 /* this function has a function call. We cannot
2756 determines register usage so we will have to push the
2758 saveRBank (0, ic, FALSE);
2759 if (options.parms_in_bank1) {
2761 for (i=0; i < 8 ; i++ ) {
2762 emitcode ("push","%s",rb1regs[i]);
2769 /* This ISR uses a non-zero bank.
2771 * We assume that the bank is available for our
2774 * However, if this ISR calls a function which uses some
2775 * other bank, we must save that bank entirely.
2777 unsigned long banksToSave = 0;
2779 if (IFFUNC_HASFCALL(sym->type))
2782 #define MAX_REGISTER_BANKS 4
2787 for (i = ic; i; i = i->next)
2789 if (i->op == ENDFUNCTION)
2791 /* we got to the end OK. */
2799 dtype = operandType (IC_LEFT(i));
2801 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2803 /* Mark this bank for saving. */
2804 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2806 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2810 banksToSave |= (1 << FUNC_REGBANK(dtype));
2813 /* And note that we don't need to do it in
2821 /* This is a mess; we have no idea what
2822 * register bank the called function might
2825 * The only thing I can think of to do is
2826 * throw a warning and hope.
2828 werror(W_FUNCPTR_IN_USING_ISR);
2832 if (banksToSave && options.useXstack)
2834 /* Since we aren't passing it an ic,
2835 * saveRBank will assume r0 is available to abuse.
2837 * So switch to our (trashable) bank now, so
2838 * the caller's R0 isn't trashed.
2840 emitcode ("push", "psw");
2841 emitcode ("mov", "psw,#0x%02x",
2842 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2846 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2848 if (banksToSave & (1 << ix))
2850 saveRBank(ix, NULL, FALSE);
2854 // TODO: this needs a closer look
2855 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2858 /* Set the register bank to the desired value if nothing else */
2859 /* has done so yet. */
2862 emitcode ("push", "psw");
2863 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2868 /* This is a non-ISR function. The caller has already switched register */
2869 /* banks, if necessary, so just handle the callee-saves option. */
2871 /* if callee-save to be used for this function
2872 then save the registers being used in this function */
2873 if (IFFUNC_CALLEESAVES(sym->type))
2877 /* if any registers used */
2880 /* save the registers used */
2881 for (i = 0; i < sym->regsUsed->size; i++)
2883 if (bitVectBitValue (sym->regsUsed, i))
2885 /* remember one saved register for later usage */
2886 if (calleesaves_saved_register < 0)
2887 calleesaves_saved_register = i;
2888 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2899 if (options.useXstack)
2901 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
2903 emitcode ("mov", "r0,%s", spname);
2904 emitcode ("inc", "%s", spname);
2905 emitcode ("xch", "a,_bpx");
2906 emitcode ("movx", "@r0,a");
2907 emitcode ("inc", "r0");
2908 emitcode ("mov", "a,r0");
2909 emitcode ("xch", "a,_bpx");
2913 emitcode ("push", "_bp"); /* save the callers stack */
2914 emitcode ("mov", "_bp,sp");
2919 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
2921 /* set up the stack */
2922 emitcode ("push", "_bp"); /* save the callers stack */
2923 emitcode ("mov", "_bp,sp");
2928 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2929 /* before setting up the stack frame completely. */
2930 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2932 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2936 if (rsym && rsym->regType == REG_CND)
2938 if (rsym && (rsym->accuse || rsym->ruonly))
2940 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2941 rsym = rsym->usl.spillLoc;
2944 /* If the RECEIVE operand immediately spills to the first entry on the */
2945 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2946 /* rather than the usual @r0/r1 machinations. */
2947 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2951 _G.current_iCode = ric;
2952 D(emitcode ("; genReceive",""));
2953 for (ofs=0; ofs < sym->recvSize; ofs++)
2955 if (!strcmp (fReturn[ofs], "a"))
2956 emitcode ("push", "acc");
2958 emitcode ("push", fReturn[ofs]);
2960 stackAdjust -= sym->recvSize;
2963 assert (stackAdjust>=0);
2966 _G.current_iCode = ic;
2970 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2971 /* to free up the accumulator. */
2972 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2976 _G.current_iCode = ric;
2977 D(emitcode ("; genReceive",""));
2978 for (ofs=0; ofs < sym->recvSize; ofs++)
2980 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2982 _G.current_iCode = ic;
2988 /* adjust the stack for the function */
2991 int i = stackAdjust;
2993 werror (W_STACK_OVERFLOW, sym->name);
2995 if (i > 3 && accIsFree)
2997 emitcode ("mov", "a,sp");
2998 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2999 emitcode ("mov", "sp,a");
3003 /* The accumulator is not free, so we will need another register */
3004 /* to clobber. No need to worry about a possible conflict with */
3005 /* the above early RECEIVE optimizations since they would have */
3006 /* freed the accumulator if they were generated. */
3008 if (IFFUNC_CALLEESAVES(sym->type))
3010 /* if it's a callee-saves function we need a saved register */
3011 if (calleesaves_saved_register >= 0)
3013 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3014 emitcode ("mov", "a,sp");
3015 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3016 emitcode ("mov", "sp,a");
3017 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3020 /* do it the hard way */
3022 emitcode ("inc", "sp");
3026 /* not callee-saves, we can clobber r0 */
3027 emitcode ("mov", "r0,a");
3028 emitcode ("mov", "a,sp");
3029 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3030 emitcode ("mov", "sp,a");
3031 emitcode ("mov", "a,r0");
3036 emitcode ("inc", "sp");
3041 char i = ((char) sym->xstack & 0xff);
3043 if (i > 3 && accIsFree)
3045 emitcode ("mov", "a,_spx");
3046 emitcode ("add", "a,#0x%02x", i);
3047 emitcode ("mov", "_spx,a");
3051 emitcode ("push", "acc");
3052 emitcode ("mov", "a,_spx");
3053 emitcode ("add", "a,#0x%02x", i);
3054 emitcode ("mov", "_spx,a");
3055 emitcode ("pop", "acc");
3060 emitcode ("inc", "_spx");
3064 /* if critical function then turn interrupts off */
3065 if (IFFUNC_ISCRITICAL (ftype))
3067 symbol *tlbl = newiTempLabel (NULL);
3068 emitcode ("setb", "c");
3069 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3070 emitcode ("clr", "c");
3071 emitcode ("", "%05d$:", (tlbl->key + 100));
3072 emitcode ("push", "psw"); /* save old ea via c in psw */
3076 /*-----------------------------------------------------------------*/
3077 /* genEndFunction - generates epilogue for functions */
3078 /*-----------------------------------------------------------------*/
3080 genEndFunction (iCode * ic)
3082 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3083 lineNode *lnp = lineCurr;
3085 bitVect *regsUsedPrologue;
3086 bitVect *regsUnneeded;
3089 _G.currentFunc = NULL;
3090 if (IFFUNC_ISNAKED(sym->type))
3092 emitcode(";", "naked function: no epilogue.");
3093 if (options.debug && currFunc)
3094 debugFile->writeEndFunction (currFunc, ic, 0);
3098 if (IFFUNC_ISCRITICAL (sym->type))
3100 emitcode ("pop", "psw"); /* restore ea via c in psw */
3101 emitcode ("mov", "ea,c");
3104 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3106 if (options.useXstack)
3110 emitcode ("mov", "sp,_bp");
3111 emitcode ("pop", "_bp");
3113 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3115 emitcode ("xch", "a,_bpx");
3116 emitcode ("mov", "r0,a");
3117 emitcode ("dec", "r0");
3118 emitcode ("movx", "a,@r0");
3119 emitcode ("xch", "a,_bpx");
3120 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3123 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3125 emitcode ("mov", "sp,_bp");
3126 emitcode ("pop", "_bp");
3130 /* restore the register bank */
3131 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3133 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3134 || !options.useXstack)
3136 /* Special case of ISR using non-zero bank with useXstack
3139 emitcode ("pop", "psw");
3143 if (IFFUNC_ISISR (sym->type))
3146 /* now we need to restore the registers */
3147 /* if this isr has no bank i.e. is going to
3148 run with bank 0 , then we need to save more
3150 if (!FUNC_REGBANK (sym->type))
3152 /* if this function does not call any other
3153 function then we can be economical and
3154 save only those registers that are used */
3155 if (!IFFUNC_HASFCALL(sym->type))
3159 /* if any registers used */
3162 /* save the registers used */
3163 for (i = sym->regsUsed->size; i >= 0; i--)
3165 if (bitVectBitValue (sym->regsUsed, i))
3166 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3172 if (options.parms_in_bank1) {
3174 for (i = 7 ; i >= 0 ; i-- ) {
3175 emitcode ("pop","%s",rb1regs[i]);
3178 /* this function has a function call cannot
3179 determines register usage so we will have to pop the
3181 unsaveRBank (0, ic, FALSE);
3186 /* This ISR uses a non-zero bank.
3188 * Restore any register banks saved by genFunction
3191 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3194 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3196 if (savedBanks & (1 << ix))
3198 unsaveRBank(ix, NULL, FALSE);
3202 if (options.useXstack)
3204 /* Restore bank AFTER calling unsaveRBank,
3205 * since it can trash r0.
3207 emitcode ("pop", "psw");
3211 if (!inExcludeList ("dph"))
3212 emitcode ("pop", "dph");
3213 if (!inExcludeList ("dpl"))
3214 emitcode ("pop", "dpl");
3215 if (!inExcludeList ("b"))
3216 emitcode ("pop", "b");
3217 if (!inExcludeList ("acc"))
3218 emitcode ("pop", "acc");
3220 /* if debug then send end of function */
3221 if (options.debug && currFunc)
3223 debugFile->writeEndFunction (currFunc, ic, 1);
3226 emitcode ("reti", "");
3230 if (IFFUNC_CALLEESAVES(sym->type))
3234 /* if any registers used */
3237 /* save the registers used */
3238 for (i = sym->regsUsed->size; i >= 0; i--)
3240 if (bitVectBitValue (sym->regsUsed, i) ||
3241 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3242 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3245 else if (mcs51_ptrRegReq)
3247 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3248 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3253 /* if debug then send end of function */
3254 if (options.debug && currFunc)
3256 debugFile->writeEndFunction (currFunc, ic, 1);
3259 emitcode ("ret", "");
3262 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3265 /* If this was an interrupt handler using bank 0 that called another */
3266 /* function, then all registers must be saved; nothing to optimized. */
3267 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3268 && !FUNC_REGBANK(sym->type))
3271 /* There are no push/pops to optimize if not callee-saves or ISR */
3272 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3275 /* If there were stack parameters, we cannot optimize without also */
3276 /* fixing all of the stack offsets; this is too dificult to consider. */
3277 if (FUNC_HASSTACKPARM(sym->type))
3280 /* Compute the registers actually used */
3281 regsUsed = newBitVect (mcs51_nRegs);
3282 regsUsedPrologue = newBitVect (mcs51_nRegs);
3285 if (lnp->ic && lnp->ic->op == FUNCTION)
3286 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3288 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3290 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3291 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3298 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3299 && !bitVectBitValue (regsUsed, CND_IDX))
3301 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3302 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3303 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3304 bitVectUnSetBit (regsUsed, CND_IDX);
3307 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3309 /* If this was an interrupt handler that called another function */
3310 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3311 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3313 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3314 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3315 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3316 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3317 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3320 /* Remove the unneeded push/pops */
3321 regsUnneeded = newBitVect (mcs51_nRegs);
3324 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3326 if (!strncmp(lnp->line, "push", 4))
3328 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3329 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3331 connectLine (lnp->prev, lnp->next);
3332 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3335 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3337 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3338 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3340 connectLine (lnp->prev, lnp->next);
3341 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3348 for (idx = 0; idx < regsUnneeded->size; idx++)
3349 if (bitVectBitValue (regsUnneeded, idx))
3350 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3352 freeBitVect (regsUnneeded);
3353 freeBitVect (regsUsed);
3354 freeBitVect (regsUsedPrologue);
3357 /*-----------------------------------------------------------------*/
3358 /* genRet - generate code for return statement */
3359 /*-----------------------------------------------------------------*/
3363 int size, offset = 0, pushed = 0;
3365 D(emitcode ("; genRet",""));
3367 /* if we have no return value then
3368 just generate the "ret" */
3372 /* we have something to return then
3373 move the return value into place */
3374 aopOp (IC_LEFT (ic), ic, FALSE);
3375 size = AOP_SIZE (IC_LEFT (ic));
3380 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3383 l = aopGet (IC_LEFT (ic), offset++,
3385 emitcode ("push", "%s", l);
3390 l = aopGet (IC_LEFT (ic), offset,
3392 if (strcmp (fReturn[offset], l))
3393 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3402 if (strcmp (fReturn[pushed], "a"))
3403 emitcode ("pop", fReturn[pushed]);
3405 emitcode ("pop", "acc");
3408 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3411 /* generate a jump to the return label
3412 if the next is not the return statement */
3413 if (!(ic->next && ic->next->op == LABEL &&
3414 IC_LABEL (ic->next) == returnLabel))
3416 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3420 /*-----------------------------------------------------------------*/
3421 /* genLabel - generates a label */
3422 /*-----------------------------------------------------------------*/
3424 genLabel (iCode * ic)
3426 /* special case never generate */
3427 if (IC_LABEL (ic) == entryLabel)
3430 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3433 /*-----------------------------------------------------------------*/
3434 /* genGoto - generates a ljmp */
3435 /*-----------------------------------------------------------------*/
3437 genGoto (iCode * ic)
3439 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3442 /*-----------------------------------------------------------------*/
3443 /* findLabelBackwards: walks back through the iCode chain looking */
3444 /* for the given label. Returns number of iCode instructions */
3445 /* between that label and given ic. */
3446 /* Returns zero if label not found. */
3447 /*-----------------------------------------------------------------*/
3449 findLabelBackwards (iCode * ic, int key)
3458 /* If we have any pushes or pops, we cannot predict the distance.
3459 I don't like this at all, this should be dealt with in the
3461 if (ic->op == IPUSH || ic->op == IPOP) {
3465 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3474 /*-----------------------------------------------------------------*/
3475 /* genPlusIncr :- does addition with increment if possible */
3476 /*-----------------------------------------------------------------*/
3478 genPlusIncr (iCode * ic)
3480 unsigned int icount;
3481 unsigned int size = getDataSize (IC_RESULT (ic));
3483 /* will try to generate an increment */
3484 /* if the right side is not a literal
3486 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3489 /* if the literal value of the right hand side
3490 is greater than 4 then it is not worth it */
3491 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3494 D(emitcode ("; genPlusIncr",""));
3496 /* if increment >=16 bits in register or direct space */
3497 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3498 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3499 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3507 /* If the next instruction is a goto and the goto target
3508 * is < 10 instructions previous to this, we can generate
3509 * jumps straight to that target.
3511 if (ic->next && ic->next->op == GOTO
3512 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3513 && labelRange <= 10)
3515 emitcode (";", "tail increment optimized");
3516 tlbl = IC_LABEL (ic->next);
3521 tlbl = newiTempLabel (NULL);
3524 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3525 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3526 IS_AOP_PREG (IC_RESULT (ic)))
3527 emitcode ("cjne", "%s,#0x00,%05d$",
3528 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3532 emitcode ("clr", "a");
3533 emitcode ("cjne", "a,%s,%05d$",
3534 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3538 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3541 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3542 IS_AOP_PREG (IC_RESULT (ic)))
3543 emitcode ("cjne", "%s,#0x00,%05d$",
3544 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3547 emitcode ("cjne", "a,%s,%05d$",
3548 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3551 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3555 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3556 IS_AOP_PREG (IC_RESULT (ic)))
3557 emitcode ("cjne", "%s,#0x00,%05d$",
3558 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3562 emitcode ("cjne", "a,%s,%05d$",
3563 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3566 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3571 emitcode ("", "%05d$:", tlbl->key + 100);
3576 /* if result is dptr */
3577 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3578 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3579 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3580 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3582 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3588 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3591 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3592 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3594 emitcode ("inc", "dptr");
3599 /* if the sizes are greater than 1 then we cannot */
3600 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3601 AOP_SIZE (IC_LEFT (ic)) > 1)
3604 /* we can if the aops of the left & result match or
3605 if they are in registers and the registers are the
3607 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3612 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3613 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3614 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3620 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3629 /*-----------------------------------------------------------------*/
3630 /* outBitAcc - output a bit in acc */
3631 /*-----------------------------------------------------------------*/
3633 outBitAcc (operand * result)
3635 symbol *tlbl = newiTempLabel (NULL);
3636 /* if the result is a bit */
3637 if (AOP_TYPE (result) == AOP_CRY)
3639 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
3643 emitcode ("jz", "%05d$", tlbl->key + 100);
3644 emitcode ("mov", "a,%s", one);
3645 emitcode ("", "%05d$:", tlbl->key + 100);
3650 /*-----------------------------------------------------------------*/
3651 /* genPlusBits - generates code for addition of two bits */
3652 /*-----------------------------------------------------------------*/
3654 genPlusBits (iCode * ic)
3656 D(emitcode ("; genPlusBits",""));
3658 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3660 symbol *lbl = newiTempLabel (NULL);
3661 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3662 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3663 emitcode ("cpl", "c");
3664 emitcode ("", "%05d$:", (lbl->key + 100));
3665 outBitC (IC_RESULT (ic));
3669 emitcode ("clr", "a");
3670 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3671 emitcode ("rlc", "a");
3672 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3673 emitcode ("addc", "a,#0x00");
3674 outAcc (IC_RESULT (ic));
3679 /* This is the original version of this code.
3681 * This is being kept around for reference,
3682 * because I am not entirely sure I got it right...
3685 adjustArithmeticResult (iCode * ic)
3687 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3688 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3689 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3690 aopPut (IC_RESULT (ic),
3691 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
3693 isOperandVolatile (IC_RESULT (ic), FALSE));
3695 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3696 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3697 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3698 aopPut (IC_RESULT (ic),
3699 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
3701 isOperandVolatile (IC_RESULT (ic), FALSE));
3703 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3704 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3705 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3706 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3707 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3710 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3711 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3715 /* This is the pure and virtuous version of this code.
3716 * I'm pretty certain it's right, but not enough to toss the old
3720 adjustArithmeticResult (iCode * ic)
3722 if (opIsGptr (IC_RESULT (ic)) &&
3723 opIsGptr (IC_LEFT (ic)) &&
3724 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3726 aopPut (IC_RESULT (ic),
3727 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
3729 isOperandVolatile (IC_RESULT (ic), FALSE));
3732 if (opIsGptr (IC_RESULT (ic)) &&
3733 opIsGptr (IC_RIGHT (ic)) &&
3734 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3736 aopPut (IC_RESULT (ic),
3737 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
3739 isOperandVolatile (IC_RESULT (ic), FALSE));
3742 if (opIsGptr (IC_RESULT (ic)) &&
3743 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3744 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3745 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3746 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3749 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3750 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3755 /*-----------------------------------------------------------------*/
3756 /* genPlus - generates code for addition */
3757 /*-----------------------------------------------------------------*/
3759 genPlus (iCode * ic)
3761 int size, offset = 0;
3764 operand *leftOp, *rightOp;
3767 /* special cases :- */
3769 D(emitcode ("; genPlus",""));
3771 aopOp (IC_LEFT (ic), ic, FALSE);
3772 aopOp (IC_RIGHT (ic), ic, FALSE);
3773 aopOp (IC_RESULT (ic), ic, TRUE);
3775 /* if literal, literal on the right or
3776 if left requires ACC or right is already
3778 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3779 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3780 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3782 operand *t = IC_RIGHT (ic);
3783 IC_RIGHT (ic) = IC_LEFT (ic);
3787 /* if both left & right are in bit
3789 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3790 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3796 /* if left in bit space & right literal */
3797 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3798 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3800 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3801 /* if result in bit space */
3802 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3804 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3805 emitcode ("cpl", "c");
3806 outBitC (IC_RESULT (ic));
3810 size = getDataSize (IC_RESULT (ic));
3813 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
3814 emitcode ("addc", "a,#00");
3815 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3821 /* if I can do an increment instead
3822 of add then GOOD for ME */
3823 if (genPlusIncr (ic) == TRUE)
3826 size = getDataSize (IC_RESULT (ic));
3827 leftOp = IC_LEFT(ic);
3828 rightOp = IC_RIGHT(ic);
3831 /* if this is an add for an array access
3832 at a 256 byte boundary */
3834 && AOP_TYPE (op) == AOP_IMMD
3836 && IS_SPEC (OP_SYM_ETYPE (op))
3837 && SPEC_ABSA (OP_SYM_ETYPE (op))
3838 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3841 D(emitcode ("; genPlus aligned array",""));
3842 aopPut (IC_RESULT (ic),
3843 aopGet (rightOp, 0, FALSE, FALSE),
3845 isOperandVolatile (IC_RESULT (ic), FALSE));
3847 if( 1 == getDataSize (IC_RIGHT (ic)) )
3849 aopPut (IC_RESULT (ic),
3850 aopGet (leftOp, 1, FALSE, FALSE),
3852 isOperandVolatile (IC_RESULT (ic), FALSE));
3856 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
3857 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3858 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3863 /* if the lower bytes of a literal are zero skip the addition */
3864 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3866 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3867 (skip_bytes+1 < size))
3872 D(emitcode ("; genPlus shortcut",""));
3877 if( offset >= skip_bytes )
3879 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3882 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3884 emitcode("xch", "a,b");
3885 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3886 emitcode (add, "a,b");
3889 else if (aopGetUsesAcc (leftOp, offset))
3891 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3892 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3896 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3897 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3899 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3900 add = "addc"; /* further adds must propagate carry */
3904 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3905 isOperandVolatile (IC_RESULT (ic), FALSE))
3908 aopPut (IC_RESULT (ic),
3909 aopGet (leftOp, offset, FALSE, FALSE),
3911 isOperandVolatile (IC_RESULT (ic), FALSE));
3917 adjustArithmeticResult (ic);
3920 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3921 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3922 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3925 /*-----------------------------------------------------------------*/
3926 /* genMinusDec :- does subtraction with deccrement if possible */
3927 /*-----------------------------------------------------------------*/
3929 genMinusDec (iCode * ic)
3931 unsigned int icount;
3932 unsigned int size = getDataSize (IC_RESULT (ic));
3934 /* will try to generate an increment */
3935 /* if the right side is not a literal
3937 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3940 /* if the literal value of the right hand side
3941 is greater than 4 then it is not worth it */
3942 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3945 D(emitcode ("; genMinusDec",""));
3947 /* if decrement >=16 bits in register or direct space */
3948 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3949 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3957 /* If the next instruction is a goto and the goto target
3958 * is <= 10 instructions previous to this, we can generate
3959 * jumps straight to that target.
3961 if (ic->next && ic->next->op == GOTO
3962 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3963 && labelRange <= 10)
3965 emitcode (";", "tail decrement optimized");
3966 tlbl = IC_LABEL (ic->next);
3971 tlbl = newiTempLabel (NULL);
3975 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3976 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3977 IS_AOP_PREG (IC_RESULT (ic)))
3978 emitcode ("cjne", "%s,#0xff,%05d$"
3979 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
3983 emitcode ("mov", "a,#0xff");
3984 emitcode ("cjne", "a,%s,%05d$"
3985 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
3988 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3991 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3992 IS_AOP_PREG (IC_RESULT (ic)))
3993 emitcode ("cjne", "%s,#0xff,%05d$"
3994 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
3998 emitcode ("cjne", "a,%s,%05d$"
3999 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4002 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4006 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4007 IS_AOP_PREG (IC_RESULT (ic)))
4008 emitcode ("cjne", "%s,#0xff,%05d$"
4009 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4013 emitcode ("cjne", "a,%s,%05d$"
4014 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4017 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4021 emitcode ("", "%05d$:", tlbl->key + 100);
4026 /* if the sizes are greater than 1 then we cannot */
4027 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4028 AOP_SIZE (IC_LEFT (ic)) > 1)
4031 /* we can if the aops of the left & result match or
4032 if they are in registers and the registers are the
4034 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4038 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4046 /*-----------------------------------------------------------------*/
4047 /* addSign - complete with sign */
4048 /*-----------------------------------------------------------------*/
4050 addSign (operand * result, int offset, int sign)
4052 int size = (getDataSize (result) - offset);
4057 emitcode ("rlc", "a");
4058 emitcode ("subb", "a,acc");
4060 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4064 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4068 /*-----------------------------------------------------------------*/
4069 /* genMinusBits - generates code for subtraction of two bits */
4070 /*-----------------------------------------------------------------*/
4072 genMinusBits (iCode * ic)
4074 symbol *lbl = newiTempLabel (NULL);
4076 D(emitcode ("; genMinusBits",""));
4078 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4080 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4081 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4082 emitcode ("cpl", "c");
4083 emitcode ("", "%05d$:", (lbl->key + 100));
4084 outBitC (IC_RESULT (ic));
4088 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4089 emitcode ("subb", "a,acc");
4090 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4091 emitcode ("inc", "a");
4092 emitcode ("", "%05d$:", (lbl->key + 100));
4093 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4094 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4098 /*-----------------------------------------------------------------*/
4099 /* genMinus - generates code for subtraction */
4100 /*-----------------------------------------------------------------*/
4102 genMinus (iCode * ic)
4104 int size, offset = 0;
4106 D(emitcode ("; genMinus",""));
4108 aopOp (IC_LEFT (ic), ic, FALSE);
4109 aopOp (IC_RIGHT (ic), ic, FALSE);
4110 aopOp (IC_RESULT (ic), ic, TRUE);
4112 /* special cases :- */
4113 /* if both left & right are in bit space */
4114 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4115 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4121 /* if I can do an decrement instead
4122 of subtract then GOOD for ME */
4123 if (genMinusDec (ic) == TRUE)
4126 size = getDataSize (IC_RESULT (ic));
4128 /* if literal, add a,#-lit, else normal subb */
4129 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4131 unsigned long lit = 0L;
4132 bool useCarry = FALSE;
4134 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4139 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4140 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4141 if (!offset && !size && lit== (unsigned long) -1) {
4142 emitcode ("dec", "a");
4143 } else if (!useCarry) {
4144 /* first add without previous c */
4145 emitcode ("add", "a,#0x%02x",
4146 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4149 emitcode ("addc", "a,#0x%02x",
4150 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4152 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4154 /* no need to add zeroes */
4161 operand *leftOp, *rightOp;
4163 leftOp = IC_LEFT(ic);
4164 rightOp = IC_RIGHT(ic);
4168 if (aopGetUsesAcc(rightOp, offset)) {
4169 if (aopGetUsesAcc(leftOp, offset)) {
4172 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4174 emitcode ("mov", "b,a");
4177 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4178 emitcode ("subb", "a,b");
4181 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4182 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4184 emitcode( "setb", "c");
4186 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4187 emitcode("cpl", "a");
4190 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4193 emitcode ("subb", "a,%s",
4194 aopGet(rightOp, offset, FALSE, TRUE));
4197 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4202 adjustArithmeticResult (ic);
4205 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4206 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4207 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4211 /*-----------------------------------------------------------------*/
4212 /* genMultbits :- multiplication of bits */
4213 /*-----------------------------------------------------------------*/
4215 genMultbits (operand * left,
4219 D(emitcode ("; genMultbits",""));
4221 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4222 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4226 /*-----------------------------------------------------------------*/
4227 /* genMultOneByte : 8*8=8/16 bit multiplication */
4228 /*-----------------------------------------------------------------*/
4230 genMultOneByte (operand * left,
4235 int size = AOP_SIZE (result);
4236 bool runtimeSign, compiletimeSign;
4237 bool lUnsigned, rUnsigned, pushedB;
4239 D(emitcode ("; genMultOneByte",""));
4241 if (size < 1 || size > 2)
4243 /* this should never happen */
4244 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4245 AOP_SIZE(result), __FILE__, lineno);
4249 /* (if two literals: the value is computed before) */
4250 /* if one literal, literal on the right */
4251 if (AOP_TYPE (left) == AOP_LIT)
4256 /* emitcode (";", "swapped left and right"); */
4258 /* if no literal, unsigned on the right: shorter code */
4259 if ( AOP_TYPE (right) != AOP_LIT
4260 && SPEC_USIGN (getSpec (operandType (left))))
4267 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4268 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4272 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4273 no need to take care about the signedness! */
4274 || (lUnsigned && rUnsigned))
4276 /* just an unsigned 8 * 8 = 8 multiply
4278 /* emitcode (";","unsigned"); */
4279 /* TODO: check for accumulator clash between left & right aops? */
4281 if (AOP_TYPE (right) == AOP_LIT)
4283 /* moving to accumulator first helps peepholes */
4284 MOVA (aopGet (left, 0, FALSE, FALSE));
4285 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4289 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4290 MOVA (aopGet (left, 0, FALSE, FALSE));
4293 emitcode ("mul", "ab");
4294 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4296 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4302 /* we have to do a signed multiply */
4303 /* emitcode (";", "signed"); */
4305 /* now sign adjust for both left & right */
4307 /* let's see what's needed: */
4308 /* apply negative sign during runtime */
4309 runtimeSign = FALSE;
4310 /* negative sign from literals */
4311 compiletimeSign = FALSE;
4315 if (AOP_TYPE(left) == AOP_LIT)
4317 /* signed literal */
4318 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4320 compiletimeSign = TRUE;
4323 /* signed but not literal */
4329 if (AOP_TYPE(right) == AOP_LIT)
4331 /* signed literal */
4332 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4334 compiletimeSign ^= TRUE;
4337 /* signed but not literal */
4341 /* initialize F0, which stores the runtime sign */
4344 if (compiletimeSign)
4345 emitcode ("setb", "F0"); /* set sign flag */
4347 emitcode ("clr", "F0"); /* reset sign flag */
4350 /* save the signs of the operands */
4351 if (AOP_TYPE(right) == AOP_LIT)
4353 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4355 if (!rUnsigned && val < 0)
4356 emitcode ("mov", "b,#0x%02x", -val);
4358 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4360 else /* ! literal */
4362 if (rUnsigned) /* emitcode (";", "signed"); */
4364 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4367 MOVA (aopGet (right, 0, FALSE, FALSE));
4368 lbl = newiTempLabel (NULL);
4369 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4370 emitcode ("cpl", "F0"); /* complement sign flag */
4371 emitcode ("cpl", "a"); /* 2's complement */
4372 emitcode ("inc", "a");
4373 emitcode ("", "%05d$:", (lbl->key + 100));
4374 emitcode ("mov", "b,a");
4378 if (AOP_TYPE(left) == AOP_LIT)
4380 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4382 if (!lUnsigned && val < 0)
4383 emitcode ("mov", "a,#0x%02x", -val);
4385 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4387 else /* ! literal */
4389 MOVA (aopGet (left, 0, FALSE, FALSE));
4393 lbl = newiTempLabel (NULL);
4394 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4395 emitcode ("cpl", "F0"); /* complement sign flag */
4396 emitcode ("cpl", "a"); /* 2's complement */
4397 emitcode ("inc", "a");
4398 emitcode ("", "%05d$:", (lbl->key + 100));
4402 /* now the multiplication */
4403 emitcode ("mul", "ab");
4404 if (runtimeSign || compiletimeSign)
4406 lbl = newiTempLabel (NULL);
4408 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4409 emitcode ("cpl", "a"); /* lsb 2's complement */
4411 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4414 emitcode ("add", "a,#1"); /* this sets carry flag */
4415 emitcode ("xch", "a,b");
4416 emitcode ("cpl", "a"); /* msb 2's complement */
4417 emitcode ("addc", "a,#0");
4418 emitcode ("xch", "a,b");
4420 emitcode ("", "%05d$:", (lbl->key + 100));
4422 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4424 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4429 /*-----------------------------------------------------------------*/
4430 /* genMult - generates code for multiplication */
4431 /*-----------------------------------------------------------------*/
4433 genMult (iCode * ic)
4435 operand *left = IC_LEFT (ic);
4436 operand *right = IC_RIGHT (ic);
4437 operand *result = IC_RESULT (ic);
4439 D(emitcode ("; genMult",""));
4441 /* assign the amsops */
4442 aopOp (left, ic, FALSE);
4443 aopOp (right, ic, FALSE);
4444 aopOp (result, ic, TRUE);
4446 /* special cases first */
4448 if (AOP_TYPE (left) == AOP_CRY &&
4449 AOP_TYPE (right) == AOP_CRY)
4451 genMultbits (left, right, result);
4455 /* if both are of size == 1 */
4456 #if 0 // one of them can be a sloc shared with the result
4457 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4459 if (getSize(operandType(left)) == 1 &&
4460 getSize(operandType(right)) == 1)
4463 genMultOneByte (left, right, result);
4467 /* should have been converted to function call */
4468 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4469 getSize(OP_SYMBOL(right)->type));
4473 freeAsmop (result, NULL, ic, TRUE);
4474 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4475 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4478 /*-----------------------------------------------------------------*/
4479 /* genDivbits :- division of bits */
4480 /*-----------------------------------------------------------------*/
4482 genDivbits (operand * left,
4489 D(emitcode ("; genDivbits",""));
4493 /* the result must be bit */
4494 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4495 l = aopGet (left, 0, FALSE, FALSE);
4499 emitcode ("div", "ab");
4500 emitcode ("rrc", "a");
4504 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4507 /*-----------------------------------------------------------------*/
4508 /* genDivOneByte : 8 bit division */
4509 /*-----------------------------------------------------------------*/
4511 genDivOneByte (operand * left,
4515 bool lUnsigned, rUnsigned, pushedB;
4516 bool runtimeSign, compiletimeSign;
4520 D(emitcode ("; genDivOneByte",""));
4522 /* Why is it necessary that genDivOneByte() can return an int result?
4525 volatile unsigned char uc;
4526 volatile signed char sc1, sc2;
4539 In all cases a one byte result would overflow, the following cast to int
4540 would return the wrong result.
4542 Two possible solution:
4543 a) cast operands to int, if ((unsigned) / (signed)) or
4544 ((signed) / (signed))
4545 b) return an 16 bit signed int; this is what we're doing here!
4548 size = AOP_SIZE (result) - 1;
4550 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4551 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4555 /* signed or unsigned */
4556 if (lUnsigned && rUnsigned)
4558 /* unsigned is easy */
4559 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4560 MOVA (aopGet (left, 0, FALSE, FALSE));
4561 emitcode ("div", "ab");
4562 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4564 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4570 /* signed is a little bit more difficult */
4572 /* now sign adjust for both left & right */
4574 /* let's see what's needed: */
4575 /* apply negative sign during runtime */
4576 runtimeSign = FALSE;
4577 /* negative sign from literals */
4578 compiletimeSign = FALSE;
4582 if (AOP_TYPE(left) == AOP_LIT)
4584 /* signed literal */
4585 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4587 compiletimeSign = TRUE;
4590 /* signed but not literal */
4596 if (AOP_TYPE(right) == AOP_LIT)
4598 /* signed literal */
4599 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4601 compiletimeSign ^= TRUE;
4604 /* signed but not literal */
4608 /* initialize F0, which stores the runtime sign */
4611 if (compiletimeSign)
4612 emitcode ("setb", "F0"); /* set sign flag */
4614 emitcode ("clr", "F0"); /* reset sign flag */
4617 /* save the signs of the operands */
4618 if (AOP_TYPE(right) == AOP_LIT)
4620 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4622 if (!rUnsigned && val < 0)
4623 emitcode ("mov", "b,#0x%02x", -val);
4625 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4627 else /* ! literal */
4630 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4633 MOVA (aopGet (right, 0, FALSE, FALSE));
4634 lbl = newiTempLabel (NULL);
4635 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4636 emitcode ("cpl", "F0"); /* complement sign flag */
4637 emitcode ("cpl", "a"); /* 2's complement */
4638 emitcode ("inc", "a");
4639 emitcode ("", "%05d$:", (lbl->key + 100));
4640 emitcode ("mov", "b,a");
4644 if (AOP_TYPE(left) == AOP_LIT)
4646 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4648 if (!lUnsigned && val < 0)
4649 emitcode ("mov", "a,#0x%02x", -val);
4651 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4653 else /* ! literal */
4655 MOVA (aopGet (left, 0, FALSE, FALSE));
4659 lbl = newiTempLabel (NULL);
4660 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4661 emitcode ("cpl", "F0"); /* complement sign flag */
4662 emitcode ("cpl", "a"); /* 2's complement */
4663 emitcode ("inc", "a");
4664 emitcode ("", "%05d$:", (lbl->key + 100));
4668 /* now the division */
4669 emitcode ("div", "ab");
4671 if (runtimeSign || compiletimeSign)
4673 lbl = newiTempLabel (NULL);
4675 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4676 emitcode ("cpl", "a"); /* lsb 2's complement */
4677 emitcode ("inc", "a");
4678 emitcode ("", "%05d$:", (lbl->key + 100));
4680 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4683 /* msb is 0x00 or 0xff depending on the sign */
4686 emitcode ("mov", "c,F0");
4687 emitcode ("subb", "a,acc");
4689 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4691 else /* compiletimeSign */
4693 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4698 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4700 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4706 /*-----------------------------------------------------------------*/
4707 /* genDiv - generates code for division */
4708 /*-----------------------------------------------------------------*/
4712 operand *left = IC_LEFT (ic);
4713 operand *right = IC_RIGHT (ic);
4714 operand *result = IC_RESULT (ic);
4716 D(emitcode ("; genDiv",""));
4718 /* assign the amsops */
4719 aopOp (left, ic, FALSE);
4720 aopOp (right, ic, FALSE);
4721 aopOp (result, ic, TRUE);
4723 /* special cases first */
4725 if (AOP_TYPE (left) == AOP_CRY &&
4726 AOP_TYPE (right) == AOP_CRY)
4728 genDivbits (left, right, result);
4732 /* if both are of size == 1 */
4733 if (AOP_SIZE (left) == 1 &&
4734 AOP_SIZE (right) == 1)
4736 genDivOneByte (left, right, result);
4740 /* should have been converted to function call */
4743 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4744 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4745 freeAsmop (result, NULL, ic, TRUE);
4748 /*-----------------------------------------------------------------*/
4749 /* genModbits :- modulus of bits */
4750 /*-----------------------------------------------------------------*/
4752 genModbits (operand * left,
4759 D(emitcode ("; genModbits",""));
4763 /* the result must be bit */
4764 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4765 l = aopGet (left, 0, FALSE, FALSE);
4769 emitcode ("div", "ab");
4770 emitcode ("mov", "a,b");
4771 emitcode ("rrc", "a");
4775 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4778 /*-----------------------------------------------------------------*/
4779 /* genModOneByte : 8 bit modulus */
4780 /*-----------------------------------------------------------------*/
4782 genModOneByte (operand * left,
4786 bool lUnsigned, rUnsigned, pushedB;
4787 bool runtimeSign, compiletimeSign;
4791 D(emitcode ("; genModOneByte",""));
4793 size = AOP_SIZE (result) - 1;
4795 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4796 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4798 /* if right is a literal, check it for 2^n */
4799 if (AOP_TYPE(right) == AOP_LIT)
4801 unsigned char val = abs((int) operandLitValue(right));
4802 symbol *lbl2 = NULL;
4806 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4815 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4816 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4817 /* because iCode should have been changed to genAnd */
4818 /* see file "SDCCopt.c", function "convertToFcall()" */
4820 MOVA (aopGet (left, 0, FALSE, FALSE));
4821 emitcode ("mov", "c,acc.7");
4822 emitcode ("anl", "a,#0x%02x", val - 1);
4823 lbl = newiTempLabel (NULL);
4824 emitcode ("jz", "%05d$", (lbl->key + 100));
4825 emitcode ("jnc", "%05d$", (lbl->key + 100));
4826 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4832 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4834 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
4835 lbl2 = newiTempLabel (NULL);
4836 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4838 emitcode ("", "%05d$:", (lbl->key + 100));
4839 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4841 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4844 emitcode ("", "%05d$:", (lbl2->key + 100));
4855 /* signed or unsigned */
4856 if (lUnsigned && rUnsigned)
4858 /* unsigned is easy */
4859 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4860 MOVA (aopGet (left, 0, FALSE, FALSE));
4861 emitcode ("div", "ab");
4862 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4864 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4870 /* signed is a little bit more difficult */
4872 /* now sign adjust for both left & right */
4874 /* modulus: sign of the right operand has no influence on the result! */
4875 if (AOP_TYPE(right) == AOP_LIT)
4877 signed char val = (char) operandLitValue(right);
4879 if (!rUnsigned && val < 0)
4880 emitcode ("mov", "b,#0x%02x", -val);
4882 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4884 else /* not literal */
4887 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4890 MOVA (aopGet (right, 0, FALSE, FALSE));
4891 lbl = newiTempLabel (NULL);
4892 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4893 emitcode ("cpl", "a"); /* 2's complement */
4894 emitcode ("inc", "a");
4895 emitcode ("", "%05d$:", (lbl->key + 100));
4896 emitcode ("mov", "b,a");
4900 /* let's see what's needed: */
4901 /* apply negative sign during runtime */
4902 runtimeSign = FALSE;
4903 /* negative sign from literals */
4904 compiletimeSign = FALSE;
4906 /* sign adjust left side */
4907 if (AOP_TYPE(left) == AOP_LIT)
4909 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4911 if (!lUnsigned && val < 0)
4913 compiletimeSign = TRUE; /* set sign flag */
4914 emitcode ("mov", "a,#0x%02x", -val);
4917 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4919 else /* ! literal */
4921 MOVA (aopGet (left, 0, FALSE, FALSE));
4926 emitcode ("clr", "F0"); /* clear sign flag */
4928 lbl = newiTempLabel (NULL);
4929 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4930 emitcode ("setb", "F0"); /* set sign flag */
4931 emitcode ("cpl", "a"); /* 2's complement */
4932 emitcode ("inc", "a");
4933 emitcode ("", "%05d$:", (lbl->key + 100));
4937 /* now the modulus */
4938 emitcode ("div", "ab");
4940 if (runtimeSign || compiletimeSign)
4942 emitcode ("mov", "a,b");
4943 lbl = newiTempLabel (NULL);
4945 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4946 emitcode ("cpl", "a"); /* 2's complement */
4947 emitcode ("inc", "a");
4948 emitcode ("", "%05d$:", (lbl->key + 100));
4950 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4953 /* msb is 0x00 or 0xff depending on the sign */
4956 emitcode ("mov", "c,F0");
4957 emitcode ("subb", "a,acc");
4959 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4961 else /* compiletimeSign */
4963 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4968 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4970 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4976 /*-----------------------------------------------------------------*/
4977 /* genMod - generates code for division */
4978 /*-----------------------------------------------------------------*/
4982 operand *left = IC_LEFT (ic);
4983 operand *right = IC_RIGHT (ic);
4984 operand *result = IC_RESULT (ic);
4986 D(emitcode ("; genMod",""));
4988 /* assign the asmops */
4989 aopOp (left, ic, FALSE);
4990 aopOp (right, ic, FALSE);
4991 aopOp (result, ic, TRUE);
4993 /* special cases first */
4995 if (AOP_TYPE (left) == AOP_CRY &&
4996 AOP_TYPE (right) == AOP_CRY)
4998 genModbits (left, right, result);
5002 /* if both are of size == 1 */
5003 if (AOP_SIZE (left) == 1 &&
5004 AOP_SIZE (right) == 1)
5006 genModOneByte (left, right, result);
5010 /* should have been converted to function call */
5014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5015 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5016 freeAsmop (result, NULL, ic, TRUE);
5019 /*-----------------------------------------------------------------*/
5020 /* genIfxJump :- will create a jump depending on the ifx */
5021 /*-----------------------------------------------------------------*/
5023 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5026 symbol *tlbl = newiTempLabel (NULL);
5029 D(emitcode ("; genIfxJump",""));
5031 /* if true label then we jump if condition
5035 jlbl = IC_TRUE (ic);
5036 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5037 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5041 /* false label is present */
5042 jlbl = IC_FALSE (ic);
5043 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5044 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5046 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5047 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5049 emitcode (inst, "%05d$", tlbl->key + 100);
5050 freeForBranchAsmop (result);
5051 freeForBranchAsmop (right);
5052 freeForBranchAsmop (left);
5053 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5054 emitcode ("", "%05d$:", tlbl->key + 100);
5056 /* mark the icode as generated */
5060 /*-----------------------------------------------------------------*/
5061 /* genCmp :- greater or less than comparison */
5062 /*-----------------------------------------------------------------*/
5064 genCmp (operand * left, operand * right,
5065 operand * result, iCode * ifx, int sign, iCode *ic)
5067 int size, offset = 0;
5068 unsigned long lit = 0L;
5071 D(emitcode ("; genCmp",""));
5073 /* if left & right are bit variables */
5074 if (AOP_TYPE (left) == AOP_CRY &&
5075 AOP_TYPE (right) == AOP_CRY)
5077 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5078 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5082 /* subtract right from left if at the
5083 end the carry flag is set then we know that
5084 left is greater than right */
5085 size = max (AOP_SIZE (left), AOP_SIZE (right));
5087 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5088 if ((size == 1) && !sign &&
5089 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5091 symbol *lbl = newiTempLabel (NULL);
5092 emitcode ("cjne", "%s,%s,%05d$",
5093 aopGet (left, offset, FALSE, FALSE),
5094 aopGet (right, offset, FALSE, FALSE),
5096 emitcode ("", "%05d$:", lbl->key + 100);
5100 if (AOP_TYPE (right) == AOP_LIT)
5102 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5103 /* optimize if(x < 0) or if(x >= 0) */
5112 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5113 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5115 genIfxJump (ifx, "acc.7", left, right, result);
5116 freeAsmop (right, NULL, ic, TRUE);
5117 freeAsmop (left, NULL, ic, TRUE);
5122 emitcode ("rlc", "a");
5130 bool pushedB = FALSE;
5131 rightInB = aopGetUsesAcc(right, offset);
5135 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5137 MOVA (aopGet (left, offset, FALSE, FALSE));
5138 if (sign && size == 0)
5140 emitcode ("xrl", "a,#0x80");
5141 if (AOP_TYPE (right) == AOP_LIT)
5143 unsigned long lit = (unsigned long)
5144 floatFromVal (AOP (right)->aopu.aop_lit);
5145 emitcode ("subb", "a,#0x%02x",
5146 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5154 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5156 emitcode ("xrl", "b,#0x80");
5157 emitcode ("subb", "a,b");
5163 emitcode ("subb", "a,b");
5165 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5175 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5183 /* if the result is used in the next
5184 ifx conditional branch then generate
5185 code a little differently */
5187 genIfxJump (ifx, "c", NULL, NULL, result);
5190 /* leave the result in acc */
5194 /*-----------------------------------------------------------------*/
5195 /* genCmpGt :- greater than comparison */
5196 /*-----------------------------------------------------------------*/
5198 genCmpGt (iCode * ic, iCode * ifx)
5200 operand *left, *right, *result;
5201 sym_link *letype, *retype;
5204 D(emitcode ("; genCmpGt",""));
5206 left = IC_LEFT (ic);
5207 right = IC_RIGHT (ic);
5208 result = IC_RESULT (ic);
5210 letype = getSpec (operandType (left));
5211 retype = getSpec (operandType (right));
5212 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5213 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5214 /* assign the amsops */
5215 aopOp (left, ic, FALSE);
5216 aopOp (right, ic, FALSE);
5217 aopOp (result, ic, TRUE);
5219 genCmp (right, left, result, ifx, sign, ic);
5221 freeAsmop (result, NULL, ic, TRUE);
5224 /*-----------------------------------------------------------------*/
5225 /* genCmpLt - less than comparisons */
5226 /*-----------------------------------------------------------------*/
5228 genCmpLt (iCode * ic, iCode * ifx)
5230 operand *left, *right, *result;
5231 sym_link *letype, *retype;
5234 D(emitcode ("; genCmpLt",""));
5236 left = IC_LEFT (ic);
5237 right = IC_RIGHT (ic);
5238 result = IC_RESULT (ic);
5240 letype = getSpec (operandType (left));
5241 retype = getSpec (operandType (right));
5242 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5243 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5244 /* assign the amsops */
5245 aopOp (left, ic, FALSE);
5246 aopOp (right, ic, FALSE);
5247 aopOp (result, ic, TRUE);
5249 genCmp (left, right, result, ifx, sign,ic);
5251 freeAsmop (result, NULL, ic, TRUE);
5254 /*-----------------------------------------------------------------*/
5255 /* gencjneshort - compare and jump if not equal */
5256 /*-----------------------------------------------------------------*/
5258 gencjneshort (operand * left, operand * right, symbol * lbl)
5260 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5262 unsigned long lit = 0L;
5264 /* if the left side is a literal or
5265 if the right is in a pointer register and left
5267 if ((AOP_TYPE (left) == AOP_LIT) ||
5268 (AOP_TYPE (left) == AOP_IMMD) ||
5269 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5276 if (AOP_TYPE (right) == AOP_LIT)
5277 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5279 /* if the right side is a literal then anything goes */
5280 if (AOP_TYPE (right) == AOP_LIT &&
5281 AOP_TYPE (left) != AOP_DIR &&
5282 AOP_TYPE (left) != AOP_IMMD)
5286 emitcode ("cjne", "%s,%s,%05d$",
5287 aopGet (left, offset, FALSE, FALSE),
5288 aopGet (right, offset, FALSE, FALSE),
5294 /* if the right side is in a register or in direct space or
5295 if the left is a pointer register & right is not */
5296 else if (AOP_TYPE (right) == AOP_REG ||
5297 AOP_TYPE (right) == AOP_DIR ||
5298 AOP_TYPE (right) == AOP_LIT ||
5299 AOP_TYPE (right) == AOP_IMMD ||
5300 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5301 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5305 MOVA (aopGet (left, offset, FALSE, FALSE));
5306 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5307 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5308 emitcode ("jnz", "%05d$", lbl->key + 100);
5310 emitcode ("cjne", "a,%s,%05d$",
5311 aopGet (right, offset, FALSE, TRUE),
5318 /* right is a pointer reg need both a & b */
5322 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5323 wassertl(!BINUSE, "B was in use");
5324 l = aopGet (left, offset, FALSE, FALSE);
5325 if (strcmp (l, "b"))
5326 emitcode ("mov", "b,%s", l);
5327 MOVA (aopGet (right, offset, FALSE, FALSE));
5328 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5334 /*-----------------------------------------------------------------*/
5335 /* gencjne - compare and jump if not equal */
5336 /*-----------------------------------------------------------------*/
5338 gencjne (operand * left, operand * right, symbol * lbl)
5340 symbol *tlbl = newiTempLabel (NULL);
5342 gencjneshort (left, right, lbl);
5344 emitcode ("mov", "a,%s", one);
5345 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5346 emitcode ("", "%05d$:", lbl->key + 100);
5347 emitcode ("clr", "a");
5348 emitcode ("", "%05d$:", tlbl->key + 100);
5351 /*-----------------------------------------------------------------*/
5352 /* genCmpEq - generates code for equal to */
5353 /*-----------------------------------------------------------------*/
5355 genCmpEq (iCode * ic, iCode * ifx)
5357 operand *left, *right, *result;
5359 D(emitcode ("; genCmpEq",""));
5361 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5362 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5363 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5365 /* if literal, literal on the right or
5366 if the right is in a pointer register and left
5368 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5369 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5371 operand *t = IC_RIGHT (ic);
5372 IC_RIGHT (ic) = IC_LEFT (ic);
5376 if (ifx && !AOP_SIZE (result))
5379 /* if they are both bit variables */
5380 if (AOP_TYPE (left) == AOP_CRY &&
5381 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5383 if (AOP_TYPE (right) == AOP_LIT)
5385 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5389 emitcode ("cpl", "c");
5393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5397 emitcode ("clr", "c");
5399 /* AOP_TYPE(right) == AOP_CRY */
5403 symbol *lbl = newiTempLabel (NULL);
5404 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5405 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5406 emitcode ("cpl", "c");
5407 emitcode ("", "%05d$:", (lbl->key + 100));
5409 /* if true label then we jump if condition
5411 tlbl = newiTempLabel (NULL);
5414 emitcode ("jnc", "%05d$", tlbl->key + 100);
5415 freeForBranchAsmop (result);
5416 freeForBranchAsmop (right);
5417 freeForBranchAsmop (left);
5418 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5422 emitcode ("jc", "%05d$", tlbl->key + 100);
5423 freeForBranchAsmop (result);
5424 freeForBranchAsmop (right);
5425 freeForBranchAsmop (left);
5426 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5428 emitcode ("", "%05d$:", tlbl->key + 100);
5432 tlbl = newiTempLabel (NULL);
5433 gencjneshort (left, right, tlbl);
5436 freeForBranchAsmop (result);
5437 freeForBranchAsmop (right);
5438 freeForBranchAsmop (left);
5439 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5440 emitcode ("", "%05d$:", tlbl->key + 100);
5444 symbol *lbl = newiTempLabel (NULL);
5445 emitcode ("sjmp", "%05d$", lbl->key + 100);
5446 emitcode ("", "%05d$:", tlbl->key + 100);
5447 freeForBranchAsmop (result);
5448 freeForBranchAsmop (right);
5449 freeForBranchAsmop (left);
5450 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5451 emitcode ("", "%05d$:", lbl->key + 100);
5454 /* mark the icode as generated */
5459 /* if they are both bit variables */
5460 if (AOP_TYPE (left) == AOP_CRY &&
5461 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5463 if (AOP_TYPE (right) == AOP_LIT)
5465 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5468 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5469 emitcode ("cpl", "c");
5473 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5477 emitcode ("clr", "c");
5479 /* AOP_TYPE(right) == AOP_CRY */
5483 symbol *lbl = newiTempLabel (NULL);
5484 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5485 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5486 emitcode ("cpl", "c");
5487 emitcode ("", "%05d$:", (lbl->key + 100));
5490 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5497 genIfxJump (ifx, "c", left, right, result);
5500 /* if the result is used in an arithmetic operation
5501 then put the result in place */
5506 gencjne (left, right, newiTempLabel (NULL));
5507 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5509 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5514 genIfxJump (ifx, "a", left, right, result);
5517 /* if the result is used in an arithmetic operation
5518 then put the result in place */
5519 if (AOP_TYPE (result) != AOP_CRY)
5521 /* leave the result in acc */
5525 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527 freeAsmop (result, NULL, ic, TRUE);
5530 /*-----------------------------------------------------------------*/
5531 /* ifxForOp - returns the icode containing the ifx for operand */
5532 /*-----------------------------------------------------------------*/
5534 ifxForOp (operand * op, iCode * ic)
5536 /* if true symbol then needs to be assigned */
5537 if (IS_TRUE_SYMOP (op))
5540 /* if this has register type condition and
5541 the next instruction is ifx with the same operand
5542 and live to of the operand is upto the ifx only then */
5544 ic->next->op == IFX &&
5545 IC_COND (ic->next)->key == op->key &&
5546 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5552 /*-----------------------------------------------------------------*/
5553 /* hasInc - operand is incremented before any other use */
5554 /*-----------------------------------------------------------------*/
5556 hasInc (operand *op, iCode *ic,int osize)
5558 sym_link *type = operandType(op);
5559 sym_link *retype = getSpec (type);
5560 iCode *lic = ic->next;
5563 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5564 if (!IS_SYMOP(op)) return NULL;
5566 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5567 if (IS_AGGREGATE(type->next)) return NULL;
5568 if (osize != (isize = getSize(type->next))) return NULL;
5571 /* if operand of the form op = op + <sizeof *op> */
5572 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5573 isOperandEqual(IC_RESULT(lic),op) &&
5574 isOperandLiteral(IC_RIGHT(lic)) &&
5575 operandLitValue(IC_RIGHT(lic)) == isize) {
5578 /* if the operand used or deffed */
5579 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5582 /* if GOTO or IFX */
5583 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5589 /*-----------------------------------------------------------------*/
5590 /* genAndOp - for && operation */
5591 /*-----------------------------------------------------------------*/
5593 genAndOp (iCode * ic)
5595 operand *left, *right, *result;
5598 D(emitcode ("; genAndOp",""));
5600 /* note here that && operations that are in an
5601 if statement are taken away by backPatchLabels
5602 only those used in arthmetic operations remain */
5603 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5604 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5605 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5607 /* if both are bit variables */
5608 if (AOP_TYPE (left) == AOP_CRY &&
5609 AOP_TYPE (right) == AOP_CRY)
5611 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5612 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5617 tlbl = newiTempLabel (NULL);
5619 emitcode ("jz", "%05d$", tlbl->key + 100);
5621 emitcode ("", "%05d$:", tlbl->key + 100);
5625 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5626 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5627 freeAsmop (result, NULL, ic, TRUE);
5631 /*-----------------------------------------------------------------*/
5632 /* genOrOp - for || operation */
5633 /*-----------------------------------------------------------------*/
5635 genOrOp (iCode * ic)
5637 operand *left, *right, *result;
5640 D(emitcode ("; genOrOp",""));
5642 /* note here that || operations that are in an
5643 if statement are taken away by backPatchLabels
5644 only those used in arthmetic operations remain */
5645 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5646 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5647 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5649 /* if both are bit variables */
5650 if (AOP_TYPE (left) == AOP_CRY &&
5651 AOP_TYPE (right) == AOP_CRY)
5653 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5654 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5659 tlbl = newiTempLabel (NULL);
5661 emitcode ("jnz", "%05d$", tlbl->key + 100);
5663 emitcode ("", "%05d$:", tlbl->key + 100);
5667 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5668 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669 freeAsmop (result, NULL, ic, TRUE);
5672 /*-----------------------------------------------------------------*/
5673 /* isLiteralBit - test if lit == 2^n */
5674 /*-----------------------------------------------------------------*/
5676 isLiteralBit (unsigned long lit)
5678 unsigned long pw[32] =
5679 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5680 0x100L, 0x200L, 0x400L, 0x800L,
5681 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5682 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5683 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5684 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5685 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5688 for (idx = 0; idx < 32; idx++)
5694 /*-----------------------------------------------------------------*/
5695 /* continueIfTrue - */
5696 /*-----------------------------------------------------------------*/
5698 continueIfTrue (iCode * ic)
5701 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5705 /*-----------------------------------------------------------------*/
5707 /*-----------------------------------------------------------------*/
5709 jumpIfTrue (iCode * ic)
5712 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5716 /*-----------------------------------------------------------------*/
5717 /* jmpTrueOrFalse - */
5718 /*-----------------------------------------------------------------*/
5720 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5722 // ugly but optimized by peephole
5725 symbol *nlbl = newiTempLabel (NULL);
5726 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5727 emitcode ("", "%05d$:", tlbl->key + 100);
5728 freeForBranchAsmop (result);
5729 freeForBranchAsmop (right);
5730 freeForBranchAsmop (left);
5731 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5732 emitcode ("", "%05d$:", nlbl->key + 100);
5736 freeForBranchAsmop (result);
5737 freeForBranchAsmop (right);
5738 freeForBranchAsmop (left);
5739 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5740 emitcode ("", "%05d$:", tlbl->key + 100);
5745 /*-----------------------------------------------------------------*/
5746 /* genAnd - code for and */
5747 /*-----------------------------------------------------------------*/
5749 genAnd (iCode * ic, iCode * ifx)
5751 operand *left, *right, *result;
5752 int size, offset = 0;
5753 unsigned long lit = 0L;
5757 D(emitcode ("; genAnd",""));
5759 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5760 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5761 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5764 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5766 AOP_TYPE (left), AOP_TYPE (right));
5767 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5769 AOP_SIZE (left), AOP_SIZE (right));
5772 /* if left is a literal & right is not then exchange them */
5773 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5774 AOP_NEEDSACC (left))
5776 operand *tmp = right;
5781 /* if result = right then exchange left and right */
5782 if (sameRegs (AOP (result), AOP (right)))
5784 operand *tmp = right;
5789 /* if right is bit then exchange them */
5790 if (AOP_TYPE (right) == AOP_CRY &&
5791 AOP_TYPE (left) != AOP_CRY)
5793 operand *tmp = right;
5797 if (AOP_TYPE (right) == AOP_LIT)
5798 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5800 size = AOP_SIZE (result);
5803 // result = bit & yy;
5804 if (AOP_TYPE (left) == AOP_CRY)
5806 // c = bit & literal;
5807 if (AOP_TYPE (right) == AOP_LIT)
5811 if (size && sameRegs (AOP (result), AOP (left)))
5814 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5819 if (size && (AOP_TYPE (result) == AOP_CRY))
5821 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5824 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5829 emitcode ("clr", "c");
5834 if (AOP_TYPE (right) == AOP_CRY)
5837 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5838 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5843 MOVA (aopGet (right, 0, FALSE, FALSE));
5845 emitcode ("rrc", "a");
5846 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5854 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5855 genIfxJump (ifx, "c", left, right, result);
5859 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5860 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5861 if ((AOP_TYPE (right) == AOP_LIT) &&
5862 (AOP_TYPE (result) == AOP_CRY) &&
5863 (AOP_TYPE (left) != AOP_CRY))
5865 int posbit = isLiteralBit (lit);
5870 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
5874 switch (posbit & 0x07)
5876 case 0: emitcode ("rrc", "a");
5878 case 7: emitcode ("rlc", "a");
5880 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5889 SNPRINTF (buffer, sizeof(buffer),
5890 "acc.%d", posbit & 0x07);
5891 genIfxJump (ifx, buffer, left, right, result);
5894 {// what is this case? just found it in ds390/gen.c
5895 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5902 symbol *tlbl = newiTempLabel (NULL);
5903 int sizel = AOP_SIZE (left);
5905 emitcode ("setb", "c");
5908 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5910 MOVA (aopGet (left, offset, FALSE, FALSE));
5912 if ((posbit = isLiteralBit (bytelit)) != 0)
5913 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5916 if (bytelit != 0x0FFL)
5917 emitcode ("anl", "a,%s",
5918 aopGet (right, offset, FALSE, TRUE));
5919 emitcode ("jnz", "%05d$", tlbl->key + 100);
5924 // bit = left & literal
5927 emitcode ("clr", "c");
5928 emitcode ("", "%05d$:", tlbl->key + 100);
5930 // if(left & literal)
5934 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5936 emitcode ("", "%05d$:", tlbl->key + 100);
5944 /* if left is same as result */
5945 if (sameRegs (AOP (result), AOP (left)))
5947 for (; size--; offset++)
5949 if (AOP_TYPE (right) == AOP_LIT)
5951 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5952 if (bytelit == 0x0FF)
5954 /* dummy read of volatile operand */
5955 if (isOperandVolatile (left, FALSE))
5956 MOVA (aopGet (left, offset, FALSE, FALSE));
5960 else if (bytelit == 0)
5962 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
5964 else if (IS_AOP_PREG (result))
5966 MOVA (aopGet (left, offset, FALSE, TRUE));
5967 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
5968 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
5971 emitcode ("anl", "%s,%s",
5972 aopGet (left, offset, FALSE, TRUE),
5973 aopGet (right, offset, FALSE, FALSE));
5977 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
5979 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
5983 MOVA (aopGet (right, offset, FALSE, FALSE));
5984 if (IS_AOP_PREG (result))
5986 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
5987 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
5990 emitcode ("anl", "%s,a",
5991 aopGet (left, offset, FALSE, TRUE));
5998 // left & result in different registers
5999 if (AOP_TYPE (result) == AOP_CRY)
6002 // if(size), result in bit
6003 // if(!size && ifx), conditional oper: if(left & right)
6004 symbol *tlbl = newiTempLabel (NULL);
6005 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6007 emitcode ("setb", "c");
6010 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6011 && AOP_TYPE(left)==AOP_ACC)
6014 emitcode("mov", "a,b");
6015 emitcode ("anl", "a,%s",
6016 aopGet (right, offset, FALSE, FALSE));
6018 if (AOP_TYPE(left)==AOP_ACC)
6022 bool pushedB = pushB ();
6023 emitcode("mov", "b,a");
6024 MOVA (aopGet (right, offset, FALSE, FALSE));
6025 emitcode("anl", "a,b");
6030 MOVA (aopGet (right, offset, FALSE, FALSE));
6031 emitcode("anl", "a,b");
6034 MOVA (aopGet (right, offset, FALSE, FALSE));
6035 emitcode ("anl", "a,%s",
6036 aopGet (left, offset, FALSE, FALSE));
6039 emitcode ("jnz", "%05d$", tlbl->key + 100);
6045 emitcode ("", "%05d$:", tlbl->key + 100);
6049 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6051 emitcode ("", "%05d$:", tlbl->key + 100);
6055 for (; (size--); offset++)
6058 // result = left & right
6059 if (AOP_TYPE (right) == AOP_LIT)
6061 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6062 if (bytelit == 0x0FF)
6065 aopGet (left, offset, FALSE, FALSE),
6067 isOperandVolatile (result, FALSE));
6070 else if (bytelit == 0)
6072 /* dummy read of volatile operand */
6073 if (isOperandVolatile (left, FALSE))
6074 MOVA (aopGet (left, offset, FALSE, FALSE));
6075 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6078 else if (AOP_TYPE (left) == AOP_ACC)
6082 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6083 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6088 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6089 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6094 // faster than result <- left, anl result,right
6095 // and better if result is SFR
6096 if (AOP_TYPE (left) == AOP_ACC)
6099 emitcode("mov", "a,b");
6100 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6104 MOVA (aopGet (right, offset, FALSE, FALSE));
6105 emitcode ("anl", "a,%s",
6106 aopGet (left, offset, FALSE, FALSE));
6108 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6114 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6115 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6116 freeAsmop (result, NULL, ic, TRUE);
6119 /*-----------------------------------------------------------------*/
6120 /* genOr - code for or */
6121 /*-----------------------------------------------------------------*/
6123 genOr (iCode * ic, iCode * ifx)
6125 operand *left, *right, *result;
6126 int size, offset = 0;
6127 unsigned long lit = 0L;
6130 D(emitcode ("; genOr",""));
6132 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6133 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6134 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6137 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6139 AOP_TYPE (left), AOP_TYPE (right));
6140 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6142 AOP_SIZE (left), AOP_SIZE (right));
6145 /* if left is a literal & right is not then exchange them */
6146 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6147 AOP_NEEDSACC (left))
6149 operand *tmp = right;
6154 /* if result = right then exchange them */
6155 if (sameRegs (AOP (result), AOP (right)))
6157 operand *tmp = right;
6162 /* if right is bit then exchange them */
6163 if (AOP_TYPE (right) == AOP_CRY &&
6164 AOP_TYPE (left) != AOP_CRY)
6166 operand *tmp = right;
6170 if (AOP_TYPE (right) == AOP_LIT)
6171 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6173 size = AOP_SIZE (result);
6177 if (AOP_TYPE (left) == AOP_CRY)
6179 if (AOP_TYPE (right) == AOP_LIT)
6181 // c = bit | literal;
6184 // lit != 0 => result = 1
6185 if (AOP_TYPE (result) == AOP_CRY)
6188 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6190 continueIfTrue (ifx);
6193 emitcode ("setb", "c");
6197 // lit == 0 => result = left
6198 if (size && sameRegs (AOP (result), AOP (left)))
6200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6205 if (AOP_TYPE (right) == AOP_CRY)
6208 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6209 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6214 symbol *tlbl = newiTempLabel (NULL);
6215 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6216 emitcode ("setb", "c");
6217 emitcode ("jb", "%s,%05d$",
6218 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6220 emitcode ("jnz", "%05d$", tlbl->key + 100);
6221 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6223 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6229 emitcode ("", "%05d$:", tlbl->key + 100);
6238 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6239 genIfxJump (ifx, "c", left, right, result);
6243 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6244 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6245 if ((AOP_TYPE (right) == AOP_LIT) &&
6246 (AOP_TYPE (result) == AOP_CRY) &&
6247 (AOP_TYPE (left) != AOP_CRY))
6253 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6255 continueIfTrue (ifx);
6260 // lit = 0, result = boolean(left)
6262 emitcode ("setb", "c");
6266 symbol *tlbl = newiTempLabel (NULL);
6267 emitcode ("jnz", "%05d$", tlbl->key + 100);
6269 emitcode ("", "%05d$:", tlbl->key + 100);
6273 genIfxJump (ifx, "a", left, right, result);
6281 /* if left is same as result */
6282 if (sameRegs (AOP (result), AOP (left)))
6284 for (; size--; offset++)
6286 if (AOP_TYPE (right) == AOP_LIT)
6288 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6291 /* dummy read of volatile operand */
6292 if (isOperandVolatile (left, FALSE))
6293 MOVA (aopGet (left, offset, FALSE, FALSE));
6297 else if (bytelit == 0x0FF)
6299 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6301 else if (IS_AOP_PREG (left))
6303 MOVA (aopGet (left, offset, FALSE, TRUE));
6304 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6305 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6309 emitcode ("orl", "%s,%s",
6310 aopGet (left, offset, FALSE, TRUE),
6311 aopGet (right, offset, FALSE, FALSE));
6316 if (AOP_TYPE (left) == AOP_ACC)
6319 emitcode("mov", "a,b");
6320 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6324 MOVA (aopGet (right, offset, FALSE, FALSE));
6325 if (IS_AOP_PREG (left))
6327 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6328 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6332 emitcode ("orl", "%s,a",
6333 aopGet (left, offset, FALSE, TRUE));
6341 // left & result in different registers
6342 if (AOP_TYPE (result) == AOP_CRY)
6345 // if(size), result in bit
6346 // if(!size && ifx), conditional oper: if(left | right)
6347 symbol *tlbl = newiTempLabel (NULL);
6348 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6350 emitcode ("setb", "c");
6353 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6355 emitcode("mov", "a,b");
6356 emitcode ("orl", "a,%s",
6357 aopGet (right, offset, FALSE, FALSE));
6359 MOVA (aopGet (right, offset, FALSE, FALSE));
6360 emitcode ("orl", "a,%s",
6361 aopGet (left, offset, FALSE, FALSE));
6363 emitcode ("jnz", "%05d$", tlbl->key + 100);
6369 emitcode ("", "%05d$:", tlbl->key + 100);
6373 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6375 emitcode ("", "%05d$:", tlbl->key + 100);
6379 for (; (size--); offset++)
6382 // result = left | right
6383 if (AOP_TYPE (right) == AOP_LIT)
6385 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6389 aopGet (left, offset, FALSE, FALSE),
6391 isOperandVolatile (result, FALSE));
6394 else if (bytelit == 0x0FF)
6396 /* dummy read of volatile operand */
6397 if (isOperandVolatile (left, FALSE))
6398 MOVA (aopGet (left, offset, FALSE, FALSE));
6399 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6403 // faster than result <- left, anl result,right
6404 // and better if result is SFR
6405 if (AOP_TYPE (left) == AOP_ACC)
6408 emitcode("mov", "a,b");
6409 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6413 MOVA (aopGet (right, offset, FALSE, FALSE));
6414 emitcode ("orl", "a,%s",
6415 aopGet (left, offset, FALSE, FALSE));
6417 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6425 freeAsmop (result, NULL, ic, TRUE);
6428 /*-----------------------------------------------------------------*/
6429 /* genXor - code for xclusive or */
6430 /*-----------------------------------------------------------------*/
6432 genXor (iCode * ic, iCode * ifx)
6434 operand *left, *right, *result;
6435 int size, offset = 0;
6436 unsigned long lit = 0L;
6439 D(emitcode ("; genXor",""));
6441 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6442 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6443 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6446 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6448 AOP_TYPE (left), AOP_TYPE (right));
6449 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6451 AOP_SIZE (left), AOP_SIZE (right));
6454 /* if left is a literal & right is not ||
6455 if left needs acc & right does not */
6456 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6457 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6459 operand *tmp = right;
6464 /* if result = right then exchange them */
6465 if (sameRegs (AOP (result), AOP (right)))
6467 operand *tmp = right;
6472 /* if right is bit then exchange them */
6473 if (AOP_TYPE (right) == AOP_CRY &&
6474 AOP_TYPE (left) != AOP_CRY)
6476 operand *tmp = right;
6480 if (AOP_TYPE (right) == AOP_LIT)
6481 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6483 size = AOP_SIZE (result);
6487 if (AOP_TYPE (left) == AOP_CRY)
6489 if (AOP_TYPE (right) == AOP_LIT)
6491 // c = bit & literal;
6494 // lit>>1 != 0 => result = 1
6495 if (AOP_TYPE (result) == AOP_CRY)
6498 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6500 continueIfTrue (ifx);
6503 emitcode ("setb", "c");
6510 // lit == 0, result = left
6511 if (size && sameRegs (AOP (result), AOP (left)))
6513 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6517 // lit == 1, result = not(left)
6518 if (size && sameRegs (AOP (result), AOP (left)))
6520 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6526 emitcode ("cpl", "c");
6535 symbol *tlbl = newiTempLabel (NULL);
6536 if (AOP_TYPE (right) == AOP_CRY)
6539 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6543 int sizer = AOP_SIZE (right);
6545 // if val>>1 != 0, result = 1
6546 emitcode ("setb", "c");
6549 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6551 // test the msb of the lsb
6552 emitcode ("anl", "a,#0xfe");
6553 emitcode ("jnz", "%05d$", tlbl->key + 100);
6557 emitcode ("rrc", "a");
6559 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6560 emitcode ("cpl", "c");
6561 emitcode ("", "%05d$:", (tlbl->key + 100));
6568 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6569 genIfxJump (ifx, "c", left, right, result);
6573 /* if left is same as result */
6574 if (sameRegs (AOP (result), AOP (left)))
6576 for (; size--; offset++)
6578 if (AOP_TYPE (right) == AOP_LIT)
6580 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6583 /* dummy read of volatile operand */
6584 if (isOperandVolatile (left, FALSE))
6585 MOVA (aopGet (left, offset, FALSE, FALSE));
6589 else if (IS_AOP_PREG (left))
6591 MOVA (aopGet (left, offset, FALSE, TRUE));
6592 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6593 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6597 emitcode ("xrl", "%s,%s",
6598 aopGet (left, offset, FALSE, TRUE),
6599 aopGet (right, offset, FALSE, FALSE));
6604 if (AOP_TYPE (left) == AOP_ACC)
6607 emitcode("mov", "a,b");
6608 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6612 MOVA (aopGet (right, offset, FALSE, FALSE));
6613 if (IS_AOP_PREG (left))
6615 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6616 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6619 emitcode ("xrl", "%s,a",
6620 aopGet (left, offset, FALSE, TRUE));
6627 // left & result in different registers
6628 if (AOP_TYPE (result) == AOP_CRY)
6631 // if(size), result in bit
6632 // if(!size && ifx), conditional oper: if(left ^ right)
6633 symbol *tlbl = newiTempLabel (NULL);
6634 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6636 emitcode ("setb", "c");
6639 if ((AOP_TYPE (right) == AOP_LIT) &&
6640 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6642 MOVA (aopGet (left, offset, FALSE, FALSE));
6646 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6648 emitcode("mov", "a,b");
6649 emitcode ("xrl", "a,%s",
6650 aopGet (right, offset, FALSE, FALSE));
6652 MOVA (aopGet (right, offset, FALSE, FALSE));
6653 emitcode ("xrl", "a,%s",
6654 aopGet (left, offset, FALSE, FALSE));
6657 emitcode ("jnz", "%05d$", tlbl->key + 100);
6663 emitcode ("", "%05d$:", tlbl->key + 100);
6667 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6671 for (; (size--); offset++)
6674 // result = left & right
6675 if (AOP_TYPE (right) == AOP_LIT)
6677 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6681 aopGet (left, offset, FALSE, FALSE),
6683 isOperandVolatile (result, FALSE));
6687 // faster than result <- left, anl result,right
6688 // and better if result is SFR
6689 if (AOP_TYPE (left) == AOP_ACC)
6692 emitcode("mov", "a,b");
6693 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6697 MOVA (aopGet (right, offset, FALSE, FALSE));
6698 emitcode ("xrl", "a,%s",
6699 aopGet (left, offset, FALSE, TRUE));
6701 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6707 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6709 freeAsmop (result, NULL, ic, TRUE);
6712 /*-----------------------------------------------------------------*/
6713 /* genInline - write the inline code out */
6714 /*-----------------------------------------------------------------*/
6716 genInline (iCode * ic)
6718 char *buffer, *bp, *bp1;
6720 D(emitcode ("; genInline",""));
6722 _G.inLine += (!options.asmpeep);
6724 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6725 strcpy (buffer, IC_INLINE (ic));
6727 /* emit each line as a code */
6738 /* Add \n for labels, not dirs such as c:\mydir */
6739 if ( (*bp == ':') && (isspace(bp[1])) )
6753 /* emitcode("",buffer); */
6754 _G.inLine -= (!options.asmpeep);
6757 /*-----------------------------------------------------------------*/
6758 /* genRRC - rotate right with carry */
6759 /*-----------------------------------------------------------------*/
6763 operand *left, *result;
6764 int size, offset = 0;
6767 D(emitcode ("; genRRC",""));
6769 /* rotate right with carry */
6770 left = IC_LEFT (ic);
6771 result = IC_RESULT (ic);
6772 aopOp (left, ic, FALSE);
6773 aopOp (result, ic, FALSE);
6775 /* move it to the result */
6776 size = AOP_SIZE (result);
6778 if (size == 1) { /* special case for 1 byte */
6779 l = aopGet (left, offset, FALSE, FALSE);
6781 emitcode ("rr", "a");
6784 /* no need to clear carry, bit7 will be written later */
6787 l = aopGet (left, offset, FALSE, FALSE);
6789 emitcode ("rrc", "a");
6790 if (AOP_SIZE (result) > 1)
6791 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
6793 /* now we need to put the carry into the
6794 highest order byte of the result */
6795 if (AOP_SIZE (result) > 1)
6797 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
6800 emitcode ("mov", "acc.7,c");
6802 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6803 freeAsmop (left, NULL, ic, TRUE);
6804 freeAsmop (result, NULL, ic, TRUE);
6807 /*-----------------------------------------------------------------*/
6808 /* genRLC - generate code for rotate left with carry */
6809 /*-----------------------------------------------------------------*/
6813 operand *left, *result;
6814 int size, offset = 0;
6817 D(emitcode ("; genRLC",""));
6819 /* rotate right with carry */
6820 left = IC_LEFT (ic);
6821 result = IC_RESULT (ic);
6822 aopOp (left, ic, FALSE);
6823 aopOp (result, ic, FALSE);
6825 /* move it to the result */
6826 size = AOP_SIZE (result);
6830 l = aopGet (left, offset, FALSE, FALSE);
6832 if (size == 0) { /* special case for 1 byte */
6836 emitcode("rlc","a"); /* bit0 will be written later */
6837 if (AOP_SIZE (result) > 1)
6838 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6841 l = aopGet (left, offset, FALSE, FALSE);
6843 emitcode ("rlc", "a");
6844 if (AOP_SIZE (result) > 1)
6845 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6848 /* now we need to put the carry into the
6849 highest order byte of the result */
6850 if (AOP_SIZE (result) > 1)
6852 l = aopGet (result, 0, FALSE, FALSE);
6855 emitcode ("mov", "acc.0,c");
6857 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6858 freeAsmop (left, NULL, ic, TRUE);
6859 freeAsmop (result, NULL, ic, TRUE);
6862 /*-----------------------------------------------------------------*/
6863 /* genGetHbit - generates code get highest order bit */
6864 /*-----------------------------------------------------------------*/
6866 genGetHbit (iCode * ic)
6868 operand *left, *result;
6870 D(emitcode ("; genGetHbit",""));
6872 left = IC_LEFT (ic);
6873 result = IC_RESULT (ic);
6874 aopOp (left, ic, FALSE);
6875 aopOp (result, ic, FALSE);
6877 /* get the highest order byte into a */
6878 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
6879 if (AOP_TYPE (result) == AOP_CRY)
6881 emitcode ("rlc", "a");
6886 emitcode ("rl", "a");
6887 emitcode ("anl", "a,#0x01");
6892 freeAsmop (left, NULL, ic, TRUE);
6893 freeAsmop (result, NULL, ic, TRUE);
6896 /*-----------------------------------------------------------------*/
6897 /* genSwap - generates code to swap nibbles or bytes */
6898 /*-----------------------------------------------------------------*/
6900 genSwap (iCode * ic)
6902 operand *left, *result;
6904 D(emitcode ("; genSwap",""));
6906 left = IC_LEFT (ic);
6907 result = IC_RESULT (ic);
6908 aopOp (left, ic, FALSE);
6909 aopOp (result, ic, FALSE);
6911 switch (AOP_SIZE (left))
6913 case 1: /* swap nibbles in byte */
6914 MOVA (aopGet (left, 0, FALSE, FALSE));
6915 emitcode ("swap", "a");
6916 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6918 case 2: /* swap bytes in word */
6919 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6921 MOVA (aopGet (left, 0, FALSE, FALSE));
6922 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6923 0, isOperandVolatile (result, FALSE));
6924 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
6926 else if (operandsEqu (left, result))
6929 bool pushedB = FALSE, leftInB = FALSE;
6931 MOVA (aopGet (left, 0, FALSE, FALSE));
6932 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
6935 emitcode ("mov", "b,a");
6939 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6940 0, isOperandVolatile (result, FALSE));
6941 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
6948 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6949 0, isOperandVolatile (result, FALSE));
6950 aopPut (result, aopGet (left, 0, FALSE, FALSE),
6951 1, isOperandVolatile (result, FALSE));
6955 wassertl(FALSE, "unsupported SWAP operand size");
6958 freeAsmop (left, NULL, ic, TRUE);
6959 freeAsmop (result, NULL, ic, TRUE);
6963 /*-----------------------------------------------------------------*/
6964 /* AccRol - rotate left accumulator by known count */
6965 /*-----------------------------------------------------------------*/
6967 AccRol (int shCount)
6969 shCount &= 0x0007; // shCount : 0..7
6976 emitcode ("rl", "a");
6979 emitcode ("rl", "a");
6980 emitcode ("rl", "a");
6983 emitcode ("swap", "a");
6984 emitcode ("rr", "a");
6987 emitcode ("swap", "a");
6990 emitcode ("swap", "a");
6991 emitcode ("rl", "a");
6994 emitcode ("rr", "a");
6995 emitcode ("rr", "a");
6998 emitcode ("rr", "a");
7003 /*-----------------------------------------------------------------*/
7004 /* AccLsh - left shift accumulator by known count */
7005 /*-----------------------------------------------------------------*/
7007 AccLsh (int shCount)
7012 emitcode ("add", "a,acc");
7013 else if (shCount == 2)
7015 emitcode ("add", "a,acc");
7016 emitcode ("add", "a,acc");
7020 /* rotate left accumulator */
7022 /* and kill the lower order bits */
7023 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7028 /*-----------------------------------------------------------------*/
7029 /* AccRsh - right shift accumulator by known count */
7030 /*-----------------------------------------------------------------*/
7032 AccRsh (int shCount)
7039 emitcode ("rrc", "a");
7043 /* rotate right accumulator */
7044 AccRol (8 - shCount);
7045 /* and kill the higher order bits */
7046 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7051 /*-----------------------------------------------------------------*/
7052 /* AccSRsh - signed right shift accumulator by known count */
7053 /*-----------------------------------------------------------------*/
7055 AccSRsh (int shCount)
7062 emitcode ("mov", "c,acc.7");
7063 emitcode ("rrc", "a");
7065 else if (shCount == 2)
7067 emitcode ("mov", "c,acc.7");
7068 emitcode ("rrc", "a");
7069 emitcode ("mov", "c,acc.7");
7070 emitcode ("rrc", "a");
7074 tlbl = newiTempLabel (NULL);
7075 /* rotate right accumulator */
7076 AccRol (8 - shCount);
7077 /* and kill the higher order bits */
7078 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7079 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7080 emitcode ("orl", "a,#0x%02x",
7081 (unsigned char) ~SRMask[shCount]);
7082 emitcode ("", "%05d$:", tlbl->key + 100);
7087 /*-----------------------------------------------------------------*/
7088 /* shiftR1Left2Result - shift right one byte from left to result */
7089 /*-----------------------------------------------------------------*/
7091 shiftR1Left2Result (operand * left, int offl,
7092 operand * result, int offr,
7093 int shCount, int sign)
7095 MOVA (aopGet (left, offl, FALSE, FALSE));
7096 /* shift right accumulator */
7101 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7104 /*-----------------------------------------------------------------*/
7105 /* shiftL1Left2Result - shift left one byte from left to result */
7106 /*-----------------------------------------------------------------*/
7108 shiftL1Left2Result (operand * left, int offl,
7109 operand * result, int offr, int shCount)
7112 l = aopGet (left, offl, FALSE, FALSE);
7114 /* shift left accumulator */
7116 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7119 /*-----------------------------------------------------------------*/
7120 /* movLeft2Result - move byte from left to result */
7121 /*-----------------------------------------------------------------*/
7123 movLeft2Result (operand * left, int offl,
7124 operand * result, int offr, int sign)
7127 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7129 l = aopGet (left, offl, FALSE, FALSE);
7131 if (*l == '@' && (IS_AOP_PREG (result)))
7133 emitcode ("mov", "a,%s", l);
7134 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7139 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7142 /* MSB sign in acc.7 ! */
7143 if (getDataSize (left) == offl + 1)
7145 emitcode ("mov", "a,%s", l);
7146 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7153 /*-----------------------------------------------------------------*/
7154 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7155 /*-----------------------------------------------------------------*/
7159 emitcode ("rrc", "a");
7160 emitcode ("xch", "a,%s", x);
7161 emitcode ("rrc", "a");
7162 emitcode ("xch", "a,%s", x);
7165 /*-----------------------------------------------------------------*/
7166 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7167 /*-----------------------------------------------------------------*/
7171 emitcode ("xch", "a,%s", x);
7172 emitcode ("rlc", "a");
7173 emitcode ("xch", "a,%s", x);
7174 emitcode ("rlc", "a");
7177 /*-----------------------------------------------------------------*/
7178 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7179 /*-----------------------------------------------------------------*/
7183 emitcode ("xch", "a,%s", x);
7184 emitcode ("add", "a,acc");
7185 emitcode ("xch", "a,%s", x);
7186 emitcode ("rlc", "a");
7189 /*-----------------------------------------------------------------*/
7190 /* AccAXLsh - left shift a:x by known count (0..7) */
7191 /*-----------------------------------------------------------------*/
7193 AccAXLsh (char *x, int shCount)
7208 case 5: // AAAAABBB:CCCCCDDD
7210 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7212 emitcode ("anl", "a,#0x%02x",
7213 SLMask[shCount]); // BBB00000:CCCCCDDD
7215 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7217 AccRol (shCount); // DDDCCCCC:BBB00000
7219 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7221 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7223 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7225 emitcode ("anl", "a,#0x%02x",
7226 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7228 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7230 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7233 case 6: // AAAAAABB:CCCCCCDD
7234 emitcode ("anl", "a,#0x%02x",
7235 SRMask[shCount]); // 000000BB:CCCCCCDD
7236 emitcode ("mov", "c,acc.0"); // c = B
7237 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7239 AccAXRrl1 (x); // BCCCCCCD:D000000B
7240 AccAXRrl1 (x); // BBCCCCCC:DD000000
7242 emitcode("rrc","a");
7243 emitcode("xch","a,%s", x);
7244 emitcode("rrc","a");
7245 emitcode("mov","c,acc.0"); //<< get correct bit
7246 emitcode("xch","a,%s", x);
7248 emitcode("rrc","a");
7249 emitcode("xch","a,%s", x);
7250 emitcode("rrc","a");
7251 emitcode("xch","a,%s", x);
7254 case 7: // a:x <<= 7
7256 emitcode ("anl", "a,#0x%02x",
7257 SRMask[shCount]); // 0000000B:CCCCCCCD
7259 emitcode ("mov", "c,acc.0"); // c = B
7261 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7263 AccAXRrl1 (x); // BCCCCCCC:D0000000
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRsh - right shift a:x known count (0..7) */
7273 /*-----------------------------------------------------------------*/
7275 AccAXRsh (char *x, int shCount)
7283 AccAXRrl1 (x); // 0->a:x
7288 AccAXRrl1 (x); // 0->a:x
7291 AccAXRrl1 (x); // 0->a:x
7296 case 5: // AAAAABBB:CCCCCDDD = a:x
7298 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7300 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7302 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7304 emitcode ("anl", "a,#0x%02x",
7305 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7307 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7309 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7311 emitcode ("anl", "a,#0x%02x",
7312 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7314 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7316 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7318 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7321 case 6: // AABBBBBB:CCDDDDDD
7323 emitcode ("mov", "c,acc.7");
7324 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7326 emitcode ("mov", "c,acc.7");
7327 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7329 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7331 emitcode ("anl", "a,#0x%02x",
7332 SRMask[shCount]); // 000000AA:BBBBBBCC
7335 case 7: // ABBBBBBB:CDDDDDDD
7337 emitcode ("mov", "c,acc.7"); // c = A
7339 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7341 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7343 emitcode ("anl", "a,#0x%02x",
7344 SRMask[shCount]); // 0000000A:BBBBBBBC
7352 /*-----------------------------------------------------------------*/
7353 /* AccAXRshS - right shift signed a:x known count (0..7) */
7354 /*-----------------------------------------------------------------*/
7356 AccAXRshS (char *x, int shCount)
7364 emitcode ("mov", "c,acc.7");
7365 AccAXRrl1 (x); // s->a:x
7369 emitcode ("mov", "c,acc.7");
7370 AccAXRrl1 (x); // s->a:x
7372 emitcode ("mov", "c,acc.7");
7373 AccAXRrl1 (x); // s->a:x
7378 case 5: // AAAAABBB:CCCCCDDD = a:x
7380 tlbl = newiTempLabel (NULL);
7381 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7383 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7385 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7387 emitcode ("anl", "a,#0x%02x",
7388 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7390 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7392 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7394 emitcode ("anl", "a,#0x%02x",
7395 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7397 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7399 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7401 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7403 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7404 emitcode ("orl", "a,#0x%02x",
7405 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7407 emitcode ("", "%05d$:", tlbl->key + 100);
7408 break; // SSSSAAAA:BBBCCCCC
7410 case 6: // AABBBBBB:CCDDDDDD
7412 tlbl = newiTempLabel (NULL);
7413 emitcode ("mov", "c,acc.7");
7414 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7416 emitcode ("mov", "c,acc.7");
7417 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7419 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7421 emitcode ("anl", "a,#0x%02x",
7422 SRMask[shCount]); // 000000AA:BBBBBBCC
7424 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7425 emitcode ("orl", "a,#0x%02x",
7426 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7428 emitcode ("", "%05d$:", tlbl->key + 100);
7430 case 7: // ABBBBBBB:CDDDDDDD
7432 tlbl = newiTempLabel (NULL);
7433 emitcode ("mov", "c,acc.7"); // c = A
7435 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7437 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7439 emitcode ("anl", "a,#0x%02x",
7440 SRMask[shCount]); // 0000000A:BBBBBBBC
7442 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7443 emitcode ("orl", "a,#0x%02x",
7444 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7446 emitcode ("", "%05d$:", tlbl->key + 100);
7453 /*-----------------------------------------------------------------*/
7454 /* shiftL2Left2Result - shift left two bytes from left to result */
7455 /*-----------------------------------------------------------------*/
7457 shiftL2Left2Result (operand * left, int offl,
7458 operand * result, int offr, int shCount)
7460 if (sameRegs (AOP (result), AOP (left)) &&
7461 ((offl + MSB16) == offr))
7463 /* don't crash result[offr] */
7464 MOVA (aopGet (left, offl, FALSE, FALSE));
7465 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7469 movLeft2Result (left, offl, result, offr, 0);
7470 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7472 /* ax << shCount (x = lsb(result)) */
7473 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7474 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7478 /*-----------------------------------------------------------------*/
7479 /* shiftR2Left2Result - shift right two bytes from left to result */
7480 /*-----------------------------------------------------------------*/
7482 shiftR2Left2Result (operand * left, int offl,
7483 operand * result, int offr,
7484 int shCount, int sign)
7486 if (sameRegs (AOP (result), AOP (left)) &&
7487 ((offl + MSB16) == offr))
7489 /* don't crash result[offr] */
7490 MOVA (aopGet (left, offl, FALSE, FALSE));
7491 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7495 movLeft2Result (left, offl, result, offr, 0);
7496 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7498 /* a:x >> shCount (x = lsb(result)) */
7500 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7502 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7503 if (getDataSize (result) > 1)
7504 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7507 /*-----------------------------------------------------------------*/
7508 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7509 /*-----------------------------------------------------------------*/
7511 shiftLLeftOrResult (operand * left, int offl,
7512 operand * result, int offr, int shCount)
7514 MOVA (aopGet (left, offl, FALSE, FALSE));
7515 /* shift left accumulator */
7517 /* or with result */
7518 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7519 /* back to result */
7520 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7523 /*-----------------------------------------------------------------*/
7524 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7525 /*-----------------------------------------------------------------*/
7527 shiftRLeftOrResult (operand * left, int offl,
7528 operand * result, int offr, int shCount)
7530 MOVA (aopGet (left, offl, FALSE, FALSE));
7531 /* shift right accumulator */
7533 /* or with result */
7534 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7535 /* back to result */
7536 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7539 /*-----------------------------------------------------------------*/
7540 /* genlshOne - left shift a one byte quantity by known count */
7541 /*-----------------------------------------------------------------*/
7543 genlshOne (operand * result, operand * left, int shCount)
7545 D(emitcode ("; genlshOne",""));
7547 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7550 /*-----------------------------------------------------------------*/
7551 /* genlshTwo - left shift two bytes by known amount != 0 */
7552 /*-----------------------------------------------------------------*/
7554 genlshTwo (operand * result, operand * left, int shCount)
7558 D(emitcode ("; genlshTwo",""));
7560 size = getDataSize (result);
7562 /* if shCount >= 8 */
7570 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7572 movLeft2Result (left, LSB, result, MSB16, 0);
7574 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7577 /* 1 <= shCount <= 7 */
7581 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7583 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7587 /*-----------------------------------------------------------------*/
7588 /* shiftLLong - shift left one long from left to result */
7589 /* offl = LSB or MSB16 */
7590 /*-----------------------------------------------------------------*/
7592 shiftLLong (operand * left, operand * result, int offr)
7595 int size = AOP_SIZE (result);
7597 if (size >= LSB + offr)
7599 l = aopGet (left, LSB, FALSE, FALSE);
7601 emitcode ("add", "a,acc");
7602 if (sameRegs (AOP (left), AOP (result)) &&
7603 size >= MSB16 + offr && offr != LSB)
7604 emitcode ("xch", "a,%s",
7605 aopGet (left, LSB + offr, FALSE, FALSE));
7607 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7610 if (size >= MSB16 + offr)
7612 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7614 l = aopGet (left, MSB16, FALSE, FALSE);
7617 emitcode ("rlc", "a");
7618 if (sameRegs (AOP (left), AOP (result)) &&
7619 size >= MSB24 + offr && offr != LSB)
7620 emitcode ("xch", "a,%s",
7621 aopGet (left, MSB16 + offr, FALSE, FALSE));
7623 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7626 if (size >= MSB24 + offr)
7628 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7630 l = aopGet (left, MSB24, FALSE, FALSE);
7633 emitcode ("rlc", "a");
7634 if (sameRegs (AOP (left), AOP (result)) &&
7635 size >= MSB32 + offr && offr != LSB)
7636 emitcode ("xch", "a,%s",
7637 aopGet (left, MSB24 + offr, FALSE, FALSE));
7639 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7642 if (size > MSB32 + offr)
7644 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7646 l = aopGet (left, MSB32, FALSE, FALSE);
7649 emitcode ("rlc", "a");
7650 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7653 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7656 /*-----------------------------------------------------------------*/
7657 /* genlshFour - shift four byte by a known amount != 0 */
7658 /*-----------------------------------------------------------------*/
7660 genlshFour (operand * result, operand * left, int shCount)
7664 D(emitcode ("; genlshFour",""));
7666 size = AOP_SIZE (result);
7668 /* if shifting more that 3 bytes */
7673 /* lowest order of left goes to the highest
7674 order of the destination */
7675 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7677 movLeft2Result (left, LSB, result, MSB32, 0);
7678 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7679 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7680 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
7684 /* more than two bytes */
7685 else if (shCount >= 16)
7687 /* lower order two bytes goes to higher order two bytes */
7689 /* if some more remaining */
7691 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7694 movLeft2Result (left, MSB16, result, MSB32, 0);
7695 movLeft2Result (left, LSB, result, MSB24, 0);
7697 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7698 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7702 /* if more than 1 byte */
7703 else if (shCount >= 8)
7705 /* lower order three bytes goes to higher order three bytes */
7710 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7712 movLeft2Result (left, LSB, result, MSB16, 0);
7718 movLeft2Result (left, MSB24, result, MSB32, 0);
7719 movLeft2Result (left, MSB16, result, MSB24, 0);
7720 movLeft2Result (left, LSB, result, MSB16, 0);
7721 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7723 else if (shCount == 1)
7724 shiftLLong (left, result, MSB16);
7727 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7728 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7729 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7730 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7735 /* 1 <= shCount <= 7 */
7736 else if (shCount <= 2)
7738 shiftLLong (left, result, LSB);
7740 shiftLLong (result, result, LSB);
7742 /* 3 <= shCount <= 7, optimize */
7745 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7746 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7747 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7751 /*-----------------------------------------------------------------*/
7752 /* genLeftShiftLiteral - left shifting by known count */
7753 /*-----------------------------------------------------------------*/
7755 genLeftShiftLiteral (operand * left,
7760 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7763 D(emitcode ("; genLeftShiftLiteral",""));
7765 freeAsmop (right, NULL, ic, TRUE);
7767 aopOp (left, ic, FALSE);
7768 aopOp (result, ic, FALSE);
7770 size = getSize (operandType (result));
7773 emitcode ("; shift left ", "result %d, left %d", size,
7777 /* I suppose that the left size >= result size */
7782 movLeft2Result (left, size, result, size, 0);
7786 else if (shCount >= (size * 8))
7788 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
7794 genlshOne (result, left, shCount);
7798 genlshTwo (result, left, shCount);
7802 genlshFour (result, left, shCount);
7805 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7806 "*** ack! mystery literal shift!\n");
7810 freeAsmop (left, NULL, ic, TRUE);
7811 freeAsmop (result, NULL, ic, TRUE);
7814 /*-----------------------------------------------------------------*/
7815 /* genLeftShift - generates code for left shifting */
7816 /*-----------------------------------------------------------------*/
7818 genLeftShift (iCode * ic)
7820 operand *left, *right, *result;
7823 symbol *tlbl, *tlbl1;
7826 D(emitcode ("; genLeftShift",""));
7828 right = IC_RIGHT (ic);
7829 left = IC_LEFT (ic);
7830 result = IC_RESULT (ic);
7832 aopOp (right, ic, FALSE);
7834 /* if the shift count is known then do it
7835 as efficiently as possible */
7836 if (AOP_TYPE (right) == AOP_LIT)
7838 genLeftShiftLiteral (left, right, result, ic);
7842 /* shift count is unknown then we have to form
7843 a loop get the loop count in B : Note: we take
7844 only the lower order byte since shifting
7845 more that 32 bits make no sense anyway, ( the
7846 largest size of an object can be only 32 bits ) */
7849 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
7850 emitcode ("inc", "b");
7851 freeAsmop (right, NULL, ic, TRUE);
7852 aopOp (left, ic, FALSE);
7853 aopOp (result, ic, FALSE);
7855 /* now move the left to the result if they are not the same */
7856 if (!sameRegs (AOP (left), AOP (result)) &&
7857 AOP_SIZE (result) > 1)
7860 size = AOP_SIZE (result);
7864 l = aopGet (left, offset, FALSE, TRUE);
7865 if (*l == '@' && (IS_AOP_PREG (result)))
7868 emitcode ("mov", "a,%s", l);
7869 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7872 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
7877 tlbl = newiTempLabel (NULL);
7878 size = AOP_SIZE (result);
7880 tlbl1 = newiTempLabel (NULL);
7882 /* if it is only one byte then */
7885 symbol *tlbl1 = newiTempLabel (NULL);
7887 l = aopGet (left, 0, FALSE, FALSE);
7889 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7890 emitcode ("", "%05d$:", tlbl->key + 100);
7891 emitcode ("add", "a,acc");
7892 emitcode ("", "%05d$:", tlbl1->key + 100);
7893 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7895 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7899 reAdjustPreg (AOP (result));
7901 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7902 emitcode ("", "%05d$:", tlbl->key + 100);
7903 l = aopGet (result, offset, FALSE, FALSE);
7905 emitcode ("add", "a,acc");
7906 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7909 l = aopGet (result, offset, FALSE, FALSE);
7911 emitcode ("rlc", "a");
7912 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7914 reAdjustPreg (AOP (result));
7916 emitcode ("", "%05d$:", tlbl1->key + 100);
7917 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7920 freeAsmop (left, NULL, ic, TRUE);
7921 freeAsmop (result, NULL, ic, TRUE);
7924 /*-----------------------------------------------------------------*/
7925 /* genrshOne - right shift a one byte quantity by known count */
7926 /*-----------------------------------------------------------------*/
7928 genrshOne (operand * result, operand * left,
7929 int shCount, int sign)
7931 D(emitcode ("; genrshOne",""));
7933 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7936 /*-----------------------------------------------------------------*/
7937 /* genrshTwo - right shift two bytes by known amount != 0 */
7938 /*-----------------------------------------------------------------*/
7940 genrshTwo (operand * result, operand * left,
7941 int shCount, int sign)
7943 D(emitcode ("; genrshTwo",""));
7945 /* if shCount >= 8 */
7950 shiftR1Left2Result (left, MSB16, result, LSB,
7953 movLeft2Result (left, MSB16, result, LSB, sign);
7954 addSign (result, MSB16, sign);
7957 /* 1 <= shCount <= 7 */
7959 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7962 /*-----------------------------------------------------------------*/
7963 /* shiftRLong - shift right one long from left to result */
7964 /* offl = LSB or MSB16 */
7965 /*-----------------------------------------------------------------*/
7967 shiftRLong (operand * left, int offl,
7968 operand * result, int sign)
7970 int isSameRegs=sameRegs(AOP(left),AOP(result));
7972 if (isSameRegs && offl>1) {
7973 // we are in big trouble, but this shouldn't happen
7974 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7977 MOVA (aopGet (left, MSB32, FALSE, FALSE));
7982 emitcode ("rlc", "a");
7983 emitcode ("subb", "a,acc");
7985 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
7987 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
7988 MOVA (aopGet (left, MSB32, FALSE, FALSE));
7991 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
7996 emitcode ("clr", "c");
7998 emitcode ("mov", "c,acc.7");
8001 emitcode ("rrc", "a");
8003 if (isSameRegs && offl==MSB16) {
8004 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8006 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8007 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8010 emitcode ("rrc", "a");
8011 if (isSameRegs && offl==1) {
8012 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8014 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8015 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8017 emitcode ("rrc", "a");
8018 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8022 MOVA (aopGet (left, LSB, FALSE, FALSE));
8023 emitcode ("rrc", "a");
8024 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8028 /*-----------------------------------------------------------------*/
8029 /* genrshFour - shift four byte by a known amount != 0 */
8030 /*-----------------------------------------------------------------*/
8032 genrshFour (operand * result, operand * left,
8033 int shCount, int sign)
8035 D(emitcode ("; genrshFour",""));
8037 /* if shifting more that 3 bytes */
8042 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8044 movLeft2Result (left, MSB32, result, LSB, sign);
8045 addSign (result, MSB16, sign);
8047 else if (shCount >= 16)
8051 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8054 movLeft2Result (left, MSB24, result, LSB, 0);
8055 movLeft2Result (left, MSB32, result, MSB16, sign);
8057 addSign (result, MSB24, sign);
8059 else if (shCount >= 8)
8063 shiftRLong (left, MSB16, result, sign);
8064 else if (shCount == 0)
8066 movLeft2Result (left, MSB16, result, LSB, 0);
8067 movLeft2Result (left, MSB24, result, MSB16, 0);
8068 movLeft2Result (left, MSB32, result, MSB24, sign);
8069 addSign (result, MSB32, sign);
8073 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8074 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8075 /* the last shift is signed */
8076 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8077 addSign (result, MSB32, sign);
8081 { /* 1 <= shCount <= 7 */
8084 shiftRLong (left, LSB, result, sign);
8086 shiftRLong (result, LSB, result, sign);
8090 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8091 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8092 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8097 /*-----------------------------------------------------------------*/
8098 /* genRightShiftLiteral - right shifting by known count */
8099 /*-----------------------------------------------------------------*/
8101 genRightShiftLiteral (operand * left,
8107 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8110 D(emitcode ("; genRightShiftLiteral",""));
8112 freeAsmop (right, NULL, ic, TRUE);
8114 aopOp (left, ic, FALSE);
8115 aopOp (result, ic, FALSE);
8118 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8122 size = getDataSize (left);
8123 /* test the LEFT size !!! */
8125 /* I suppose that the left size >= result size */
8128 size = getDataSize (result);
8130 movLeft2Result (left, size, result, size, 0);
8133 else if (shCount >= (size * 8))
8136 /* get sign in acc.7 */
8137 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8139 addSign (result, LSB, sign);
8146 genrshOne (result, left, shCount, sign);
8150 genrshTwo (result, left, shCount, sign);
8154 genrshFour (result, left, shCount, sign);
8160 freeAsmop (left, NULL, ic, TRUE);
8161 freeAsmop (result, NULL, ic, TRUE);
8164 /*-----------------------------------------------------------------*/
8165 /* genSignedRightShift - right shift of signed number */
8166 /*-----------------------------------------------------------------*/
8168 genSignedRightShift (iCode * ic)
8170 operand *right, *left, *result;
8173 symbol *tlbl, *tlbl1;
8176 D(emitcode ("; genSignedRightShift",""));
8178 /* we do it the hard way put the shift count in b
8179 and loop thru preserving the sign */
8181 right = IC_RIGHT (ic);
8182 left = IC_LEFT (ic);
8183 result = IC_RESULT (ic);
8185 aopOp (right, ic, FALSE);
8188 if (AOP_TYPE (right) == AOP_LIT)
8190 genRightShiftLiteral (left, right, result, ic, 1);
8193 /* shift count is unknown then we have to form
8194 a loop get the loop count in B : Note: we take
8195 only the lower order byte since shifting
8196 more that 32 bits make no sense anyway, ( the
8197 largest size of an object can be only 32 bits ) */
8200 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8201 emitcode ("inc", "b");
8202 freeAsmop (right, NULL, ic, TRUE);
8203 aopOp (left, ic, FALSE);
8204 aopOp (result, ic, FALSE);
8206 /* now move the left to the result if they are not the
8208 if (!sameRegs (AOP (left), AOP (result)) &&
8209 AOP_SIZE (result) > 1)
8212 size = AOP_SIZE (result);
8216 l = aopGet (left, offset, FALSE, TRUE);
8217 if (*l == '@' && IS_AOP_PREG (result))
8220 emitcode ("mov", "a,%s", l);
8221 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8224 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8229 /* mov the highest order bit to OVR */
8230 tlbl = newiTempLabel (NULL);
8231 tlbl1 = newiTempLabel (NULL);
8233 size = AOP_SIZE (result);
8235 MOVA (aopGet (left, offset, FALSE, FALSE));
8236 emitcode ("rlc", "a");
8237 emitcode ("mov", "ov,c");
8238 /* if it is only one byte then */
8241 l = aopGet (left, 0, FALSE, FALSE);
8243 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8244 emitcode ("", "%05d$:", tlbl->key + 100);
8245 emitcode ("mov", "c,ov");
8246 emitcode ("rrc", "a");
8247 emitcode ("", "%05d$:", tlbl1->key + 100);
8248 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8250 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8254 reAdjustPreg (AOP (result));
8255 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8256 emitcode ("", "%05d$:", tlbl->key + 100);
8257 emitcode ("mov", "c,ov");
8260 l = aopGet (result, offset, FALSE, FALSE);
8262 emitcode ("rrc", "a");
8263 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8265 reAdjustPreg (AOP (result));
8266 emitcode ("", "%05d$:", tlbl1->key + 100);
8267 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8271 freeAsmop (left, NULL, ic, TRUE);
8272 freeAsmop (result, NULL, ic, TRUE);
8275 /*-----------------------------------------------------------------*/
8276 /* genRightShift - generate code for right shifting */
8277 /*-----------------------------------------------------------------*/
8279 genRightShift (iCode * ic)
8281 operand *right, *left, *result;
8285 symbol *tlbl, *tlbl1;
8288 D(emitcode ("; genRightShift",""));
8290 /* if signed then we do it the hard way preserve the
8291 sign bit moving it inwards */
8292 letype = getSpec (operandType (IC_LEFT (ic)));
8294 if (!SPEC_USIGN (letype))
8296 genSignedRightShift (ic);
8300 /* signed & unsigned types are treated the same : i.e. the
8301 signed is NOT propagated inwards : quoting from the
8302 ANSI - standard : "for E1 >> E2, is equivalent to division
8303 by 2**E2 if unsigned or if it has a non-negative value,
8304 otherwise the result is implementation defined ", MY definition
8305 is that the sign does not get propagated */
8307 right = IC_RIGHT (ic);
8308 left = IC_LEFT (ic);
8309 result = IC_RESULT (ic);
8311 aopOp (right, ic, FALSE);
8313 /* if the shift count is known then do it
8314 as efficiently as possible */
8315 if (AOP_TYPE (right) == AOP_LIT)
8317 genRightShiftLiteral (left, right, result, ic, 0);
8321 /* shift count is unknown then we have to form
8322 a loop get the loop count in B : Note: we take
8323 only the lower order byte since shifting
8324 more that 32 bits make no sense anyway, ( the
8325 largest size of an object can be only 32 bits ) */
8328 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8329 emitcode ("inc", "b");
8330 freeAsmop (right, NULL, ic, TRUE);
8331 aopOp (left, ic, FALSE);
8332 aopOp (result, ic, FALSE);
8334 /* now move the left to the result if they are not the
8336 if (!sameRegs (AOP (left), AOP (result)) &&
8337 AOP_SIZE (result) > 1)
8340 size = AOP_SIZE (result);
8344 l = aopGet (left, offset, FALSE, TRUE);
8345 if (*l == '@' && IS_AOP_PREG (result))
8348 emitcode ("mov", "a,%s", l);
8349 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8352 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8357 tlbl = newiTempLabel (NULL);
8358 tlbl1 = newiTempLabel (NULL);
8359 size = AOP_SIZE (result);
8362 /* if it is only one byte then */
8365 l = aopGet (left, 0, FALSE, FALSE);
8367 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8368 emitcode ("", "%05d$:", tlbl->key + 100);
8370 emitcode ("rrc", "a");
8371 emitcode ("", "%05d$:", tlbl1->key + 100);
8372 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8374 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8378 reAdjustPreg (AOP (result));
8379 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8380 emitcode ("", "%05d$:", tlbl->key + 100);
8384 l = aopGet (result, offset, FALSE, FALSE);
8386 emitcode ("rrc", "a");
8387 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8389 reAdjustPreg (AOP (result));
8391 emitcode ("", "%05d$:", tlbl1->key + 100);
8392 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8396 freeAsmop (left, NULL, ic, TRUE);
8397 freeAsmop (result, NULL, ic, TRUE);
8400 /*-----------------------------------------------------------------*/
8401 /* emitPtrByteGet - emits code to get a byte into A through a */
8402 /* pointer register (R0, R1, or DPTR). The */
8403 /* original value of A can be preserved in B. */
8404 /*-----------------------------------------------------------------*/
8406 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8413 emitcode ("mov", "b,a");
8414 emitcode ("mov", "a,@%s", rname);
8419 emitcode ("mov", "b,a");
8420 emitcode ("movx", "a,@%s", rname);
8425 emitcode ("mov", "b,a");
8426 emitcode ("movx", "a,@dptr");
8431 emitcode ("mov", "b,a");
8432 emitcode ("clr", "a");
8433 emitcode ("movc", "a,@a+dptr");
8439 emitcode ("push", "b");
8440 emitcode ("push", "acc");
8442 emitcode ("lcall", "__gptrget");
8444 emitcode ("pop", "b");
8449 /*-----------------------------------------------------------------*/
8450 /* emitPtrByteSet - emits code to set a byte from src through a */
8451 /* pointer register (R0, R1, or DPTR). */
8452 /*-----------------------------------------------------------------*/
8454 emitPtrByteSet (char *rname, int p_type, char *src)
8463 emitcode ("mov", "@%s,a", rname);
8466 emitcode ("mov", "@%s,%s", rname, src);
8471 emitcode ("movx", "@%s,a", rname);
8476 emitcode ("movx", "@dptr,a");
8481 emitcode ("lcall", "__gptrput");
8486 /*-----------------------------------------------------------------*/
8487 /* genUnpackBits - generates code for unpacking bits */
8488 /*-----------------------------------------------------------------*/
8490 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8492 int offset = 0; /* result byte offset */
8493 int rsize; /* result size */
8494 int rlen = 0; /* remaining bitfield length */
8495 sym_link *etype; /* bitfield type information */
8496 int blen; /* bitfield length */
8497 int bstr; /* bitfield starting bit within byte */
8500 D(emitcode ("; genUnpackBits",""));
8502 etype = getSpec (operandType (result));
8503 rsize = getSize (operandType (result));
8504 blen = SPEC_BLEN (etype);
8505 bstr = SPEC_BSTR (etype);
8507 if (ifx && blen <= 8)
8509 emitPtrByteGet (rname, ptype, FALSE);
8512 SNPRINTF (buffer, sizeof(buffer),
8514 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8519 emitcode ("anl", "a,#0x%02x",
8520 (((unsigned char) -1) >> (8 - blen)) << bstr);
8521 genIfxJump (ifx, "a", NULL, NULL, NULL);
8527 /* If the bitfield length is less than a byte */
8530 emitPtrByteGet (rname, ptype, FALSE);
8532 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8533 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8537 /* Bit field did not fit in a byte. Copy all
8538 but the partial byte at the end. */
8539 for (rlen=blen;rlen>=8;rlen-=8)
8541 emitPtrByteGet (rname, ptype, FALSE);
8542 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8544 emitcode ("inc", "%s", rname);
8547 /* Handle the partial byte at the end */
8550 emitPtrByteGet (rname, ptype, FALSE);
8551 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8552 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8560 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8565 /*-----------------------------------------------------------------*/
8566 /* genDataPointerGet - generates code when ptr offset is known */
8567 /*-----------------------------------------------------------------*/
8569 genDataPointerGet (operand * left,
8575 int size, offset = 0;
8577 D(emitcode ("; genDataPointerGet",""));
8579 aopOp (result, ic, TRUE);
8581 /* get the string representation of the name */
8582 l = aopGet (left, 0, FALSE, TRUE);
8583 size = AOP_SIZE (result);
8587 sprintf (buffer, "(%s + %d)", l + 1, offset);
8589 sprintf (buffer, "%s", l + 1);
8590 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8593 freeAsmop (left, NULL, ic, TRUE);
8594 freeAsmop (result, NULL, ic, TRUE);
8597 /*-----------------------------------------------------------------*/
8598 /* genNearPointerGet - emitcode for near pointer fetch */
8599 /*-----------------------------------------------------------------*/
8601 genNearPointerGet (operand * left,
8610 sym_link *rtype, *retype;
8611 sym_link *ltype = operandType (left);
8614 D(emitcode ("; genNearPointerGet",""));
8616 rtype = operandType (result);
8617 retype = getSpec (rtype);
8619 aopOp (left, ic, FALSE);
8621 /* if left is rematerialisable and
8622 result is not bitfield variable type and
8623 the left is pointer to data space i.e
8624 lower 128 bytes of space */
8625 if (AOP_TYPE (left) == AOP_IMMD &&
8626 !IS_BITFIELD (retype) &&
8627 DCL_TYPE (ltype) == POINTER)
8629 genDataPointerGet (left, result, ic);
8633 /* if the value is already in a pointer register
8634 then don't need anything more */
8635 if (!AOP_INPREG (AOP (left)))
8637 if (IS_AOP_PREG (left))
8639 // Aha, it is a pointer, just in disguise.
8640 rname = aopGet (left, 0, FALSE, FALSE);
8643 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8644 __FILE__, __LINE__);
8649 emitcode ("mov", "a%s,%s", rname + 1, rname);
8650 rname++; // skip the '@'.
8655 /* otherwise get a free pointer register */
8657 preg = getFreePtr (ic, &aop, FALSE);
8658 emitcode ("mov", "%s,%s",
8660 aopGet (left, 0, FALSE, TRUE));
8665 rname = aopGet (left, 0, FALSE, FALSE);
8667 //aopOp (result, ic, FALSE);
8668 aopOp (result, ic, result?TRUE:FALSE);
8670 /* if bitfield then unpack the bits */
8671 if (IS_BITFIELD (retype))
8672 genUnpackBits (result, rname, POINTER, ifx);
8675 /* we have can just get the values */
8676 int size = AOP_SIZE (result);
8681 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8684 emitcode ("mov", "a,@%s", rname);
8686 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8690 sprintf (buffer, "@%s", rname);
8691 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
8695 emitcode ("inc", "%s", rname);
8699 /* now some housekeeping stuff */
8700 if (aop) /* we had to allocate for this iCode */
8702 if (pi) { /* post increment present */
8703 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8705 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8709 /* we did not allocate which means left
8710 already in a pointer register, then
8711 if size > 0 && this could be used again
8712 we have to point it back to where it
8714 if ((AOP_SIZE (result) > 1 &&
8715 !OP_SYMBOL (left)->remat &&
8716 (OP_SYMBOL (left)->liveTo > ic->seq ||
8720 int size = AOP_SIZE (result) - 1;
8722 emitcode ("dec", "%s", rname);
8726 if (ifx && !ifx->generated)
8728 genIfxJump (ifx, "a", left, NULL, result);
8732 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8733 freeAsmop (left, NULL, ic, TRUE);
8734 if (pi) pi->generated = 1;
8737 /*-----------------------------------------------------------------*/
8738 /* genPagedPointerGet - emitcode for paged pointer fetch */
8739 /*-----------------------------------------------------------------*/
8741 genPagedPointerGet (operand * left,
8750 sym_link *rtype, *retype;
8752 D(emitcode ("; genPagedPointerGet",""));
8754 rtype = operandType (result);
8755 retype = getSpec (rtype);
8757 aopOp (left, ic, FALSE);
8759 /* if the value is already in a pointer register
8760 then don't need anything more */
8761 if (!AOP_INPREG (AOP (left)))
8763 /* otherwise get a free pointer register */
8765 preg = getFreePtr (ic, &aop, FALSE);
8766 emitcode ("mov", "%s,%s",
8768 aopGet (left, 0, FALSE, TRUE));
8772 rname = aopGet (left, 0, FALSE, FALSE);
8774 aopOp (result, ic, FALSE);
8776 /* if bitfield then unpack the bits */
8777 if (IS_BITFIELD (retype))
8778 genUnpackBits (result, rname, PPOINTER, ifx);
8781 /* we have can just get the values */
8782 int size = AOP_SIZE (result);
8788 emitcode ("movx", "a,@%s", rname);
8790 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8795 emitcode ("inc", "%s", rname);
8799 /* now some housekeeping stuff */
8800 if (aop) /* we had to allocate for this iCode */
8802 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8803 freeAsmop (NULL, aop, ic, TRUE);
8807 /* we did not allocate which means left
8808 already in a pointer register, then
8809 if size > 0 && this could be used again
8810 we have to point it back to where it
8812 if ((AOP_SIZE (result) > 1 &&
8813 !OP_SYMBOL (left)->remat &&
8814 (OP_SYMBOL (left)->liveTo > ic->seq ||
8818 int size = AOP_SIZE (result) - 1;
8820 emitcode ("dec", "%s", rname);
8824 if (ifx && !ifx->generated)
8826 genIfxJump (ifx, "a", left, NULL, result);
8830 freeAsmop (left, NULL, ic, TRUE);
8831 freeAsmop (result, NULL, ic, TRUE);
8832 if (pi) pi->generated = 1;
8836 /*--------------------------------------------------------------------*/
8837 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8838 /*--------------------------------------------------------------------*/
8840 loadDptrFromOperand (operand *op, bool loadBToo)
8842 if (AOP_TYPE (op) != AOP_STR)
8844 /* if this is rematerializable */
8845 if (AOP_TYPE (op) == AOP_IMMD)
8847 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
8850 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8851 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
8854 wassertl(FALSE, "need pointerCode");
8855 emitcode ("", "; mov b,???");
8856 /* genPointerGet and genPointerSet originally did different
8857 ** things for this case. Both seem wrong.
8858 ** from genPointerGet:
8859 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8860 ** from genPointerSet:
8861 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
8866 else if (AOP_TYPE (op) == AOP_DPTR)
8870 MOVA (aopGet (op, 0, FALSE, FALSE));
8871 emitcode ("push", "acc");
8872 MOVA (aopGet (op, 1, FALSE, FALSE));
8873 emitcode ("push", "acc");
8874 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8875 emitcode ("pop", "dph");
8876 emitcode ("pop", "dpl");
8880 MOVA (aopGet (op, 0, FALSE, FALSE));
8881 emitcode ("push", "acc");
8882 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
8883 emitcode ("pop", "dpl");
8887 { /* we need to get it byte by byte */
8888 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
8889 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
8891 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8896 /*-----------------------------------------------------------------*/
8897 /* genFarPointerGet - gget value from far space */
8898 /*-----------------------------------------------------------------*/
8900 genFarPointerGet (operand * left,
8901 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8904 sym_link *retype = getSpec (operandType (result));
8906 D(emitcode ("; genFarPointerGet",""));
8908 aopOp (left, ic, FALSE);
8909 loadDptrFromOperand (left, FALSE);
8911 /* so dptr now contains the address */
8912 aopOp (result, ic, FALSE);
8914 /* if bit then unpack */
8915 if (IS_BITFIELD (retype))
8916 genUnpackBits (result, "dptr", FPOINTER, ifx);
8919 size = AOP_SIZE (result);
8924 emitcode ("movx", "a,@dptr");
8926 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8928 emitcode ("inc", "dptr");
8932 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8934 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
8935 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
8939 if (ifx && !ifx->generated)
8941 genIfxJump (ifx, "a", left, NULL, result);
8944 freeAsmop (left, NULL, ic, TRUE);
8945 freeAsmop (result, NULL, ic, TRUE);
8948 /*-----------------------------------------------------------------*/
8949 /* genCodePointerGet - gget value from code space */
8950 /*-----------------------------------------------------------------*/
8952 genCodePointerGet (operand * left,
8953 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8956 sym_link *retype = getSpec (operandType (result));
8958 D(emitcode ("; genCodePointerGet",""));
8960 aopOp (left, ic, FALSE);
8961 loadDptrFromOperand (left, FALSE);
8963 /* so dptr now contains the address */
8964 aopOp (result, ic, FALSE);
8966 /* if bit then unpack */
8967 if (IS_BITFIELD (retype))
8968 genUnpackBits (result, "dptr", CPOINTER, ifx);
8971 size = AOP_SIZE (result);
8978 emitcode ("clr", "a");
8979 emitcode ("movc", "a,@a+dptr");
8981 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8982 emitcode ("inc", "dptr");
8986 emitcode ("mov", "a,#0x%02x", offset);
8987 emitcode ("movc", "a,@a+dptr");
8989 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8994 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8996 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
8997 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9001 if (ifx && !ifx->generated)
9003 genIfxJump (ifx, "a", left, NULL, result);
9006 freeAsmop (left, NULL, ic, TRUE);
9007 freeAsmop (result, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genGenPointerGet - gget value from generic pointer space */
9012 /*-----------------------------------------------------------------*/
9014 genGenPointerGet (operand * left,
9015 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9018 sym_link *retype = getSpec (operandType (result));
9020 D(emitcode ("; genGenPointerGet",""));
9022 aopOp (left, ic, FALSE);
9023 loadDptrFromOperand (left, TRUE);
9025 /* so dptr know contains the address */
9026 aopOp (result, ic, FALSE);
9028 /* if bit then unpack */
9029 if (IS_BITFIELD (retype))
9030 genUnpackBits (result, "dptr", GPOINTER, ifx);
9033 size = AOP_SIZE (result);
9038 emitcode ("lcall", "__gptrget");
9040 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9042 emitcode ("inc", "dptr");
9046 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9048 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9049 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9053 if (ifx && !ifx->generated)
9055 genIfxJump (ifx, "a", left, NULL, result);
9059 freeAsmop (left, NULL, ic, TRUE);
9060 freeAsmop (result, NULL, ic, TRUE);
9063 /*-----------------------------------------------------------------*/
9064 /* genPointerGet - generate code for pointer get */
9065 /*-----------------------------------------------------------------*/
9067 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9069 operand *left, *result;
9070 sym_link *type, *etype;
9073 D(emitcode ("; genPointerGet",""));
9075 left = IC_LEFT (ic);
9076 result = IC_RESULT (ic);
9078 if (getSize (operandType (result))>1)
9081 /* depending on the type of pointer we need to
9082 move it to the correct pointer register */
9083 type = operandType (left);
9084 etype = getSpec (type);
9085 /* if left is of type of pointer then it is simple */
9086 if (IS_PTR (type) && !IS_FUNC (type->next))
9087 p_type = DCL_TYPE (type);
9090 /* we have to go by the storage class */
9091 p_type = PTR_TYPE (SPEC_OCLS (etype));
9094 /* special case when cast remat */
9095 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9096 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9097 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9098 type = operandType (left);
9099 p_type = DCL_TYPE (type);
9101 /* now that we have the pointer type we assign
9102 the pointer values */
9108 genNearPointerGet (left, result, ic, pi, ifx);
9112 genPagedPointerGet (left, result, ic, pi, ifx);
9116 genFarPointerGet (left, result, ic, pi, ifx);
9120 genCodePointerGet (left, result, ic, pi, ifx);
9124 genGenPointerGet (left, result, ic, pi, ifx);
9132 /*-----------------------------------------------------------------*/
9133 /* genPackBits - generates code for packed bit storage */
9134 /*-----------------------------------------------------------------*/
9136 genPackBits (sym_link * etype,
9138 char *rname, int p_type)
9140 int offset = 0; /* source byte offset */
9141 int rlen = 0; /* remaining bitfield length */
9142 int blen; /* bitfield length */
9143 int bstr; /* bitfield starting bit within byte */
9144 int litval; /* source literal value (if AOP_LIT) */
9145 unsigned char mask; /* bitmask within current byte */
9147 D(emitcode ("; genPackBits",""));
9149 blen = SPEC_BLEN (etype);
9150 bstr = SPEC_BSTR (etype);
9152 /* If the bitfield length is less than a byte */
9155 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9156 (unsigned char) (0xFF >> (8 - bstr)));
9158 if (AOP_TYPE (right) == AOP_LIT)
9160 /* Case with a bitfield length <8 and literal source
9162 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9164 litval &= (~mask) & 0xff;
9165 emitPtrByteGet (rname, p_type, FALSE);
9166 if ((mask|litval)!=0xff)
9167 emitcode ("anl","a,#0x%02x", mask);
9169 emitcode ("orl","a,#0x%02x", litval);
9173 if ((blen==1) && (p_type!=GPOINTER))
9175 /* Case with a bitfield length == 1 and no generic pointer
9177 if (AOP_TYPE (right) == AOP_CRY)
9178 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9181 MOVA (aopGet (right, 0, FALSE, FALSE));
9182 emitcode ("rrc","a");
9184 emitPtrByteGet (rname, p_type, FALSE);
9185 emitcode ("mov","acc.%d,c",bstr);
9190 /* Case with a bitfield length < 8 and arbitrary source
9192 MOVA (aopGet (right, 0, FALSE, FALSE));
9193 /* shift and mask source value */
9195 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9198 /* transfer A to B and get next byte */
9199 emitPtrByteGet (rname, p_type, TRUE);
9201 emitcode ("anl", "a,#0x%02x", mask);
9202 emitcode ("orl", "a,b");
9203 if (p_type == GPOINTER)
9204 emitcode ("pop", "b");
9210 emitPtrByteSet (rname, p_type, "a");
9214 /* Bit length is greater than 7 bits. In this case, copy */
9215 /* all except the partial byte at the end */
9216 for (rlen=blen;rlen>=8;rlen-=8)
9218 emitPtrByteSet (rname, p_type,
9219 aopGet (right, offset++, FALSE, TRUE) );
9221 emitcode ("inc", "%s", rname);
9224 /* If there was a partial byte at the end */
9227 mask = (((unsigned char) -1 << rlen) & 0xff);
9229 if (AOP_TYPE (right) == AOP_LIT)
9231 /* Case with partial byte and literal source
9233 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9234 litval >>= (blen-rlen);
9235 litval &= (~mask) & 0xff;
9236 emitPtrByteGet (rname, p_type, FALSE);
9237 if ((mask|litval)!=0xff)
9238 emitcode ("anl","a,#0x%02x", mask);
9240 emitcode ("orl","a,#0x%02x", litval);
9245 /* Case with partial byte and arbitrary source
9247 MOVA (aopGet (right, offset++, FALSE, FALSE));
9248 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9251 /* transfer A to B and get next byte */
9252 emitPtrByteGet (rname, p_type, TRUE);
9254 emitcode ("anl", "a,#0x%02x", mask);
9255 emitcode ("orl", "a,b");
9256 if (p_type == GPOINTER)
9257 emitcode ("pop", "b");
9261 emitPtrByteSet (rname, p_type, "a");
9267 /*-----------------------------------------------------------------*/
9268 /* genDataPointerSet - remat pointer to data space */
9269 /*-----------------------------------------------------------------*/
9271 genDataPointerSet (operand * right,
9275 int size, offset = 0;
9276 char *l, buffer[256];
9278 D(emitcode ("; genDataPointerSet",""));
9280 aopOp (right, ic, FALSE);
9282 l = aopGet (result, 0, FALSE, TRUE);
9283 size = AOP_SIZE (right);
9287 sprintf (buffer, "(%s + %d)", l + 1, offset);
9289 sprintf (buffer, "%s", l + 1);
9290 emitcode ("mov", "%s,%s", buffer,
9291 aopGet (right, offset++, FALSE, FALSE));
9294 freeAsmop (right, NULL, ic, TRUE);
9295 freeAsmop (result, NULL, ic, TRUE);
9298 /*-----------------------------------------------------------------*/
9299 /* genNearPointerSet - emitcode for near pointer put */
9300 /*-----------------------------------------------------------------*/
9302 genNearPointerSet (operand * right,
9310 sym_link *retype, *letype;
9311 sym_link *ptype = operandType (result);
9313 D(emitcode ("; genNearPointerSet",""));
9315 retype = getSpec (operandType (right));
9316 letype = getSpec (ptype);
9317 aopOp (result, ic, FALSE);
9319 /* if the result is rematerializable &
9320 in data space & not a bit variable */
9321 if (AOP_TYPE (result) == AOP_IMMD &&
9322 DCL_TYPE (ptype) == POINTER &&
9323 !IS_BITVAR (retype) &&
9324 !IS_BITVAR (letype))
9326 genDataPointerSet (right, result, ic);
9330 /* if the value is already in a pointer register
9331 then don't need anything more */
9332 if (!AOP_INPREG (AOP (result)))
9335 //AOP_TYPE (result) == AOP_STK
9339 // Aha, it is a pointer, just in disguise.
9340 rname = aopGet (result, 0, FALSE, FALSE);
9343 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9344 __FILE__, __LINE__);
9349 emitcode ("mov", "a%s,%s", rname + 1, rname);
9350 rname++; // skip the '@'.
9355 /* otherwise get a free pointer register */
9357 preg = getFreePtr (ic, &aop, FALSE);
9358 emitcode ("mov", "%s,%s",
9360 aopGet (result, 0, FALSE, TRUE));
9366 rname = aopGet (result, 0, FALSE, FALSE);
9369 aopOp (right, ic, FALSE);
9371 /* if bitfield then unpack the bits */
9372 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9373 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9376 /* we have can just get the values */
9377 int size = AOP_SIZE (right);
9382 l = aopGet (right, offset, FALSE, TRUE);
9386 emitcode ("mov", "@%s,a", rname);
9389 emitcode ("mov", "@%s,%s", rname, l);
9391 emitcode ("inc", "%s", rname);
9396 /* now some housekeeping stuff */
9397 if (aop) /* we had to allocate for this iCode */
9400 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9401 freeAsmop (NULL, aop, ic, TRUE);
9405 /* we did not allocate which means left
9406 already in a pointer register, then
9407 if size > 0 && this could be used again
9408 we have to point it back to where it
9410 if ((AOP_SIZE (right) > 1 &&
9411 !OP_SYMBOL (result)->remat &&
9412 (OP_SYMBOL (result)->liveTo > ic->seq ||
9416 int size = AOP_SIZE (right) - 1;
9418 emitcode ("dec", "%s", rname);
9423 if (pi) pi->generated = 1;
9424 freeAsmop (result, NULL, ic, TRUE);
9425 freeAsmop (right, NULL, ic, TRUE);
9428 /*-----------------------------------------------------------------*/
9429 /* genPagedPointerSet - emitcode for Paged pointer put */
9430 /*-----------------------------------------------------------------*/
9432 genPagedPointerSet (operand * right,
9440 sym_link *retype, *letype;
9442 D(emitcode ("; genPagedPointerSet",""));
9444 retype = getSpec (operandType (right));
9445 letype = getSpec (operandType (result));
9447 aopOp (result, ic, FALSE);
9449 /* if the value is already in a pointer register
9450 then don't need anything more */
9451 if (!AOP_INPREG (AOP (result)))
9453 /* otherwise get a free pointer register */
9455 preg = getFreePtr (ic, &aop, FALSE);
9456 emitcode ("mov", "%s,%s",
9458 aopGet (result, 0, FALSE, TRUE));
9462 rname = aopGet (result, 0, FALSE, FALSE);
9464 aopOp (right, ic, FALSE);
9466 /* if bitfield then unpack the bits */
9467 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9468 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9471 /* we have can just get the values */
9472 int size = AOP_SIZE (right);
9477 l = aopGet (right, offset, FALSE, TRUE);
9480 emitcode ("movx", "@%s,a", rname);
9483 emitcode ("inc", "%s", rname);
9489 /* now some housekeeping stuff */
9490 if (aop) /* we had to allocate for this iCode */
9493 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9494 freeAsmop (NULL, aop, ic, TRUE);
9498 /* we did not allocate which means left
9499 already in a pointer register, then
9500 if size > 0 && this could be used again
9501 we have to point it back to where it
9503 if (AOP_SIZE (right) > 1 &&
9504 !OP_SYMBOL (result)->remat &&
9505 (OP_SYMBOL (result)->liveTo > ic->seq ||
9508 int size = AOP_SIZE (right) - 1;
9510 emitcode ("dec", "%s", rname);
9515 if (pi) pi->generated = 1;
9516 freeAsmop (result, NULL, ic, TRUE);
9517 freeAsmop (right, NULL, ic, TRUE);
9522 /*-----------------------------------------------------------------*/
9523 /* genFarPointerSet - set value from far space */
9524 /*-----------------------------------------------------------------*/
9526 genFarPointerSet (operand * right,
9527 operand * result, iCode * ic, iCode * pi)
9530 sym_link *retype = getSpec (operandType (right));
9531 sym_link *letype = getSpec (operandType (result));
9533 D(emitcode ("; genFarPointerSet",""));
9535 aopOp (result, ic, FALSE);
9536 loadDptrFromOperand (result, FALSE);
9538 /* so dptr know contains the address */
9539 aopOp (right, ic, FALSE);
9541 /* if bit then unpack */
9542 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9543 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9546 size = AOP_SIZE (right);
9551 char *l = aopGet (right, offset++, FALSE, FALSE);
9553 emitcode ("movx", "@dptr,a");
9555 emitcode ("inc", "dptr");
9558 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9559 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9560 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9563 freeAsmop (result, NULL, ic, TRUE);
9564 freeAsmop (right, NULL, ic, TRUE);
9567 /*-----------------------------------------------------------------*/
9568 /* genGenPointerSet - set value from generic pointer space */
9569 /*-----------------------------------------------------------------*/
9571 genGenPointerSet (operand * right,
9572 operand * result, iCode * ic, iCode * pi)
9575 sym_link *retype = getSpec (operandType (right));
9576 sym_link *letype = getSpec (operandType (result));
9578 D(emitcode ("; genGenPointerSet",""));
9580 aopOp (result, ic, FALSE);
9581 loadDptrFromOperand (result, TRUE);
9583 /* so dptr know contains the address */
9584 aopOp (right, ic, FALSE);
9586 /* if bit then unpack */
9587 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9588 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9591 size = AOP_SIZE (right);
9596 char *l = aopGet (right, offset++, FALSE, FALSE);
9598 emitcode ("lcall", "__gptrput");
9600 emitcode ("inc", "dptr");
9604 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9605 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9606 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9609 freeAsmop (result, NULL, ic, TRUE);
9610 freeAsmop (right, NULL, ic, TRUE);
9613 /*-----------------------------------------------------------------*/
9614 /* genPointerSet - stores the value into a pointer location */
9615 /*-----------------------------------------------------------------*/
9617 genPointerSet (iCode * ic, iCode *pi)
9619 operand *right, *result;
9620 sym_link *type, *etype;
9623 D(emitcode ("; genPointerSet",""));
9625 right = IC_RIGHT (ic);
9626 result = IC_RESULT (ic);
9628 /* depending on the type of pointer we need to
9629 move it to the correct pointer register */
9630 type = operandType (result);
9631 etype = getSpec (type);
9632 /* if left is of type of pointer then it is simple */
9633 if (IS_PTR (type) && !IS_FUNC (type->next))
9635 p_type = DCL_TYPE (type);
9639 /* we have to go by the storage class */
9640 p_type = PTR_TYPE (SPEC_OCLS (etype));
9643 /* special case when cast remat */
9644 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9645 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9646 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9647 type = operandType (result);
9648 p_type = DCL_TYPE (type);
9650 /* now that we have the pointer type we assign
9651 the pointer values */
9657 genNearPointerSet (right, result, ic, pi);
9661 genPagedPointerSet (right, result, ic, pi);
9665 genFarPointerSet (right, result, ic, pi);
9669 genGenPointerSet (right, result, ic, pi);
9673 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9674 "genPointerSet: illegal pointer type");
9679 /*-----------------------------------------------------------------*/
9680 /* genIfx - generate code for Ifx statement */
9681 /*-----------------------------------------------------------------*/
9683 genIfx (iCode * ic, iCode * popIc)
9685 operand *cond = IC_COND (ic);
9688 D(emitcode ("; genIfx",""));
9690 aopOp (cond, ic, FALSE);
9692 /* get the value into acc */
9693 if (AOP_TYPE (cond) != AOP_CRY)
9697 /* the result is now in the accumulator */
9698 freeAsmop (cond, NULL, ic, TRUE);
9700 /* if there was something to be popped then do it */
9704 /* if the condition is a bit variable */
9705 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9706 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9707 else if (isbit && !IS_ITEMP (cond))
9708 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9710 genIfxJump (ic, "a", NULL, NULL, NULL);
9715 /*-----------------------------------------------------------------*/
9716 /* genAddrOf - generates code for address of */
9717 /*-----------------------------------------------------------------*/
9719 genAddrOf (iCode * ic)
9721 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9724 D(emitcode ("; genAddrOf",""));
9726 aopOp (IC_RESULT (ic), ic, FALSE);
9728 /* if the operand is on the stack then we
9729 need to get the stack offset of this
9733 /* if it has an offset then we need to compute
9737 emitcode ("mov", "a,%s", SYM_BP (sym));
9738 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9739 ((char) (sym->stack - _G.nRegsSaved)) :
9740 ((char) sym->stack)) & 0xff);
9741 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9745 /* we can just move _bp */
9746 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9748 /* fill the result with zero */
9749 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9754 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9760 /* object not on stack then we need the name */
9761 size = AOP_SIZE (IC_RESULT (ic));
9766 char s[SDCC_NAME_MAX];
9768 sprintf (s, "#(%s >> %d)",
9772 sprintf (s, "#%s", sym->rname);
9773 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9777 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9781 /*-----------------------------------------------------------------*/
9782 /* genFarFarAssign - assignment when both are in far space */
9783 /*-----------------------------------------------------------------*/
9785 genFarFarAssign (operand * result, operand * right, iCode * ic)
9787 int size = AOP_SIZE (right);
9791 D(emitcode ("; genFarFarAssign",""));
9793 /* first push the right side on to the stack */
9796 l = aopGet (right, offset++, FALSE, FALSE);
9798 emitcode ("push", "acc");
9801 freeAsmop (right, NULL, ic, FALSE);
9802 /* now assign DPTR to result */
9803 aopOp (result, ic, FALSE);
9804 size = AOP_SIZE (result);
9807 emitcode ("pop", "acc");
9808 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
9810 freeAsmop (result, NULL, ic, FALSE);
9814 /*-----------------------------------------------------------------*/
9815 /* genAssign - generate code for assignment */
9816 /*-----------------------------------------------------------------*/
9818 genAssign (iCode * ic)
9820 operand *result, *right;
9822 unsigned long lit = 0L;
9824 D(emitcode("; genAssign",""));
9826 result = IC_RESULT (ic);
9827 right = IC_RIGHT (ic);
9829 /* if they are the same */
9830 if (operandsEqu (result, right) &&
9831 !isOperandVolatile (result, FALSE) &&
9832 !isOperandVolatile (right, FALSE))
9835 aopOp (right, ic, FALSE);
9837 /* special case both in far space */
9838 if (AOP_TYPE (right) == AOP_DPTR &&
9839 IS_TRUE_SYMOP (result) &&
9840 isOperandInFarSpace (result))
9843 genFarFarAssign (result, right, ic);
9847 aopOp (result, ic, TRUE);
9849 /* if they are the same registers */
9850 if (sameRegs (AOP (right), AOP (result)) &&
9851 !isOperandVolatile (result, FALSE) &&
9852 !isOperandVolatile (right, FALSE))
9855 /* if the result is a bit */
9856 if (AOP_TYPE (result) == AOP_CRY)
9859 /* if the right size is a literal then
9860 we know what the value is */
9861 if (AOP_TYPE (right) == AOP_LIT)
9863 if (((int) operandLitValue (right)))
9864 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
9866 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
9870 /* the right is also a bit variable */
9871 if (AOP_TYPE (right) == AOP_CRY)
9873 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9874 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
9880 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9884 /* bit variables done */
9886 size = AOP_SIZE (result);
9888 if (AOP_TYPE (right) == AOP_LIT)
9889 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9891 (AOP_TYPE (result) != AOP_REG) &&
9892 (AOP_TYPE (right) == AOP_LIT) &&
9893 !IS_FLOAT (operandType (right)) &&
9896 while ((size) && (lit))
9899 aopGet (right, offset, FALSE, FALSE),
9901 isOperandVolatile (result, FALSE));
9906 emitcode ("clr", "a");
9909 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9918 aopGet (right, offset, FALSE, FALSE),
9920 isOperandVolatile (result, FALSE));
9926 freeAsmop (right, NULL, ic, TRUE);
9927 freeAsmop (result, NULL, ic, TRUE);
9930 /*-----------------------------------------------------------------*/
9931 /* genJumpTab - generates code for jump table */
9932 /*-----------------------------------------------------------------*/
9934 genJumpTab (iCode * ic)
9936 symbol *jtab,*jtablo,*jtabhi;
9940 D(emitcode ("; genJumpTab",""));
9942 count = elementsInSet( IC_JTLABELS (ic) );
9946 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9947 if the switch argument is in a register.
9948 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9949 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9950 How will multiply by three be updated ???*/
9951 aopOp (IC_JTCOND (ic), ic, FALSE);
9952 /* get the condition into accumulator */
9953 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
9955 /* multiply by three */
9956 emitcode ("add", "a,acc");
9957 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
9958 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9960 jtab = newiTempLabel (NULL);
9961 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9962 emitcode ("jmp", "@a+dptr");
9963 emitcode ("", "%05d$:", jtab->key + 100);
9964 /* now generate the jump labels */
9965 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9966 jtab = setNextItem (IC_JTLABELS (ic)))
9967 emitcode ("ljmp", "%05d$", jtab->key + 100);
9971 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9972 if the switch argument is in a register.
9973 For n>6 this algorithm may be more compact */
9974 jtablo = newiTempLabel (NULL);
9975 jtabhi = newiTempLabel (NULL);
9977 /* get the condition into accumulator.
9978 Using b as temporary storage, if register push/pop is needed */
9979 aopOp (IC_JTCOND (ic), ic, FALSE);
9980 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
9981 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9982 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9984 // (MB) what if B is in use???
9985 wassertl(!BINUSE, "B was in use");
9986 emitcode ("mov", "b,%s", l);
9989 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9993 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9994 emitcode ("movc", "a,@a+pc");
9995 emitcode ("push", "acc");
9998 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9999 emitcode ("movc", "a,@a+pc");
10000 emitcode ("push", "acc");
10004 /* this scales up to n<=255, but needs two more bytes
10005 and changes dptr */
10006 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10007 emitcode ("movc", "a,@a+dptr");
10008 emitcode ("push", "acc");
10011 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10012 emitcode ("movc", "a,@a+dptr");
10013 emitcode ("push", "acc");
10016 emitcode ("ret", "");
10018 /* now generate jump table, LSB */
10019 emitcode ("", "%05d$:", jtablo->key + 100);
10020 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10021 jtab = setNextItem (IC_JTLABELS (ic)))
10022 emitcode (".db", "%05d$", jtab->key + 100);
10024 /* now generate jump table, MSB */
10025 emitcode ("", "%05d$:", jtabhi->key + 100);
10026 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10027 jtab = setNextItem (IC_JTLABELS (ic)))
10028 emitcode (".db", "%05d$>>8", jtab->key + 100);
10032 /*-----------------------------------------------------------------*/
10033 /* genCast - gen code for casting */
10034 /*-----------------------------------------------------------------*/
10036 genCast (iCode * ic)
10038 operand *result = IC_RESULT (ic);
10039 sym_link *ctype = operandType (IC_LEFT (ic));
10040 sym_link *rtype = operandType (IC_RIGHT (ic));
10041 operand *right = IC_RIGHT (ic);
10044 D(emitcode("; genCast",""));
10046 /* if they are equivalent then do nothing */
10047 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10050 aopOp (right, ic, FALSE);
10051 aopOp (result, ic, FALSE);
10053 /* if the result is a bit (and not a bitfield) */
10054 // if (AOP_TYPE (result) == AOP_CRY)
10055 if (IS_BITVAR (OP_SYMBOL (result)->type)
10056 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10058 /* if the right size is a literal then
10059 we know what the value is */
10060 if (AOP_TYPE (right) == AOP_LIT)
10062 if (((int) operandLitValue (right)))
10063 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10065 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10070 /* the right is also a bit variable */
10071 if (AOP_TYPE (right) == AOP_CRY)
10073 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10074 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10078 /* we need to or */
10080 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10085 /* if they are the same size : or less */
10086 if (AOP_SIZE (result) <= AOP_SIZE (right))
10089 /* if they are in the same place */
10090 if (sameRegs (AOP (right), AOP (result)))
10093 /* if they in different places then copy */
10094 size = AOP_SIZE (result);
10099 aopGet (right, offset, FALSE, FALSE),
10101 isOperandVolatile (result, FALSE));
10108 /* if the result is of type pointer */
10109 if (IS_PTR (ctype))
10113 sym_link *type = operandType (right);
10114 sym_link *etype = getSpec (type);
10116 /* pointer to generic pointer */
10117 if (IS_GENPTR (ctype))
10120 p_type = DCL_TYPE (type);
10123 if (SPEC_SCLS(etype)==S_REGISTER) {
10124 // let's assume it is a generic pointer
10127 /* we have to go by the storage class */
10128 p_type = PTR_TYPE (SPEC_OCLS (etype));
10132 /* the first two bytes are known */
10133 size = GPTRSIZE - 1;
10138 aopGet (right, offset, FALSE, FALSE),
10140 isOperandVolatile (result, FALSE));
10143 /* the last byte depending on type */
10145 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10150 // pointerTypeToGPByte will have bitched.
10154 sprintf(gpValStr, "#0x%x", gpVal);
10155 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10160 /* just copy the pointers */
10161 size = AOP_SIZE (result);
10166 aopGet (right, offset, FALSE, FALSE),
10168 isOperandVolatile (result, FALSE));
10174 /* so we now know that the size of destination is greater
10175 than the size of the source */
10176 /* we move to result for the size of source */
10177 size = AOP_SIZE (right);
10182 aopGet (right, offset, FALSE, FALSE),
10184 isOperandVolatile (result, FALSE));
10188 /* now depending on the sign of the source && destination */
10189 size = AOP_SIZE (result) - AOP_SIZE (right);
10190 /* if unsigned or not an integral type */
10191 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10194 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10198 /* we need to extend the sign :{ */
10199 char *l = aopGet (right, AOP_SIZE (right) - 1,
10202 emitcode ("rlc", "a");
10203 emitcode ("subb", "a,acc");
10205 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10208 /* we are done hurray !!!! */
10211 freeAsmop (right, NULL, ic, TRUE);
10212 freeAsmop (result, NULL, ic, TRUE);
10216 /*-----------------------------------------------------------------*/
10217 /* genDjnz - generate decrement & jump if not zero instrucion */
10218 /*-----------------------------------------------------------------*/
10220 genDjnz (iCode * ic, iCode * ifx)
10222 symbol *lbl, *lbl1;
10226 D(emitcode ("; genDjnz",""));
10228 /* if the if condition has a false label
10229 then we cannot save */
10230 if (IC_FALSE (ifx))
10233 /* if the minus is not of the form
10235 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10236 !IS_OP_LITERAL (IC_RIGHT (ic)))
10239 if (operandLitValue (IC_RIGHT (ic)) != 1)
10242 /* if the size of this greater than one then no
10244 if (getSize (operandType (IC_RESULT (ic))) > 1)
10247 /* otherwise we can save BIG */
10248 lbl = newiTempLabel (NULL);
10249 lbl1 = newiTempLabel (NULL);
10251 aopOp (IC_RESULT (ic), ic, FALSE);
10253 if (AOP_NEEDSACC(IC_RESULT(ic)))
10255 /* If the result is accessed indirectly via
10256 * the accumulator, we must explicitly write
10257 * it back after the decrement.
10259 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10261 if (strcmp(rByte, "a"))
10263 /* Something is hopelessly wrong */
10264 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10265 __FILE__, __LINE__);
10266 /* We can just give up; the generated code will be inefficient,
10267 * but what the hey.
10269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10272 emitcode ("dec", "%s", rByte);
10273 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10274 emitcode ("jnz", "%05d$", lbl->key + 100);
10276 else if (IS_AOP_PREG (IC_RESULT (ic)))
10278 emitcode ("dec", "%s",
10279 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10280 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10281 emitcode ("jnz", "%05d$", lbl->key + 100);
10285 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10288 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10289 emitcode ("", "%05d$:", lbl->key + 100);
10290 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10291 emitcode ("", "%05d$:", lbl1->key + 100);
10293 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10294 ifx->generated = 1;
10298 /*-----------------------------------------------------------------*/
10299 /* genReceive - generate code for a receive iCode */
10300 /*-----------------------------------------------------------------*/
10302 genReceive (iCode * ic)
10304 int size = getSize (operandType (IC_RESULT (ic)));
10306 D(emitcode ("; genReceive",""));
10308 if (ic->argreg == 1) { /* first parameter */
10309 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10310 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10311 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10314 int receivingA = 0;
10317 for (offset = 0; offset<size; offset++)
10318 if (!strcmp (fReturn[offset], "a"))
10323 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10325 for (offset = size-1; offset>0; offset--)
10326 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10327 emitcode("mov","a,%s", fReturn[0]);
10329 aopOp (IC_RESULT (ic), ic, FALSE);
10331 aopPut (IC_RESULT (ic), "a", offset,
10332 isOperandVolatile (IC_RESULT (ic), FALSE));
10333 for (offset = 1; offset<size; offset++)
10334 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10335 isOperandVolatile (IC_RESULT (ic), FALSE));
10341 if (getTempRegs(tempRegs, size, ic))
10343 for (offset = 0; offset<size; offset++)
10344 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10345 aopOp (IC_RESULT (ic), ic, FALSE);
10346 for (offset = 0; offset<size; offset++)
10347 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10348 isOperandVolatile (IC_RESULT (ic), FALSE));
10353 offset = fReturnSizeMCS51 - size;
10355 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10356 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10359 aopOp (IC_RESULT (ic), ic, FALSE);
10360 size = AOP_SIZE (IC_RESULT (ic));
10363 emitcode ("pop", "acc");
10364 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10369 aopOp (IC_RESULT (ic), ic, FALSE);
10371 assignResultValue (IC_RESULT (ic));
10373 } else { /* second receive onwards */
10375 aopOp (IC_RESULT (ic), ic, FALSE);
10376 rb1off = ic->argreg;
10378 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10383 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10386 /*-----------------------------------------------------------------*/
10387 /* genDummyRead - generate code for dummy read of volatiles */
10388 /*-----------------------------------------------------------------*/
10390 genDummyRead (iCode * ic)
10395 D(emitcode("; genDummyRead",""));
10397 op = IC_RIGHT (ic);
10398 if (op && IS_SYMOP (op))
10400 aopOp (op, ic, FALSE);
10402 /* if the result is a bit */
10403 if (AOP_TYPE (op) == AOP_CRY)
10404 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10407 /* bit variables done */
10409 size = AOP_SIZE (op);
10413 MOVA (aopGet (op, offset, FALSE, FALSE));
10418 freeAsmop (op, NULL, ic, TRUE);
10422 if (op && IS_SYMOP (op))
10424 aopOp (op, ic, FALSE);
10426 /* if the result is a bit */
10427 if (AOP_TYPE (op) == AOP_CRY)
10428 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10431 /* bit variables done */
10433 size = AOP_SIZE (op);
10437 MOVA (aopGet (op, offset, FALSE, FALSE));
10442 freeAsmop (op, NULL, ic, TRUE);
10446 /*-----------------------------------------------------------------*/
10447 /* genCritical - generate code for start of a critical sequence */
10448 /*-----------------------------------------------------------------*/
10450 genCritical (iCode *ic)
10452 symbol *tlbl = newiTempLabel (NULL);
10454 D(emitcode("; genCritical",""));
10456 if (IC_RESULT (ic))
10458 aopOp (IC_RESULT (ic), ic, TRUE);
10459 aopPut (IC_RESULT (ic), one, 0, 0);
10460 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10461 aopPut (IC_RESULT (ic), zero, 0, 0);
10462 emitcode ("", "%05d$:", (tlbl->key + 100));
10463 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10467 emitcode ("setb", "c");
10468 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10469 emitcode ("clr", "c");
10470 emitcode ("", "%05d$:", (tlbl->key + 100));
10471 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10475 /*-----------------------------------------------------------------*/
10476 /* genEndCritical - generate code for end of a critical sequence */
10477 /*-----------------------------------------------------------------*/
10479 genEndCritical (iCode *ic)
10481 D(emitcode("; genEndCritical",""));
10485 aopOp (IC_RIGHT (ic), ic, FALSE);
10486 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10488 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10489 emitcode ("mov", "ea,c");
10493 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10494 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10495 emitcode ("rrc", "a");
10496 emitcode ("mov", "ea,c");
10498 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10502 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10503 emitcode ("mov", "ea,c");
10507 /*-----------------------------------------------------------------*/
10508 /* gen51Code - generate code for 8051 based controllers */
10509 /*-----------------------------------------------------------------*/
10511 gen51Code (iCode * lic)
10515 /* int cseq = 0; */
10517 _G.currentFunc = NULL;
10518 lineHead = lineCurr = NULL;
10520 /* print the allocation information */
10521 if (allocInfo && currFunc)
10522 printAllocInfo (currFunc, codeOutFile);
10523 /* if debug information required */
10524 if (options.debug && currFunc)
10526 debugFile->writeFunction (currFunc, lic);
10528 /* stack pointer name */
10529 if (options.useXstack)
10535 for (ic = lic; ic; ic = ic->next)
10537 _G.current_iCode = ic;
10539 if (ic->lineno && cln != ic->lineno)
10543 debugFile->writeCLine (ic);
10545 if (!options.noCcodeInAsm) {
10546 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10547 printCLine(ic->filename, ic->lineno));
10552 if (ic->seqPoint && ic->seqPoint != cseq)
10554 emitcode ("", "; sequence point %d", ic->seqPoint);
10555 cseq = ic->seqPoint;
10558 if (options.iCodeInAsm) {
10559 char regsInUse[80];
10562 for (i=0; i<8; i++) {
10563 sprintf (®sInUse[i],
10564 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10567 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10569 /* if the result is marked as
10570 spilt and rematerializable or code for
10571 this has already been generated then
10573 if (resultRemat (ic) || ic->generated)
10576 /* depending on the operation */
10596 /* IPOP happens only when trying to restore a
10597 spilt live range, if there is an ifx statement
10598 following this pop then the if statement might
10599 be using some of the registers being popped which
10600 would destory the contents of the register so
10601 we need to check for this condition and handle it */
10603 ic->next->op == IFX &&
10604 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10605 genIfx (ic->next, ic);
10623 genEndFunction (ic);
10643 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10660 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10664 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10671 /* note these two are xlated by algebraic equivalence
10672 during parsing SDCC.y */
10673 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10674 "got '>=' or '<=' shouldn't have come here");
10678 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10690 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10694 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10698 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10722 genRightShift (ic);
10725 case GET_VALUE_AT_ADDRESS:
10727 hasInc (IC_LEFT (ic), ic,
10728 getSize (operandType (IC_RESULT (ic)))),
10729 ifxForOp (IC_RESULT (ic), ic) );
10733 if (POINTER_SET (ic))
10734 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10760 addSet (&_G.sendSet, ic);
10763 case DUMMY_READ_VOLATILE:
10772 genEndCritical (ic);
10784 _G.current_iCode = NULL;
10786 /* now we are ready to call the
10787 peep hole optimizer */
10788 if (!options.nopeep)
10789 peepHole (&lineHead);
10791 /* now do the actual printing */
10792 printLine (lineHead, codeOutFile);