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))) &&
3506 /* If the next instruction is a goto and the goto target
3507 * is < 10 instructions previous to this, we can generate
3508 * jumps straight to that target.
3510 if (ic->next && ic->next->op == GOTO
3511 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3512 && labelRange <= 10)
3514 emitcode (";", "tail increment optimized");
3515 tlbl = IC_LABEL (ic->next);
3520 tlbl = newiTempLabel (NULL);
3523 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3524 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3525 IS_AOP_PREG (IC_RESULT (ic)))
3526 emitcode ("cjne", "%s,#0x00,%05d$",
3527 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3531 emitcode ("clr", "a");
3532 emitcode ("cjne", "a,%s,%05d$",
3533 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3537 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3540 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3541 IS_AOP_PREG (IC_RESULT (ic)))
3542 emitcode ("cjne", "%s,#0x00,%05d$",
3543 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3546 emitcode ("cjne", "a,%s,%05d$",
3547 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3550 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3554 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3555 IS_AOP_PREG (IC_RESULT (ic)))
3556 emitcode ("cjne", "%s,#0x00,%05d$",
3557 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3561 emitcode ("cjne", "a,%s,%05d$",
3562 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3565 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3570 emitcode ("", "%05d$:", tlbl->key + 100);
3575 /* if the sizes are greater than 1 then we cannot */
3576 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3577 AOP_SIZE (IC_LEFT (ic)) > 1)
3580 /* we can if the aops of the left & result match or
3581 if they are in registers and the registers are the
3583 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3588 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3589 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3590 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3596 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3605 /*-----------------------------------------------------------------*/
3606 /* outBitAcc - output a bit in acc */
3607 /*-----------------------------------------------------------------*/
3609 outBitAcc (operand * result)
3611 symbol *tlbl = newiTempLabel (NULL);
3612 /* if the result is a bit */
3613 if (AOP_TYPE (result) == AOP_CRY)
3615 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
3619 emitcode ("jz", "%05d$", tlbl->key + 100);
3620 emitcode ("mov", "a,%s", one);
3621 emitcode ("", "%05d$:", tlbl->key + 100);
3626 /*-----------------------------------------------------------------*/
3627 /* genPlusBits - generates code for addition of two bits */
3628 /*-----------------------------------------------------------------*/
3630 genPlusBits (iCode * ic)
3632 D(emitcode ("; genPlusBits",""));
3634 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3636 symbol *lbl = newiTempLabel (NULL);
3637 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3638 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3639 emitcode ("cpl", "c");
3640 emitcode ("", "%05d$:", (lbl->key + 100));
3641 outBitC (IC_RESULT (ic));
3645 emitcode ("clr", "a");
3646 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3647 emitcode ("rlc", "a");
3648 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3649 emitcode ("addc", "a,#0x00");
3650 outAcc (IC_RESULT (ic));
3655 /* This is the original version of this code.
3657 * This is being kept around for reference,
3658 * because I am not entirely sure I got it right...
3661 adjustArithmeticResult (iCode * ic)
3663 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3664 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3665 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3666 aopPut (IC_RESULT (ic),
3667 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
3669 isOperandVolatile (IC_RESULT (ic), FALSE));
3671 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3672 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3673 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3674 aopPut (IC_RESULT (ic),
3675 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
3677 isOperandVolatile (IC_RESULT (ic), FALSE));
3679 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3680 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3681 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3682 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3683 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3686 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3687 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3691 /* This is the pure and virtuous version of this code.
3692 * I'm pretty certain it's right, but not enough to toss the old
3696 adjustArithmeticResult (iCode * ic)
3698 if (opIsGptr (IC_RESULT (ic)) &&
3699 opIsGptr (IC_LEFT (ic)) &&
3700 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3702 aopPut (IC_RESULT (ic),
3703 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
3705 isOperandVolatile (IC_RESULT (ic), FALSE));
3708 if (opIsGptr (IC_RESULT (ic)) &&
3709 opIsGptr (IC_RIGHT (ic)) &&
3710 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3712 aopPut (IC_RESULT (ic),
3713 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
3715 isOperandVolatile (IC_RESULT (ic), FALSE));
3718 if (opIsGptr (IC_RESULT (ic)) &&
3719 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3720 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3721 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3722 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3725 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
3726 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3731 /*-----------------------------------------------------------------*/
3732 /* genPlus - generates code for addition */
3733 /*-----------------------------------------------------------------*/
3735 genPlus (iCode * ic)
3737 int size, offset = 0;
3740 operand *leftOp, *rightOp;
3743 /* special cases :- */
3745 D(emitcode ("; genPlus",""));
3747 aopOp (IC_LEFT (ic), ic, FALSE);
3748 aopOp (IC_RIGHT (ic), ic, FALSE);
3749 aopOp (IC_RESULT (ic), ic, TRUE);
3751 /* if literal, literal on the right or
3752 if left requires ACC or right is already
3754 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3755 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3756 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3758 operand *t = IC_RIGHT (ic);
3759 IC_RIGHT (ic) = IC_LEFT (ic);
3763 /* if both left & right are in bit
3765 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3766 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3772 /* if left in bit space & right literal */
3773 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3774 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3776 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777 /* if result in bit space */
3778 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3780 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3781 emitcode ("cpl", "c");
3782 outBitC (IC_RESULT (ic));
3786 size = getDataSize (IC_RESULT (ic));
3789 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
3790 emitcode ("addc", "a,#00");
3791 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3797 /* if I can do an increment instead
3798 of add then GOOD for ME */
3799 if (genPlusIncr (ic) == TRUE)
3802 size = getDataSize (IC_RESULT (ic));
3803 leftOp = IC_LEFT(ic);
3804 rightOp = IC_RIGHT(ic);
3807 /* if this is an add for an array access
3808 at a 256 byte boundary */
3810 && AOP_TYPE (op) == AOP_IMMD
3812 && IS_SPEC (OP_SYM_ETYPE (op))
3813 && SPEC_ABSA (OP_SYM_ETYPE (op))
3814 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3817 D(emitcode ("; genPlus aligned array",""));
3818 aopPut (IC_RESULT (ic),
3819 aopGet (rightOp, 0, FALSE, FALSE),
3821 isOperandVolatile (IC_RESULT (ic), FALSE));
3823 if( 1 == getDataSize (IC_RIGHT (ic)) )
3825 aopPut (IC_RESULT (ic),
3826 aopGet (leftOp, 1, FALSE, FALSE),
3828 isOperandVolatile (IC_RESULT (ic), FALSE));
3832 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
3833 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3834 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3839 /* if the lower bytes of a literal are zero skip the addition */
3840 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3842 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3843 (skip_bytes+1 < size))
3848 D(emitcode ("; genPlus shortcut",""));
3853 if( offset >= skip_bytes )
3855 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3858 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3860 emitcode("xch", "a,b");
3861 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3862 emitcode (add, "a,b");
3865 else if (aopGetUsesAcc (leftOp, offset))
3867 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3868 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3872 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3873 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3875 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3876 add = "addc"; /* further adds must propagate carry */
3880 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3881 isOperandVolatile (IC_RESULT (ic), FALSE))
3884 aopPut (IC_RESULT (ic),
3885 aopGet (leftOp, offset, FALSE, FALSE),
3887 isOperandVolatile (IC_RESULT (ic), FALSE));
3893 adjustArithmeticResult (ic);
3896 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3897 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3898 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3901 /*-----------------------------------------------------------------*/
3902 /* genMinusDec :- does subtraction with deccrement if possible */
3903 /*-----------------------------------------------------------------*/
3905 genMinusDec (iCode * ic)
3907 unsigned int icount;
3908 unsigned int size = getDataSize (IC_RESULT (ic));
3910 /* will try to generate an increment */
3911 /* if the right side is not a literal
3913 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3916 /* if the literal value of the right hand side
3917 is greater than 4 then it is not worth it */
3918 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3921 D(emitcode ("; genMinusDec",""));
3923 /* if decrement >=16 bits in register or direct space */
3924 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3925 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3933 /* If the next instruction is a goto and the goto target
3934 * is <= 10 instructions previous to this, we can generate
3935 * jumps straight to that target.
3937 if (ic->next && ic->next->op == GOTO
3938 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3939 && labelRange <= 10)
3941 emitcode (";", "tail decrement optimized");
3942 tlbl = IC_LABEL (ic->next);
3947 tlbl = newiTempLabel (NULL);
3951 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3952 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3953 IS_AOP_PREG (IC_RESULT (ic)))
3954 emitcode ("cjne", "%s,#0xff,%05d$"
3955 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
3959 emitcode ("mov", "a,#0xff");
3960 emitcode ("cjne", "a,%s,%05d$"
3961 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
3964 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3967 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3968 IS_AOP_PREG (IC_RESULT (ic)))
3969 emitcode ("cjne", "%s,#0xff,%05d$"
3970 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
3974 emitcode ("cjne", "a,%s,%05d$"
3975 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
3978 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3982 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3983 IS_AOP_PREG (IC_RESULT (ic)))
3984 emitcode ("cjne", "%s,#0xff,%05d$"
3985 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
3989 emitcode ("cjne", "a,%s,%05d$"
3990 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
3993 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3997 emitcode ("", "%05d$:", tlbl->key + 100);
4002 /* if the sizes are greater than 1 then we cannot */
4003 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4004 AOP_SIZE (IC_LEFT (ic)) > 1)
4007 /* we can if the aops of the left & result match or
4008 if they are in registers and the registers are the
4010 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4014 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4022 /*-----------------------------------------------------------------*/
4023 /* addSign - complete with sign */
4024 /*-----------------------------------------------------------------*/
4026 addSign (operand * result, int offset, int sign)
4028 int size = (getDataSize (result) - offset);
4033 emitcode ("rlc", "a");
4034 emitcode ("subb", "a,acc");
4036 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4040 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4044 /*-----------------------------------------------------------------*/
4045 /* genMinusBits - generates code for subtraction of two bits */
4046 /*-----------------------------------------------------------------*/
4048 genMinusBits (iCode * ic)
4050 symbol *lbl = newiTempLabel (NULL);
4052 D(emitcode ("; genMinusBits",""));
4054 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4056 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4057 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4058 emitcode ("cpl", "c");
4059 emitcode ("", "%05d$:", (lbl->key + 100));
4060 outBitC (IC_RESULT (ic));
4064 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4065 emitcode ("subb", "a,acc");
4066 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4067 emitcode ("inc", "a");
4068 emitcode ("", "%05d$:", (lbl->key + 100));
4069 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4070 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4074 /*-----------------------------------------------------------------*/
4075 /* genMinus - generates code for subtraction */
4076 /*-----------------------------------------------------------------*/
4078 genMinus (iCode * ic)
4080 int size, offset = 0;
4082 D(emitcode ("; genMinus",""));
4084 aopOp (IC_LEFT (ic), ic, FALSE);
4085 aopOp (IC_RIGHT (ic), ic, FALSE);
4086 aopOp (IC_RESULT (ic), ic, TRUE);
4088 /* special cases :- */
4089 /* if both left & right are in bit space */
4090 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4091 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4097 /* if I can do an decrement instead
4098 of subtract then GOOD for ME */
4099 if (genMinusDec (ic) == TRUE)
4102 size = getDataSize (IC_RESULT (ic));
4104 /* if literal, add a,#-lit, else normal subb */
4105 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4107 unsigned long lit = 0L;
4108 bool useCarry = FALSE;
4110 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4115 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4116 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4117 if (!offset && !size && lit== (unsigned long) -1) {
4118 emitcode ("dec", "a");
4119 } else if (!useCarry) {
4120 /* first add without previous c */
4121 emitcode ("add", "a,#0x%02x",
4122 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4125 emitcode ("addc", "a,#0x%02x",
4126 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4128 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4130 /* no need to add zeroes */
4137 operand *leftOp, *rightOp;
4139 leftOp = IC_LEFT(ic);
4140 rightOp = IC_RIGHT(ic);
4144 if (aopGetUsesAcc(rightOp, offset)) {
4145 if (aopGetUsesAcc(leftOp, offset)) {
4148 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4150 emitcode ("mov", "b,a");
4153 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4154 emitcode ("subb", "a,b");
4157 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4158 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4160 emitcode( "setb", "c");
4162 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4163 emitcode("cpl", "a");
4166 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4169 emitcode ("subb", "a,%s",
4170 aopGet(rightOp, offset, FALSE, TRUE));
4173 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4178 adjustArithmeticResult (ic);
4181 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4182 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4183 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4187 /*-----------------------------------------------------------------*/
4188 /* genMultbits :- multiplication of bits */
4189 /*-----------------------------------------------------------------*/
4191 genMultbits (operand * left,
4195 D(emitcode ("; genMultbits",""));
4197 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4198 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4202 /*-----------------------------------------------------------------*/
4203 /* genMultOneByte : 8*8=8/16 bit multiplication */
4204 /*-----------------------------------------------------------------*/
4206 genMultOneByte (operand * left,
4211 int size = AOP_SIZE (result);
4212 bool runtimeSign, compiletimeSign;
4213 bool lUnsigned, rUnsigned, pushedB;
4215 D(emitcode ("; genMultOneByte",""));
4217 if (size < 1 || size > 2)
4219 /* this should never happen */
4220 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4221 AOP_SIZE(result), __FILE__, lineno);
4225 /* (if two literals: the value is computed before) */
4226 /* if one literal, literal on the right */
4227 if (AOP_TYPE (left) == AOP_LIT)
4232 /* emitcode (";", "swapped left and right"); */
4234 /* if no literal, unsigned on the right: shorter code */
4235 if ( AOP_TYPE (right) != AOP_LIT
4236 && SPEC_USIGN (getSpec (operandType (left))))
4243 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4244 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4248 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4249 no need to take care about the signedness! */
4250 || (lUnsigned && rUnsigned))
4252 /* just an unsigned 8 * 8 = 8 multiply
4254 /* emitcode (";","unsigned"); */
4255 /* TODO: check for accumulator clash between left & right aops? */
4257 if (AOP_TYPE (right) == AOP_LIT)
4259 /* moving to accumulator first helps peepholes */
4260 MOVA (aopGet (left, 0, FALSE, FALSE));
4261 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4265 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4266 MOVA (aopGet (left, 0, FALSE, FALSE));
4269 emitcode ("mul", "ab");
4270 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4272 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4278 /* we have to do a signed multiply */
4279 /* emitcode (";", "signed"); */
4281 /* now sign adjust for both left & right */
4283 /* let's see what's needed: */
4284 /* apply negative sign during runtime */
4285 runtimeSign = FALSE;
4286 /* negative sign from literals */
4287 compiletimeSign = FALSE;
4291 if (AOP_TYPE(left) == AOP_LIT)
4293 /* signed literal */
4294 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4296 compiletimeSign = TRUE;
4299 /* signed but not literal */
4305 if (AOP_TYPE(right) == AOP_LIT)
4307 /* signed literal */
4308 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4310 compiletimeSign ^= TRUE;
4313 /* signed but not literal */
4317 /* initialize F0, which stores the runtime sign */
4320 if (compiletimeSign)
4321 emitcode ("setb", "F0"); /* set sign flag */
4323 emitcode ("clr", "F0"); /* reset sign flag */
4326 /* save the signs of the operands */
4327 if (AOP_TYPE(right) == AOP_LIT)
4329 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4331 if (!rUnsigned && val < 0)
4332 emitcode ("mov", "b,#0x%02x", -val);
4334 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4336 else /* ! literal */
4338 if (rUnsigned) /* emitcode (";", "signed"); */
4340 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4343 MOVA (aopGet (right, 0, FALSE, FALSE));
4344 lbl = newiTempLabel (NULL);
4345 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4346 emitcode ("cpl", "F0"); /* complement sign flag */
4347 emitcode ("cpl", "a"); /* 2's complement */
4348 emitcode ("inc", "a");
4349 emitcode ("", "%05d$:", (lbl->key + 100));
4350 emitcode ("mov", "b,a");
4354 if (AOP_TYPE(left) == AOP_LIT)
4356 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4358 if (!lUnsigned && val < 0)
4359 emitcode ("mov", "a,#0x%02x", -val);
4361 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4363 else /* ! literal */
4365 MOVA (aopGet (left, 0, FALSE, FALSE));
4369 lbl = newiTempLabel (NULL);
4370 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4371 emitcode ("cpl", "F0"); /* complement sign flag */
4372 emitcode ("cpl", "a"); /* 2's complement */
4373 emitcode ("inc", "a");
4374 emitcode ("", "%05d$:", (lbl->key + 100));
4378 /* now the multiplication */
4379 emitcode ("mul", "ab");
4380 if (runtimeSign || compiletimeSign)
4382 lbl = newiTempLabel (NULL);
4384 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4385 emitcode ("cpl", "a"); /* lsb 2's complement */
4387 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4390 emitcode ("add", "a,#1"); /* this sets carry flag */
4391 emitcode ("xch", "a,b");
4392 emitcode ("cpl", "a"); /* msb 2's complement */
4393 emitcode ("addc", "a,#0");
4394 emitcode ("xch", "a,b");
4396 emitcode ("", "%05d$:", (lbl->key + 100));
4398 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4400 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4405 /*-----------------------------------------------------------------*/
4406 /* genMult - generates code for multiplication */
4407 /*-----------------------------------------------------------------*/
4409 genMult (iCode * ic)
4411 operand *left = IC_LEFT (ic);
4412 operand *right = IC_RIGHT (ic);
4413 operand *result = IC_RESULT (ic);
4415 D(emitcode ("; genMult",""));
4417 /* assign the amsops */
4418 aopOp (left, ic, FALSE);
4419 aopOp (right, ic, FALSE);
4420 aopOp (result, ic, TRUE);
4422 /* special cases first */
4424 if (AOP_TYPE (left) == AOP_CRY &&
4425 AOP_TYPE (right) == AOP_CRY)
4427 genMultbits (left, right, result);
4431 /* if both are of size == 1 */
4432 #if 0 // one of them can be a sloc shared with the result
4433 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4435 if (getSize(operandType(left)) == 1 &&
4436 getSize(operandType(right)) == 1)
4439 genMultOneByte (left, right, result);
4443 /* should have been converted to function call */
4444 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4445 getSize(OP_SYMBOL(right)->type));
4449 freeAsmop (result, NULL, ic, TRUE);
4450 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4451 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4454 /*-----------------------------------------------------------------*/
4455 /* genDivbits :- division of bits */
4456 /*-----------------------------------------------------------------*/
4458 genDivbits (operand * left,
4465 D(emitcode ("; genDivbits",""));
4469 /* the result must be bit */
4470 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4471 l = aopGet (left, 0, FALSE, FALSE);
4475 emitcode ("div", "ab");
4476 emitcode ("rrc", "a");
4480 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4483 /*-----------------------------------------------------------------*/
4484 /* genDivOneByte : 8 bit division */
4485 /*-----------------------------------------------------------------*/
4487 genDivOneByte (operand * left,
4491 bool lUnsigned, rUnsigned, pushedB;
4492 bool runtimeSign, compiletimeSign;
4496 D(emitcode ("; genDivOneByte",""));
4498 /* Why is it necessary that genDivOneByte() can return an int result?
4501 volatile unsigned char uc;
4502 volatile signed char sc1, sc2;
4515 In all cases a one byte result would overflow, the following cast to int
4516 would return the wrong result.
4518 Two possible solution:
4519 a) cast operands to int, if ((unsigned) / (signed)) or
4520 ((signed) / (signed))
4521 b) return an 16 bit signed int; this is what we're doing here!
4524 size = AOP_SIZE (result) - 1;
4526 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4527 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4531 /* signed or unsigned */
4532 if (lUnsigned && rUnsigned)
4534 /* unsigned is easy */
4535 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4536 MOVA (aopGet (left, 0, FALSE, FALSE));
4537 emitcode ("div", "ab");
4538 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4540 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4546 /* signed is a little bit more difficult */
4548 /* now sign adjust for both left & right */
4550 /* let's see what's needed: */
4551 /* apply negative sign during runtime */
4552 runtimeSign = FALSE;
4553 /* negative sign from literals */
4554 compiletimeSign = FALSE;
4558 if (AOP_TYPE(left) == AOP_LIT)
4560 /* signed literal */
4561 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4563 compiletimeSign = TRUE;
4566 /* signed but not literal */
4572 if (AOP_TYPE(right) == AOP_LIT)
4574 /* signed literal */
4575 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4577 compiletimeSign ^= TRUE;
4580 /* signed but not literal */
4584 /* initialize F0, which stores the runtime sign */
4587 if (compiletimeSign)
4588 emitcode ("setb", "F0"); /* set sign flag */
4590 emitcode ("clr", "F0"); /* reset sign flag */
4593 /* save the signs of the operands */
4594 if (AOP_TYPE(right) == AOP_LIT)
4596 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4598 if (!rUnsigned && val < 0)
4599 emitcode ("mov", "b,#0x%02x", -val);
4601 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4603 else /* ! literal */
4606 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4609 MOVA (aopGet (right, 0, FALSE, FALSE));
4610 lbl = newiTempLabel (NULL);
4611 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4612 emitcode ("cpl", "F0"); /* complement sign flag */
4613 emitcode ("cpl", "a"); /* 2's complement */
4614 emitcode ("inc", "a");
4615 emitcode ("", "%05d$:", (lbl->key + 100));
4616 emitcode ("mov", "b,a");
4620 if (AOP_TYPE(left) == AOP_LIT)
4622 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4624 if (!lUnsigned && val < 0)
4625 emitcode ("mov", "a,#0x%02x", -val);
4627 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4629 else /* ! literal */
4631 MOVA (aopGet (left, 0, FALSE, FALSE));
4635 lbl = newiTempLabel (NULL);
4636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4637 emitcode ("cpl", "F0"); /* complement sign flag */
4638 emitcode ("cpl", "a"); /* 2's complement */
4639 emitcode ("inc", "a");
4640 emitcode ("", "%05d$:", (lbl->key + 100));
4644 /* now the division */
4645 emitcode ("div", "ab");
4647 if (runtimeSign || compiletimeSign)
4649 lbl = newiTempLabel (NULL);
4651 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4652 emitcode ("cpl", "a"); /* lsb 2's complement */
4653 emitcode ("inc", "a");
4654 emitcode ("", "%05d$:", (lbl->key + 100));
4656 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4659 /* msb is 0x00 or 0xff depending on the sign */
4662 emitcode ("mov", "c,F0");
4663 emitcode ("subb", "a,acc");
4665 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4667 else /* compiletimeSign */
4669 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4674 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4676 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4682 /*-----------------------------------------------------------------*/
4683 /* genDiv - generates code for division */
4684 /*-----------------------------------------------------------------*/
4688 operand *left = IC_LEFT (ic);
4689 operand *right = IC_RIGHT (ic);
4690 operand *result = IC_RESULT (ic);
4692 D(emitcode ("; genDiv",""));
4694 /* assign the amsops */
4695 aopOp (left, ic, FALSE);
4696 aopOp (right, ic, FALSE);
4697 aopOp (result, ic, TRUE);
4699 /* special cases first */
4701 if (AOP_TYPE (left) == AOP_CRY &&
4702 AOP_TYPE (right) == AOP_CRY)
4704 genDivbits (left, right, result);
4708 /* if both are of size == 1 */
4709 if (AOP_SIZE (left) == 1 &&
4710 AOP_SIZE (right) == 1)
4712 genDivOneByte (left, right, result);
4716 /* should have been converted to function call */
4719 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4721 freeAsmop (result, NULL, ic, TRUE);
4724 /*-----------------------------------------------------------------*/
4725 /* genModbits :- modulus of bits */
4726 /*-----------------------------------------------------------------*/
4728 genModbits (operand * left,
4735 D(emitcode ("; genModbits",""));
4739 /* the result must be bit */
4740 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4741 l = aopGet (left, 0, FALSE, FALSE);
4745 emitcode ("div", "ab");
4746 emitcode ("mov", "a,b");
4747 emitcode ("rrc", "a");
4751 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4754 /*-----------------------------------------------------------------*/
4755 /* genModOneByte : 8 bit modulus */
4756 /*-----------------------------------------------------------------*/
4758 genModOneByte (operand * left,
4762 bool lUnsigned, rUnsigned, pushedB;
4763 bool runtimeSign, compiletimeSign;
4767 D(emitcode ("; genModOneByte",""));
4769 size = AOP_SIZE (result) - 1;
4771 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4772 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4774 /* if right is a literal, check it for 2^n */
4775 if (AOP_TYPE(right) == AOP_LIT)
4777 unsigned char val = abs((int) operandLitValue(right));
4778 symbol *lbl2 = NULL;
4782 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4792 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4793 /* because iCode should have been changed to genAnd */
4794 /* see file "SDCCopt.c", function "convertToFcall()" */
4796 MOVA (aopGet (left, 0, FALSE, FALSE));
4797 emitcode ("mov", "c,acc.7");
4798 emitcode ("anl", "a,#0x%02x", val - 1);
4799 lbl = newiTempLabel (NULL);
4800 emitcode ("jz", "%05d$", (lbl->key + 100));
4801 emitcode ("jnc", "%05d$", (lbl->key + 100));
4802 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4808 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4810 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
4811 lbl2 = newiTempLabel (NULL);
4812 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4814 emitcode ("", "%05d$:", (lbl->key + 100));
4815 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4817 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4820 emitcode ("", "%05d$:", (lbl2->key + 100));
4831 /* signed or unsigned */
4832 if (lUnsigned && rUnsigned)
4834 /* unsigned is easy */
4835 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4836 MOVA (aopGet (left, 0, FALSE, FALSE));
4837 emitcode ("div", "ab");
4838 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4840 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4846 /* signed is a little bit more difficult */
4848 /* now sign adjust for both left & right */
4850 /* modulus: sign of the right operand has no influence on the result! */
4851 if (AOP_TYPE(right) == AOP_LIT)
4853 signed char val = (char) operandLitValue(right);
4855 if (!rUnsigned && val < 0)
4856 emitcode ("mov", "b,#0x%02x", -val);
4858 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4860 else /* not literal */
4863 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4866 MOVA (aopGet (right, 0, FALSE, FALSE));
4867 lbl = newiTempLabel (NULL);
4868 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4869 emitcode ("cpl", "a"); /* 2's complement */
4870 emitcode ("inc", "a");
4871 emitcode ("", "%05d$:", (lbl->key + 100));
4872 emitcode ("mov", "b,a");
4876 /* let's see what's needed: */
4877 /* apply negative sign during runtime */
4878 runtimeSign = FALSE;
4879 /* negative sign from literals */
4880 compiletimeSign = FALSE;
4882 /* sign adjust left side */
4883 if (AOP_TYPE(left) == AOP_LIT)
4885 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4887 if (!lUnsigned && val < 0)
4889 compiletimeSign = TRUE; /* set sign flag */
4890 emitcode ("mov", "a,#0x%02x", -val);
4893 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4895 else /* ! literal */
4897 MOVA (aopGet (left, 0, FALSE, FALSE));
4902 emitcode ("clr", "F0"); /* clear sign flag */
4904 lbl = newiTempLabel (NULL);
4905 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4906 emitcode ("setb", "F0"); /* set sign flag */
4907 emitcode ("cpl", "a"); /* 2's complement */
4908 emitcode ("inc", "a");
4909 emitcode ("", "%05d$:", (lbl->key + 100));
4913 /* now the modulus */
4914 emitcode ("div", "ab");
4916 if (runtimeSign || compiletimeSign)
4918 emitcode ("mov", "a,b");
4919 lbl = newiTempLabel (NULL);
4921 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4922 emitcode ("cpl", "a"); /* 2's complement */
4923 emitcode ("inc", "a");
4924 emitcode ("", "%05d$:", (lbl->key + 100));
4926 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4929 /* msb is 0x00 or 0xff depending on the sign */
4932 emitcode ("mov", "c,F0");
4933 emitcode ("subb", "a,acc");
4935 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4937 else /* compiletimeSign */
4939 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
4944 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
4946 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4952 /*-----------------------------------------------------------------*/
4953 /* genMod - generates code for division */
4954 /*-----------------------------------------------------------------*/
4958 operand *left = IC_LEFT (ic);
4959 operand *right = IC_RIGHT (ic);
4960 operand *result = IC_RESULT (ic);
4962 D(emitcode ("; genMod",""));
4964 /* assign the asmops */
4965 aopOp (left, ic, FALSE);
4966 aopOp (right, ic, FALSE);
4967 aopOp (result, ic, TRUE);
4969 /* special cases first */
4971 if (AOP_TYPE (left) == AOP_CRY &&
4972 AOP_TYPE (right) == AOP_CRY)
4974 genModbits (left, right, result);
4978 /* if both are of size == 1 */
4979 if (AOP_SIZE (left) == 1 &&
4980 AOP_SIZE (right) == 1)
4982 genModOneByte (left, right, result);
4986 /* should have been converted to function call */
4990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* genIfxJump :- will create a jump depending on the ifx */
4997 /*-----------------------------------------------------------------*/
4999 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5002 symbol *tlbl = newiTempLabel (NULL);
5005 D(emitcode ("; genIfxJump",""));
5007 /* if true label then we jump if condition
5011 jlbl = IC_TRUE (ic);
5012 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5013 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5017 /* false label is present */
5018 jlbl = IC_FALSE (ic);
5019 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5020 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5022 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5023 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5025 emitcode (inst, "%05d$", tlbl->key + 100);
5026 freeForBranchAsmop (result);
5027 freeForBranchAsmop (right);
5028 freeForBranchAsmop (left);
5029 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5030 emitcode ("", "%05d$:", tlbl->key + 100);
5032 /* mark the icode as generated */
5036 /*-----------------------------------------------------------------*/
5037 /* genCmp :- greater or less than comparison */
5038 /*-----------------------------------------------------------------*/
5040 genCmp (operand * left, operand * right,
5041 operand * result, iCode * ifx, int sign, iCode *ic)
5043 int size, offset = 0;
5044 unsigned long lit = 0L;
5047 D(emitcode ("; genCmp",""));
5049 /* if left & right are bit variables */
5050 if (AOP_TYPE (left) == AOP_CRY &&
5051 AOP_TYPE (right) == AOP_CRY)
5053 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5054 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5058 /* subtract right from left if at the
5059 end the carry flag is set then we know that
5060 left is greater than right */
5061 size = max (AOP_SIZE (left), AOP_SIZE (right));
5063 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5064 if ((size == 1) && !sign &&
5065 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5067 symbol *lbl = newiTempLabel (NULL);
5068 emitcode ("cjne", "%s,%s,%05d$",
5069 aopGet (left, offset, FALSE, FALSE),
5070 aopGet (right, offset, FALSE, FALSE),
5072 emitcode ("", "%05d$:", lbl->key + 100);
5076 if (AOP_TYPE (right) == AOP_LIT)
5078 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5079 /* optimize if(x < 0) or if(x >= 0) */
5088 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5089 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5091 genIfxJump (ifx, "acc.7", left, right, result);
5092 freeAsmop (right, NULL, ic, TRUE);
5093 freeAsmop (left, NULL, ic, TRUE);
5098 emitcode ("rlc", "a");
5106 bool pushedB = FALSE;
5107 rightInB = aopGetUsesAcc(right, offset);
5111 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5113 MOVA (aopGet (left, offset, FALSE, FALSE));
5114 if (sign && size == 0)
5116 emitcode ("xrl", "a,#0x80");
5117 if (AOP_TYPE (right) == AOP_LIT)
5119 unsigned long lit = (unsigned long)
5120 floatFromVal (AOP (right)->aopu.aop_lit);
5121 emitcode ("subb", "a,#0x%02x",
5122 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5130 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5132 emitcode ("xrl", "b,#0x80");
5133 emitcode ("subb", "a,b");
5139 emitcode ("subb", "a,b");
5141 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5151 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5153 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5159 /* if the result is used in the next
5160 ifx conditional branch then generate
5161 code a little differently */
5163 genIfxJump (ifx, "c", NULL, NULL, result);
5166 /* leave the result in acc */
5170 /*-----------------------------------------------------------------*/
5171 /* genCmpGt :- greater than comparison */
5172 /*-----------------------------------------------------------------*/
5174 genCmpGt (iCode * ic, iCode * ifx)
5176 operand *left, *right, *result;
5177 sym_link *letype, *retype;
5180 D(emitcode ("; genCmpGt",""));
5182 left = IC_LEFT (ic);
5183 right = IC_RIGHT (ic);
5184 result = IC_RESULT (ic);
5186 letype = getSpec (operandType (left));
5187 retype = getSpec (operandType (right));
5188 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5189 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5190 /* assign the amsops */
5191 aopOp (left, ic, FALSE);
5192 aopOp (right, ic, FALSE);
5193 aopOp (result, ic, TRUE);
5195 genCmp (right, left, result, ifx, sign, ic);
5197 freeAsmop (result, NULL, ic, TRUE);
5200 /*-----------------------------------------------------------------*/
5201 /* genCmpLt - less than comparisons */
5202 /*-----------------------------------------------------------------*/
5204 genCmpLt (iCode * ic, iCode * ifx)
5206 operand *left, *right, *result;
5207 sym_link *letype, *retype;
5210 D(emitcode ("; genCmpLt",""));
5212 left = IC_LEFT (ic);
5213 right = IC_RIGHT (ic);
5214 result = IC_RESULT (ic);
5216 letype = getSpec (operandType (left));
5217 retype = getSpec (operandType (right));
5218 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5219 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5220 /* assign the amsops */
5221 aopOp (left, ic, FALSE);
5222 aopOp (right, ic, FALSE);
5223 aopOp (result, ic, TRUE);
5225 genCmp (left, right, result, ifx, sign,ic);
5227 freeAsmop (result, NULL, ic, TRUE);
5230 /*-----------------------------------------------------------------*/
5231 /* gencjneshort - compare and jump if not equal */
5232 /*-----------------------------------------------------------------*/
5234 gencjneshort (operand * left, operand * right, symbol * lbl)
5236 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5238 unsigned long lit = 0L;
5240 /* if the left side is a literal or
5241 if the right is in a pointer register and left
5243 if ((AOP_TYPE (left) == AOP_LIT) ||
5244 (AOP_TYPE (left) == AOP_IMMD) ||
5245 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5252 if (AOP_TYPE (right) == AOP_LIT)
5253 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5255 /* if the right side is a literal then anything goes */
5256 if (AOP_TYPE (right) == AOP_LIT &&
5257 AOP_TYPE (left) != AOP_DIR &&
5258 AOP_TYPE (left) != AOP_IMMD)
5262 emitcode ("cjne", "%s,%s,%05d$",
5263 aopGet (left, offset, FALSE, FALSE),
5264 aopGet (right, offset, FALSE, FALSE),
5270 /* if the right side is in a register or in direct space or
5271 if the left is a pointer register & right is not */
5272 else if (AOP_TYPE (right) == AOP_REG ||
5273 AOP_TYPE (right) == AOP_DIR ||
5274 AOP_TYPE (right) == AOP_LIT ||
5275 AOP_TYPE (right) == AOP_IMMD ||
5276 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5277 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5281 MOVA (aopGet (left, offset, FALSE, FALSE));
5282 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5283 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5284 emitcode ("jnz", "%05d$", lbl->key + 100);
5286 emitcode ("cjne", "a,%s,%05d$",
5287 aopGet (right, offset, FALSE, TRUE),
5294 /* right is a pointer reg need both a & b */
5298 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5299 wassertl(!BINUSE, "B was in use");
5300 l = aopGet (left, offset, FALSE, FALSE);
5301 if (strcmp (l, "b"))
5302 emitcode ("mov", "b,%s", l);
5303 MOVA (aopGet (right, offset, FALSE, FALSE));
5304 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5310 /*-----------------------------------------------------------------*/
5311 /* gencjne - compare and jump if not equal */
5312 /*-----------------------------------------------------------------*/
5314 gencjne (operand * left, operand * right, symbol * lbl)
5316 symbol *tlbl = newiTempLabel (NULL);
5318 gencjneshort (left, right, lbl);
5320 emitcode ("mov", "a,%s", one);
5321 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5322 emitcode ("", "%05d$:", lbl->key + 100);
5323 emitcode ("clr", "a");
5324 emitcode ("", "%05d$:", tlbl->key + 100);
5327 /*-----------------------------------------------------------------*/
5328 /* genCmpEq - generates code for equal to */
5329 /*-----------------------------------------------------------------*/
5331 genCmpEq (iCode * ic, iCode * ifx)
5333 operand *left, *right, *result;
5335 D(emitcode ("; genCmpEq",""));
5337 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5338 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5339 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5341 /* if literal, literal on the right or
5342 if the right is in a pointer register and left
5344 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5345 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5347 operand *t = IC_RIGHT (ic);
5348 IC_RIGHT (ic) = IC_LEFT (ic);
5352 if (ifx && !AOP_SIZE (result))
5355 /* if they are both bit variables */
5356 if (AOP_TYPE (left) == AOP_CRY &&
5357 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5359 if (AOP_TYPE (right) == AOP_LIT)
5361 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5364 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5365 emitcode ("cpl", "c");
5369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5373 emitcode ("clr", "c");
5375 /* AOP_TYPE(right) == AOP_CRY */
5379 symbol *lbl = newiTempLabel (NULL);
5380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5381 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5382 emitcode ("cpl", "c");
5383 emitcode ("", "%05d$:", (lbl->key + 100));
5385 /* if true label then we jump if condition
5387 tlbl = newiTempLabel (NULL);
5390 emitcode ("jnc", "%05d$", tlbl->key + 100);
5391 freeForBranchAsmop (result);
5392 freeForBranchAsmop (right);
5393 freeForBranchAsmop (left);
5394 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5398 emitcode ("jc", "%05d$", tlbl->key + 100);
5399 freeForBranchAsmop (result);
5400 freeForBranchAsmop (right);
5401 freeForBranchAsmop (left);
5402 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5404 emitcode ("", "%05d$:", tlbl->key + 100);
5408 tlbl = newiTempLabel (NULL);
5409 gencjneshort (left, right, tlbl);
5412 freeForBranchAsmop (result);
5413 freeForBranchAsmop (right);
5414 freeForBranchAsmop (left);
5415 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5416 emitcode ("", "%05d$:", tlbl->key + 100);
5420 symbol *lbl = newiTempLabel (NULL);
5421 emitcode ("sjmp", "%05d$", lbl->key + 100);
5422 emitcode ("", "%05d$:", tlbl->key + 100);
5423 freeForBranchAsmop (result);
5424 freeForBranchAsmop (right);
5425 freeForBranchAsmop (left);
5426 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5427 emitcode ("", "%05d$:", lbl->key + 100);
5430 /* mark the icode as generated */
5435 /* if they are both bit variables */
5436 if (AOP_TYPE (left) == AOP_CRY &&
5437 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5439 if (AOP_TYPE (right) == AOP_LIT)
5441 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5444 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5445 emitcode ("cpl", "c");
5449 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5453 emitcode ("clr", "c");
5455 /* AOP_TYPE(right) == AOP_CRY */
5459 symbol *lbl = newiTempLabel (NULL);
5460 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5461 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5462 emitcode ("cpl", "c");
5463 emitcode ("", "%05d$:", (lbl->key + 100));
5466 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5473 genIfxJump (ifx, "c", left, right, result);
5476 /* if the result is used in an arithmetic operation
5477 then put the result in place */
5482 gencjne (left, right, newiTempLabel (NULL));
5483 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5485 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5490 genIfxJump (ifx, "a", left, right, result);
5493 /* if the result is used in an arithmetic operation
5494 then put the result in place */
5495 if (AOP_TYPE (result) != AOP_CRY)
5497 /* leave the result in acc */
5501 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 freeAsmop (result, NULL, ic, TRUE);
5506 /*-----------------------------------------------------------------*/
5507 /* ifxForOp - returns the icode containing the ifx for operand */
5508 /*-----------------------------------------------------------------*/
5510 ifxForOp (operand * op, iCode * ic)
5512 /* if true symbol then needs to be assigned */
5513 if (IS_TRUE_SYMOP (op))
5516 /* if this has register type condition and
5517 the next instruction is ifx with the same operand
5518 and live to of the operand is upto the ifx only then */
5520 ic->next->op == IFX &&
5521 IC_COND (ic->next)->key == op->key &&
5522 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5528 /*-----------------------------------------------------------------*/
5529 /* hasInc - operand is incremented before any other use */
5530 /*-----------------------------------------------------------------*/
5532 hasInc (operand *op, iCode *ic,int osize)
5534 sym_link *type = operandType(op);
5535 sym_link *retype = getSpec (type);
5536 iCode *lic = ic->next;
5539 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5540 if (!IS_SYMOP(op)) return NULL;
5542 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5543 if (IS_AGGREGATE(type->next)) return NULL;
5544 if (osize != (isize = getSize(type->next))) return NULL;
5547 /* if operand of the form op = op + <sizeof *op> */
5548 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5549 isOperandEqual(IC_RESULT(lic),op) &&
5550 isOperandLiteral(IC_RIGHT(lic)) &&
5551 operandLitValue(IC_RIGHT(lic)) == isize) {
5554 /* if the operand used or deffed */
5555 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5558 /* if GOTO or IFX */
5559 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5565 /*-----------------------------------------------------------------*/
5566 /* genAndOp - for && operation */
5567 /*-----------------------------------------------------------------*/
5569 genAndOp (iCode * ic)
5571 operand *left, *right, *result;
5574 D(emitcode ("; genAndOp",""));
5576 /* note here that && operations that are in an
5577 if statement are taken away by backPatchLabels
5578 only those used in arthmetic operations remain */
5579 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5580 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5581 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5583 /* if both are bit variables */
5584 if (AOP_TYPE (left) == AOP_CRY &&
5585 AOP_TYPE (right) == AOP_CRY)
5587 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5588 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5593 tlbl = newiTempLabel (NULL);
5595 emitcode ("jz", "%05d$", tlbl->key + 100);
5597 emitcode ("", "%05d$:", tlbl->key + 100);
5601 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5602 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5603 freeAsmop (result, NULL, ic, TRUE);
5607 /*-----------------------------------------------------------------*/
5608 /* genOrOp - for || operation */
5609 /*-----------------------------------------------------------------*/
5611 genOrOp (iCode * ic)
5613 operand *left, *right, *result;
5616 D(emitcode ("; genOrOp",""));
5618 /* note here that || operations that are in an
5619 if statement are taken away by backPatchLabels
5620 only those used in arthmetic operations remain */
5621 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5622 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5623 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5625 /* if both are bit variables */
5626 if (AOP_TYPE (left) == AOP_CRY &&
5627 AOP_TYPE (right) == AOP_CRY)
5629 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5630 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5635 tlbl = newiTempLabel (NULL);
5637 emitcode ("jnz", "%05d$", tlbl->key + 100);
5639 emitcode ("", "%05d$:", tlbl->key + 100);
5643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5644 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5645 freeAsmop (result, NULL, ic, TRUE);
5648 /*-----------------------------------------------------------------*/
5649 /* isLiteralBit - test if lit == 2^n */
5650 /*-----------------------------------------------------------------*/
5652 isLiteralBit (unsigned long lit)
5654 unsigned long pw[32] =
5655 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5656 0x100L, 0x200L, 0x400L, 0x800L,
5657 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5658 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5659 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5660 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5661 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5664 for (idx = 0; idx < 32; idx++)
5670 /*-----------------------------------------------------------------*/
5671 /* continueIfTrue - */
5672 /*-----------------------------------------------------------------*/
5674 continueIfTrue (iCode * ic)
5677 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5681 /*-----------------------------------------------------------------*/
5683 /*-----------------------------------------------------------------*/
5685 jumpIfTrue (iCode * ic)
5688 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5692 /*-----------------------------------------------------------------*/
5693 /* jmpTrueOrFalse - */
5694 /*-----------------------------------------------------------------*/
5696 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5698 // ugly but optimized by peephole
5701 symbol *nlbl = newiTempLabel (NULL);
5702 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5703 emitcode ("", "%05d$:", tlbl->key + 100);
5704 freeForBranchAsmop (result);
5705 freeForBranchAsmop (right);
5706 freeForBranchAsmop (left);
5707 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5708 emitcode ("", "%05d$:", nlbl->key + 100);
5712 freeForBranchAsmop (result);
5713 freeForBranchAsmop (right);
5714 freeForBranchAsmop (left);
5715 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5716 emitcode ("", "%05d$:", tlbl->key + 100);
5721 /*-----------------------------------------------------------------*/
5722 /* genAnd - code for and */
5723 /*-----------------------------------------------------------------*/
5725 genAnd (iCode * ic, iCode * ifx)
5727 operand *left, *right, *result;
5728 int size, offset = 0;
5729 unsigned long lit = 0L;
5733 D(emitcode ("; genAnd",""));
5735 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5736 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5737 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5740 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5742 AOP_TYPE (left), AOP_TYPE (right));
5743 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5745 AOP_SIZE (left), AOP_SIZE (right));
5748 /* if left is a literal & right is not then exchange them */
5749 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5750 AOP_NEEDSACC (left))
5752 operand *tmp = right;
5757 /* if result = right then exchange left and right */
5758 if (sameRegs (AOP (result), AOP (right)))
5760 operand *tmp = right;
5765 /* if right is bit then exchange them */
5766 if (AOP_TYPE (right) == AOP_CRY &&
5767 AOP_TYPE (left) != AOP_CRY)
5769 operand *tmp = right;
5773 if (AOP_TYPE (right) == AOP_LIT)
5774 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776 size = AOP_SIZE (result);
5779 // result = bit & yy;
5780 if (AOP_TYPE (left) == AOP_CRY)
5782 // c = bit & literal;
5783 if (AOP_TYPE (right) == AOP_LIT)
5787 if (size && sameRegs (AOP (result), AOP (left)))
5790 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5795 if (size && (AOP_TYPE (result) == AOP_CRY))
5797 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5800 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5805 emitcode ("clr", "c");
5810 if (AOP_TYPE (right) == AOP_CRY)
5813 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5814 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5819 MOVA (aopGet (right, 0, FALSE, FALSE));
5821 emitcode ("rrc", "a");
5822 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5830 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5831 genIfxJump (ifx, "c", left, right, result);
5835 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5836 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5837 if ((AOP_TYPE (right) == AOP_LIT) &&
5838 (AOP_TYPE (result) == AOP_CRY) &&
5839 (AOP_TYPE (left) != AOP_CRY))
5841 int posbit = isLiteralBit (lit);
5846 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
5850 switch (posbit & 0x07)
5852 case 0: emitcode ("rrc", "a");
5854 case 7: emitcode ("rlc", "a");
5856 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5865 SNPRINTF (buffer, sizeof(buffer),
5866 "acc.%d", posbit & 0x07);
5867 genIfxJump (ifx, buffer, left, right, result);
5870 {// what is this case? just found it in ds390/gen.c
5871 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5878 symbol *tlbl = newiTempLabel (NULL);
5879 int sizel = AOP_SIZE (left);
5881 emitcode ("setb", "c");
5884 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5886 MOVA (aopGet (left, offset, FALSE, FALSE));
5888 if ((posbit = isLiteralBit (bytelit)) != 0)
5889 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5892 if (bytelit != 0x0FFL)
5893 emitcode ("anl", "a,%s",
5894 aopGet (right, offset, FALSE, TRUE));
5895 emitcode ("jnz", "%05d$", tlbl->key + 100);
5900 // bit = left & literal
5903 emitcode ("clr", "c");
5904 emitcode ("", "%05d$:", tlbl->key + 100);
5906 // if(left & literal)
5910 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5912 emitcode ("", "%05d$:", tlbl->key + 100);
5920 /* if left is same as result */
5921 if (sameRegs (AOP (result), AOP (left)))
5923 for (; size--; offset++)
5925 if (AOP_TYPE (right) == AOP_LIT)
5927 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5928 if (bytelit == 0x0FF)
5930 /* dummy read of volatile operand */
5931 if (isOperandVolatile (left, FALSE))
5932 MOVA (aopGet (left, offset, FALSE, FALSE));
5936 else if (bytelit == 0)
5938 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
5940 else if (IS_AOP_PREG (result))
5942 MOVA (aopGet (left, offset, FALSE, TRUE));
5943 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
5944 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
5947 emitcode ("anl", "%s,%s",
5948 aopGet (left, offset, FALSE, TRUE),
5949 aopGet (right, offset, FALSE, FALSE));
5953 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
5955 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
5959 MOVA (aopGet (right, offset, FALSE, FALSE));
5960 if (IS_AOP_PREG (result))
5962 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
5963 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
5966 emitcode ("anl", "%s,a",
5967 aopGet (left, offset, FALSE, TRUE));
5974 // left & result in different registers
5975 if (AOP_TYPE (result) == AOP_CRY)
5978 // if(size), result in bit
5979 // if(!size && ifx), conditional oper: if(left & right)
5980 symbol *tlbl = newiTempLabel (NULL);
5981 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5983 emitcode ("setb", "c");
5986 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
5987 && AOP_TYPE(left)==AOP_ACC)
5990 emitcode("mov", "a,b");
5991 emitcode ("anl", "a,%s",
5992 aopGet (right, offset, FALSE, FALSE));
5994 if (AOP_TYPE(left)==AOP_ACC)
5998 bool pushedB = pushB ();
5999 emitcode("mov", "b,a");
6000 MOVA (aopGet (right, offset, FALSE, FALSE));
6001 emitcode("anl", "a,b");
6006 MOVA (aopGet (right, offset, FALSE, FALSE));
6007 emitcode("anl", "a,b");
6010 MOVA (aopGet (right, offset, FALSE, FALSE));
6011 emitcode ("anl", "a,%s",
6012 aopGet (left, offset, FALSE, FALSE));
6015 emitcode ("jnz", "%05d$", tlbl->key + 100);
6021 emitcode ("", "%05d$:", tlbl->key + 100);
6025 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6027 emitcode ("", "%05d$:", tlbl->key + 100);
6031 for (; (size--); offset++)
6034 // result = left & right
6035 if (AOP_TYPE (right) == AOP_LIT)
6037 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6038 if (bytelit == 0x0FF)
6041 aopGet (left, offset, FALSE, FALSE),
6043 isOperandVolatile (result, FALSE));
6046 else if (bytelit == 0)
6048 /* dummy read of volatile operand */
6049 if (isOperandVolatile (left, FALSE))
6050 MOVA (aopGet (left, offset, FALSE, FALSE));
6051 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6054 else if (AOP_TYPE (left) == AOP_ACC)
6058 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6059 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6064 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6065 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6070 // faster than result <- left, anl result,right
6071 // and better if result is SFR
6072 if (AOP_TYPE (left) == AOP_ACC)
6075 emitcode("mov", "a,b");
6076 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6080 MOVA (aopGet (right, offset, FALSE, FALSE));
6081 emitcode ("anl", "a,%s",
6082 aopGet (left, offset, FALSE, FALSE));
6084 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6090 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6091 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6092 freeAsmop (result, NULL, ic, TRUE);
6095 /*-----------------------------------------------------------------*/
6096 /* genOr - code for or */
6097 /*-----------------------------------------------------------------*/
6099 genOr (iCode * ic, iCode * ifx)
6101 operand *left, *right, *result;
6102 int size, offset = 0;
6103 unsigned long lit = 0L;
6106 D(emitcode ("; genOr",""));
6108 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6109 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6110 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6113 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6115 AOP_TYPE (left), AOP_TYPE (right));
6116 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6118 AOP_SIZE (left), AOP_SIZE (right));
6121 /* if left is a literal & right is not then exchange them */
6122 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6123 AOP_NEEDSACC (left))
6125 operand *tmp = right;
6130 /* if result = right then exchange them */
6131 if (sameRegs (AOP (result), AOP (right)))
6133 operand *tmp = right;
6138 /* if right is bit then exchange them */
6139 if (AOP_TYPE (right) == AOP_CRY &&
6140 AOP_TYPE (left) != AOP_CRY)
6142 operand *tmp = right;
6146 if (AOP_TYPE (right) == AOP_LIT)
6147 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6149 size = AOP_SIZE (result);
6153 if (AOP_TYPE (left) == AOP_CRY)
6155 if (AOP_TYPE (right) == AOP_LIT)
6157 // c = bit | literal;
6160 // lit != 0 => result = 1
6161 if (AOP_TYPE (result) == AOP_CRY)
6164 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6166 continueIfTrue (ifx);
6169 emitcode ("setb", "c");
6173 // lit == 0 => result = left
6174 if (size && sameRegs (AOP (result), AOP (left)))
6176 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6181 if (AOP_TYPE (right) == AOP_CRY)
6184 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6185 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6190 symbol *tlbl = newiTempLabel (NULL);
6191 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6192 emitcode ("setb", "c");
6193 emitcode ("jb", "%s,%05d$",
6194 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6196 emitcode ("jnz", "%05d$", tlbl->key + 100);
6197 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6199 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6205 emitcode ("", "%05d$:", tlbl->key + 100);
6214 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6215 genIfxJump (ifx, "c", left, right, result);
6219 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6220 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6221 if ((AOP_TYPE (right) == AOP_LIT) &&
6222 (AOP_TYPE (result) == AOP_CRY) &&
6223 (AOP_TYPE (left) != AOP_CRY))
6229 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6231 continueIfTrue (ifx);
6236 // lit = 0, result = boolean(left)
6238 emitcode ("setb", "c");
6242 symbol *tlbl = newiTempLabel (NULL);
6243 emitcode ("jnz", "%05d$", tlbl->key + 100);
6245 emitcode ("", "%05d$:", tlbl->key + 100);
6249 genIfxJump (ifx, "a", left, right, result);
6257 /* if left is same as result */
6258 if (sameRegs (AOP (result), AOP (left)))
6260 for (; size--; offset++)
6262 if (AOP_TYPE (right) == AOP_LIT)
6264 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6267 /* dummy read of volatile operand */
6268 if (isOperandVolatile (left, FALSE))
6269 MOVA (aopGet (left, offset, FALSE, FALSE));
6273 else if (bytelit == 0x0FF)
6275 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6277 else if (IS_AOP_PREG (left))
6279 MOVA (aopGet (left, offset, FALSE, TRUE));
6280 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6281 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6285 emitcode ("orl", "%s,%s",
6286 aopGet (left, offset, FALSE, TRUE),
6287 aopGet (right, offset, FALSE, FALSE));
6292 if (AOP_TYPE (left) == AOP_ACC)
6295 emitcode("mov", "a,b");
6296 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6300 MOVA (aopGet (right, offset, FALSE, FALSE));
6301 if (IS_AOP_PREG (left))
6303 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6304 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6308 emitcode ("orl", "%s,a",
6309 aopGet (left, offset, FALSE, TRUE));
6317 // left & result in different registers
6318 if (AOP_TYPE (result) == AOP_CRY)
6321 // if(size), result in bit
6322 // if(!size && ifx), conditional oper: if(left | right)
6323 symbol *tlbl = newiTempLabel (NULL);
6324 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6326 emitcode ("setb", "c");
6329 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6331 emitcode("mov", "a,b");
6332 emitcode ("orl", "a,%s",
6333 aopGet (right, offset, FALSE, FALSE));
6335 MOVA (aopGet (right, offset, FALSE, FALSE));
6336 emitcode ("orl", "a,%s",
6337 aopGet (left, offset, FALSE, FALSE));
6339 emitcode ("jnz", "%05d$", tlbl->key + 100);
6345 emitcode ("", "%05d$:", tlbl->key + 100);
6349 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6351 emitcode ("", "%05d$:", tlbl->key + 100);
6355 for (; (size--); offset++)
6358 // result = left | right
6359 if (AOP_TYPE (right) == AOP_LIT)
6361 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6365 aopGet (left, offset, FALSE, FALSE),
6367 isOperandVolatile (result, FALSE));
6370 else if (bytelit == 0x0FF)
6372 /* dummy read of volatile operand */
6373 if (isOperandVolatile (left, FALSE))
6374 MOVA (aopGet (left, offset, FALSE, FALSE));
6375 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6379 // faster than result <- left, anl result,right
6380 // and better if result is SFR
6381 if (AOP_TYPE (left) == AOP_ACC)
6384 emitcode("mov", "a,b");
6385 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6389 MOVA (aopGet (right, offset, FALSE, FALSE));
6390 emitcode ("orl", "a,%s",
6391 aopGet (left, offset, FALSE, FALSE));
6393 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6399 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6400 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6401 freeAsmop (result, NULL, ic, TRUE);
6404 /*-----------------------------------------------------------------*/
6405 /* genXor - code for xclusive or */
6406 /*-----------------------------------------------------------------*/
6408 genXor (iCode * ic, iCode * ifx)
6410 operand *left, *right, *result;
6411 int size, offset = 0;
6412 unsigned long lit = 0L;
6415 D(emitcode ("; genXor",""));
6417 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6418 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6419 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6422 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6424 AOP_TYPE (left), AOP_TYPE (right));
6425 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6427 AOP_SIZE (left), AOP_SIZE (right));
6430 /* if left is a literal & right is not ||
6431 if left needs acc & right does not */
6432 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6433 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6435 operand *tmp = right;
6440 /* if result = right then exchange them */
6441 if (sameRegs (AOP (result), AOP (right)))
6443 operand *tmp = right;
6448 /* if right is bit then exchange them */
6449 if (AOP_TYPE (right) == AOP_CRY &&
6450 AOP_TYPE (left) != AOP_CRY)
6452 operand *tmp = right;
6456 if (AOP_TYPE (right) == AOP_LIT)
6457 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6459 size = AOP_SIZE (result);
6463 if (AOP_TYPE (left) == AOP_CRY)
6465 if (AOP_TYPE (right) == AOP_LIT)
6467 // c = bit & literal;
6470 // lit>>1 != 0 => result = 1
6471 if (AOP_TYPE (result) == AOP_CRY)
6474 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6476 continueIfTrue (ifx);
6479 emitcode ("setb", "c");
6486 // lit == 0, result = left
6487 if (size && sameRegs (AOP (result), AOP (left)))
6489 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6493 // lit == 1, result = not(left)
6494 if (size && sameRegs (AOP (result), AOP (left)))
6496 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6501 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6502 emitcode ("cpl", "c");
6511 symbol *tlbl = newiTempLabel (NULL);
6512 if (AOP_TYPE (right) == AOP_CRY)
6515 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6519 int sizer = AOP_SIZE (right);
6521 // if val>>1 != 0, result = 1
6522 emitcode ("setb", "c");
6525 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6527 // test the msb of the lsb
6528 emitcode ("anl", "a,#0xfe");
6529 emitcode ("jnz", "%05d$", tlbl->key + 100);
6533 emitcode ("rrc", "a");
6535 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6536 emitcode ("cpl", "c");
6537 emitcode ("", "%05d$:", (tlbl->key + 100));
6544 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6545 genIfxJump (ifx, "c", left, right, result);
6549 /* if left is same as result */
6550 if (sameRegs (AOP (result), AOP (left)))
6552 for (; size--; offset++)
6554 if (AOP_TYPE (right) == AOP_LIT)
6556 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6559 /* dummy read of volatile operand */
6560 if (isOperandVolatile (left, FALSE))
6561 MOVA (aopGet (left, offset, FALSE, FALSE));
6565 else if (IS_AOP_PREG (left))
6567 MOVA (aopGet (left, offset, FALSE, TRUE));
6568 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6569 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6573 emitcode ("xrl", "%s,%s",
6574 aopGet (left, offset, FALSE, TRUE),
6575 aopGet (right, offset, FALSE, FALSE));
6580 if (AOP_TYPE (left) == AOP_ACC)
6583 emitcode("mov", "a,b");
6584 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6588 MOVA (aopGet (right, offset, FALSE, FALSE));
6589 if (IS_AOP_PREG (left))
6591 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6592 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6595 emitcode ("xrl", "%s,a",
6596 aopGet (left, offset, FALSE, TRUE));
6603 // left & result in different registers
6604 if (AOP_TYPE (result) == AOP_CRY)
6607 // if(size), result in bit
6608 // if(!size && ifx), conditional oper: if(left ^ right)
6609 symbol *tlbl = newiTempLabel (NULL);
6610 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6612 emitcode ("setb", "c");
6615 if ((AOP_TYPE (right) == AOP_LIT) &&
6616 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6618 MOVA (aopGet (left, offset, FALSE, FALSE));
6622 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6624 emitcode("mov", "a,b");
6625 emitcode ("xrl", "a,%s",
6626 aopGet (right, offset, FALSE, FALSE));
6628 MOVA (aopGet (right, offset, FALSE, FALSE));
6629 emitcode ("xrl", "a,%s",
6630 aopGet (left, offset, FALSE, FALSE));
6633 emitcode ("jnz", "%05d$", tlbl->key + 100);
6639 emitcode ("", "%05d$:", tlbl->key + 100);
6643 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6647 for (; (size--); offset++)
6650 // result = left & right
6651 if (AOP_TYPE (right) == AOP_LIT)
6653 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6657 aopGet (left, offset, FALSE, FALSE),
6659 isOperandVolatile (result, FALSE));
6663 // faster than result <- left, anl result,right
6664 // and better if result is SFR
6665 if (AOP_TYPE (left) == AOP_ACC)
6668 emitcode("mov", "a,b");
6669 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6673 MOVA (aopGet (right, offset, FALSE, FALSE));
6674 emitcode ("xrl", "a,%s",
6675 aopGet (left, offset, FALSE, TRUE));
6677 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6683 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6684 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6685 freeAsmop (result, NULL, ic, TRUE);
6688 /*-----------------------------------------------------------------*/
6689 /* genInline - write the inline code out */
6690 /*-----------------------------------------------------------------*/
6692 genInline (iCode * ic)
6694 char *buffer, *bp, *bp1;
6696 D(emitcode ("; genInline",""));
6698 _G.inLine += (!options.asmpeep);
6700 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6701 strcpy (buffer, IC_INLINE (ic));
6703 /* emit each line as a code */
6714 /* Add \n for labels, not dirs such as c:\mydir */
6715 if ( (*bp == ':') && (isspace(bp[1])) )
6729 /* emitcode("",buffer); */
6730 _G.inLine -= (!options.asmpeep);
6733 /*-----------------------------------------------------------------*/
6734 /* genRRC - rotate right with carry */
6735 /*-----------------------------------------------------------------*/
6739 operand *left, *result;
6740 int size, offset = 0;
6743 D(emitcode ("; genRRC",""));
6745 /* rotate right with carry */
6746 left = IC_LEFT (ic);
6747 result = IC_RESULT (ic);
6748 aopOp (left, ic, FALSE);
6749 aopOp (result, ic, FALSE);
6751 /* move it to the result */
6752 size = AOP_SIZE (result);
6754 if (size == 1) { /* special case for 1 byte */
6755 l = aopGet (left, offset, FALSE, FALSE);
6757 emitcode ("rr", "a");
6760 /* no need to clear carry, bit7 will be written later */
6763 l = aopGet (left, offset, FALSE, FALSE);
6765 emitcode ("rrc", "a");
6766 if (AOP_SIZE (result) > 1)
6767 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
6769 /* now we need to put the carry into the
6770 highest order byte of the result */
6771 if (AOP_SIZE (result) > 1)
6773 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
6776 emitcode ("mov", "acc.7,c");
6778 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6779 freeAsmop (left, NULL, ic, TRUE);
6780 freeAsmop (result, NULL, ic, TRUE);
6783 /*-----------------------------------------------------------------*/
6784 /* genRLC - generate code for rotate left with carry */
6785 /*-----------------------------------------------------------------*/
6789 operand *left, *result;
6790 int size, offset = 0;
6793 D(emitcode ("; genRLC",""));
6795 /* rotate right with carry */
6796 left = IC_LEFT (ic);
6797 result = IC_RESULT (ic);
6798 aopOp (left, ic, FALSE);
6799 aopOp (result, ic, FALSE);
6801 /* move it to the result */
6802 size = AOP_SIZE (result);
6806 l = aopGet (left, offset, FALSE, FALSE);
6808 if (size == 0) { /* special case for 1 byte */
6812 emitcode("rlc","a"); /* bit0 will be written later */
6813 if (AOP_SIZE (result) > 1)
6814 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6817 l = aopGet (left, offset, FALSE, FALSE);
6819 emitcode ("rlc", "a");
6820 if (AOP_SIZE (result) > 1)
6821 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
6824 /* now we need to put the carry into the
6825 highest order byte of the result */
6826 if (AOP_SIZE (result) > 1)
6828 l = aopGet (result, 0, FALSE, FALSE);
6831 emitcode ("mov", "acc.0,c");
6833 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6834 freeAsmop (left, NULL, ic, TRUE);
6835 freeAsmop (result, NULL, ic, TRUE);
6838 /*-----------------------------------------------------------------*/
6839 /* genGetHbit - generates code get highest order bit */
6840 /*-----------------------------------------------------------------*/
6842 genGetHbit (iCode * ic)
6844 operand *left, *result;
6846 D(emitcode ("; genGetHbit",""));
6848 left = IC_LEFT (ic);
6849 result = IC_RESULT (ic);
6850 aopOp (left, ic, FALSE);
6851 aopOp (result, ic, FALSE);
6853 /* get the highest order byte into a */
6854 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
6855 if (AOP_TYPE (result) == AOP_CRY)
6857 emitcode ("rlc", "a");
6862 emitcode ("rl", "a");
6863 emitcode ("anl", "a,#0x01");
6868 freeAsmop (left, NULL, ic, TRUE);
6869 freeAsmop (result, NULL, ic, TRUE);
6872 /*-----------------------------------------------------------------*/
6873 /* genSwap - generates code to swap nibbles or bytes */
6874 /*-----------------------------------------------------------------*/
6876 genSwap (iCode * ic)
6878 operand *left, *result;
6880 D(emitcode ("; genSwap",""));
6882 left = IC_LEFT (ic);
6883 result = IC_RESULT (ic);
6884 aopOp (left, ic, FALSE);
6885 aopOp (result, ic, FALSE);
6887 switch (AOP_SIZE (left))
6889 case 1: /* swap nibbles in byte */
6890 MOVA (aopGet (left, 0, FALSE, FALSE));
6891 emitcode ("swap", "a");
6892 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6894 case 2: /* swap bytes in word */
6895 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6897 MOVA (aopGet (left, 0, FALSE, FALSE));
6898 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6899 0, isOperandVolatile (result, FALSE));
6900 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
6902 else if (operandsEqu (left, result))
6905 bool pushedB = FALSE, leftInB = FALSE;
6907 MOVA (aopGet (left, 0, FALSE, FALSE));
6908 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
6911 emitcode ("mov", "b,a");
6915 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6916 0, isOperandVolatile (result, FALSE));
6917 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
6924 aopPut (result, aopGet (left, 1, FALSE, FALSE),
6925 0, isOperandVolatile (result, FALSE));
6926 aopPut (result, aopGet (left, 0, FALSE, FALSE),
6927 1, isOperandVolatile (result, FALSE));
6931 wassertl(FALSE, "unsupported SWAP operand size");
6934 freeAsmop (left, NULL, ic, TRUE);
6935 freeAsmop (result, NULL, ic, TRUE);
6939 /*-----------------------------------------------------------------*/
6940 /* AccRol - rotate left accumulator by known count */
6941 /*-----------------------------------------------------------------*/
6943 AccRol (int shCount)
6945 shCount &= 0x0007; // shCount : 0..7
6952 emitcode ("rl", "a");
6955 emitcode ("rl", "a");
6956 emitcode ("rl", "a");
6959 emitcode ("swap", "a");
6960 emitcode ("rr", "a");
6963 emitcode ("swap", "a");
6966 emitcode ("swap", "a");
6967 emitcode ("rl", "a");
6970 emitcode ("rr", "a");
6971 emitcode ("rr", "a");
6974 emitcode ("rr", "a");
6979 /*-----------------------------------------------------------------*/
6980 /* AccLsh - left shift accumulator by known count */
6981 /*-----------------------------------------------------------------*/
6983 AccLsh (int shCount)
6988 emitcode ("add", "a,acc");
6989 else if (shCount == 2)
6991 emitcode ("add", "a,acc");
6992 emitcode ("add", "a,acc");
6996 /* rotate left accumulator */
6998 /* and kill the lower order bits */
6999 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7004 /*-----------------------------------------------------------------*/
7005 /* AccRsh - right shift accumulator by known count */
7006 /*-----------------------------------------------------------------*/
7008 AccRsh (int shCount)
7015 emitcode ("rrc", "a");
7019 /* rotate right accumulator */
7020 AccRol (8 - shCount);
7021 /* and kill the higher order bits */
7022 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7027 /*-----------------------------------------------------------------*/
7028 /* AccSRsh - signed right shift accumulator by known count */
7029 /*-----------------------------------------------------------------*/
7031 AccSRsh (int shCount)
7038 emitcode ("mov", "c,acc.7");
7039 emitcode ("rrc", "a");
7041 else if (shCount == 2)
7043 emitcode ("mov", "c,acc.7");
7044 emitcode ("rrc", "a");
7045 emitcode ("mov", "c,acc.7");
7046 emitcode ("rrc", "a");
7050 tlbl = newiTempLabel (NULL);
7051 /* rotate right accumulator */
7052 AccRol (8 - shCount);
7053 /* and kill the higher order bits */
7054 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7055 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7056 emitcode ("orl", "a,#0x%02x",
7057 (unsigned char) ~SRMask[shCount]);
7058 emitcode ("", "%05d$:", tlbl->key + 100);
7063 /*-----------------------------------------------------------------*/
7064 /* shiftR1Left2Result - shift right one byte from left to result */
7065 /*-----------------------------------------------------------------*/
7067 shiftR1Left2Result (operand * left, int offl,
7068 operand * result, int offr,
7069 int shCount, int sign)
7071 MOVA (aopGet (left, offl, FALSE, FALSE));
7072 /* shift right accumulator */
7077 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7080 /*-----------------------------------------------------------------*/
7081 /* shiftL1Left2Result - shift left one byte from left to result */
7082 /*-----------------------------------------------------------------*/
7084 shiftL1Left2Result (operand * left, int offl,
7085 operand * result, int offr, int shCount)
7088 l = aopGet (left, offl, FALSE, FALSE);
7090 /* shift left accumulator */
7092 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7095 /*-----------------------------------------------------------------*/
7096 /* movLeft2Result - move byte from left to result */
7097 /*-----------------------------------------------------------------*/
7099 movLeft2Result (operand * left, int offl,
7100 operand * result, int offr, int sign)
7103 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7105 l = aopGet (left, offl, FALSE, FALSE);
7107 if (*l == '@' && (IS_AOP_PREG (result)))
7109 emitcode ("mov", "a,%s", l);
7110 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7115 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7118 /* MSB sign in acc.7 ! */
7119 if (getDataSize (left) == offl + 1)
7121 emitcode ("mov", "a,%s", l);
7122 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7129 /*-----------------------------------------------------------------*/
7130 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7131 /*-----------------------------------------------------------------*/
7135 emitcode ("rrc", "a");
7136 emitcode ("xch", "a,%s", x);
7137 emitcode ("rrc", "a");
7138 emitcode ("xch", "a,%s", x);
7141 /*-----------------------------------------------------------------*/
7142 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7143 /*-----------------------------------------------------------------*/
7147 emitcode ("xch", "a,%s", x);
7148 emitcode ("rlc", "a");
7149 emitcode ("xch", "a,%s", x);
7150 emitcode ("rlc", "a");
7153 /*-----------------------------------------------------------------*/
7154 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7155 /*-----------------------------------------------------------------*/
7159 emitcode ("xch", "a,%s", x);
7160 emitcode ("add", "a,acc");
7161 emitcode ("xch", "a,%s", x);
7162 emitcode ("rlc", "a");
7165 /*-----------------------------------------------------------------*/
7166 /* AccAXLsh - left shift a:x by known count (0..7) */
7167 /*-----------------------------------------------------------------*/
7169 AccAXLsh (char *x, int shCount)
7184 case 5: // AAAAABBB:CCCCCDDD
7186 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7188 emitcode ("anl", "a,#0x%02x",
7189 SLMask[shCount]); // BBB00000:CCCCCDDD
7191 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7193 AccRol (shCount); // DDDCCCCC:BBB00000
7195 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7197 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7199 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7201 emitcode ("anl", "a,#0x%02x",
7202 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7204 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7206 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7209 case 6: // AAAAAABB:CCCCCCDD
7210 emitcode ("anl", "a,#0x%02x",
7211 SRMask[shCount]); // 000000BB:CCCCCCDD
7212 emitcode ("mov", "c,acc.0"); // c = B
7213 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7215 AccAXRrl1 (x); // BCCCCCCD:D000000B
7216 AccAXRrl1 (x); // BBCCCCCC:DD000000
7218 emitcode("rrc","a");
7219 emitcode("xch","a,%s", x);
7220 emitcode("rrc","a");
7221 emitcode("mov","c,acc.0"); //<< get correct bit
7222 emitcode("xch","a,%s", x);
7224 emitcode("rrc","a");
7225 emitcode("xch","a,%s", x);
7226 emitcode("rrc","a");
7227 emitcode("xch","a,%s", x);
7230 case 7: // a:x <<= 7
7232 emitcode ("anl", "a,#0x%02x",
7233 SRMask[shCount]); // 0000000B:CCCCCCCD
7235 emitcode ("mov", "c,acc.0"); // c = B
7237 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7239 AccAXRrl1 (x); // BCCCCCCC:D0000000
7247 /*-----------------------------------------------------------------*/
7248 /* AccAXRsh - right shift a:x known count (0..7) */
7249 /*-----------------------------------------------------------------*/
7251 AccAXRsh (char *x, int shCount)
7259 AccAXRrl1 (x); // 0->a:x
7264 AccAXRrl1 (x); // 0->a:x
7267 AccAXRrl1 (x); // 0->a:x
7272 case 5: // AAAAABBB:CCCCCDDD = a:x
7274 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7276 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7278 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7280 emitcode ("anl", "a,#0x%02x",
7281 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7283 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7285 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7287 emitcode ("anl", "a,#0x%02x",
7288 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7290 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7292 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7294 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7297 case 6: // AABBBBBB:CCDDDDDD
7299 emitcode ("mov", "c,acc.7");
7300 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7302 emitcode ("mov", "c,acc.7");
7303 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7305 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7307 emitcode ("anl", "a,#0x%02x",
7308 SRMask[shCount]); // 000000AA:BBBBBBCC
7311 case 7: // ABBBBBBB:CDDDDDDD
7313 emitcode ("mov", "c,acc.7"); // c = A
7315 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7317 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7319 emitcode ("anl", "a,#0x%02x",
7320 SRMask[shCount]); // 0000000A:BBBBBBBC
7328 /*-----------------------------------------------------------------*/
7329 /* AccAXRshS - right shift signed a:x known count (0..7) */
7330 /*-----------------------------------------------------------------*/
7332 AccAXRshS (char *x, int shCount)
7340 emitcode ("mov", "c,acc.7");
7341 AccAXRrl1 (x); // s->a:x
7345 emitcode ("mov", "c,acc.7");
7346 AccAXRrl1 (x); // s->a:x
7348 emitcode ("mov", "c,acc.7");
7349 AccAXRrl1 (x); // s->a:x
7354 case 5: // AAAAABBB:CCCCCDDD = a:x
7356 tlbl = newiTempLabel (NULL);
7357 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7359 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7361 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7363 emitcode ("anl", "a,#0x%02x",
7364 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7366 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7368 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7370 emitcode ("anl", "a,#0x%02x",
7371 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7373 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7375 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7377 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7379 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7380 emitcode ("orl", "a,#0x%02x",
7381 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7383 emitcode ("", "%05d$:", tlbl->key + 100);
7384 break; // SSSSAAAA:BBBCCCCC
7386 case 6: // AABBBBBB:CCDDDDDD
7388 tlbl = newiTempLabel (NULL);
7389 emitcode ("mov", "c,acc.7");
7390 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7392 emitcode ("mov", "c,acc.7");
7393 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7395 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7397 emitcode ("anl", "a,#0x%02x",
7398 SRMask[shCount]); // 000000AA:BBBBBBCC
7400 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7401 emitcode ("orl", "a,#0x%02x",
7402 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7404 emitcode ("", "%05d$:", tlbl->key + 100);
7406 case 7: // ABBBBBBB:CDDDDDDD
7408 tlbl = newiTempLabel (NULL);
7409 emitcode ("mov", "c,acc.7"); // c = A
7411 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7413 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7415 emitcode ("anl", "a,#0x%02x",
7416 SRMask[shCount]); // 0000000A:BBBBBBBC
7418 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7419 emitcode ("orl", "a,#0x%02x",
7420 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7422 emitcode ("", "%05d$:", tlbl->key + 100);
7429 /*-----------------------------------------------------------------*/
7430 /* shiftL2Left2Result - shift left two bytes from left to result */
7431 /*-----------------------------------------------------------------*/
7433 shiftL2Left2Result (operand * left, int offl,
7434 operand * result, int offr, int shCount)
7436 if (sameRegs (AOP (result), AOP (left)) &&
7437 ((offl + MSB16) == offr))
7439 /* don't crash result[offr] */
7440 MOVA (aopGet (left, offl, FALSE, FALSE));
7441 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7445 movLeft2Result (left, offl, result, offr, 0);
7446 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7448 /* ax << shCount (x = lsb(result)) */
7449 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7450 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7454 /*-----------------------------------------------------------------*/
7455 /* shiftR2Left2Result - shift right two bytes from left to result */
7456 /*-----------------------------------------------------------------*/
7458 shiftR2Left2Result (operand * left, int offl,
7459 operand * result, int offr,
7460 int shCount, int sign)
7462 if (sameRegs (AOP (result), AOP (left)) &&
7463 ((offl + MSB16) == offr))
7465 /* don't crash result[offr] */
7466 MOVA (aopGet (left, offl, FALSE, FALSE));
7467 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7471 movLeft2Result (left, offl, result, offr, 0);
7472 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7474 /* a:x >> shCount (x = lsb(result)) */
7476 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7478 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7479 if (getDataSize (result) > 1)
7480 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7483 /*-----------------------------------------------------------------*/
7484 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7485 /*-----------------------------------------------------------------*/
7487 shiftLLeftOrResult (operand * left, int offl,
7488 operand * result, int offr, int shCount)
7490 MOVA (aopGet (left, offl, FALSE, FALSE));
7491 /* shift left accumulator */
7493 /* or with result */
7494 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7495 /* back to result */
7496 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7499 /*-----------------------------------------------------------------*/
7500 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7501 /*-----------------------------------------------------------------*/
7503 shiftRLeftOrResult (operand * left, int offl,
7504 operand * result, int offr, int shCount)
7506 MOVA (aopGet (left, offl, FALSE, FALSE));
7507 /* shift right accumulator */
7509 /* or with result */
7510 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7511 /* back to result */
7512 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7515 /*-----------------------------------------------------------------*/
7516 /* genlshOne - left shift a one byte quantity by known count */
7517 /*-----------------------------------------------------------------*/
7519 genlshOne (operand * result, operand * left, int shCount)
7521 D(emitcode ("; genlshOne",""));
7523 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7526 /*-----------------------------------------------------------------*/
7527 /* genlshTwo - left shift two bytes by known amount != 0 */
7528 /*-----------------------------------------------------------------*/
7530 genlshTwo (operand * result, operand * left, int shCount)
7534 D(emitcode ("; genlshTwo",""));
7536 size = getDataSize (result);
7538 /* if shCount >= 8 */
7546 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7548 movLeft2Result (left, LSB, result, MSB16, 0);
7550 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7553 /* 1 <= shCount <= 7 */
7557 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7559 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7563 /*-----------------------------------------------------------------*/
7564 /* shiftLLong - shift left one long from left to result */
7565 /* offl = LSB or MSB16 */
7566 /*-----------------------------------------------------------------*/
7568 shiftLLong (operand * left, operand * result, int offr)
7571 int size = AOP_SIZE (result);
7573 if (size >= LSB + offr)
7575 l = aopGet (left, LSB, FALSE, FALSE);
7577 emitcode ("add", "a,acc");
7578 if (sameRegs (AOP (left), AOP (result)) &&
7579 size >= MSB16 + offr && offr != LSB)
7580 emitcode ("xch", "a,%s",
7581 aopGet (left, LSB + offr, FALSE, FALSE));
7583 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7586 if (size >= MSB16 + offr)
7588 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7590 l = aopGet (left, MSB16, FALSE, FALSE);
7593 emitcode ("rlc", "a");
7594 if (sameRegs (AOP (left), AOP (result)) &&
7595 size >= MSB24 + offr && offr != LSB)
7596 emitcode ("xch", "a,%s",
7597 aopGet (left, MSB16 + offr, FALSE, FALSE));
7599 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7602 if (size >= MSB24 + offr)
7604 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7606 l = aopGet (left, MSB24, FALSE, FALSE);
7609 emitcode ("rlc", "a");
7610 if (sameRegs (AOP (left), AOP (result)) &&
7611 size >= MSB32 + offr && offr != LSB)
7612 emitcode ("xch", "a,%s",
7613 aopGet (left, MSB24 + offr, FALSE, FALSE));
7615 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7618 if (size > MSB32 + offr)
7620 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7622 l = aopGet (left, MSB32, FALSE, FALSE);
7625 emitcode ("rlc", "a");
7626 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7629 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7632 /*-----------------------------------------------------------------*/
7633 /* genlshFour - shift four byte by a known amount != 0 */
7634 /*-----------------------------------------------------------------*/
7636 genlshFour (operand * result, operand * left, int shCount)
7640 D(emitcode ("; genlshFour",""));
7642 size = AOP_SIZE (result);
7644 /* if shifting more that 3 bytes */
7649 /* lowest order of left goes to the highest
7650 order of the destination */
7651 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7653 movLeft2Result (left, LSB, result, MSB32, 0);
7654 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7655 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7656 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
7660 /* more than two bytes */
7661 else if (shCount >= 16)
7663 /* lower order two bytes goes to higher order two bytes */
7665 /* if some more remaining */
7667 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7670 movLeft2Result (left, MSB16, result, MSB32, 0);
7671 movLeft2Result (left, LSB, result, MSB24, 0);
7673 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
7674 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7678 /* if more than 1 byte */
7679 else if (shCount >= 8)
7681 /* lower order three bytes goes to higher order three bytes */
7686 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7688 movLeft2Result (left, LSB, result, MSB16, 0);
7694 movLeft2Result (left, MSB24, result, MSB32, 0);
7695 movLeft2Result (left, MSB16, result, MSB24, 0);
7696 movLeft2Result (left, LSB, result, MSB16, 0);
7697 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7699 else if (shCount == 1)
7700 shiftLLong (left, result, MSB16);
7703 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7704 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7705 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7706 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7711 /* 1 <= shCount <= 7 */
7712 else if (shCount <= 2)
7714 shiftLLong (left, result, LSB);
7716 shiftLLong (result, result, LSB);
7718 /* 3 <= shCount <= 7, optimize */
7721 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7722 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7723 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7727 /*-----------------------------------------------------------------*/
7728 /* genLeftShiftLiteral - left shifting by known count */
7729 /*-----------------------------------------------------------------*/
7731 genLeftShiftLiteral (operand * left,
7736 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7739 D(emitcode ("; genLeftShiftLiteral",""));
7741 freeAsmop (right, NULL, ic, TRUE);
7743 aopOp (left, ic, FALSE);
7744 aopOp (result, ic, FALSE);
7746 size = getSize (operandType (result));
7749 emitcode ("; shift left ", "result %d, left %d", size,
7753 /* I suppose that the left size >= result size */
7758 movLeft2Result (left, size, result, size, 0);
7762 else if (shCount >= (size * 8))
7764 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
7770 genlshOne (result, left, shCount);
7774 genlshTwo (result, left, shCount);
7778 genlshFour (result, left, shCount);
7781 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7782 "*** ack! mystery literal shift!\n");
7786 freeAsmop (left, NULL, ic, TRUE);
7787 freeAsmop (result, NULL, ic, TRUE);
7790 /*-----------------------------------------------------------------*/
7791 /* genLeftShift - generates code for left shifting */
7792 /*-----------------------------------------------------------------*/
7794 genLeftShift (iCode * ic)
7796 operand *left, *right, *result;
7799 symbol *tlbl, *tlbl1;
7802 D(emitcode ("; genLeftShift",""));
7804 right = IC_RIGHT (ic);
7805 left = IC_LEFT (ic);
7806 result = IC_RESULT (ic);
7808 aopOp (right, ic, FALSE);
7810 /* if the shift count is known then do it
7811 as efficiently as possible */
7812 if (AOP_TYPE (right) == AOP_LIT)
7814 genLeftShiftLiteral (left, right, result, ic);
7818 /* shift count is unknown then we have to form
7819 a loop get the loop count in B : Note: we take
7820 only the lower order byte since shifting
7821 more that 32 bits make no sense anyway, ( the
7822 largest size of an object can be only 32 bits ) */
7825 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
7826 emitcode ("inc", "b");
7827 freeAsmop (right, NULL, ic, TRUE);
7828 aopOp (left, ic, FALSE);
7829 aopOp (result, ic, FALSE);
7831 /* now move the left to the result if they are not the same */
7832 if (!sameRegs (AOP (left), AOP (result)) &&
7833 AOP_SIZE (result) > 1)
7836 size = AOP_SIZE (result);
7840 l = aopGet (left, offset, FALSE, TRUE);
7841 if (*l == '@' && (IS_AOP_PREG (result)))
7844 emitcode ("mov", "a,%s", l);
7845 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7848 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
7853 tlbl = newiTempLabel (NULL);
7854 size = AOP_SIZE (result);
7856 tlbl1 = newiTempLabel (NULL);
7858 /* if it is only one byte then */
7861 symbol *tlbl1 = newiTempLabel (NULL);
7863 l = aopGet (left, 0, FALSE, FALSE);
7865 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7866 emitcode ("", "%05d$:", tlbl->key + 100);
7867 emitcode ("add", "a,acc");
7868 emitcode ("", "%05d$:", tlbl1->key + 100);
7869 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7871 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7875 reAdjustPreg (AOP (result));
7877 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7878 emitcode ("", "%05d$:", tlbl->key + 100);
7879 l = aopGet (result, offset, FALSE, FALSE);
7881 emitcode ("add", "a,acc");
7882 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7885 l = aopGet (result, offset, FALSE, FALSE);
7887 emitcode ("rlc", "a");
7888 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7890 reAdjustPreg (AOP (result));
7892 emitcode ("", "%05d$:", tlbl1->key + 100);
7893 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7896 freeAsmop (left, NULL, ic, TRUE);
7897 freeAsmop (result, NULL, ic, TRUE);
7900 /*-----------------------------------------------------------------*/
7901 /* genrshOne - right shift a one byte quantity by known count */
7902 /*-----------------------------------------------------------------*/
7904 genrshOne (operand * result, operand * left,
7905 int shCount, int sign)
7907 D(emitcode ("; genrshOne",""));
7909 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7912 /*-----------------------------------------------------------------*/
7913 /* genrshTwo - right shift two bytes by known amount != 0 */
7914 /*-----------------------------------------------------------------*/
7916 genrshTwo (operand * result, operand * left,
7917 int shCount, int sign)
7919 D(emitcode ("; genrshTwo",""));
7921 /* if shCount >= 8 */
7926 shiftR1Left2Result (left, MSB16, result, LSB,
7929 movLeft2Result (left, MSB16, result, LSB, sign);
7930 addSign (result, MSB16, sign);
7933 /* 1 <= shCount <= 7 */
7935 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7938 /*-----------------------------------------------------------------*/
7939 /* shiftRLong - shift right one long from left to result */
7940 /* offl = LSB or MSB16 */
7941 /*-----------------------------------------------------------------*/
7943 shiftRLong (operand * left, int offl,
7944 operand * result, int sign)
7946 int isSameRegs=sameRegs(AOP(left),AOP(result));
7948 if (isSameRegs && offl>1) {
7949 // we are in big trouble, but this shouldn't happen
7950 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7953 MOVA (aopGet (left, MSB32, FALSE, FALSE));
7958 emitcode ("rlc", "a");
7959 emitcode ("subb", "a,acc");
7961 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
7963 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
7964 MOVA (aopGet (left, MSB32, FALSE, FALSE));
7967 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
7972 emitcode ("clr", "c");
7974 emitcode ("mov", "c,acc.7");
7977 emitcode ("rrc", "a");
7979 if (isSameRegs && offl==MSB16) {
7980 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
7982 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
7983 MOVA (aopGet (left, MSB24, FALSE, FALSE));
7986 emitcode ("rrc", "a");
7987 if (isSameRegs && offl==1) {
7988 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
7990 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
7991 MOVA (aopGet (left, MSB16, FALSE, FALSE));
7993 emitcode ("rrc", "a");
7994 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7998 MOVA (aopGet (left, LSB, FALSE, FALSE));
7999 emitcode ("rrc", "a");
8000 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8004 /*-----------------------------------------------------------------*/
8005 /* genrshFour - shift four byte by a known amount != 0 */
8006 /*-----------------------------------------------------------------*/
8008 genrshFour (operand * result, operand * left,
8009 int shCount, int sign)
8011 D(emitcode ("; genrshFour",""));
8013 /* if shifting more that 3 bytes */
8018 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8020 movLeft2Result (left, MSB32, result, LSB, sign);
8021 addSign (result, MSB16, sign);
8023 else if (shCount >= 16)
8027 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8030 movLeft2Result (left, MSB24, result, LSB, 0);
8031 movLeft2Result (left, MSB32, result, MSB16, sign);
8033 addSign (result, MSB24, sign);
8035 else if (shCount >= 8)
8039 shiftRLong (left, MSB16, result, sign);
8040 else if (shCount == 0)
8042 movLeft2Result (left, MSB16, result, LSB, 0);
8043 movLeft2Result (left, MSB24, result, MSB16, 0);
8044 movLeft2Result (left, MSB32, result, MSB24, sign);
8045 addSign (result, MSB32, sign);
8049 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8050 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8051 /* the last shift is signed */
8052 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8053 addSign (result, MSB32, sign);
8057 { /* 1 <= shCount <= 7 */
8060 shiftRLong (left, LSB, result, sign);
8062 shiftRLong (result, LSB, result, sign);
8066 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8067 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8068 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8073 /*-----------------------------------------------------------------*/
8074 /* genRightShiftLiteral - right shifting by known count */
8075 /*-----------------------------------------------------------------*/
8077 genRightShiftLiteral (operand * left,
8083 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8086 D(emitcode ("; genRightShiftLiteral",""));
8088 freeAsmop (right, NULL, ic, TRUE);
8090 aopOp (left, ic, FALSE);
8091 aopOp (result, ic, FALSE);
8094 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8098 size = getDataSize (left);
8099 /* test the LEFT size !!! */
8101 /* I suppose that the left size >= result size */
8104 size = getDataSize (result);
8106 movLeft2Result (left, size, result, size, 0);
8109 else if (shCount >= (size * 8))
8112 /* get sign in acc.7 */
8113 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8115 addSign (result, LSB, sign);
8122 genrshOne (result, left, shCount, sign);
8126 genrshTwo (result, left, shCount, sign);
8130 genrshFour (result, left, shCount, sign);
8136 freeAsmop (left, NULL, ic, TRUE);
8137 freeAsmop (result, NULL, ic, TRUE);
8140 /*-----------------------------------------------------------------*/
8141 /* genSignedRightShift - right shift of signed number */
8142 /*-----------------------------------------------------------------*/
8144 genSignedRightShift (iCode * ic)
8146 operand *right, *left, *result;
8149 symbol *tlbl, *tlbl1;
8152 D(emitcode ("; genSignedRightShift",""));
8154 /* we do it the hard way put the shift count in b
8155 and loop thru preserving the sign */
8157 right = IC_RIGHT (ic);
8158 left = IC_LEFT (ic);
8159 result = IC_RESULT (ic);
8161 aopOp (right, ic, FALSE);
8164 if (AOP_TYPE (right) == AOP_LIT)
8166 genRightShiftLiteral (left, right, result, ic, 1);
8169 /* shift count is unknown then we have to form
8170 a loop get the loop count in B : Note: we take
8171 only the lower order byte since shifting
8172 more that 32 bits make no sense anyway, ( the
8173 largest size of an object can be only 32 bits ) */
8176 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8177 emitcode ("inc", "b");
8178 freeAsmop (right, NULL, ic, TRUE);
8179 aopOp (left, ic, FALSE);
8180 aopOp (result, ic, FALSE);
8182 /* now move the left to the result if they are not the
8184 if (!sameRegs (AOP (left), AOP (result)) &&
8185 AOP_SIZE (result) > 1)
8188 size = AOP_SIZE (result);
8192 l = aopGet (left, offset, FALSE, TRUE);
8193 if (*l == '@' && IS_AOP_PREG (result))
8196 emitcode ("mov", "a,%s", l);
8197 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8200 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8205 /* mov the highest order bit to OVR */
8206 tlbl = newiTempLabel (NULL);
8207 tlbl1 = newiTempLabel (NULL);
8209 size = AOP_SIZE (result);
8211 MOVA (aopGet (left, offset, FALSE, FALSE));
8212 emitcode ("rlc", "a");
8213 emitcode ("mov", "ov,c");
8214 /* if it is only one byte then */
8217 l = aopGet (left, 0, FALSE, FALSE);
8219 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8220 emitcode ("", "%05d$:", tlbl->key + 100);
8221 emitcode ("mov", "c,ov");
8222 emitcode ("rrc", "a");
8223 emitcode ("", "%05d$:", tlbl1->key + 100);
8224 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8226 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8230 reAdjustPreg (AOP (result));
8231 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8232 emitcode ("", "%05d$:", tlbl->key + 100);
8233 emitcode ("mov", "c,ov");
8236 l = aopGet (result, offset, FALSE, FALSE);
8238 emitcode ("rrc", "a");
8239 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8241 reAdjustPreg (AOP (result));
8242 emitcode ("", "%05d$:", tlbl1->key + 100);
8243 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8247 freeAsmop (left, NULL, ic, TRUE);
8248 freeAsmop (result, NULL, ic, TRUE);
8251 /*-----------------------------------------------------------------*/
8252 /* genRightShift - generate code for right shifting */
8253 /*-----------------------------------------------------------------*/
8255 genRightShift (iCode * ic)
8257 operand *right, *left, *result;
8261 symbol *tlbl, *tlbl1;
8264 D(emitcode ("; genRightShift",""));
8266 /* if signed then we do it the hard way preserve the
8267 sign bit moving it inwards */
8268 letype = getSpec (operandType (IC_LEFT (ic)));
8270 if (!SPEC_USIGN (letype))
8272 genSignedRightShift (ic);
8276 /* signed & unsigned types are treated the same : i.e. the
8277 signed is NOT propagated inwards : quoting from the
8278 ANSI - standard : "for E1 >> E2, is equivalent to division
8279 by 2**E2 if unsigned or if it has a non-negative value,
8280 otherwise the result is implementation defined ", MY definition
8281 is that the sign does not get propagated */
8283 right = IC_RIGHT (ic);
8284 left = IC_LEFT (ic);
8285 result = IC_RESULT (ic);
8287 aopOp (right, ic, FALSE);
8289 /* if the shift count is known then do it
8290 as efficiently as possible */
8291 if (AOP_TYPE (right) == AOP_LIT)
8293 genRightShiftLiteral (left, right, result, ic, 0);
8297 /* shift count is unknown then we have to form
8298 a loop get the loop count in B : Note: we take
8299 only the lower order byte since shifting
8300 more that 32 bits make no sense anyway, ( the
8301 largest size of an object can be only 32 bits ) */
8304 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8305 emitcode ("inc", "b");
8306 freeAsmop (right, NULL, ic, TRUE);
8307 aopOp (left, ic, FALSE);
8308 aopOp (result, ic, FALSE);
8310 /* now move the left to the result if they are not the
8312 if (!sameRegs (AOP (left), AOP (result)) &&
8313 AOP_SIZE (result) > 1)
8316 size = AOP_SIZE (result);
8320 l = aopGet (left, offset, FALSE, TRUE);
8321 if (*l == '@' && IS_AOP_PREG (result))
8324 emitcode ("mov", "a,%s", l);
8325 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8328 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8333 tlbl = newiTempLabel (NULL);
8334 tlbl1 = newiTempLabel (NULL);
8335 size = AOP_SIZE (result);
8338 /* if it is only one byte then */
8341 l = aopGet (left, 0, FALSE, FALSE);
8343 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8344 emitcode ("", "%05d$:", tlbl->key + 100);
8346 emitcode ("rrc", "a");
8347 emitcode ("", "%05d$:", tlbl1->key + 100);
8348 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8350 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8354 reAdjustPreg (AOP (result));
8355 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8356 emitcode ("", "%05d$:", tlbl->key + 100);
8360 l = aopGet (result, offset, FALSE, FALSE);
8362 emitcode ("rrc", "a");
8363 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8365 reAdjustPreg (AOP (result));
8367 emitcode ("", "%05d$:", tlbl1->key + 100);
8368 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8372 freeAsmop (left, NULL, ic, TRUE);
8373 freeAsmop (result, NULL, ic, TRUE);
8376 /*-----------------------------------------------------------------*/
8377 /* emitPtrByteGet - emits code to get a byte into A through a */
8378 /* pointer register (R0, R1, or DPTR). The */
8379 /* original value of A can be preserved in B. */
8380 /*-----------------------------------------------------------------*/
8382 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8389 emitcode ("mov", "b,a");
8390 emitcode ("mov", "a,@%s", rname);
8395 emitcode ("mov", "b,a");
8396 emitcode ("movx", "a,@%s", rname);
8401 emitcode ("mov", "b,a");
8402 emitcode ("movx", "a,@dptr");
8407 emitcode ("mov", "b,a");
8408 emitcode ("clr", "a");
8409 emitcode ("movc", "a,@a+dptr");
8415 emitcode ("push", "b");
8416 emitcode ("push", "acc");
8418 emitcode ("lcall", "__gptrget");
8420 emitcode ("pop", "b");
8425 /*-----------------------------------------------------------------*/
8426 /* emitPtrByteSet - emits code to set a byte from src through a */
8427 /* pointer register (R0, R1, or DPTR). */
8428 /*-----------------------------------------------------------------*/
8430 emitPtrByteSet (char *rname, int p_type, char *src)
8439 emitcode ("mov", "@%s,a", rname);
8442 emitcode ("mov", "@%s,%s", rname, src);
8447 emitcode ("movx", "@%s,a", rname);
8452 emitcode ("movx", "@dptr,a");
8457 emitcode ("lcall", "__gptrput");
8462 /*-----------------------------------------------------------------*/
8463 /* genUnpackBits - generates code for unpacking bits */
8464 /*-----------------------------------------------------------------*/
8466 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8468 int offset = 0; /* result byte offset */
8469 int rsize; /* result size */
8470 int rlen = 0; /* remaining bitfield length */
8471 sym_link *etype; /* bitfield type information */
8472 int blen; /* bitfield length */
8473 int bstr; /* bitfield starting bit within byte */
8476 D(emitcode ("; genUnpackBits",""));
8478 etype = getSpec (operandType (result));
8479 rsize = getSize (operandType (result));
8480 blen = SPEC_BLEN (etype);
8481 bstr = SPEC_BSTR (etype);
8483 if (ifx && blen <= 8)
8485 emitPtrByteGet (rname, ptype, FALSE);
8488 SNPRINTF (buffer, sizeof(buffer),
8490 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8495 emitcode ("anl", "a,#0x%02x",
8496 (((unsigned char) -1) >> (8 - blen)) << bstr);
8497 genIfxJump (ifx, "a", NULL, NULL, NULL);
8503 /* If the bitfield length is less than a byte */
8506 emitPtrByteGet (rname, ptype, FALSE);
8508 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8509 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8513 /* Bit field did not fit in a byte. Copy all
8514 but the partial byte at the end. */
8515 for (rlen=blen;rlen>=8;rlen-=8)
8517 emitPtrByteGet (rname, ptype, FALSE);
8518 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8520 emitcode ("inc", "%s", rname);
8523 /* Handle the partial byte at the end */
8526 emitPtrByteGet (rname, ptype, FALSE);
8527 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8528 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8536 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8541 /*-----------------------------------------------------------------*/
8542 /* genDataPointerGet - generates code when ptr offset is known */
8543 /*-----------------------------------------------------------------*/
8545 genDataPointerGet (operand * left,
8551 int size, offset = 0;
8553 D(emitcode ("; genDataPointerGet",""));
8555 aopOp (result, ic, TRUE);
8557 /* get the string representation of the name */
8558 l = aopGet (left, 0, FALSE, TRUE);
8559 size = AOP_SIZE (result);
8563 sprintf (buffer, "(%s + %d)", l + 1, offset);
8565 sprintf (buffer, "%s", l + 1);
8566 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8569 freeAsmop (left, NULL, ic, TRUE);
8570 freeAsmop (result, NULL, ic, TRUE);
8573 /*-----------------------------------------------------------------*/
8574 /* genNearPointerGet - emitcode for near pointer fetch */
8575 /*-----------------------------------------------------------------*/
8577 genNearPointerGet (operand * left,
8586 sym_link *rtype, *retype;
8587 sym_link *ltype = operandType (left);
8590 D(emitcode ("; genNearPointerGet",""));
8592 rtype = operandType (result);
8593 retype = getSpec (rtype);
8595 aopOp (left, ic, FALSE);
8597 /* if left is rematerialisable and
8598 result is not bitfield variable type and
8599 the left is pointer to data space i.e
8600 lower 128 bytes of space */
8601 if (AOP_TYPE (left) == AOP_IMMD &&
8602 !IS_BITFIELD (retype) &&
8603 DCL_TYPE (ltype) == POINTER)
8605 genDataPointerGet (left, result, ic);
8609 /* if the value is already in a pointer register
8610 then don't need anything more */
8611 if (!AOP_INPREG (AOP (left)))
8613 if (IS_AOP_PREG (left))
8615 // Aha, it is a pointer, just in disguise.
8616 rname = aopGet (left, 0, FALSE, FALSE);
8619 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8620 __FILE__, __LINE__);
8625 emitcode ("mov", "a%s,%s", rname + 1, rname);
8626 rname++; // skip the '@'.
8631 /* otherwise get a free pointer register */
8633 preg = getFreePtr (ic, &aop, FALSE);
8634 emitcode ("mov", "%s,%s",
8636 aopGet (left, 0, FALSE, TRUE));
8641 rname = aopGet (left, 0, FALSE, FALSE);
8643 //aopOp (result, ic, FALSE);
8644 aopOp (result, ic, result?TRUE:FALSE);
8646 /* if bitfield then unpack the bits */
8647 if (IS_BITFIELD (retype))
8648 genUnpackBits (result, rname, POINTER, ifx);
8651 /* we have can just get the values */
8652 int size = AOP_SIZE (result);
8657 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8660 emitcode ("mov", "a,@%s", rname);
8662 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8666 sprintf (buffer, "@%s", rname);
8667 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
8671 emitcode ("inc", "%s", rname);
8675 /* now some housekeeping stuff */
8676 if (aop) /* we had to allocate for this iCode */
8678 if (pi) { /* post increment present */
8679 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8681 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8685 /* we did not allocate which means left
8686 already in a pointer register, then
8687 if size > 0 && this could be used again
8688 we have to point it back to where it
8690 if ((AOP_SIZE (result) > 1 &&
8691 !OP_SYMBOL (left)->remat &&
8692 (OP_SYMBOL (left)->liveTo > ic->seq ||
8696 int size = AOP_SIZE (result) - 1;
8698 emitcode ("dec", "%s", rname);
8702 if (ifx && !ifx->generated)
8704 genIfxJump (ifx, "a", left, NULL, result);
8708 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8709 freeAsmop (left, NULL, ic, TRUE);
8710 if (pi) pi->generated = 1;
8713 /*-----------------------------------------------------------------*/
8714 /* genPagedPointerGet - emitcode for paged pointer fetch */
8715 /*-----------------------------------------------------------------*/
8717 genPagedPointerGet (operand * left,
8726 sym_link *rtype, *retype;
8728 D(emitcode ("; genPagedPointerGet",""));
8730 rtype = operandType (result);
8731 retype = getSpec (rtype);
8733 aopOp (left, ic, FALSE);
8735 /* if the value is already in a pointer register
8736 then don't need anything more */
8737 if (!AOP_INPREG (AOP (left)))
8739 /* otherwise get a free pointer register */
8741 preg = getFreePtr (ic, &aop, FALSE);
8742 emitcode ("mov", "%s,%s",
8744 aopGet (left, 0, FALSE, TRUE));
8748 rname = aopGet (left, 0, FALSE, FALSE);
8750 aopOp (result, ic, FALSE);
8752 /* if bitfield then unpack the bits */
8753 if (IS_BITFIELD (retype))
8754 genUnpackBits (result, rname, PPOINTER, ifx);
8757 /* we have can just get the values */
8758 int size = AOP_SIZE (result);
8764 emitcode ("movx", "a,@%s", rname);
8766 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8771 emitcode ("inc", "%s", rname);
8775 /* now some housekeeping stuff */
8776 if (aop) /* we had to allocate for this iCode */
8778 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
8779 freeAsmop (NULL, aop, ic, TRUE);
8783 /* we did not allocate which means left
8784 already in a pointer register, then
8785 if size > 0 && this could be used again
8786 we have to point it back to where it
8788 if ((AOP_SIZE (result) > 1 &&
8789 !OP_SYMBOL (left)->remat &&
8790 (OP_SYMBOL (left)->liveTo > ic->seq ||
8794 int size = AOP_SIZE (result) - 1;
8796 emitcode ("dec", "%s", rname);
8800 if (ifx && !ifx->generated)
8802 genIfxJump (ifx, "a", left, NULL, result);
8806 freeAsmop (left, NULL, ic, TRUE);
8807 freeAsmop (result, NULL, ic, TRUE);
8808 if (pi) pi->generated = 1;
8812 /*--------------------------------------------------------------------*/
8813 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8814 /*--------------------------------------------------------------------*/
8816 loadDptrFromOperand (operand *op, bool loadBToo)
8818 if (AOP_TYPE (op) != AOP_STR)
8820 /* if this is rematerializable */
8821 if (AOP_TYPE (op) == AOP_IMMD)
8823 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
8826 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8827 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
8830 wassertl(FALSE, "need pointerCode");
8831 emitcode ("", "; mov b,???");
8832 /* genPointerGet and genPointerSet originally did different
8833 ** things for this case. Both seem wrong.
8834 ** from genPointerGet:
8835 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8836 ** from genPointerSet:
8837 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
8842 else if (AOP_TYPE (op) == AOP_DPTR)
8846 MOVA (aopGet (op, 0, FALSE, FALSE));
8847 emitcode ("push", "acc");
8848 MOVA (aopGet (op, 1, FALSE, FALSE));
8849 emitcode ("push", "acc");
8850 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8851 emitcode ("pop", "dph");
8852 emitcode ("pop", "dpl");
8856 MOVA (aopGet (op, 0, FALSE, FALSE));
8857 emitcode ("push", "acc");
8858 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
8859 emitcode ("pop", "dpl");
8863 { /* we need to get it byte by byte */
8864 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
8865 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
8867 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
8872 /*-----------------------------------------------------------------*/
8873 /* genFarPointerGet - gget value from far space */
8874 /*-----------------------------------------------------------------*/
8876 genFarPointerGet (operand * left,
8877 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8880 sym_link *retype = getSpec (operandType (result));
8882 D(emitcode ("; genFarPointerGet",""));
8884 aopOp (left, ic, FALSE);
8885 loadDptrFromOperand (left, FALSE);
8887 /* so dptr now contains the address */
8888 aopOp (result, ic, FALSE);
8890 /* if bit then unpack */
8891 if (IS_BITFIELD (retype))
8892 genUnpackBits (result, "dptr", FPOINTER, ifx);
8895 size = AOP_SIZE (result);
8900 emitcode ("movx", "a,@dptr");
8902 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8904 emitcode ("inc", "dptr");
8908 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8910 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
8911 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
8915 if (ifx && !ifx->generated)
8917 genIfxJump (ifx, "a", left, NULL, result);
8920 freeAsmop (left, NULL, ic, TRUE);
8921 freeAsmop (result, NULL, ic, TRUE);
8924 /*-----------------------------------------------------------------*/
8925 /* genCodePointerGet - gget value from code space */
8926 /*-----------------------------------------------------------------*/
8928 genCodePointerGet (operand * left,
8929 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8932 sym_link *retype = getSpec (operandType (result));
8934 D(emitcode ("; genCodePointerGet",""));
8936 aopOp (left, ic, FALSE);
8937 loadDptrFromOperand (left, FALSE);
8939 /* so dptr now contains the address */
8940 aopOp (result, ic, FALSE);
8942 /* if bit then unpack */
8943 if (IS_BITFIELD (retype))
8944 genUnpackBits (result, "dptr", CPOINTER, ifx);
8947 size = AOP_SIZE (result);
8954 emitcode ("clr", "a");
8955 emitcode ("movc", "a,@a+dptr");
8957 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8958 emitcode ("inc", "dptr");
8962 emitcode ("mov", "a,#0x%02x", offset);
8963 emitcode ("movc", "a,@a+dptr");
8965 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8970 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8972 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
8973 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
8977 if (ifx && !ifx->generated)
8979 genIfxJump (ifx, "a", left, NULL, result);
8982 freeAsmop (left, NULL, ic, TRUE);
8983 freeAsmop (result, NULL, ic, TRUE);
8986 /*-----------------------------------------------------------------*/
8987 /* genGenPointerGet - gget value from generic pointer space */
8988 /*-----------------------------------------------------------------*/
8990 genGenPointerGet (operand * left,
8991 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8994 sym_link *retype = getSpec (operandType (result));
8996 D(emitcode ("; genGenPointerGet",""));
8998 aopOp (left, ic, FALSE);
8999 loadDptrFromOperand (left, TRUE);
9001 /* so dptr know contains the address */
9002 aopOp (result, ic, FALSE);
9004 /* if bit then unpack */
9005 if (IS_BITFIELD (retype))
9006 genUnpackBits (result, "dptr", GPOINTER, ifx);
9009 size = AOP_SIZE (result);
9014 emitcode ("lcall", "__gptrget");
9016 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9018 emitcode ("inc", "dptr");
9022 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9024 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9025 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9029 if (ifx && !ifx->generated)
9031 genIfxJump (ifx, "a", left, NULL, result);
9035 freeAsmop (left, NULL, ic, TRUE);
9036 freeAsmop (result, NULL, ic, TRUE);
9039 /*-----------------------------------------------------------------*/
9040 /* genPointerGet - generate code for pointer get */
9041 /*-----------------------------------------------------------------*/
9043 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9045 operand *left, *result;
9046 sym_link *type, *etype;
9049 D(emitcode ("; genPointerGet",""));
9051 left = IC_LEFT (ic);
9052 result = IC_RESULT (ic);
9054 if (getSize (operandType (result))>1)
9057 /* depending on the type of pointer we need to
9058 move it to the correct pointer register */
9059 type = operandType (left);
9060 etype = getSpec (type);
9061 /* if left is of type of pointer then it is simple */
9062 if (IS_PTR (type) && !IS_FUNC (type->next))
9063 p_type = DCL_TYPE (type);
9066 /* we have to go by the storage class */
9067 p_type = PTR_TYPE (SPEC_OCLS (etype));
9070 /* special case when cast remat */
9071 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9072 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9073 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9074 type = operandType (left);
9075 p_type = DCL_TYPE (type);
9077 /* now that we have the pointer type we assign
9078 the pointer values */
9084 genNearPointerGet (left, result, ic, pi, ifx);
9088 genPagedPointerGet (left, result, ic, pi, ifx);
9092 genFarPointerGet (left, result, ic, pi, ifx);
9096 genCodePointerGet (left, result, ic, pi, ifx);
9100 genGenPointerGet (left, result, ic, pi, ifx);
9108 /*-----------------------------------------------------------------*/
9109 /* genPackBits - generates code for packed bit storage */
9110 /*-----------------------------------------------------------------*/
9112 genPackBits (sym_link * etype,
9114 char *rname, int p_type)
9116 int offset = 0; /* source byte offset */
9117 int rlen = 0; /* remaining bitfield length */
9118 int blen; /* bitfield length */
9119 int bstr; /* bitfield starting bit within byte */
9120 int litval; /* source literal value (if AOP_LIT) */
9121 unsigned char mask; /* bitmask within current byte */
9123 D(emitcode ("; genPackBits",""));
9125 blen = SPEC_BLEN (etype);
9126 bstr = SPEC_BSTR (etype);
9128 /* If the bitfield length is less than a byte */
9131 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9132 (unsigned char) (0xFF >> (8 - bstr)));
9134 if (AOP_TYPE (right) == AOP_LIT)
9136 /* Case with a bitfield length <8 and literal source
9138 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9140 litval &= (~mask) & 0xff;
9141 emitPtrByteGet (rname, p_type, FALSE);
9142 if ((mask|litval)!=0xff)
9143 emitcode ("anl","a,#0x%02x", mask);
9145 emitcode ("orl","a,#0x%02x", litval);
9149 if ((blen==1) && (p_type!=GPOINTER))
9151 /* Case with a bitfield length == 1 and no generic pointer
9153 if (AOP_TYPE (right) == AOP_CRY)
9154 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9157 MOVA (aopGet (right, 0, FALSE, FALSE));
9158 emitcode ("rrc","a");
9160 emitPtrByteGet (rname, p_type, FALSE);
9161 emitcode ("mov","acc.%d,c",bstr);
9166 /* Case with a bitfield length < 8 and arbitrary source
9168 MOVA (aopGet (right, 0, FALSE, FALSE));
9169 /* shift and mask source value */
9171 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9174 /* transfer A to B and get next byte */
9175 emitPtrByteGet (rname, p_type, TRUE);
9177 emitcode ("anl", "a,#0x%02x", mask);
9178 emitcode ("orl", "a,b");
9179 if (p_type == GPOINTER)
9180 emitcode ("pop", "b");
9186 emitPtrByteSet (rname, p_type, "a");
9190 /* Bit length is greater than 7 bits. In this case, copy */
9191 /* all except the partial byte at the end */
9192 for (rlen=blen;rlen>=8;rlen-=8)
9194 emitPtrByteSet (rname, p_type,
9195 aopGet (right, offset++, FALSE, TRUE) );
9197 emitcode ("inc", "%s", rname);
9200 /* If there was a partial byte at the end */
9203 mask = (((unsigned char) -1 << rlen) & 0xff);
9205 if (AOP_TYPE (right) == AOP_LIT)
9207 /* Case with partial byte and literal source
9209 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9210 litval >>= (blen-rlen);
9211 litval &= (~mask) & 0xff;
9212 emitPtrByteGet (rname, p_type, FALSE);
9213 if ((mask|litval)!=0xff)
9214 emitcode ("anl","a,#0x%02x", mask);
9216 emitcode ("orl","a,#0x%02x", litval);
9221 /* Case with partial byte and arbitrary source
9223 MOVA (aopGet (right, offset++, FALSE, FALSE));
9224 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9227 /* transfer A to B and get next byte */
9228 emitPtrByteGet (rname, p_type, TRUE);
9230 emitcode ("anl", "a,#0x%02x", mask);
9231 emitcode ("orl", "a,b");
9232 if (p_type == GPOINTER)
9233 emitcode ("pop", "b");
9237 emitPtrByteSet (rname, p_type, "a");
9243 /*-----------------------------------------------------------------*/
9244 /* genDataPointerSet - remat pointer to data space */
9245 /*-----------------------------------------------------------------*/
9247 genDataPointerSet (operand * right,
9251 int size, offset = 0;
9252 char *l, buffer[256];
9254 D(emitcode ("; genDataPointerSet",""));
9256 aopOp (right, ic, FALSE);
9258 l = aopGet (result, 0, FALSE, TRUE);
9259 size = AOP_SIZE (right);
9263 sprintf (buffer, "(%s + %d)", l + 1, offset);
9265 sprintf (buffer, "%s", l + 1);
9266 emitcode ("mov", "%s,%s", buffer,
9267 aopGet (right, offset++, FALSE, FALSE));
9270 freeAsmop (right, NULL, ic, TRUE);
9271 freeAsmop (result, NULL, ic, TRUE);
9274 /*-----------------------------------------------------------------*/
9275 /* genNearPointerSet - emitcode for near pointer put */
9276 /*-----------------------------------------------------------------*/
9278 genNearPointerSet (operand * right,
9286 sym_link *retype, *letype;
9287 sym_link *ptype = operandType (result);
9289 D(emitcode ("; genNearPointerSet",""));
9291 retype = getSpec (operandType (right));
9292 letype = getSpec (ptype);
9293 aopOp (result, ic, FALSE);
9295 /* if the result is rematerializable &
9296 in data space & not a bit variable */
9297 if (AOP_TYPE (result) == AOP_IMMD &&
9298 DCL_TYPE (ptype) == POINTER &&
9299 !IS_BITVAR (retype) &&
9300 !IS_BITVAR (letype))
9302 genDataPointerSet (right, result, ic);
9306 /* if the value is already in a pointer register
9307 then don't need anything more */
9308 if (!AOP_INPREG (AOP (result)))
9311 //AOP_TYPE (result) == AOP_STK
9315 // Aha, it is a pointer, just in disguise.
9316 rname = aopGet (result, 0, FALSE, FALSE);
9319 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9320 __FILE__, __LINE__);
9325 emitcode ("mov", "a%s,%s", rname + 1, rname);
9326 rname++; // skip the '@'.
9331 /* otherwise get a free pointer register */
9333 preg = getFreePtr (ic, &aop, FALSE);
9334 emitcode ("mov", "%s,%s",
9336 aopGet (result, 0, FALSE, TRUE));
9342 rname = aopGet (result, 0, FALSE, FALSE);
9345 aopOp (right, ic, FALSE);
9347 /* if bitfield then unpack the bits */
9348 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9349 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9352 /* we have can just get the values */
9353 int size = AOP_SIZE (right);
9358 l = aopGet (right, offset, FALSE, TRUE);
9362 emitcode ("mov", "@%s,a", rname);
9365 emitcode ("mov", "@%s,%s", rname, l);
9367 emitcode ("inc", "%s", rname);
9372 /* now some housekeeping stuff */
9373 if (aop) /* we had to allocate for this iCode */
9376 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9377 freeAsmop (NULL, aop, ic, TRUE);
9381 /* we did not allocate which means left
9382 already in a pointer register, then
9383 if size > 0 && this could be used again
9384 we have to point it back to where it
9386 if ((AOP_SIZE (right) > 1 &&
9387 !OP_SYMBOL (result)->remat &&
9388 (OP_SYMBOL (result)->liveTo > ic->seq ||
9392 int size = AOP_SIZE (right) - 1;
9394 emitcode ("dec", "%s", rname);
9399 if (pi) pi->generated = 1;
9400 freeAsmop (result, NULL, ic, TRUE);
9401 freeAsmop (right, NULL, ic, TRUE);
9404 /*-----------------------------------------------------------------*/
9405 /* genPagedPointerSet - emitcode for Paged pointer put */
9406 /*-----------------------------------------------------------------*/
9408 genPagedPointerSet (operand * right,
9416 sym_link *retype, *letype;
9418 D(emitcode ("; genPagedPointerSet",""));
9420 retype = getSpec (operandType (right));
9421 letype = getSpec (operandType (result));
9423 aopOp (result, ic, FALSE);
9425 /* if the value is already in a pointer register
9426 then don't need anything more */
9427 if (!AOP_INPREG (AOP (result)))
9429 /* otherwise get a free pointer register */
9431 preg = getFreePtr (ic, &aop, FALSE);
9432 emitcode ("mov", "%s,%s",
9434 aopGet (result, 0, FALSE, TRUE));
9438 rname = aopGet (result, 0, FALSE, FALSE);
9440 aopOp (right, ic, FALSE);
9442 /* if bitfield then unpack the bits */
9443 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9444 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9447 /* we have can just get the values */
9448 int size = AOP_SIZE (right);
9453 l = aopGet (right, offset, FALSE, TRUE);
9456 emitcode ("movx", "@%s,a", rname);
9459 emitcode ("inc", "%s", rname);
9465 /* now some housekeeping stuff */
9466 if (aop) /* we had to allocate for this iCode */
9469 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9470 freeAsmop (NULL, aop, ic, TRUE);
9474 /* we did not allocate which means left
9475 already in a pointer register, then
9476 if size > 0 && this could be used again
9477 we have to point it back to where it
9479 if (AOP_SIZE (right) > 1 &&
9480 !OP_SYMBOL (result)->remat &&
9481 (OP_SYMBOL (result)->liveTo > ic->seq ||
9484 int size = AOP_SIZE (right) - 1;
9486 emitcode ("dec", "%s", rname);
9491 if (pi) pi->generated = 1;
9492 freeAsmop (result, NULL, ic, TRUE);
9493 freeAsmop (right, NULL, ic, TRUE);
9498 /*-----------------------------------------------------------------*/
9499 /* genFarPointerSet - set value from far space */
9500 /*-----------------------------------------------------------------*/
9502 genFarPointerSet (operand * right,
9503 operand * result, iCode * ic, iCode * pi)
9506 sym_link *retype = getSpec (operandType (right));
9507 sym_link *letype = getSpec (operandType (result));
9509 D(emitcode ("; genFarPointerSet",""));
9511 aopOp (result, ic, FALSE);
9512 loadDptrFromOperand (result, FALSE);
9514 /* so dptr know contains the address */
9515 aopOp (right, ic, FALSE);
9517 /* if bit then unpack */
9518 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9519 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9522 size = AOP_SIZE (right);
9527 char *l = aopGet (right, offset++, FALSE, FALSE);
9529 emitcode ("movx", "@dptr,a");
9531 emitcode ("inc", "dptr");
9534 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9535 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9536 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9539 freeAsmop (result, NULL, ic, TRUE);
9540 freeAsmop (right, NULL, ic, TRUE);
9543 /*-----------------------------------------------------------------*/
9544 /* genGenPointerSet - set value from generic pointer space */
9545 /*-----------------------------------------------------------------*/
9547 genGenPointerSet (operand * right,
9548 operand * result, iCode * ic, iCode * pi)
9551 sym_link *retype = getSpec (operandType (right));
9552 sym_link *letype = getSpec (operandType (result));
9554 D(emitcode ("; genGenPointerSet",""));
9556 aopOp (result, ic, FALSE);
9557 loadDptrFromOperand (result, TRUE);
9559 /* so dptr know contains the address */
9560 aopOp (right, ic, FALSE);
9562 /* if bit then unpack */
9563 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9564 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9567 size = AOP_SIZE (right);
9572 char *l = aopGet (right, offset++, FALSE, FALSE);
9574 emitcode ("lcall", "__gptrput");
9576 emitcode ("inc", "dptr");
9580 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9581 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9582 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9585 freeAsmop (result, NULL, ic, TRUE);
9586 freeAsmop (right, NULL, ic, TRUE);
9589 /*-----------------------------------------------------------------*/
9590 /* genPointerSet - stores the value into a pointer location */
9591 /*-----------------------------------------------------------------*/
9593 genPointerSet (iCode * ic, iCode *pi)
9595 operand *right, *result;
9596 sym_link *type, *etype;
9599 D(emitcode ("; genPointerSet",""));
9601 right = IC_RIGHT (ic);
9602 result = IC_RESULT (ic);
9604 /* depending on the type of pointer we need to
9605 move it to the correct pointer register */
9606 type = operandType (result);
9607 etype = getSpec (type);
9608 /* if left is of type of pointer then it is simple */
9609 if (IS_PTR (type) && !IS_FUNC (type->next))
9611 p_type = DCL_TYPE (type);
9615 /* we have to go by the storage class */
9616 p_type = PTR_TYPE (SPEC_OCLS (etype));
9619 /* special case when cast remat */
9620 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9621 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9622 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9623 type = operandType (result);
9624 p_type = DCL_TYPE (type);
9626 /* now that we have the pointer type we assign
9627 the pointer values */
9633 genNearPointerSet (right, result, ic, pi);
9637 genPagedPointerSet (right, result, ic, pi);
9641 genFarPointerSet (right, result, ic, pi);
9645 genGenPointerSet (right, result, ic, pi);
9649 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9650 "genPointerSet: illegal pointer type");
9655 /*-----------------------------------------------------------------*/
9656 /* genIfx - generate code for Ifx statement */
9657 /*-----------------------------------------------------------------*/
9659 genIfx (iCode * ic, iCode * popIc)
9661 operand *cond = IC_COND (ic);
9664 D(emitcode ("; genIfx",""));
9666 aopOp (cond, ic, FALSE);
9668 /* get the value into acc */
9669 if (AOP_TYPE (cond) != AOP_CRY)
9673 /* the result is now in the accumulator */
9674 freeAsmop (cond, NULL, ic, TRUE);
9676 /* if there was something to be popped then do it */
9680 /* if the condition is a bit variable */
9681 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9682 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9683 else if (isbit && !IS_ITEMP (cond))
9684 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9686 genIfxJump (ic, "a", NULL, NULL, NULL);
9691 /*-----------------------------------------------------------------*/
9692 /* genAddrOf - generates code for address of */
9693 /*-----------------------------------------------------------------*/
9695 genAddrOf (iCode * ic)
9697 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9700 D(emitcode ("; genAddrOf",""));
9702 aopOp (IC_RESULT (ic), ic, FALSE);
9704 /* if the operand is on the stack then we
9705 need to get the stack offset of this
9709 /* if it has an offset then we need to compute
9713 emitcode ("mov", "a,%s", SYM_BP (sym));
9714 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9715 ((char) (sym->stack - _G.nRegsSaved)) :
9716 ((char) sym->stack)) & 0xff);
9717 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9721 /* we can just move _bp */
9722 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9724 /* fill the result with zero */
9725 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9730 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9736 /* object not on stack then we need the name */
9737 size = AOP_SIZE (IC_RESULT (ic));
9742 char s[SDCC_NAME_MAX];
9744 sprintf (s, "#(%s >> %d)",
9748 sprintf (s, "#%s", sym->rname);
9749 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9753 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9757 /*-----------------------------------------------------------------*/
9758 /* genFarFarAssign - assignment when both are in far space */
9759 /*-----------------------------------------------------------------*/
9761 genFarFarAssign (operand * result, operand * right, iCode * ic)
9763 int size = AOP_SIZE (right);
9767 D(emitcode ("; genFarFarAssign",""));
9769 /* first push the right side on to the stack */
9772 l = aopGet (right, offset++, FALSE, FALSE);
9774 emitcode ("push", "acc");
9777 freeAsmop (right, NULL, ic, FALSE);
9778 /* now assign DPTR to result */
9779 aopOp (result, ic, FALSE);
9780 size = AOP_SIZE (result);
9783 emitcode ("pop", "acc");
9784 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
9786 freeAsmop (result, NULL, ic, FALSE);
9790 /*-----------------------------------------------------------------*/
9791 /* genAssign - generate code for assignment */
9792 /*-----------------------------------------------------------------*/
9794 genAssign (iCode * ic)
9796 operand *result, *right;
9798 unsigned long lit = 0L;
9800 D(emitcode("; genAssign",""));
9802 result = IC_RESULT (ic);
9803 right = IC_RIGHT (ic);
9805 /* if they are the same */
9806 if (operandsEqu (result, right) &&
9807 !isOperandVolatile (result, FALSE) &&
9808 !isOperandVolatile (right, FALSE))
9811 aopOp (right, ic, FALSE);
9813 /* special case both in far space */
9814 if (AOP_TYPE (right) == AOP_DPTR &&
9815 IS_TRUE_SYMOP (result) &&
9816 isOperandInFarSpace (result))
9819 genFarFarAssign (result, right, ic);
9823 aopOp (result, ic, TRUE);
9825 /* if they are the same registers */
9826 if (sameRegs (AOP (right), AOP (result)) &&
9827 !isOperandVolatile (result, FALSE) &&
9828 !isOperandVolatile (right, FALSE))
9831 /* if the result is a bit */
9832 if (AOP_TYPE (result) == AOP_CRY)
9835 /* if the right size is a literal then
9836 we know what the value is */
9837 if (AOP_TYPE (right) == AOP_LIT)
9839 if (((int) operandLitValue (right)))
9840 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
9842 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
9846 /* the right is also a bit variable */
9847 if (AOP_TYPE (right) == AOP_CRY)
9849 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9850 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
9856 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9860 /* bit variables done */
9862 size = AOP_SIZE (result);
9864 if (AOP_TYPE (right) == AOP_LIT)
9865 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9867 (AOP_TYPE (result) != AOP_REG) &&
9868 (AOP_TYPE (right) == AOP_LIT) &&
9869 !IS_FLOAT (operandType (right)) &&
9872 while ((size) && (lit))
9875 aopGet (right, offset, FALSE, FALSE),
9877 isOperandVolatile (result, FALSE));
9882 emitcode ("clr", "a");
9885 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9894 aopGet (right, offset, FALSE, FALSE),
9896 isOperandVolatile (result, FALSE));
9902 freeAsmop (right, NULL, ic, TRUE);
9903 freeAsmop (result, NULL, ic, TRUE);
9906 /*-----------------------------------------------------------------*/
9907 /* genJumpTab - generates code for jump table */
9908 /*-----------------------------------------------------------------*/
9910 genJumpTab (iCode * ic)
9912 symbol *jtab,*jtablo,*jtabhi;
9916 D(emitcode ("; genJumpTab",""));
9918 count = elementsInSet( IC_JTLABELS (ic) );
9922 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9923 if the switch argument is in a register.
9924 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9925 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9926 How will multiply by three be updated ???*/
9927 aopOp (IC_JTCOND (ic), ic, FALSE);
9928 /* get the condition into accumulator */
9929 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
9931 /* multiply by three */
9932 emitcode ("add", "a,acc");
9933 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
9934 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9936 jtab = newiTempLabel (NULL);
9937 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9938 emitcode ("jmp", "@a+dptr");
9939 emitcode ("", "%05d$:", jtab->key + 100);
9940 /* now generate the jump labels */
9941 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9942 jtab = setNextItem (IC_JTLABELS (ic)))
9943 emitcode ("ljmp", "%05d$", jtab->key + 100);
9947 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9948 if the switch argument is in a register.
9949 For n>6 this algorithm may be more compact */
9950 jtablo = newiTempLabel (NULL);
9951 jtabhi = newiTempLabel (NULL);
9953 /* get the condition into accumulator.
9954 Using b as temporary storage, if register push/pop is needed */
9955 aopOp (IC_JTCOND (ic), ic, FALSE);
9956 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
9957 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9958 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9960 // (MB) what if B is in use???
9961 wassertl(!BINUSE, "B was in use");
9962 emitcode ("mov", "b,%s", l);
9965 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9969 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9970 emitcode ("movc", "a,@a+pc");
9971 emitcode ("push", "acc");
9974 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9975 emitcode ("movc", "a,@a+pc");
9976 emitcode ("push", "acc");
9980 /* this scales up to n<=255, but needs two more bytes
9982 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9983 emitcode ("movc", "a,@a+dptr");
9984 emitcode ("push", "acc");
9987 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9988 emitcode ("movc", "a,@a+dptr");
9989 emitcode ("push", "acc");
9992 emitcode ("ret", "");
9994 /* now generate jump table, LSB */
9995 emitcode ("", "%05d$:", jtablo->key + 100);
9996 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9997 jtab = setNextItem (IC_JTLABELS (ic)))
9998 emitcode (".db", "%05d$", jtab->key + 100);
10000 /* now generate jump table, MSB */
10001 emitcode ("", "%05d$:", jtabhi->key + 100);
10002 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10003 jtab = setNextItem (IC_JTLABELS (ic)))
10004 emitcode (".db", "%05d$>>8", jtab->key + 100);
10008 /*-----------------------------------------------------------------*/
10009 /* genCast - gen code for casting */
10010 /*-----------------------------------------------------------------*/
10012 genCast (iCode * ic)
10014 operand *result = IC_RESULT (ic);
10015 sym_link *ctype = operandType (IC_LEFT (ic));
10016 sym_link *rtype = operandType (IC_RIGHT (ic));
10017 operand *right = IC_RIGHT (ic);
10020 D(emitcode("; genCast",""));
10022 /* if they are equivalent then do nothing */
10023 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10026 aopOp (right, ic, FALSE);
10027 aopOp (result, ic, FALSE);
10029 /* if the result is a bit (and not a bitfield) */
10030 // if (AOP_TYPE (result) == AOP_CRY)
10031 if (IS_BITVAR (OP_SYMBOL (result)->type)
10032 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10034 /* if the right size is a literal then
10035 we know what the value is */
10036 if (AOP_TYPE (right) == AOP_LIT)
10038 if (((int) operandLitValue (right)))
10039 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10041 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10046 /* the right is also a bit variable */
10047 if (AOP_TYPE (right) == AOP_CRY)
10049 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10050 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10054 /* we need to or */
10056 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10061 /* if they are the same size : or less */
10062 if (AOP_SIZE (result) <= AOP_SIZE (right))
10065 /* if they are in the same place */
10066 if (sameRegs (AOP (right), AOP (result)))
10069 /* if they in different places then copy */
10070 size = AOP_SIZE (result);
10075 aopGet (right, offset, FALSE, FALSE),
10077 isOperandVolatile (result, FALSE));
10084 /* if the result is of type pointer */
10085 if (IS_PTR (ctype))
10089 sym_link *type = operandType (right);
10090 sym_link *etype = getSpec (type);
10092 /* pointer to generic pointer */
10093 if (IS_GENPTR (ctype))
10096 p_type = DCL_TYPE (type);
10099 if (SPEC_SCLS(etype)==S_REGISTER) {
10100 // let's assume it is a generic pointer
10103 /* we have to go by the storage class */
10104 p_type = PTR_TYPE (SPEC_OCLS (etype));
10108 /* the first two bytes are known */
10109 size = GPTRSIZE - 1;
10114 aopGet (right, offset, FALSE, FALSE),
10116 isOperandVolatile (result, FALSE));
10119 /* the last byte depending on type */
10121 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10126 // pointerTypeToGPByte will have bitched.
10130 sprintf(gpValStr, "#0x%x", gpVal);
10131 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10136 /* just copy the pointers */
10137 size = AOP_SIZE (result);
10142 aopGet (right, offset, FALSE, FALSE),
10144 isOperandVolatile (result, FALSE));
10150 /* so we now know that the size of destination is greater
10151 than the size of the source */
10152 /* we move to result for the size of source */
10153 size = AOP_SIZE (right);
10158 aopGet (right, offset, FALSE, FALSE),
10160 isOperandVolatile (result, FALSE));
10164 /* now depending on the sign of the source && destination */
10165 size = AOP_SIZE (result) - AOP_SIZE (right);
10166 /* if unsigned or not an integral type */
10167 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10170 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10174 /* we need to extend the sign :{ */
10175 char *l = aopGet (right, AOP_SIZE (right) - 1,
10178 emitcode ("rlc", "a");
10179 emitcode ("subb", "a,acc");
10181 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10184 /* we are done hurray !!!! */
10187 freeAsmop (right, NULL, ic, TRUE);
10188 freeAsmop (result, NULL, ic, TRUE);
10192 /*-----------------------------------------------------------------*/
10193 /* genDjnz - generate decrement & jump if not zero instrucion */
10194 /*-----------------------------------------------------------------*/
10196 genDjnz (iCode * ic, iCode * ifx)
10198 symbol *lbl, *lbl1;
10202 D(emitcode ("; genDjnz",""));
10204 /* if the if condition has a false label
10205 then we cannot save */
10206 if (IC_FALSE (ifx))
10209 /* if the minus is not of the form
10211 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10212 !IS_OP_LITERAL (IC_RIGHT (ic)))
10215 if (operandLitValue (IC_RIGHT (ic)) != 1)
10218 /* if the size of this greater than one then no
10220 if (getSize (operandType (IC_RESULT (ic))) > 1)
10223 /* otherwise we can save BIG */
10224 lbl = newiTempLabel (NULL);
10225 lbl1 = newiTempLabel (NULL);
10227 aopOp (IC_RESULT (ic), ic, FALSE);
10229 if (AOP_NEEDSACC(IC_RESULT(ic)))
10231 /* If the result is accessed indirectly via
10232 * the accumulator, we must explicitly write
10233 * it back after the decrement.
10235 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10237 if (strcmp(rByte, "a"))
10239 /* Something is hopelessly wrong */
10240 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10241 __FILE__, __LINE__);
10242 /* We can just give up; the generated code will be inefficient,
10243 * but what the hey.
10245 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10248 emitcode ("dec", "%s", rByte);
10249 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10250 emitcode ("jnz", "%05d$", lbl->key + 100);
10252 else if (IS_AOP_PREG (IC_RESULT (ic)))
10254 emitcode ("dec", "%s",
10255 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10256 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10257 emitcode ("jnz", "%05d$", lbl->key + 100);
10261 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10264 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10265 emitcode ("", "%05d$:", lbl->key + 100);
10266 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10267 emitcode ("", "%05d$:", lbl1->key + 100);
10269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10270 ifx->generated = 1;
10274 /*-----------------------------------------------------------------*/
10275 /* genReceive - generate code for a receive iCode */
10276 /*-----------------------------------------------------------------*/
10278 genReceive (iCode * ic)
10280 int size = getSize (operandType (IC_RESULT (ic)));
10282 D(emitcode ("; genReceive",""));
10284 if (ic->argreg == 1) { /* first parameter */
10285 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10286 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10287 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10290 int receivingA = 0;
10293 for (offset = 0; offset<size; offset++)
10294 if (!strcmp (fReturn[offset], "a"))
10299 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10301 for (offset = size-1; offset>0; offset--)
10302 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10303 emitcode("mov","a,%s", fReturn[0]);
10305 aopOp (IC_RESULT (ic), ic, FALSE);
10307 aopPut (IC_RESULT (ic), "a", offset,
10308 isOperandVolatile (IC_RESULT (ic), FALSE));
10309 for (offset = 1; offset<size; offset++)
10310 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10311 isOperandVolatile (IC_RESULT (ic), FALSE));
10317 if (getTempRegs(tempRegs, size, ic))
10319 for (offset = 0; offset<size; offset++)
10320 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10321 aopOp (IC_RESULT (ic), ic, FALSE);
10322 for (offset = 0; offset<size; offset++)
10323 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10324 isOperandVolatile (IC_RESULT (ic), FALSE));
10329 offset = fReturnSizeMCS51 - size;
10331 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10332 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10335 aopOp (IC_RESULT (ic), ic, FALSE);
10336 size = AOP_SIZE (IC_RESULT (ic));
10339 emitcode ("pop", "acc");
10340 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10345 aopOp (IC_RESULT (ic), ic, FALSE);
10347 assignResultValue (IC_RESULT (ic));
10349 } else { /* second receive onwards */
10351 aopOp (IC_RESULT (ic), ic, FALSE);
10352 rb1off = ic->argreg;
10354 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10359 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10362 /*-----------------------------------------------------------------*/
10363 /* genDummyRead - generate code for dummy read of volatiles */
10364 /*-----------------------------------------------------------------*/
10366 genDummyRead (iCode * ic)
10371 D(emitcode("; genDummyRead",""));
10373 op = IC_RIGHT (ic);
10374 if (op && IS_SYMOP (op))
10376 aopOp (op, ic, FALSE);
10378 /* if the result is a bit */
10379 if (AOP_TYPE (op) == AOP_CRY)
10380 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10383 /* bit variables done */
10385 size = AOP_SIZE (op);
10389 MOVA (aopGet (op, offset, FALSE, FALSE));
10394 freeAsmop (op, NULL, ic, TRUE);
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 /*-----------------------------------------------------------------*/
10423 /* genCritical - generate code for start of a critical sequence */
10424 /*-----------------------------------------------------------------*/
10426 genCritical (iCode *ic)
10428 symbol *tlbl = newiTempLabel (NULL);
10430 D(emitcode("; genCritical",""));
10432 if (IC_RESULT (ic))
10434 aopOp (IC_RESULT (ic), ic, TRUE);
10435 aopPut (IC_RESULT (ic), one, 0, 0);
10436 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10437 aopPut (IC_RESULT (ic), zero, 0, 0);
10438 emitcode ("", "%05d$:", (tlbl->key + 100));
10439 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10443 emitcode ("setb", "c");
10444 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10445 emitcode ("clr", "c");
10446 emitcode ("", "%05d$:", (tlbl->key + 100));
10447 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10451 /*-----------------------------------------------------------------*/
10452 /* genEndCritical - generate code for end of a critical sequence */
10453 /*-----------------------------------------------------------------*/
10455 genEndCritical (iCode *ic)
10457 D(emitcode("; genEndCritical",""));
10461 aopOp (IC_RIGHT (ic), ic, FALSE);
10462 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10464 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10465 emitcode ("mov", "ea,c");
10469 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10470 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10471 emitcode ("rrc", "a");
10472 emitcode ("mov", "ea,c");
10474 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10478 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10479 emitcode ("mov", "ea,c");
10483 /*-----------------------------------------------------------------*/
10484 /* gen51Code - generate code for 8051 based controllers */
10485 /*-----------------------------------------------------------------*/
10487 gen51Code (iCode * lic)
10491 /* int cseq = 0; */
10493 _G.currentFunc = NULL;
10494 lineHead = lineCurr = NULL;
10496 /* print the allocation information */
10497 if (allocInfo && currFunc)
10498 printAllocInfo (currFunc, codeOutFile);
10499 /* if debug information required */
10500 if (options.debug && currFunc)
10502 debugFile->writeFunction (currFunc, lic);
10504 /* stack pointer name */
10505 if (options.useXstack)
10511 for (ic = lic; ic; ic = ic->next)
10513 _G.current_iCode = ic;
10515 if (ic->lineno && cln != ic->lineno)
10519 debugFile->writeCLine (ic);
10521 if (!options.noCcodeInAsm) {
10522 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10523 printCLine(ic->filename, ic->lineno));
10528 if (ic->seqPoint && ic->seqPoint != cseq)
10530 emitcode ("", "; sequence point %d", ic->seqPoint);
10531 cseq = ic->seqPoint;
10534 if (options.iCodeInAsm) {
10535 char regsInUse[80];
10538 for (i=0; i<8; i++) {
10539 sprintf (®sInUse[i],
10540 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10543 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10545 /* if the result is marked as
10546 spilt and rematerializable or code for
10547 this has already been generated then
10549 if (resultRemat (ic) || ic->generated)
10552 /* depending on the operation */
10572 /* IPOP happens only when trying to restore a
10573 spilt live range, if there is an ifx statement
10574 following this pop then the if statement might
10575 be using some of the registers being popped which
10576 would destory the contents of the register so
10577 we need to check for this condition and handle it */
10579 ic->next->op == IFX &&
10580 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10581 genIfx (ic->next, ic);
10599 genEndFunction (ic);
10619 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10636 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10640 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10647 /* note these two are xlated by algebraic equivalence
10648 during parsing SDCC.y */
10649 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10650 "got '>=' or '<=' shouldn't have come here");
10654 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10666 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10670 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10674 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10698 genRightShift (ic);
10701 case GET_VALUE_AT_ADDRESS:
10703 hasInc (IC_LEFT (ic), ic,
10704 getSize (operandType (IC_RESULT (ic)))),
10705 ifxForOp (IC_RESULT (ic), ic) );
10709 if (POINTER_SET (ic))
10710 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10736 addSet (&_G.sendSet, ic);
10739 case DUMMY_READ_VOLATILE:
10748 genEndCritical (ic);
10760 _G.current_iCode = NULL;
10762 /* now we are ready to call the
10763 peep hole optimizer */
10764 if (!options.nopeep)
10765 peepHole (&lineHead);
10767 /* now do the actual printing */
10768 printLine (lineHead, codeOutFile);