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 R0INB _G.bu.bs.r0InB
68 #define R1INB _G.bu.bs.r1InB
69 #define OPINB _G.bu.bs.OpInB
70 #define BINUSE _G.bu.BInUse
80 short r0InB : 2;//2 so we can see it overflow
81 short r1InB : 2;//2 so we can see it overflow
82 short OpInB : 2;//2 so we can see it overflow
96 static char *rb1regs[] = {
97 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
105 #define RESULTONSTACK(x) \
106 (IC_RESULT(x) && IC_RESULT(x)->aop && \
107 IC_RESULT(x)->aop->type == AOP_STK )
109 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
110 #define CLRC emitcode("clr","c")
111 #define SETC emitcode("setb","c")
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
116 static unsigned char SLMask[] =
117 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
118 0xE0, 0xC0, 0x80, 0x00};
119 static unsigned char SRMask[] =
120 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
121 0x07, 0x03, 0x01, 0x00};
128 /*-----------------------------------------------------------------*/
129 /* emitcode - writes the code into a file : for now it is simple */
130 /*-----------------------------------------------------------------*/
132 emitcode (char *inst, const char *fmt,...)
135 char lb[INITIAL_INLINEASM];
143 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
145 SNPRINTF (lb, sizeof(lb), "%s", inst);
146 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
149 tvsprintf (lb, sizeof(lb), fmt, ap);
151 while (isspace (*lbp))
155 lineCurr = (lineCurr ?
156 connectLine (lineCurr, newLineNode (lb)) :
157 (lineHead = newLineNode (lb)));
158 lineCurr->isInline = _G.inLine;
159 lineCurr->isDebug = _G.debugLine;
160 lineCurr->ic = _G.current_iCode;
161 lineCurr->isComment = (*lbp==';');
165 /*-----------------------------------------------------------------*/
166 /* mcs51_emitDebuggerSymbol - associate the current code location */
167 /* with a debugger symbol */
168 /*-----------------------------------------------------------------*/
170 mcs51_emitDebuggerSymbol (char * debugSym)
173 emitcode ("", "%s ==.", debugSym);
177 /*-----------------------------------------------------------------*/
178 /* mova - moves specified value into accumulator */
179 /*-----------------------------------------------------------------*/
183 /* do some early peephole optimization */
184 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
187 emitcode("mov","a,%s", x);
190 /*-----------------------------------------------------------------*/
191 /* pushB - saves register B if necessary */
192 /*-----------------------------------------------------------------*/
196 bool pushedB = FALSE;
200 emitcode ("push", "b");
201 // printf("B was in use !\n");
211 /*-----------------------------------------------------------------*/
212 /* popB - restores value of register B if necessary */
213 /*-----------------------------------------------------------------*/
219 emitcode ("pop", "b");
227 /*-----------------------------------------------------------------*/
228 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
229 /*-----------------------------------------------------------------*/
231 getFreePtr (iCode * ic, asmop ** aopp, bool result)
236 /* the logic: if r0 & r1 used in the instruction
237 then we are in trouble otherwise */
239 /* first check if r0 & r1 are used by this
240 instruction, in which case we are in trouble */
241 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
242 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
247 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
248 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
250 /* if no usage of r0 then return it */
253 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
254 (*aopp)->type = AOP_R0;
256 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
259 /* if no usage of r1 then return it */
262 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
263 (*aopp)->type = AOP_R1;
265 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
268 /* now we know they both have usage */
269 /* if r0 not used in this instruction */
272 /* push it if not already pushed */
275 emitcode ("mov", "b,%s",
276 mcs51_regWithIdx (R0_IDX)->dname);
279 else if (!_G.r0Pushed)
281 emitcode ("push", "%s",
282 mcs51_regWithIdx (R0_IDX)->dname);
286 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
287 (*aopp)->type = AOP_R0;
289 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
292 /* if r1 not used then */
296 /* push it if not already pushed */
299 emitcode ("mov", "b,%s",
300 mcs51_regWithIdx (R1_IDX)->dname);
303 else if (!_G.r1Pushed)
305 emitcode ("push", "%s",
306 mcs51_regWithIdx (R1_IDX)->dname);
310 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
311 (*aopp)->type = AOP_R1;
312 return mcs51_regWithIdx (R1_IDX);
315 /* I said end of world, but not quite end of world yet */
317 /* we can push it on the stack */
318 (*aopp)->type = AOP_STK;
321 /* in the case that result AND left AND right needs a pointer reg
322 we can safely use the result's */
323 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
324 (*aopp)->type = AOP_R0;
325 return mcs51_regWithIdx (R0_IDX);
327 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
328 (*aopp)->type = AOP_R1;
329 return mcs51_regWithIdx (R1_IDX);
333 /* now this is REALLY the end of the world */
334 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
335 "getFreePtr should never reach here");
340 /*-----------------------------------------------------------------*/
341 /* getTempRegs - initialize an array of pointers to GPR registers */
342 /* that are not in use. Returns 1 if the requested */
343 /* number of registers were available, 0 otherwise. */
344 /*-----------------------------------------------------------------*/
346 getTempRegs(regs **tempRegs, int size, iCode *ic)
353 ic = _G.current_iCode;
359 freeRegs = newBitVect(8);
360 bitVectSetBit (freeRegs, R2_IDX);
361 bitVectSetBit (freeRegs, R3_IDX);
362 bitVectSetBit (freeRegs, R4_IDX);
363 bitVectSetBit (freeRegs, R5_IDX);
364 bitVectSetBit (freeRegs, R6_IDX);
365 bitVectSetBit (freeRegs, R7_IDX);
367 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
369 bitVect * newfreeRegs;
370 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
371 freeBitVect(freeRegs);
372 freeRegs = newfreeRegs;
374 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
377 for (i=0; i<freeRegs->size; i++)
379 if (bitVectBitValue(freeRegs,i))
380 tempRegs[offset++] = mcs51_regWithIdx(i);
383 freeBitVect(freeRegs);
388 freeBitVect(freeRegs);
393 /*-----------------------------------------------------------------*/
394 /* newAsmop - creates a new asmOp */
395 /*-----------------------------------------------------------------*/
397 newAsmop (short type)
401 aop = Safe_calloc (1, sizeof (asmop));
406 /*-----------------------------------------------------------------*/
407 /* pointerCode - returns the code for a pointer type */
408 /*-----------------------------------------------------------------*/
410 pointerCode (sym_link * etype)
413 return PTR_TYPE (SPEC_OCLS (etype));
417 /*-----------------------------------------------------------------*/
418 /* leftRightUseAcc - returns size of accumulator use by operands */
419 /*-----------------------------------------------------------------*/
421 leftRightUseAcc(iCode *ic)
430 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
431 "null iCode pointer");
438 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
441 size = getSize (OP_SYMBOL (op)->type);
446 else if (ic->op == JUMPTABLE)
449 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
452 size = getSize (OP_SYMBOL (op)->type);
460 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
463 size = getSize (OP_SYMBOL (op)->type);
468 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
471 size = getSize (OP_SYMBOL (op)->type);
483 /*-----------------------------------------------------------------*/
484 /* aopForSym - for a true symbol */
485 /*-----------------------------------------------------------------*/
487 aopForSym (iCode * ic, symbol * sym, bool result)
492 wassertl (ic != NULL, "Got a null iCode");
493 wassertl (sym != NULL, "Got a null symbol");
495 space = SPEC_OCLS (sym->etype);
497 /* if already has one */
501 /* assign depending on the storage class */
502 /* if it is on the stack or indirectly addressable */
503 /* space we need to assign either r0 or r1 to it */
504 if (sym->onStack || sym->iaccess)
506 sym->aop = aop = newAsmop (0);
507 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
508 aop->size = getSize (sym->type);
510 /* now assign the address of the variable to
511 the pointer register */
512 if (aop->type != AOP_STK)
517 if (_G.accInUse || leftRightUseAcc (ic))
518 emitcode ("push", "acc");
520 emitcode ("mov", "a,_bp");
521 emitcode ("add", "a,#0x%02x",
523 ((char) (sym->stack - _G.nRegsSaved)) :
524 ((char) sym->stack)) & 0xff);
525 emitcode ("mov", "%s,a",
526 aop->aopu.aop_ptr->name);
528 if (_G.accInUse || leftRightUseAcc (ic))
529 emitcode ("pop", "acc");
532 emitcode ("mov", "%s,#%s",
533 aop->aopu.aop_ptr->name,
535 aop->paged = space->paged;
538 aop->aopu.aop_stk = sym->stack;
542 /* if in bit space */
543 if (IN_BITSPACE (space))
545 sym->aop = aop = newAsmop (AOP_CRY);
546 aop->aopu.aop_dir = sym->rname;
547 aop->size = getSize (sym->type);
550 /* if it is in direct space */
551 if (IN_DIRSPACE (space))
553 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
554 //printTypeChainRaw(sym->type, NULL);
555 //printf("space = %s\n", space ? space->sname : "NULL");
556 sym->aop = aop = newAsmop (AOP_DIR);
557 aop->aopu.aop_dir = sym->rname;
558 aop->size = getSize (sym->type);
562 /* special case for a function */
563 if (IS_FUNC (sym->type))
565 sym->aop = aop = newAsmop (AOP_IMMD);
566 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
567 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
568 aop->size = FPTRSIZE;
572 /* only remaining is far space */
573 /* in which case DPTR gets the address */
574 sym->aop = aop = newAsmop (AOP_DPTR);
575 emitcode ("mov", "dptr,#%s", sym->rname);
576 aop->size = getSize (sym->type);
578 /* if it is in code space */
579 if (IN_CODESPACE (space))
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object */
587 /*-----------------------------------------------------------------*/
589 aopForRemat (symbol * sym)
591 iCode *ic = sym->rematiCode;
592 asmop *aop = newAsmop (AOP_IMMD);
599 val += (int) operandLitValue (IC_RIGHT (ic));
600 else if (ic->op == '-')
601 val -= (int) operandLitValue (IC_RIGHT (ic));
602 else if (IS_CAST_ICODE(ic)) {
603 sym_link *from_type = operandType(IC_RIGHT(ic));
604 aop->aopu.aop_immd.from_cast_remat = 1;
605 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
606 ptr_type = DCL_TYPE(from_type);
607 if (ptr_type == IPOINTER) {
614 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
618 sprintf (buffer, "(%s %c 0x%04x)",
619 OP_SYMBOL (IC_LEFT (ic))->rname,
620 val >= 0 ? '+' : '-',
623 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
625 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
626 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
627 /* set immd2 field if required */
628 if (aop->aopu.aop_immd.from_cast_remat) {
629 sprintf(buffer,"#0x%02x",ptr_type);
630 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
631 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
637 /*-----------------------------------------------------------------*/
638 /* regsInCommon - two operands have some registers in common */
639 /*-----------------------------------------------------------------*/
641 regsInCommon (operand * op1, operand * op2)
646 /* if they have registers in common */
647 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
650 sym1 = OP_SYMBOL (op1);
651 sym2 = OP_SYMBOL (op2);
653 if (sym1->nRegs == 0 || sym2->nRegs == 0)
656 for (i = 0; i < sym1->nRegs; i++)
662 for (j = 0; j < sym2->nRegs; j++)
667 if (sym2->regs[j] == sym1->regs[i])
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent */
677 /*-----------------------------------------------------------------*/
679 operandsEqu (operand * op1, operand * op2)
683 /* if they're not symbols */
684 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
687 sym1 = OP_SYMBOL (op1);
688 sym2 = OP_SYMBOL (op2);
690 /* if both are itemps & one is spilt
691 and the other is not then false */
692 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
693 sym1->isspilt != sym2->isspilt)
696 /* if they are the same */
700 /* if they have the same rname */
701 if (sym1->rname[0] && sym2->rname[0]
702 && strcmp (sym1->rname, sym2->rname) == 0)
705 /* if left is a tmp & right is not */
706 if (IS_ITEMP (op1) &&
709 (sym1->usl.spillLoc == sym2))
712 if (IS_ITEMP (op2) &&
716 (sym2->usl.spillLoc == sym1))
722 /*-----------------------------------------------------------------*/
723 /* sameRegs - two asmops have the same registers */
724 /*-----------------------------------------------------------------*/
726 sameRegs (asmop * aop1, asmop * aop2)
733 if (aop1->type != AOP_REG ||
734 aop2->type != AOP_REG)
737 if (aop1->size != aop2->size)
740 for (i = 0; i < aop1->size; i++)
741 if (aop1->aopu.aop_reg[i] !=
742 aop2->aopu.aop_reg[i])
748 /*-----------------------------------------------------------------*/
749 /* aopOp - allocates an asmop for an operand : */
750 /*-----------------------------------------------------------------*/
752 aopOp (operand * op, iCode * ic, bool result)
761 /* if this a literal */
762 if (IS_OP_LITERAL (op))
764 op->aop = aop = newAsmop (AOP_LIT);
765 aop->aopu.aop_lit = op->operand.valOperand;
766 aop->size = getSize (operandType (op));
770 /* if already has a asmop then continue */
774 /* if the underlying symbol has a aop */
775 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
777 op->aop = OP_SYMBOL (op)->aop;
781 /* if this is a true symbol */
782 if (IS_TRUE_SYMOP (op))
784 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
788 /* this is a temporary : this has
794 e) can be a return use only */
796 sym = OP_SYMBOL (op);
798 /* if the type is a conditional */
799 if (sym->regType == REG_CND)
801 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
806 /* if it is spilt then two situations
808 b) has a spill location */
809 if (sym->isspilt || sym->nRegs == 0)
812 /* rematerialize it NOW */
815 sym->aop = op->aop = aop =
817 aop->size = getSize (sym->type);
824 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
825 aop->size = getSize (sym->type);
826 for (i = 0; i < 2; i++)
827 aop->aopu.aop_str[i] = accUse[i];
835 aop = op->aop = sym->aop = newAsmop (AOP_STR);
836 aop->size = getSize (sym->type);
837 for (i = 0; i < fReturnSizeMCS51; i++)
838 aop->aopu.aop_str[i] = fReturn[i];
842 if (sym->usl.spillLoc)
844 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
846 /* force a new aop if sizes differ */
847 sym->usl.spillLoc->aop = NULL;
849 sym->aop = op->aop = aop =
850 aopForSym (ic, sym->usl.spillLoc, result);
851 aop->size = getSize (sym->type);
855 /* else must be a dummy iTemp */
856 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
857 aop->size = getSize (sym->type);
861 /* must be in a register */
862 sym->aop = op->aop = aop = newAsmop (AOP_REG);
863 aop->size = sym->nRegs;
864 for (i = 0; i < sym->nRegs; i++)
865 aop->aopu.aop_reg[i] = sym->regs[i];
868 /*-----------------------------------------------------------------*/
869 /* freeAsmop - free up the asmop given to an operand */
870 /*----------------------------------------------------------------*/
872 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
889 /* depending on the asmop type only three cases need work AOP_RO
890 , AOP_R1 && AOP_STK */
896 emitcode ("mov", "r0,b");
899 else if (_G.r0Pushed)
903 emitcode ("pop", "ar0");
907 bitVectUnSetBit (ic->rUsed, R0_IDX);
913 emitcode ("mov", "r1,b");
920 emitcode ("pop", "ar1");
924 bitVectUnSetBit (ic->rUsed, R1_IDX);
930 int stk = aop->aopu.aop_stk + aop->size - 1;
931 bitVectUnSetBit (ic->rUsed, R0_IDX);
932 bitVectUnSetBit (ic->rUsed, R1_IDX);
934 getFreePtr (ic, &aop, FALSE);
938 emitcode ("mov", "a,_bp");
939 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
940 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
944 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
949 emitcode ("pop", "acc");
950 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
953 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
956 freeAsmop (op, NULL, ic, TRUE);
959 emitcode ("pop", "ar1");
965 emitcode ("pop", "ar0");
972 /* all other cases just dealloc */
978 OP_SYMBOL (op)->aop = NULL;
979 /* if the symbol has a spill */
981 SPIL_LOC (op)->aop = NULL;
986 /*------------------------------------------------------------------*/
987 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
988 /* pop r0 or r1 off stack if pushed */
989 /*------------------------------------------------------------------*/
991 freeForBranchAsmop (operand * op)
1011 emitcode ("mov", "r0,b");
1013 else if (_G.r0Pushed)
1015 emitcode ("pop", "ar0");
1022 emitcode ("mov", "r1,b");
1024 else if (_G.r1Pushed)
1026 emitcode ("pop", "ar1");
1033 int stk = aop->aopu.aop_stk + aop->size - 1;
1035 emitcode ("mov", "b,r0");
1038 emitcode ("mov", "a,_bp");
1039 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1040 emitcode ("mov", "r0,a");
1044 emitcode ("mov", "r0,_bp");
1049 emitcode ("pop", "acc");
1050 emitcode ("mov", "@r0,a");
1053 emitcode ("dec", "r0");
1055 emitcode ("mov", "r0,b");
1061 /*-----------------------------------------------------------------*/
1062 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1063 /* clobber the accumulator */
1064 /*-----------------------------------------------------------------*/
1066 aopGetUsesAcc (asmop *aop, int offset)
1068 if (offset > (aop->size - 1))
1086 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1095 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1101 /* Error case --- will have been caught already */
1107 /*-----------------------------------------------------------------*/
1108 /* aopGet - for fetching value of the aop */
1109 /*-----------------------------------------------------------------*/
1111 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1116 /* offset is greater than
1118 if (offset > (aop->size - 1) &&
1119 aop->type != AOP_LIT)
1122 /* depending on type */
1130 /* if we need to increment it */
1131 while (offset > aop->coff)
1133 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1137 while (offset < aop->coff)
1139 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1146 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1147 return (dname ? "acc" : "a");
1149 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1150 rs = Safe_calloc (1, strlen (s) + 1);
1155 if (aop->code && aop->coff==0 && offset>=1) {
1156 emitcode ("mov", "a,#0x%02x", offset);
1157 emitcode ("movc", "a,@a+dptr");
1158 return (dname ? "acc" : "a");
1161 while (offset > aop->coff)
1163 emitcode ("inc", "dptr");
1167 while (offset < aop->coff)
1169 emitcode ("lcall", "__decdptr");
1176 emitcode ("clr", "a");
1177 emitcode ("movc", "a,@a+dptr");
1181 emitcode ("movx", "a,@dptr");
1183 return (dname ? "acc" : "a");
1187 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1188 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1190 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1192 sprintf (s, "#(%s >> %d)",
1193 aop->aopu.aop_immd.aop_immd1,
1197 aop->aopu.aop_immd.aop_immd1);
1198 rs = Safe_calloc (1, strlen (s) + 1);
1204 sprintf (s, "(%s + %d)",
1208 sprintf (s, "%s", aop->aopu.aop_dir);
1209 rs = Safe_calloc (1, strlen (s) + 1);
1215 return aop->aopu.aop_reg[offset]->dname;
1217 return aop->aopu.aop_reg[offset]->name;
1220 emitcode ("clr", "a");
1221 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1222 emitcode ("rlc", "a");
1223 return (dname ? "acc" : "a");
1226 if (!offset && dname)
1228 return aop->aopu.aop_str[offset];
1231 return aopLiteral (aop->aopu.aop_lit, offset);
1235 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1239 return aop->aopu.aop_str[offset];
1243 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1244 "aopget got unsupported aop->type");
1247 /*-----------------------------------------------------------------*/
1248 /* aopPut - puts a string for a aop */
1249 /*-----------------------------------------------------------------*/
1251 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1255 if (aop->size && offset > (aop->size - 1))
1257 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1258 "aopPut got offset > aop->size");
1262 /* will assign value to value */
1263 /* depending on where it is ofcourse */
1267 MOVA (s); /* read s in case it was volatile */
1272 sprintf (d, "(%s + %d)",
1273 aop->aopu.aop_dir, offset);
1275 sprintf (d, "%s", aop->aopu.aop_dir);
1277 if (strcmp (d, s) ||
1279 emitcode ("mov", "%s,%s", d, s);
1284 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1285 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1288 strcmp (s, "r0") == 0 ||
1289 strcmp (s, "r1") == 0 ||
1290 strcmp (s, "r2") == 0 ||
1291 strcmp (s, "r3") == 0 ||
1292 strcmp (s, "r4") == 0 ||
1293 strcmp (s, "r5") == 0 ||
1294 strcmp (s, "r6") == 0 ||
1295 strcmp (s, "r7") == 0)
1296 emitcode ("mov", "%s,%s",
1297 aop->aopu.aop_reg[offset]->dname, s);
1299 emitcode ("mov", "%s,%s",
1300 aop->aopu.aop_reg[offset]->name, s);
1307 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1308 "aopPut writing to code space");
1312 while (offset > aop->coff)
1315 emitcode ("inc", "dptr");
1318 while (offset < aop->coff)
1321 emitcode ("lcall", "__decdptr");
1326 /* if not in accumulater */
1329 emitcode ("movx", "@dptr,a");
1334 while (offset > aop->coff)
1337 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1339 while (offset < aop->coff)
1342 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1349 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1355 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1357 else if (strcmp (s, "r0") == 0 ||
1358 strcmp (s, "r1") == 0 ||
1359 strcmp (s, "r2") == 0 ||
1360 strcmp (s, "r3") == 0 ||
1361 strcmp (s, "r4") == 0 ||
1362 strcmp (s, "r5") == 0 ||
1363 strcmp (s, "r6") == 0 ||
1364 strcmp (s, "r7") == 0)
1367 sprintf (buffer, "a%s", s);
1368 emitcode ("mov", "@%s,%s",
1369 aop->aopu.aop_ptr->name, buffer);
1372 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1377 if (strcmp (s, "a") == 0)
1378 emitcode ("push", "acc");
1382 emitcode ("push", "acc");
1384 emitcode ("push", s);
1390 /* if bit variable */
1391 if (!aop->aopu.aop_dir)
1393 emitcode ("clr", "a");
1394 emitcode ("rlc", "a");
1399 emitcode ("clr", "%s", aop->aopu.aop_dir);
1401 emitcode ("setb", "%s", aop->aopu.aop_dir);
1402 else if (!strcmp (s, "c"))
1403 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1406 if (strcmp (s, "a"))
1411 /* set C, if a >= 1 */
1412 emitcode ("add", "a,#0xff");
1413 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1421 if (strcmp (aop->aopu.aop_str[offset], s) ||
1423 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1428 if (!offset && (strcmp (s, "acc") == 0) &&
1432 if (strcmp (aop->aopu.aop_str[offset], s) &&
1434 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1438 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439 "aopPut got unsupported aop->type");
1447 /*-----------------------------------------------------------------*/
1448 /* pointToEnd :- points to the last byte of the operand */
1449 /*-----------------------------------------------------------------*/
1451 pointToEnd (asmop * aop)
1457 aop->coff = count = (aop->size - 1);
1463 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1467 emitcode ("inc", "dptr");
1474 /*-----------------------------------------------------------------*/
1475 /* reAdjustPreg - points a register back to where it should */
1476 /*-----------------------------------------------------------------*/
1478 reAdjustPreg (asmop * aop)
1480 if ((aop->coff==0) || aop->size <= 1)
1488 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1493 emitcode ("lcall", "__decdptr");
1500 #define AOP(op) op->aop
1501 #define AOP_TYPE(op) AOP(op)->type
1502 #define AOP_SIZE(op) AOP(op)->size
1503 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1504 AOP_TYPE(x) == AOP_R0))
1506 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1507 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1509 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1510 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1511 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1514 /*-----------------------------------------------------------------*/
1515 /* opIsGptr: returns non-zero if the passed operand is */
1516 /* a generic pointer type. */
1517 /*-----------------------------------------------------------------*/
1519 opIsGptr (operand * op)
1521 sym_link *type = operandType (op);
1523 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1530 /*-----------------------------------------------------------------*/
1531 /* getDataSize - get the operand data size */
1532 /*-----------------------------------------------------------------*/
1534 getDataSize (operand * op)
1537 size = AOP_SIZE (op);
1538 if (size == GPTRSIZE)
1540 sym_link *type = operandType (op);
1541 if (IS_GENPTR (type))
1543 /* generic pointer; arithmetic operations
1544 * should ignore the high byte (pointer type).
1552 /*-----------------------------------------------------------------*/
1553 /* outAcc - output Acc */
1554 /*-----------------------------------------------------------------*/
1556 outAcc (operand * result)
1559 size = getDataSize (result);
1562 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1565 /* unsigned or positive */
1568 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1573 /*-----------------------------------------------------------------*/
1574 /* outBitC - output a bit C */
1575 /*-----------------------------------------------------------------*/
1577 outBitC (operand * result)
1579 /* if the result is bit */
1580 if (AOP_TYPE (result) == AOP_CRY)
1581 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1584 emitcode ("clr", "a");
1585 emitcode ("rlc", "a");
1590 /*-----------------------------------------------------------------*/
1591 /* toBoolean - emit code for orl a,operator(sizeop) */
1592 /*-----------------------------------------------------------------*/
1594 toBoolean (operand * oper)
1596 int size = AOP_SIZE (oper) - 1;
1598 bool AccUsed = FALSE;
1601 while (!AccUsed && size--)
1603 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1606 size = AOP_SIZE (oper) - 1;
1608 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1609 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1612 emitcode("mov", "b,a");
1615 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1616 emitcode ("orl", "b,a");
1624 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1630 /*-----------------------------------------------------------------*/
1631 /* genNot - generate code for ! operation */
1632 /*-----------------------------------------------------------------*/
1638 D(emitcode ("; genNot",""));
1640 /* assign asmOps to operand & result */
1641 aopOp (IC_LEFT (ic), ic, FALSE);
1642 aopOp (IC_RESULT (ic), ic, TRUE);
1644 /* if in bit space then a special case */
1645 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1647 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1648 emitcode ("cpl", "c");
1649 outBitC (IC_RESULT (ic));
1653 toBoolean (IC_LEFT (ic));
1655 tlbl = newiTempLabel (NULL);
1656 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1657 emitcode ("", "%05d$:", tlbl->key + 100);
1658 outBitC (IC_RESULT (ic));
1661 /* release the aops */
1662 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1667 /*-----------------------------------------------------------------*/
1668 /* genCpl - generate code for complement */
1669 /*-----------------------------------------------------------------*/
1676 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1678 D(emitcode (";", "genCpl"));
1680 /* assign asmOps to operand & result */
1681 aopOp (IC_LEFT (ic), ic, FALSE);
1682 aopOp (IC_RESULT (ic), ic, TRUE);
1684 /* special case if in bit space */
1685 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1689 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1690 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1692 /* promotion rules are responsible for this strange result:
1693 bit -> int -> ~int -> bit
1694 uchar -> int -> ~int -> bit
1696 werror(W_COMPLEMENT);
1697 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1701 tlbl=newiTempLabel(NULL);
1702 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1703 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1704 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1705 IS_AOP_PREG (IC_LEFT (ic)))
1707 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1712 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1714 emitcode ("", "%05d$:", tlbl->key + 100);
1715 outBitC (IC_RESULT(ic));
1719 size = AOP_SIZE (IC_RESULT (ic));
1722 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1724 emitcode ("cpl", "a");
1725 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1730 /* release the aops */
1731 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1732 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1735 /*-----------------------------------------------------------------*/
1736 /* genUminusFloat - unary minus for floating points */
1737 /*-----------------------------------------------------------------*/
1739 genUminusFloat (operand * op, operand * result)
1741 int size, offset = 0;
1744 D(emitcode ("; genUminusFloat",""));
1746 /* for this we just copy and then flip the bit */
1748 size = AOP_SIZE (op) - 1;
1752 aopPut (AOP (result),
1753 aopGet (AOP (op), offset, FALSE, FALSE),
1755 isOperandVolatile (result, FALSE));
1759 l = aopGet (AOP (op), offset, FALSE, FALSE);
1763 emitcode ("cpl", "acc.7");
1764 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1767 /*-----------------------------------------------------------------*/
1768 /* genUminus - unary minus code generation */
1769 /*-----------------------------------------------------------------*/
1771 genUminus (iCode * ic)
1774 sym_link *optype, *rtype;
1777 D(emitcode ("; genUminus",""));
1780 aopOp (IC_LEFT (ic), ic, FALSE);
1781 aopOp (IC_RESULT (ic), ic, TRUE);
1783 /* if both in bit space then special
1785 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1786 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1789 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1790 emitcode ("cpl", "c");
1791 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1795 optype = operandType (IC_LEFT (ic));
1796 rtype = operandType (IC_RESULT (ic));
1798 /* if float then do float stuff */
1799 if (IS_FLOAT (optype))
1801 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1805 /* otherwise subtract from zero */
1806 size = AOP_SIZE (IC_LEFT (ic));
1811 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1812 if (!strcmp (l, "a"))
1816 emitcode ("cpl", "a");
1817 emitcode ("addc", "a,#0");
1823 emitcode ("clr", "a");
1824 emitcode ("subb", "a,%s", l);
1826 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1829 /* if any remaining bytes in the result */
1830 /* we just need to propagate the sign */
1831 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1833 emitcode ("rlc", "a");
1834 emitcode ("subb", "a,acc");
1836 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1840 /* release the aops */
1841 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* saveRegisters - will look for a call and save the registers */
1847 /*-----------------------------------------------------------------*/
1849 saveRegisters (iCode * lic)
1856 for (ic = lic; ic; ic = ic->next)
1857 if (ic->op == CALL || ic->op == PCALL)
1862 fprintf (stderr, "found parameter push with no function call\n");
1866 /* if the registers have been saved already or don't need to be then
1870 if (IS_SYMOP(IC_LEFT(ic)) &&
1871 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1872 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1875 /* save the registers in use at this time but skip the
1876 ones for the result */
1877 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1878 mcs51_rUmaskForOp (IC_RESULT(ic)));
1881 if (options.useXstack)
1883 int count = bitVectnBitsOn (rsave);
1887 i = bitVectFirstBit (rsave);
1888 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1889 emitcode ("mov", "r0,%s", spname);
1890 emitcode ("inc", "%s", spname);// allocate before use
1891 emitcode ("movx", "@r0,a");
1892 if (bitVectBitValue (rsave, R0_IDX))
1893 emitcode ("mov", "r0,a");
1895 else if (count != 0)
1897 if (bitVectBitValue (rsave, R0_IDX))
1899 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1901 emitcode ("mov", "r0,%s", spname);
1903 emitcode ("add", "a,#%d", count);
1904 emitcode ("mov", "%s,a", spname);
1905 for (i = 0; i < mcs51_nRegs; i++)
1907 if (bitVectBitValue (rsave, i))
1911 emitcode ("pop", "acc");
1912 emitcode ("push", "acc");
1916 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1918 emitcode ("movx", "@r0,a");
1921 emitcode ("inc", "r0");
1925 if (bitVectBitValue (rsave, R0_IDX))
1927 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1932 for (i = 0; i < mcs51_nRegs; i++)
1934 if (bitVectBitValue (rsave, i))
1935 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1939 /*-----------------------------------------------------------------*/
1940 /* unsaveRegisters - pop the pushed registers */
1941 /*-----------------------------------------------------------------*/
1943 unsaveRegisters (iCode * ic)
1948 /* restore the registers in use at this time but skip the
1949 ones for the result */
1950 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1951 mcs51_rUmaskForOp (IC_RESULT(ic)));
1953 if (options.useXstack)
1955 int count = bitVectnBitsOn (rsave);
1959 emitcode ("mov", "r0,%s", spname);
1960 emitcode ("dec", "r0");
1961 emitcode ("movx", "a,@r0");
1962 i = bitVectFirstBit (rsave);
1963 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1964 emitcode ("dec", "%s", spname);
1968 emitcode ("mov", "r0,%s", spname);
1969 for (i = mcs51_nRegs; i >= 0; i--)
1971 if (bitVectBitValue (rsave, i))
1973 emitcode ("dec", "r0");
1974 emitcode ("movx", "a,@r0");
1976 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1979 emitcode ("mov", "%s,r0", spname);
1980 if (bitVectBitValue (rsave, R0_IDX))
1982 emitcode ("mov", "r0,a");
1987 for (i = mcs51_nRegs; i >= 0; i--)
1989 if (bitVectBitValue (rsave, i))
1990 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1995 /*-----------------------------------------------------------------*/
1997 /*-----------------------------------------------------------------*/
1999 pushSide (operand * oper, int size)
2004 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2005 if (AOP_TYPE (oper) != AOP_REG &&
2006 AOP_TYPE (oper) != AOP_DIR &&
2010 emitcode ("push", "acc");
2013 emitcode ("push", "%s", l);
2017 /*-----------------------------------------------------------------*/
2018 /* assignResultValue - */
2019 /*-----------------------------------------------------------------*/
2021 assignResultValue (operand * oper)
2024 int size = AOP_SIZE (oper);
2027 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2033 /*-----------------------------------------------------------------*/
2034 /* genXpush - pushes onto the external stack */
2035 /*-----------------------------------------------------------------*/
2037 genXpush (iCode * ic)
2039 asmop *aop = newAsmop (0);
2041 int size, offset = 0;
2043 D(emitcode ("; genXpush",""));
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2046 r = getFreePtr (ic, &aop, FALSE);
2048 size = AOP_SIZE (IC_LEFT (ic));
2052 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2053 emitcode ("mov", "%s,%s", r->name, spname);
2054 emitcode ("inc", "%s", spname); // allocate space first
2055 emitcode ("movx", "@%s,a", r->name);
2059 // allocate space first
2060 emitcode ("mov", "%s,%s", r->name, spname);
2062 emitcode ("add", "a,#%d", size);
2063 emitcode ("mov", "%s,a", spname);
2067 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2068 emitcode ("movx", "@%s,a", r->name);
2069 emitcode ("inc", "%s", r->name);
2073 freeAsmop (NULL, aop, ic, TRUE);
2074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2077 /*-----------------------------------------------------------------*/
2078 /* genIpush - genrate code for pushing this gets a little complex */
2079 /*-----------------------------------------------------------------*/
2081 genIpush (iCode * ic)
2083 int size, offset = 0;
2086 D(emitcode ("; genIpush",""));
2088 /* if this is not a parm push : ie. it is spill push
2089 and spill push is always done on the local stack */
2093 /* and the item is spilt then do nothing */
2094 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2097 aopOp (IC_LEFT (ic), ic, FALSE);
2098 size = AOP_SIZE (IC_LEFT (ic));
2099 /* push it on the stack */
2102 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2108 emitcode ("push", "%s", l);
2113 /* this is a paramter push: in this case we call
2114 the routine to find the call and save those
2115 registers that need to be saved */
2118 /* if use external stack then call the external
2119 stack pushing routine */
2120 if (options.useXstack)
2126 /* then do the push */
2127 aopOp (IC_LEFT (ic), ic, FALSE);
2129 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2130 size = AOP_SIZE (IC_LEFT (ic));
2134 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2135 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2136 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2140 emitcode ("push", "acc");
2143 emitcode ("push", "%s", l);
2146 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2149 /*-----------------------------------------------------------------*/
2150 /* genIpop - recover the registers: can happen only for spilling */
2151 /*-----------------------------------------------------------------*/
2153 genIpop (iCode * ic)
2157 D(emitcode ("; genIpop",""));
2159 /* if the temp was not pushed then */
2160 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2163 aopOp (IC_LEFT (ic), ic, FALSE);
2164 size = AOP_SIZE (IC_LEFT (ic));
2165 offset = (size - 1);
2167 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2170 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2173 /*-----------------------------------------------------------------*/
2174 /* saveRBank - saves an entire register bank on the stack */
2175 /*-----------------------------------------------------------------*/
2177 saveRBank (int bank, iCode * ic, bool pushPsw)
2180 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2184 if (options.useXstack)
2188 /* Assume r0 is available for use. */
2189 r = mcs51_regWithIdx (R0_IDX);;
2194 r = getFreePtr (ic, &aop, FALSE);
2196 // allocate space first
2197 emitcode ("mov", "%s,%s", r->name, spname);
2199 emitcode ("add", "a,#%d", count);
2200 emitcode ("mov", "%s,a", spname);
2203 for (i = 0; i < mcs51_nRegs; i++)
2205 if (options.useXstack)
2207 emitcode ("mov", "a,(%s+%d)",
2208 regs8051[i].base, 8 * bank + regs8051[i].offset);
2209 emitcode ("movx", "@%s,a", r->name);
2211 emitcode ("inc", "%s", r->name);
2214 emitcode ("push", "(%s+%d)",
2215 regs8051[i].base, 8 * bank + regs8051[i].offset);
2220 if (options.useXstack)
2222 emitcode ("mov", "a,psw");
2223 emitcode ("movx", "@%s,a", r->name);
2228 emitcode ("push", "psw");
2231 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2236 freeAsmop (NULL, aop, ic, TRUE);
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRBank - restores the register bank from stack */
2247 /*-----------------------------------------------------------------*/
2249 unsaveRBank (int bank, iCode * ic, bool popPsw)
2255 if (options.useXstack)
2259 /* Assume r0 is available for use. */
2260 r = mcs51_regWithIdx (R0_IDX);;
2265 r = getFreePtr (ic, &aop, FALSE);
2267 emitcode ("mov", "%s,%s", r->name, spname);
2272 if (options.useXstack)
2274 emitcode ("dec", "%s", r->name);
2275 emitcode ("movx", "a,@%s", r->name);
2276 emitcode ("mov", "psw,a");
2280 emitcode ("pop", "psw");
2284 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2286 if (options.useXstack)
2288 emitcode ("dec", "%s", r->name);
2289 emitcode ("movx", "a,@%s", r->name);
2290 emitcode ("mov", "(%s+%d),a",
2291 regs8051[i].base, 8 * bank + regs8051[i].offset);
2295 emitcode ("pop", "(%s+%d)",
2296 regs8051[i].base, 8 * bank + regs8051[i].offset);
2300 if (options.useXstack)
2302 emitcode ("mov", "%s,%s", spname, r->name);
2307 freeAsmop (NULL, aop, ic, TRUE);
2311 /*-----------------------------------------------------------------*/
2312 /* genSend - gen code for SEND */
2313 /*-----------------------------------------------------------------*/
2314 static void genSend(set *sendSet)
2319 for (sic = setFirstItem (sendSet); sic;
2320 sic = setNextItem (sendSet)) {
2321 int size, offset = 0;
2322 aopOp (IC_LEFT (sic), sic, FALSE);
2323 size = AOP_SIZE (IC_LEFT (sic));
2325 if (sic->argreg == 1) {
2327 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2329 if (strcmp (l, fReturn[offset]))
2330 emitcode ("mov", "%s,%s", fReturn[offset], l);
2336 emitcode ("mov","b1_%d,%s",rb1_count++,
2337 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2340 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2344 /*-----------------------------------------------------------------*/
2345 /* genCall - generates a call statement */
2346 /*-----------------------------------------------------------------*/
2348 genCall (iCode * ic)
2351 // bool restoreBank = FALSE;
2352 bool swapBanks = FALSE;
2354 D(emitcode("; genCall",""));
2356 dtype = operandType (IC_LEFT (ic));
2357 /* if send set is not empty then assign */
2360 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2361 genSend(reverseSet(_G.sendSet));
2363 genSend(_G.sendSet);
2369 /* if we are calling a not _naked function that is not using
2370 the same register bank then we need to save the
2371 destination registers on the stack */
2372 dtype = operandType (IC_LEFT (ic));
2373 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2374 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2375 !IFFUNC_ISISR (dtype))
2380 /* if caller saves & we have not saved then */
2386 emitcode ("mov", "psw,#0x%02x",
2387 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2391 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2392 OP_SYMBOL (IC_LEFT (ic))->rname :
2393 OP_SYMBOL (IC_LEFT (ic))->name));
2397 emitcode ("mov", "psw,#0x%02x",
2398 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2401 /* if we need assign a result value */
2402 if ((IS_ITEMP (IC_RESULT (ic)) &&
2403 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2404 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2405 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2406 IS_TRUE_SYMOP (IC_RESULT (ic)))
2410 aopOp (IC_RESULT (ic), ic, FALSE);
2413 assignResultValue (IC_RESULT (ic));
2415 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2418 /* adjust the stack for parameters if
2423 if (ic->parmBytes > 3)
2425 emitcode ("mov", "a,%s", spname);
2426 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2427 emitcode ("mov", "%s,a", spname);
2430 for (i = 0; i < ic->parmBytes; i++)
2431 emitcode ("dec", "%s", spname);
2434 /* if we hade saved some registers then unsave them */
2435 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2436 unsaveRegisters (ic);
2438 // /* if register bank was saved then pop them */
2440 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2443 /*-----------------------------------------------------------------*/
2444 /* -10l - generates a call by pointer statement */
2445 /*-----------------------------------------------------------------*/
2447 genPcall (iCode * ic)
2450 symbol *rlbl = newiTempLabel (NULL);
2451 // bool restoreBank=FALSE;
2452 bool swapBanks = FALSE;
2454 D(emitcode("; genPCall",""));
2456 /* if caller saves & we have not saved then */
2460 /* if we are calling a not _naked function that is not using
2461 the same register bank then we need to save the
2462 destination registers on the stack */
2463 dtype = operandType (IC_LEFT (ic))->next;
2464 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2465 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2466 !IFFUNC_ISISR (dtype))
2468 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2469 // restoreBank=TRUE;
2471 // need caution message to user here
2474 /* push the return address on to the stack */
2475 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2476 emitcode ("push", "acc");
2477 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2478 emitcode ("push", "acc");
2480 /* now push the calling address */
2481 aopOp (IC_LEFT (ic), ic, FALSE);
2483 pushSide (IC_LEFT (ic), FPTRSIZE);
2485 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2487 /* if send set is not empty the assign */
2490 genSend(reverseSet(_G.sendSet));
2496 emitcode ("mov", "psw,#0x%02x",
2497 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2501 emitcode ("ret", "");
2502 emitcode ("", "%05d$:", (rlbl->key + 100));
2507 emitcode ("mov", "psw,#0x%02x",
2508 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2511 /* if we need assign a result value */
2512 if ((IS_ITEMP (IC_RESULT (ic)) &&
2513 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2514 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2515 IS_TRUE_SYMOP (IC_RESULT (ic)))
2519 aopOp (IC_RESULT (ic), ic, FALSE);
2522 assignResultValue (IC_RESULT (ic));
2524 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2527 /* adjust the stack for parameters if
2532 if (ic->parmBytes > 3)
2534 emitcode ("mov", "a,%s", spname);
2535 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2536 emitcode ("mov", "%s,a", spname);
2539 for (i = 0; i < ic->parmBytes; i++)
2540 emitcode ("dec", "%s", spname);
2544 // /* if register bank was saved then unsave them */
2546 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2548 /* if we hade saved some registers then
2550 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2551 unsaveRegisters (ic);
2554 /*-----------------------------------------------------------------*/
2555 /* resultRemat - result is rematerializable */
2556 /*-----------------------------------------------------------------*/
2558 resultRemat (iCode * ic)
2560 if (SKIP_IC (ic) || ic->op == IFX)
2563 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2565 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2566 if (sym->remat && !POINTER_SET (ic))
2573 #if defined(__BORLANDC__) || defined(_MSC_VER)
2574 #define STRCASECMP stricmp
2576 #define STRCASECMP strcasecmp
2579 /*-----------------------------------------------------------------*/
2580 /* inExcludeList - return 1 if the string is in exclude Reg list */
2581 /*-----------------------------------------------------------------*/
2583 regsCmp(void *p1, void *p2)
2585 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2589 inExcludeList (char *s)
2591 const char *p = setFirstItem(options.excludeRegsSet);
2593 if (p == NULL || STRCASECMP(p, "none") == 0)
2597 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2600 /*-----------------------------------------------------------------*/
2601 /* genFunction - generated code for function entry */
2602 /*-----------------------------------------------------------------*/
2604 genFunction (iCode * ic)
2606 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2608 bool switchedPSW = FALSE;
2609 int calleesaves_saved_register = -1;
2610 int stackAdjust = sym->stack;
2611 int accIsFree = sym->recvSize < 4;
2612 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2613 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2616 /* create the function header */
2617 emitcode (";", "-----------------------------------------");
2618 emitcode (";", " function %s", sym->name);
2619 emitcode (";", "-----------------------------------------");
2621 emitcode ("", "%s:", sym->rname);
2622 ftype = operandType (IC_LEFT (ic));
2623 _G.currentFunc = sym;
2625 if (IFFUNC_ISNAKED(ftype))
2627 emitcode(";", "naked function: no prologue.");
2631 /* here we need to generate the equates for the
2632 register bank if required */
2633 if (FUNC_REGBANK (ftype) != rbank)
2637 rbank = FUNC_REGBANK (ftype);
2638 for (i = 0; i < mcs51_nRegs; i++)
2640 if (strcmp (regs8051[i].base, "0") == 0)
2641 emitcode ("", "%s = 0x%02x",
2643 8 * rbank + regs8051[i].offset);
2645 emitcode ("", "%s = %s + 0x%02x",
2648 8 * rbank + regs8051[i].offset);
2652 /* if this is an interrupt service routine then
2653 save acc, b, dpl, dph */
2654 if (IFFUNC_ISISR (sym->type))
2657 if (!inExcludeList ("acc"))
2658 emitcode ("push", "acc");
2659 if (!inExcludeList ("b"))
2660 emitcode ("push", "b");
2661 if (!inExcludeList ("dpl"))
2662 emitcode ("push", "dpl");
2663 if (!inExcludeList ("dph"))
2664 emitcode ("push", "dph");
2665 /* if this isr has no bank i.e. is going to
2666 run with bank 0 , then we need to save more
2668 if (!FUNC_REGBANK (sym->type))
2671 /* if this function does not call any other
2672 function then we can be economical and
2673 save only those registers that are used */
2674 if (!IFFUNC_HASFCALL(sym->type))
2678 /* if any registers used */
2681 /* save the registers used */
2682 for (i = 0; i < sym->regsUsed->size; i++)
2684 if (bitVectBitValue (sym->regsUsed, i))
2685 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2692 /* this function has a function call. We cannot
2693 determines register usage so we will have to push the
2695 saveRBank (0, ic, FALSE);
2696 if (options.parms_in_bank1) {
2698 for (i=0; i < 8 ; i++ ) {
2699 emitcode ("push","%s",rb1regs[i]);
2706 /* This ISR uses a non-zero bank.
2708 * We assume that the bank is available for our
2711 * However, if this ISR calls a function which uses some
2712 * other bank, we must save that bank entirely.
2714 unsigned long banksToSave = 0;
2716 if (IFFUNC_HASFCALL(sym->type))
2719 #define MAX_REGISTER_BANKS 4
2724 for (i = ic; i; i = i->next)
2726 if (i->op == ENDFUNCTION)
2728 /* we got to the end OK. */
2736 dtype = operandType (IC_LEFT(i));
2738 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2740 /* Mark this bank for saving. */
2741 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2743 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2747 banksToSave |= (1 << FUNC_REGBANK(dtype));
2750 /* And note that we don't need to do it in
2758 /* This is a mess; we have no idea what
2759 * register bank the called function might
2762 * The only thing I can think of to do is
2763 * throw a warning and hope.
2765 werror(W_FUNCPTR_IN_USING_ISR);
2769 if (banksToSave && options.useXstack)
2771 /* Since we aren't passing it an ic,
2772 * saveRBank will assume r0 is available to abuse.
2774 * So switch to our (trashable) bank now, so
2775 * the caller's R0 isn't trashed.
2777 emitcode ("push", "psw");
2778 emitcode ("mov", "psw,#0x%02x",
2779 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2783 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2785 if (banksToSave & (1 << ix))
2787 saveRBank(ix, NULL, FALSE);
2791 // TODO: this needs a closer look
2792 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2795 /* Set the register bank to the desired value if nothing else */
2796 /* has done so yet. */
2799 emitcode ("push", "psw");
2800 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2805 /* This is a non-ISR function. The caller has already switched register */
2806 /* banks, if necessary, so just handle the callee-saves option. */
2808 /* if callee-save to be used for this function
2809 then save the registers being used in this function */
2810 if (IFFUNC_CALLEESAVES(sym->type))
2814 /* if any registers used */
2817 /* save the registers used */
2818 for (i = 0; i < sym->regsUsed->size; i++)
2820 if (bitVectBitValue (sym->regsUsed, i))
2822 /* remember one saved register for later usage */
2823 if (calleesaves_saved_register < 0)
2824 calleesaves_saved_register = i;
2825 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2836 if (options.useXstack)
2838 emitcode ("mov", "r0,%s", spname);
2839 emitcode ("inc", "%s", spname);
2840 emitcode ("xch", "a,_bp");
2841 emitcode ("movx", "@r0,a");
2842 emitcode ("inc", "r0");
2843 emitcode ("mov", "a,r0");
2844 emitcode ("xch", "a,_bp");
2848 /* set up the stack */
2849 emitcode ("push", "_bp"); /* save the callers stack */
2850 emitcode ("mov", "_bp,%s", spname);
2854 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2855 /* before setting up the stack frame completely. */
2856 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2858 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2862 if (rsym && rsym->regType == REG_CND)
2864 if (rsym && (rsym->accuse || rsym->ruonly))
2866 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2867 rsym = rsym->usl.spillLoc;
2870 /* If the RECEIVE operand immediately spills to the first entry on the */
2871 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2872 /* rather than the usual @r0/r1 machinations. */
2873 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2877 _G.current_iCode = ric;
2878 D(emitcode ("; genReceive",""));
2879 for (ofs=0; ofs < sym->recvSize; ofs++)
2881 if (!strcmp (fReturn[ofs], "a"))
2882 emitcode ("push", "acc");
2884 emitcode ("push", fReturn[ofs]);
2886 stackAdjust -= sym->recvSize;
2889 assert (stackAdjust>=0);
2892 _G.current_iCode = ic;
2896 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2897 /* to free up the accumulator. */
2898 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2902 _G.current_iCode = ric;
2903 D(emitcode ("; genReceive",""));
2904 for (ofs=0; ofs < sym->recvSize; ofs++)
2906 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2908 _G.current_iCode = ic;
2914 /* adjust the stack for the function */
2917 int i = stackAdjust;
2919 werror (W_STACK_OVERFLOW, sym->name);
2921 if (i > 3 && accIsFree)
2923 emitcode ("mov", "a,sp");
2924 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2925 emitcode ("mov", "sp,a");
2929 /* The accumulator is not free, so we will need another register */
2930 /* to clobber. No need to worry about a possible conflict with */
2931 /* the above early RECEIVE optimizations since they would have */
2932 /* freed the accumulator if they were generated. */
2934 if (IFFUNC_CALLEESAVES(sym->type))
2936 /* if it's a callee-saves function we need a saved register */
2937 if (calleesaves_saved_register >= 0)
2939 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2940 emitcode ("mov", "a,sp");
2941 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2942 emitcode ("mov", "sp,a");
2943 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2946 /* do it the hard way */
2948 emitcode ("inc", "sp");
2952 /* not callee-saves, we can clobber r0 */
2953 emitcode ("mov", "r0,a");
2954 emitcode ("mov", "a,sp");
2955 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2956 emitcode ("mov", "sp,a");
2957 emitcode ("mov", "a,r0");
2962 emitcode ("inc", "sp");
2967 char i = ((char) sym->xstack & 0xff);
2969 if (i > 3 && accIsFree)
2971 emitcode ("mov", "a,_spx");
2972 emitcode ("add", "a,#0x%02x", i);
2973 emitcode ("mov", "_spx,a");
2977 emitcode ("push", "acc");
2978 emitcode ("mov", "a,_spx");
2979 emitcode ("add", "a,#0x%02x", i);
2980 emitcode ("mov", "_spx,a");
2981 emitcode ("pop", "acc");
2986 emitcode ("inc", "_spx");
2990 /* if critical function then turn interrupts off */
2991 if (IFFUNC_ISCRITICAL (ftype))
2993 symbol *tlbl = newiTempLabel (NULL);
2994 emitcode ("setb", "c");
2995 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2996 emitcode ("clr", "c");
2997 emitcode ("", "%05d$:", (tlbl->key + 100));
2998 emitcode ("push", "psw"); /* save old ea via c in psw */
3002 /*-----------------------------------------------------------------*/
3003 /* genEndFunction - generates epilogue for functions */
3004 /*-----------------------------------------------------------------*/
3006 genEndFunction (iCode * ic)
3008 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3009 lineNode *lnp = lineCurr;
3011 bitVect *regsUsedPrologue;
3012 bitVect *regsUnneeded;
3013 int accIsFree = sym->recvSize < 4;
3016 _G.currentFunc = NULL;
3017 if (IFFUNC_ISNAKED(sym->type))
3019 emitcode(";", "naked function: no epilogue.");
3020 if (options.debug && currFunc)
3021 debugFile->writeEndFunction (currFunc, ic, 0);
3025 if (IFFUNC_ISCRITICAL (sym->type))
3027 emitcode ("pop", "psw"); /* restore ea via c in psw */
3028 emitcode ("mov", "ea,c");
3031 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3033 emitcode ("mov", "%s,_bp", spname);
3036 /* if use external stack but some variables were
3037 added to the local stack then decrement the
3039 if (options.useXstack && sym->stack)
3041 char count = sym->stack;
3043 if ((count>3) && accIsFree)
3045 emitcode ("mov", "a,sp");
3046 emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3047 emitcode ("mov", "sp,a");
3052 emitcode ("dec", "sp");
3056 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3058 if (options.useXstack)
3060 emitcode ("xch", "a,_bp");
3061 emitcode ("mov", "r0,a");
3062 emitcode ("dec", "r0");
3063 emitcode ("movx", "a,@r0");
3064 emitcode ("xch", "a,_bp");
3065 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3069 emitcode ("pop", "_bp");
3073 /* restore the register bank */
3074 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3076 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3077 || !options.useXstack)
3079 /* Special case of ISR using non-zero bank with useXstack
3082 emitcode ("pop", "psw");
3086 if (IFFUNC_ISISR (sym->type))
3089 /* now we need to restore the registers */
3090 /* if this isr has no bank i.e. is going to
3091 run with bank 0 , then we need to save more
3093 if (!FUNC_REGBANK (sym->type))
3095 /* if this function does not call any other
3096 function then we can be economical and
3097 save only those registers that are used */
3098 if (!IFFUNC_HASFCALL(sym->type))
3102 /* if any registers used */
3105 /* save the registers used */
3106 for (i = sym->regsUsed->size; i >= 0; i--)
3108 if (bitVectBitValue (sym->regsUsed, i))
3109 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3115 if (options.parms_in_bank1) {
3117 for (i = 7 ; i >= 0 ; i-- ) {
3118 emitcode ("pop","%s",rb1regs[i]);
3121 /* this function has a function call cannot
3122 determines register usage so we will have to pop the
3124 unsaveRBank (0, ic, FALSE);
3129 /* This ISR uses a non-zero bank.
3131 * Restore any register banks saved by genFunction
3134 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3137 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3139 if (savedBanks & (1 << ix))
3141 unsaveRBank(ix, NULL, FALSE);
3145 if (options.useXstack)
3147 /* Restore bank AFTER calling unsaveRBank,
3148 * since it can trash r0.
3150 emitcode ("pop", "psw");
3154 if (!inExcludeList ("dph"))
3155 emitcode ("pop", "dph");
3156 if (!inExcludeList ("dpl"))
3157 emitcode ("pop", "dpl");
3158 if (!inExcludeList ("b"))
3159 emitcode ("pop", "b");
3160 if (!inExcludeList ("acc"))
3161 emitcode ("pop", "acc");
3163 /* if debug then send end of function */
3164 if (options.debug && currFunc)
3166 debugFile->writeEndFunction (currFunc, ic, 1);
3169 emitcode ("reti", "");
3173 if (IFFUNC_CALLEESAVES(sym->type))
3177 /* if any registers used */
3180 /* save the registers used */
3181 for (i = sym->regsUsed->size; i >= 0; i--)
3183 if (bitVectBitValue (sym->regsUsed, i) ||
3184 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3185 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3188 else if (mcs51_ptrRegReq)
3190 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3191 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3196 /* if debug then send end of function */
3197 if (options.debug && currFunc)
3199 debugFile->writeEndFunction (currFunc, ic, 1);
3202 emitcode ("ret", "");
3205 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3208 /* If this was an interrupt handler using bank 0 that called another */
3209 /* function, then all registers must be saved; nothing to optimized. */
3210 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3211 && !FUNC_REGBANK(sym->type))
3214 /* There are no push/pops to optimize if not callee-saves or ISR */
3215 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3218 /* If there were stack parameters, we cannot optimize without also */
3219 /* fixing all of the stack offsets; this is too dificult to consider. */
3220 if (FUNC_HASSTACKPARM(sym->type))
3223 /* Compute the registers actually used */
3224 regsUsed = newBitVect (mcs51_nRegs);
3225 regsUsedPrologue = newBitVect (mcs51_nRegs);
3228 if (lnp->ic && lnp->ic->op == FUNCTION)
3229 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3231 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3233 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3234 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3241 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3242 && !bitVectBitValue (regsUsed, CND_IDX))
3244 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3245 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3246 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3247 bitVectUnSetBit (regsUsed, CND_IDX);
3250 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3252 /* If this was an interrupt handler that called another function */
3253 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3254 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3256 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3257 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3258 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3259 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3260 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3263 /* Remove the unneeded push/pops */
3264 regsUnneeded = newBitVect (mcs51_nRegs);
3267 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3269 if (!strncmp(lnp->line, "push", 4))
3271 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3272 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3274 connectLine (lnp->prev, lnp->next);
3275 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3278 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3280 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3281 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3283 connectLine (lnp->prev, lnp->next);
3284 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3291 for (idx = 0; idx < regsUnneeded->size; idx++)
3292 if (bitVectBitValue (regsUnneeded, idx))
3293 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3295 freeBitVect (regsUnneeded);
3296 freeBitVect (regsUsed);
3297 freeBitVect (regsUsedPrologue);
3300 /*-----------------------------------------------------------------*/
3301 /* genRet - generate code for return statement */
3302 /*-----------------------------------------------------------------*/
3306 int size, offset = 0, pushed = 0;
3308 D(emitcode ("; genRet",""));
3310 /* if we have no return value then
3311 just generate the "ret" */
3315 /* we have something to return then
3316 move the return value into place */
3317 aopOp (IC_LEFT (ic), ic, FALSE);
3318 size = AOP_SIZE (IC_LEFT (ic));
3323 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3326 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3328 emitcode ("push", "%s", l);
3333 l = aopGet (AOP (IC_LEFT (ic)), offset,
3335 if (strcmp (fReturn[offset], l))
3336 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3345 if (strcmp (fReturn[pushed], "a"))
3346 emitcode ("pop", fReturn[pushed]);
3348 emitcode ("pop", "acc");
3351 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3354 /* generate a jump to the return label
3355 if the next is not the return statement */
3356 if (!(ic->next && ic->next->op == LABEL &&
3357 IC_LABEL (ic->next) == returnLabel))
3359 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3363 /*-----------------------------------------------------------------*/
3364 /* genLabel - generates a label */
3365 /*-----------------------------------------------------------------*/
3367 genLabel (iCode * ic)
3369 /* special case never generate */
3370 if (IC_LABEL (ic) == entryLabel)
3373 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3376 /*-----------------------------------------------------------------*/
3377 /* genGoto - generates a ljmp */
3378 /*-----------------------------------------------------------------*/
3380 genGoto (iCode * ic)
3382 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3385 /*-----------------------------------------------------------------*/
3386 /* findLabelBackwards: walks back through the iCode chain looking */
3387 /* for the given label. Returns number of iCode instructions */
3388 /* between that label and given ic. */
3389 /* Returns zero if label not found. */
3390 /*-----------------------------------------------------------------*/
3392 findLabelBackwards (iCode * ic, int key)
3401 /* If we have any pushes or pops, we cannot predict the distance.
3402 I don't like this at all, this should be dealt with in the
3404 if (ic->op == IPUSH || ic->op == IPOP) {
3408 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3417 /*-----------------------------------------------------------------*/
3418 /* genPlusIncr :- does addition with increment if possible */
3419 /*-----------------------------------------------------------------*/
3421 genPlusIncr (iCode * ic)
3423 unsigned int icount;
3424 unsigned int size = getDataSize (IC_RESULT (ic));
3426 /* will try to generate an increment */
3427 /* if the right side is not a literal
3429 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3432 /* if the literal value of the right hand side
3433 is greater than 4 then it is not worth it */
3434 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3437 D(emitcode ("; genPlusIncr",""));
3439 /* if increment >=16 bits in register or direct space */
3440 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3441 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3449 /* If the next instruction is a goto and the goto target
3450 * is < 10 instructions previous to this, we can generate
3451 * jumps straight to that target.
3453 if (ic->next && ic->next->op == GOTO
3454 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3455 && labelRange <= 10)
3457 emitcode (";", "tail increment optimized");
3458 tlbl = IC_LABEL (ic->next);
3463 tlbl = newiTempLabel (NULL);
3466 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3467 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3468 IS_AOP_PREG (IC_RESULT (ic)))
3469 emitcode ("cjne", "%s,#0x00,%05d$",
3470 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3474 emitcode ("clr", "a");
3475 emitcode ("cjne", "a,%s,%05d$",
3476 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3480 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3483 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3484 IS_AOP_PREG (IC_RESULT (ic)))
3485 emitcode ("cjne", "%s,#0x00,%05d$",
3486 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3489 emitcode ("cjne", "a,%s,%05d$",
3490 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3493 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3498 IS_AOP_PREG (IC_RESULT (ic)))
3499 emitcode ("cjne", "%s,#0x00,%05d$",
3500 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3504 emitcode ("cjne", "a,%s,%05d$",
3505 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3508 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3513 emitcode ("", "%05d$:", tlbl->key + 100);
3518 /* if the sizes are greater than 1 then we cannot */
3519 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3520 AOP_SIZE (IC_LEFT (ic)) > 1)
3523 /* we can if the aops of the left & result match or
3524 if they are in registers and the registers are the
3526 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3531 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3532 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3533 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3539 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3548 /*-----------------------------------------------------------------*/
3549 /* outBitAcc - output a bit in acc */
3550 /*-----------------------------------------------------------------*/
3552 outBitAcc (operand * result)
3554 symbol *tlbl = newiTempLabel (NULL);
3555 /* if the result is a bit */
3556 if (AOP_TYPE (result) == AOP_CRY)
3558 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3562 emitcode ("jz", "%05d$", tlbl->key + 100);
3563 emitcode ("mov", "a,%s", one);
3564 emitcode ("", "%05d$:", tlbl->key + 100);
3569 /*-----------------------------------------------------------------*/
3570 /* genPlusBits - generates code for addition of two bits */
3571 /*-----------------------------------------------------------------*/
3573 genPlusBits (iCode * ic)
3575 D(emitcode ("; genPlusBits",""));
3577 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3579 symbol *lbl = newiTempLabel (NULL);
3580 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3581 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3582 emitcode ("cpl", "c");
3583 emitcode ("", "%05d$:", (lbl->key + 100));
3584 outBitC (IC_RESULT (ic));
3588 emitcode ("clr", "a");
3589 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3590 emitcode ("rlc", "a");
3591 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3592 emitcode ("addc", "a,#0x00");
3593 outAcc (IC_RESULT (ic));
3598 /* This is the original version of this code.
3600 * This is being kept around for reference,
3601 * because I am not entirely sure I got it right...
3604 adjustArithmeticResult (iCode * ic)
3606 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3607 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3608 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3609 aopPut (AOP (IC_RESULT (ic)),
3610 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3612 isOperandVolatile (IC_RESULT (ic), FALSE));
3614 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3615 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3616 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3617 aopPut (AOP (IC_RESULT (ic)),
3618 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3620 isOperandVolatile (IC_RESULT (ic), FALSE));
3622 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3623 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3624 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3625 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3626 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3629 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3630 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3634 /* This is the pure and virtuous version of this code.
3635 * I'm pretty certain it's right, but not enough to toss the old
3639 adjustArithmeticResult (iCode * ic)
3641 if (opIsGptr (IC_RESULT (ic)) &&
3642 opIsGptr (IC_LEFT (ic)) &&
3643 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3645 aopPut (AOP (IC_RESULT (ic)),
3646 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3648 isOperandVolatile (IC_RESULT (ic), FALSE));
3651 if (opIsGptr (IC_RESULT (ic)) &&
3652 opIsGptr (IC_RIGHT (ic)) &&
3653 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3655 aopPut (AOP (IC_RESULT (ic)),
3656 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3658 isOperandVolatile (IC_RESULT (ic), FALSE));
3661 if (opIsGptr (IC_RESULT (ic)) &&
3662 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3663 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3664 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3665 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3668 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3669 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3674 /*-----------------------------------------------------------------*/
3675 /* genPlus - generates code for addition */
3676 /*-----------------------------------------------------------------*/
3678 genPlus (iCode * ic)
3680 int size, offset = 0;
3683 asmop *leftOp, *rightOp;
3686 /* special cases :- */
3688 D(emitcode ("; genPlus",""));
3690 aopOp (IC_LEFT (ic), ic, FALSE);
3691 aopOp (IC_RIGHT (ic), ic, FALSE);
3692 aopOp (IC_RESULT (ic), ic, TRUE);
3694 /* if literal, literal on the right or
3695 if left requires ACC or right is already
3697 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3698 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3699 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3701 operand *t = IC_RIGHT (ic);
3702 IC_RIGHT (ic) = IC_LEFT (ic);
3706 /* if both left & right are in bit
3708 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3709 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3715 /* if left in bit space & right literal */
3716 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3717 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3719 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3720 /* if result in bit space */
3721 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3723 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3724 emitcode ("cpl", "c");
3725 outBitC (IC_RESULT (ic));
3729 size = getDataSize (IC_RESULT (ic));
3732 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3733 emitcode ("addc", "a,#00");
3734 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3740 /* if I can do an increment instead
3741 of add then GOOD for ME */
3742 if (genPlusIncr (ic) == TRUE)
3745 size = getDataSize (IC_RESULT (ic));
3746 leftOp = AOP(IC_LEFT(ic));
3747 rightOp = AOP(IC_RIGHT(ic));
3750 /* if this is an add for an array access
3751 at a 256 byte boundary */
3753 && AOP_TYPE (op) == AOP_IMMD
3755 && IS_SPEC (OP_SYM_ETYPE (op))
3756 && SPEC_ABSA (OP_SYM_ETYPE (op))
3757 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3760 D(emitcode ("; genPlus aligned array",""));
3761 aopPut (AOP (IC_RESULT (ic)),
3762 aopGet (rightOp, 0, FALSE, FALSE),
3764 isOperandVolatile (IC_RESULT (ic), FALSE));
3766 if( 1 == getDataSize (IC_RIGHT (ic)) )
3768 aopPut (AOP (IC_RESULT (ic)),
3769 aopGet (leftOp, 1, FALSE, FALSE),
3771 isOperandVolatile (IC_RESULT (ic), FALSE));
3775 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3776 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3777 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3782 /* if the lower bytes of a literal are zero skip the addition */
3783 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3785 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3786 (skip_bytes+1 < size))
3791 D(emitcode ("; genPlus shortcut",""));
3796 if( offset >= skip_bytes )
3798 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3801 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3803 emitcode("xch", "a,b");
3804 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3805 emitcode (add, "a,b");
3808 else if (aopGetUsesAcc (leftOp, offset))
3810 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3811 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3815 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3816 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3818 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3819 add = "addc"; /* further adds must propagate carry */
3823 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3824 isOperandVolatile (IC_RESULT (ic), FALSE))
3827 aopPut (AOP (IC_RESULT (ic)),
3828 aopGet (leftOp, offset, FALSE, FALSE),
3830 isOperandVolatile (IC_RESULT (ic), FALSE));
3836 adjustArithmeticResult (ic);
3839 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3840 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3844 /*-----------------------------------------------------------------*/
3845 /* genMinusDec :- does subtraction with deccrement if possible */
3846 /*-----------------------------------------------------------------*/
3848 genMinusDec (iCode * ic)
3850 unsigned int icount;
3851 unsigned int size = getDataSize (IC_RESULT (ic));
3853 /* will try to generate an increment */
3854 /* if the right side is not a literal
3856 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3859 /* if the literal value of the right hand side
3860 is greater than 4 then it is not worth it */
3861 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3864 D(emitcode ("; genMinusDec",""));
3866 /* if decrement >=16 bits in register or direct space */
3867 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3868 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3876 /* If the next instruction is a goto and the goto target
3877 * is <= 10 instructions previous to this, we can generate
3878 * jumps straight to that target.
3880 if (ic->next && ic->next->op == GOTO
3881 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3882 && labelRange <= 10)
3884 emitcode (";", "tail decrement optimized");
3885 tlbl = IC_LABEL (ic->next);
3890 tlbl = newiTempLabel (NULL);
3894 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3895 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3896 IS_AOP_PREG (IC_RESULT (ic)))
3897 emitcode ("cjne", "%s,#0xff,%05d$"
3898 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3902 emitcode ("mov", "a,#0xff");
3903 emitcode ("cjne", "a,%s,%05d$"
3904 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3907 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3910 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3911 IS_AOP_PREG (IC_RESULT (ic)))
3912 emitcode ("cjne", "%s,#0xff,%05d$"
3913 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3917 emitcode ("cjne", "a,%s,%05d$"
3918 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3921 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3925 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3926 IS_AOP_PREG (IC_RESULT (ic)))
3927 emitcode ("cjne", "%s,#0xff,%05d$"
3928 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3932 emitcode ("cjne", "a,%s,%05d$"
3933 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3936 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3940 emitcode ("", "%05d$:", tlbl->key + 100);
3945 /* if the sizes are greater than 1 then we cannot */
3946 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3947 AOP_SIZE (IC_LEFT (ic)) > 1)
3950 /* we can if the aops of the left & result match or
3951 if they are in registers and the registers are the
3953 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3957 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3965 /*-----------------------------------------------------------------*/
3966 /* addSign - complete with sign */
3967 /*-----------------------------------------------------------------*/
3969 addSign (operand * result, int offset, int sign)
3971 int size = (getDataSize (result) - offset);
3976 emitcode ("rlc", "a");
3977 emitcode ("subb", "a,acc");
3979 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3983 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3987 /*-----------------------------------------------------------------*/
3988 /* genMinusBits - generates code for subtraction of two bits */
3989 /*-----------------------------------------------------------------*/
3991 genMinusBits (iCode * ic)
3993 symbol *lbl = newiTempLabel (NULL);
3995 D(emitcode ("; genMinusBits",""));
3997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3999 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4000 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4001 emitcode ("cpl", "c");
4002 emitcode ("", "%05d$:", (lbl->key + 100));
4003 outBitC (IC_RESULT (ic));
4007 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4008 emitcode ("subb", "a,acc");
4009 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4010 emitcode ("inc", "a");
4011 emitcode ("", "%05d$:", (lbl->key + 100));
4012 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4013 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4017 /*-----------------------------------------------------------------*/
4018 /* genMinus - generates code for subtraction */
4019 /*-----------------------------------------------------------------*/
4021 genMinus (iCode * ic)
4023 int size, offset = 0;
4025 D(emitcode ("; genMinus",""));
4027 aopOp (IC_LEFT (ic), ic, FALSE);
4028 aopOp (IC_RIGHT (ic), ic, FALSE);
4029 aopOp (IC_RESULT (ic), ic, TRUE);
4031 /* special cases :- */
4032 /* if both left & right are in bit space */
4033 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4034 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4040 /* if I can do an decrement instead
4041 of subtract then GOOD for ME */
4042 if (genMinusDec (ic) == TRUE)
4045 size = getDataSize (IC_RESULT (ic));
4047 /* if literal, add a,#-lit, else normal subb */
4048 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4050 unsigned long lit = 0L;
4052 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4057 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4058 /* first add without previous c */
4060 if (!size && lit== (unsigned long) -1) {
4061 emitcode ("dec", "a");
4063 emitcode ("add", "a,#0x%02x",
4064 (unsigned int) (lit & 0x0FFL));
4067 emitcode ("addc", "a,#0x%02x",
4068 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4070 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4075 asmop *leftOp, *rightOp;
4077 leftOp = AOP(IC_LEFT(ic));
4078 rightOp = AOP(IC_RIGHT(ic));
4082 if (aopGetUsesAcc(rightOp, offset)) {
4083 if (aopGetUsesAcc(leftOp, offset)) {
4086 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4088 emitcode ("mov", "b,a");
4091 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4092 emitcode ("subb", "a,b");
4095 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4096 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4098 emitcode( "setb", "c");
4100 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4101 emitcode("cpl", "a");
4104 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4107 emitcode ("subb", "a,%s",
4108 aopGet(rightOp, offset, FALSE, TRUE));
4111 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4116 adjustArithmeticResult (ic);
4119 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4120 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4121 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4125 /*-----------------------------------------------------------------*/
4126 /* genMultbits :- multiplication of bits */
4127 /*-----------------------------------------------------------------*/
4129 genMultbits (operand * left,
4133 D(emitcode ("; genMultbits",""));
4135 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4136 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4140 /*-----------------------------------------------------------------*/
4141 /* genMultOneByte : 8*8=8/16 bit multiplication */
4142 /*-----------------------------------------------------------------*/
4144 genMultOneByte (operand * left,
4149 int size = AOP_SIZE (result);
4150 bool runtimeSign, compiletimeSign;
4151 bool lUnsigned, rUnsigned, pushedB;
4153 D(emitcode ("; genMultOneByte",""));
4155 if (size < 1 || size > 2)
4157 /* this should never happen */
4158 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4159 AOP_SIZE(result), __FILE__, lineno);
4163 /* (if two literals: the value is computed before) */
4164 /* if one literal, literal on the right */
4165 if (AOP_TYPE (left) == AOP_LIT)
4170 /* emitcode (";", "swapped left and right"); */
4172 /* if no literal, unsigned on the right: shorter code */
4173 if ( AOP_TYPE (right) != AOP_LIT
4174 && SPEC_USIGN (getSpec (operandType (left))))
4181 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4182 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4186 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4187 no need to take care about the signedness! */
4188 || (lUnsigned && rUnsigned))
4190 /* just an unsigned 8 * 8 = 8 multiply
4192 /* emitcode (";","unsigned"); */
4193 /* TODO: check for accumulator clash between left & right aops? */
4195 if (AOP_TYPE (right) == AOP_LIT)
4197 /* moving to accumulator first helps peepholes */
4198 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4199 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4203 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4204 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4207 emitcode ("mul", "ab");
4208 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4210 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4216 /* we have to do a signed multiply */
4217 /* emitcode (";", "signed"); */
4219 /* now sign adjust for both left & right */
4221 /* let's see what's needed: */
4222 /* apply negative sign during runtime */
4223 runtimeSign = FALSE;
4224 /* negative sign from literals */
4225 compiletimeSign = FALSE;
4229 if (AOP_TYPE(left) == AOP_LIT)
4231 /* signed literal */
4232 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4234 compiletimeSign = TRUE;
4237 /* signed but not literal */
4243 if (AOP_TYPE(right) == AOP_LIT)
4245 /* signed literal */
4246 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4248 compiletimeSign ^= TRUE;
4251 /* signed but not literal */
4255 /* initialize F0, which stores the runtime sign */
4258 if (compiletimeSign)
4259 emitcode ("setb", "F0"); /* set sign flag */
4261 emitcode ("clr", "F0"); /* reset sign flag */
4264 /* save the signs of the operands */
4265 if (AOP_TYPE(right) == AOP_LIT)
4267 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4269 if (!rUnsigned && val < 0)
4270 emitcode ("mov", "b,#0x%02x", -val);
4272 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4274 else /* ! literal */
4276 if (rUnsigned) /* emitcode (";", "signed"); */
4278 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4281 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4282 lbl = newiTempLabel (NULL);
4283 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4284 emitcode ("cpl", "F0"); /* complement sign flag */
4285 emitcode ("cpl", "a"); /* 2's complement */
4286 emitcode ("inc", "a");
4287 emitcode ("", "%05d$:", (lbl->key + 100));
4288 emitcode ("mov", "b,a");
4292 if (AOP_TYPE(left) == AOP_LIT)
4294 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4296 if (!lUnsigned && val < 0)
4297 emitcode ("mov", "a,#0x%02x", -val);
4299 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4301 else /* ! literal */
4303 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4307 lbl = newiTempLabel (NULL);
4308 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4309 emitcode ("cpl", "F0"); /* complement sign flag */
4310 emitcode ("cpl", "a"); /* 2's complement */
4311 emitcode ("inc", "a");
4312 emitcode ("", "%05d$:", (lbl->key + 100));
4316 /* now the multiplication */
4317 emitcode ("mul", "ab");
4318 if (runtimeSign || compiletimeSign)
4320 lbl = newiTempLabel (NULL);
4322 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4323 emitcode ("cpl", "a"); /* lsb 2's complement */
4325 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4328 emitcode ("add", "a,#1"); /* this sets carry flag */
4329 emitcode ("xch", "a,b");
4330 emitcode ("cpl", "a"); /* msb 2's complement */
4331 emitcode ("addc", "a,#0");
4332 emitcode ("xch", "a,b");
4334 emitcode ("", "%05d$:", (lbl->key + 100));
4336 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4338 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4343 /*-----------------------------------------------------------------*/
4344 /* genMult - generates code for multiplication */
4345 /*-----------------------------------------------------------------*/
4347 genMult (iCode * ic)
4349 operand *left = IC_LEFT (ic);
4350 operand *right = IC_RIGHT (ic);
4351 operand *result = IC_RESULT (ic);
4353 D(emitcode ("; genMult",""));
4355 /* assign the amsops */
4356 aopOp (left, ic, FALSE);
4357 aopOp (right, ic, FALSE);
4358 aopOp (result, ic, TRUE);
4360 /* special cases first */
4362 if (AOP_TYPE (left) == AOP_CRY &&
4363 AOP_TYPE (right) == AOP_CRY)
4365 genMultbits (left, right, result);
4369 /* if both are of size == 1 */
4370 #if 0 // one of them can be a sloc shared with the result
4371 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4373 if (getSize(operandType(left)) == 1 &&
4374 getSize(operandType(right)) == 1)
4377 genMultOneByte (left, right, result);
4381 /* should have been converted to function call */
4382 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4383 getSize(OP_SYMBOL(right)->type));
4387 freeAsmop (result, NULL, ic, TRUE);
4388 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits */
4394 /*-----------------------------------------------------------------*/
4396 genDivbits (operand * left,
4403 D(emitcode ("; genDivbits",""));
4407 /* the result must be bit */
4408 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4409 l = aopGet (AOP (left), 0, FALSE, FALSE);
4413 emitcode ("div", "ab");
4414 emitcode ("rrc", "a");
4418 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4421 /*-----------------------------------------------------------------*/
4422 /* genDivOneByte : 8 bit division */
4423 /*-----------------------------------------------------------------*/
4425 genDivOneByte (operand * left,
4429 bool lUnsigned, rUnsigned, pushedB;
4430 bool runtimeSign, compiletimeSign;
4434 D(emitcode ("; genDivOneByte",""));
4436 /* Why is it necessary that genDivOneByte() can return an int result?
4439 volatile unsigned char uc;
4440 volatile signed char sc1, sc2;
4453 In all cases a one byte result would overflow, the following cast to int
4454 would return the wrong result.
4456 Two possible solution:
4457 a) cast operands to int, if ((unsigned) / (signed)) or
4458 ((signed) / (signed))
4459 b) return an 16 bit signed int; this is what we're doing here!
4462 size = AOP_SIZE (result) - 1;
4464 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4465 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4469 /* signed or unsigned */
4470 if (lUnsigned && rUnsigned)
4472 /* unsigned is easy */
4473 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4474 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4475 emitcode ("div", "ab");
4476 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4478 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4484 /* signed is a little bit more difficult */
4486 /* now sign adjust for both left & right */
4488 /* let's see what's needed: */
4489 /* apply negative sign during runtime */
4490 runtimeSign = FALSE;
4491 /* negative sign from literals */
4492 compiletimeSign = FALSE;
4496 if (AOP_TYPE(left) == AOP_LIT)
4498 /* signed literal */
4499 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4501 compiletimeSign = TRUE;
4504 /* signed but not literal */
4510 if (AOP_TYPE(right) == AOP_LIT)
4512 /* signed literal */
4513 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4515 compiletimeSign ^= TRUE;
4518 /* signed but not literal */
4522 /* initialize F0, which stores the runtime sign */
4525 if (compiletimeSign)
4526 emitcode ("setb", "F0"); /* set sign flag */
4528 emitcode ("clr", "F0"); /* reset sign flag */
4531 /* save the signs of the operands */
4532 if (AOP_TYPE(right) == AOP_LIT)
4534 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4536 if (!rUnsigned && val < 0)
4537 emitcode ("mov", "b,#0x%02x", -val);
4539 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4541 else /* ! literal */
4544 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4547 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4548 lbl = newiTempLabel (NULL);
4549 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4550 emitcode ("cpl", "F0"); /* complement sign flag */
4551 emitcode ("cpl", "a"); /* 2's complement */
4552 emitcode ("inc", "a");
4553 emitcode ("", "%05d$:", (lbl->key + 100));
4554 emitcode ("mov", "b,a");
4558 if (AOP_TYPE(left) == AOP_LIT)
4560 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4562 if (!lUnsigned && val < 0)
4563 emitcode ("mov", "a,#0x%02x", -val);
4565 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4567 else /* ! literal */
4569 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4573 lbl = newiTempLabel (NULL);
4574 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4575 emitcode ("cpl", "F0"); /* complement sign flag */
4576 emitcode ("cpl", "a"); /* 2's complement */
4577 emitcode ("inc", "a");
4578 emitcode ("", "%05d$:", (lbl->key + 100));
4582 /* now the division */
4583 emitcode ("div", "ab");
4585 if (runtimeSign || compiletimeSign)
4587 lbl = newiTempLabel (NULL);
4589 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4590 emitcode ("cpl", "a"); /* lsb 2's complement */
4591 emitcode ("inc", "a");
4592 emitcode ("", "%05d$:", (lbl->key + 100));
4594 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4597 /* msb is 0x00 or 0xff depending on the sign */
4600 emitcode ("mov", "c,F0");
4601 emitcode ("subb", "a,acc");
4603 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4605 else /* compiletimeSign */
4607 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4612 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4614 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4620 /*-----------------------------------------------------------------*/
4621 /* genDiv - generates code for division */
4622 /*-----------------------------------------------------------------*/
4626 operand *left = IC_LEFT (ic);
4627 operand *right = IC_RIGHT (ic);
4628 operand *result = IC_RESULT (ic);
4630 D(emitcode ("; genDiv",""));
4632 /* assign the amsops */
4633 aopOp (left, ic, FALSE);
4634 aopOp (right, ic, FALSE);
4635 aopOp (result, ic, TRUE);
4637 /* special cases first */
4639 if (AOP_TYPE (left) == AOP_CRY &&
4640 AOP_TYPE (right) == AOP_CRY)
4642 genDivbits (left, right, result);
4646 /* if both are of size == 1 */
4647 if (AOP_SIZE (left) == 1 &&
4648 AOP_SIZE (right) == 1)
4650 genDivOneByte (left, right, result);
4654 /* should have been converted to function call */
4657 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4658 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4659 freeAsmop (result, NULL, ic, TRUE);
4662 /*-----------------------------------------------------------------*/
4663 /* genModbits :- modulus of bits */
4664 /*-----------------------------------------------------------------*/
4666 genModbits (operand * left,
4673 D(emitcode ("; genModbits",""));
4677 /* the result must be bit */
4678 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4679 l = aopGet (AOP (left), 0, FALSE, FALSE);
4683 emitcode ("div", "ab");
4684 emitcode ("mov", "a,b");
4685 emitcode ("rrc", "a");
4689 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4692 /*-----------------------------------------------------------------*/
4693 /* genModOneByte : 8 bit modulus */
4694 /*-----------------------------------------------------------------*/
4696 genModOneByte (operand * left,
4700 bool lUnsigned, rUnsigned, pushedB;
4701 bool runtimeSign, compiletimeSign;
4705 D(emitcode ("; genModOneByte",""));
4707 size = AOP_SIZE (result) - 1;
4709 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4710 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4712 /* if right is a literal, check it for 2^n */
4713 if (AOP_TYPE(right) == AOP_LIT)
4715 unsigned char val = abs(operandLitValue(right));
4716 symbol *lbl2 = NULL;
4720 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4729 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4730 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4731 /* because iCode should have been changed to genAnd */
4732 /* see file "SDCCopt.c", function "convertToFcall()" */
4734 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4735 emitcode ("mov", "c,acc.7");
4736 emitcode ("anl", "a,#0x%02x", val - 1);
4737 lbl = newiTempLabel (NULL);
4738 emitcode ("jz", "%05d$", (lbl->key + 100));
4739 emitcode ("jnc", "%05d$", (lbl->key + 100));
4740 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4746 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4748 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4749 lbl2 = newiTempLabel (NULL);
4750 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4752 emitcode ("", "%05d$:", (lbl->key + 100));
4753 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4755 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4758 emitcode ("", "%05d$:", (lbl2->key + 100));
4769 /* signed or unsigned */
4770 if (lUnsigned && rUnsigned)
4772 /* unsigned is easy */
4773 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4774 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4775 emitcode ("div", "ab");
4776 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4778 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4784 /* signed is a little bit more difficult */
4786 /* now sign adjust for both left & right */
4788 /* modulus: sign of the right operand has no influence on the result! */
4789 if (AOP_TYPE(right) == AOP_LIT)
4791 signed char val = (char) operandLitValue(right);
4793 if (!rUnsigned && val < 0)
4794 emitcode ("mov", "b,#0x%02x", -val);
4796 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4798 else /* not literal */
4801 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4804 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4805 lbl = newiTempLabel (NULL);
4806 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4807 emitcode ("cpl", "a"); /* 2's complement */
4808 emitcode ("inc", "a");
4809 emitcode ("", "%05d$:", (lbl->key + 100));
4810 emitcode ("mov", "b,a");
4814 /* let's see what's needed: */
4815 /* apply negative sign during runtime */
4816 runtimeSign = FALSE;
4817 /* negative sign from literals */
4818 compiletimeSign = FALSE;
4820 /* sign adjust left side */
4821 if (AOP_TYPE(left) == AOP_LIT)
4823 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4825 if (!lUnsigned && val < 0)
4827 compiletimeSign = TRUE; /* set sign flag */
4828 emitcode ("mov", "a,#0x%02x", -val);
4831 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4833 else /* ! literal */
4835 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4840 emitcode ("clr", "F0"); /* clear sign flag */
4842 lbl = newiTempLabel (NULL);
4843 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4844 emitcode ("setb", "F0"); /* set sign flag */
4845 emitcode ("cpl", "a"); /* 2's complement */
4846 emitcode ("inc", "a");
4847 emitcode ("", "%05d$:", (lbl->key + 100));
4851 /* now the modulus */
4852 emitcode ("div", "ab");
4854 if (runtimeSign || compiletimeSign)
4856 emitcode ("mov", "a,b");
4857 lbl = newiTempLabel (NULL);
4859 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4860 emitcode ("cpl", "a"); /* 2's complement */
4861 emitcode ("inc", "a");
4862 emitcode ("", "%05d$:", (lbl->key + 100));
4864 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4867 /* msb is 0x00 or 0xff depending on the sign */
4870 emitcode ("mov", "c,F0");
4871 emitcode ("subb", "a,acc");
4873 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4875 else /* compiletimeSign */
4877 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4882 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4884 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4890 /*-----------------------------------------------------------------*/
4891 /* genMod - generates code for division */
4892 /*-----------------------------------------------------------------*/
4896 operand *left = IC_LEFT (ic);
4897 operand *right = IC_RIGHT (ic);
4898 operand *result = IC_RESULT (ic);
4900 D(emitcode ("; genMod",""));
4902 /* assign the asmops */
4903 aopOp (left, ic, FALSE);
4904 aopOp (right, ic, FALSE);
4905 aopOp (result, ic, TRUE);
4907 /* special cases first */
4909 if (AOP_TYPE (left) == AOP_CRY &&
4910 AOP_TYPE (right) == AOP_CRY)
4912 genModbits (left, right, result);
4916 /* if both are of size == 1 */
4917 if (AOP_SIZE (left) == 1 &&
4918 AOP_SIZE (right) == 1)
4920 genModOneByte (left, right, result);
4924 /* should have been converted to function call */
4928 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4930 freeAsmop (result, NULL, ic, TRUE);
4933 /*-----------------------------------------------------------------*/
4934 /* genIfxJump :- will create a jump depending on the ifx */
4935 /*-----------------------------------------------------------------*/
4937 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4940 symbol *tlbl = newiTempLabel (NULL);
4943 D(emitcode ("; genIfxJump",""));
4945 /* if true label then we jump if condition
4949 jlbl = IC_TRUE (ic);
4950 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4951 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4955 /* false label is present */
4956 jlbl = IC_FALSE (ic);
4957 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4958 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4960 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4961 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4963 emitcode (inst, "%05d$", tlbl->key + 100);
4964 freeForBranchAsmop (result);
4965 freeForBranchAsmop (right);
4966 freeForBranchAsmop (left);
4967 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4968 emitcode ("", "%05d$:", tlbl->key + 100);
4970 /* mark the icode as generated */
4974 /*-----------------------------------------------------------------*/
4975 /* genCmp :- greater or less than comparison */
4976 /*-----------------------------------------------------------------*/
4978 genCmp (operand * left, operand * right,
4979 operand * result, iCode * ifx, int sign, iCode *ic)
4981 int size, offset = 0;
4982 unsigned long lit = 0L;
4985 D(emitcode ("; genCmp",""));
4987 /* if left & right are bit variables */
4988 if (AOP_TYPE (left) == AOP_CRY &&
4989 AOP_TYPE (right) == AOP_CRY)
4991 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4992 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4996 /* subtract right from left if at the
4997 end the carry flag is set then we know that
4998 left is greater than right */
4999 size = max (AOP_SIZE (left), AOP_SIZE (right));
5001 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5002 if ((size == 1) && !sign &&
5003 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5005 symbol *lbl = newiTempLabel (NULL);
5006 emitcode ("cjne", "%s,%s,%05d$",
5007 aopGet (AOP (left), offset, FALSE, FALSE),
5008 aopGet (AOP (right), offset, FALSE, FALSE),
5010 emitcode ("", "%05d$:", lbl->key + 100);
5014 if (AOP_TYPE (right) == AOP_LIT)
5016 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5017 /* optimize if(x < 0) or if(x >= 0) */
5026 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5027 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5029 genIfxJump (ifx, "acc.7", left, right, result);
5030 freeAsmop (right, NULL, ic, TRUE);
5031 freeAsmop (left, NULL, ic, TRUE);
5036 emitcode ("rlc", "a");
5044 bool pushedB = FALSE;
5045 rightInB = aopGetUsesAcc(AOP (right), offset);
5049 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5051 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5052 if (sign && size == 0)
5054 emitcode ("xrl", "a,#0x80");
5055 if (AOP_TYPE (right) == AOP_LIT)
5057 unsigned long lit = (unsigned long)
5058 floatFromVal (AOP (right)->aopu.aop_lit);
5059 emitcode ("subb", "a,#0x%02x",
5060 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5068 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5070 emitcode ("xrl", "b,#0x80");
5071 emitcode ("subb", "a,b");
5077 emitcode ("subb", "a,b");
5079 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5089 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5090 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5091 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5097 /* if the result is used in the next
5098 ifx conditional branch then generate
5099 code a little differently */
5101 genIfxJump (ifx, "c", NULL, NULL, result);
5104 /* leave the result in acc */
5108 /*-----------------------------------------------------------------*/
5109 /* genCmpGt :- greater than comparison */
5110 /*-----------------------------------------------------------------*/
5112 genCmpGt (iCode * ic, iCode * ifx)
5114 operand *left, *right, *result;
5115 sym_link *letype, *retype;
5118 D(emitcode ("; genCmpGt",""));
5120 left = IC_LEFT (ic);
5121 right = IC_RIGHT (ic);
5122 result = IC_RESULT (ic);
5124 letype = getSpec (operandType (left));
5125 retype = getSpec (operandType (right));
5126 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5127 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5128 /* assign the amsops */
5129 aopOp (left, ic, FALSE);
5130 aopOp (right, ic, FALSE);
5131 aopOp (result, ic, TRUE);
5133 genCmp (right, left, result, ifx, sign, ic);
5135 freeAsmop (result, NULL, ic, TRUE);
5138 /*-----------------------------------------------------------------*/
5139 /* genCmpLt - less than comparisons */
5140 /*-----------------------------------------------------------------*/
5142 genCmpLt (iCode * ic, iCode * ifx)
5144 operand *left, *right, *result;
5145 sym_link *letype, *retype;
5148 D(emitcode ("; genCmpLt",""));
5150 left = IC_LEFT (ic);
5151 right = IC_RIGHT (ic);
5152 result = IC_RESULT (ic);
5154 letype = getSpec (operandType (left));
5155 retype = getSpec (operandType (right));
5156 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5157 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5158 /* assign the amsops */
5159 aopOp (left, ic, FALSE);
5160 aopOp (right, ic, FALSE);
5161 aopOp (result, ic, TRUE);
5163 genCmp (left, right, result, ifx, sign,ic);
5165 freeAsmop (result, NULL, ic, TRUE);
5168 /*-----------------------------------------------------------------*/
5169 /* gencjneshort - compare and jump if not equal */
5170 /*-----------------------------------------------------------------*/
5172 gencjneshort (operand * left, operand * right, symbol * lbl)
5174 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5176 unsigned long lit = 0L;
5178 /* if the left side is a literal or
5179 if the right is in a pointer register and left
5181 if ((AOP_TYPE (left) == AOP_LIT) ||
5182 (AOP_TYPE (left) == AOP_IMMD) ||
5183 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5190 if (AOP_TYPE (right) == AOP_LIT)
5191 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5193 /* if the right side is a literal then anything goes */
5194 if (AOP_TYPE (right) == AOP_LIT &&
5195 AOP_TYPE (left) != AOP_DIR &&
5196 AOP_TYPE (left) != AOP_IMMD)
5200 emitcode ("cjne", "%s,%s,%05d$",
5201 aopGet (AOP (left), offset, FALSE, FALSE),
5202 aopGet (AOP (right), offset, FALSE, FALSE),
5208 /* if the right side is in a register or in direct space or
5209 if the left is a pointer register & right is not */
5210 else if (AOP_TYPE (right) == AOP_REG ||
5211 AOP_TYPE (right) == AOP_DIR ||
5212 AOP_TYPE (right) == AOP_LIT ||
5213 AOP_TYPE (right) == AOP_IMMD ||
5214 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5215 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5219 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5220 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5221 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5222 emitcode ("jnz", "%05d$", lbl->key + 100);
5224 emitcode ("cjne", "a,%s,%05d$",
5225 aopGet (AOP (right), offset, FALSE, TRUE),
5232 /* right is a pointer reg need both a & b */
5236 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5237 wassertl(!BINUSE, "B was in use");
5238 l = aopGet (AOP (left), offset, FALSE, FALSE);
5239 if (strcmp (l, "b"))
5240 emitcode ("mov", "b,%s", l);
5241 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5242 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5248 /*-----------------------------------------------------------------*/
5249 /* gencjne - compare and jump if not equal */
5250 /*-----------------------------------------------------------------*/
5252 gencjne (operand * left, operand * right, symbol * lbl)
5254 symbol *tlbl = newiTempLabel (NULL);
5256 gencjneshort (left, right, lbl);
5258 emitcode ("mov", "a,%s", one);
5259 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5260 emitcode ("", "%05d$:", lbl->key + 100);
5261 emitcode ("clr", "a");
5262 emitcode ("", "%05d$:", tlbl->key + 100);
5265 /*-----------------------------------------------------------------*/
5266 /* genCmpEq - generates code for equal to */
5267 /*-----------------------------------------------------------------*/
5269 genCmpEq (iCode * ic, iCode * ifx)
5271 operand *left, *right, *result;
5273 D(emitcode ("; genCmpEq",""));
5275 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5276 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5277 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5279 /* if literal, literal on the right or
5280 if the right is in a pointer register and left
5282 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5283 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5285 operand *t = IC_RIGHT (ic);
5286 IC_RIGHT (ic) = IC_LEFT (ic);
5290 if (ifx && !AOP_SIZE (result))
5293 /* if they are both bit variables */
5294 if (AOP_TYPE (left) == AOP_CRY &&
5295 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5297 if (AOP_TYPE (right) == AOP_LIT)
5299 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5303 emitcode ("cpl", "c");
5307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5311 emitcode ("clr", "c");
5313 /* AOP_TYPE(right) == AOP_CRY */
5317 symbol *lbl = newiTempLabel (NULL);
5318 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5319 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5320 emitcode ("cpl", "c");
5321 emitcode ("", "%05d$:", (lbl->key + 100));
5323 /* if true label then we jump if condition
5325 tlbl = newiTempLabel (NULL);
5328 emitcode ("jnc", "%05d$", tlbl->key + 100);
5329 freeForBranchAsmop (result);
5330 freeForBranchAsmop (right);
5331 freeForBranchAsmop (left);
5332 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5336 emitcode ("jc", "%05d$", tlbl->key + 100);
5337 freeForBranchAsmop (result);
5338 freeForBranchAsmop (right);
5339 freeForBranchAsmop (left);
5340 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5342 emitcode ("", "%05d$:", tlbl->key + 100);
5346 tlbl = newiTempLabel (NULL);
5347 gencjneshort (left, right, tlbl);
5350 freeForBranchAsmop (result);
5351 freeForBranchAsmop (right);
5352 freeForBranchAsmop (left);
5353 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5354 emitcode ("", "%05d$:", tlbl->key + 100);
5358 symbol *lbl = newiTempLabel (NULL);
5359 emitcode ("sjmp", "%05d$", lbl->key + 100);
5360 emitcode ("", "%05d$:", tlbl->key + 100);
5361 freeForBranchAsmop (result);
5362 freeForBranchAsmop (right);
5363 freeForBranchAsmop (left);
5364 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5365 emitcode ("", "%05d$:", lbl->key + 100);
5368 /* mark the icode as generated */
5373 /* if they are both bit variables */
5374 if (AOP_TYPE (left) == AOP_CRY &&
5375 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5377 if (AOP_TYPE (right) == AOP_LIT)
5379 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5383 emitcode ("cpl", "c");
5387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5391 emitcode ("clr", "c");
5393 /* AOP_TYPE(right) == AOP_CRY */
5397 symbol *lbl = newiTempLabel (NULL);
5398 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5399 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5400 emitcode ("cpl", "c");
5401 emitcode ("", "%05d$:", (lbl->key + 100));
5404 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5411 genIfxJump (ifx, "c", left, right, result);
5414 /* if the result is used in an arithmetic operation
5415 then put the result in place */
5420 gencjne (left, right, newiTempLabel (NULL));
5421 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5423 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5428 genIfxJump (ifx, "a", left, right, result);
5431 /* if the result is used in an arithmetic operation
5432 then put the result in place */
5433 if (AOP_TYPE (result) != AOP_CRY)
5435 /* leave the result in acc */
5439 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441 freeAsmop (result, NULL, ic, TRUE);
5444 /*-----------------------------------------------------------------*/
5445 /* ifxForOp - returns the icode containing the ifx for operand */
5446 /*-----------------------------------------------------------------*/
5448 ifxForOp (operand * op, iCode * ic)
5450 /* if true symbol then needs to be assigned */
5451 if (IS_TRUE_SYMOP (op))
5454 /* if this has register type condition and
5455 the next instruction is ifx with the same operand
5456 and live to of the operand is upto the ifx only then */
5458 ic->next->op == IFX &&
5459 IC_COND (ic->next)->key == op->key &&
5460 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5466 /*-----------------------------------------------------------------*/
5467 /* hasInc - operand is incremented before any other use */
5468 /*-----------------------------------------------------------------*/
5470 hasInc (operand *op, iCode *ic,int osize)
5472 sym_link *type = operandType(op);
5473 sym_link *retype = getSpec (type);
5474 iCode *lic = ic->next;
5477 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5478 if (!IS_SYMOP(op)) return NULL;
5480 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5481 if (IS_AGGREGATE(type->next)) return NULL;
5482 if (osize != (isize = getSize(type->next))) return NULL;
5485 /* if operand of the form op = op + <sizeof *op> */
5486 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5487 isOperandEqual(IC_RESULT(lic),op) &&
5488 isOperandLiteral(IC_RIGHT(lic)) &&
5489 operandLitValue(IC_RIGHT(lic)) == isize) {
5492 /* if the operand used or deffed */
5493 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5496 /* if GOTO or IFX */
5497 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5503 /*-----------------------------------------------------------------*/
5504 /* genAndOp - for && operation */
5505 /*-----------------------------------------------------------------*/
5507 genAndOp (iCode * ic)
5509 operand *left, *right, *result;
5512 D(emitcode ("; genAndOp",""));
5514 /* note here that && operations that are in an
5515 if statement are taken away by backPatchLabels
5516 only those used in arthmetic operations remain */
5517 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5518 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5519 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5521 /* if both are bit variables */
5522 if (AOP_TYPE (left) == AOP_CRY &&
5523 AOP_TYPE (right) == AOP_CRY)
5525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5526 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5531 tlbl = newiTempLabel (NULL);
5533 emitcode ("jz", "%05d$", tlbl->key + 100);
5535 emitcode ("", "%05d$:", tlbl->key + 100);
5539 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541 freeAsmop (result, NULL, ic, TRUE);
5545 /*-----------------------------------------------------------------*/
5546 /* genOrOp - for || operation */
5547 /*-----------------------------------------------------------------*/
5549 genOrOp (iCode * ic)
5551 operand *left, *right, *result;
5554 D(emitcode ("; genOrOp",""));
5556 /* note here that || operations that are in an
5557 if statement are taken away by backPatchLabels
5558 only those used in arthmetic operations remain */
5559 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5560 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5561 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5563 /* if both are bit variables */
5564 if (AOP_TYPE (left) == AOP_CRY &&
5565 AOP_TYPE (right) == AOP_CRY)
5567 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5568 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5573 tlbl = newiTempLabel (NULL);
5575 emitcode ("jnz", "%05d$", tlbl->key + 100);
5577 emitcode ("", "%05d$:", tlbl->key + 100);
5581 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5582 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5583 freeAsmop (result, NULL, ic, TRUE);
5586 /*-----------------------------------------------------------------*/
5587 /* isLiteralBit - test if lit == 2^n */
5588 /*-----------------------------------------------------------------*/
5590 isLiteralBit (unsigned long lit)
5592 unsigned long pw[32] =
5593 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5594 0x100L, 0x200L, 0x400L, 0x800L,
5595 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5596 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5597 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5598 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5599 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5602 for (idx = 0; idx < 32; idx++)
5608 /*-----------------------------------------------------------------*/
5609 /* continueIfTrue - */
5610 /*-----------------------------------------------------------------*/
5612 continueIfTrue (iCode * ic)
5615 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5619 /*-----------------------------------------------------------------*/
5621 /*-----------------------------------------------------------------*/
5623 jumpIfTrue (iCode * ic)
5626 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5630 /*-----------------------------------------------------------------*/
5631 /* jmpTrueOrFalse - */
5632 /*-----------------------------------------------------------------*/
5634 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5636 // ugly but optimized by peephole
5639 symbol *nlbl = newiTempLabel (NULL);
5640 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5641 emitcode ("", "%05d$:", tlbl->key + 100);
5642 freeForBranchAsmop (result);
5643 freeForBranchAsmop (right);
5644 freeForBranchAsmop (left);
5645 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5646 emitcode ("", "%05d$:", nlbl->key + 100);
5650 freeForBranchAsmop (result);
5651 freeForBranchAsmop (right);
5652 freeForBranchAsmop (left);
5653 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5654 emitcode ("", "%05d$:", tlbl->key + 100);
5659 /*-----------------------------------------------------------------*/
5660 /* genAnd - code for and */
5661 /*-----------------------------------------------------------------*/
5663 genAnd (iCode * ic, iCode * ifx)
5665 operand *left, *right, *result;
5666 int size, offset = 0;
5667 unsigned long lit = 0L;
5671 D(emitcode ("; genAnd",""));
5673 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5674 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5675 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5678 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5680 AOP_TYPE (left), AOP_TYPE (right));
5681 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5683 AOP_SIZE (left), AOP_SIZE (right));
5686 /* if left is a literal & right is not then exchange them */
5687 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5688 AOP_NEEDSACC (left))
5690 operand *tmp = right;
5695 /* if result = right then exchange left and right */
5696 if (sameRegs (AOP (result), AOP (right)))
5698 operand *tmp = right;
5703 /* if right is bit then exchange them */
5704 if (AOP_TYPE (right) == AOP_CRY &&
5705 AOP_TYPE (left) != AOP_CRY)
5707 operand *tmp = right;
5711 if (AOP_TYPE (right) == AOP_LIT)
5712 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5714 size = AOP_SIZE (result);
5717 // result = bit & yy;
5718 if (AOP_TYPE (left) == AOP_CRY)
5720 // c = bit & literal;
5721 if (AOP_TYPE (right) == AOP_LIT)
5725 if (size && sameRegs (AOP (result), AOP (left)))
5728 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5733 if (size && (AOP_TYPE (result) == AOP_CRY))
5735 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5738 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5743 emitcode ("clr", "c");
5748 if (AOP_TYPE (right) == AOP_CRY)
5751 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5752 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5757 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5759 emitcode ("rrc", "a");
5760 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5768 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5769 genIfxJump (ifx, "c", left, right, result);
5773 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5774 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5775 if ((AOP_TYPE (right) == AOP_LIT) &&
5776 (AOP_TYPE (result) == AOP_CRY) &&
5777 (AOP_TYPE (left) != AOP_CRY))
5779 int posbit = isLiteralBit (lit);
5784 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5788 switch (posbit & 0x07)
5790 case 0: emitcode ("rrc", "a");
5792 case 7: emitcode ("rlc", "a");
5794 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5803 SNPRINTF (buffer, sizeof(buffer),
5804 "acc.%d", posbit & 0x07);
5805 genIfxJump (ifx, buffer, left, right, result);
5808 {// what is this case? just found it in ds390/gen.c
5809 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5816 symbol *tlbl = newiTempLabel (NULL);
5817 int sizel = AOP_SIZE (left);
5819 emitcode ("setb", "c");
5822 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5824 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5826 if ((posbit = isLiteralBit (bytelit)) != 0)
5827 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5830 if (bytelit != 0x0FFL)
5831 emitcode ("anl", "a,%s",
5832 aopGet (AOP (right), offset, FALSE, TRUE));
5833 emitcode ("jnz", "%05d$", tlbl->key + 100);
5838 // bit = left & literal
5841 emitcode ("clr", "c");
5842 emitcode ("", "%05d$:", tlbl->key + 100);
5844 // if(left & literal)
5848 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5850 emitcode ("", "%05d$:", tlbl->key + 100);
5858 /* if left is same as result */
5859 if (sameRegs (AOP (result), AOP (left)))
5861 for (; size--; offset++)
5863 if (AOP_TYPE (right) == AOP_LIT)
5865 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5866 if (bytelit == 0x0FF)
5868 /* dummy read of volatile operand */
5869 if (isOperandVolatile (left, FALSE))
5870 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5874 else if (bytelit == 0)
5876 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5878 else if (IS_AOP_PREG (result))
5880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5881 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5882 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5885 emitcode ("anl", "%s,%s",
5886 aopGet (AOP (left), offset, FALSE, TRUE),
5887 aopGet (AOP (right), offset, FALSE, FALSE));
5891 if (AOP_TYPE (left) == AOP_ACC)
5892 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5895 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5896 if (IS_AOP_PREG (result))
5898 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5899 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5902 emitcode ("anl", "%s,a",
5903 aopGet (AOP (left), offset, FALSE, TRUE));
5910 // left & result in different registers
5911 if (AOP_TYPE (result) == AOP_CRY)
5914 // if(size), result in bit
5915 // if(!size && ifx), conditional oper: if(left & right)
5916 symbol *tlbl = newiTempLabel (NULL);
5917 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5919 emitcode ("setb", "c");
5922 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5923 emitcode ("anl", "a,%s",
5924 aopGet (AOP (right), offset, FALSE, FALSE));
5926 if (AOP_TYPE(left)==AOP_ACC) {
5927 bool pushedB = pushB ();
5928 emitcode("mov", "b,a");
5929 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5930 emitcode("anl", "a,b");
5933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5934 emitcode ("anl", "a,%s",
5935 aopGet (AOP (left), offset, FALSE, FALSE));
5938 emitcode ("jnz", "%05d$", tlbl->key + 100);
5944 emitcode ("", "%05d$:", tlbl->key + 100);
5948 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5950 emitcode ("", "%05d$:", tlbl->key + 100);
5954 for (; (size--); offset++)
5957 // result = left & right
5958 if (AOP_TYPE (right) == AOP_LIT)
5960 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5961 if (bytelit == 0x0FF)
5963 aopPut (AOP (result),
5964 aopGet (AOP (left), offset, FALSE, FALSE),
5966 isOperandVolatile (result, FALSE));
5969 else if (bytelit == 0)
5971 /* dummy read of volatile operand */
5972 if (isOperandVolatile (left, FALSE))
5973 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5974 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5978 // faster than result <- left, anl result,right
5979 // and better if result is SFR
5980 if (AOP_TYPE (left) == AOP_ACC)
5981 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5984 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5985 emitcode ("anl", "a,%s",
5986 aopGet (AOP (left), offset, FALSE, FALSE));
5988 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5994 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996 freeAsmop (result, NULL, ic, TRUE);
5999 /*-----------------------------------------------------------------*/
6000 /* genOr - code for or */
6001 /*-----------------------------------------------------------------*/
6003 genOr (iCode * ic, iCode * ifx)
6005 operand *left, *right, *result;
6006 int size, offset = 0;
6007 unsigned long lit = 0L;
6010 D(emitcode ("; genOr",""));
6012 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6013 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6014 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6017 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6019 AOP_TYPE (left), AOP_TYPE (right));
6020 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6022 AOP_SIZE (left), AOP_SIZE (right));
6025 /* if left is a literal & right is not then exchange them */
6026 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6027 AOP_NEEDSACC (left))
6029 operand *tmp = right;
6034 /* if result = right then exchange them */
6035 if (sameRegs (AOP (result), AOP (right)))
6037 operand *tmp = right;
6042 /* if right is bit then exchange them */
6043 if (AOP_TYPE (right) == AOP_CRY &&
6044 AOP_TYPE (left) != AOP_CRY)
6046 operand *tmp = right;
6050 if (AOP_TYPE (right) == AOP_LIT)
6051 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6053 size = AOP_SIZE (result);
6057 if (AOP_TYPE (left) == AOP_CRY)
6059 if (AOP_TYPE (right) == AOP_LIT)
6061 // c = bit | literal;
6064 // lit != 0 => result = 1
6065 if (AOP_TYPE (result) == AOP_CRY)
6068 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6070 continueIfTrue (ifx);
6073 emitcode ("setb", "c");
6077 // lit == 0 => result = left
6078 if (size && sameRegs (AOP (result), AOP (left)))
6080 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6085 if (AOP_TYPE (right) == AOP_CRY)
6088 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6089 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6094 symbol *tlbl = newiTempLabel (NULL);
6095 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6096 emitcode ("setb", "c");
6097 emitcode ("jb", "%s,%05d$",
6098 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6100 emitcode ("jnz", "%05d$", tlbl->key + 100);
6101 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6103 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6109 emitcode ("", "%05d$:", tlbl->key + 100);
6118 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6119 genIfxJump (ifx, "c", left, right, result);
6123 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6124 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6125 if ((AOP_TYPE (right) == AOP_LIT) &&
6126 (AOP_TYPE (result) == AOP_CRY) &&
6127 (AOP_TYPE (left) != AOP_CRY))
6133 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6135 continueIfTrue (ifx);
6140 // lit = 0, result = boolean(left)
6142 emitcode ("setb", "c");
6146 symbol *tlbl = newiTempLabel (NULL);
6147 emitcode ("jnz", "%05d$", tlbl->key + 100);
6149 emitcode ("", "%05d$:", tlbl->key + 100);
6153 genIfxJump (ifx, "a", left, right, result);
6161 /* if left is same as result */
6162 if (sameRegs (AOP (result), AOP (left)))
6164 for (; size--; offset++)
6166 if (AOP_TYPE (right) == AOP_LIT)
6168 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6171 /* dummy read of volatile operand */
6172 if (isOperandVolatile (left, FALSE))
6173 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6177 else if (bytelit == 0x0FF)
6179 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6181 else if (IS_AOP_PREG (left))
6183 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6184 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6185 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6189 emitcode ("orl", "%s,%s",
6190 aopGet (AOP (left), offset, FALSE, TRUE),
6191 aopGet (AOP (right), offset, FALSE, FALSE));
6196 if (AOP_TYPE (left) == AOP_ACC)
6197 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6200 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6201 if (IS_AOP_PREG (left))
6203 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6204 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6208 emitcode ("orl", "%s,a",
6209 aopGet (AOP (left), offset, FALSE, TRUE));
6217 // left & result in different registers
6218 if (AOP_TYPE (result) == AOP_CRY)
6221 // if(size), result in bit
6222 // if(!size && ifx), conditional oper: if(left | right)
6223 symbol *tlbl = newiTempLabel (NULL);
6224 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6226 emitcode ("setb", "c");
6229 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6230 emitcode ("orl", "a,%s",
6231 aopGet (AOP (right), offset, FALSE, FALSE));
6233 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6234 emitcode ("orl", "a,%s",
6235 aopGet (AOP (left), offset, FALSE, FALSE));
6237 emitcode ("jnz", "%05d$", tlbl->key + 100);
6243 emitcode ("", "%05d$:", tlbl->key + 100);
6247 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6249 emitcode ("", "%05d$:", tlbl->key + 100);
6253 for (; (size--); offset++)
6256 // result = left | right
6257 if (AOP_TYPE (right) == AOP_LIT)
6259 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6262 aopPut (AOP (result),
6263 aopGet (AOP (left), offset, FALSE, FALSE),
6265 isOperandVolatile (result, FALSE));
6268 else if (bytelit == 0x0FF)
6270 /* dummy read of volatile operand */
6271 if (isOperandVolatile (left, FALSE))
6272 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6273 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6277 // faster than result <- left, anl result,right
6278 // and better if result is SFR
6279 if (AOP_TYPE (left) == AOP_ACC)
6280 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6283 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6284 emitcode ("orl", "a,%s",
6285 aopGet (AOP (left), offset, FALSE, FALSE));
6287 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6293 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6294 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6295 freeAsmop (result, NULL, ic, TRUE);
6298 /*-----------------------------------------------------------------*/
6299 /* genXor - code for xclusive or */
6300 /*-----------------------------------------------------------------*/
6302 genXor (iCode * ic, iCode * ifx)
6304 operand *left, *right, *result;
6305 int size, offset = 0;
6306 unsigned long lit = 0L;
6309 D(emitcode ("; genXor",""));
6311 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6312 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6313 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6316 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6318 AOP_TYPE (left), AOP_TYPE (right));
6319 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6321 AOP_SIZE (left), AOP_SIZE (right));
6324 /* if left is a literal & right is not ||
6325 if left needs acc & right does not */
6326 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6327 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6329 operand *tmp = right;
6334 /* if result = right then exchange them */
6335 if (sameRegs (AOP (result), AOP (right)))
6337 operand *tmp = right;
6342 /* if right is bit then exchange them */
6343 if (AOP_TYPE (right) == AOP_CRY &&
6344 AOP_TYPE (left) != AOP_CRY)
6346 operand *tmp = right;
6350 if (AOP_TYPE (right) == AOP_LIT)
6351 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6353 size = AOP_SIZE (result);
6357 if (AOP_TYPE (left) == AOP_CRY)
6359 if (AOP_TYPE (right) == AOP_LIT)
6361 // c = bit & literal;
6364 // lit>>1 != 0 => result = 1
6365 if (AOP_TYPE (result) == AOP_CRY)
6368 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6370 continueIfTrue (ifx);
6373 emitcode ("setb", "c");
6380 // lit == 0, result = left
6381 if (size && sameRegs (AOP (result), AOP (left)))
6383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6387 // lit == 1, result = not(left)
6388 if (size && sameRegs (AOP (result), AOP (left)))
6390 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6395 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6396 emitcode ("cpl", "c");
6405 symbol *tlbl = newiTempLabel (NULL);
6406 if (AOP_TYPE (right) == AOP_CRY)
6409 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6413 int sizer = AOP_SIZE (right);
6415 // if val>>1 != 0, result = 1
6416 emitcode ("setb", "c");
6419 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6421 // test the msb of the lsb
6422 emitcode ("anl", "a,#0xfe");
6423 emitcode ("jnz", "%05d$", tlbl->key + 100);
6427 emitcode ("rrc", "a");
6429 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6430 emitcode ("cpl", "c");
6431 emitcode ("", "%05d$:", (tlbl->key + 100));
6438 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6439 genIfxJump (ifx, "c", left, right, result);
6443 /* if left is same as result */
6444 if (sameRegs (AOP (result), AOP (left)))
6446 for (; size--; offset++)
6448 if (AOP_TYPE (right) == AOP_LIT)
6450 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6453 /* dummy read of volatile operand */
6454 if (isOperandVolatile (left, FALSE))
6455 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6459 else if (IS_AOP_PREG (left))
6461 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6462 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6463 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6467 emitcode ("xrl", "%s,%s",
6468 aopGet (AOP (left), offset, FALSE, TRUE),
6469 aopGet (AOP (right), offset, FALSE, FALSE));
6474 if (AOP_TYPE (left) == AOP_ACC)
6475 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6478 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6479 if (IS_AOP_PREG (left))
6481 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6482 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6485 emitcode ("xrl", "%s,a",
6486 aopGet (AOP (left), offset, FALSE, TRUE));
6493 // left & result in different registers
6494 if (AOP_TYPE (result) == AOP_CRY)
6497 // if(size), result in bit
6498 // if(!size && ifx), conditional oper: if(left ^ right)
6499 symbol *tlbl = newiTempLabel (NULL);
6500 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6502 emitcode ("setb", "c");
6505 if ((AOP_TYPE (right) == AOP_LIT) &&
6506 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6508 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6512 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6513 emitcode ("xrl", "a,%s",
6514 aopGet (AOP (right), offset, FALSE, FALSE));
6516 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6517 emitcode ("xrl", "a,%s",
6518 aopGet (AOP (left), offset, FALSE, FALSE));
6521 emitcode ("jnz", "%05d$", tlbl->key + 100);
6527 emitcode ("", "%05d$:", tlbl->key + 100);
6531 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6535 for (; (size--); offset++)
6538 // result = left & right
6539 if (AOP_TYPE (right) == AOP_LIT)
6541 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6544 aopPut (AOP (result),
6545 aopGet (AOP (left), offset, FALSE, FALSE),
6547 isOperandVolatile (result, FALSE));
6551 // faster than result <- left, anl result,right
6552 // and better if result is SFR
6553 if (AOP_TYPE (left) == AOP_ACC)
6554 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6557 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6558 emitcode ("xrl", "a,%s",
6559 aopGet (AOP (left), offset, FALSE, TRUE));
6561 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6568 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6569 freeAsmop (result, NULL, ic, TRUE);
6572 /*-----------------------------------------------------------------*/
6573 /* genInline - write the inline code out */
6574 /*-----------------------------------------------------------------*/
6576 genInline (iCode * ic)
6578 char *buffer, *bp, *bp1;
6580 D(emitcode ("; genInline",""));
6582 _G.inLine += (!options.asmpeep);
6584 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6585 strcpy (buffer, IC_INLINE (ic));
6587 /* emit each line as a code */
6598 /* Add \n for labels, not dirs such as c:\mydir */
6599 if ( (*bp == ':') && (isspace(bp[1])) )
6613 /* emitcode("",buffer); */
6614 _G.inLine -= (!options.asmpeep);
6617 /*-----------------------------------------------------------------*/
6618 /* genRRC - rotate right with carry */
6619 /*-----------------------------------------------------------------*/
6623 operand *left, *result;
6624 int size, offset = 0;
6627 D(emitcode ("; genRRC",""));
6629 /* rotate right with carry */
6630 left = IC_LEFT (ic);
6631 result = IC_RESULT (ic);
6632 aopOp (left, ic, FALSE);
6633 aopOp (result, ic, FALSE);
6635 /* move it to the result */
6636 size = AOP_SIZE (result);
6638 if (size == 1) { /* special case for 1 byte */
6639 l = aopGet (AOP (left), offset, FALSE, FALSE);
6641 emitcode ("rr", "a");
6644 /* no need to clear carry, bit7 will be written later */
6647 l = aopGet (AOP (left), offset, FALSE, FALSE);
6649 emitcode ("rrc", "a");
6650 if (AOP_SIZE (result) > 1)
6651 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6653 /* now we need to put the carry into the
6654 highest order byte of the result */
6655 if (AOP_SIZE (result) > 1)
6657 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6660 emitcode ("mov", "acc.7,c");
6662 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6663 freeAsmop (left, NULL, ic, TRUE);
6664 freeAsmop (result, NULL, ic, TRUE);
6667 /*-----------------------------------------------------------------*/
6668 /* genRLC - generate code for rotate left with carry */
6669 /*-----------------------------------------------------------------*/
6673 operand *left, *result;
6674 int size, offset = 0;
6677 D(emitcode ("; genRLC",""));
6679 /* rotate right with carry */
6680 left = IC_LEFT (ic);
6681 result = IC_RESULT (ic);
6682 aopOp (left, ic, FALSE);
6683 aopOp (result, ic, FALSE);
6685 /* move it to the result */
6686 size = AOP_SIZE (result);
6690 l = aopGet (AOP (left), offset, FALSE, FALSE);
6692 if (size == 0) { /* special case for 1 byte */
6696 emitcode("rlc","a"); /* bit0 will be written later */
6697 if (AOP_SIZE (result) > 1)
6698 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6701 l = aopGet (AOP (left), offset, FALSE, FALSE);
6703 emitcode ("rlc", "a");
6704 if (AOP_SIZE (result) > 1)
6705 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6708 /* now we need to put the carry into the
6709 highest order byte of the result */
6710 if (AOP_SIZE (result) > 1)
6712 l = aopGet (AOP (result), 0, FALSE, FALSE);
6715 emitcode ("mov", "acc.0,c");
6717 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6718 freeAsmop (left, NULL, ic, TRUE);
6719 freeAsmop (result, NULL, ic, TRUE);
6722 /*-----------------------------------------------------------------*/
6723 /* genGetHbit - generates code get highest order bit */
6724 /*-----------------------------------------------------------------*/
6726 genGetHbit (iCode * ic)
6728 operand *left, *result;
6730 D(emitcode ("; genGetHbit",""));
6732 left = IC_LEFT (ic);
6733 result = IC_RESULT (ic);
6734 aopOp (left, ic, FALSE);
6735 aopOp (result, ic, FALSE);
6737 /* get the highest order byte into a */
6738 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6739 if (AOP_TYPE (result) == AOP_CRY)
6741 emitcode ("rlc", "a");
6746 emitcode ("rl", "a");
6747 emitcode ("anl", "a,#0x01");
6752 freeAsmop (left, NULL, ic, TRUE);
6753 freeAsmop (result, NULL, ic, TRUE);
6756 /*-----------------------------------------------------------------*/
6757 /* genSwap - generates code to swap nibbles or bytes */
6758 /*-----------------------------------------------------------------*/
6760 genSwap (iCode * ic)
6762 operand *left, *result;
6764 D(emitcode ("; genSwap",""));
6766 left = IC_LEFT (ic);
6767 result = IC_RESULT (ic);
6768 aopOp (left, ic, FALSE);
6769 aopOp (result, ic, FALSE);
6771 switch (AOP_SIZE (left))
6773 case 1: /* swap nibbles in byte */
6774 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6775 emitcode ("swap", "a");
6776 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6778 case 2: /* swap bytes in word */
6779 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6781 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6782 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6783 0, isOperandVolatile (result, FALSE));
6784 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6786 else if (operandsEqu (left, result))
6789 bool pushedB = FALSE, leftInB = FALSE;
6791 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6792 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6795 emitcode ("mov", "b,a");
6799 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6800 0, isOperandVolatile (result, FALSE));
6801 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6808 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6809 0, isOperandVolatile (result, FALSE));
6810 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6811 1, isOperandVolatile (result, FALSE));
6815 wassertl(FALSE, "unsupported SWAP operand size");
6818 freeAsmop (left, NULL, ic, TRUE);
6819 freeAsmop (result, NULL, ic, TRUE);
6823 /*-----------------------------------------------------------------*/
6824 /* AccRol - rotate left accumulator by known count */
6825 /*-----------------------------------------------------------------*/
6827 AccRol (int shCount)
6829 shCount &= 0x0007; // shCount : 0..7
6836 emitcode ("rl", "a");
6839 emitcode ("rl", "a");
6840 emitcode ("rl", "a");
6843 emitcode ("swap", "a");
6844 emitcode ("rr", "a");
6847 emitcode ("swap", "a");
6850 emitcode ("swap", "a");
6851 emitcode ("rl", "a");
6854 emitcode ("rr", "a");
6855 emitcode ("rr", "a");
6858 emitcode ("rr", "a");
6863 /*-----------------------------------------------------------------*/
6864 /* AccLsh - left shift accumulator by known count */
6865 /*-----------------------------------------------------------------*/
6867 AccLsh (int shCount)
6872 emitcode ("add", "a,acc");
6873 else if (shCount == 2)
6875 emitcode ("add", "a,acc");
6876 emitcode ("add", "a,acc");
6880 /* rotate left accumulator */
6882 /* and kill the lower order bits */
6883 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6888 /*-----------------------------------------------------------------*/
6889 /* AccRsh - right shift accumulator by known count */
6890 /*-----------------------------------------------------------------*/
6892 AccRsh (int shCount)
6899 emitcode ("rrc", "a");
6903 /* rotate right accumulator */
6904 AccRol (8 - shCount);
6905 /* and kill the higher order bits */
6906 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6911 /*-----------------------------------------------------------------*/
6912 /* AccSRsh - signed right shift accumulator by known count */
6913 /*-----------------------------------------------------------------*/
6915 AccSRsh (int shCount)
6922 emitcode ("mov", "c,acc.7");
6923 emitcode ("rrc", "a");
6925 else if (shCount == 2)
6927 emitcode ("mov", "c,acc.7");
6928 emitcode ("rrc", "a");
6929 emitcode ("mov", "c,acc.7");
6930 emitcode ("rrc", "a");
6934 tlbl = newiTempLabel (NULL);
6935 /* rotate right accumulator */
6936 AccRol (8 - shCount);
6937 /* and kill the higher order bits */
6938 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6939 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6940 emitcode ("orl", "a,#0x%02x",
6941 (unsigned char) ~SRMask[shCount]);
6942 emitcode ("", "%05d$:", tlbl->key + 100);
6947 /*-----------------------------------------------------------------*/
6948 /* shiftR1Left2Result - shift right one byte from left to result */
6949 /*-----------------------------------------------------------------*/
6951 shiftR1Left2Result (operand * left, int offl,
6952 operand * result, int offr,
6953 int shCount, int sign)
6955 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6956 /* shift right accumulator */
6961 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6964 /*-----------------------------------------------------------------*/
6965 /* shiftL1Left2Result - shift left one byte from left to result */
6966 /*-----------------------------------------------------------------*/
6968 shiftL1Left2Result (operand * left, int offl,
6969 operand * result, int offr, int shCount)
6972 l = aopGet (AOP (left), offl, FALSE, FALSE);
6974 /* shift left accumulator */
6976 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6979 /*-----------------------------------------------------------------*/
6980 /* movLeft2Result - move byte from left to result */
6981 /*-----------------------------------------------------------------*/
6983 movLeft2Result (operand * left, int offl,
6984 operand * result, int offr, int sign)
6987 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6989 l = aopGet (AOP (left), offl, FALSE, FALSE);
6991 if (*l == '@' && (IS_AOP_PREG (result)))
6993 emitcode ("mov", "a,%s", l);
6994 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6999 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
7002 /* MSB sign in acc.7 ! */
7003 if (getDataSize (left) == offl + 1)
7005 emitcode ("mov", "a,%s", l);
7006 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7013 /*-----------------------------------------------------------------*/
7014 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7015 /*-----------------------------------------------------------------*/
7019 emitcode ("rrc", "a");
7020 emitcode ("xch", "a,%s", x);
7021 emitcode ("rrc", "a");
7022 emitcode ("xch", "a,%s", x);
7025 /*-----------------------------------------------------------------*/
7026 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7027 /*-----------------------------------------------------------------*/
7031 emitcode ("xch", "a,%s", x);
7032 emitcode ("rlc", "a");
7033 emitcode ("xch", "a,%s", x);
7034 emitcode ("rlc", "a");
7037 /*-----------------------------------------------------------------*/
7038 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7039 /*-----------------------------------------------------------------*/
7043 emitcode ("xch", "a,%s", x);
7044 emitcode ("add", "a,acc");
7045 emitcode ("xch", "a,%s", x);
7046 emitcode ("rlc", "a");
7049 /*-----------------------------------------------------------------*/
7050 /* AccAXLsh - left shift a:x by known count (0..7) */
7051 /*-----------------------------------------------------------------*/
7053 AccAXLsh (char *x, int shCount)
7068 case 5: // AAAAABBB:CCCCCDDD
7070 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7072 emitcode ("anl", "a,#0x%02x",
7073 SLMask[shCount]); // BBB00000:CCCCCDDD
7075 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7077 AccRol (shCount); // DDDCCCCC:BBB00000
7079 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7081 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7083 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7085 emitcode ("anl", "a,#0x%02x",
7086 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7088 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7090 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7093 case 6: // AAAAAABB:CCCCCCDD
7094 emitcode ("anl", "a,#0x%02x",
7095 SRMask[shCount]); // 000000BB:CCCCCCDD
7096 emitcode ("mov", "c,acc.0"); // c = B
7097 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7099 AccAXRrl1 (x); // BCCCCCCD:D000000B
7100 AccAXRrl1 (x); // BBCCCCCC:DD000000
7102 emitcode("rrc","a");
7103 emitcode("xch","a,%s", x);
7104 emitcode("rrc","a");
7105 emitcode("mov","c,acc.0"); //<< get correct bit
7106 emitcode("xch","a,%s", x);
7108 emitcode("rrc","a");
7109 emitcode("xch","a,%s", x);
7110 emitcode("rrc","a");
7111 emitcode("xch","a,%s", x);
7114 case 7: // a:x <<= 7
7116 emitcode ("anl", "a,#0x%02x",
7117 SRMask[shCount]); // 0000000B:CCCCCCCD
7119 emitcode ("mov", "c,acc.0"); // c = B
7121 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7123 AccAXRrl1 (x); // BCCCCCCC:D0000000
7131 /*-----------------------------------------------------------------*/
7132 /* AccAXRsh - right shift a:x known count (0..7) */
7133 /*-----------------------------------------------------------------*/
7135 AccAXRsh (char *x, int shCount)
7143 AccAXRrl1 (x); // 0->a:x
7148 AccAXRrl1 (x); // 0->a:x
7151 AccAXRrl1 (x); // 0->a:x
7156 case 5: // AAAAABBB:CCCCCDDD = a:x
7158 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7160 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7162 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7164 emitcode ("anl", "a,#0x%02x",
7165 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7167 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7169 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7171 emitcode ("anl", "a,#0x%02x",
7172 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7174 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7176 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7178 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7181 case 6: // AABBBBBB:CCDDDDDD
7183 emitcode ("mov", "c,acc.7");
7184 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7186 emitcode ("mov", "c,acc.7");
7187 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7189 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7191 emitcode ("anl", "a,#0x%02x",
7192 SRMask[shCount]); // 000000AA:BBBBBBCC
7195 case 7: // ABBBBBBB:CDDDDDDD
7197 emitcode ("mov", "c,acc.7"); // c = A
7199 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7201 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7203 emitcode ("anl", "a,#0x%02x",
7204 SRMask[shCount]); // 0000000A:BBBBBBBC
7212 /*-----------------------------------------------------------------*/
7213 /* AccAXRshS - right shift signed a:x known count (0..7) */
7214 /*-----------------------------------------------------------------*/
7216 AccAXRshS (char *x, int shCount)
7224 emitcode ("mov", "c,acc.7");
7225 AccAXRrl1 (x); // s->a:x
7229 emitcode ("mov", "c,acc.7");
7230 AccAXRrl1 (x); // s->a:x
7232 emitcode ("mov", "c,acc.7");
7233 AccAXRrl1 (x); // s->a:x
7238 case 5: // AAAAABBB:CCCCCDDD = a:x
7240 tlbl = newiTempLabel (NULL);
7241 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7243 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7245 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7247 emitcode ("anl", "a,#0x%02x",
7248 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7250 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7252 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7254 emitcode ("anl", "a,#0x%02x",
7255 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7257 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7259 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7261 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7263 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7264 emitcode ("orl", "a,#0x%02x",
7265 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7267 emitcode ("", "%05d$:", tlbl->key + 100);
7268 break; // SSSSAAAA:BBBCCCCC
7270 case 6: // AABBBBBB:CCDDDDDD
7272 tlbl = newiTempLabel (NULL);
7273 emitcode ("mov", "c,acc.7");
7274 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7276 emitcode ("mov", "c,acc.7");
7277 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7279 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7281 emitcode ("anl", "a,#0x%02x",
7282 SRMask[shCount]); // 000000AA:BBBBBBCC
7284 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7285 emitcode ("orl", "a,#0x%02x",
7286 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7288 emitcode ("", "%05d$:", tlbl->key + 100);
7290 case 7: // ABBBBBBB:CDDDDDDD
7292 tlbl = newiTempLabel (NULL);
7293 emitcode ("mov", "c,acc.7"); // c = A
7295 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7297 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7299 emitcode ("anl", "a,#0x%02x",
7300 SRMask[shCount]); // 0000000A:BBBBBBBC
7302 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7303 emitcode ("orl", "a,#0x%02x",
7304 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7306 emitcode ("", "%05d$:", tlbl->key + 100);
7313 /*-----------------------------------------------------------------*/
7314 /* shiftL2Left2Result - shift left two bytes from left to result */
7315 /*-----------------------------------------------------------------*/
7317 shiftL2Left2Result (operand * left, int offl,
7318 operand * result, int offr, int shCount)
7320 if (sameRegs (AOP (result), AOP (left)) &&
7321 ((offl + MSB16) == offr))
7323 /* don't crash result[offr] */
7324 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7325 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7329 movLeft2Result (left, offl, result, offr, 0);
7330 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7332 /* ax << shCount (x = lsb(result)) */
7333 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7334 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7338 /*-----------------------------------------------------------------*/
7339 /* shiftR2Left2Result - shift right two bytes from left to result */
7340 /*-----------------------------------------------------------------*/
7342 shiftR2Left2Result (operand * left, int offl,
7343 operand * result, int offr,
7344 int shCount, int sign)
7346 if (sameRegs (AOP (result), AOP (left)) &&
7347 ((offl + MSB16) == offr))
7349 /* don't crash result[offr] */
7350 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7351 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7355 movLeft2Result (left, offl, result, offr, 0);
7356 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7358 /* a:x >> shCount (x = lsb(result)) */
7360 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7362 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7363 if (getDataSize (result) > 1)
7364 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7367 /*-----------------------------------------------------------------*/
7368 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7369 /*-----------------------------------------------------------------*/
7371 shiftLLeftOrResult (operand * left, int offl,
7372 operand * result, int offr, int shCount)
7374 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7375 /* shift left accumulator */
7377 /* or with result */
7378 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7379 /* back to result */
7380 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7383 /*-----------------------------------------------------------------*/
7384 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7385 /*-----------------------------------------------------------------*/
7387 shiftRLeftOrResult (operand * left, int offl,
7388 operand * result, int offr, int shCount)
7390 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7391 /* shift right accumulator */
7393 /* or with result */
7394 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7395 /* back to result */
7396 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7399 /*-----------------------------------------------------------------*/
7400 /* genlshOne - left shift a one byte quantity by known count */
7401 /*-----------------------------------------------------------------*/
7403 genlshOne (operand * result, operand * left, int shCount)
7405 D(emitcode ("; genlshOne",""));
7407 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7410 /*-----------------------------------------------------------------*/
7411 /* genlshTwo - left shift two bytes by known amount != 0 */
7412 /*-----------------------------------------------------------------*/
7414 genlshTwo (operand * result, operand * left, int shCount)
7418 D(emitcode ("; genlshTwo",""));
7420 size = getDataSize (result);
7422 /* if shCount >= 8 */
7430 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7432 movLeft2Result (left, LSB, result, MSB16, 0);
7434 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7437 /* 1 <= shCount <= 7 */
7441 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7443 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7447 /*-----------------------------------------------------------------*/
7448 /* shiftLLong - shift left one long from left to result */
7449 /* offl = LSB or MSB16 */
7450 /*-----------------------------------------------------------------*/
7452 shiftLLong (operand * left, operand * result, int offr)
7455 int size = AOP_SIZE (result);
7457 if (size >= LSB + offr)
7459 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7461 emitcode ("add", "a,acc");
7462 if (sameRegs (AOP (left), AOP (result)) &&
7463 size >= MSB16 + offr && offr != LSB)
7464 emitcode ("xch", "a,%s",
7465 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7467 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7470 if (size >= MSB16 + offr)
7472 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7474 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7477 emitcode ("rlc", "a");
7478 if (sameRegs (AOP (left), AOP (result)) &&
7479 size >= MSB24 + offr && offr != LSB)
7480 emitcode ("xch", "a,%s",
7481 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7483 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7486 if (size >= MSB24 + offr)
7488 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7490 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7493 emitcode ("rlc", "a");
7494 if (sameRegs (AOP (left), AOP (result)) &&
7495 size >= MSB32 + offr && offr != LSB)
7496 emitcode ("xch", "a,%s",
7497 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7499 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7502 if (size > MSB32 + offr)
7504 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7506 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7509 emitcode ("rlc", "a");
7510 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7513 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7516 /*-----------------------------------------------------------------*/
7517 /* genlshFour - shift four byte by a known amount != 0 */
7518 /*-----------------------------------------------------------------*/
7520 genlshFour (operand * result, operand * left, int shCount)
7524 D(emitcode ("; genlshFour",""));
7526 size = AOP_SIZE (result);
7528 /* if shifting more that 3 bytes */
7533 /* lowest order of left goes to the highest
7534 order of the destination */
7535 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7537 movLeft2Result (left, LSB, result, MSB32, 0);
7538 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7539 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7540 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7544 /* more than two bytes */
7545 else if (shCount >= 16)
7547 /* lower order two bytes goes to higher order two bytes */
7549 /* if some more remaining */
7551 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7554 movLeft2Result (left, MSB16, result, MSB32, 0);
7555 movLeft2Result (left, LSB, result, MSB24, 0);
7557 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7558 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7562 /* if more than 1 byte */
7563 else if (shCount >= 8)
7565 /* lower order three bytes goes to higher order three bytes */
7570 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7572 movLeft2Result (left, LSB, result, MSB16, 0);
7578 movLeft2Result (left, MSB24, result, MSB32, 0);
7579 movLeft2Result (left, MSB16, result, MSB24, 0);
7580 movLeft2Result (left, LSB, result, MSB16, 0);
7581 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7583 else if (shCount == 1)
7584 shiftLLong (left, result, MSB16);
7587 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7588 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7589 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7590 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7595 /* 1 <= shCount <= 7 */
7596 else if (shCount <= 2)
7598 shiftLLong (left, result, LSB);
7600 shiftLLong (result, result, LSB);
7602 /* 3 <= shCount <= 7, optimize */
7605 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7606 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7607 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7611 /*-----------------------------------------------------------------*/
7612 /* genLeftShiftLiteral - left shifting by known count */
7613 /*-----------------------------------------------------------------*/
7615 genLeftShiftLiteral (operand * left,
7620 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7623 D(emitcode ("; genLeftShiftLiteral",""));
7625 freeAsmop (right, NULL, ic, TRUE);
7627 aopOp (left, ic, FALSE);
7628 aopOp (result, ic, FALSE);
7630 size = getSize (operandType (result));
7633 emitcode ("; shift left ", "result %d, left %d", size,
7637 /* I suppose that the left size >= result size */
7642 movLeft2Result (left, size, result, size, 0);
7646 else if (shCount >= (size * 8))
7648 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7654 genlshOne (result, left, shCount);
7658 genlshTwo (result, left, shCount);
7662 genlshFour (result, left, shCount);
7665 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7666 "*** ack! mystery literal shift!\n");
7670 freeAsmop (left, NULL, ic, TRUE);
7671 freeAsmop (result, NULL, ic, TRUE);
7674 /*-----------------------------------------------------------------*/
7675 /* genLeftShift - generates code for left shifting */
7676 /*-----------------------------------------------------------------*/
7678 genLeftShift (iCode * ic)
7680 operand *left, *right, *result;
7683 symbol *tlbl, *tlbl1;
7686 D(emitcode ("; genLeftShift",""));
7688 right = IC_RIGHT (ic);
7689 left = IC_LEFT (ic);
7690 result = IC_RESULT (ic);
7692 aopOp (right, ic, FALSE);
7694 /* if the shift count is known then do it
7695 as efficiently as possible */
7696 if (AOP_TYPE (right) == AOP_LIT)
7698 genLeftShiftLiteral (left, right, result, ic);
7702 /* shift count is unknown then we have to form
7703 a loop get the loop count in B : Note: we take
7704 only the lower order byte since shifting
7705 more that 32 bits make no sense anyway, ( the
7706 largest size of an object can be only 32 bits ) */
7709 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7710 emitcode ("inc", "b");
7711 freeAsmop (right, NULL, ic, TRUE);
7712 aopOp (left, ic, FALSE);
7713 aopOp (result, ic, FALSE);
7715 /* now move the left to the result if they are not the same */
7716 if (!sameRegs (AOP (left), AOP (result)) &&
7717 AOP_SIZE (result) > 1)
7720 size = AOP_SIZE (result);
7724 l = aopGet (AOP (left), offset, FALSE, TRUE);
7725 if (*l == '@' && (IS_AOP_PREG (result)))
7728 emitcode ("mov", "a,%s", l);
7729 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7732 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7737 tlbl = newiTempLabel (NULL);
7738 size = AOP_SIZE (result);
7740 tlbl1 = newiTempLabel (NULL);
7742 /* if it is only one byte then */
7745 symbol *tlbl1 = newiTempLabel (NULL);
7747 l = aopGet (AOP (left), 0, FALSE, FALSE);
7749 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7750 emitcode ("", "%05d$:", tlbl->key + 100);
7751 emitcode ("add", "a,acc");
7752 emitcode ("", "%05d$:", tlbl1->key + 100);
7753 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7755 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7759 reAdjustPreg (AOP (result));
7761 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7762 emitcode ("", "%05d$:", tlbl->key + 100);
7763 l = aopGet (AOP (result), offset, FALSE, FALSE);
7765 emitcode ("add", "a,acc");
7766 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7769 l = aopGet (AOP (result), offset, FALSE, FALSE);
7771 emitcode ("rlc", "a");
7772 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7774 reAdjustPreg (AOP (result));
7776 emitcode ("", "%05d$:", tlbl1->key + 100);
7777 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7780 freeAsmop (left, NULL, ic, TRUE);
7781 freeAsmop (result, NULL, ic, TRUE);
7784 /*-----------------------------------------------------------------*/
7785 /* genrshOne - right shift a one byte quantity by known count */
7786 /*-----------------------------------------------------------------*/
7788 genrshOne (operand * result, operand * left,
7789 int shCount, int sign)
7791 D(emitcode ("; genrshOne",""));
7793 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7796 /*-----------------------------------------------------------------*/
7797 /* genrshTwo - right shift two bytes by known amount != 0 */
7798 /*-----------------------------------------------------------------*/
7800 genrshTwo (operand * result, operand * left,
7801 int shCount, int sign)
7803 D(emitcode ("; genrshTwo",""));
7805 /* if shCount >= 8 */
7810 shiftR1Left2Result (left, MSB16, result, LSB,
7813 movLeft2Result (left, MSB16, result, LSB, sign);
7814 addSign (result, MSB16, sign);
7817 /* 1 <= shCount <= 7 */
7819 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7822 /*-----------------------------------------------------------------*/
7823 /* shiftRLong - shift right one long from left to result */
7824 /* offl = LSB or MSB16 */
7825 /*-----------------------------------------------------------------*/
7827 shiftRLong (operand * left, int offl,
7828 operand * result, int sign)
7830 int isSameRegs=sameRegs(AOP(left),AOP(result));
7832 if (isSameRegs && offl>1) {
7833 // we are in big trouble, but this shouldn't happen
7834 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7837 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7842 emitcode ("rlc", "a");
7843 emitcode ("subb", "a,acc");
7845 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7847 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7848 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7851 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7856 emitcode ("clr", "c");
7858 emitcode ("mov", "c,acc.7");
7861 emitcode ("rrc", "a");
7863 if (isSameRegs && offl==MSB16) {
7864 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7866 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7867 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7870 emitcode ("rrc", "a");
7871 if (isSameRegs && offl==1) {
7872 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7874 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7875 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7877 emitcode ("rrc", "a");
7878 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7882 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7883 emitcode ("rrc", "a");
7884 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7888 /*-----------------------------------------------------------------*/
7889 /* genrshFour - shift four byte by a known amount != 0 */
7890 /*-----------------------------------------------------------------*/
7892 genrshFour (operand * result, operand * left,
7893 int shCount, int sign)
7895 D(emitcode ("; genrshFour",""));
7897 /* if shifting more that 3 bytes */
7902 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7904 movLeft2Result (left, MSB32, result, LSB, sign);
7905 addSign (result, MSB16, sign);
7907 else if (shCount >= 16)
7911 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7914 movLeft2Result (left, MSB24, result, LSB, 0);
7915 movLeft2Result (left, MSB32, result, MSB16, sign);
7917 addSign (result, MSB24, sign);
7919 else if (shCount >= 8)
7923 shiftRLong (left, MSB16, result, sign);
7924 else if (shCount == 0)
7926 movLeft2Result (left, MSB16, result, LSB, 0);
7927 movLeft2Result (left, MSB24, result, MSB16, 0);
7928 movLeft2Result (left, MSB32, result, MSB24, sign);
7929 addSign (result, MSB32, sign);
7933 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7934 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7935 /* the last shift is signed */
7936 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7937 addSign (result, MSB32, sign);
7941 { /* 1 <= shCount <= 7 */
7944 shiftRLong (left, LSB, result, sign);
7946 shiftRLong (result, LSB, result, sign);
7950 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7951 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7952 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7957 /*-----------------------------------------------------------------*/
7958 /* genRightShiftLiteral - right shifting by known count */
7959 /*-----------------------------------------------------------------*/
7961 genRightShiftLiteral (operand * left,
7967 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7970 D(emitcode ("; genRightShiftLiteral",""));
7972 freeAsmop (right, NULL, ic, TRUE);
7974 aopOp (left, ic, FALSE);
7975 aopOp (result, ic, FALSE);
7978 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7982 size = getDataSize (left);
7983 /* test the LEFT size !!! */
7985 /* I suppose that the left size >= result size */
7988 size = getDataSize (result);
7990 movLeft2Result (left, size, result, size, 0);
7993 else if (shCount >= (size * 8))
7996 /* get sign in acc.7 */
7997 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7999 addSign (result, LSB, sign);
8006 genrshOne (result, left, shCount, sign);
8010 genrshTwo (result, left, shCount, sign);
8014 genrshFour (result, left, shCount, sign);
8020 freeAsmop (left, NULL, ic, TRUE);
8021 freeAsmop (result, NULL, ic, TRUE);
8024 /*-----------------------------------------------------------------*/
8025 /* genSignedRightShift - right shift of signed number */
8026 /*-----------------------------------------------------------------*/
8028 genSignedRightShift (iCode * ic)
8030 operand *right, *left, *result;
8033 symbol *tlbl, *tlbl1;
8036 D(emitcode ("; genSignedRightShift",""));
8038 /* we do it the hard way put the shift count in b
8039 and loop thru preserving the sign */
8041 right = IC_RIGHT (ic);
8042 left = IC_LEFT (ic);
8043 result = IC_RESULT (ic);
8045 aopOp (right, ic, FALSE);
8048 if (AOP_TYPE (right) == AOP_LIT)
8050 genRightShiftLiteral (left, right, result, ic, 1);
8053 /* shift count is unknown then we have to form
8054 a loop get the loop count in B : Note: we take
8055 only the lower order byte since shifting
8056 more that 32 bits make no sense anyway, ( the
8057 largest size of an object can be only 32 bits ) */
8060 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8061 emitcode ("inc", "b");
8062 freeAsmop (right, NULL, ic, TRUE);
8063 aopOp (left, ic, FALSE);
8064 aopOp (result, ic, FALSE);
8066 /* now move the left to the result if they are not the
8068 if (!sameRegs (AOP (left), AOP (result)) &&
8069 AOP_SIZE (result) > 1)
8072 size = AOP_SIZE (result);
8076 l = aopGet (AOP (left), offset, FALSE, TRUE);
8077 if (*l == '@' && IS_AOP_PREG (result))
8080 emitcode ("mov", "a,%s", l);
8081 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8084 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8089 /* mov the highest order bit to OVR */
8090 tlbl = newiTempLabel (NULL);
8091 tlbl1 = newiTempLabel (NULL);
8093 size = AOP_SIZE (result);
8095 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8096 emitcode ("rlc", "a");
8097 emitcode ("mov", "ov,c");
8098 /* if it is only one byte then */
8101 l = aopGet (AOP (left), 0, FALSE, FALSE);
8103 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8104 emitcode ("", "%05d$:", tlbl->key + 100);
8105 emitcode ("mov", "c,ov");
8106 emitcode ("rrc", "a");
8107 emitcode ("", "%05d$:", tlbl1->key + 100);
8108 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8110 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8114 reAdjustPreg (AOP (result));
8115 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8116 emitcode ("", "%05d$:", tlbl->key + 100);
8117 emitcode ("mov", "c,ov");
8120 l = aopGet (AOP (result), offset, FALSE, FALSE);
8122 emitcode ("rrc", "a");
8123 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8125 reAdjustPreg (AOP (result));
8126 emitcode ("", "%05d$:", tlbl1->key + 100);
8127 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8131 freeAsmop (left, NULL, ic, TRUE);
8132 freeAsmop (result, NULL, ic, TRUE);
8135 /*-----------------------------------------------------------------*/
8136 /* genRightShift - generate code for right shifting */
8137 /*-----------------------------------------------------------------*/
8139 genRightShift (iCode * ic)
8141 operand *right, *left, *result;
8145 symbol *tlbl, *tlbl1;
8148 D(emitcode ("; genRightShift",""));
8150 /* if signed then we do it the hard way preserve the
8151 sign bit moving it inwards */
8152 letype = getSpec (operandType (IC_LEFT (ic)));
8154 if (!SPEC_USIGN (letype))
8156 genSignedRightShift (ic);
8160 /* signed & unsigned types are treated the same : i.e. the
8161 signed is NOT propagated inwards : quoting from the
8162 ANSI - standard : "for E1 >> E2, is equivalent to division
8163 by 2**E2 if unsigned or if it has a non-negative value,
8164 otherwise the result is implementation defined ", MY definition
8165 is that the sign does not get propagated */
8167 right = IC_RIGHT (ic);
8168 left = IC_LEFT (ic);
8169 result = IC_RESULT (ic);
8171 aopOp (right, ic, FALSE);
8173 /* if the shift count is known then do it
8174 as efficiently as possible */
8175 if (AOP_TYPE (right) == AOP_LIT)
8177 genRightShiftLiteral (left, right, result, ic, 0);
8181 /* shift count is unknown then we have to form
8182 a loop get the loop count in B : Note: we take
8183 only the lower order byte since shifting
8184 more that 32 bits make no sense anyway, ( the
8185 largest size of an object can be only 32 bits ) */
8188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8189 emitcode ("inc", "b");
8190 freeAsmop (right, NULL, ic, TRUE);
8191 aopOp (left, ic, FALSE);
8192 aopOp (result, ic, FALSE);
8194 /* now move the left to the result if they are not the
8196 if (!sameRegs (AOP (left), AOP (result)) &&
8197 AOP_SIZE (result) > 1)
8200 size = AOP_SIZE (result);
8204 l = aopGet (AOP (left), offset, FALSE, TRUE);
8205 if (*l == '@' && IS_AOP_PREG (result))
8208 emitcode ("mov", "a,%s", l);
8209 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8212 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8217 tlbl = newiTempLabel (NULL);
8218 tlbl1 = newiTempLabel (NULL);
8219 size = AOP_SIZE (result);
8222 /* if it is only one byte then */
8225 l = aopGet (AOP (left), 0, FALSE, FALSE);
8227 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8228 emitcode ("", "%05d$:", tlbl->key + 100);
8230 emitcode ("rrc", "a");
8231 emitcode ("", "%05d$:", tlbl1->key + 100);
8232 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8234 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8238 reAdjustPreg (AOP (result));
8239 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8240 emitcode ("", "%05d$:", tlbl->key + 100);
8244 l = aopGet (AOP (result), offset, FALSE, FALSE);
8246 emitcode ("rrc", "a");
8247 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8249 reAdjustPreg (AOP (result));
8251 emitcode ("", "%05d$:", tlbl1->key + 100);
8252 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8256 freeAsmop (left, NULL, ic, TRUE);
8257 freeAsmop (result, NULL, ic, TRUE);
8260 /*-----------------------------------------------------------------*/
8261 /* emitPtrByteGet - emits code to get a byte into A through a */
8262 /* pointer register (R0, R1, or DPTR). The */
8263 /* original value of A can be preserved in B. */
8264 /*-----------------------------------------------------------------*/
8266 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8273 emitcode ("mov", "b,a");
8274 emitcode ("mov", "a,@%s", rname);
8279 emitcode ("mov", "b,a");
8280 emitcode ("movx", "a,@%s", rname);
8285 emitcode ("mov", "b,a");
8286 emitcode ("movx", "a,@dptr");
8291 emitcode ("mov", "b,a");
8292 emitcode ("clr", "a");
8293 emitcode ("movc", "a,@a+dptr");
8299 emitcode ("push", "b");
8300 emitcode ("push", "acc");
8302 emitcode ("lcall", "__gptrget");
8304 emitcode ("pop", "b");
8309 /*-----------------------------------------------------------------*/
8310 /* emitPtrByteSet - emits code to set a byte from src through a */
8311 /* pointer register (R0, R1, or DPTR). */
8312 /*-----------------------------------------------------------------*/
8314 emitPtrByteSet (char *rname, int p_type, char *src)
8323 emitcode ("mov", "@%s,a", rname);
8326 emitcode ("mov", "@%s,%s", rname, src);
8331 emitcode ("movx", "@%s,a", rname);
8336 emitcode ("movx", "@dptr,a");
8341 emitcode ("lcall", "__gptrput");
8346 /*-----------------------------------------------------------------*/
8347 /* genUnpackBits - generates code for unpacking bits */
8348 /*-----------------------------------------------------------------*/
8350 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8352 int offset = 0; /* result byte offset */
8353 int rsize; /* result size */
8354 int rlen = 0; /* remaining bitfield length */
8355 sym_link *etype; /* bitfield type information */
8356 int blen; /* bitfield length */
8357 int bstr; /* bitfield starting bit within byte */
8360 D(emitcode ("; genUnpackBits",""));
8362 etype = getSpec (operandType (result));
8363 rsize = getSize (operandType (result));
8364 blen = SPEC_BLEN (etype);
8365 bstr = SPEC_BSTR (etype);
8367 if (ifx && blen <= 8)
8369 emitPtrByteGet (rname, ptype, FALSE);
8372 SNPRINTF (buffer, sizeof(buffer),
8374 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8379 emitcode ("anl", "a,#0x%02x",
8380 (((unsigned char) -1) >> (8 - blen)) << bstr);
8381 genIfxJump (ifx, "a", NULL, NULL, NULL);
8387 /* If the bitfield length is less than a byte */
8390 emitPtrByteGet (rname, ptype, FALSE);
8392 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8393 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8397 /* Bit field did not fit in a byte. Copy all
8398 but the partial byte at the end. */
8399 for (rlen=blen;rlen>=8;rlen-=8)
8401 emitPtrByteGet (rname, ptype, FALSE);
8402 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8404 emitcode ("inc", "%s", rname);
8407 /* Handle the partial byte at the end */
8410 emitPtrByteGet (rname, ptype, FALSE);
8411 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8412 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8420 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8425 /*-----------------------------------------------------------------*/
8426 /* genDataPointerGet - generates code when ptr offset is known */
8427 /*-----------------------------------------------------------------*/
8429 genDataPointerGet (operand * left,
8435 int size, offset = 0;
8437 D(emitcode ("; genDataPointerGet",""));
8439 aopOp (result, ic, TRUE);
8441 /* get the string representation of the name */
8442 l = aopGet (AOP (left), 0, FALSE, TRUE);
8443 size = AOP_SIZE (result);
8447 sprintf (buffer, "(%s + %d)", l + 1, offset);
8449 sprintf (buffer, "%s", l + 1);
8450 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8453 freeAsmop (left, NULL, ic, TRUE);
8454 freeAsmop (result, NULL, ic, TRUE);
8457 /*-----------------------------------------------------------------*/
8458 /* genNearPointerGet - emitcode for near pointer fetch */
8459 /*-----------------------------------------------------------------*/
8461 genNearPointerGet (operand * left,
8470 sym_link *rtype, *retype;
8471 sym_link *ltype = operandType (left);
8474 D(emitcode ("; genNearPointerGet",""));
8476 rtype = operandType (result);
8477 retype = getSpec (rtype);
8479 aopOp (left, ic, FALSE);
8481 /* if left is rematerialisable and
8482 result is not bitfield variable type and
8483 the left is pointer to data space i.e
8484 lower 128 bytes of space */
8485 if (AOP_TYPE (left) == AOP_IMMD &&
8486 !IS_BITFIELD (retype) &&
8487 DCL_TYPE (ltype) == POINTER)
8489 genDataPointerGet (left, result, ic);
8493 /* if the value is already in a pointer register
8494 then don't need anything more */
8495 if (!AOP_INPREG (AOP (left)))
8497 if (IS_AOP_PREG (left))
8499 // Aha, it is a pointer, just in disguise.
8500 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8503 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8504 __FILE__, __LINE__);
8509 emitcode ("mov", "a%s,%s", rname + 1, rname);
8510 rname++; // skip the '@'.
8515 /* otherwise get a free pointer register */
8517 preg = getFreePtr (ic, &aop, FALSE);
8518 emitcode ("mov", "%s,%s",
8520 aopGet (AOP (left), 0, FALSE, TRUE));
8525 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8527 //aopOp (result, ic, FALSE);
8528 aopOp (result, ic, result?TRUE:FALSE);
8530 /* if bitfield then unpack the bits */
8531 if (IS_BITFIELD (retype))
8532 genUnpackBits (result, rname, POINTER, ifx);
8535 /* we have can just get the values */
8536 int size = AOP_SIZE (result);
8541 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8544 emitcode ("mov", "a,@%s", rname);
8546 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8550 sprintf (buffer, "@%s", rname);
8551 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8555 emitcode ("inc", "%s", rname);
8559 /* now some housekeeping stuff */
8560 if (aop) /* we had to allocate for this iCode */
8562 if (pi) { /* post increment present */
8563 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8565 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8569 /* we did not allocate which means left
8570 already in a pointer register, then
8571 if size > 0 && this could be used again
8572 we have to point it back to where it
8574 if ((AOP_SIZE (result) > 1 &&
8575 !OP_SYMBOL (left)->remat &&
8576 (OP_SYMBOL (left)->liveTo > ic->seq ||
8580 int size = AOP_SIZE (result) - 1;
8582 emitcode ("dec", "%s", rname);
8586 if (ifx && !ifx->generated)
8588 genIfxJump (ifx, "a", left, NULL, result);
8592 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8593 freeAsmop (left, NULL, ic, TRUE);
8594 if (pi) pi->generated = 1;
8597 /*-----------------------------------------------------------------*/
8598 /* genPagedPointerGet - emitcode for paged pointer fetch */
8599 /*-----------------------------------------------------------------*/
8601 genPagedPointerGet (operand * left,
8610 sym_link *rtype, *retype;
8612 D(emitcode ("; genPagedPointerGet",""));
8614 rtype = operandType (result);
8615 retype = getSpec (rtype);
8617 aopOp (left, ic, FALSE);
8619 /* if the value is already in a pointer register
8620 then don't need anything more */
8621 if (!AOP_INPREG (AOP (left)))
8623 /* otherwise get a free pointer register */
8625 preg = getFreePtr (ic, &aop, FALSE);
8626 emitcode ("mov", "%s,%s",
8628 aopGet (AOP (left), 0, FALSE, TRUE));
8632 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8634 aopOp (result, ic, FALSE);
8636 /* if bitfield then unpack the bits */
8637 if (IS_BITFIELD (retype))
8638 genUnpackBits (result, rname, PPOINTER, ifx);
8641 /* we have can just get the values */
8642 int size = AOP_SIZE (result);
8648 emitcode ("movx", "a,@%s", rname);
8650 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8655 emitcode ("inc", "%s", rname);
8659 /* now some housekeeping stuff */
8660 if (aop) /* we had to allocate for this iCode */
8662 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8663 freeAsmop (NULL, aop, ic, TRUE);
8667 /* we did not allocate which means left
8668 already in a pointer register, then
8669 if size > 0 && this could be used again
8670 we have to point it back to where it
8672 if ((AOP_SIZE (result) > 1 &&
8673 !OP_SYMBOL (left)->remat &&
8674 (OP_SYMBOL (left)->liveTo > ic->seq ||
8678 int size = AOP_SIZE (result) - 1;
8680 emitcode ("dec", "%s", rname);
8684 if (ifx && !ifx->generated)
8686 genIfxJump (ifx, "a", left, NULL, result);
8690 freeAsmop (left, NULL, ic, TRUE);
8691 freeAsmop (result, NULL, ic, TRUE);
8692 if (pi) pi->generated = 1;
8696 /*--------------------------------------------------------------------*/
8697 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8698 /*--------------------------------------------------------------------*/
8700 loadDptrFromOperand (operand *op, bool loadBToo)
8702 if (AOP_TYPE (op) != AOP_STR)
8704 /* if this is rematerializable */
8705 if (AOP_TYPE (op) == AOP_IMMD)
8707 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8710 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8711 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8714 wassertl(FALSE, "need pointerCode");
8715 emitcode ("", "; mov b,???");
8716 /* genPointerGet and genPointerSet originally did different
8717 ** things for this case. Both seem wrong.
8718 ** from genPointerGet:
8719 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8720 ** from genPointerSet:
8721 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8726 else if (AOP_TYPE (op) == AOP_DPTR)
8730 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8731 emitcode ("push", "acc");
8732 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8733 emitcode ("push", "acc");
8734 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8735 emitcode ("pop", "dph");
8736 emitcode ("pop", "dpl");
8740 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8741 emitcode ("push", "acc");
8742 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8743 emitcode ("pop", "dpl");
8747 { /* we need to get it byte by byte */
8748 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8749 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8751 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8756 /*-----------------------------------------------------------------*/
8757 /* genFarPointerGet - gget value from far space */
8758 /*-----------------------------------------------------------------*/
8760 genFarPointerGet (operand * left,
8761 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8764 sym_link *retype = getSpec (operandType (result));
8766 D(emitcode ("; genFarPointerGet",""));
8768 aopOp (left, ic, FALSE);
8769 loadDptrFromOperand (left, FALSE);
8771 /* so dptr now contains the address */
8772 aopOp (result, ic, FALSE);
8774 /* if bit then unpack */
8775 if (IS_BITFIELD (retype))
8776 genUnpackBits (result, "dptr", FPOINTER, ifx);
8779 size = AOP_SIZE (result);
8784 emitcode ("movx", "a,@dptr");
8786 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8788 emitcode ("inc", "dptr");
8792 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8794 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8795 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8799 if (ifx && !ifx->generated)
8801 genIfxJump (ifx, "a", left, NULL, result);
8804 freeAsmop (left, NULL, ic, TRUE);
8805 freeAsmop (result, NULL, ic, TRUE);
8808 /*-----------------------------------------------------------------*/
8809 /* genCodePointerGet - gget value from code space */
8810 /*-----------------------------------------------------------------*/
8812 genCodePointerGet (operand * left,
8813 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8816 sym_link *retype = getSpec (operandType (result));
8818 D(emitcode ("; genCodePointerGet",""));
8820 aopOp (left, ic, FALSE);
8821 loadDptrFromOperand (left, FALSE);
8823 /* so dptr now contains the address */
8824 aopOp (result, ic, FALSE);
8826 /* if bit then unpack */
8827 if (IS_BITFIELD (retype))
8828 genUnpackBits (result, "dptr", CPOINTER, ifx);
8831 size = AOP_SIZE (result);
8838 emitcode ("clr", "a");
8839 emitcode ("movc", "a,@a+dptr");
8841 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8842 emitcode ("inc", "dptr");
8846 emitcode ("mov", "a,#0x%02x", offset);
8847 emitcode ("movc", "a,@a+dptr");
8849 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8854 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8856 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8857 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8861 if (ifx && !ifx->generated)
8863 genIfxJump (ifx, "a", left, NULL, result);
8866 freeAsmop (left, NULL, ic, TRUE);
8867 freeAsmop (result, NULL, ic, TRUE);
8870 /*-----------------------------------------------------------------*/
8871 /* genGenPointerGet - gget value from generic pointer space */
8872 /*-----------------------------------------------------------------*/
8874 genGenPointerGet (operand * left,
8875 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8878 sym_link *retype = getSpec (operandType (result));
8880 D(emitcode ("; genGenPointerGet",""));
8882 aopOp (left, ic, FALSE);
8883 loadDptrFromOperand (left, TRUE);
8885 /* so dptr know contains the address */
8886 aopOp (result, ic, FALSE);
8888 /* if bit then unpack */
8889 if (IS_BITFIELD (retype))
8890 genUnpackBits (result, "dptr", GPOINTER, ifx);
8893 size = AOP_SIZE (result);
8898 emitcode ("lcall", "__gptrget");
8900 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8902 emitcode ("inc", "dptr");
8906 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8908 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8909 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8913 if (ifx && !ifx->generated)
8915 genIfxJump (ifx, "a", left, NULL, result);
8919 freeAsmop (left, NULL, ic, TRUE);
8920 freeAsmop (result, NULL, ic, TRUE);
8923 /*-----------------------------------------------------------------*/
8924 /* genPointerGet - generate code for pointer get */
8925 /*-----------------------------------------------------------------*/
8927 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8929 operand *left, *result;
8930 sym_link *type, *etype;
8933 D(emitcode ("; genPointerGet",""));
8935 left = IC_LEFT (ic);
8936 result = IC_RESULT (ic);
8938 if (getSize (operandType (result))>1)
8941 /* depending on the type of pointer we need to
8942 move it to the correct pointer register */
8943 type = operandType (left);
8944 etype = getSpec (type);
8945 /* if left is of type of pointer then it is simple */
8946 if (IS_PTR (type) && !IS_FUNC (type->next))
8947 p_type = DCL_TYPE (type);
8950 /* we have to go by the storage class */
8951 p_type = PTR_TYPE (SPEC_OCLS (etype));
8954 /* special case when cast remat */
8955 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8956 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8957 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8958 type = operandType (left);
8959 p_type = DCL_TYPE (type);
8961 /* now that we have the pointer type we assign
8962 the pointer values */
8968 genNearPointerGet (left, result, ic, pi, ifx);
8972 genPagedPointerGet (left, result, ic, pi, ifx);
8976 genFarPointerGet (left, result, ic, pi, ifx);
8980 genCodePointerGet (left, result, ic, pi, ifx);
8984 genGenPointerGet (left, result, ic, pi, ifx);
8992 /*-----------------------------------------------------------------*/
8993 /* genPackBits - generates code for packed bit storage */
8994 /*-----------------------------------------------------------------*/
8996 genPackBits (sym_link * etype,
8998 char *rname, int p_type)
9000 int offset = 0; /* source byte offset */
9001 int rlen = 0; /* remaining bitfield length */
9002 int blen; /* bitfield length */
9003 int bstr; /* bitfield starting bit within byte */
9004 int litval; /* source literal value (if AOP_LIT) */
9005 unsigned char mask; /* bitmask within current byte */
9007 D(emitcode ("; genPackBits",""));
9009 blen = SPEC_BLEN (etype);
9010 bstr = SPEC_BSTR (etype);
9012 /* If the bitfield length is less than a byte */
9015 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9016 (unsigned char) (0xFF >> (8 - bstr)));
9018 if (AOP_TYPE (right) == AOP_LIT)
9020 /* Case with a bitfield length <8 and literal source
9022 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9024 litval &= (~mask) & 0xff;
9025 emitPtrByteGet (rname, p_type, FALSE);
9026 if ((mask|litval)!=0xff)
9027 emitcode ("anl","a,#0x%02x", mask);
9029 emitcode ("orl","a,#0x%02x", litval);
9033 if ((blen==1) && (p_type!=GPOINTER))
9035 /* Case with a bitfield length == 1 and no generic pointer
9037 if (AOP_TYPE (right) == AOP_CRY)
9038 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9041 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9042 emitcode ("rrc","a");
9044 emitPtrByteGet (rname, p_type, FALSE);
9045 emitcode ("mov","acc.%d,c",bstr);
9050 /* Case with a bitfield length < 8 and arbitrary source
9052 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9053 /* shift and mask source value */
9055 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9058 /* transfer A to B and get next byte */
9059 emitPtrByteGet (rname, p_type, TRUE);
9061 emitcode ("anl", "a,#0x%02x", mask);
9062 emitcode ("orl", "a,b");
9063 if (p_type == GPOINTER)
9064 emitcode ("pop", "b");
9070 emitPtrByteSet (rname, p_type, "a");
9074 /* Bit length is greater than 7 bits. In this case, copy */
9075 /* all except the partial byte at the end */
9076 for (rlen=blen;rlen>=8;rlen-=8)
9078 emitPtrByteSet (rname, p_type,
9079 aopGet (AOP (right), offset++, FALSE, TRUE) );
9081 emitcode ("inc", "%s", rname);
9084 /* If there was a partial byte at the end */
9087 mask = (((unsigned char) -1 << rlen) & 0xff);
9089 if (AOP_TYPE (right) == AOP_LIT)
9091 /* Case with partial byte and literal source
9093 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9094 litval >>= (blen-rlen);
9095 litval &= (~mask) & 0xff;
9096 emitPtrByteGet (rname, p_type, FALSE);
9097 if ((mask|litval)!=0xff)
9098 emitcode ("anl","a,#0x%02x", mask);
9100 emitcode ("orl","a,#0x%02x", litval);
9105 /* Case with partial byte and arbitrary source
9107 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9108 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9111 /* transfer A to B and get next byte */
9112 emitPtrByteGet (rname, p_type, TRUE);
9114 emitcode ("anl", "a,#0x%02x", mask);
9115 emitcode ("orl", "a,b");
9116 if (p_type == GPOINTER)
9117 emitcode ("pop", "b");
9121 emitPtrByteSet (rname, p_type, "a");
9127 /*-----------------------------------------------------------------*/
9128 /* genDataPointerSet - remat pointer to data space */
9129 /*-----------------------------------------------------------------*/
9131 genDataPointerSet (operand * right,
9135 int size, offset = 0;
9136 char *l, buffer[256];
9138 D(emitcode ("; genDataPointerSet",""));
9140 aopOp (right, ic, FALSE);
9142 l = aopGet (AOP (result), 0, FALSE, TRUE);
9143 size = AOP_SIZE (right);
9147 sprintf (buffer, "(%s + %d)", l + 1, offset);
9149 sprintf (buffer, "%s", l + 1);
9150 emitcode ("mov", "%s,%s", buffer,
9151 aopGet (AOP (right), offset++, FALSE, FALSE));
9154 freeAsmop (right, NULL, ic, TRUE);
9155 freeAsmop (result, NULL, ic, TRUE);
9158 /*-----------------------------------------------------------------*/
9159 /* genNearPointerSet - emitcode for near pointer put */
9160 /*-----------------------------------------------------------------*/
9162 genNearPointerSet (operand * right,
9170 sym_link *retype, *letype;
9171 sym_link *ptype = operandType (result);
9173 D(emitcode ("; genNearPointerSet",""));
9175 retype = getSpec (operandType (right));
9176 letype = getSpec (ptype);
9177 aopOp (result, ic, FALSE);
9179 /* if the result is rematerializable &
9180 in data space & not a bit variable */
9181 if (AOP_TYPE (result) == AOP_IMMD &&
9182 DCL_TYPE (ptype) == POINTER &&
9183 !IS_BITVAR (retype) &&
9184 !IS_BITVAR (letype))
9186 genDataPointerSet (right, result, ic);
9190 /* if the value is already in a pointer register
9191 then don't need anything more */
9192 if (!AOP_INPREG (AOP (result)))
9195 //AOP_TYPE (result) == AOP_STK
9199 // Aha, it is a pointer, just in disguise.
9200 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9203 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9204 __FILE__, __LINE__);
9209 emitcode ("mov", "a%s,%s", rname + 1, rname);
9210 rname++; // skip the '@'.
9215 /* otherwise get a free pointer register */
9217 preg = getFreePtr (ic, &aop, FALSE);
9218 emitcode ("mov", "%s,%s",
9220 aopGet (AOP (result), 0, FALSE, TRUE));
9226 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9229 aopOp (right, ic, FALSE);
9231 /* if bitfield then unpack the bits */
9232 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9233 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9236 /* we have can just get the values */
9237 int size = AOP_SIZE (right);
9242 l = aopGet (AOP (right), offset, FALSE, TRUE);
9246 emitcode ("mov", "@%s,a", rname);
9249 emitcode ("mov", "@%s,%s", rname, l);
9251 emitcode ("inc", "%s", rname);
9256 /* now some housekeeping stuff */
9257 if (aop) /* we had to allocate for this iCode */
9260 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9261 freeAsmop (NULL, aop, ic, TRUE);
9265 /* we did not allocate which means left
9266 already in a pointer register, then
9267 if size > 0 && this could be used again
9268 we have to point it back to where it
9270 if ((AOP_SIZE (right) > 1 &&
9271 !OP_SYMBOL (result)->remat &&
9272 (OP_SYMBOL (result)->liveTo > ic->seq ||
9276 int size = AOP_SIZE (right) - 1;
9278 emitcode ("dec", "%s", rname);
9283 if (pi) pi->generated = 1;
9284 freeAsmop (result, NULL, ic, TRUE);
9285 freeAsmop (right, NULL, ic, TRUE);
9288 /*-----------------------------------------------------------------*/
9289 /* genPagedPointerSet - emitcode for Paged pointer put */
9290 /*-----------------------------------------------------------------*/
9292 genPagedPointerSet (operand * right,
9300 sym_link *retype, *letype;
9302 D(emitcode ("; genPagedPointerSet",""));
9304 retype = getSpec (operandType (right));
9305 letype = getSpec (operandType (result));
9307 aopOp (result, ic, FALSE);
9309 /* if the value is already in a pointer register
9310 then don't need anything more */
9311 if (!AOP_INPREG (AOP (result)))
9313 /* otherwise get a free pointer register */
9315 preg = getFreePtr (ic, &aop, FALSE);
9316 emitcode ("mov", "%s,%s",
9318 aopGet (AOP (result), 0, FALSE, TRUE));
9322 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9324 aopOp (right, ic, FALSE);
9326 /* if bitfield then unpack the bits */
9327 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9328 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9331 /* we have can just get the values */
9332 int size = AOP_SIZE (right);
9337 l = aopGet (AOP (right), offset, FALSE, TRUE);
9340 emitcode ("movx", "@%s,a", rname);
9343 emitcode ("inc", "%s", rname);
9349 /* now some housekeeping stuff */
9350 if (aop) /* we had to allocate for this iCode */
9353 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9354 freeAsmop (NULL, aop, ic, TRUE);
9358 /* we did not allocate which means left
9359 already in a pointer register, then
9360 if size > 0 && this could be used again
9361 we have to point it back to where it
9363 if (AOP_SIZE (right) > 1 &&
9364 !OP_SYMBOL (result)->remat &&
9365 (OP_SYMBOL (result)->liveTo > ic->seq ||
9368 int size = AOP_SIZE (right) - 1;
9370 emitcode ("dec", "%s", rname);
9375 if (pi) pi->generated = 1;
9376 freeAsmop (result, NULL, ic, TRUE);
9377 freeAsmop (right, NULL, ic, TRUE);
9382 /*-----------------------------------------------------------------*/
9383 /* genFarPointerSet - set value from far space */
9384 /*-----------------------------------------------------------------*/
9386 genFarPointerSet (operand * right,
9387 operand * result, iCode * ic, iCode * pi)
9390 sym_link *retype = getSpec (operandType (right));
9391 sym_link *letype = getSpec (operandType (result));
9393 D(emitcode ("; genFarPointerSet",""));
9395 aopOp (result, ic, FALSE);
9396 loadDptrFromOperand (result, FALSE);
9398 /* so dptr know contains the address */
9399 aopOp (right, ic, FALSE);
9401 /* if bit then unpack */
9402 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9403 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9406 size = AOP_SIZE (right);
9411 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9413 emitcode ("movx", "@dptr,a");
9415 emitcode ("inc", "dptr");
9418 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9419 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9420 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9423 freeAsmop (result, NULL, ic, TRUE);
9424 freeAsmop (right, NULL, ic, TRUE);
9427 /*-----------------------------------------------------------------*/
9428 /* genGenPointerSet - set value from generic pointer space */
9429 /*-----------------------------------------------------------------*/
9431 genGenPointerSet (operand * right,
9432 operand * result, iCode * ic, iCode * pi)
9435 sym_link *retype = getSpec (operandType (right));
9436 sym_link *letype = getSpec (operandType (result));
9438 D(emitcode ("; genGenPointerSet",""));
9440 aopOp (result, ic, FALSE);
9441 loadDptrFromOperand (result, TRUE);
9443 /* so dptr know contains the address */
9444 aopOp (right, ic, FALSE);
9446 /* if bit then unpack */
9447 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9448 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9451 size = AOP_SIZE (right);
9456 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9458 emitcode ("lcall", "__gptrput");
9460 emitcode ("inc", "dptr");
9464 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9465 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9466 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9469 freeAsmop (result, NULL, ic, TRUE);
9470 freeAsmop (right, NULL, ic, TRUE);
9473 /*-----------------------------------------------------------------*/
9474 /* genPointerSet - stores the value into a pointer location */
9475 /*-----------------------------------------------------------------*/
9477 genPointerSet (iCode * ic, iCode *pi)
9479 operand *right, *result;
9480 sym_link *type, *etype;
9483 D(emitcode ("; genPointerSet",""));
9485 right = IC_RIGHT (ic);
9486 result = IC_RESULT (ic);
9488 /* depending on the type of pointer we need to
9489 move it to the correct pointer register */
9490 type = operandType (result);
9491 etype = getSpec (type);
9492 /* if left is of type of pointer then it is simple */
9493 if (IS_PTR (type) && !IS_FUNC (type->next))
9495 p_type = DCL_TYPE (type);
9499 /* we have to go by the storage class */
9500 p_type = PTR_TYPE (SPEC_OCLS (etype));
9503 /* special case when cast remat */
9504 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9505 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9506 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9507 type = operandType (result);
9508 p_type = DCL_TYPE (type);
9510 /* now that we have the pointer type we assign
9511 the pointer values */
9517 genNearPointerSet (right, result, ic, pi);
9521 genPagedPointerSet (right, result, ic, pi);
9525 genFarPointerSet (right, result, ic, pi);
9529 genGenPointerSet (right, result, ic, pi);
9533 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9534 "genPointerSet: illegal pointer type");
9539 /*-----------------------------------------------------------------*/
9540 /* genIfx - generate code for Ifx statement */
9541 /*-----------------------------------------------------------------*/
9543 genIfx (iCode * ic, iCode * popIc)
9545 operand *cond = IC_COND (ic);
9548 D(emitcode ("; genIfx",""));
9550 aopOp (cond, ic, FALSE);
9552 /* get the value into acc */
9553 if (AOP_TYPE (cond) != AOP_CRY)
9557 /* the result is now in the accumulator */
9558 freeAsmop (cond, NULL, ic, TRUE);
9560 /* if there was something to be popped then do it */
9564 /* if the condition is a bit variable */
9565 if (isbit && IS_ITEMP (cond) &&
9567 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9568 else if (isbit && !IS_ITEMP (cond))
9569 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9571 genIfxJump (ic, "a", NULL, NULL, NULL);
9576 /*-----------------------------------------------------------------*/
9577 /* genAddrOf - generates code for address of */
9578 /*-----------------------------------------------------------------*/
9580 genAddrOf (iCode * ic)
9582 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9585 D(emitcode ("; genAddrOf",""));
9587 aopOp (IC_RESULT (ic), ic, FALSE);
9589 /* if the operand is on the stack then we
9590 need to get the stack offset of this
9594 /* if it has an offset then we need to compute
9598 emitcode ("mov", "a,_bp");
9599 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9600 ((char) (sym->stack - _G.nRegsSaved)) :
9601 ((char) sym->stack)) & 0xff);
9602 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9606 /* we can just move _bp */
9607 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9609 /* fill the result with zero */
9610 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9615 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9621 /* object not on stack then we need the name */
9622 size = AOP_SIZE (IC_RESULT (ic));
9627 char s[SDCC_NAME_MAX];
9629 sprintf (s, "#(%s >> %d)",
9633 sprintf (s, "#%s", sym->rname);
9634 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9638 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9642 /*-----------------------------------------------------------------*/
9643 /* genFarFarAssign - assignment when both are in far space */
9644 /*-----------------------------------------------------------------*/
9646 genFarFarAssign (operand * result, operand * right, iCode * ic)
9648 int size = AOP_SIZE (right);
9652 D(emitcode ("; genFarFarAssign",""));
9654 /* first push the right side on to the stack */
9657 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9659 emitcode ("push", "acc");
9662 freeAsmop (right, NULL, ic, FALSE);
9663 /* now assign DPTR to result */
9664 aopOp (result, ic, FALSE);
9665 size = AOP_SIZE (result);
9668 emitcode ("pop", "acc");
9669 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9671 freeAsmop (result, NULL, ic, FALSE);
9675 /*-----------------------------------------------------------------*/
9676 /* genAssign - generate code for assignment */
9677 /*-----------------------------------------------------------------*/
9679 genAssign (iCode * ic)
9681 operand *result, *right;
9683 unsigned long lit = 0L;
9685 D(emitcode("; genAssign",""));
9687 result = IC_RESULT (ic);
9688 right = IC_RIGHT (ic);
9690 /* if they are the same */
9691 if (operandsEqu (result, right) &&
9692 !isOperandVolatile (result, FALSE) &&
9693 !isOperandVolatile (right, FALSE))
9696 aopOp (right, ic, FALSE);
9698 /* special case both in far space */
9699 if (AOP_TYPE (right) == AOP_DPTR &&
9700 IS_TRUE_SYMOP (result) &&
9701 isOperandInFarSpace (result))
9704 genFarFarAssign (result, right, ic);
9708 aopOp (result, ic, TRUE);
9710 /* if they are the same registers */
9711 if (sameRegs (AOP (right), AOP (result)) &&
9712 !isOperandVolatile (result, FALSE) &&
9713 !isOperandVolatile (right, FALSE))
9716 /* if the result is a bit */
9717 if (AOP_TYPE (result) == AOP_CRY)
9720 /* if the right size is a literal then
9721 we know what the value is */
9722 if (AOP_TYPE (right) == AOP_LIT)
9724 if (((int) operandLitValue (right)))
9725 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9727 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9731 /* the right is also a bit variable */
9732 if (AOP_TYPE (right) == AOP_CRY)
9734 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9735 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9741 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9745 /* bit variables done */
9747 size = AOP_SIZE (result);
9749 if (AOP_TYPE (right) == AOP_LIT)
9750 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9752 (AOP_TYPE (result) != AOP_REG) &&
9753 (AOP_TYPE (right) == AOP_LIT) &&
9754 !IS_FLOAT (operandType (right)) &&
9757 while ((size) && (lit))
9759 aopPut (AOP (result),
9760 aopGet (AOP (right), offset, FALSE, FALSE),
9762 isOperandVolatile (result, FALSE));
9767 emitcode ("clr", "a");
9770 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9778 aopPut (AOP (result),
9779 aopGet (AOP (right), offset, FALSE, FALSE),
9781 isOperandVolatile (result, FALSE));
9787 freeAsmop (right, NULL, ic, TRUE);
9788 freeAsmop (result, NULL, ic, TRUE);
9791 /*-----------------------------------------------------------------*/
9792 /* genJumpTab - genrates code for jump table */
9793 /*-----------------------------------------------------------------*/
9795 genJumpTab (iCode * ic)
9797 symbol *jtab,*jtablo,*jtabhi;
9801 D(emitcode ("; genJumpTab",""));
9803 count = elementsInSet( IC_JTLABELS (ic) );
9807 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9808 if the switch argument is in a register.
9809 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9810 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9811 How will multiply by three be updated ???*/
9812 aopOp (IC_JTCOND (ic), ic, FALSE);
9813 /* get the condition into accumulator */
9814 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9816 /* multiply by three */
9817 emitcode ("add", "a,acc");
9818 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9819 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9821 jtab = newiTempLabel (NULL);
9822 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9823 emitcode ("jmp", "@a+dptr");
9824 emitcode ("", "%05d$:", jtab->key + 100);
9825 /* now generate the jump labels */
9826 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9827 jtab = setNextItem (IC_JTLABELS (ic)))
9828 emitcode ("ljmp", "%05d$", jtab->key + 100);
9832 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9833 if the switch argument is in a register.
9834 For n>6 this algorithm may be more compact */
9835 jtablo = newiTempLabel (NULL);
9836 jtabhi = newiTempLabel (NULL);
9838 /* get the condition into accumulator.
9839 Using b as temporary storage, if register push/pop is needed */
9840 aopOp (IC_JTCOND (ic), ic, FALSE);
9841 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9842 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9843 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9845 // (MB) what if B is in use???
9846 wassertl(!BINUSE, "B was in use");
9847 emitcode ("mov", "b,%s", l);
9850 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9854 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9855 emitcode ("movc", "a,@a+pc");
9856 emitcode ("push", "acc");
9859 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9860 emitcode ("movc", "a,@a+pc");
9861 emitcode ("push", "acc");
9865 /* this scales up to n<=255, but needs two more bytes
9867 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9868 emitcode ("movc", "a,@a+dptr");
9869 emitcode ("push", "acc");
9872 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9873 emitcode ("movc", "a,@a+dptr");
9874 emitcode ("push", "acc");
9877 emitcode ("ret", "");
9879 /* now generate jump table, LSB */
9880 emitcode ("", "%05d$:", jtablo->key + 100);
9881 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9882 jtab = setNextItem (IC_JTLABELS (ic)))
9883 emitcode (".db", "%05d$", jtab->key + 100);
9885 /* now generate jump table, MSB */
9886 emitcode ("", "%05d$:", jtabhi->key + 100);
9887 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9888 jtab = setNextItem (IC_JTLABELS (ic)))
9889 emitcode (".db", "%05d$>>8", jtab->key + 100);
9893 /*-----------------------------------------------------------------*/
9894 /* genCast - gen code for casting */
9895 /*-----------------------------------------------------------------*/
9897 genCast (iCode * ic)
9899 operand *result = IC_RESULT (ic);
9900 sym_link *ctype = operandType (IC_LEFT (ic));
9901 sym_link *rtype = operandType (IC_RIGHT (ic));
9902 operand *right = IC_RIGHT (ic);
9905 D(emitcode("; genCast",""));
9907 /* if they are equivalent then do nothing */
9908 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9911 aopOp (right, ic, FALSE);
9912 aopOp (result, ic, FALSE);
9914 /* if the result is a bit (and not a bitfield) */
9915 // if (AOP_TYPE (result) == AOP_CRY)
9916 if (IS_BITVAR (OP_SYMBOL (result)->type)
9917 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9919 /* if the right size is a literal then
9920 we know what the value is */
9921 if (AOP_TYPE (right) == AOP_LIT)
9923 if (((int) operandLitValue (right)))
9924 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9926 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9931 /* the right is also a bit variable */
9932 if (AOP_TYPE (right) == AOP_CRY)
9934 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9935 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9941 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9946 /* if they are the same size : or less */
9947 if (AOP_SIZE (result) <= AOP_SIZE (right))
9950 /* if they are in the same place */
9951 if (sameRegs (AOP (right), AOP (result)))
9954 /* if they in different places then copy */
9955 size = AOP_SIZE (result);
9959 aopPut (AOP (result),
9960 aopGet (AOP (right), offset, FALSE, FALSE),
9962 isOperandVolatile (result, FALSE));
9969 /* if the result is of type pointer */
9974 sym_link *type = operandType (right);
9975 sym_link *etype = getSpec (type);
9977 /* pointer to generic pointer */
9978 if (IS_GENPTR (ctype))
9981 p_type = DCL_TYPE (type);
9984 if (SPEC_SCLS(etype)==S_REGISTER) {
9985 // let's assume it is a generic pointer
9988 /* we have to go by the storage class */
9989 p_type = PTR_TYPE (SPEC_OCLS (etype));
9993 /* the first two bytes are known */
9994 size = GPTRSIZE - 1;
9998 aopPut (AOP (result),
9999 aopGet (AOP (right), offset, FALSE, FALSE),
10001 isOperandVolatile (result, FALSE));
10004 /* the last byte depending on type */
10006 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10011 // pointerTypeToGPByte will have bitched.
10015 sprintf(gpValStr, "#0x%d", gpVal);
10016 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10021 /* just copy the pointers */
10022 size = AOP_SIZE (result);
10026 aopPut (AOP (result),
10027 aopGet (AOP (right), offset, FALSE, FALSE),
10029 isOperandVolatile (result, FALSE));
10035 /* so we now know that the size of destination is greater
10036 than the size of the source */
10037 /* we move to result for the size of source */
10038 size = AOP_SIZE (right);
10042 aopPut (AOP (result),
10043 aopGet (AOP (right), offset, FALSE, FALSE),
10045 isOperandVolatile (result, FALSE));
10049 /* now depending on the sign of the source && destination */
10050 size = AOP_SIZE (result) - AOP_SIZE (right);
10051 /* if unsigned or not an integral type */
10052 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10055 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10059 /* we need to extend the sign :{ */
10060 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10063 emitcode ("rlc", "a");
10064 emitcode ("subb", "a,acc");
10066 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10069 /* we are done hurray !!!! */
10072 freeAsmop (right, NULL, ic, TRUE);
10073 freeAsmop (result, NULL, ic, TRUE);
10077 /*-----------------------------------------------------------------*/
10078 /* genDjnz - generate decrement & jump if not zero instrucion */
10079 /*-----------------------------------------------------------------*/
10081 genDjnz (iCode * ic, iCode * ifx)
10083 symbol *lbl, *lbl1;
10087 D(emitcode ("; genDjnz",""));
10089 /* if the if condition has a false label
10090 then we cannot save */
10091 if (IC_FALSE (ifx))
10094 /* if the minus is not of the form
10096 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10097 !IS_OP_LITERAL (IC_RIGHT (ic)))
10100 if (operandLitValue (IC_RIGHT (ic)) != 1)
10103 /* if the size of this greater than one then no
10105 if (getSize (operandType (IC_RESULT (ic))) > 1)
10108 /* otherwise we can save BIG */
10109 lbl = newiTempLabel (NULL);
10110 lbl1 = newiTempLabel (NULL);
10112 aopOp (IC_RESULT (ic), ic, FALSE);
10114 if (AOP_NEEDSACC(IC_RESULT(ic)))
10116 /* If the result is accessed indirectly via
10117 * the accumulator, we must explicitly write
10118 * it back after the decrement.
10120 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10122 if (strcmp(rByte, "a"))
10124 /* Something is hopelessly wrong */
10125 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10126 __FILE__, __LINE__);
10127 /* We can just give up; the generated code will be inefficient,
10128 * but what the hey.
10130 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10133 emitcode ("dec", "%s", rByte);
10134 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10135 emitcode ("jnz", "%05d$", lbl->key + 100);
10137 else if (IS_AOP_PREG (IC_RESULT (ic)))
10139 emitcode ("dec", "%s",
10140 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10141 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10142 emitcode ("jnz", "%05d$", lbl->key + 100);
10146 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10149 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10150 emitcode ("", "%05d$:", lbl->key + 100);
10151 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10152 emitcode ("", "%05d$:", lbl1->key + 100);
10154 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10155 ifx->generated = 1;
10159 /*-----------------------------------------------------------------*/
10160 /* genReceive - generate code for a receive iCode */
10161 /*-----------------------------------------------------------------*/
10163 genReceive (iCode * ic)
10165 int size = getSize (operandType (IC_RESULT (ic)));
10167 D(emitcode ("; genReceive",""));
10169 if (ic->argreg == 1) { /* first parameter */
10170 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10171 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10172 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10175 int receivingA = 0;
10178 for (offset = 0; offset<size; offset++)
10179 if (!strcmp (fReturn[offset], "a"))
10184 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10186 for (offset = size-1; offset>0; offset--)
10187 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10188 emitcode("mov","a,%s", fReturn[0]);
10190 aopOp (IC_RESULT (ic), ic, FALSE);
10192 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10193 isOperandVolatile (IC_RESULT (ic), FALSE));
10194 for (offset = 1; offset<size; offset++)
10195 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10196 isOperandVolatile (IC_RESULT (ic), FALSE));
10202 if (getTempRegs(tempRegs, size, ic))
10204 for (offset = 0; offset<size; offset++)
10205 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10206 aopOp (IC_RESULT (ic), ic, FALSE);
10207 for (offset = 0; offset<size; offset++)
10208 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10209 isOperandVolatile (IC_RESULT (ic), FALSE));
10214 offset = fReturnSizeMCS51 - size;
10216 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10217 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10220 aopOp (IC_RESULT (ic), ic, FALSE);
10221 size = AOP_SIZE (IC_RESULT (ic));
10224 emitcode ("pop", "acc");
10225 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10230 aopOp (IC_RESULT (ic), ic, FALSE);
10232 assignResultValue (IC_RESULT (ic));
10234 } else { /* second receive onwards */
10236 aopOp (IC_RESULT (ic), ic, FALSE);
10237 rb1off = ic->argreg;
10239 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10244 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10247 /*-----------------------------------------------------------------*/
10248 /* genDummyRead - generate code for dummy read of volatiles */
10249 /*-----------------------------------------------------------------*/
10251 genDummyRead (iCode * ic)
10256 D(emitcode("; genDummyRead",""));
10258 op = IC_RIGHT (ic);
10259 if (op && IS_SYMOP (op))
10261 aopOp (op, ic, FALSE);
10263 /* if the result is a bit */
10264 if (AOP_TYPE (op) == AOP_CRY)
10265 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10268 /* bit variables done */
10270 size = AOP_SIZE (op);
10274 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10279 freeAsmop (op, NULL, ic, TRUE);
10283 if (op && IS_SYMOP (op))
10285 aopOp (op, ic, FALSE);
10287 /* if the result is a bit */
10288 if (AOP_TYPE (op) == AOP_CRY)
10289 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10292 /* bit variables done */
10294 size = AOP_SIZE (op);
10298 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10303 freeAsmop (op, NULL, ic, TRUE);
10307 /*-----------------------------------------------------------------*/
10308 /* genCritical - generate code for start of a critical sequence */
10309 /*-----------------------------------------------------------------*/
10311 genCritical (iCode *ic)
10313 symbol *tlbl = newiTempLabel (NULL);
10315 D(emitcode("; genCritical",""));
10317 if (IC_RESULT (ic))
10319 aopOp (IC_RESULT (ic), ic, TRUE);
10320 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10321 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10322 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10323 emitcode ("", "%05d$:", (tlbl->key + 100));
10324 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10328 emitcode ("setb", "c");
10329 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10330 emitcode ("clr", "c");
10331 emitcode ("", "%05d$:", (tlbl->key + 100));
10332 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10336 /*-----------------------------------------------------------------*/
10337 /* genEndCritical - generate code for end of a critical sequence */
10338 /*-----------------------------------------------------------------*/
10340 genEndCritical (iCode *ic)
10342 D(emitcode("; genEndCritical",""));
10346 aopOp (IC_RIGHT (ic), ic, FALSE);
10347 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10349 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10350 emitcode ("mov", "ea,c");
10354 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10355 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10356 emitcode ("rrc", "a");
10357 emitcode ("mov", "ea,c");
10359 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10363 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10364 emitcode ("mov", "ea,c");
10368 /*-----------------------------------------------------------------*/
10369 /* gen51Code - generate code for 8051 based controllers */
10370 /*-----------------------------------------------------------------*/
10372 gen51Code (iCode * lic)
10376 /* int cseq = 0; */
10378 _G.currentFunc = NULL;
10379 lineHead = lineCurr = NULL;
10381 /* print the allocation information */
10382 if (allocInfo && currFunc)
10383 printAllocInfo (currFunc, codeOutFile);
10384 /* if debug information required */
10385 if (options.debug && currFunc)
10387 debugFile->writeFunction (currFunc, lic);
10389 /* stack pointer name */
10390 if (options.useXstack)
10396 for (ic = lic; ic; ic = ic->next)
10398 _G.current_iCode = ic;
10400 if (ic->lineno && cln != ic->lineno)
10404 debugFile->writeCLine (ic);
10406 if (!options.noCcodeInAsm) {
10407 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10408 printCLine(ic->filename, ic->lineno));
10413 if (ic->seqPoint && ic->seqPoint != cseq)
10415 emitcode ("", "; sequence point %d", ic->seqPoint);
10416 cseq = ic->seqPoint;
10419 if (options.iCodeInAsm) {
10420 char regsInUse[80];
10423 for (i=0; i<8; i++) {
10424 sprintf (®sInUse[i],
10425 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10428 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10430 /* if the result is marked as
10431 spilt and rematerializable or code for
10432 this has already been generated then
10434 if (resultRemat (ic) || ic->generated)
10437 /* depending on the operation */
10457 /* IPOP happens only when trying to restore a
10458 spilt live range, if there is an ifx statement
10459 following this pop then the if statement might
10460 be using some of the registers being popped which
10461 would destory the contents of the register so
10462 we need to check for this condition and handle it */
10464 ic->next->op == IFX &&
10465 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10466 genIfx (ic->next, ic);
10484 genEndFunction (ic);
10504 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10521 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10525 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10532 /* note these two are xlated by algebraic equivalence
10533 during parsing SDCC.y */
10534 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10535 "got '>=' or '<=' shouldn't have come here");
10539 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10551 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10555 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10559 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10583 genRightShift (ic);
10586 case GET_VALUE_AT_ADDRESS:
10588 hasInc (IC_LEFT (ic), ic,
10589 getSize (operandType (IC_RESULT (ic)))),
10590 ifxForOp (IC_RESULT (ic), ic) );
10594 if (POINTER_SET (ic))
10595 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10621 addSet (&_G.sendSet, ic);
10624 case DUMMY_READ_VOLATILE:
10633 genEndCritical (ic);
10645 _G.current_iCode = NULL;
10647 /* now we are ready to call the
10648 peep hole optimizer */
10649 if (!options.nopeep)
10650 peepHole (&lineHead);
10652 /* now do the actual printing */
10653 printLine (lineHead, codeOutFile);