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;
83 static char *rb1regs[] = {
84 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
96 #define CLRC emitcode("clr","c")
97 #define SETC emitcode("setb","c")
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, const char *fmt,...)
121 char lb[INITIAL_INLINEASM];
129 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
140 //printf ("%s\n", lb);
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
148 lineCurr->ic = _G.current_iCode;
149 lineCurr->isComment = (*lbp==';');
153 /*-----------------------------------------------------------------*/
154 /* mcs51_emitDebuggerSymbol - associate the current code location */
155 /* with a debugger symbol */
156 /*-----------------------------------------------------------------*/
158 mcs51_emitDebuggerSymbol (char * debugSym)
161 emitcode ("", "%s ==.", debugSym);
165 /*-----------------------------------------------------------------*/
166 /* mova - moves specified value into accumulator */
167 /*-----------------------------------------------------------------*/
171 /* do some early peephole optimization */
172 if (!strcmp(x, "a") || !strcmp(x, "acc"))
175 emitcode("mov","a,%s", x);
178 /*-----------------------------------------------------------------*/
179 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
180 /*-----------------------------------------------------------------*/
182 getFreePtr (iCode * ic, asmop ** aopp, bool result)
184 bool r0iu = FALSE, r1iu = FALSE;
185 bool r0ou = FALSE, r1ou = FALSE;
187 /* the logic: if r0 & r1 used in the instruction
188 then we are in trouble otherwise */
190 /* first check if r0 & r1 are used by this
191 instruction, in which case we are in trouble */
192 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
193 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
198 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
199 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
201 /* if no usage of r0 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if no usage of r1 then return it */
213 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
214 (*aopp)->type = AOP_R1;
216 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
219 /* now we know they both have usage */
220 /* if r0 not used in this instruction */
223 /* push it if not already pushed */
226 emitcode ("mov", "b,%s",
227 mcs51_regWithIdx (R0_IDX)->dname);
230 else if (!_G.r0Pushed)
232 emitcode ("push", "%s",
233 mcs51_regWithIdx (R0_IDX)->dname);
237 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
238 (*aopp)->type = AOP_R0;
240 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
243 /* if r1 not used then */
247 /* push it if not already pushed */
250 emitcode ("mov", "b,%s",
251 mcs51_regWithIdx (R1_IDX)->dname);
254 else if (!_G.r1Pushed)
256 emitcode ("push", "%s",
257 mcs51_regWithIdx (R1_IDX)->dname);
261 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262 (*aopp)->type = AOP_R1;
263 return mcs51_regWithIdx (R1_IDX);
266 /* I said end of world, but not quite end of world yet */
268 /* we can push it on the stack */
269 (*aopp)->type = AOP_STK;
272 /* in the case that result AND left AND right needs a pointer reg
273 we can safely use the result's */
274 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
275 (*aopp)->type = AOP_R0;
276 return mcs51_regWithIdx (R0_IDX);
278 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
279 (*aopp)->type = AOP_R1;
280 return mcs51_regWithIdx (R1_IDX);
284 /* now this is REALLY the end of the world */
285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
286 "getFreePtr should never reach here");
291 /*-----------------------------------------------------------------*/
292 /* getTempRegs - initialize an array of pointers to GPR registers */
293 /* that are not in use. Returns 1 if the requested */
294 /* number of registers were available, 0 otherwise. */
295 /*-----------------------------------------------------------------*/
297 getTempRegs(regs **tempRegs, int size, iCode *ic)
304 ic = _G.current_iCode;
310 freeRegs = newBitVect(8);
311 bitVectSetBit (freeRegs, R2_IDX);
312 bitVectSetBit (freeRegs, R3_IDX);
313 bitVectSetBit (freeRegs, R4_IDX);
314 bitVectSetBit (freeRegs, R5_IDX);
315 bitVectSetBit (freeRegs, R6_IDX);
316 bitVectSetBit (freeRegs, R7_IDX);
318 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
320 bitVect * newfreeRegs;
321 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
322 freeBitVect(freeRegs);
323 freeRegs = newfreeRegs;
325 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
328 for (i=0; i<freeRegs->size; i++)
330 if (bitVectBitValue(freeRegs,i))
331 tempRegs[offset++] = mcs51_regWithIdx(i);
334 freeBitVect(freeRegs);
339 freeBitVect(freeRegs);
344 /*-----------------------------------------------------------------*/
345 /* newAsmop - creates a new asmOp */
346 /*-----------------------------------------------------------------*/
348 newAsmop (short type)
352 aop = Safe_calloc (1, sizeof (asmop));
357 /*-----------------------------------------------------------------*/
358 /* pointerCode - returns the code for a pointer type */
359 /*-----------------------------------------------------------------*/
361 pointerCode (sym_link * etype)
364 return PTR_TYPE (SPEC_OCLS (etype));
369 /*-----------------------------------------------------------------*/
370 /* leftRightUseAcc - returns size of accumulator use by operands */
371 /*-----------------------------------------------------------------*/
373 leftRightUseAcc(iCode *ic)
382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383 "null iCode pointer");
390 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
393 size = getSize (OP_SYMBOL (op)->type);
398 else if (ic->op == JUMPTABLE)
401 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
404 size = getSize (OP_SYMBOL (op)->type);
412 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
415 size = getSize (OP_SYMBOL (op)->type);
420 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
423 size = getSize (OP_SYMBOL (op)->type);
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
445 wassertl (ic != NULL, "Got a null iCode");
446 wassertl (sym != NULL, "Got a null symbol");
448 space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if (sym->onStack || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
470 if (_G.accInUse || leftRightUseAcc (ic))
471 emitcode ("push", "acc");
473 emitcode ("mov", "a,_bp");
474 emitcode ("add", "a,#0x%02x",
476 ((char) (sym->stack - _G.nRegsSaved)) :
477 ((char) sym->stack)) & 0xff);
478 emitcode ("mov", "%s,a",
479 aop->aopu.aop_ptr->name);
481 if (_G.accInUse || leftRightUseAcc (ic))
482 emitcode ("pop", "acc");
485 emitcode ("mov", "%s,#%s",
486 aop->aopu.aop_ptr->name,
488 aop->paged = space->paged;
491 aop->aopu.aop_stk = sym->stack;
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
507 //printTypeChainRaw(sym->type, NULL);
508 //printf("space = %s\n", space ? space->sname : "NULL");
509 sym->aop = aop = newAsmop (AOP_DIR);
510 aop->aopu.aop_dir = sym->rname;
511 aop->size = getSize (sym->type);
515 /* special case for a function */
516 if (IS_FUNC (sym->type))
518 sym->aop = aop = newAsmop (AOP_IMMD);
519 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
520 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
521 aop->size = FPTRSIZE;
525 /* only remaining is far space */
526 /* in which case DPTR gets the address */
527 sym->aop = aop = newAsmop (AOP_DPTR);
528 emitcode ("mov", "dptr,#%s", sym->rname);
529 aop->size = getSize (sym->type);
531 /* if it is in code space */
532 if (IN_CODESPACE (space))
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object */
540 /*-----------------------------------------------------------------*/
542 aopForRemat (symbol * sym)
544 iCode *ic = sym->rematiCode;
545 asmop *aop = newAsmop (AOP_IMMD);
552 val += (int) operandLitValue (IC_RIGHT (ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue (IC_RIGHT (ic));
555 else if (IS_CAST_ICODE(ic)) {
556 sym_link *from_type = operandType(IC_RIGHT(ic));
557 aop->aopu.aop_immd.from_cast_remat = 1;
558 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
559 ptr_type = DCL_TYPE(from_type);
560 if (ptr_type == IPOINTER) {
567 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
571 sprintf (buffer, "(%s %c 0x%04x)",
572 OP_SYMBOL (IC_LEFT (ic))->rname,
573 val >= 0 ? '+' : '-',
576 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
579 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
580 /* set immd2 field if required */
581 if (aop->aopu.aop_immd.from_cast_remat) {
582 sprintf(buffer,"#0x%02x",ptr_type);
583 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
584 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
590 /*-----------------------------------------------------------------*/
591 /* regsInCommon - two operands have some registers in common */
592 /*-----------------------------------------------------------------*/
594 regsInCommon (operand * op1, operand * op2)
599 /* if they have registers in common */
600 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
603 sym1 = OP_SYMBOL (op1);
604 sym2 = OP_SYMBOL (op2);
606 if (sym1->nRegs == 0 || sym2->nRegs == 0)
609 for (i = 0; i < sym1->nRegs; i++)
615 for (j = 0; j < sym2->nRegs; j++)
620 if (sym2->regs[j] == sym1->regs[i])
628 /*-----------------------------------------------------------------*/
629 /* operandsEqu - equivalent */
630 /*-----------------------------------------------------------------*/
632 operandsEqu (operand * op1, operand * op2)
636 /* if they not symbols */
637 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
640 sym1 = OP_SYMBOL (op1);
641 sym2 = OP_SYMBOL (op2);
643 /* if both are itemps & one is spilt
644 and the other is not then false */
645 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
646 sym1->isspilt != sym2->isspilt)
649 /* if they are the same */
653 if (sym1->rname[0] && sym2->rname[0]
654 && strcmp (sym1->rname, sym2->rname) == 0)
657 /* if left is a tmp & right is not */
658 if (IS_ITEMP (op1) &&
661 (sym1->usl.spillLoc == sym2))
664 if (IS_ITEMP (op2) &&
668 (sym2->usl.spillLoc == sym1))
674 /*-----------------------------------------------------------------*/
675 /* sameRegs - two asmops have the same registers */
676 /*-----------------------------------------------------------------*/
678 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type != AOP_REG ||
686 aop2->type != AOP_REG)
689 if (aop1->size != aop2->size)
692 for (i = 0; i < aop1->size; i++)
693 if (aop1->aopu.aop_reg[i] !=
694 aop2->aopu.aop_reg[i])
700 /*-----------------------------------------------------------------*/
701 /* aopOp - allocates an asmop for an operand : */
702 /*-----------------------------------------------------------------*/
704 aopOp (operand * op, iCode * ic, bool result)
713 /* if this a literal */
714 if (IS_OP_LITERAL (op))
716 op->aop = aop = newAsmop (AOP_LIT);
717 aop->aopu.aop_lit = op->operand.valOperand;
718 aop->size = getSize (operandType (op));
722 /* if already has a asmop then continue */
726 /* if the underlying symbol has a aop */
727 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
729 op->aop = OP_SYMBOL (op)->aop;
733 /* if this is a true symbol */
734 if (IS_TRUE_SYMOP (op))
736 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
740 /* this is a temporary : this has
746 e) can be a return use only */
748 sym = OP_SYMBOL (op);
750 /* if the type is a conditional */
751 if (sym->regType == REG_CND)
753 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
758 /* if it is spilt then two situations
760 b) has a spill location */
761 if (sym->isspilt || sym->nRegs == 0)
764 /* rematerialize it NOW */
767 sym->aop = op->aop = aop =
769 aop->size = getSize (sym->type);
776 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < 2; i++)
779 aop->aopu.aop_str[i] = accUse[i];
787 aop = op->aop = sym->aop = newAsmop (AOP_STR);
788 aop->size = getSize (sym->type);
789 for (i = 0; i < fReturnSizeMCS51; i++)
790 aop->aopu.aop_str[i] = fReturn[i];
794 if (sym->usl.spillLoc)
796 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
798 /* force a new aop if sizes differ */
799 sym->usl.spillLoc->aop = NULL;
801 sym->aop = op->aop = aop =
802 aopForSym (ic, sym->usl.spillLoc, result);
803 aop->size = getSize (sym->type);
807 /* else must be a dummy iTemp */
808 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
809 aop->size = getSize (sym->type);
813 /* must be in a register */
814 sym->aop = op->aop = aop = newAsmop (AOP_REG);
815 aop->size = sym->nRegs;
816 for (i = 0; i < sym->nRegs; i++)
817 aop->aopu.aop_reg[i] = sym->regs[i];
820 /*-----------------------------------------------------------------*/
821 /* freeAsmop - free up the asmop given to an operand */
822 /*----------------------------------------------------------------*/
824 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
841 /* depending on the asmop type only three cases need work AOP_RO
842 , AOP_R1 && AOP_STK */
848 emitcode ("mov", "r0,b");
851 else if (_G.r0Pushed)
855 emitcode ("pop", "ar0");
859 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 emitcode ("mov", "r1,b");
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size - 1;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
890 emitcode ("mov", "a,_bp");
891 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
892 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
901 emitcode ("pop", "acc");
902 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
908 freeAsmop (op, NULL, ic, TRUE);
911 emitcode ("pop", "ar1");
917 emitcode ("pop", "ar0");
924 /* all other cases just dealloc */
930 OP_SYMBOL (op)->aop = NULL;
931 /* if the symbol has a spill */
933 SPIL_LOC (op)->aop = NULL;
938 /*------------------------------------------------------------------*/
939 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
940 /* pop r0 or r1 off stack if pushed */
941 /*------------------------------------------------------------------*/
943 freeForBranchAsmop (operand * op)
963 emitcode ("mov", "r0,b");
965 else if (_G.r0Pushed)
967 emitcode ("pop", "ar0");
974 emitcode ("mov", "r1,b");
976 else if (_G.r1Pushed)
978 emitcode ("pop", "ar1");
985 int stk = aop->aopu.aop_stk + aop->size - 1;
987 emitcode ("mov", "b,r0");
990 emitcode ("mov", "a,_bp");
991 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
992 emitcode ("mov", "r0,a");
996 emitcode ("mov", "r0,_bp");
1001 emitcode ("pop", "acc");
1002 emitcode ("mov", "@r0,a");
1005 emitcode ("dec", "r0");
1007 emitcode ("mov", "r0,b");
1013 /*-----------------------------------------------------------------*/
1014 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1015 /* clobber the accumulator */
1016 /*-----------------------------------------------------------------*/
1018 aopGetUsesAcc (asmop *aop, int offset)
1020 if (offset > (aop->size - 1))
1038 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1047 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1053 /* Error case --- will have been caught already */
1059 /*-----------------------------------------------------------------*/
1060 /* aopGet - for fetching value of the aop */
1061 /*-----------------------------------------------------------------*/
1063 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1068 /* offset is greater than
1070 if (offset > (aop->size - 1) &&
1071 aop->type != AOP_LIT)
1074 /* depending on type */
1082 /* if we need to increment it */
1083 while (offset > aop->coff)
1085 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1089 while (offset < aop->coff)
1091 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1098 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1099 return (dname ? "acc" : "a");
1101 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1102 rs = Safe_calloc (1, strlen (s) + 1);
1107 if (aop->code && aop->coff==0 && offset>=1) {
1108 emitcode ("mov", "a,#0x%02x", offset);
1109 emitcode ("movc", "a,@a+dptr");
1110 return (dname ? "acc" : "a");
1113 while (offset > aop->coff)
1115 emitcode ("inc", "dptr");
1119 while (offset < aop->coff)
1121 emitcode ("lcall", "__decdptr");
1128 emitcode ("clr", "a");
1129 emitcode ("movc", "a,@a+dptr");
1133 emitcode ("movx", "a,@dptr");
1135 return (dname ? "acc" : "a");
1139 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1142 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1144 sprintf (s, "#(%s >> %d)",
1145 aop->aopu.aop_immd.aop_immd1,
1149 aop->aopu.aop_immd.aop_immd1);
1150 rs = Safe_calloc (1, strlen (s) + 1);
1156 sprintf (s, "(%s + %d)",
1160 sprintf (s, "%s", aop->aopu.aop_dir);
1161 rs = Safe_calloc (1, strlen (s) + 1);
1167 return aop->aopu.aop_reg[offset]->dname;
1169 return aop->aopu.aop_reg[offset]->name;
1172 emitcode ("clr", "a");
1173 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1174 emitcode ("rlc", "a");
1175 return (dname ? "acc" : "a");
1178 if (!offset && dname)
1180 return aop->aopu.aop_str[offset];
1183 return aopLiteral (aop->aopu.aop_lit, offset);
1187 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1191 return aop->aopu.aop_str[offset];
1195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1196 "aopget got unsupported aop->type");
1199 /*-----------------------------------------------------------------*/
1200 /* aopPut - puts a string for a aop */
1201 /*-----------------------------------------------------------------*/
1203 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1207 if (aop->size && offset > (aop->size - 1))
1209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1210 "aopPut got offset > aop->size");
1214 /* will assign value to value */
1215 /* depending on where it is ofcourse */
1219 MOVA (s); /* read s in case it was volatile */
1224 sprintf (d, "(%s + %d)",
1225 aop->aopu.aop_dir, offset);
1227 sprintf (d, "%s", aop->aopu.aop_dir);
1229 if (strcmp (d, s) ||
1231 emitcode ("mov", "%s,%s", d, s);
1236 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1237 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1240 strcmp (s, "r0") == 0 ||
1241 strcmp (s, "r1") == 0 ||
1242 strcmp (s, "r2") == 0 ||
1243 strcmp (s, "r3") == 0 ||
1244 strcmp (s, "r4") == 0 ||
1245 strcmp (s, "r5") == 0 ||
1246 strcmp (s, "r6") == 0 ||
1247 strcmp (s, "r7") == 0)
1248 emitcode ("mov", "%s,%s",
1249 aop->aopu.aop_reg[offset]->dname, s);
1251 emitcode ("mov", "%s,%s",
1252 aop->aopu.aop_reg[offset]->name, s);
1259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260 "aopPut writing to code space");
1264 while (offset > aop->coff)
1267 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1273 emitcode ("lcall", "__decdptr");
1278 /* if not in accumulater */
1281 emitcode ("movx", "@dptr,a");
1286 while (offset > aop->coff)
1289 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1291 while (offset < aop->coff)
1294 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1301 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1307 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1309 else if (strcmp (s, "r0") == 0 ||
1310 strcmp (s, "r1") == 0 ||
1311 strcmp (s, "r2") == 0 ||
1312 strcmp (s, "r3") == 0 ||
1313 strcmp (s, "r4") == 0 ||
1314 strcmp (s, "r5") == 0 ||
1315 strcmp (s, "r6") == 0 ||
1316 strcmp (s, "r7") == 0)
1319 sprintf (buffer, "a%s", s);
1320 emitcode ("mov", "@%s,%s",
1321 aop->aopu.aop_ptr->name, buffer);
1324 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1329 if (strcmp (s, "a") == 0)
1330 emitcode ("push", "acc");
1334 emitcode ("push", "acc");
1336 emitcode ("push", s);
1342 /* if bit variable */
1343 if (!aop->aopu.aop_dir)
1345 emitcode ("clr", "a");
1346 emitcode ("rlc", "a");
1351 emitcode ("clr", "%s", aop->aopu.aop_dir);
1353 emitcode ("setb", "%s", aop->aopu.aop_dir);
1354 else if (!strcmp (s, "c"))
1355 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1358 if (strcmp (s, "a"))
1363 /* set C, if a >= 1 */
1364 emitcode ("add", "a,#0xff");
1365 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1373 if (strcmp (aop->aopu.aop_str[offset], s) ||
1375 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1380 if (!offset && (strcmp (s, "acc") == 0) &&
1384 if (strcmp (aop->aopu.aop_str[offset], s) &&
1386 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1390 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1391 "aopPut got unsupported aop->type");
1399 /*-----------------------------------------------------------------*/
1400 /* pointToEnd :- points to the last byte of the operand */
1401 /*-----------------------------------------------------------------*/
1403 pointToEnd (asmop * aop)
1409 aop->coff = count = (aop->size - 1);
1415 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1419 emitcode ("inc", "dptr");
1426 /*-----------------------------------------------------------------*/
1427 /* reAdjustPreg - points a register back to where it should */
1428 /*-----------------------------------------------------------------*/
1430 reAdjustPreg (asmop * aop)
1432 if ((aop->coff==0) || aop->size <= 1)
1440 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1445 emitcode ("lcall", "__decdptr");
1452 #define AOP(op) op->aop
1453 #define AOP_TYPE(op) AOP(op)->type
1454 #define AOP_SIZE(op) AOP(op)->size
1455 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1456 AOP_TYPE(x) == AOP_R0))
1458 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1459 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1461 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1462 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1463 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1466 /*-----------------------------------------------------------------*/
1467 /* opIsGptr: returns non-zero if the passed operand is */
1468 /* a generic pointer type. */
1469 /*-----------------------------------------------------------------*/
1471 opIsGptr (operand * op)
1473 sym_link *type = operandType (op);
1475 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1482 /*-----------------------------------------------------------------*/
1483 /* getDataSize - get the operand data size */
1484 /*-----------------------------------------------------------------*/
1486 getDataSize (operand * op)
1489 size = AOP_SIZE (op);
1490 if (size == GPTRSIZE)
1492 sym_link *type = operandType (op);
1493 if (IS_GENPTR (type))
1495 /* generic pointer; arithmetic operations
1496 * should ignore the high byte (pointer type).
1504 /*-----------------------------------------------------------------*/
1505 /* outAcc - output Acc */
1506 /*-----------------------------------------------------------------*/
1508 outAcc (operand * result)
1511 size = getDataSize (result);
1514 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1517 /* unsigned or positive */
1520 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1525 /*-----------------------------------------------------------------*/
1526 /* outBitC - output a bit C */
1527 /*-----------------------------------------------------------------*/
1529 outBitC (operand * result)
1531 /* if the result is bit */
1532 if (AOP_TYPE (result) == AOP_CRY)
1533 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1536 emitcode ("clr", "a");
1537 emitcode ("rlc", "a");
1542 /*-----------------------------------------------------------------*/
1543 /* toBoolean - emit code for orl a,operator(sizeop) */
1544 /*-----------------------------------------------------------------*/
1546 toBoolean (operand * oper)
1548 int size = AOP_SIZE (oper) - 1;
1550 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1552 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1556 /*-----------------------------------------------------------------*/
1557 /* genNot - generate code for ! operation */
1558 /*-----------------------------------------------------------------*/
1564 D(emitcode ("; genNot",""));
1566 /* assign asmOps to operand & result */
1567 aopOp (IC_LEFT (ic), ic, FALSE);
1568 aopOp (IC_RESULT (ic), ic, TRUE);
1570 /* if in bit space then a special case */
1571 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1573 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1574 emitcode ("cpl", "c");
1575 outBitC (IC_RESULT (ic));
1579 toBoolean (IC_LEFT (ic));
1581 tlbl = newiTempLabel (NULL);
1582 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1583 emitcode ("", "%05d$:", tlbl->key + 100);
1584 outBitC (IC_RESULT (ic));
1587 /* release the aops */
1588 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1593 /*-----------------------------------------------------------------*/
1594 /* genCpl - generate code for complement */
1595 /*-----------------------------------------------------------------*/
1603 D(emitcode ("; genCpl",""));
1605 /* assign asmOps to operand & result */
1606 aopOp (IC_LEFT (ic), ic, FALSE);
1607 aopOp (IC_RESULT (ic), ic, TRUE);
1609 /* special case if in bit space */
1610 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1612 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1614 /* promotion rules are responsible for this strange result: */
1615 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1619 tlbl=newiTempLabel(NULL);
1620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1621 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1622 IS_AOP_PREG (IC_LEFT (ic)))
1624 emitcode ("cjne", "%s,#0x01,%05d$",
1625 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1630 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1632 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1634 emitcode ("", "%05d$:", tlbl->key + 100);
1635 outBitC (IC_RESULT(ic));
1639 size = AOP_SIZE (IC_RESULT (ic));
1642 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1644 emitcode ("cpl", "a");
1645 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1650 /* release the aops */
1651 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1652 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* genUminusFloat - unary minus for floating points */
1657 /*-----------------------------------------------------------------*/
1659 genUminusFloat (operand * op, operand * result)
1661 int size, offset = 0;
1664 D(emitcode ("; genUminusFloat",""));
1666 /* for this we just copy and then flip the bit */
1668 size = AOP_SIZE (op) - 1;
1672 aopPut (AOP (result),
1673 aopGet (AOP (op), offset, FALSE, FALSE),
1675 isOperandVolatile (result, FALSE));
1679 l = aopGet (AOP (op), offset, FALSE, FALSE);
1683 emitcode ("cpl", "acc.7");
1684 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1687 /*-----------------------------------------------------------------*/
1688 /* genUminus - unary minus code generation */
1689 /*-----------------------------------------------------------------*/
1691 genUminus (iCode * ic)
1694 sym_link *optype, *rtype;
1697 D(emitcode ("; genUminus",""));
1700 aopOp (IC_LEFT (ic), ic, FALSE);
1701 aopOp (IC_RESULT (ic), ic, TRUE);
1703 /* if both in bit space then special
1705 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1706 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1709 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1710 emitcode ("cpl", "c");
1711 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1715 optype = operandType (IC_LEFT (ic));
1716 rtype = operandType (IC_RESULT (ic));
1718 /* if float then do float stuff */
1719 if (IS_FLOAT (optype))
1721 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1725 /* otherwise subtract from zero */
1726 size = AOP_SIZE (IC_LEFT (ic));
1731 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1732 if (!strcmp (l, "a"))
1736 emitcode ("cpl", "a");
1737 emitcode ("addc", "a,#0");
1743 emitcode ("clr", "a");
1744 emitcode ("subb", "a,%s", l);
1746 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1749 /* if any remaining bytes in the result */
1750 /* we just need to propagate the sign */
1751 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1753 emitcode ("rlc", "a");
1754 emitcode ("subb", "a,acc");
1756 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1760 /* release the aops */
1761 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1762 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1765 /*-----------------------------------------------------------------*/
1766 /* saveRegisters - will look for a call and save the registers */
1767 /*-----------------------------------------------------------------*/
1769 saveRegisters (iCode * lic)
1776 for (ic = lic; ic; ic = ic->next)
1777 if (ic->op == CALL || ic->op == PCALL)
1782 fprintf (stderr, "found parameter push with no function call\n");
1786 /* if the registers have been saved already or don't need to be then
1790 if (IS_SYMOP(IC_LEFT(ic)) &&
1791 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1792 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1795 /* safe the registers in use at this time but skip the
1796 ones for the result */
1797 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1798 mcs51_rUmaskForOp (IC_RESULT(ic)));
1801 if (options.useXstack)
1803 if (bitVectBitValue (rsave, R0_IDX))
1804 emitcode ("mov", "b,r0");
1805 emitcode ("mov", "r0,%s", spname);
1806 for (i = 0; i < mcs51_nRegs; i++)
1808 if (bitVectBitValue (rsave, i))
1811 emitcode ("mov", "a,b");
1813 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1814 emitcode ("movx", "@r0,a");
1815 emitcode ("inc", "r0");
1818 emitcode ("mov", "%s,r0", spname);
1819 if (bitVectBitValue (rsave, R0_IDX))
1820 emitcode ("mov", "r0,b");
1823 for (i = 0; i < mcs51_nRegs; i++)
1825 if (bitVectBitValue (rsave, i))
1826 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1830 /*-----------------------------------------------------------------*/
1831 /* unsaveRegisters - pop the pushed registers */
1832 /*-----------------------------------------------------------------*/
1834 unsaveRegisters (iCode * ic)
1839 /* restore the registers in use at this time but skip the
1840 ones for the result */
1841 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1842 mcs51_rUmaskForOp (IC_RESULT(ic)));
1844 if (options.useXstack)
1846 emitcode ("mov", "r0,%s", spname);
1847 for (i = mcs51_nRegs; i >= 0; i--)
1849 if (bitVectBitValue (rsave, i))
1851 emitcode ("dec", "r0");
1852 emitcode ("movx", "a,@r0");
1854 emitcode ("mov", "b,a");
1856 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1860 emitcode ("mov", "%s,r0", spname);
1861 if (bitVectBitValue (rsave, R0_IDX))
1862 emitcode ("mov", "r0,b");
1865 for (i = mcs51_nRegs; i >= 0; i--)
1867 if (bitVectBitValue (rsave, i))
1868 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1874 /*-----------------------------------------------------------------*/
1876 /*-----------------------------------------------------------------*/
1878 pushSide (operand * oper, int size)
1883 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1884 if (AOP_TYPE (oper) != AOP_REG &&
1885 AOP_TYPE (oper) != AOP_DIR &&
1889 emitcode ("push", "acc");
1892 emitcode ("push", "%s", l);
1896 /*-----------------------------------------------------------------*/
1897 /* assignResultValue - */
1898 /*-----------------------------------------------------------------*/
1900 assignResultValue (operand * oper)
1903 int size = AOP_SIZE (oper);
1906 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1912 /*-----------------------------------------------------------------*/
1913 /* genXpush - pushes onto the external stack */
1914 /*-----------------------------------------------------------------*/
1916 genXpush (iCode * ic)
1918 asmop *aop = newAsmop (0);
1920 int size, offset = 0;
1922 D(emitcode ("; genXpush",""));
1924 aopOp (IC_LEFT (ic), ic, FALSE);
1925 r = getFreePtr (ic, &aop, FALSE);
1928 emitcode ("mov", "%s,_spx", r->name);
1930 size = AOP_SIZE (IC_LEFT (ic));
1934 char *l = aopGet (AOP (IC_LEFT (ic)),
1935 offset++, FALSE, FALSE);
1937 emitcode ("movx", "@%s,a", r->name);
1938 emitcode ("inc", "%s", r->name);
1943 emitcode ("mov", "_spx,%s", r->name);
1945 freeAsmop (NULL, aop, ic, TRUE);
1946 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1949 /*-----------------------------------------------------------------*/
1950 /* genIpush - genrate code for pushing this gets a little complex */
1951 /*-----------------------------------------------------------------*/
1953 genIpush (iCode * ic)
1955 int size, offset = 0;
1958 D(emitcode ("; genIpush",""));
1960 /* if this is not a parm push : ie. it is spill push
1961 and spill push is always done on the local stack */
1965 /* and the item is spilt then do nothing */
1966 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1969 aopOp (IC_LEFT (ic), ic, FALSE);
1970 size = AOP_SIZE (IC_LEFT (ic));
1971 /* push it on the stack */
1974 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1980 emitcode ("push", "%s", l);
1985 /* this is a paramter push: in this case we call
1986 the routine to find the call and save those
1987 registers that need to be saved */
1990 /* if use external stack then call the external
1991 stack pushing routine */
1992 if (options.useXstack)
1998 /* then do the push */
1999 aopOp (IC_LEFT (ic), ic, FALSE);
2002 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2003 size = AOP_SIZE (IC_LEFT (ic));
2007 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2008 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2009 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2013 emitcode ("push", "acc");
2016 emitcode ("push", "%s", l);
2019 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2022 /*-----------------------------------------------------------------*/
2023 /* genIpop - recover the registers: can happen only for spilling */
2024 /*-----------------------------------------------------------------*/
2026 genIpop (iCode * ic)
2030 D(emitcode ("; genIpop",""));
2032 /* if the temp was not pushed then */
2033 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2037 size = AOP_SIZE (IC_LEFT (ic));
2038 offset = (size - 1);
2040 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2043 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2046 /*-----------------------------------------------------------------*/
2047 /* unsaveRBank - restores the resgister bank from stack */
2048 /*-----------------------------------------------------------------*/
2050 unsaveRBank (int bank, iCode * ic, bool popPsw)
2056 if (options.useXstack)
2060 /* Assume r0 is available for use. */
2061 r = mcs51_regWithIdx (R0_IDX);;
2066 r = getFreePtr (ic, &aop, FALSE);
2068 emitcode ("mov", "%s,_spx", r->name);
2073 if (options.useXstack)
2075 emitcode ("movx", "a,@%s", r->name);
2076 emitcode ("mov", "psw,a");
2077 emitcode ("dec", "%s", r->name);
2081 emitcode ("pop", "psw");
2085 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2087 if (options.useXstack)
2089 emitcode ("movx", "a,@%s", r->name);
2090 emitcode ("mov", "(%s+%d),a",
2091 regs8051[i].base, 8 * bank + regs8051[i].offset);
2092 emitcode ("dec", "%s", r->name);
2096 emitcode ("pop", "(%s+%d)",
2097 regs8051[i].base, 8 * bank + regs8051[i].offset);
2100 if (options.useXstack)
2102 emitcode ("mov", "_spx,%s", r->name);
2107 freeAsmop (NULL, aop, ic, TRUE);
2111 /*-----------------------------------------------------------------*/
2112 /* saveRBank - saves an entire register bank on the stack */
2113 /*-----------------------------------------------------------------*/
2115 saveRBank (int bank, iCode * ic, bool pushPsw)
2121 if (options.useXstack)
2125 /* Assume r0 is available for use. */
2126 r = mcs51_regWithIdx (R0_IDX);;
2131 r = getFreePtr (ic, &aop, FALSE);
2133 emitcode ("mov", "%s,_spx", r->name);
2136 for (i = 0; i < mcs51_nRegs; i++)
2138 if (options.useXstack)
2140 emitcode ("inc", "%s", r->name);
2141 emitcode ("mov", "a,(%s+%d)",
2142 regs8051[i].base, 8 * bank + regs8051[i].offset);
2143 emitcode ("movx", "@%s,a", r->name);
2146 emitcode ("push", "(%s+%d)",
2147 regs8051[i].base, 8 * bank + regs8051[i].offset);
2152 if (options.useXstack)
2154 emitcode ("mov", "a,psw");
2155 emitcode ("movx", "@%s,a", r->name);
2156 emitcode ("inc", "%s", r->name);
2157 emitcode ("mov", "_spx,%s", r->name);
2162 emitcode ("push", "psw");
2165 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2170 freeAsmop (NULL, aop, ic, TRUE);
2179 /*-----------------------------------------------------------------*/
2180 /* genSend - gen code for SEND */
2181 /*-----------------------------------------------------------------*/
2182 static void genSend(set *sendSet)
2187 for (sic = setFirstItem (_G.sendSet); sic;
2188 sic = setNextItem (_G.sendSet)) {
2189 int size, offset = 0;
2190 aopOp (IC_LEFT (sic), sic, FALSE);
2191 size = AOP_SIZE (IC_LEFT (sic));
2193 if (sic->argreg == 1) {
2195 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2197 if (strcmp (l, fReturn[offset]))
2198 emitcode ("mov", "%s,%s", fReturn[offset], l);
2204 emitcode ("mov","b1_%d,%s",rb1_count++,
2205 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2208 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2212 /*-----------------------------------------------------------------*/
2213 /* genCall - generates a call statement */
2214 /*-----------------------------------------------------------------*/
2216 genCall (iCode * ic)
2219 // bool restoreBank = FALSE;
2220 bool swapBanks = FALSE;
2222 D(emitcode("; genCall",""));
2224 dtype = operandType (IC_LEFT (ic));
2225 /* if send set is not empty the assign */
2228 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2229 genSend(reverseSet(_G.sendSet));
2231 genSend(_G.sendSet);
2237 /* if we are calling a not _naked function that is not using
2238 the same register bank then we need to save the
2239 destination registers on the stack */
2240 dtype = operandType (IC_LEFT (ic));
2241 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2242 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2243 !IFFUNC_ISISR (dtype))
2248 /* if caller saves & we have not saved then */
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2259 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2260 OP_SYMBOL (IC_LEFT (ic))->rname :
2261 OP_SYMBOL (IC_LEFT (ic))->name));
2265 emitcode ("mov", "psw,#0x%02x",
2266 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2269 /* if we need assign a result value */
2270 if ((IS_ITEMP (IC_RESULT (ic)) &&
2271 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2272 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2273 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2274 IS_TRUE_SYMOP (IC_RESULT (ic)))
2278 aopOp (IC_RESULT (ic), ic, FALSE);
2281 assignResultValue (IC_RESULT (ic));
2283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2286 /* adjust the stack for parameters if
2291 if (ic->parmBytes > 3)
2293 emitcode ("mov", "a,%s", spname);
2294 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2295 emitcode ("mov", "%s,a", spname);
2298 for (i = 0; i < ic->parmBytes; i++)
2299 emitcode ("dec", "%s", spname);
2302 /* if we hade saved some registers then unsave them */
2303 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2304 unsaveRegisters (ic);
2306 // /* if register bank was saved then pop them */
2308 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2311 /*-----------------------------------------------------------------*/
2312 /* -10l - generates a call by pointer statement */
2313 /*-----------------------------------------------------------------*/
2315 genPcall (iCode * ic)
2318 symbol *rlbl = newiTempLabel (NULL);
2319 // bool restoreBank=FALSE;
2320 bool swapBanks = FALSE;
2322 D(emitcode("; genPCall",""));
2324 /* if caller saves & we have not saved then */
2328 /* if we are calling a not _naked function that is not using
2329 the same register bank then we need to save the
2330 destination registers on the stack */
2331 dtype = operandType (IC_LEFT (ic))->next;
2332 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2333 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2334 !IFFUNC_ISISR (dtype))
2336 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2337 // restoreBank=TRUE;
2339 // need caution message to user here
2342 /* push the return address on to the stack */
2343 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2344 emitcode ("push", "acc");
2345 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2346 emitcode ("push", "acc");
2348 /* now push the calling address */
2349 aopOp (IC_LEFT (ic), ic, FALSE);
2351 pushSide (IC_LEFT (ic), FPTRSIZE);
2353 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2355 /* if send set is not empty the assign */
2358 genSend(reverseSet(_G.sendSet));
2364 emitcode ("mov", "psw,#0x%02x",
2365 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2369 emitcode ("ret", "");
2370 emitcode ("", "%05d$:", (rlbl->key + 100));
2375 emitcode ("mov", "psw,#0x%02x",
2376 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2379 /* if we need assign a result value */
2380 if ((IS_ITEMP (IC_RESULT (ic)) &&
2381 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2382 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2383 IS_TRUE_SYMOP (IC_RESULT (ic)))
2387 aopOp (IC_RESULT (ic), ic, FALSE);
2390 assignResultValue (IC_RESULT (ic));
2392 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2395 /* adjust the stack for parameters if
2400 if (ic->parmBytes > 3)
2402 emitcode ("mov", "a,%s", spname);
2403 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2404 emitcode ("mov", "%s,a", spname);
2407 for (i = 0; i < ic->parmBytes; i++)
2408 emitcode ("dec", "%s", spname);
2412 // /* if register bank was saved then unsave them */
2414 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2416 /* if we hade saved some registers then
2418 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2419 unsaveRegisters (ic);
2422 /*-----------------------------------------------------------------*/
2423 /* resultRemat - result is rematerializable */
2424 /*-----------------------------------------------------------------*/
2426 resultRemat (iCode * ic)
2428 if (SKIP_IC (ic) || ic->op == IFX)
2431 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2433 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2434 if (sym->remat && !POINTER_SET (ic))
2441 #if defined(__BORLANDC__) || defined(_MSC_VER)
2442 #define STRCASECMP stricmp
2444 #define STRCASECMP strcasecmp
2447 /*-----------------------------------------------------------------*/
2448 /* inExcludeList - return 1 if the string is in exclude Reg list */
2449 /*-----------------------------------------------------------------*/
2451 regsCmp(void *p1, void *p2)
2453 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2457 inExcludeList (char *s)
2459 const char *p = setFirstItem(options.excludeRegsSet);
2461 if (p == NULL || STRCASECMP(p, "none") == 0)
2465 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2468 /*-----------------------------------------------------------------*/
2469 /* genFunction - generated code for function entry */
2470 /*-----------------------------------------------------------------*/
2472 genFunction (iCode * ic)
2474 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2476 bool switchedPSW = FALSE;
2477 int calleesaves_saved_register = -1;
2478 int stackAdjust = sym->stack;
2479 int accIsFree = sym->recvSize < 4;
2480 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2483 /* create the function header */
2484 emitcode (";", "-----------------------------------------");
2485 emitcode (";", " function %s", sym->name);
2486 emitcode (";", "-----------------------------------------");
2488 emitcode ("", "%s:", sym->rname);
2489 ftype = operandType (IC_LEFT (ic));
2490 _G.currentFunc = sym;
2492 if (IFFUNC_ISNAKED(ftype))
2494 emitcode(";", "naked function: no prologue.");
2498 /* here we need to generate the equates for the
2499 register bank if required */
2500 if (FUNC_REGBANK (ftype) != rbank)
2504 rbank = FUNC_REGBANK (ftype);
2505 for (i = 0; i < mcs51_nRegs; i++)
2507 if (strcmp (regs8051[i].base, "0") == 0)
2508 emitcode ("", "%s = 0x%02x",
2510 8 * rbank + regs8051[i].offset);
2512 emitcode ("", "%s = %s + 0x%02x",
2515 8 * rbank + regs8051[i].offset);
2519 /* if this is an interrupt service routine then
2520 save acc, b, dpl, dph */
2521 if (IFFUNC_ISISR (sym->type))
2524 if (!inExcludeList ("acc"))
2525 emitcode ("push", "acc");
2526 if (!inExcludeList ("b"))
2527 emitcode ("push", "b");
2528 if (!inExcludeList ("dpl"))
2529 emitcode ("push", "dpl");
2530 if (!inExcludeList ("dph"))
2531 emitcode ("push", "dph");
2532 /* if this isr has no bank i.e. is going to
2533 run with bank 0 , then we need to save more
2535 if (!FUNC_REGBANK (sym->type))
2538 /* if this function does not call any other
2539 function then we can be economical and
2540 save only those registers that are used */
2541 if (!IFFUNC_HASFCALL(sym->type))
2545 /* if any registers used */
2548 /* save the registers used */
2549 for (i = 0; i < sym->regsUsed->size; i++)
2551 if (bitVectBitValue (sym->regsUsed, i))
2552 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2559 /* this function has a function call. We cannot
2560 determines register usage so we will have to push the
2562 saveRBank (0, ic, FALSE);
2563 if (options.parms_in_bank1) {
2565 for (i=0; i < 8 ; i++ ) {
2566 emitcode ("push","%s",rb1regs[i]);
2573 /* This ISR uses a non-zero bank.
2575 * We assume that the bank is available for our
2578 * However, if this ISR calls a function which uses some
2579 * other bank, we must save that bank entirely.
2581 unsigned long banksToSave = 0;
2583 if (IFFUNC_HASFCALL(sym->type))
2586 #define MAX_REGISTER_BANKS 4
2591 for (i = ic; i; i = i->next)
2593 if (i->op == ENDFUNCTION)
2595 /* we got to the end OK. */
2603 dtype = operandType (IC_LEFT(i));
2605 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2607 /* Mark this bank for saving. */
2608 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2610 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2614 banksToSave |= (1 << FUNC_REGBANK(dtype));
2617 /* And note that we don't need to do it in
2625 /* This is a mess; we have no idea what
2626 * register bank the called function might
2629 * The only thing I can think of to do is
2630 * throw a warning and hope.
2632 werror(W_FUNCPTR_IN_USING_ISR);
2636 if (banksToSave && options.useXstack)
2638 /* Since we aren't passing it an ic,
2639 * saveRBank will assume r0 is available to abuse.
2641 * So switch to our (trashable) bank now, so
2642 * the caller's R0 isn't trashed.
2644 emitcode ("push", "psw");
2645 emitcode ("mov", "psw,#0x%02x",
2646 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2650 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2652 if (banksToSave & (1 << ix))
2654 saveRBank(ix, NULL, FALSE);
2658 // TODO: this needs a closer look
2659 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2662 /* Set the register bank to the desired value if nothing else */
2663 /* has done so yet. */
2666 emitcode ("push", "psw");
2667 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2672 /* This is a non-ISR function. The caller has already switched register */
2673 /* banks, if necessary, so just handle the callee-saves option. */
2675 /* if callee-save to be used for this function
2676 then save the registers being used in this function */
2677 if (IFFUNC_CALLEESAVES(sym->type))
2681 /* if any registers used */
2684 /* save the registers used */
2685 for (i = 0; i < sym->regsUsed->size; i++)
2687 if (bitVectBitValue (sym->regsUsed, i))
2689 /* remember one saved register for later usage */
2690 if (calleesaves_saved_register < 0)
2691 calleesaves_saved_register = i;
2692 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2701 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2704 if (options.useXstack)
2707 emitcode ("push", "acc");
2708 emitcode ("mov", "r0,%s", spname);
2709 emitcode ("mov", "a,_bp");
2710 emitcode ("movx", "@r0,a");
2711 emitcode ("inc", "%s", spname);
2713 emitcode ("pop", "acc");
2717 /* set up the stack */
2718 emitcode ("push", "_bp"); /* save the callers stack */
2720 emitcode ("mov", "_bp,%s", spname);
2723 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2724 /* before setting up the stack frame completely. */
2725 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2727 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2731 if (rsym && rsym->regType == REG_CND)
2733 if (rsym && (rsym->accuse || rsym->ruonly))
2735 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2736 rsym = rsym->usl.spillLoc;
2739 /* If the RECEIVE operand immediately spills to the first entry on the */
2740 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2741 /* rather than the usual @r0/r1 machinations. */
2742 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2746 _G.current_iCode = ric;
2747 D(emitcode ("; genReceive",""));
2748 for (ofs=0; ofs < sym->recvSize; ofs++)
2750 if (!strcmp (fReturn[ofs], "a"))
2751 emitcode ("push", "acc");
2753 emitcode ("push", fReturn[ofs]);
2755 stackAdjust -= sym->recvSize;
2758 assert (stackAdjust>=0);
2761 _G.current_iCode = ic;
2765 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2766 /* to free up the accumulator. */
2767 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2771 _G.current_iCode = ric;
2772 D(emitcode ("; genReceive",""));
2773 for (ofs=0; ofs < sym->recvSize; ofs++)
2775 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2777 _G.current_iCode = ic;
2783 /* adjust the stack for the function */
2787 int i = stackAdjust;
2789 werror (W_STACK_OVERFLOW, sym->name);
2791 if (i > 3 && accIsFree)
2794 emitcode ("mov", "a,sp");
2795 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796 emitcode ("mov", "sp,a");
2801 /* The accumulator is not free, so we will need another register */
2802 /* to clobber. No need to worry about a possible conflict with */
2803 /* the above early RECEIVE optimizations since they would have */
2804 /* freed the accumulator if they were generated. */
2806 if (IFFUNC_CALLEESAVES(sym->type))
2808 /* if it's a callee-saves function we need a saved register */
2809 if (calleesaves_saved_register >= 0)
2811 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2812 emitcode ("mov", "a,sp");
2813 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2814 emitcode ("mov", "sp,a");
2815 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2818 /* do it the hard way */
2820 emitcode ("inc", "sp");
2824 /* not callee-saves, we can clobber r0 */
2825 emitcode ("mov", "r0,a");
2826 emitcode ("mov", "a,sp");
2827 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2828 emitcode ("mov", "sp,a");
2829 emitcode ("mov", "a,r0");
2834 emitcode ("inc", "sp");
2841 emitcode ("push", "acc");
2842 emitcode ("mov", "a,_spx");
2843 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2844 emitcode ("mov", "_spx,a");
2846 emitcode ("pop", "acc");
2849 /* if critical function then turn interrupts off */
2850 if (IFFUNC_ISCRITICAL (ftype))
2852 symbol *tlbl = newiTempLabel (NULL);
2853 emitcode ("setb", "c");
2854 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2855 emitcode ("clr", "c");
2856 emitcode ("", "%05d$:", (tlbl->key + 100));
2857 emitcode ("push", "psw"); /* save old ea via c in psw */
2861 /*-----------------------------------------------------------------*/
2862 /* genEndFunction - generates epilogue for functions */
2863 /*-----------------------------------------------------------------*/
2865 genEndFunction (iCode * ic)
2867 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 lineNode *lnp = lineCurr;
2870 bitVect *regsUsedPrologue;
2871 bitVect *regsUnneeded;
2874 _G.currentFunc = NULL;
2875 if (IFFUNC_ISNAKED(sym->type))
2877 emitcode(";", "naked function: no epilogue.");
2878 if (options.debug && currFunc)
2879 debugFile->writeEndFunction (currFunc, ic, 0);
2883 if (IFFUNC_ISCRITICAL (sym->type))
2885 emitcode ("pop", "psw"); /* restore ea via c in psw */
2886 emitcode ("mov", "ea,c");
2889 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2891 emitcode ("mov", "%s,_bp", spname);
2894 /* if use external stack but some variables were
2895 added to the local stack then decrement the
2897 if (options.useXstack && sym->stack)
2899 emitcode ("mov", "a,sp");
2900 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2901 emitcode ("mov", "sp,a");
2905 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2907 if (options.useXstack)
2909 emitcode ("mov", "r0,%s", spname);
2910 emitcode ("movx", "a,@r0");
2911 emitcode ("mov", "_bp,a");
2912 emitcode ("dec", "%s", spname);
2916 emitcode ("pop", "_bp");
2920 /* restore the register bank */
2921 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2923 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2924 || !options.useXstack)
2926 /* Special case of ISR using non-zero bank with useXstack
2929 emitcode ("pop", "psw");
2933 if (IFFUNC_ISISR (sym->type))
2936 /* now we need to restore the registers */
2937 /* if this isr has no bank i.e. is going to
2938 run with bank 0 , then we need to save more
2940 if (!FUNC_REGBANK (sym->type))
2942 /* if this function does not call any other
2943 function then we can be economical and
2944 save only those registers that are used */
2945 if (!IFFUNC_HASFCALL(sym->type))
2949 /* if any registers used */
2952 /* save the registers used */
2953 for (i = sym->regsUsed->size; i >= 0; i--)
2955 if (bitVectBitValue (sym->regsUsed, i))
2956 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2962 if (options.parms_in_bank1) {
2964 for (i = 7 ; i >= 0 ; i-- ) {
2965 emitcode ("pop","%s",rb1regs[i]);
2968 /* this function has a function call cannot
2969 determines register usage so we will have to pop the
2971 unsaveRBank (0, ic, FALSE);
2976 /* This ISR uses a non-zero bank.
2978 * Restore any register banks saved by genFunction
2981 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2984 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2986 if (savedBanks & (1 << ix))
2988 unsaveRBank(ix, NULL, FALSE);
2992 if (options.useXstack)
2994 /* Restore bank AFTER calling unsaveRBank,
2995 * since it can trash r0.
2997 emitcode ("pop", "psw");
3001 if (!inExcludeList ("dph"))
3002 emitcode ("pop", "dph");
3003 if (!inExcludeList ("dpl"))
3004 emitcode ("pop", "dpl");
3005 if (!inExcludeList ("b"))
3006 emitcode ("pop", "b");
3007 if (!inExcludeList ("acc"))
3008 emitcode ("pop", "acc");
3010 /* if debug then send end of function */
3011 if (options.debug && currFunc)
3013 debugFile->writeEndFunction (currFunc, ic, 1);
3016 emitcode ("reti", "");
3020 if (IFFUNC_CALLEESAVES(sym->type))
3024 /* if any registers used */
3027 /* save the registers used */
3028 for (i = sym->regsUsed->size; i >= 0; i--)
3030 if (bitVectBitValue (sym->regsUsed, i) ||
3031 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3032 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3035 else if (mcs51_ptrRegReq)
3037 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3038 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3043 /* if debug then send end of function */
3044 if (options.debug && currFunc)
3046 debugFile->writeEndFunction (currFunc, ic, 1);
3049 emitcode ("ret", "");
3052 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3055 /* If this was an interrupt handler using bank 0 that called another */
3056 /* function, then all registers must be saved; nothing to optimized. */
3057 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3058 && !FUNC_REGBANK(sym->type))
3061 /* There are no push/pops to optimize if not callee-saves or ISR */
3062 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3065 /* If there were stack parameters, we cannot optimize without also */
3066 /* fixing all of the stack offsets; this is too dificult to consider. */
3067 if (FUNC_HASSTACKPARM(sym->type))
3070 /* Compute the registers actually used */
3071 regsUsed = newBitVect (mcs51_nRegs);
3072 regsUsedPrologue = newBitVect (mcs51_nRegs);
3075 if (lnp->ic && lnp->ic->op == FUNCTION)
3076 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3078 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3080 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3081 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3088 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3089 && !bitVectBitValue (regsUsed, CND_IDX))
3091 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3092 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3093 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3094 bitVectUnSetBit (regsUsed, CND_IDX);
3097 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3099 /* If this was an interrupt handler that called another function */
3100 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3101 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3103 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3104 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3105 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3106 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3107 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3110 /* Remove the unneeded push/pops */
3111 regsUnneeded = newBitVect (mcs51_nRegs);
3114 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3116 if (!strncmp(lnp->line, "push", 4))
3118 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3119 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3121 connectLine (lnp->prev, lnp->next);
3122 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3125 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3127 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3128 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3130 connectLine (lnp->prev, lnp->next);
3131 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3138 for (idx = 0; idx < regsUnneeded->size; idx++)
3139 if (bitVectBitValue (regsUnneeded, idx))
3140 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3142 freeBitVect (regsUnneeded);
3143 freeBitVect (regsUsed);
3144 freeBitVect (regsUsedPrologue);
3147 /*-----------------------------------------------------------------*/
3148 /* genRet - generate code for return statement */
3149 /*-----------------------------------------------------------------*/
3153 int size, offset = 0, pushed = 0;
3155 D(emitcode ("; genRet",""));
3157 /* if we have no return value then
3158 just generate the "ret" */
3162 /* we have something to return then
3163 move the return value into place */
3164 aopOp (IC_LEFT (ic), ic, FALSE);
3165 size = AOP_SIZE (IC_LEFT (ic));
3170 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3173 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3175 emitcode ("push", "%s", l);
3180 l = aopGet (AOP (IC_LEFT (ic)), offset,
3182 if (strcmp (fReturn[offset], l))
3183 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3192 if (strcmp (fReturn[pushed], "a"))
3193 emitcode ("pop", fReturn[pushed]);
3195 emitcode ("pop", "acc");
3198 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3201 /* generate a jump to the return label
3202 if the next is not the return statement */
3203 if (!(ic->next && ic->next->op == LABEL &&
3204 IC_LABEL (ic->next) == returnLabel))
3206 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3210 /*-----------------------------------------------------------------*/
3211 /* genLabel - generates a label */
3212 /*-----------------------------------------------------------------*/
3214 genLabel (iCode * ic)
3216 /* special case never generate */
3217 if (IC_LABEL (ic) == entryLabel)
3220 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3223 /*-----------------------------------------------------------------*/
3224 /* genGoto - generates a ljmp */
3225 /*-----------------------------------------------------------------*/
3227 genGoto (iCode * ic)
3229 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3232 /*-----------------------------------------------------------------*/
3233 /* findLabelBackwards: walks back through the iCode chain looking */
3234 /* for the given label. Returns number of iCode instructions */
3235 /* between that label and given ic. */
3236 /* Returns zero if label not found. */
3237 /*-----------------------------------------------------------------*/
3239 findLabelBackwards (iCode * ic, int key)
3248 /* If we have any pushes or pops, we cannot predict the distance.
3249 I don't like this at all, this should be dealt with in the
3251 if (ic->op == IPUSH || ic->op == IPOP) {
3255 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3264 /*-----------------------------------------------------------------*/
3265 /* genPlusIncr :- does addition with increment if possible */
3266 /*-----------------------------------------------------------------*/
3268 genPlusIncr (iCode * ic)
3270 unsigned int icount;
3271 unsigned int size = getDataSize (IC_RESULT (ic));
3273 /* will try to generate an increment */
3274 /* if the right side is not a literal
3276 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3279 /* if the literal value of the right hand side
3280 is greater than 4 then it is not worth it */
3281 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3284 D(emitcode ("; genPlusIncr",""));
3286 /* if increment >=16 bits in register or direct space */
3287 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3288 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3296 /* If the next instruction is a goto and the goto target
3297 * is < 10 instructions previous to this, we can generate
3298 * jumps straight to that target.
3300 if (ic->next && ic->next->op == GOTO
3301 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3302 && labelRange <= 10)
3304 emitcode (";", "tail increment optimized");
3305 tlbl = IC_LABEL (ic->next);
3310 tlbl = newiTempLabel (NULL);
3313 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3314 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3315 IS_AOP_PREG (IC_RESULT (ic)))
3316 emitcode ("cjne", "%s,#0x00,%05d$",
3317 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3321 emitcode ("clr", "a");
3322 emitcode ("cjne", "a,%s,%05d$",
3323 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3327 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3330 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3331 IS_AOP_PREG (IC_RESULT (ic)))
3332 emitcode ("cjne", "%s,#0x00,%05d$",
3333 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3336 emitcode ("cjne", "a,%s,%05d$",
3337 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3340 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3344 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3345 IS_AOP_PREG (IC_RESULT (ic)))
3346 emitcode ("cjne", "%s,#0x00,%05d$",
3347 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3351 emitcode ("cjne", "a,%s,%05d$",
3352 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3355 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3360 emitcode ("", "%05d$:", tlbl->key + 100);
3365 /* if the sizes are greater than 1 then we cannot */
3366 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3367 AOP_SIZE (IC_LEFT (ic)) > 1)
3370 /* we can if the aops of the left & result match or
3371 if they are in registers and the registers are the
3373 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3378 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3379 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3380 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3386 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3395 /*-----------------------------------------------------------------*/
3396 /* outBitAcc - output a bit in acc */
3397 /*-----------------------------------------------------------------*/
3399 outBitAcc (operand * result)
3401 symbol *tlbl = newiTempLabel (NULL);
3402 /* if the result is a bit */
3403 if (AOP_TYPE (result) == AOP_CRY)
3405 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3409 emitcode ("jz", "%05d$", tlbl->key + 100);
3410 emitcode ("mov", "a,%s", one);
3411 emitcode ("", "%05d$:", tlbl->key + 100);
3416 /*-----------------------------------------------------------------*/
3417 /* genPlusBits - generates code for addition of two bits */
3418 /*-----------------------------------------------------------------*/
3420 genPlusBits (iCode * ic)
3422 D(emitcode ("; genPlusBits",""));
3424 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3426 symbol *lbl = newiTempLabel (NULL);
3427 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3428 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3429 emitcode ("cpl", "c");
3430 emitcode ("", "%05d$:", (lbl->key + 100));
3431 outBitC (IC_RESULT (ic));
3435 emitcode ("clr", "a");
3436 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3437 emitcode ("rlc", "a");
3438 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3439 emitcode ("addc", "a,#0x00");
3440 outAcc (IC_RESULT (ic));
3445 /* This is the original version of this code.
3447 * This is being kept around for reference,
3448 * because I am not entirely sure I got it right...
3451 adjustArithmeticResult (iCode * ic)
3453 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3454 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3455 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3456 aopPut (AOP (IC_RESULT (ic)),
3457 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3459 isOperandVolatile (IC_RESULT (ic), FALSE));
3461 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3462 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3463 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3464 aopPut (AOP (IC_RESULT (ic)),
3465 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3467 isOperandVolatile (IC_RESULT (ic), FALSE));
3469 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3470 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3471 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3476 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3477 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3481 /* This is the pure and virtuous version of this code.
3482 * I'm pretty certain it's right, but not enough to toss the old
3486 adjustArithmeticResult (iCode * ic)
3488 if (opIsGptr (IC_RESULT (ic)) &&
3489 opIsGptr (IC_LEFT (ic)) &&
3490 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3492 aopPut (AOP (IC_RESULT (ic)),
3493 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3495 isOperandVolatile (IC_RESULT (ic), FALSE));
3498 if (opIsGptr (IC_RESULT (ic)) &&
3499 opIsGptr (IC_RIGHT (ic)) &&
3500 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3502 aopPut (AOP (IC_RESULT (ic)),
3503 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3505 isOperandVolatile (IC_RESULT (ic), FALSE));
3508 if (opIsGptr (IC_RESULT (ic)) &&
3509 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3510 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3511 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3512 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3515 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3516 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3521 /*-----------------------------------------------------------------*/
3522 /* genPlus - generates code for addition */
3523 /*-----------------------------------------------------------------*/
3525 genPlus (iCode * ic)
3527 int size, offset = 0;
3530 asmop *leftOp, *rightOp;
3533 /* special cases :- */
3535 D(emitcode ("; genPlus",""));
3537 aopOp (IC_LEFT (ic), ic, FALSE);
3538 aopOp (IC_RIGHT (ic), ic, FALSE);
3539 aopOp (IC_RESULT (ic), ic, TRUE);
3541 /* if literal, literal on the right or
3542 if left requires ACC or right is already
3544 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3545 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3546 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3548 operand *t = IC_RIGHT (ic);
3549 IC_RIGHT (ic) = IC_LEFT (ic);
3553 /* if both left & right are in bit
3555 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3556 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3562 /* if left in bit space & right literal */
3563 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3564 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3566 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3567 /* if result in bit space */
3568 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3570 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3571 emitcode ("cpl", "c");
3572 outBitC (IC_RESULT (ic));
3576 size = getDataSize (IC_RESULT (ic));
3579 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3580 emitcode ("addc", "a,#00");
3581 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3587 /* if I can do an increment instead
3588 of add then GOOD for ME */
3589 if (genPlusIncr (ic) == TRUE)
3592 size = getDataSize (IC_RESULT (ic));
3593 leftOp = AOP(IC_LEFT(ic));
3594 rightOp = AOP(IC_RIGHT(ic));
3597 /* if this is an add for an array access
3598 at a 256 byte boundary */
3600 && AOP_TYPE (op) == AOP_IMMD
3602 && IS_SPEC (OP_SYM_ETYPE (op))
3603 && SPEC_ABSA (OP_SYM_ETYPE (op))
3604 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3607 D(emitcode ("; genPlus aligned array",""));
3608 aopPut (AOP (IC_RESULT (ic)),
3609 aopGet (rightOp, 0, FALSE, FALSE),
3611 isOperandVolatile (IC_RESULT (ic), FALSE));
3613 if( 1 == getDataSize (IC_RIGHT (ic)) )
3615 aopPut (AOP (IC_RESULT (ic)),
3616 aopGet (leftOp, 1, FALSE, FALSE),
3618 isOperandVolatile (IC_RESULT (ic), FALSE));
3622 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3623 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3624 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3629 /* if the lower bytes of a literal are zero skip the addition */
3630 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3632 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3633 (skip_bytes+1 < size))
3638 D(emitcode ("; genPlus shortcut",""));
3643 if( offset >= skip_bytes )
3645 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3647 emitcode("mov", "b,a");
3648 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3649 emitcode("xch", "a,b");
3650 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3651 emitcode (add, "a,b");
3653 else if (aopGetUsesAcc (leftOp, offset))
3655 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3656 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3660 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3661 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3663 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3664 add = "addc"; /* further adds must propagate carry */
3668 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3669 isOperandVolatile (IC_RESULT (ic), FALSE))
3672 aopPut (AOP (IC_RESULT (ic)),
3673 aopGet (leftOp, offset, FALSE, FALSE),
3675 isOperandVolatile (IC_RESULT (ic), FALSE));
3681 adjustArithmeticResult (ic);
3684 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3685 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3689 /*-----------------------------------------------------------------*/
3690 /* genMinusDec :- does subtraction with deccrement if possible */
3691 /*-----------------------------------------------------------------*/
3693 genMinusDec (iCode * ic)
3695 unsigned int icount;
3696 unsigned int size = getDataSize (IC_RESULT (ic));
3698 /* will try to generate an increment */
3699 /* if the right side is not a literal
3701 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3704 /* if the literal value of the right hand side
3705 is greater than 4 then it is not worth it */
3706 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3709 D(emitcode ("; genMinusDec",""));
3711 /* if decrement >=16 bits in register or direct space */
3712 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3713 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3721 /* If the next instruction is a goto and the goto target
3722 * is <= 10 instructions previous to this, we can generate
3723 * jumps straight to that target.
3725 if (ic->next && ic->next->op == GOTO
3726 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3727 && labelRange <= 10)
3729 emitcode (";", "tail decrement optimized");
3730 tlbl = IC_LABEL (ic->next);
3735 tlbl = newiTempLabel (NULL);
3739 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3740 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3741 IS_AOP_PREG (IC_RESULT (ic)))
3742 emitcode ("cjne", "%s,#0xff,%05d$"
3743 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3747 emitcode ("mov", "a,#0xff");
3748 emitcode ("cjne", "a,%s,%05d$"
3749 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3752 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3755 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3756 IS_AOP_PREG (IC_RESULT (ic)))
3757 emitcode ("cjne", "%s,#0xff,%05d$"
3758 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3762 emitcode ("cjne", "a,%s,%05d$"
3763 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3766 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3770 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3771 IS_AOP_PREG (IC_RESULT (ic)))
3772 emitcode ("cjne", "%s,#0xff,%05d$"
3773 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3777 emitcode ("cjne", "a,%s,%05d$"
3778 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3781 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3785 emitcode ("", "%05d$:", tlbl->key + 100);
3790 /* if the sizes are greater than 1 then we cannot */
3791 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3792 AOP_SIZE (IC_LEFT (ic)) > 1)
3795 /* we can if the aops of the left & result match or
3796 if they are in registers and the registers are the
3798 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3802 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3810 /*-----------------------------------------------------------------*/
3811 /* addSign - complete with sign */
3812 /*-----------------------------------------------------------------*/
3814 addSign (operand * result, int offset, int sign)
3816 int size = (getDataSize (result) - offset);
3821 emitcode ("rlc", "a");
3822 emitcode ("subb", "a,acc");
3824 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3828 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3832 /*-----------------------------------------------------------------*/
3833 /* genMinusBits - generates code for subtraction of two bits */
3834 /*-----------------------------------------------------------------*/
3836 genMinusBits (iCode * ic)
3838 symbol *lbl = newiTempLabel (NULL);
3840 D(emitcode ("; genMinusBits",""));
3842 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3844 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3845 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3846 emitcode ("cpl", "c");
3847 emitcode ("", "%05d$:", (lbl->key + 100));
3848 outBitC (IC_RESULT (ic));
3852 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3853 emitcode ("subb", "a,acc");
3854 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3855 emitcode ("inc", "a");
3856 emitcode ("", "%05d$:", (lbl->key + 100));
3857 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3858 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3862 /*-----------------------------------------------------------------*/
3863 /* genMinus - generates code for subtraction */
3864 /*-----------------------------------------------------------------*/
3866 genMinus (iCode * ic)
3868 int size, offset = 0;
3870 D(emitcode ("; genMinus",""));
3872 aopOp (IC_LEFT (ic), ic, FALSE);
3873 aopOp (IC_RIGHT (ic), ic, FALSE);
3874 aopOp (IC_RESULT (ic), ic, TRUE);
3876 /* special cases :- */
3877 /* if both left & right are in bit space */
3878 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3879 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3885 /* if I can do an decrement instead
3886 of subtract then GOOD for ME */
3887 if (genMinusDec (ic) == TRUE)
3890 size = getDataSize (IC_RESULT (ic));
3892 /* if literal, add a,#-lit, else normal subb */
3893 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3895 unsigned long lit = 0L;
3897 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3902 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3903 /* first add without previous c */
3905 if (!size && lit== (unsigned long) -1) {
3906 emitcode ("dec", "a");
3908 emitcode ("add", "a,#0x%02x",
3909 (unsigned int) (lit & 0x0FFL));
3912 emitcode ("addc", "a,#0x%02x",
3913 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3915 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3920 asmop *leftOp, *rightOp;
3922 leftOp = AOP(IC_LEFT(ic));
3923 rightOp = AOP(IC_RIGHT(ic));
3927 if (aopGetUsesAcc(rightOp, offset)) {
3928 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3929 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3931 emitcode( "setb", "c");
3933 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3934 emitcode("cpl", "a");
3936 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3939 emitcode ("subb", "a,%s",
3940 aopGet(rightOp, offset, FALSE, TRUE));
3943 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3948 adjustArithmeticResult (ic);
3951 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3952 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3957 /*-----------------------------------------------------------------*/
3958 /* genMultbits :- multiplication of bits */
3959 /*-----------------------------------------------------------------*/
3961 genMultbits (operand * left,
3965 D(emitcode ("; genMultbits",""));
3967 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3968 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3972 /*-----------------------------------------------------------------*/
3973 /* genMultOneByte : 8*8=8/16 bit multiplication */
3974 /*-----------------------------------------------------------------*/
3976 genMultOneByte (operand * left,
3981 int size = AOP_SIZE (result);
3982 bool runtimeSign, compiletimeSign;
3983 bool lUnsigned, rUnsigned;
3985 D(emitcode ("; genMultOneByte",""));
3987 if (size < 1 || size > 2)
3989 /* this should never happen */
3990 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3991 AOP_SIZE(result), __FILE__, lineno);
3995 /* (if two literals: the value is computed before) */
3996 /* if one literal, literal on the right */
3997 if (AOP_TYPE (left) == AOP_LIT)
4002 /* emitcode (";", "swapped left and right"); */
4004 /* if no literal, unsigned on the right: shorter code */
4005 if ( AOP_TYPE (right) != AOP_LIT
4006 && SPEC_USIGN (getSpec (operandType (left))))
4013 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4014 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4016 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4017 no need to take care about the signedness! */
4018 || (lUnsigned && rUnsigned))
4020 /* just an unsigned 8 * 8 = 8 multiply
4022 /* emitcode (";","unsigned"); */
4023 /* TODO: check for accumulator clash between left & right aops? */
4025 if (AOP_TYPE (right) == AOP_LIT)
4027 /* moving to accumulator first helps peepholes */
4028 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4029 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4033 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4034 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4037 emitcode ("mul", "ab");
4038 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4040 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4044 /* we have to do a signed multiply */
4045 /* emitcode (";", "signed"); */
4047 /* now sign adjust for both left & right */
4049 /* let's see what's needed: */
4050 /* apply negative sign during runtime */
4051 runtimeSign = FALSE;
4052 /* negative sign from literals */
4053 compiletimeSign = FALSE;
4057 if (AOP_TYPE(left) == AOP_LIT)
4059 /* signed literal */
4060 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4062 compiletimeSign = TRUE;
4065 /* signed but not literal */
4071 if (AOP_TYPE(right) == AOP_LIT)
4073 /* signed literal */
4074 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4076 compiletimeSign ^= TRUE;
4079 /* signed but not literal */
4083 /* initialize F0, which stores the runtime sign */
4086 if (compiletimeSign)
4087 emitcode ("setb", "F0"); /* set sign flag */
4089 emitcode ("clr", "F0"); /* reset sign flag */
4092 /* save the signs of the operands */
4093 if (AOP_TYPE(right) == AOP_LIT)
4095 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4097 if (!rUnsigned && val < 0)
4098 emitcode ("mov", "b,#0x%02x", -val);
4100 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4102 else /* ! literal */
4104 if (rUnsigned) /* emitcode (";", "signed"); */
4106 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4109 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4110 lbl = newiTempLabel (NULL);
4111 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4112 emitcode ("cpl", "F0"); /* complement sign flag */
4113 emitcode ("cpl", "a"); /* 2's complement */
4114 emitcode ("inc", "a");
4115 emitcode ("", "%05d$:", (lbl->key + 100));
4116 emitcode ("mov", "b,a");
4120 if (AOP_TYPE(left) == AOP_LIT)
4122 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4124 if (!lUnsigned && val < 0)
4125 emitcode ("mov", "a,#0x%02x", -val);
4127 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4129 else /* ! literal */
4131 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4135 lbl = newiTempLabel (NULL);
4136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4137 emitcode ("cpl", "F0"); /* complement sign flag */
4138 emitcode ("cpl", "a"); /* 2's complement */
4139 emitcode ("inc", "a");
4140 emitcode ("", "%05d$:", (lbl->key + 100));
4144 /* now the multiplication */
4145 emitcode ("mul", "ab");
4146 if (runtimeSign || compiletimeSign)
4148 lbl = newiTempLabel (NULL);
4150 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4151 emitcode ("cpl", "a"); /* lsb 2's complement */
4153 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4156 emitcode ("add", "a,#1"); /* this sets carry flag */
4157 emitcode ("xch", "a,b");
4158 emitcode ("cpl", "a"); /* msb 2's complement */
4159 emitcode ("addc", "a,#0");
4160 emitcode ("xch", "a,b");
4162 emitcode ("", "%05d$:", (lbl->key + 100));
4164 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4166 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4169 /*-----------------------------------------------------------------*/
4170 /* genMult - generates code for multiplication */
4171 /*-----------------------------------------------------------------*/
4173 genMult (iCode * ic)
4175 operand *left = IC_LEFT (ic);
4176 operand *right = IC_RIGHT (ic);
4177 operand *result = IC_RESULT (ic);
4179 D(emitcode ("; genMult",""));
4181 /* assign the amsops */
4182 aopOp (left, ic, FALSE);
4183 aopOp (right, ic, FALSE);
4184 aopOp (result, ic, TRUE);
4186 /* special cases first */
4188 if (AOP_TYPE (left) == AOP_CRY &&
4189 AOP_TYPE (right) == AOP_CRY)
4191 genMultbits (left, right, result);
4195 /* if both are of size == 1 */
4196 #if 0 // one of them can be a sloc shared with the result
4197 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4199 if (getSize(operandType(left)) == 1 &&
4200 getSize(operandType(right)) == 1)
4203 genMultOneByte (left, right, result);
4207 /* should have been converted to function call */
4208 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4209 getSize(OP_SYMBOL(right)->type));
4213 freeAsmop (result, NULL, ic, TRUE);
4214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 /*-----------------------------------------------------------------*/
4219 /* genDivbits :- division of bits */
4220 /*-----------------------------------------------------------------*/
4222 genDivbits (operand * left,
4229 D(emitcode ("; genDivbits",""));
4231 /* the result must be bit */
4232 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4233 l = aopGet (AOP (left), 0, FALSE, FALSE);
4237 emitcode ("div", "ab");
4238 emitcode ("rrc", "a");
4239 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4242 /*-----------------------------------------------------------------*/
4243 /* genDivOneByte : 8 bit division */
4244 /*-----------------------------------------------------------------*/
4246 genDivOneByte (operand * left,
4250 bool lUnsigned, rUnsigned;
4251 bool runtimeSign, compiletimeSign;
4255 D(emitcode ("; genDivOneByte",""));
4257 /* Why is it necessary that genDivOneByte() can return an int result?
4260 volatile unsigned char uc;
4261 volatile signed char sc1, sc2;
4274 In all cases a one byte result would overflow, the following cast to int
4275 would return the wrong result.
4277 Two possible solution:
4278 a) cast operands to int, if ((unsigned) / (signed)) or
4279 ((signed) / (signed))
4280 b) return an 16 bit signed int; this is what we're doing here!
4283 size = AOP_SIZE (result) - 1;
4285 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4286 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4288 /* signed or unsigned */
4289 if (lUnsigned && rUnsigned)
4291 /* unsigned is easy */
4292 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4293 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4294 emitcode ("div", "ab");
4295 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4297 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4301 /* signed is a little bit more difficult */
4303 /* now sign adjust for both left & right */
4305 /* let's see what's needed: */
4306 /* apply negative sign during runtime */
4307 runtimeSign = FALSE;
4308 /* negative sign from literals */
4309 compiletimeSign = FALSE;
4313 if (AOP_TYPE(left) == AOP_LIT)
4315 /* signed literal */
4316 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4318 compiletimeSign = TRUE;
4321 /* signed but not literal */
4327 if (AOP_TYPE(right) == AOP_LIT)
4329 /* signed literal */
4330 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4332 compiletimeSign ^= TRUE;
4335 /* signed but not literal */
4339 /* initialize F0, which stores the runtime sign */
4342 if (compiletimeSign)
4343 emitcode ("setb", "F0"); /* set sign flag */
4345 emitcode ("clr", "F0"); /* reset sign flag */
4348 /* save the signs of the operands */
4349 if (AOP_TYPE(right) == AOP_LIT)
4351 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4353 if (!rUnsigned && val < 0)
4354 emitcode ("mov", "b,#0x%02x", -val);
4356 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4358 else /* ! literal */
4361 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4364 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4365 lbl = newiTempLabel (NULL);
4366 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4367 emitcode ("cpl", "F0"); /* complement sign flag */
4368 emitcode ("cpl", "a"); /* 2's complement */
4369 emitcode ("inc", "a");
4370 emitcode ("", "%05d$:", (lbl->key + 100));
4371 emitcode ("mov", "b,a");
4375 if (AOP_TYPE(left) == AOP_LIT)
4377 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4379 if (!lUnsigned && val < 0)
4380 emitcode ("mov", "a,#0x%02x", -val);
4382 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4384 else /* ! literal */
4386 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4390 lbl = newiTempLabel (NULL);
4391 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4392 emitcode ("cpl", "F0"); /* complement sign flag */
4393 emitcode ("cpl", "a"); /* 2's complement */
4394 emitcode ("inc", "a");
4395 emitcode ("", "%05d$:", (lbl->key + 100));
4399 /* now the division */
4400 emitcode ("div", "ab");
4402 if (runtimeSign || compiletimeSign)
4404 lbl = newiTempLabel (NULL);
4406 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4407 emitcode ("cpl", "a"); /* lsb 2's complement */
4408 emitcode ("inc", "a");
4409 emitcode ("", "%05d$:", (lbl->key + 100));
4411 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4414 /* msb is 0x00 or 0xff depending on the sign */
4417 emitcode ("mov", "c,F0");
4418 emitcode ("subb", "a,acc");
4420 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4422 else /* compiletimeSign */
4424 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4429 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4431 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4435 /*-----------------------------------------------------------------*/
4436 /* genDiv - generates code for division */
4437 /*-----------------------------------------------------------------*/
4441 operand *left = IC_LEFT (ic);
4442 operand *right = IC_RIGHT (ic);
4443 operand *result = IC_RESULT (ic);
4445 D(emitcode ("; genDiv",""));
4447 /* assign the amsops */
4448 aopOp (left, ic, FALSE);
4449 aopOp (right, ic, FALSE);
4450 aopOp (result, ic, TRUE);
4452 /* special cases first */
4454 if (AOP_TYPE (left) == AOP_CRY &&
4455 AOP_TYPE (right) == AOP_CRY)
4457 genDivbits (left, right, result);
4461 /* if both are of size == 1 */
4462 if (AOP_SIZE (left) == 1 &&
4463 AOP_SIZE (right) == 1)
4465 genDivOneByte (left, right, result);
4469 /* should have been converted to function call */
4472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474 freeAsmop (result, NULL, ic, TRUE);
4477 /*-----------------------------------------------------------------*/
4478 /* genModbits :- modulus of bits */
4479 /*-----------------------------------------------------------------*/
4481 genModbits (operand * left,
4488 D(emitcode ("; genModbits",""));
4490 /* the result must be bit */
4491 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4492 l = aopGet (AOP (left), 0, FALSE, FALSE);
4496 emitcode ("div", "ab");
4497 emitcode ("mov", "a,b");
4498 emitcode ("rrc", "a");
4499 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4502 /*-----------------------------------------------------------------*/
4503 /* genModOneByte : 8 bit modulus */
4504 /*-----------------------------------------------------------------*/
4506 genModOneByte (operand * left,
4510 bool lUnsigned, rUnsigned;
4511 bool runtimeSign, compiletimeSign;
4515 D(emitcode ("; genModOneByte",""));
4517 size = AOP_SIZE (result) - 1;
4519 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4520 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4522 /* signed or unsigned */
4523 if (lUnsigned && rUnsigned)
4525 /* unsigned is easy */
4526 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4527 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4528 emitcode ("div", "ab");
4529 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4531 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4535 /* signed is a little bit more difficult */
4537 /* now sign adjust for both left & right */
4539 /* modulus: sign of the right operand has no influence on the result! */
4540 if (AOP_TYPE(right) == AOP_LIT)
4542 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4544 if (!rUnsigned && val < 0)
4545 emitcode ("mov", "b,#0x%02x", -val);
4547 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4549 else /* not literal */
4552 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4555 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4556 lbl = newiTempLabel (NULL);
4557 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4558 emitcode ("cpl", "a"); /* 2's complement */
4559 emitcode ("inc", "a");
4560 emitcode ("", "%05d$:", (lbl->key + 100));
4561 emitcode ("mov", "b,a");
4565 /* let's see what's needed: */
4566 /* apply negative sign during runtime */
4567 runtimeSign = FALSE;
4568 /* negative sign from literals */
4569 compiletimeSign = FALSE;
4571 /* sign adjust left side */
4572 if (AOP_TYPE(left) == AOP_LIT)
4574 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4576 if (!lUnsigned && val < 0)
4578 compiletimeSign = TRUE; /* set sign flag */
4579 emitcode ("mov", "a,#0x%02x", -val);
4582 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4584 else /* ! literal */
4586 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4591 emitcode ("clr", "F0"); /* clear sign flag */
4593 lbl = newiTempLabel (NULL);
4594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4595 emitcode ("setb", "F0"); /* set sign flag */
4596 emitcode ("cpl", "a"); /* 2's complement */
4597 emitcode ("inc", "a");
4598 emitcode ("", "%05d$:", (lbl->key + 100));
4602 /* now the modulus */
4603 emitcode ("div", "ab");
4605 if (runtimeSign || compiletimeSign)
4607 emitcode ("mov", "a,b");
4608 lbl = newiTempLabel (NULL);
4610 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4611 emitcode ("cpl", "a"); /* 2's complement */
4612 emitcode ("inc", "a");
4613 emitcode ("", "%05d$:", (lbl->key + 100));
4615 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4618 /* msb is 0x00 or 0xff depending on the sign */
4621 emitcode ("mov", "c,F0");
4622 emitcode ("subb", "a,acc");
4624 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4626 else /* compiletimeSign */
4628 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4633 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4635 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4639 /*-----------------------------------------------------------------*/
4640 /* genMod - generates code for division */
4641 /*-----------------------------------------------------------------*/
4645 operand *left = IC_LEFT (ic);
4646 operand *right = IC_RIGHT (ic);
4647 operand *result = IC_RESULT (ic);
4649 D(emitcode ("; genMod",""));
4651 /* assign the amsops */
4652 aopOp (left, ic, FALSE);
4653 aopOp (right, ic, FALSE);
4654 aopOp (result, ic, TRUE);
4656 /* special cases first */
4658 if (AOP_TYPE (left) == AOP_CRY &&
4659 AOP_TYPE (right) == AOP_CRY)
4661 genModbits (left, right, result);
4665 /* if both are of size == 1 */
4666 if (AOP_SIZE (left) == 1 &&
4667 AOP_SIZE (right) == 1)
4669 genModOneByte (left, right, result);
4673 /* should have been converted to function call */
4677 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (result, NULL, ic, TRUE);
4682 /*-----------------------------------------------------------------*/
4683 /* genIfxJump :- will create a jump depending on the ifx */
4684 /*-----------------------------------------------------------------*/
4686 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4689 symbol *tlbl = newiTempLabel (NULL);
4692 D(emitcode ("; genIfxJump",""));
4694 /* if true label then we jump if condition
4698 jlbl = IC_TRUE (ic);
4699 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4700 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4704 /* false label is present */
4705 jlbl = IC_FALSE (ic);
4706 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4707 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4709 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4710 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4712 emitcode (inst, "%05d$", tlbl->key + 100);
4713 freeForBranchAsmop (result);
4714 freeForBranchAsmop (right);
4715 freeForBranchAsmop (left);
4716 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4717 emitcode ("", "%05d$:", tlbl->key + 100);
4719 /* mark the icode as generated */
4723 /*-----------------------------------------------------------------*/
4724 /* genCmp :- greater or less than comparison */
4725 /*-----------------------------------------------------------------*/
4727 genCmp (operand * left, operand * right,
4728 operand * result, iCode * ifx, int sign, iCode *ic)
4730 int size, offset = 0;
4731 unsigned long lit = 0L;
4734 D(emitcode ("; genCmp",""));
4736 /* if left & right are bit variables */
4737 if (AOP_TYPE (left) == AOP_CRY &&
4738 AOP_TYPE (right) == AOP_CRY)
4740 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4741 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4745 /* subtract right from left if at the
4746 end the carry flag is set then we know that
4747 left is greater than right */
4748 size = max (AOP_SIZE (left), AOP_SIZE (right));
4750 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4751 if ((size == 1) && !sign &&
4752 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4754 symbol *lbl = newiTempLabel (NULL);
4755 emitcode ("cjne", "%s,%s,%05d$",
4756 aopGet (AOP (left), offset, FALSE, FALSE),
4757 aopGet (AOP (right), offset, FALSE, FALSE),
4759 emitcode ("", "%05d$:", lbl->key + 100);
4763 if (AOP_TYPE (right) == AOP_LIT)
4765 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4766 /* optimize if(x < 0) or if(x >= 0) */
4775 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4776 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4778 genIfxJump (ifx, "acc.7", left, right, result);
4779 freeAsmop (right, NULL, ic, TRUE);
4780 freeAsmop (left, NULL, ic, TRUE);
4785 emitcode ("rlc", "a");
4793 rightInB = aopGetUsesAcc(AOP (right), offset);
4795 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4796 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4797 if (sign && size == 0)
4799 emitcode ("xrl", "a,#0x80");
4800 if (AOP_TYPE (right) == AOP_LIT)
4802 unsigned long lit = (unsigned long)
4803 floatFromVal (AOP (right)->aopu.aop_lit);
4804 emitcode ("subb", "a,#0x%02x",
4805 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4810 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4811 emitcode ("xrl", "b,#0x80");
4812 emitcode ("subb", "a,b");
4818 emitcode ("subb", "a,b");
4820 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4836 /* if the result is used in the next
4837 ifx conditional branch then generate
4838 code a little differently */
4840 genIfxJump (ifx, "c", NULL, NULL, result);
4843 /* leave the result in acc */
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpGt :- greater than comparison */
4849 /*-----------------------------------------------------------------*/
4851 genCmpGt (iCode * ic, iCode * ifx)
4853 operand *left, *right, *result;
4854 sym_link *letype, *retype;
4857 D(emitcode ("; genCmpGt",""));
4859 left = IC_LEFT (ic);
4860 right = IC_RIGHT (ic);
4861 result = IC_RESULT (ic);
4863 letype = getSpec (operandType (left));
4864 retype = getSpec (operandType (right));
4865 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4866 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4867 /* assign the amsops */
4868 aopOp (left, ic, FALSE);
4869 aopOp (right, ic, FALSE);
4870 aopOp (result, ic, TRUE);
4872 genCmp (right, left, result, ifx, sign,ic);
4874 freeAsmop (result, NULL, ic, TRUE);
4877 /*-----------------------------------------------------------------*/
4878 /* genCmpLt - less than comparisons */
4879 /*-----------------------------------------------------------------*/
4881 genCmpLt (iCode * ic, iCode * ifx)
4883 operand *left, *right, *result;
4884 sym_link *letype, *retype;
4887 D(emitcode ("; genCmpLt",""));
4889 left = IC_LEFT (ic);
4890 right = IC_RIGHT (ic);
4891 result = IC_RESULT (ic);
4893 letype = getSpec (operandType (left));
4894 retype = getSpec (operandType (right));
4895 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4896 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4897 /* assign the amsops */
4898 aopOp (left, ic, FALSE);
4899 aopOp (right, ic, FALSE);
4900 aopOp (result, ic, TRUE);
4902 genCmp (left, right, result, ifx, sign,ic);
4904 freeAsmop (result, NULL, ic, TRUE);
4907 /*-----------------------------------------------------------------*/
4908 /* gencjneshort - compare and jump if not equal */
4909 /*-----------------------------------------------------------------*/
4911 gencjneshort (operand * left, operand * right, symbol * lbl)
4913 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4915 unsigned long lit = 0L;
4917 /* if the left side is a literal or
4918 if the right is in a pointer register and left
4920 if ((AOP_TYPE (left) == AOP_LIT) ||
4921 (AOP_TYPE (left) == AOP_IMMD) ||
4922 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4929 if (AOP_TYPE (right) == AOP_LIT)
4930 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4932 /* if the right side is a literal then anything goes */
4933 if (AOP_TYPE (right) == AOP_LIT &&
4934 AOP_TYPE (left) != AOP_DIR &&
4935 AOP_TYPE (left) != AOP_IMMD)
4939 emitcode ("cjne", "%s,%s,%05d$",
4940 aopGet (AOP (left), offset, FALSE, FALSE),
4941 aopGet (AOP (right), offset, FALSE, FALSE),
4947 /* if the right side is in a register or in direct space or
4948 if the left is a pointer register & right is not */
4949 else if (AOP_TYPE (right) == AOP_REG ||
4950 AOP_TYPE (right) == AOP_DIR ||
4951 AOP_TYPE (right) == AOP_LIT ||
4952 AOP_TYPE (right) == AOP_IMMD ||
4953 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4954 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4959 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4960 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4961 emitcode ("jnz", "%05d$", lbl->key + 100);
4963 emitcode ("cjne", "a,%s,%05d$",
4964 aopGet (AOP (right), offset, FALSE, TRUE),
4971 /* right is a pointer reg need both a & b */
4974 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4975 if (strcmp (l, "b"))
4976 emitcode ("mov", "b,%s", l);
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4984 /*-----------------------------------------------------------------*/
4985 /* gencjne - compare and jump if not equal */
4986 /*-----------------------------------------------------------------*/
4988 gencjne (operand * left, operand * right, symbol * lbl)
4990 symbol *tlbl = newiTempLabel (NULL);
4992 gencjneshort (left, right, lbl);
4994 emitcode ("mov", "a,%s", one);
4995 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4996 emitcode ("", "%05d$:", lbl->key + 100);
4997 emitcode ("clr", "a");
4998 emitcode ("", "%05d$:", tlbl->key + 100);
5001 /*-----------------------------------------------------------------*/
5002 /* genCmpEq - generates code for equal to */
5003 /*-----------------------------------------------------------------*/
5005 genCmpEq (iCode * ic, iCode * ifx)
5007 operand *left, *right, *result;
5009 D(emitcode ("; genCmpEq",""));
5011 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5012 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5013 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5015 /* if literal, literal on the right or
5016 if the right is in a pointer register and left
5018 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5019 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5021 operand *t = IC_RIGHT (ic);
5022 IC_RIGHT (ic) = IC_LEFT (ic);
5026 if (ifx && !AOP_SIZE (result))
5029 /* if they are both bit variables */
5030 if (AOP_TYPE (left) == AOP_CRY &&
5031 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5033 if (AOP_TYPE (right) == AOP_LIT)
5035 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5039 emitcode ("cpl", "c");
5043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5047 emitcode ("clr", "c");
5049 /* AOP_TYPE(right) == AOP_CRY */
5053 symbol *lbl = newiTempLabel (NULL);
5054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5055 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5056 emitcode ("cpl", "c");
5057 emitcode ("", "%05d$:", (lbl->key + 100));
5059 /* if true label then we jump if condition
5061 tlbl = newiTempLabel (NULL);
5064 emitcode ("jnc", "%05d$", tlbl->key + 100);
5065 freeForBranchAsmop (result);
5066 freeForBranchAsmop (right);
5067 freeForBranchAsmop (left);
5068 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5072 emitcode ("jc", "%05d$", tlbl->key + 100);
5073 freeForBranchAsmop (result);
5074 freeForBranchAsmop (right);
5075 freeForBranchAsmop (left);
5076 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5082 tlbl = newiTempLabel (NULL);
5083 gencjneshort (left, right, tlbl);
5086 freeForBranchAsmop (result);
5087 freeForBranchAsmop (right);
5088 freeForBranchAsmop (left);
5089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5090 emitcode ("", "%05d$:", tlbl->key + 100);
5094 symbol *lbl = newiTempLabel (NULL);
5095 emitcode ("sjmp", "%05d$", lbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5097 freeForBranchAsmop (result);
5098 freeForBranchAsmop (right);
5099 freeForBranchAsmop (left);
5100 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5101 emitcode ("", "%05d$:", lbl->key + 100);
5104 /* mark the icode as generated */
5109 /* if they are both bit variables */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119 emitcode ("cpl", "c");
5123 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5127 emitcode ("clr", "c");
5129 /* AOP_TYPE(right) == AOP_CRY */
5133 symbol *lbl = newiTempLabel (NULL);
5134 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5135 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5136 emitcode ("cpl", "c");
5137 emitcode ("", "%05d$:", (lbl->key + 100));
5140 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5147 genIfxJump (ifx, "c", left, right, result);
5150 /* if the result is used in an arithmetic operation
5151 then put the result in place */
5156 gencjne (left, right, newiTempLabel (NULL));
5157 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5159 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5164 genIfxJump (ifx, "a", left, right, result);
5167 /* if the result is used in an arithmetic operation
5168 then put the result in place */
5169 if (AOP_TYPE (result) != AOP_CRY)
5171 /* leave the result in acc */
5175 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177 freeAsmop (result, NULL, ic, TRUE);
5180 /*-----------------------------------------------------------------*/
5181 /* ifxForOp - returns the icode containing the ifx for operand */
5182 /*-----------------------------------------------------------------*/
5184 ifxForOp (operand * op, iCode * ic)
5186 /* if true symbol then needs to be assigned */
5187 if (IS_TRUE_SYMOP (op))
5190 /* if this has register type condition and
5191 the next instruction is ifx with the same operand
5192 and live to of the operand is upto the ifx only then */
5194 ic->next->op == IFX &&
5195 IC_COND (ic->next)->key == op->key &&
5196 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5202 /*-----------------------------------------------------------------*/
5203 /* hasInc - operand is incremented before any other use */
5204 /*-----------------------------------------------------------------*/
5206 hasInc (operand *op, iCode *ic,int osize)
5208 sym_link *type = operandType(op);
5209 sym_link *retype = getSpec (type);
5210 iCode *lic = ic->next;
5213 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5214 if (!IS_SYMOP(op)) return NULL;
5216 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5217 if (IS_AGGREGATE(type->next)) return NULL;
5218 if (osize != (isize = getSize(type->next))) return NULL;
5221 /* if operand of the form op = op + <sizeof *op> */
5222 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5223 isOperandEqual(IC_RESULT(lic),op) &&
5224 isOperandLiteral(IC_RIGHT(lic)) &&
5225 operandLitValue(IC_RIGHT(lic)) == isize) {
5228 /* if the operand used or deffed */
5229 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5232 /* if GOTO or IFX */
5233 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5239 /*-----------------------------------------------------------------*/
5240 /* genAndOp - for && operation */
5241 /*-----------------------------------------------------------------*/
5243 genAndOp (iCode * ic)
5245 operand *left, *right, *result;
5248 D(emitcode ("; genAndOp",""));
5250 /* note here that && operations that are in an
5251 if statement are taken away by backPatchLabels
5252 only those used in arthmetic operations remain */
5253 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5254 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5255 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5257 /* if both are bit variables */
5258 if (AOP_TYPE (left) == AOP_CRY &&
5259 AOP_TYPE (right) == AOP_CRY)
5261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5267 tlbl = newiTempLabel (NULL);
5269 emitcode ("jz", "%05d$", tlbl->key + 100);
5271 emitcode ("", "%05d$:", tlbl->key + 100);
5275 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 freeAsmop (result, NULL, ic, TRUE);
5281 /*-----------------------------------------------------------------*/
5282 /* genOrOp - for || operation */
5283 /*-----------------------------------------------------------------*/
5285 genOrOp (iCode * ic)
5287 operand *left, *right, *result;
5290 D(emitcode ("; genOrOp",""));
5292 /* note here that || operations that are in an
5293 if statement are taken away by backPatchLabels
5294 only those used in arthmetic operations remain */
5295 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5296 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5297 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5299 /* if both are bit variables */
5300 if (AOP_TYPE (left) == AOP_CRY &&
5301 AOP_TYPE (right) == AOP_CRY)
5303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5309 tlbl = newiTempLabel (NULL);
5311 emitcode ("jnz", "%05d$", tlbl->key + 100);
5313 emitcode ("", "%05d$:", tlbl->key + 100);
5317 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5319 freeAsmop (result, NULL, ic, TRUE);
5322 /*-----------------------------------------------------------------*/
5323 /* isLiteralBit - test if lit == 2^n */
5324 /*-----------------------------------------------------------------*/
5326 isLiteralBit (unsigned long lit)
5328 unsigned long pw[32] =
5329 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5330 0x100L, 0x200L, 0x400L, 0x800L,
5331 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5332 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5333 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5334 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5335 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5338 for (idx = 0; idx < 32; idx++)
5344 /*-----------------------------------------------------------------*/
5345 /* continueIfTrue - */
5346 /*-----------------------------------------------------------------*/
5348 continueIfTrue (iCode * ic)
5351 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5355 /*-----------------------------------------------------------------*/
5357 /*-----------------------------------------------------------------*/
5359 jumpIfTrue (iCode * ic)
5362 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5366 /*-----------------------------------------------------------------*/
5367 /* jmpTrueOrFalse - */
5368 /*-----------------------------------------------------------------*/
5370 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5372 // ugly but optimized by peephole
5375 symbol *nlbl = newiTempLabel (NULL);
5376 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5377 emitcode ("", "%05d$:", tlbl->key + 100);
5378 freeForBranchAsmop (result);
5379 freeForBranchAsmop (right);
5380 freeForBranchAsmop (left);
5381 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5382 emitcode ("", "%05d$:", nlbl->key + 100);
5386 freeForBranchAsmop (result);
5387 freeForBranchAsmop (right);
5388 freeForBranchAsmop (left);
5389 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5390 emitcode ("", "%05d$:", tlbl->key + 100);
5395 /*-----------------------------------------------------------------*/
5396 /* genAnd - code for and */
5397 /*-----------------------------------------------------------------*/
5399 genAnd (iCode * ic, iCode * ifx)
5401 operand *left, *right, *result;
5402 int size, offset = 0;
5403 unsigned long lit = 0L;
5407 D(emitcode ("; genAnd",""));
5409 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5410 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5411 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5414 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5416 AOP_TYPE (left), AOP_TYPE (right));
5417 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5419 AOP_SIZE (left), AOP_SIZE (right));
5422 /* if left is a literal & right is not then exchange them */
5423 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5424 AOP_NEEDSACC (left))
5426 operand *tmp = right;
5431 /* if result = right then exchange left and right */
5432 if (sameRegs (AOP (result), AOP (right)))
5434 operand *tmp = right;
5439 /* if right is bit then exchange them */
5440 if (AOP_TYPE (right) == AOP_CRY &&
5441 AOP_TYPE (left) != AOP_CRY)
5443 operand *tmp = right;
5447 if (AOP_TYPE (right) == AOP_LIT)
5448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5450 size = AOP_SIZE (result);
5453 // result = bit & yy;
5454 if (AOP_TYPE (left) == AOP_CRY)
5456 // c = bit & literal;
5457 if (AOP_TYPE (right) == AOP_LIT)
5461 if (size && sameRegs (AOP (result), AOP (left)))
5464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5469 if (size && (AOP_TYPE (result) == AOP_CRY))
5471 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5474 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5479 emitcode ("clr", "c");
5484 if (AOP_TYPE (right) == AOP_CRY)
5487 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5488 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5493 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5495 emitcode ("rrc", "a");
5496 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5504 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5505 genIfxJump (ifx, "c", left, right, result);
5509 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5510 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5511 if ((AOP_TYPE (right) == AOP_LIT) &&
5512 (AOP_TYPE (result) == AOP_CRY) &&
5513 (AOP_TYPE (left) != AOP_CRY))
5515 int posbit = isLiteralBit (lit);
5520 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5523 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5529 SNPRINTF (buffer, sizeof(buffer),
5530 "acc.%d", posbit & 0x07);
5531 genIfxJump (ifx, buffer, left, right, result);
5534 {// what is this case? just found it in ds390/gen.c
5535 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5542 symbol *tlbl = newiTempLabel (NULL);
5543 int sizel = AOP_SIZE (left);
5545 emitcode ("setb", "c");
5548 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5550 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5552 if ((posbit = isLiteralBit (bytelit)) != 0)
5553 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5556 if (bytelit != 0x0FFL)
5557 emitcode ("anl", "a,%s",
5558 aopGet (AOP (right), offset, FALSE, TRUE));
5559 emitcode ("jnz", "%05d$", tlbl->key + 100);
5564 // bit = left & literal
5567 emitcode ("clr", "c");
5568 emitcode ("", "%05d$:", tlbl->key + 100);
5570 // if(left & literal)
5574 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5576 emitcode ("", "%05d$:", tlbl->key + 100);
5584 /* if left is same as result */
5585 if (sameRegs (AOP (result), AOP (left)))
5587 for (; size--; offset++)
5589 if (AOP_TYPE (right) == AOP_LIT)
5591 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5592 if (bytelit == 0x0FF)
5594 /* dummy read of volatile operand */
5595 if (isOperandVolatile (left, FALSE))
5596 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5600 else if (bytelit == 0)
5602 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5604 else if (IS_AOP_PREG (result))
5606 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5607 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5608 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5611 emitcode ("anl", "%s,%s",
5612 aopGet (AOP (left), offset, FALSE, TRUE),
5613 aopGet (AOP (right), offset, FALSE, FALSE));
5617 if (AOP_TYPE (left) == AOP_ACC)
5618 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5621 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5622 if (IS_AOP_PREG (result))
5624 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5625 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5628 emitcode ("anl", "%s,a",
5629 aopGet (AOP (left), offset, FALSE, TRUE));
5636 // left & result in different registers
5637 if (AOP_TYPE (result) == AOP_CRY)
5640 // if(size), result in bit
5641 // if(!size && ifx), conditional oper: if(left & right)
5642 symbol *tlbl = newiTempLabel (NULL);
5643 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5645 emitcode ("setb", "c");
5648 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5649 emitcode ("anl", "a,%s",
5650 aopGet (AOP (right), offset, FALSE, FALSE));
5652 if (AOP_TYPE(left)==AOP_ACC) {
5653 emitcode("mov", "b,a");
5654 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5655 emitcode("anl", "a,b");
5657 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5658 emitcode ("anl", "a,%s",
5659 aopGet (AOP (left), offset, FALSE, FALSE));
5662 emitcode ("jnz", "%05d$", tlbl->key + 100);
5668 emitcode ("", "%05d$:", tlbl->key + 100);
5672 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5674 emitcode ("", "%05d$:", tlbl->key + 100);
5678 for (; (size--); offset++)
5681 // result = left & right
5682 if (AOP_TYPE (right) == AOP_LIT)
5684 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5685 if (bytelit == 0x0FF)
5687 aopPut (AOP (result),
5688 aopGet (AOP (left), offset, FALSE, FALSE),
5690 isOperandVolatile (result, FALSE));
5693 else if (bytelit == 0)
5695 /* dummy read of volatile operand */
5696 if (isOperandVolatile (left, FALSE))
5697 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5698 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5702 // faster than result <- left, anl result,right
5703 // and better if result is SFR
5704 if (AOP_TYPE (left) == AOP_ACC)
5705 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5708 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5709 emitcode ("anl", "a,%s",
5710 aopGet (AOP (left), offset, FALSE, FALSE));
5712 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5718 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720 freeAsmop (result, NULL, ic, TRUE);
5723 /*-----------------------------------------------------------------*/
5724 /* genOr - code for or */
5725 /*-----------------------------------------------------------------*/
5727 genOr (iCode * ic, iCode * ifx)
5729 operand *left, *right, *result;
5730 int size, offset = 0;
5731 unsigned long lit = 0L;
5734 D(emitcode ("; genOr",""));
5736 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5737 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5738 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5741 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5743 AOP_TYPE (left), AOP_TYPE (right));
5744 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5746 AOP_SIZE (left), AOP_SIZE (right));
5749 /* if left is a literal & right is not then exchange them */
5750 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5751 AOP_NEEDSACC (left))
5753 operand *tmp = right;
5758 /* if result = right then exchange them */
5759 if (sameRegs (AOP (result), AOP (right)))
5761 operand *tmp = right;
5766 /* if right is bit then exchange them */
5767 if (AOP_TYPE (right) == AOP_CRY &&
5768 AOP_TYPE (left) != AOP_CRY)
5770 operand *tmp = right;
5774 if (AOP_TYPE (right) == AOP_LIT)
5775 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5777 size = AOP_SIZE (result);
5781 if (AOP_TYPE (left) == AOP_CRY)
5783 if (AOP_TYPE (right) == AOP_LIT)
5785 // c = bit | literal;
5788 // lit != 0 => result = 1
5789 if (AOP_TYPE (result) == AOP_CRY)
5792 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5794 continueIfTrue (ifx);
5797 emitcode ("setb", "c");
5801 // lit == 0 => result = left
5802 if (size && sameRegs (AOP (result), AOP (left)))
5804 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 if (AOP_TYPE (right) == AOP_CRY)
5812 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5813 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5818 symbol *tlbl = newiTempLabel (NULL);
5819 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5820 emitcode ("setb", "c");
5821 emitcode ("jb", "%s,%05d$",
5822 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5824 emitcode ("jnz", "%05d$", tlbl->key + 100);
5825 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5827 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5833 emitcode ("", "%05d$:", tlbl->key + 100);
5842 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5843 genIfxJump (ifx, "c", left, right, result);
5847 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5848 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5849 if ((AOP_TYPE (right) == AOP_LIT) &&
5850 (AOP_TYPE (result) == AOP_CRY) &&
5851 (AOP_TYPE (left) != AOP_CRY))
5857 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5859 continueIfTrue (ifx);
5864 // lit = 0, result = boolean(left)
5866 emitcode ("setb", "c");
5870 symbol *tlbl = newiTempLabel (NULL);
5871 emitcode ("jnz", "%05d$", tlbl->key + 100);
5873 emitcode ("", "%05d$:", tlbl->key + 100);
5877 genIfxJump (ifx, "a", left, right, result);
5885 /* if left is same as result */
5886 if (sameRegs (AOP (result), AOP (left)))
5888 for (; size--; offset++)
5890 if (AOP_TYPE (right) == AOP_LIT)
5892 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5895 /* dummy read of volatile operand */
5896 if (isOperandVolatile (left, FALSE))
5897 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5901 else if (bytelit == 0x0FF)
5903 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
5905 else if (IS_AOP_PREG (left))
5907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5908 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5909 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5913 emitcode ("orl", "%s,%s",
5914 aopGet (AOP (left), offset, FALSE, TRUE),
5915 aopGet (AOP (right), offset, FALSE, FALSE));
5920 if (AOP_TYPE (left) == AOP_ACC)
5921 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5924 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5925 if (IS_AOP_PREG (left))
5927 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5928 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5932 emitcode ("orl", "%s,a",
5933 aopGet (AOP (left), offset, FALSE, TRUE));
5941 // left & result in different registers
5942 if (AOP_TYPE (result) == AOP_CRY)
5945 // if(size), result in bit
5946 // if(!size && ifx), conditional oper: if(left | right)
5947 symbol *tlbl = newiTempLabel (NULL);
5948 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5950 emitcode ("setb", "c");
5953 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5954 emitcode ("orl", "a,%s",
5955 aopGet (AOP (right), offset, FALSE, FALSE));
5957 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5958 emitcode ("orl", "a,%s",
5959 aopGet (AOP (left), offset, FALSE, FALSE));
5961 emitcode ("jnz", "%05d$", tlbl->key + 100);
5967 emitcode ("", "%05d$:", tlbl->key + 100);
5971 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5973 emitcode ("", "%05d$:", tlbl->key + 100);
5977 for (; (size--); offset++)
5980 // result = left | right
5981 if (AOP_TYPE (right) == AOP_LIT)
5983 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5986 aopPut (AOP (result),
5987 aopGet (AOP (left), offset, FALSE, FALSE),
5989 isOperandVolatile (result, FALSE));
5992 else if (bytelit == 0x0FF)
5994 /* dummy read of volatile operand */
5995 if (isOperandVolatile (left, FALSE))
5996 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5997 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6001 // faster than result <- left, anl result,right
6002 // and better if result is SFR
6003 if (AOP_TYPE (left) == AOP_ACC)
6004 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6007 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6008 emitcode ("orl", "a,%s",
6009 aopGet (AOP (left), offset, FALSE, FALSE));
6011 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6017 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 freeAsmop (result, NULL, ic, TRUE);
6022 /*-----------------------------------------------------------------*/
6023 /* genXor - code for xclusive or */
6024 /*-----------------------------------------------------------------*/
6026 genXor (iCode * ic, iCode * ifx)
6028 operand *left, *right, *result;
6029 int size, offset = 0;
6030 unsigned long lit = 0L;
6033 D(emitcode ("; genXor",""));
6035 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6036 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6037 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6040 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6042 AOP_TYPE (left), AOP_TYPE (right));
6043 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6045 AOP_SIZE (left), AOP_SIZE (right));
6048 /* if left is a literal & right is not ||
6049 if left needs acc & right does not */
6050 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6051 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6053 operand *tmp = right;
6058 /* if result = right then exchange them */
6059 if (sameRegs (AOP (result), AOP (right)))
6061 operand *tmp = right;
6066 /* if right is bit then exchange them */
6067 if (AOP_TYPE (right) == AOP_CRY &&
6068 AOP_TYPE (left) != AOP_CRY)
6070 operand *tmp = right;
6074 if (AOP_TYPE (right) == AOP_LIT)
6075 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6077 size = AOP_SIZE (result);
6081 if (AOP_TYPE (left) == AOP_CRY)
6083 if (AOP_TYPE (right) == AOP_LIT)
6085 // c = bit & literal;
6088 // lit>>1 != 0 => result = 1
6089 if (AOP_TYPE (result) == AOP_CRY)
6092 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6094 continueIfTrue (ifx);
6097 emitcode ("setb", "c");
6104 // lit == 0, result = left
6105 if (size && sameRegs (AOP (result), AOP (left)))
6107 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6111 // lit == 1, result = not(left)
6112 if (size && sameRegs (AOP (result), AOP (left)))
6114 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6119 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6120 emitcode ("cpl", "c");
6129 symbol *tlbl = newiTempLabel (NULL);
6130 if (AOP_TYPE (right) == AOP_CRY)
6133 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6137 int sizer = AOP_SIZE (right);
6139 // if val>>1 != 0, result = 1
6140 emitcode ("setb", "c");
6143 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6145 // test the msb of the lsb
6146 emitcode ("anl", "a,#0xfe");
6147 emitcode ("jnz", "%05d$", tlbl->key + 100);
6151 emitcode ("rrc", "a");
6153 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6154 emitcode ("cpl", "c");
6155 emitcode ("", "%05d$:", (tlbl->key + 100));
6162 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6163 genIfxJump (ifx, "c", left, right, result);
6167 /* if left is same as result */
6168 if (sameRegs (AOP (result), AOP (left)))
6170 for (; size--; offset++)
6172 if (AOP_TYPE (right) == AOP_LIT)
6174 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6177 /* dummy read of volatile operand */
6178 if (isOperandVolatile (left, FALSE))
6179 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6183 else if (IS_AOP_PREG (left))
6185 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6186 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6187 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6191 emitcode ("xrl", "%s,%s",
6192 aopGet (AOP (left), offset, FALSE, TRUE),
6193 aopGet (AOP (right), offset, FALSE, FALSE));
6198 if (AOP_TYPE (left) == AOP_ACC)
6199 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6202 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6203 if (IS_AOP_PREG (left))
6205 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6206 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6209 emitcode ("xrl", "%s,a",
6210 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_LIT) &&
6230 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6232 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6236 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6237 emitcode ("xrl", "a,%s",
6238 aopGet (AOP (right), offset, FALSE, FALSE));
6240 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6241 emitcode ("xrl", "a,%s",
6242 aopGet (AOP (left), offset, FALSE, FALSE));
6245 emitcode ("jnz", "%05d$", tlbl->key + 100);
6251 emitcode ("", "%05d$:", tlbl->key + 100);
6255 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6259 for (; (size--); offset++)
6262 // result = left & right
6263 if (AOP_TYPE (right) == AOP_LIT)
6265 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6268 aopPut (AOP (result),
6269 aopGet (AOP (left), offset, FALSE, FALSE),
6271 isOperandVolatile (result, FALSE));
6275 // faster than result <- left, anl result,right
6276 // and better if result is SFR
6277 if (AOP_TYPE (left) == AOP_ACC)
6278 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6281 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6282 emitcode ("xrl", "a,%s",
6283 aopGet (AOP (left), offset, FALSE, TRUE));
6285 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6292 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6293 freeAsmop (result, NULL, ic, TRUE);
6296 /*-----------------------------------------------------------------*/
6297 /* genInline - write the inline code out */
6298 /*-----------------------------------------------------------------*/
6300 genInline (iCode * ic)
6302 char *buffer, *bp, *bp1;
6304 D(emitcode ("; genInline",""));
6306 _G.inLine += (!options.asmpeep);
6308 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6309 strcpy (buffer, IC_INLINE (ic));
6311 /* emit each line as a code */
6336 /* emitcode("",buffer); */
6337 _G.inLine -= (!options.asmpeep);
6340 /*-----------------------------------------------------------------*/
6341 /* genRRC - rotate right with carry */
6342 /*-----------------------------------------------------------------*/
6346 operand *left, *result;
6347 int size, offset = 0;
6350 D(emitcode ("; genRRC",""));
6352 /* rotate right with carry */
6353 left = IC_LEFT (ic);
6354 result = IC_RESULT (ic);
6355 aopOp (left, ic, FALSE);
6356 aopOp (result, ic, FALSE);
6358 /* move it to the result */
6359 size = AOP_SIZE (result);
6361 if (size == 1) { /* special case for 1 byte */
6362 l = aopGet (AOP (left), offset, FALSE, FALSE);
6364 emitcode ("rr", "a");
6370 l = aopGet (AOP (left), offset, FALSE, FALSE);
6372 emitcode ("rrc", "a");
6373 if (AOP_SIZE (result) > 1)
6374 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6376 /* now we need to put the carry into the
6377 highest order byte of the result */
6378 if (AOP_SIZE (result) > 1)
6380 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6383 emitcode ("mov", "acc.7,c");
6385 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6386 freeAsmop (left, NULL, ic, TRUE);
6387 freeAsmop (result, NULL, ic, TRUE);
6390 /*-----------------------------------------------------------------*/
6391 /* genRLC - generate code for rotate left with carry */
6392 /*-----------------------------------------------------------------*/
6396 operand *left, *result;
6397 int size, offset = 0;
6400 D(emitcode ("; genRLC",""));
6402 /* rotate right with carry */
6403 left = IC_LEFT (ic);
6404 result = IC_RESULT (ic);
6405 aopOp (left, ic, FALSE);
6406 aopOp (result, ic, FALSE);
6408 /* move it to the result */
6409 size = AOP_SIZE (result);
6413 l = aopGet (AOP (left), offset, FALSE, FALSE);
6415 if (size == 0) { /* special case for 1 byte */
6419 emitcode ("add", "a,acc");
6420 if (AOP_SIZE (result) > 1)
6421 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6424 l = aopGet (AOP (left), offset, FALSE, FALSE);
6426 emitcode ("rlc", "a");
6427 if (AOP_SIZE (result) > 1)
6428 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6431 /* now we need to put the carry into the
6432 highest order byte of the result */
6433 if (AOP_SIZE (result) > 1)
6435 l = aopGet (AOP (result), 0, FALSE, FALSE);
6438 emitcode ("mov", "acc.0,c");
6440 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6441 freeAsmop (left, NULL, ic, TRUE);
6442 freeAsmop (result, NULL, ic, TRUE);
6445 /*-----------------------------------------------------------------*/
6446 /* genGetHbit - generates code get highest order bit */
6447 /*-----------------------------------------------------------------*/
6449 genGetHbit (iCode * ic)
6451 operand *left, *result;
6453 D(emitcode ("; genGetHbit",""));
6455 left = IC_LEFT (ic);
6456 result = IC_RESULT (ic);
6457 aopOp (left, ic, FALSE);
6458 aopOp (result, ic, FALSE);
6460 /* get the highest order byte into a */
6461 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6462 if (AOP_TYPE (result) == AOP_CRY)
6464 emitcode ("rlc", "a");
6469 emitcode ("rl", "a");
6470 emitcode ("anl", "a,#0x01");
6475 freeAsmop (left, NULL, ic, TRUE);
6476 freeAsmop (result, NULL, ic, TRUE);
6479 /*-----------------------------------------------------------------*/
6480 /* genSwap - generates code to swap nibbles or bytes */
6481 /*-----------------------------------------------------------------*/
6483 genSwap (iCode * ic)
6485 operand *left, *result;
6487 D(emitcode ("; genSwap",""));
6489 left = IC_LEFT (ic);
6490 result = IC_RESULT (ic);
6491 aopOp (left, ic, FALSE);
6492 aopOp (result, ic, FALSE);
6494 switch (AOP_SIZE (left))
6496 case 1: /* swap nibbles in byte */
6497 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6498 emitcode ("swap", "a");
6499 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6501 case 2: /* swap bytes in word */
6502 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6504 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6505 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6506 0, isOperandVolatile (result, FALSE));
6507 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6509 else if (operandsEqu (left, result))
6512 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6513 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6515 emitcode ("mov", "b,a");
6518 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6519 0, isOperandVolatile (result, FALSE));
6520 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6524 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6525 0, isOperandVolatile (result, FALSE));
6526 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6527 1, isOperandVolatile (result, FALSE));
6531 wassertl(FALSE, "unsupported SWAP operand size");
6534 freeAsmop (left, NULL, ic, TRUE);
6535 freeAsmop (result, NULL, ic, TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* AccRol - rotate left accumulator by known count */
6541 /*-----------------------------------------------------------------*/
6543 AccRol (int shCount)
6545 shCount &= 0x0007; // shCount : 0..7
6552 emitcode ("rl", "a");
6555 emitcode ("rl", "a");
6556 emitcode ("rl", "a");
6559 emitcode ("swap", "a");
6560 emitcode ("rr", "a");
6563 emitcode ("swap", "a");
6566 emitcode ("swap", "a");
6567 emitcode ("rl", "a");
6570 emitcode ("rr", "a");
6571 emitcode ("rr", "a");
6574 emitcode ("rr", "a");
6579 /*-----------------------------------------------------------------*/
6580 /* AccLsh - left shift accumulator by known count */
6581 /*-----------------------------------------------------------------*/
6583 AccLsh (int shCount)
6588 emitcode ("add", "a,acc");
6589 else if (shCount == 2)
6591 emitcode ("add", "a,acc");
6592 emitcode ("add", "a,acc");
6596 /* rotate left accumulator */
6598 /* and kill the lower order bits */
6599 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6604 /*-----------------------------------------------------------------*/
6605 /* AccRsh - right shift accumulator by known count */
6606 /*-----------------------------------------------------------------*/
6608 AccRsh (int shCount)
6615 emitcode ("rrc", "a");
6619 /* rotate right accumulator */
6620 AccRol (8 - shCount);
6621 /* and kill the higher order bits */
6622 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6627 /*-----------------------------------------------------------------*/
6628 /* AccSRsh - signed right shift accumulator by known count */
6629 /*-----------------------------------------------------------------*/
6631 AccSRsh (int shCount)
6638 emitcode ("mov", "c,acc.7");
6639 emitcode ("rrc", "a");
6641 else if (shCount == 2)
6643 emitcode ("mov", "c,acc.7");
6644 emitcode ("rrc", "a");
6645 emitcode ("mov", "c,acc.7");
6646 emitcode ("rrc", "a");
6650 tlbl = newiTempLabel (NULL);
6651 /* rotate right accumulator */
6652 AccRol (8 - shCount);
6653 /* and kill the higher order bits */
6654 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6655 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6656 emitcode ("orl", "a,#0x%02x",
6657 (unsigned char) ~SRMask[shCount]);
6658 emitcode ("", "%05d$:", tlbl->key + 100);
6663 /*-----------------------------------------------------------------*/
6664 /* shiftR1Left2Result - shift right one byte from left to result */
6665 /*-----------------------------------------------------------------*/
6667 shiftR1Left2Result (operand * left, int offl,
6668 operand * result, int offr,
6669 int shCount, int sign)
6671 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6672 /* shift right accumulator */
6677 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6680 /*-----------------------------------------------------------------*/
6681 /* shiftL1Left2Result - shift left one byte from left to result */
6682 /*-----------------------------------------------------------------*/
6684 shiftL1Left2Result (operand * left, int offl,
6685 operand * result, int offr, int shCount)
6688 l = aopGet (AOP (left), offl, FALSE, FALSE);
6690 /* shift left accumulator */
6692 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6695 /*-----------------------------------------------------------------*/
6696 /* movLeft2Result - move byte from left to result */
6697 /*-----------------------------------------------------------------*/
6699 movLeft2Result (operand * left, int offl,
6700 operand * result, int offr, int sign)
6703 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6705 l = aopGet (AOP (left), offl, FALSE, FALSE);
6707 if (*l == '@' && (IS_AOP_PREG (result)))
6709 emitcode ("mov", "a,%s", l);
6710 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6715 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6718 /* MSB sign in acc.7 ! */
6719 if (getDataSize (left) == offl + 1)
6721 emitcode ("mov", "a,%s", l);
6722 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6729 /*-----------------------------------------------------------------*/
6730 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6731 /*-----------------------------------------------------------------*/
6735 emitcode ("rrc", "a");
6736 emitcode ("xch", "a,%s", x);
6737 emitcode ("rrc", "a");
6738 emitcode ("xch", "a,%s", x);
6741 /*-----------------------------------------------------------------*/
6742 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6743 /*-----------------------------------------------------------------*/
6747 emitcode ("xch", "a,%s", x);
6748 emitcode ("rlc", "a");
6749 emitcode ("xch", "a,%s", x);
6750 emitcode ("rlc", "a");
6753 /*-----------------------------------------------------------------*/
6754 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6755 /*-----------------------------------------------------------------*/
6759 emitcode ("xch", "a,%s", x);
6760 emitcode ("add", "a,acc");
6761 emitcode ("xch", "a,%s", x);
6762 emitcode ("rlc", "a");
6765 /*-----------------------------------------------------------------*/
6766 /* AccAXLsh - left shift a:x by known count (0..7) */
6767 /*-----------------------------------------------------------------*/
6769 AccAXLsh (char *x, int shCount)
6784 case 5: // AAAAABBB:CCCCCDDD
6786 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6788 emitcode ("anl", "a,#0x%02x",
6789 SLMask[shCount]); // BBB00000:CCCCCDDD
6791 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6793 AccRol (shCount); // DDDCCCCC:BBB00000
6795 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6797 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6799 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6801 emitcode ("anl", "a,#0x%02x",
6802 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6804 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6806 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6809 case 6: // AAAAAABB:CCCCCCDD
6810 emitcode ("anl", "a,#0x%02x",
6811 SRMask[shCount]); // 000000BB:CCCCCCDD
6812 emitcode ("mov", "c,acc.0"); // c = B
6813 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6815 AccAXRrl1 (x); // BCCCCCCD:D000000B
6816 AccAXRrl1 (x); // BBCCCCCC:DD000000
6818 emitcode("rrc","a");
6819 emitcode("xch","a,%s", x);
6820 emitcode("rrc","a");
6821 emitcode("mov","c,acc.0"); //<< get correct bit
6822 emitcode("xch","a,%s", x);
6824 emitcode("rrc","a");
6825 emitcode("xch","a,%s", x);
6826 emitcode("rrc","a");
6827 emitcode("xch","a,%s", x);
6830 case 7: // a:x <<= 7
6832 emitcode ("anl", "a,#0x%02x",
6833 SRMask[shCount]); // 0000000B:CCCCCCCD
6835 emitcode ("mov", "c,acc.0"); // c = B
6837 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6839 AccAXRrl1 (x); // BCCCCCCC:D0000000
6847 /*-----------------------------------------------------------------*/
6848 /* AccAXRsh - right shift a:x known count (0..7) */
6849 /*-----------------------------------------------------------------*/
6851 AccAXRsh (char *x, int shCount)
6859 AccAXRrl1 (x); // 0->a:x
6864 AccAXRrl1 (x); // 0->a:x
6867 AccAXRrl1 (x); // 0->a:x
6872 case 5: // AAAAABBB:CCCCCDDD = a:x
6874 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6876 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6878 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6880 emitcode ("anl", "a,#0x%02x",
6881 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6883 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6885 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6887 emitcode ("anl", "a,#0x%02x",
6888 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6890 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6892 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6894 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6897 case 6: // AABBBBBB:CCDDDDDD
6899 emitcode ("mov", "c,acc.7");
6900 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6902 emitcode ("mov", "c,acc.7");
6903 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6905 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6907 emitcode ("anl", "a,#0x%02x",
6908 SRMask[shCount]); // 000000AA:BBBBBBCC
6911 case 7: // ABBBBBBB:CDDDDDDD
6913 emitcode ("mov", "c,acc.7"); // c = A
6915 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6917 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6919 emitcode ("anl", "a,#0x%02x",
6920 SRMask[shCount]); // 0000000A:BBBBBBBC
6928 /*-----------------------------------------------------------------*/
6929 /* AccAXRshS - right shift signed a:x known count (0..7) */
6930 /*-----------------------------------------------------------------*/
6932 AccAXRshS (char *x, int shCount)
6940 emitcode ("mov", "c,acc.7");
6941 AccAXRrl1 (x); // s->a:x
6945 emitcode ("mov", "c,acc.7");
6946 AccAXRrl1 (x); // s->a:x
6948 emitcode ("mov", "c,acc.7");
6949 AccAXRrl1 (x); // s->a:x
6954 case 5: // AAAAABBB:CCCCCDDD = a:x
6956 tlbl = newiTempLabel (NULL);
6957 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6959 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6961 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6963 emitcode ("anl", "a,#0x%02x",
6964 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6966 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6968 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6970 emitcode ("anl", "a,#0x%02x",
6971 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6973 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6975 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6977 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6979 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6980 emitcode ("orl", "a,#0x%02x",
6981 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6983 emitcode ("", "%05d$:", tlbl->key + 100);
6984 break; // SSSSAAAA:BBBCCCCC
6986 case 6: // AABBBBBB:CCDDDDDD
6988 tlbl = newiTempLabel (NULL);
6989 emitcode ("mov", "c,acc.7");
6990 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6992 emitcode ("mov", "c,acc.7");
6993 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6995 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6997 emitcode ("anl", "a,#0x%02x",
6998 SRMask[shCount]); // 000000AA:BBBBBBCC
7000 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7001 emitcode ("orl", "a,#0x%02x",
7002 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7004 emitcode ("", "%05d$:", tlbl->key + 100);
7006 case 7: // ABBBBBBB:CDDDDDDD
7008 tlbl = newiTempLabel (NULL);
7009 emitcode ("mov", "c,acc.7"); // c = A
7011 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7013 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7015 emitcode ("anl", "a,#0x%02x",
7016 SRMask[shCount]); // 0000000A:BBBBBBBC
7018 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7019 emitcode ("orl", "a,#0x%02x",
7020 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7022 emitcode ("", "%05d$:", tlbl->key + 100);
7029 /*-----------------------------------------------------------------*/
7030 /* shiftL2Left2Result - shift left two bytes from left to result */
7031 /*-----------------------------------------------------------------*/
7033 shiftL2Left2Result (operand * left, int offl,
7034 operand * result, int offr, int shCount)
7036 if (sameRegs (AOP (result), AOP (left)) &&
7037 ((offl + MSB16) == offr))
7039 /* don't crash result[offr] */
7040 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7041 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7045 movLeft2Result (left, offl, result, offr, 0);
7046 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7048 /* ax << shCount (x = lsb(result)) */
7049 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7050 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7054 /*-----------------------------------------------------------------*/
7055 /* shiftR2Left2Result - shift right two bytes from left to result */
7056 /*-----------------------------------------------------------------*/
7058 shiftR2Left2Result (operand * left, int offl,
7059 operand * result, int offr,
7060 int shCount, int sign)
7062 if (sameRegs (AOP (result), AOP (left)) &&
7063 ((offl + MSB16) == offr))
7065 /* don't crash result[offr] */
7066 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7067 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7071 movLeft2Result (left, offl, result, offr, 0);
7072 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7074 /* a:x >> shCount (x = lsb(result)) */
7076 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7078 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7079 if (getDataSize (result) > 1)
7080 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7083 /*-----------------------------------------------------------------*/
7084 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7085 /*-----------------------------------------------------------------*/
7087 shiftLLeftOrResult (operand * left, int offl,
7088 operand * result, int offr, int shCount)
7090 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7091 /* shift left accumulator */
7093 /* or with result */
7094 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7095 /* back to result */
7096 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7099 /*-----------------------------------------------------------------*/
7100 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7101 /*-----------------------------------------------------------------*/
7103 shiftRLeftOrResult (operand * left, int offl,
7104 operand * result, int offr, int shCount)
7106 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7107 /* shift right accumulator */
7109 /* or with result */
7110 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7111 /* back to result */
7112 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7115 /*-----------------------------------------------------------------*/
7116 /* genlshOne - left shift a one byte quantity by known count */
7117 /*-----------------------------------------------------------------*/
7119 genlshOne (operand * result, operand * left, int shCount)
7121 D(emitcode ("; genlshOne",""));
7123 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7126 /*-----------------------------------------------------------------*/
7127 /* genlshTwo - left shift two bytes by known amount != 0 */
7128 /*-----------------------------------------------------------------*/
7130 genlshTwo (operand * result, operand * left, int shCount)
7134 D(emitcode ("; genlshTwo",""));
7136 size = getDataSize (result);
7138 /* if shCount >= 8 */
7146 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7148 movLeft2Result (left, LSB, result, MSB16, 0);
7150 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7153 /* 1 <= shCount <= 7 */
7157 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7159 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7163 /*-----------------------------------------------------------------*/
7164 /* shiftLLong - shift left one long from left to result */
7165 /* offl = LSB or MSB16 */
7166 /*-----------------------------------------------------------------*/
7168 shiftLLong (operand * left, operand * result, int offr)
7171 int size = AOP_SIZE (result);
7173 if (size >= LSB + offr)
7175 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7177 emitcode ("add", "a,acc");
7178 if (sameRegs (AOP (left), AOP (result)) &&
7179 size >= MSB16 + offr && offr != LSB)
7180 emitcode ("xch", "a,%s",
7181 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7183 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7186 if (size >= MSB16 + offr)
7188 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7190 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7193 emitcode ("rlc", "a");
7194 if (sameRegs (AOP (left), AOP (result)) &&
7195 size >= MSB24 + offr && offr != LSB)
7196 emitcode ("xch", "a,%s",
7197 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7199 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7202 if (size >= MSB24 + offr)
7204 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7206 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7209 emitcode ("rlc", "a");
7210 if (sameRegs (AOP (left), AOP (result)) &&
7211 size >= MSB32 + offr && offr != LSB)
7212 emitcode ("xch", "a,%s",
7213 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7215 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7218 if (size > MSB32 + offr)
7220 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7222 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7225 emitcode ("rlc", "a");
7226 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7229 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7232 /*-----------------------------------------------------------------*/
7233 /* genlshFour - shift four byte by a known amount != 0 */
7234 /*-----------------------------------------------------------------*/
7236 genlshFour (operand * result, operand * left, int shCount)
7240 D(emitcode ("; genlshFour",""));
7242 size = AOP_SIZE (result);
7244 /* if shifting more that 3 bytes */
7249 /* lowest order of left goes to the highest
7250 order of the destination */
7251 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7253 movLeft2Result (left, LSB, result, MSB32, 0);
7254 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7255 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7256 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7260 /* more than two bytes */
7261 else if (shCount >= 16)
7263 /* lower order two bytes goes to higher order two bytes */
7265 /* if some more remaining */
7267 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7270 movLeft2Result (left, MSB16, result, MSB32, 0);
7271 movLeft2Result (left, LSB, result, MSB24, 0);
7273 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7274 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7278 /* if more than 1 byte */
7279 else if (shCount >= 8)
7281 /* lower order three bytes goes to higher order three bytes */
7286 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7288 movLeft2Result (left, LSB, result, MSB16, 0);
7294 movLeft2Result (left, MSB24, result, MSB32, 0);
7295 movLeft2Result (left, MSB16, result, MSB24, 0);
7296 movLeft2Result (left, LSB, result, MSB16, 0);
7297 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7299 else if (shCount == 1)
7300 shiftLLong (left, result, MSB16);
7303 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7304 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7305 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7306 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7311 /* 1 <= shCount <= 7 */
7312 else if (shCount <= 2)
7314 shiftLLong (left, result, LSB);
7316 shiftLLong (result, result, LSB);
7318 /* 3 <= shCount <= 7, optimize */
7321 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7322 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7323 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7327 /*-----------------------------------------------------------------*/
7328 /* genLeftShiftLiteral - left shifting by known count */
7329 /*-----------------------------------------------------------------*/
7331 genLeftShiftLiteral (operand * left,
7336 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7339 D(emitcode ("; genLeftShiftLiteral",""));
7341 freeAsmop (right, NULL, ic, TRUE);
7343 aopOp (left, ic, FALSE);
7344 aopOp (result, ic, FALSE);
7346 size = getSize (operandType (result));
7349 emitcode ("; shift left ", "result %d, left %d", size,
7353 /* I suppose that the left size >= result size */
7358 movLeft2Result (left, size, result, size, 0);
7362 else if (shCount >= (size * 8))
7364 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7370 genlshOne (result, left, shCount);
7374 genlshTwo (result, left, shCount);
7378 genlshFour (result, left, shCount);
7381 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7382 "*** ack! mystery literal shift!\n");
7386 freeAsmop (left, NULL, ic, TRUE);
7387 freeAsmop (result, NULL, ic, TRUE);
7390 /*-----------------------------------------------------------------*/
7391 /* genLeftShift - generates code for left shifting */
7392 /*-----------------------------------------------------------------*/
7394 genLeftShift (iCode * ic)
7396 operand *left, *right, *result;
7399 symbol *tlbl, *tlbl1;
7401 D(emitcode ("; genLeftShift",""));
7403 right = IC_RIGHT (ic);
7404 left = IC_LEFT (ic);
7405 result = IC_RESULT (ic);
7407 aopOp (right, ic, FALSE);
7409 /* if the shift count is known then do it
7410 as efficiently as possible */
7411 if (AOP_TYPE (right) == AOP_LIT)
7413 genLeftShiftLiteral (left, right, result, ic);
7417 /* shift count is unknown then we have to form
7418 a loop get the loop count in B : Note: we take
7419 only the lower order byte since shifting
7420 more that 32 bits make no sense anyway, ( the
7421 largest size of an object can be only 32 bits ) */
7423 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7424 emitcode ("inc", "b");
7425 freeAsmop (right, NULL, ic, TRUE);
7426 aopOp (left, ic, FALSE);
7427 aopOp (result, ic, FALSE);
7429 /* now move the left to the result if they are not the
7431 if (!sameRegs (AOP (left), AOP (result)) &&
7432 AOP_SIZE (result) > 1)
7435 size = AOP_SIZE (result);
7439 l = aopGet (AOP (left), offset, FALSE, TRUE);
7440 if (*l == '@' && (IS_AOP_PREG (result)))
7443 emitcode ("mov", "a,%s", l);
7444 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7447 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7452 tlbl = newiTempLabel (NULL);
7453 size = AOP_SIZE (result);
7455 tlbl1 = newiTempLabel (NULL);
7457 /* if it is only one byte then */
7460 symbol *tlbl1 = newiTempLabel (NULL);
7462 l = aopGet (AOP (left), 0, FALSE, FALSE);
7464 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7465 emitcode ("", "%05d$:", tlbl->key + 100);
7466 emitcode ("add", "a,acc");
7467 emitcode ("", "%05d$:", tlbl1->key + 100);
7468 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7469 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7473 reAdjustPreg (AOP (result));
7475 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7476 emitcode ("", "%05d$:", tlbl->key + 100);
7477 l = aopGet (AOP (result), offset, FALSE, FALSE);
7479 emitcode ("add", "a,acc");
7480 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7483 l = aopGet (AOP (result), offset, FALSE, FALSE);
7485 emitcode ("rlc", "a");
7486 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7488 reAdjustPreg (AOP (result));
7490 emitcode ("", "%05d$:", tlbl1->key + 100);
7491 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7493 freeAsmop (left, NULL, ic, TRUE);
7494 freeAsmop (result, NULL, ic, TRUE);
7497 /*-----------------------------------------------------------------*/
7498 /* genrshOne - right shift a one byte quantity by known count */
7499 /*-----------------------------------------------------------------*/
7501 genrshOne (operand * result, operand * left,
7502 int shCount, int sign)
7504 D(emitcode ("; genrshOne",""));
7506 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7509 /*-----------------------------------------------------------------*/
7510 /* genrshTwo - right shift two bytes by known amount != 0 */
7511 /*-----------------------------------------------------------------*/
7513 genrshTwo (operand * result, operand * left,
7514 int shCount, int sign)
7516 D(emitcode ("; genrshTwo",""));
7518 /* if shCount >= 8 */
7523 shiftR1Left2Result (left, MSB16, result, LSB,
7526 movLeft2Result (left, MSB16, result, LSB, sign);
7527 addSign (result, MSB16, sign);
7530 /* 1 <= shCount <= 7 */
7532 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7535 /*-----------------------------------------------------------------*/
7536 /* shiftRLong - shift right one long from left to result */
7537 /* offl = LSB or MSB16 */
7538 /*-----------------------------------------------------------------*/
7540 shiftRLong (operand * left, int offl,
7541 operand * result, int sign)
7543 int isSameRegs=sameRegs(AOP(left),AOP(result));
7545 if (isSameRegs && offl>1) {
7546 // we are in big trouble, but this shouldn't happen
7547 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7550 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7555 emitcode ("rlc", "a");
7556 emitcode ("subb", "a,acc");
7558 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7560 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7561 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7564 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7569 emitcode ("clr", "c");
7571 emitcode ("mov", "c,acc.7");
7574 emitcode ("rrc", "a");
7576 if (isSameRegs && offl==MSB16) {
7577 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7579 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7580 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7583 emitcode ("rrc", "a");
7584 if (isSameRegs && offl==1) {
7585 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7587 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7588 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7590 emitcode ("rrc", "a");
7591 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7595 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7596 emitcode ("rrc", "a");
7597 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7601 /*-----------------------------------------------------------------*/
7602 /* genrshFour - shift four byte by a known amount != 0 */
7603 /*-----------------------------------------------------------------*/
7605 genrshFour (operand * result, operand * left,
7606 int shCount, int sign)
7608 D(emitcode ("; genrshFour",""));
7610 /* if shifting more that 3 bytes */
7615 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7617 movLeft2Result (left, MSB32, result, LSB, sign);
7618 addSign (result, MSB16, sign);
7620 else if (shCount >= 16)
7624 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7627 movLeft2Result (left, MSB24, result, LSB, 0);
7628 movLeft2Result (left, MSB32, result, MSB16, sign);
7630 addSign (result, MSB24, sign);
7632 else if (shCount >= 8)
7636 shiftRLong (left, MSB16, result, sign);
7637 else if (shCount == 0)
7639 movLeft2Result (left, MSB16, result, LSB, 0);
7640 movLeft2Result (left, MSB24, result, MSB16, 0);
7641 movLeft2Result (left, MSB32, result, MSB24, sign);
7642 addSign (result, MSB32, sign);
7646 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7647 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7648 /* the last shift is signed */
7649 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7650 addSign (result, MSB32, sign);
7654 { /* 1 <= shCount <= 7 */
7657 shiftRLong (left, LSB, result, sign);
7659 shiftRLong (result, LSB, result, sign);
7663 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7664 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7665 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7670 /*-----------------------------------------------------------------*/
7671 /* genRightShiftLiteral - right shifting by known count */
7672 /*-----------------------------------------------------------------*/
7674 genRightShiftLiteral (operand * left,
7680 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7683 D(emitcode ("; genRightShiftLiteral",""));
7685 freeAsmop (right, NULL, ic, TRUE);
7687 aopOp (left, ic, FALSE);
7688 aopOp (result, ic, FALSE);
7691 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7695 size = getDataSize (left);
7696 /* test the LEFT size !!! */
7698 /* I suppose that the left size >= result size */
7701 size = getDataSize (result);
7703 movLeft2Result (left, size, result, size, 0);
7706 else if (shCount >= (size * 8))
7709 /* get sign in acc.7 */
7710 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7712 addSign (result, LSB, sign);
7719 genrshOne (result, left, shCount, sign);
7723 genrshTwo (result, left, shCount, sign);
7727 genrshFour (result, left, shCount, sign);
7733 freeAsmop (left, NULL, ic, TRUE);
7734 freeAsmop (result, NULL, ic, TRUE);
7737 /*-----------------------------------------------------------------*/
7738 /* genSignedRightShift - right shift of signed number */
7739 /*-----------------------------------------------------------------*/
7741 genSignedRightShift (iCode * ic)
7743 operand *right, *left, *result;
7746 symbol *tlbl, *tlbl1;
7748 D(emitcode ("; genSignedRightShift",""));
7750 /* we do it the hard way put the shift count in b
7751 and loop thru preserving the sign */
7753 right = IC_RIGHT (ic);
7754 left = IC_LEFT (ic);
7755 result = IC_RESULT (ic);
7757 aopOp (right, ic, FALSE);
7760 if (AOP_TYPE (right) == AOP_LIT)
7762 genRightShiftLiteral (left, right, result, ic, 1);
7765 /* shift count is unknown then we have to form
7766 a loop get the loop count in B : Note: we take
7767 only the lower order byte since shifting
7768 more that 32 bits make no sense anyway, ( the
7769 largest size of an object can be only 32 bits ) */
7771 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7772 emitcode ("inc", "b");
7773 freeAsmop (right, NULL, ic, TRUE);
7774 aopOp (left, ic, FALSE);
7775 aopOp (result, ic, FALSE);
7777 /* now move the left to the result if they are not the
7779 if (!sameRegs (AOP (left), AOP (result)) &&
7780 AOP_SIZE (result) > 1)
7783 size = AOP_SIZE (result);
7787 l = aopGet (AOP (left), offset, FALSE, TRUE);
7788 if (*l == '@' && IS_AOP_PREG (result))
7791 emitcode ("mov", "a,%s", l);
7792 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7795 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7800 /* mov the highest order bit to OVR */
7801 tlbl = newiTempLabel (NULL);
7802 tlbl1 = newiTempLabel (NULL);
7804 size = AOP_SIZE (result);
7806 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7807 emitcode ("rlc", "a");
7808 emitcode ("mov", "ov,c");
7809 /* if it is only one byte then */
7812 l = aopGet (AOP (left), 0, FALSE, FALSE);
7814 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7815 emitcode ("", "%05d$:", tlbl->key + 100);
7816 emitcode ("mov", "c,ov");
7817 emitcode ("rrc", "a");
7818 emitcode ("", "%05d$:", tlbl1->key + 100);
7819 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7820 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7824 reAdjustPreg (AOP (result));
7825 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7826 emitcode ("", "%05d$:", tlbl->key + 100);
7827 emitcode ("mov", "c,ov");
7830 l = aopGet (AOP (result), offset, FALSE, FALSE);
7832 emitcode ("rrc", "a");
7833 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7835 reAdjustPreg (AOP (result));
7836 emitcode ("", "%05d$:", tlbl1->key + 100);
7837 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7840 freeAsmop (left, NULL, ic, TRUE);
7841 freeAsmop (result, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genRightShift - generate code for right shifting */
7846 /*-----------------------------------------------------------------*/
7848 genRightShift (iCode * ic)
7850 operand *right, *left, *result;
7854 symbol *tlbl, *tlbl1;
7856 D(emitcode ("; genRightShift",""));
7858 /* if signed then we do it the hard way preserve the
7859 sign bit moving it inwards */
7860 letype = getSpec (operandType (IC_LEFT (ic)));
7862 if (!SPEC_USIGN (letype))
7864 genSignedRightShift (ic);
7868 /* signed & unsigned types are treated the same : i.e. the
7869 signed is NOT propagated inwards : quoting from the
7870 ANSI - standard : "for E1 >> E2, is equivalent to division
7871 by 2**E2 if unsigned or if it has a non-negative value,
7872 otherwise the result is implementation defined ", MY definition
7873 is that the sign does not get propagated */
7875 right = IC_RIGHT (ic);
7876 left = IC_LEFT (ic);
7877 result = IC_RESULT (ic);
7879 aopOp (right, ic, FALSE);
7881 /* if the shift count is known then do it
7882 as efficiently as possible */
7883 if (AOP_TYPE (right) == AOP_LIT)
7885 genRightShiftLiteral (left, right, result, ic, 0);
7889 /* shift count is unknown then we have to form
7890 a loop get the loop count in B : Note: we take
7891 only the lower order byte since shifting
7892 more that 32 bits make no sense anyway, ( the
7893 largest size of an object can be only 32 bits ) */
7895 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7896 emitcode ("inc", "b");
7897 freeAsmop (right, NULL, ic, TRUE);
7898 aopOp (left, ic, FALSE);
7899 aopOp (result, ic, FALSE);
7901 /* now move the left to the result if they are not the
7903 if (!sameRegs (AOP (left), AOP (result)) &&
7904 AOP_SIZE (result) > 1)
7907 size = AOP_SIZE (result);
7911 l = aopGet (AOP (left), offset, FALSE, TRUE);
7912 if (*l == '@' && IS_AOP_PREG (result))
7915 emitcode ("mov", "a,%s", l);
7916 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7919 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7924 tlbl = newiTempLabel (NULL);
7925 tlbl1 = newiTempLabel (NULL);
7926 size = AOP_SIZE (result);
7929 /* if it is only one byte then */
7932 l = aopGet (AOP (left), 0, FALSE, FALSE);
7934 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7935 emitcode ("", "%05d$:", tlbl->key + 100);
7937 emitcode ("rrc", "a");
7938 emitcode ("", "%05d$:", tlbl1->key + 100);
7939 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7940 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7944 reAdjustPreg (AOP (result));
7945 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7946 emitcode ("", "%05d$:", tlbl->key + 100);
7950 l = aopGet (AOP (result), offset, FALSE, FALSE);
7952 emitcode ("rrc", "a");
7953 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7955 reAdjustPreg (AOP (result));
7957 emitcode ("", "%05d$:", tlbl1->key + 100);
7958 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7961 freeAsmop (left, NULL, ic, TRUE);
7962 freeAsmop (result, NULL, ic, TRUE);
7965 /*-----------------------------------------------------------------*/
7966 /* emitPtrByteGet - emits code to get a byte into A through a */
7967 /* pointer register (R0, R1, or DPTR). The */
7968 /* original value of A can be preserved in B. */
7969 /*-----------------------------------------------------------------*/
7971 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7978 emitcode ("mov", "b,a");
7979 emitcode ("mov", "a,@%s", rname);
7984 emitcode ("mov", "b,a");
7985 emitcode ("movx", "a,@%s", rname);
7990 emitcode ("mov", "b,a");
7991 emitcode ("movx", "a,@dptr");
7996 emitcode ("mov", "b,a");
7997 emitcode ("clr", "a");
7998 emitcode ("movc", "a,@a+dptr");
8004 emitcode ("push", "b");
8005 emitcode ("push", "acc");
8007 emitcode ("lcall", "__gptrget");
8009 emitcode ("pop", "b");
8014 /*-----------------------------------------------------------------*/
8015 /* emitPtrByteSet - emits code to set a byte from src through a */
8016 /* pointer register (R0, R1, or DPTR). */
8017 /*-----------------------------------------------------------------*/
8019 emitPtrByteSet (char *rname, int p_type, char *src)
8028 emitcode ("mov", "@%s,a", rname);
8031 emitcode ("mov", "@%s,%s", rname, src);
8036 emitcode ("movx", "@%s,a", rname);
8041 emitcode ("movx", "@dptr,a");
8046 emitcode ("lcall", "__gptrput");
8051 /*-----------------------------------------------------------------*/
8052 /* genUnpackBits - generates code for unpacking bits */
8053 /*-----------------------------------------------------------------*/
8055 genUnpackBits (operand * result, char *rname, int ptype)
8057 int offset = 0; /* result byte offset */
8058 int rsize; /* result size */
8059 int rlen = 0; /* remaining bitfield length */
8060 sym_link *etype; /* bitfield type information */
8061 int blen; /* bitfield length */
8062 int bstr; /* bitfield starting bit within byte */
8064 D(emitcode ("; genUnpackBits",""));
8066 etype = getSpec (operandType (result));
8067 rsize = getSize (operandType (result));
8068 blen = SPEC_BLEN (etype);
8069 bstr = SPEC_BSTR (etype);
8071 /* If the bitfield length is less than a byte */
8074 emitPtrByteGet (rname, ptype, FALSE);
8076 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8077 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8081 /* Bit field did not fit in a byte. Copy all
8082 but the partial byte at the end. */
8083 for (rlen=blen;rlen>=8;rlen-=8)
8085 emitPtrByteGet (rname, ptype, FALSE);
8086 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8088 emitcode ("inc", "%s", rname);
8091 /* Handle the partial byte at the end */
8094 emitPtrByteGet (rname, ptype, FALSE);
8095 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8096 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8104 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8109 /*-----------------------------------------------------------------*/
8110 /* genDataPointerGet - generates code when ptr offset is known */
8111 /*-----------------------------------------------------------------*/
8113 genDataPointerGet (operand * left,
8119 int size, offset = 0;
8121 D(emitcode ("; genDataPointerGet",""));
8123 aopOp (result, ic, TRUE);
8125 /* get the string representation of the name */
8126 l = aopGet (AOP (left), 0, FALSE, TRUE);
8127 size = AOP_SIZE (result);
8131 sprintf (buffer, "(%s + %d)", l + 1, offset);
8133 sprintf (buffer, "%s", l + 1);
8134 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8137 freeAsmop (left, NULL, ic, TRUE);
8138 freeAsmop (result, NULL, ic, TRUE);
8141 /*-----------------------------------------------------------------*/
8142 /* genNearPointerGet - emitcode for near pointer fetch */
8143 /*-----------------------------------------------------------------*/
8145 genNearPointerGet (operand * left,
8153 sym_link *rtype, *retype;
8154 sym_link *ltype = operandType (left);
8157 D(emitcode ("; genNearPointerGet",""));
8159 rtype = operandType (result);
8160 retype = getSpec (rtype);
8162 aopOp (left, ic, FALSE);
8164 /* if left is rematerialisable and
8165 result is not bitfield variable type and
8166 the left is pointer to data space i.e
8167 lower 128 bytes of space */
8168 if (AOP_TYPE (left) == AOP_IMMD &&
8169 !IS_BITFIELD (retype) &&
8170 DCL_TYPE (ltype) == POINTER)
8172 genDataPointerGet (left, result, ic);
8176 /* if the value is already in a pointer register
8177 then don't need anything more */
8178 if (!AOP_INPREG (AOP (left)))
8180 if (IS_AOP_PREG (left))
8182 // Aha, it is a pointer, just in disguise.
8183 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8186 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8187 __FILE__, __LINE__);
8192 emitcode ("mov", "a%s,%s", rname + 1, rname);
8193 rname++; // skip the '@'.
8198 /* otherwise get a free pointer register */
8200 preg = getFreePtr (ic, &aop, FALSE);
8201 emitcode ("mov", "%s,%s",
8203 aopGet (AOP (left), 0, FALSE, TRUE));
8208 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8210 //aopOp (result, ic, FALSE);
8211 aopOp (result, ic, result?TRUE:FALSE);
8213 /* if bitfield then unpack the bits */
8214 if (IS_BITFIELD (retype))
8215 genUnpackBits (result, rname, POINTER);
8218 /* we have can just get the values */
8219 int size = AOP_SIZE (result);
8224 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8227 emitcode ("mov", "a,@%s", rname);
8228 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8232 sprintf (buffer, "@%s", rname);
8233 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8237 emitcode ("inc", "%s", rname);
8241 /* now some housekeeping stuff */
8242 if (aop) /* we had to allocate for this iCode */
8244 if (pi) { /* post increment present */
8245 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8247 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8251 /* we did not allocate which means left
8252 already in a pointer register, then
8253 if size > 0 && this could be used again
8254 we have to point it back to where it
8256 if ((AOP_SIZE (result) > 1 &&
8257 !OP_SYMBOL (left)->remat &&
8258 (OP_SYMBOL (left)->liveTo > ic->seq ||
8262 int size = AOP_SIZE (result) - 1;
8264 emitcode ("dec", "%s", rname);
8269 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8270 freeAsmop (left, NULL, ic, TRUE);
8271 if (pi) pi->generated = 1;
8274 /*-----------------------------------------------------------------*/
8275 /* genPagedPointerGet - emitcode for paged pointer fetch */
8276 /*-----------------------------------------------------------------*/
8278 genPagedPointerGet (operand * left,
8286 sym_link *rtype, *retype;
8288 D(emitcode ("; genPagedPointerGet",""));
8290 rtype = operandType (result);
8291 retype = getSpec (rtype);
8293 aopOp (left, ic, FALSE);
8295 /* if the value is already in a pointer register
8296 then don't need anything more */
8297 if (!AOP_INPREG (AOP (left)))
8299 /* otherwise get a free pointer register */
8301 preg = getFreePtr (ic, &aop, FALSE);
8302 emitcode ("mov", "%s,%s",
8304 aopGet (AOP (left), 0, FALSE, TRUE));
8308 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8310 aopOp (result, ic, FALSE);
8312 /* if bitfield then unpack the bits */
8313 if (IS_BITFIELD (retype))
8314 genUnpackBits (result, rname, PPOINTER);
8317 /* we have can just get the values */
8318 int size = AOP_SIZE (result);
8324 emitcode ("movx", "a,@%s", rname);
8325 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8330 emitcode ("inc", "%s", rname);
8334 /* now some housekeeping stuff */
8335 if (aop) /* we had to allocate for this iCode */
8337 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8338 freeAsmop (NULL, aop, ic, TRUE);
8342 /* we did not allocate which means left
8343 already in a pointer register, then
8344 if size > 0 && this could be used again
8345 we have to point it back to where it
8347 if ((AOP_SIZE (result) > 1 &&
8348 !OP_SYMBOL (left)->remat &&
8349 (OP_SYMBOL (left)->liveTo > ic->seq ||
8353 int size = AOP_SIZE (result) - 1;
8355 emitcode ("dec", "%s", rname);
8360 freeAsmop (left, NULL, ic, TRUE);
8361 freeAsmop (result, NULL, ic, TRUE);
8362 if (pi) pi->generated = 1;
8366 /*--------------------------------------------------------------------*/
8367 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8368 /*--------------------------------------------------------------------*/
8370 loadDptrFromOperand (operand *op, bool loadBToo)
8372 if (AOP_TYPE (op) != AOP_STR)
8374 /* if this is remateriazable */
8375 if (AOP_TYPE (op) == AOP_IMMD)
8377 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8380 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8381 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8384 wassertl(FALSE, "need pointerCode");
8385 emitcode ("", "; mov b,???");
8386 /* genPointerGet and genPointerSet originally did different
8387 ** things for this case. Both seem wrong.
8388 ** from genPointerGet:
8389 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8390 ** from genPointerSet:
8391 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8396 else if (AOP_TYPE (op) == AOP_DPTR)
8400 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8401 emitcode ("push", "acc");
8402 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8403 emitcode ("push", "acc");
8404 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8405 emitcode ("pop", "dph");
8406 emitcode ("pop", "dpl");
8410 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8411 emitcode ("push", "acc");
8412 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8413 emitcode ("pop", "dpl");
8417 { /* we need to get it byte by byte */
8418 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8419 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8421 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8426 /*-----------------------------------------------------------------*/
8427 /* genFarPointerGet - gget value from far space */
8428 /*-----------------------------------------------------------------*/
8430 genFarPointerGet (operand * left,
8431 operand * result, iCode * ic, iCode * pi)
8434 sym_link *retype = getSpec (operandType (result));
8436 D(emitcode ("; genFarPointerGet",""));
8438 aopOp (left, ic, FALSE);
8439 loadDptrFromOperand (left, FALSE);
8441 /* so dptr now contains the address */
8442 aopOp (result, ic, FALSE);
8444 /* if bit then unpack */
8445 if (IS_BITFIELD (retype))
8446 genUnpackBits (result, "dptr", FPOINTER);
8449 size = AOP_SIZE (result);
8454 emitcode ("movx", "a,@dptr");
8455 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8457 emitcode ("inc", "dptr");
8461 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8462 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8463 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8466 freeAsmop (left, NULL, ic, TRUE);
8467 freeAsmop (result, NULL, ic, TRUE);
8470 /*-----------------------------------------------------------------*/
8471 /* genCodePointerGet - gget value from code space */
8472 /*-----------------------------------------------------------------*/
8474 genCodePointerGet (operand * left,
8475 operand * result, iCode * ic, iCode *pi)
8478 sym_link *retype = getSpec (operandType (result));
8480 D(emitcode ("; genCodePointerGet",""));
8482 aopOp (left, ic, FALSE);
8483 loadDptrFromOperand (left, FALSE);
8485 /* so dptr now contains the address */
8486 aopOp (result, ic, FALSE);
8488 /* if bit then unpack */
8489 if (IS_BITFIELD (retype))
8490 genUnpackBits (result, "dptr", CPOINTER);
8493 size = AOP_SIZE (result);
8500 emitcode ("clr", "a");
8501 emitcode ("movc", "a,@a+dptr");
8502 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8503 emitcode ("inc", "dptr");
8507 emitcode ("mov", "a,#0x%02x", offset);
8508 emitcode ("movc", "a,@a+dptr");
8509 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8514 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8515 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8516 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8519 freeAsmop (left, NULL, ic, TRUE);
8520 freeAsmop (result, NULL, ic, TRUE);
8523 /*-----------------------------------------------------------------*/
8524 /* genGenPointerGet - gget value from generic pointer space */
8525 /*-----------------------------------------------------------------*/
8527 genGenPointerGet (operand * left,
8528 operand * result, iCode * ic, iCode *pi)
8531 sym_link *retype = getSpec (operandType (result));
8533 D(emitcode ("; genGenPointerGet",""));
8535 aopOp (left, ic, FALSE);
8536 loadDptrFromOperand (left, TRUE);
8538 /* so dptr know contains the address */
8539 aopOp (result, ic, FALSE);
8541 /* if bit then unpack */
8542 if (IS_BITFIELD (retype))
8543 genUnpackBits (result, "dptr", GPOINTER);
8546 size = AOP_SIZE (result);
8551 emitcode ("lcall", "__gptrget");
8552 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8554 emitcode ("inc", "dptr");
8558 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8559 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8560 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8563 freeAsmop (left, NULL, ic, TRUE);
8564 freeAsmop (result, NULL, ic, TRUE);
8567 /*-----------------------------------------------------------------*/
8568 /* genPointerGet - generate code for pointer get */
8569 /*-----------------------------------------------------------------*/
8571 genPointerGet (iCode * ic, iCode *pi)
8573 operand *left, *result;
8574 sym_link *type, *etype;
8577 D(emitcode ("; genPointerGet",""));
8579 left = IC_LEFT (ic);
8580 result = IC_RESULT (ic);
8582 /* depending on the type of pointer we need to
8583 move it to the correct pointer register */
8584 type = operandType (left);
8585 etype = getSpec (type);
8586 /* if left is of type of pointer then it is simple */
8587 if (IS_PTR (type) && !IS_FUNC (type->next))
8588 p_type = DCL_TYPE (type);
8591 /* we have to go by the storage class */
8592 p_type = PTR_TYPE (SPEC_OCLS (etype));
8595 /* special case when cast remat */
8596 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8597 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8598 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8599 type = operandType (left);
8600 p_type = DCL_TYPE (type);
8602 /* now that we have the pointer type we assign
8603 the pointer values */
8609 genNearPointerGet (left, result, ic, pi);
8613 genPagedPointerGet (left, result, ic, pi);
8617 genFarPointerGet (left, result, ic, pi);
8621 genCodePointerGet (left, result, ic, pi);
8625 genGenPointerGet (left, result, ic, pi);
8633 /*-----------------------------------------------------------------*/
8634 /* genPackBits - generates code for packed bit storage */
8635 /*-----------------------------------------------------------------*/
8637 genPackBits (sym_link * etype,
8639 char *rname, int p_type)
8641 int offset = 0; /* source byte offset */
8642 int rlen = 0; /* remaining bitfield length */
8643 int blen; /* bitfield length */
8644 int bstr; /* bitfield starting bit within byte */
8645 int litval; /* source literal value (if AOP_LIT) */
8646 unsigned char mask; /* bitmask within current byte */
8648 D(emitcode ("; genPackBits",""));
8650 blen = SPEC_BLEN (etype);
8651 bstr = SPEC_BSTR (etype);
8653 /* If the bitfield length is less than a byte */
8656 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8657 (unsigned char) (0xFF >> (8 - bstr)));
8659 if (AOP_TYPE (right) == AOP_LIT)
8661 /* Case with a bitfield length <8 and literal source
8663 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8665 litval &= (~mask) & 0xff;
8666 emitPtrByteGet (rname, p_type, FALSE);
8667 if ((mask|litval)!=0xff)
8668 emitcode ("anl","a,#0x%02x", mask);
8670 emitcode ("orl","a,#0x%02x", litval);
8674 if ((blen==1) && (p_type!=GPOINTER))
8676 /* Case with a bitfield length == 1 and no generic pointer
8678 if (AOP_TYPE (right) == AOP_CRY)
8679 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8682 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8683 emitcode ("rrc","a");
8685 emitPtrByteGet (rname, p_type, FALSE);
8686 emitcode ("mov","acc.%d,c",bstr);
8690 /* Case with a bitfield length < 8 and arbitrary source
8692 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8693 /* shift and mask source value */
8695 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8697 /* transfer A to B and get next byte */
8698 emitPtrByteGet (rname, p_type, TRUE);
8700 emitcode ("anl", "a,#0x%02x", mask);
8701 emitcode ("orl", "a,b");
8702 if (p_type == GPOINTER)
8703 emitcode ("pop", "b");
8707 emitPtrByteSet (rname, p_type, "a");
8711 /* Bit length is greater than 7 bits. In this case, copy */
8712 /* all except the partial byte at the end */
8713 for (rlen=blen;rlen>=8;rlen-=8)
8715 emitPtrByteSet (rname, p_type,
8716 aopGet (AOP (right), offset++, FALSE, TRUE) );
8718 emitcode ("inc", "%s", rname);
8721 /* If there was a partial byte at the end */
8724 mask = (((unsigned char) -1 << rlen) & 0xff);
8726 if (AOP_TYPE (right) == AOP_LIT)
8728 /* Case with partial byte and literal source
8730 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8731 litval >>= (blen-rlen);
8732 litval &= (~mask) & 0xff;
8733 emitPtrByteGet (rname, p_type, FALSE);
8734 if ((mask|litval)!=0xff)
8735 emitcode ("anl","a,#0x%02x", mask);
8737 emitcode ("orl","a,#0x%02x", litval);
8741 /* Case with partial byte and arbitrary source
8743 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8744 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8746 /* transfer A to B and get next byte */
8747 emitPtrByteGet (rname, p_type, TRUE);
8749 emitcode ("anl", "a,#0x%02x", mask);
8750 emitcode ("orl", "a,b");
8751 if (p_type == GPOINTER)
8752 emitcode ("pop", "b");
8754 emitPtrByteSet (rname, p_type, "a");
8760 /*-----------------------------------------------------------------*/
8761 /* genDataPointerSet - remat pointer to data space */
8762 /*-----------------------------------------------------------------*/
8764 genDataPointerSet (operand * right,
8768 int size, offset = 0;
8769 char *l, buffer[256];
8771 D(emitcode ("; genDataPointerSet",""));
8773 aopOp (right, ic, FALSE);
8775 l = aopGet (AOP (result), 0, FALSE, TRUE);
8776 size = AOP_SIZE (right);
8780 sprintf (buffer, "(%s + %d)", l + 1, offset);
8782 sprintf (buffer, "%s", l + 1);
8783 emitcode ("mov", "%s,%s", buffer,
8784 aopGet (AOP (right), offset++, FALSE, FALSE));
8787 freeAsmop (right, NULL, ic, TRUE);
8788 freeAsmop (result, NULL, ic, TRUE);
8791 /*-----------------------------------------------------------------*/
8792 /* genNearPointerSet - emitcode for near pointer put */
8793 /*-----------------------------------------------------------------*/
8795 genNearPointerSet (operand * right,
8803 sym_link *retype, *letype;
8804 sym_link *ptype = operandType (result);
8806 D(emitcode ("; genNearPointerSet",""));
8808 retype = getSpec (operandType (right));
8809 letype = getSpec (ptype);
8810 aopOp (result, ic, FALSE);
8812 /* if the result is rematerializable &
8813 in data space & not a bit variable */
8814 if (AOP_TYPE (result) == AOP_IMMD &&
8815 DCL_TYPE (ptype) == POINTER &&
8816 !IS_BITVAR (retype) &&
8817 !IS_BITVAR (letype))
8819 genDataPointerSet (right, result, ic);
8823 /* if the value is already in a pointer register
8824 then don't need anything more */
8825 if (!AOP_INPREG (AOP (result)))
8828 //AOP_TYPE (result) == AOP_STK
8832 // Aha, it is a pointer, just in disguise.
8833 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8836 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8837 __FILE__, __LINE__);
8842 emitcode ("mov", "a%s,%s", rname + 1, rname);
8843 rname++; // skip the '@'.
8848 /* otherwise get a free pointer register */
8850 preg = getFreePtr (ic, &aop, FALSE);
8851 emitcode ("mov", "%s,%s",
8853 aopGet (AOP (result), 0, FALSE, TRUE));
8859 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8862 aopOp (right, ic, FALSE);
8864 /* if bitfield then unpack the bits */
8865 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8866 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8869 /* we have can just get the values */
8870 int size = AOP_SIZE (right);
8875 l = aopGet (AOP (right), offset, FALSE, TRUE);
8879 emitcode ("mov", "@%s,a", rname);
8882 emitcode ("mov", "@%s,%s", rname, l);
8884 emitcode ("inc", "%s", rname);
8889 /* now some housekeeping stuff */
8890 if (aop) /* we had to allocate for this iCode */
8893 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8894 freeAsmop (NULL, aop, ic, TRUE);
8898 /* we did not allocate which means left
8899 already in a pointer register, then
8900 if size > 0 && this could be used again
8901 we have to point it back to where it
8903 if ((AOP_SIZE (right) > 1 &&
8904 !OP_SYMBOL (result)->remat &&
8905 (OP_SYMBOL (result)->liveTo > ic->seq ||
8909 int size = AOP_SIZE (right) - 1;
8911 emitcode ("dec", "%s", rname);
8916 if (pi) pi->generated = 1;
8917 freeAsmop (result, NULL, ic, TRUE);
8918 freeAsmop (right, NULL, ic, TRUE);
8921 /*-----------------------------------------------------------------*/
8922 /* genPagedPointerSet - emitcode for Paged pointer put */
8923 /*-----------------------------------------------------------------*/
8925 genPagedPointerSet (operand * right,
8933 sym_link *retype, *letype;
8935 D(emitcode ("; genPagedPointerSet",""));
8937 retype = getSpec (operandType (right));
8938 letype = getSpec (operandType (result));
8940 aopOp (result, ic, FALSE);
8942 /* if the value is already in a pointer register
8943 then don't need anything more */
8944 if (!AOP_INPREG (AOP (result)))
8946 /* otherwise get a free pointer register */
8948 preg = getFreePtr (ic, &aop, FALSE);
8949 emitcode ("mov", "%s,%s",
8951 aopGet (AOP (result), 0, FALSE, TRUE));
8955 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8957 aopOp (right, ic, FALSE);
8959 /* if bitfield then unpack the bits */
8960 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8961 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8964 /* we have can just get the values */
8965 int size = AOP_SIZE (right);
8970 l = aopGet (AOP (right), offset, FALSE, TRUE);
8973 emitcode ("movx", "@%s,a", rname);
8976 emitcode ("inc", "%s", rname);
8982 /* now some housekeeping stuff */
8983 if (aop) /* we had to allocate for this iCode */
8986 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8987 freeAsmop (NULL, aop, ic, TRUE);
8991 /* we did not allocate which means left
8992 already in a pointer register, then
8993 if size > 0 && this could be used again
8994 we have to point it back to where it
8996 if (AOP_SIZE (right) > 1 &&
8997 !OP_SYMBOL (result)->remat &&
8998 (OP_SYMBOL (result)->liveTo > ic->seq ||
9001 int size = AOP_SIZE (right) - 1;
9003 emitcode ("dec", "%s", rname);
9008 if (pi) pi->generated = 1;
9009 freeAsmop (result, NULL, ic, TRUE);
9010 freeAsmop (right, NULL, ic, TRUE);
9015 /*-----------------------------------------------------------------*/
9016 /* genFarPointerSet - set value from far space */
9017 /*-----------------------------------------------------------------*/
9019 genFarPointerSet (operand * right,
9020 operand * result, iCode * ic, iCode * pi)
9023 sym_link *retype = getSpec (operandType (right));
9024 sym_link *letype = getSpec (operandType (result));
9026 D(emitcode ("; genFarPointerSet",""));
9028 aopOp (result, ic, FALSE);
9029 loadDptrFromOperand (result, FALSE);
9031 /* so dptr know contains the address */
9032 aopOp (right, ic, FALSE);
9034 /* if bit then unpack */
9035 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9036 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9039 size = AOP_SIZE (right);
9044 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9046 emitcode ("movx", "@dptr,a");
9048 emitcode ("inc", "dptr");
9051 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9052 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9053 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9056 freeAsmop (result, NULL, ic, TRUE);
9057 freeAsmop (right, NULL, ic, TRUE);
9060 /*-----------------------------------------------------------------*/
9061 /* genGenPointerSet - set value from generic pointer space */
9062 /*-----------------------------------------------------------------*/
9064 genGenPointerSet (operand * right,
9065 operand * result, iCode * ic, iCode * pi)
9068 sym_link *retype = getSpec (operandType (right));
9069 sym_link *letype = getSpec (operandType (result));
9071 D(emitcode ("; genGenPointerSet",""));
9073 aopOp (result, ic, FALSE);
9074 loadDptrFromOperand (result, TRUE);
9076 /* so dptr know contains the address */
9077 aopOp (right, ic, FALSE);
9079 /* if bit then unpack */
9080 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9081 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9084 size = AOP_SIZE (right);
9089 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9091 emitcode ("lcall", "__gptrput");
9093 emitcode ("inc", "dptr");
9097 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9098 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9099 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9102 freeAsmop (result, NULL, ic, TRUE);
9103 freeAsmop (right, NULL, ic, TRUE);
9106 /*-----------------------------------------------------------------*/
9107 /* genPointerSet - stores the value into a pointer location */
9108 /*-----------------------------------------------------------------*/
9110 genPointerSet (iCode * ic, iCode *pi)
9112 operand *right, *result;
9113 sym_link *type, *etype;
9116 D(emitcode ("; genPointerSet",""));
9118 right = IC_RIGHT (ic);
9119 result = IC_RESULT (ic);
9121 /* depending on the type of pointer we need to
9122 move it to the correct pointer register */
9123 type = operandType (result);
9124 etype = getSpec (type);
9125 /* if left is of type of pointer then it is simple */
9126 if (IS_PTR (type) && !IS_FUNC (type->next))
9128 p_type = DCL_TYPE (type);
9132 /* we have to go by the storage class */
9133 p_type = PTR_TYPE (SPEC_OCLS (etype));
9136 /* special case when cast remat */
9137 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9138 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9139 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9140 type = operandType (result);
9141 p_type = DCL_TYPE (type);
9143 /* now that we have the pointer type we assign
9144 the pointer values */
9150 genNearPointerSet (right, result, ic, pi);
9154 genPagedPointerSet (right, result, ic, pi);
9158 genFarPointerSet (right, result, ic, pi);
9162 genGenPointerSet (right, result, ic, pi);
9166 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9167 "genPointerSet: illegal pointer type");
9172 /*-----------------------------------------------------------------*/
9173 /* genIfx - generate code for Ifx statement */
9174 /*-----------------------------------------------------------------*/
9176 genIfx (iCode * ic, iCode * popIc)
9178 operand *cond = IC_COND (ic);
9181 D(emitcode ("; genIfx",""));
9183 aopOp (cond, ic, FALSE);
9185 /* get the value into acc */
9186 if (AOP_TYPE (cond) != AOP_CRY)
9190 /* the result is now in the accumulator */
9191 freeAsmop (cond, NULL, ic, TRUE);
9193 /* if there was something to be popped then do it */
9197 /* if the condition is a bit variable */
9198 if (isbit && IS_ITEMP (cond) &&
9200 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9201 else if (isbit && !IS_ITEMP (cond))
9202 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9204 genIfxJump (ic, "a", NULL, NULL, NULL);
9209 /*-----------------------------------------------------------------*/
9210 /* genAddrOf - generates code for address of */
9211 /*-----------------------------------------------------------------*/
9213 genAddrOf (iCode * ic)
9215 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9218 D(emitcode ("; genAddrOf",""));
9220 aopOp (IC_RESULT (ic), ic, FALSE);
9222 /* if the operand is on the stack then we
9223 need to get the stack offset of this
9227 /* if it has an offset then we need to compute
9231 emitcode ("mov", "a,_bp");
9232 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9233 ((char) (sym->stack - _G.nRegsSaved)) :
9234 ((char) sym->stack)) & 0xff);
9235 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9239 /* we can just move _bp */
9240 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9242 /* fill the result with zero */
9243 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9248 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9254 /* object not on stack then we need the name */
9255 size = AOP_SIZE (IC_RESULT (ic));
9260 char s[SDCC_NAME_MAX];
9262 sprintf (s, "#(%s >> %d)",
9266 sprintf (s, "#%s", sym->rname);
9267 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9271 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9275 /*-----------------------------------------------------------------*/
9276 /* genFarFarAssign - assignment when both are in far space */
9277 /*-----------------------------------------------------------------*/
9279 genFarFarAssign (operand * result, operand * right, iCode * ic)
9281 int size = AOP_SIZE (right);
9285 D(emitcode ("; genFarFarAssign",""));
9287 /* first push the right side on to the stack */
9290 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9292 emitcode ("push", "acc");
9295 freeAsmop (right, NULL, ic, FALSE);
9296 /* now assign DPTR to result */
9297 aopOp (result, ic, FALSE);
9298 size = AOP_SIZE (result);
9301 emitcode ("pop", "acc");
9302 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9304 freeAsmop (result, NULL, ic, FALSE);
9308 /*-----------------------------------------------------------------*/
9309 /* genAssign - generate code for assignment */
9310 /*-----------------------------------------------------------------*/
9312 genAssign (iCode * ic)
9314 operand *result, *right;
9316 unsigned long lit = 0L;
9318 D(emitcode("; genAssign",""));
9320 result = IC_RESULT (ic);
9321 right = IC_RIGHT (ic);
9323 /* if they are the same */
9324 if (operandsEqu (result, right) &&
9325 !isOperandVolatile (result, FALSE) &&
9326 !isOperandVolatile (right, FALSE))
9329 aopOp (right, ic, FALSE);
9331 /* special case both in far space */
9332 if (AOP_TYPE (right) == AOP_DPTR &&
9333 IS_TRUE_SYMOP (result) &&
9334 isOperandInFarSpace (result))
9337 genFarFarAssign (result, right, ic);
9341 aopOp (result, ic, TRUE);
9343 /* if they are the same registers */
9344 if (sameRegs (AOP (right), AOP (result)) &&
9345 !isOperandVolatile (result, FALSE) &&
9346 !isOperandVolatile (right, FALSE))
9349 /* if the result is a bit */
9350 if (AOP_TYPE (result) == AOP_CRY)
9353 /* if the right size is a literal then
9354 we know what the value is */
9355 if (AOP_TYPE (right) == AOP_LIT)
9357 if (((int) operandLitValue (right)))
9358 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9360 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9364 /* the right is also a bit variable */
9365 if (AOP_TYPE (right) == AOP_CRY)
9367 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9368 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9374 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9378 /* bit variables done */
9380 size = AOP_SIZE (result);
9382 if (AOP_TYPE (right) == AOP_LIT)
9383 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9385 (AOP_TYPE (result) != AOP_REG) &&
9386 (AOP_TYPE (right) == AOP_LIT) &&
9387 !IS_FLOAT (operandType (right)) &&
9390 emitcode ("clr", "a");
9393 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9394 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9396 aopPut (AOP (result),
9397 aopGet (AOP (right), size, FALSE, FALSE),
9399 isOperandVolatile (result, FALSE));
9406 aopPut (AOP (result),
9407 aopGet (AOP (right), offset, FALSE, FALSE),
9409 isOperandVolatile (result, FALSE));
9415 freeAsmop (right, NULL, ic, TRUE);
9416 freeAsmop (result, NULL, ic, TRUE);
9419 /*-----------------------------------------------------------------*/
9420 /* genJumpTab - genrates code for jump table */
9421 /*-----------------------------------------------------------------*/
9423 genJumpTab (iCode * ic)
9428 D(emitcode ("; genJumpTab",""));
9430 aopOp (IC_JTCOND (ic), ic, FALSE);
9431 /* get the condition into accumulator */
9432 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9434 /* multiply by three */
9435 emitcode ("add", "a,acc");
9436 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9437 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9439 jtab = newiTempLabel (NULL);
9440 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9441 emitcode ("jmp", "@a+dptr");
9442 emitcode ("", "%05d$:", jtab->key + 100);
9443 /* now generate the jump labels */
9444 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9445 jtab = setNextItem (IC_JTLABELS (ic)))
9446 emitcode ("ljmp", "%05d$", jtab->key + 100);
9450 /*-----------------------------------------------------------------*/
9451 /* genCast - gen code for casting */
9452 /*-----------------------------------------------------------------*/
9454 genCast (iCode * ic)
9456 operand *result = IC_RESULT (ic);
9457 sym_link *ctype = operandType (IC_LEFT (ic));
9458 sym_link *rtype = operandType (IC_RIGHT (ic));
9459 operand *right = IC_RIGHT (ic);
9462 D(emitcode("; genCast",""));
9464 /* if they are equivalent then do nothing */
9465 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9468 aopOp (right, ic, FALSE);
9469 aopOp (result, ic, FALSE);
9471 /* if the result is a bit (and not a bitfield) */
9472 // if (AOP_TYPE (result) == AOP_CRY)
9473 if (IS_BITVAR (OP_SYMBOL (result)->type)
9474 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9476 /* if the right size is a literal then
9477 we know what the value is */
9478 if (AOP_TYPE (right) == AOP_LIT)
9480 if (((int) operandLitValue (right)))
9481 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9483 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9488 /* the right is also a bit variable */
9489 if (AOP_TYPE (right) == AOP_CRY)
9491 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9492 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9498 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9503 /* if they are the same size : or less */
9504 if (AOP_SIZE (result) <= AOP_SIZE (right))
9507 /* if they are in the same place */
9508 if (sameRegs (AOP (right), AOP (result)))
9511 /* if they in different places then copy */
9512 size = AOP_SIZE (result);
9516 aopPut (AOP (result),
9517 aopGet (AOP (right), offset, FALSE, FALSE),
9519 isOperandVolatile (result, FALSE));
9526 /* if the result is of type pointer */
9531 sym_link *type = operandType (right);
9532 sym_link *etype = getSpec (type);
9534 /* pointer to generic pointer */
9535 if (IS_GENPTR (ctype))
9538 p_type = DCL_TYPE (type);
9541 if (SPEC_SCLS(etype)==S_REGISTER) {
9542 // let's assume it is a generic pointer
9545 /* we have to go by the storage class */
9546 p_type = PTR_TYPE (SPEC_OCLS (etype));
9550 /* the first two bytes are known */
9551 size = GPTRSIZE - 1;
9555 aopPut (AOP (result),
9556 aopGet (AOP (right), offset, FALSE, FALSE),
9558 isOperandVolatile (result, FALSE));
9561 /* the last byte depending on type */
9563 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9568 // pointerTypeToGPByte will have bitched.
9572 sprintf(gpValStr, "#0x%d", gpVal);
9573 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9578 /* just copy the pointers */
9579 size = AOP_SIZE (result);
9583 aopPut (AOP (result),
9584 aopGet (AOP (right), offset, FALSE, FALSE),
9586 isOperandVolatile (result, FALSE));
9592 /* so we now know that the size of destination is greater
9593 than the size of the source */
9594 /* we move to result for the size of source */
9595 size = AOP_SIZE (right);
9599 aopPut (AOP (result),
9600 aopGet (AOP (right), offset, FALSE, FALSE),
9602 isOperandVolatile (result, FALSE));
9606 /* now depending on the sign of the source && destination */
9607 size = AOP_SIZE (result) - AOP_SIZE (right);
9608 /* if unsigned or not an integral type */
9609 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9612 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9616 /* we need to extend the sign :{ */
9617 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9620 emitcode ("rlc", "a");
9621 emitcode ("subb", "a,acc");
9623 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9626 /* we are done hurray !!!! */
9629 freeAsmop (right, NULL, ic, TRUE);
9630 freeAsmop (result, NULL, ic, TRUE);
9634 /*-----------------------------------------------------------------*/
9635 /* genDjnz - generate decrement & jump if not zero instrucion */
9636 /*-----------------------------------------------------------------*/
9638 genDjnz (iCode * ic, iCode * ifx)
9644 D(emitcode ("; genDjnz",""));
9646 /* if the if condition has a false label
9647 then we cannot save */
9651 /* if the minus is not of the form
9653 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9654 !IS_OP_LITERAL (IC_RIGHT (ic)))
9657 if (operandLitValue (IC_RIGHT (ic)) != 1)
9660 /* if the size of this greater than one then no
9662 if (getSize (operandType (IC_RESULT (ic))) > 1)
9665 /* otherwise we can save BIG */
9666 lbl = newiTempLabel (NULL);
9667 lbl1 = newiTempLabel (NULL);
9669 aopOp (IC_RESULT (ic), ic, FALSE);
9671 if (AOP_NEEDSACC(IC_RESULT(ic)))
9673 /* If the result is accessed indirectly via
9674 * the accumulator, we must explicitly write
9675 * it back after the decrement.
9677 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9679 if (strcmp(rByte, "a"))
9681 /* Something is hopelessly wrong */
9682 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9683 __FILE__, __LINE__);
9684 /* We can just give up; the generated code will be inefficient,
9687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9690 emitcode ("dec", "%s", rByte);
9691 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9692 emitcode ("jnz", "%05d$", lbl->key + 100);
9694 else if (IS_AOP_PREG (IC_RESULT (ic)))
9696 emitcode ("dec", "%s",
9697 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9698 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9699 emitcode ("jnz", "%05d$", lbl->key + 100);
9703 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9706 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9707 emitcode ("", "%05d$:", lbl->key + 100);
9708 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9709 emitcode ("", "%05d$:", lbl1->key + 100);
9711 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9716 /*-----------------------------------------------------------------*/
9717 /* genReceive - generate code for a receive iCode */
9718 /*-----------------------------------------------------------------*/
9720 genReceive (iCode * ic)
9722 int size = getSize (operandType (IC_RESULT (ic)));
9724 D(emitcode ("; genReceive",""));
9726 if (ic->argreg == 1) { /* first parameter */
9727 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9728 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9729 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9735 for (offset = 0; offset<size; offset++)
9736 if (!strcmp (fReturn[offset], "a"))
9741 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9743 for (offset = size-1; offset>0; offset--)
9744 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9745 emitcode("mov","a,%s", fReturn[0]);
9747 aopOp (IC_RESULT (ic), ic, FALSE);
9749 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9750 isOperandVolatile (IC_RESULT (ic), FALSE));
9751 for (offset = 1; offset<size; offset++)
9752 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9753 isOperandVolatile (IC_RESULT (ic), FALSE));
9759 if (getTempRegs(tempRegs, size, ic))
9761 for (offset = 0; offset<size; offset++)
9762 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9763 aopOp (IC_RESULT (ic), ic, FALSE);
9764 for (offset = 0; offset<size; offset++)
9765 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9766 isOperandVolatile (IC_RESULT (ic), FALSE));
9771 offset = fReturnSizeMCS51 - size;
9773 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9774 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9777 aopOp (IC_RESULT (ic), ic, FALSE);
9778 size = AOP_SIZE (IC_RESULT (ic));
9781 emitcode ("pop", "acc");
9782 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9787 aopOp (IC_RESULT (ic), ic, FALSE);
9789 assignResultValue (IC_RESULT (ic));
9791 } else { /* second receive onwards */
9793 aopOp (IC_RESULT (ic), ic, FALSE);
9794 rb1off = ic->argreg;
9796 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9801 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9804 /*-----------------------------------------------------------------*/
9805 /* genDummyRead - generate code for dummy read of volatiles */
9806 /*-----------------------------------------------------------------*/
9808 genDummyRead (iCode * ic)
9813 D(emitcode("; genDummyRead",""));
9816 if (op && IS_SYMOP (op))
9818 aopOp (op, ic, FALSE);
9820 /* if the result is a bit */
9821 if (AOP_TYPE (op) == AOP_CRY)
9822 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9825 /* bit variables done */
9827 size = AOP_SIZE (op);
9831 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9836 freeAsmop (op, NULL, ic, TRUE);
9840 if (op && IS_SYMOP (op))
9842 aopOp (op, ic, FALSE);
9844 /* if the result is a bit */
9845 if (AOP_TYPE (op) == AOP_CRY)
9846 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9849 /* bit variables done */
9851 size = AOP_SIZE (op);
9855 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9860 freeAsmop (op, NULL, ic, TRUE);
9864 /*-----------------------------------------------------------------*/
9865 /* genCritical - generate code for start of a critical sequence */
9866 /*-----------------------------------------------------------------*/
9868 genCritical (iCode *ic)
9870 symbol *tlbl = newiTempLabel (NULL);
9872 D(emitcode("; genCritical",""));
9875 aopOp (IC_RESULT (ic), ic, TRUE);
9877 emitcode ("setb", "c");
9878 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9879 emitcode ("clr", "c");
9880 emitcode ("", "%05d$:", (tlbl->key + 100));
9883 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9885 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9888 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9891 /*-----------------------------------------------------------------*/
9892 /* genEndCritical - generate code for end of a critical sequence */
9893 /*-----------------------------------------------------------------*/
9895 genEndCritical (iCode *ic)
9897 D(emitcode("; genEndCritical",""));
9901 aopOp (IC_RIGHT (ic), ic, FALSE);
9902 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9904 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9905 emitcode ("mov", "ea,c");
9909 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9910 emitcode ("rrc", "a");
9911 emitcode ("mov", "ea,c");
9913 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9917 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9918 emitcode ("mov", "ea,c");
9922 /*-----------------------------------------------------------------*/
9923 /* gen51Code - generate code for 8051 based controllers */
9924 /*-----------------------------------------------------------------*/
9926 gen51Code (iCode * lic)
9932 _G.currentFunc = NULL;
9933 lineHead = lineCurr = NULL;
9935 /* print the allocation information */
9936 if (allocInfo && currFunc)
9937 printAllocInfo (currFunc, codeOutFile);
9938 /* if debug information required */
9939 if (options.debug && currFunc)
9941 debugFile->writeFunction (currFunc, lic);
9943 /* stack pointer name */
9944 if (options.useXstack)
9950 for (ic = lic; ic; ic = ic->next)
9952 _G.current_iCode = ic;
9954 if (ic->lineno && cln != ic->lineno)
9958 debugFile->writeCLine(ic);
9960 if (!options.noCcodeInAsm) {
9961 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9962 printCLine(ic->filename, ic->lineno));
9967 if (ic->seqPoint && ic->seqPoint != cseq)
9969 emitcode ("", "; sequence point %d", ic->seqPoint);
9970 cseq = ic->seqPoint;
9973 if (options.iCodeInAsm) {
9977 for (i=0; i<8; i++) {
9978 sprintf (®sInUse[i],
9979 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9982 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9984 /* if the result is marked as
9985 spilt and rematerializable or code for
9986 this has already been generated then
9988 if (resultRemat (ic) || ic->generated)
9991 /* depending on the operation */
10011 /* IPOP happens only when trying to restore a
10012 spilt live range, if there is an ifx statement
10013 following this pop then the if statement might
10014 be using some of the registers being popped which
10015 would destory the contents of the register so
10016 we need to check for this condition and handle it */
10018 ic->next->op == IFX &&
10019 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10020 genIfx (ic->next, ic);
10038 genEndFunction (ic);
10058 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10075 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10079 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10086 /* note these two are xlated by algebraic equivalence
10087 during parsing SDCC.y */
10088 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10089 "got '>=' or '<=' shouldn't have come here");
10093 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10105 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10109 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10113 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10137 genRightShift (ic);
10140 case GET_VALUE_AT_ADDRESS:
10141 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10145 if (POINTER_SET (ic))
10146 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10172 addSet (&_G.sendSet, ic);
10175 case DUMMY_READ_VOLATILE:
10184 genEndCritical (ic);
10196 _G.current_iCode = NULL;
10198 /* now we are ready to call the
10199 peep hole optimizer */
10200 if (!options.nopeep)
10201 peepHole (&lineHead);
10203 /* now do the actual printing */
10204 printLine (lineHead, codeOutFile);