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 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
131 SNPRINTF (lb, sizeof(lb), "%s", inst);
132 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
135 tvsprintf (lb, sizeof(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 */
6322 /* Add \n for labels, not dirs such as c:\mydir */
6323 if ( (*bp == ':') && (isspace(bp[1])) )
6337 /* emitcode("",buffer); */
6338 _G.inLine -= (!options.asmpeep);
6341 /*-----------------------------------------------------------------*/
6342 /* genRRC - rotate right with carry */
6343 /*-----------------------------------------------------------------*/
6347 operand *left, *result;
6348 int size, offset = 0;
6351 D(emitcode ("; genRRC",""));
6353 /* rotate right with carry */
6354 left = IC_LEFT (ic);
6355 result = IC_RESULT (ic);
6356 aopOp (left, ic, FALSE);
6357 aopOp (result, ic, FALSE);
6359 /* move it to the result */
6360 size = AOP_SIZE (result);
6362 if (size == 1) { /* special case for 1 byte */
6363 l = aopGet (AOP (left), offset, FALSE, FALSE);
6365 emitcode ("rr", "a");
6371 l = aopGet (AOP (left), offset, FALSE, FALSE);
6373 emitcode ("rrc", "a");
6374 if (AOP_SIZE (result) > 1)
6375 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6377 /* now we need to put the carry into the
6378 highest order byte of the result */
6379 if (AOP_SIZE (result) > 1)
6381 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6384 emitcode ("mov", "acc.7,c");
6386 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6387 freeAsmop (left, NULL, ic, TRUE);
6388 freeAsmop (result, NULL, ic, TRUE);
6391 /*-----------------------------------------------------------------*/
6392 /* genRLC - generate code for rotate left with carry */
6393 /*-----------------------------------------------------------------*/
6397 operand *left, *result;
6398 int size, offset = 0;
6401 D(emitcode ("; genRLC",""));
6403 /* rotate right with carry */
6404 left = IC_LEFT (ic);
6405 result = IC_RESULT (ic);
6406 aopOp (left, ic, FALSE);
6407 aopOp (result, ic, FALSE);
6409 /* move it to the result */
6410 size = AOP_SIZE (result);
6414 l = aopGet (AOP (left), offset, FALSE, FALSE);
6416 if (size == 0) { /* special case for 1 byte */
6420 emitcode ("add", "a,acc");
6421 if (AOP_SIZE (result) > 1)
6422 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6425 l = aopGet (AOP (left), offset, FALSE, FALSE);
6427 emitcode ("rlc", "a");
6428 if (AOP_SIZE (result) > 1)
6429 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6432 /* now we need to put the carry into the
6433 highest order byte of the result */
6434 if (AOP_SIZE (result) > 1)
6436 l = aopGet (AOP (result), 0, FALSE, FALSE);
6439 emitcode ("mov", "acc.0,c");
6441 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6442 freeAsmop (left, NULL, ic, TRUE);
6443 freeAsmop (result, NULL, ic, TRUE);
6446 /*-----------------------------------------------------------------*/
6447 /* genGetHbit - generates code get highest order bit */
6448 /*-----------------------------------------------------------------*/
6450 genGetHbit (iCode * ic)
6452 operand *left, *result;
6454 D(emitcode ("; genGetHbit",""));
6456 left = IC_LEFT (ic);
6457 result = IC_RESULT (ic);
6458 aopOp (left, ic, FALSE);
6459 aopOp (result, ic, FALSE);
6461 /* get the highest order byte into a */
6462 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6463 if (AOP_TYPE (result) == AOP_CRY)
6465 emitcode ("rlc", "a");
6470 emitcode ("rl", "a");
6471 emitcode ("anl", "a,#0x01");
6476 freeAsmop (left, NULL, ic, TRUE);
6477 freeAsmop (result, NULL, ic, TRUE);
6480 /*-----------------------------------------------------------------*/
6481 /* genSwap - generates code to swap nibbles or bytes */
6482 /*-----------------------------------------------------------------*/
6484 genSwap (iCode * ic)
6486 operand *left, *result;
6488 D(emitcode ("; genSwap",""));
6490 left = IC_LEFT (ic);
6491 result = IC_RESULT (ic);
6492 aopOp (left, ic, FALSE);
6493 aopOp (result, ic, FALSE);
6495 switch (AOP_SIZE (left))
6497 case 1: /* swap nibbles in byte */
6498 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6499 emitcode ("swap", "a");
6500 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6502 case 2: /* swap bytes in word */
6503 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6505 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6506 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6507 0, isOperandVolatile (result, FALSE));
6508 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6510 else if (operandsEqu (left, result))
6513 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6514 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6516 emitcode ("mov", "b,a");
6519 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6520 0, isOperandVolatile (result, FALSE));
6521 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6525 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6526 0, isOperandVolatile (result, FALSE));
6527 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6528 1, isOperandVolatile (result, FALSE));
6532 wassertl(FALSE, "unsupported SWAP operand size");
6535 freeAsmop (left, NULL, ic, TRUE);
6536 freeAsmop (result, NULL, ic, TRUE);
6540 /*-----------------------------------------------------------------*/
6541 /* AccRol - rotate left accumulator by known count */
6542 /*-----------------------------------------------------------------*/
6544 AccRol (int shCount)
6546 shCount &= 0x0007; // shCount : 0..7
6553 emitcode ("rl", "a");
6556 emitcode ("rl", "a");
6557 emitcode ("rl", "a");
6560 emitcode ("swap", "a");
6561 emitcode ("rr", "a");
6564 emitcode ("swap", "a");
6567 emitcode ("swap", "a");
6568 emitcode ("rl", "a");
6571 emitcode ("rr", "a");
6572 emitcode ("rr", "a");
6575 emitcode ("rr", "a");
6580 /*-----------------------------------------------------------------*/
6581 /* AccLsh - left shift accumulator by known count */
6582 /*-----------------------------------------------------------------*/
6584 AccLsh (int shCount)
6589 emitcode ("add", "a,acc");
6590 else if (shCount == 2)
6592 emitcode ("add", "a,acc");
6593 emitcode ("add", "a,acc");
6597 /* rotate left accumulator */
6599 /* and kill the lower order bits */
6600 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6605 /*-----------------------------------------------------------------*/
6606 /* AccRsh - right shift accumulator by known count */
6607 /*-----------------------------------------------------------------*/
6609 AccRsh (int shCount)
6616 emitcode ("rrc", "a");
6620 /* rotate right accumulator */
6621 AccRol (8 - shCount);
6622 /* and kill the higher order bits */
6623 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6628 /*-----------------------------------------------------------------*/
6629 /* AccSRsh - signed right shift accumulator by known count */
6630 /*-----------------------------------------------------------------*/
6632 AccSRsh (int shCount)
6639 emitcode ("mov", "c,acc.7");
6640 emitcode ("rrc", "a");
6642 else if (shCount == 2)
6644 emitcode ("mov", "c,acc.7");
6645 emitcode ("rrc", "a");
6646 emitcode ("mov", "c,acc.7");
6647 emitcode ("rrc", "a");
6651 tlbl = newiTempLabel (NULL);
6652 /* rotate right accumulator */
6653 AccRol (8 - shCount);
6654 /* and kill the higher order bits */
6655 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6656 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6657 emitcode ("orl", "a,#0x%02x",
6658 (unsigned char) ~SRMask[shCount]);
6659 emitcode ("", "%05d$:", tlbl->key + 100);
6664 /*-----------------------------------------------------------------*/
6665 /* shiftR1Left2Result - shift right one byte from left to result */
6666 /*-----------------------------------------------------------------*/
6668 shiftR1Left2Result (operand * left, int offl,
6669 operand * result, int offr,
6670 int shCount, int sign)
6672 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6673 /* shift right accumulator */
6678 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6681 /*-----------------------------------------------------------------*/
6682 /* shiftL1Left2Result - shift left one byte from left to result */
6683 /*-----------------------------------------------------------------*/
6685 shiftL1Left2Result (operand * left, int offl,
6686 operand * result, int offr, int shCount)
6689 l = aopGet (AOP (left), offl, FALSE, FALSE);
6691 /* shift left accumulator */
6693 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6696 /*-----------------------------------------------------------------*/
6697 /* movLeft2Result - move byte from left to result */
6698 /*-----------------------------------------------------------------*/
6700 movLeft2Result (operand * left, int offl,
6701 operand * result, int offr, int sign)
6704 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6706 l = aopGet (AOP (left), offl, FALSE, FALSE);
6708 if (*l == '@' && (IS_AOP_PREG (result)))
6710 emitcode ("mov", "a,%s", l);
6711 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6716 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6719 /* MSB sign in acc.7 ! */
6720 if (getDataSize (left) == offl + 1)
6722 emitcode ("mov", "a,%s", l);
6723 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6730 /*-----------------------------------------------------------------*/
6731 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6732 /*-----------------------------------------------------------------*/
6736 emitcode ("rrc", "a");
6737 emitcode ("xch", "a,%s", x);
6738 emitcode ("rrc", "a");
6739 emitcode ("xch", "a,%s", x);
6742 /*-----------------------------------------------------------------*/
6743 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6744 /*-----------------------------------------------------------------*/
6748 emitcode ("xch", "a,%s", x);
6749 emitcode ("rlc", "a");
6750 emitcode ("xch", "a,%s", x);
6751 emitcode ("rlc", "a");
6754 /*-----------------------------------------------------------------*/
6755 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6756 /*-----------------------------------------------------------------*/
6760 emitcode ("xch", "a,%s", x);
6761 emitcode ("add", "a,acc");
6762 emitcode ("xch", "a,%s", x);
6763 emitcode ("rlc", "a");
6766 /*-----------------------------------------------------------------*/
6767 /* AccAXLsh - left shift a:x by known count (0..7) */
6768 /*-----------------------------------------------------------------*/
6770 AccAXLsh (char *x, int shCount)
6785 case 5: // AAAAABBB:CCCCCDDD
6787 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6789 emitcode ("anl", "a,#0x%02x",
6790 SLMask[shCount]); // BBB00000:CCCCCDDD
6792 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6794 AccRol (shCount); // DDDCCCCC:BBB00000
6796 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6798 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6800 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6802 emitcode ("anl", "a,#0x%02x",
6803 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6805 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6807 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6810 case 6: // AAAAAABB:CCCCCCDD
6811 emitcode ("anl", "a,#0x%02x",
6812 SRMask[shCount]); // 000000BB:CCCCCCDD
6813 emitcode ("mov", "c,acc.0"); // c = B
6814 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6816 AccAXRrl1 (x); // BCCCCCCD:D000000B
6817 AccAXRrl1 (x); // BBCCCCCC:DD000000
6819 emitcode("rrc","a");
6820 emitcode("xch","a,%s", x);
6821 emitcode("rrc","a");
6822 emitcode("mov","c,acc.0"); //<< get correct bit
6823 emitcode("xch","a,%s", x);
6825 emitcode("rrc","a");
6826 emitcode("xch","a,%s", x);
6827 emitcode("rrc","a");
6828 emitcode("xch","a,%s", x);
6831 case 7: // a:x <<= 7
6833 emitcode ("anl", "a,#0x%02x",
6834 SRMask[shCount]); // 0000000B:CCCCCCCD
6836 emitcode ("mov", "c,acc.0"); // c = B
6838 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6840 AccAXRrl1 (x); // BCCCCCCC:D0000000
6848 /*-----------------------------------------------------------------*/
6849 /* AccAXRsh - right shift a:x known count (0..7) */
6850 /*-----------------------------------------------------------------*/
6852 AccAXRsh (char *x, int shCount)
6860 AccAXRrl1 (x); // 0->a:x
6865 AccAXRrl1 (x); // 0->a:x
6868 AccAXRrl1 (x); // 0->a:x
6873 case 5: // AAAAABBB:CCCCCDDD = a:x
6875 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6877 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6879 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6881 emitcode ("anl", "a,#0x%02x",
6882 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6884 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6886 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6888 emitcode ("anl", "a,#0x%02x",
6889 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6891 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6893 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6895 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6898 case 6: // AABBBBBB:CCDDDDDD
6900 emitcode ("mov", "c,acc.7");
6901 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6903 emitcode ("mov", "c,acc.7");
6904 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6906 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6908 emitcode ("anl", "a,#0x%02x",
6909 SRMask[shCount]); // 000000AA:BBBBBBCC
6912 case 7: // ABBBBBBB:CDDDDDDD
6914 emitcode ("mov", "c,acc.7"); // c = A
6916 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6918 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6920 emitcode ("anl", "a,#0x%02x",
6921 SRMask[shCount]); // 0000000A:BBBBBBBC
6929 /*-----------------------------------------------------------------*/
6930 /* AccAXRshS - right shift signed a:x known count (0..7) */
6931 /*-----------------------------------------------------------------*/
6933 AccAXRshS (char *x, int shCount)
6941 emitcode ("mov", "c,acc.7");
6942 AccAXRrl1 (x); // s->a:x
6946 emitcode ("mov", "c,acc.7");
6947 AccAXRrl1 (x); // s->a:x
6949 emitcode ("mov", "c,acc.7");
6950 AccAXRrl1 (x); // s->a:x
6955 case 5: // AAAAABBB:CCCCCDDD = a:x
6957 tlbl = newiTempLabel (NULL);
6958 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6960 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6962 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6964 emitcode ("anl", "a,#0x%02x",
6965 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6967 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6969 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6971 emitcode ("anl", "a,#0x%02x",
6972 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6974 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6976 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6978 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6980 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6981 emitcode ("orl", "a,#0x%02x",
6982 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6984 emitcode ("", "%05d$:", tlbl->key + 100);
6985 break; // SSSSAAAA:BBBCCCCC
6987 case 6: // AABBBBBB:CCDDDDDD
6989 tlbl = newiTempLabel (NULL);
6990 emitcode ("mov", "c,acc.7");
6991 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6993 emitcode ("mov", "c,acc.7");
6994 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6996 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6998 emitcode ("anl", "a,#0x%02x",
6999 SRMask[shCount]); // 000000AA:BBBBBBCC
7001 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7002 emitcode ("orl", "a,#0x%02x",
7003 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7005 emitcode ("", "%05d$:", tlbl->key + 100);
7007 case 7: // ABBBBBBB:CDDDDDDD
7009 tlbl = newiTempLabel (NULL);
7010 emitcode ("mov", "c,acc.7"); // c = A
7012 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7014 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7016 emitcode ("anl", "a,#0x%02x",
7017 SRMask[shCount]); // 0000000A:BBBBBBBC
7019 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7020 emitcode ("orl", "a,#0x%02x",
7021 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7023 emitcode ("", "%05d$:", tlbl->key + 100);
7030 /*-----------------------------------------------------------------*/
7031 /* shiftL2Left2Result - shift left two bytes from left to result */
7032 /*-----------------------------------------------------------------*/
7034 shiftL2Left2Result (operand * left, int offl,
7035 operand * result, int offr, int shCount)
7037 if (sameRegs (AOP (result), AOP (left)) &&
7038 ((offl + MSB16) == offr))
7040 /* don't crash result[offr] */
7041 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7042 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7046 movLeft2Result (left, offl, result, offr, 0);
7047 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7049 /* ax << shCount (x = lsb(result)) */
7050 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7051 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7055 /*-----------------------------------------------------------------*/
7056 /* shiftR2Left2Result - shift right two bytes from left to result */
7057 /*-----------------------------------------------------------------*/
7059 shiftR2Left2Result (operand * left, int offl,
7060 operand * result, int offr,
7061 int shCount, int sign)
7063 if (sameRegs (AOP (result), AOP (left)) &&
7064 ((offl + MSB16) == offr))
7066 /* don't crash result[offr] */
7067 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7068 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7072 movLeft2Result (left, offl, result, offr, 0);
7073 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7075 /* a:x >> shCount (x = lsb(result)) */
7077 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7079 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7080 if (getDataSize (result) > 1)
7081 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7084 /*-----------------------------------------------------------------*/
7085 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7086 /*-----------------------------------------------------------------*/
7088 shiftLLeftOrResult (operand * left, int offl,
7089 operand * result, int offr, int shCount)
7091 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7092 /* shift left accumulator */
7094 /* or with result */
7095 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7096 /* back to result */
7097 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7100 /*-----------------------------------------------------------------*/
7101 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7102 /*-----------------------------------------------------------------*/
7104 shiftRLeftOrResult (operand * left, int offl,
7105 operand * result, int offr, int shCount)
7107 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7108 /* shift right accumulator */
7110 /* or with result */
7111 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7112 /* back to result */
7113 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7116 /*-----------------------------------------------------------------*/
7117 /* genlshOne - left shift a one byte quantity by known count */
7118 /*-----------------------------------------------------------------*/
7120 genlshOne (operand * result, operand * left, int shCount)
7122 D(emitcode ("; genlshOne",""));
7124 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7127 /*-----------------------------------------------------------------*/
7128 /* genlshTwo - left shift two bytes by known amount != 0 */
7129 /*-----------------------------------------------------------------*/
7131 genlshTwo (operand * result, operand * left, int shCount)
7135 D(emitcode ("; genlshTwo",""));
7137 size = getDataSize (result);
7139 /* if shCount >= 8 */
7147 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7149 movLeft2Result (left, LSB, result, MSB16, 0);
7151 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7154 /* 1 <= shCount <= 7 */
7158 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7160 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7164 /*-----------------------------------------------------------------*/
7165 /* shiftLLong - shift left one long from left to result */
7166 /* offl = LSB or MSB16 */
7167 /*-----------------------------------------------------------------*/
7169 shiftLLong (operand * left, operand * result, int offr)
7172 int size = AOP_SIZE (result);
7174 if (size >= LSB + offr)
7176 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7178 emitcode ("add", "a,acc");
7179 if (sameRegs (AOP (left), AOP (result)) &&
7180 size >= MSB16 + offr && offr != LSB)
7181 emitcode ("xch", "a,%s",
7182 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7184 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7187 if (size >= MSB16 + offr)
7189 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7191 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7194 emitcode ("rlc", "a");
7195 if (sameRegs (AOP (left), AOP (result)) &&
7196 size >= MSB24 + offr && offr != LSB)
7197 emitcode ("xch", "a,%s",
7198 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7200 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7203 if (size >= MSB24 + offr)
7205 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7207 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7210 emitcode ("rlc", "a");
7211 if (sameRegs (AOP (left), AOP (result)) &&
7212 size >= MSB32 + offr && offr != LSB)
7213 emitcode ("xch", "a,%s",
7214 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7216 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7219 if (size > MSB32 + offr)
7221 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7223 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7226 emitcode ("rlc", "a");
7227 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7230 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7233 /*-----------------------------------------------------------------*/
7234 /* genlshFour - shift four byte by a known amount != 0 */
7235 /*-----------------------------------------------------------------*/
7237 genlshFour (operand * result, operand * left, int shCount)
7241 D(emitcode ("; genlshFour",""));
7243 size = AOP_SIZE (result);
7245 /* if shifting more that 3 bytes */
7250 /* lowest order of left goes to the highest
7251 order of the destination */
7252 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7254 movLeft2Result (left, LSB, result, MSB32, 0);
7255 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7256 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7257 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7261 /* more than two bytes */
7262 else if (shCount >= 16)
7264 /* lower order two bytes goes to higher order two bytes */
7266 /* if some more remaining */
7268 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7271 movLeft2Result (left, MSB16, result, MSB32, 0);
7272 movLeft2Result (left, LSB, result, MSB24, 0);
7274 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7275 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7279 /* if more than 1 byte */
7280 else if (shCount >= 8)
7282 /* lower order three bytes goes to higher order three bytes */
7287 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7289 movLeft2Result (left, LSB, result, MSB16, 0);
7295 movLeft2Result (left, MSB24, result, MSB32, 0);
7296 movLeft2Result (left, MSB16, result, MSB24, 0);
7297 movLeft2Result (left, LSB, result, MSB16, 0);
7298 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7300 else if (shCount == 1)
7301 shiftLLong (left, result, MSB16);
7304 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7305 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7306 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7307 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7312 /* 1 <= shCount <= 7 */
7313 else if (shCount <= 2)
7315 shiftLLong (left, result, LSB);
7317 shiftLLong (result, result, LSB);
7319 /* 3 <= shCount <= 7, optimize */
7322 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7323 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7324 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7328 /*-----------------------------------------------------------------*/
7329 /* genLeftShiftLiteral - left shifting by known count */
7330 /*-----------------------------------------------------------------*/
7332 genLeftShiftLiteral (operand * left,
7337 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7340 D(emitcode ("; genLeftShiftLiteral",""));
7342 freeAsmop (right, NULL, ic, TRUE);
7344 aopOp (left, ic, FALSE);
7345 aopOp (result, ic, FALSE);
7347 size = getSize (operandType (result));
7350 emitcode ("; shift left ", "result %d, left %d", size,
7354 /* I suppose that the left size >= result size */
7359 movLeft2Result (left, size, result, size, 0);
7363 else if (shCount >= (size * 8))
7365 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7371 genlshOne (result, left, shCount);
7375 genlshTwo (result, left, shCount);
7379 genlshFour (result, left, shCount);
7382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7383 "*** ack! mystery literal shift!\n");
7387 freeAsmop (left, NULL, ic, TRUE);
7388 freeAsmop (result, NULL, ic, TRUE);
7391 /*-----------------------------------------------------------------*/
7392 /* genLeftShift - generates code for left shifting */
7393 /*-----------------------------------------------------------------*/
7395 genLeftShift (iCode * ic)
7397 operand *left, *right, *result;
7400 symbol *tlbl, *tlbl1;
7402 D(emitcode ("; genLeftShift",""));
7404 right = IC_RIGHT (ic);
7405 left = IC_LEFT (ic);
7406 result = IC_RESULT (ic);
7408 aopOp (right, ic, FALSE);
7410 /* if the shift count is known then do it
7411 as efficiently as possible */
7412 if (AOP_TYPE (right) == AOP_LIT)
7414 genLeftShiftLiteral (left, right, result, ic);
7418 /* shift count is unknown then we have to form
7419 a loop get the loop count in B : Note: we take
7420 only the lower order byte since shifting
7421 more that 32 bits make no sense anyway, ( the
7422 largest size of an object can be only 32 bits ) */
7424 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7425 emitcode ("inc", "b");
7426 freeAsmop (right, NULL, ic, TRUE);
7427 aopOp (left, ic, FALSE);
7428 aopOp (result, ic, FALSE);
7430 /* now move the left to the result if they are not the
7432 if (!sameRegs (AOP (left), AOP (result)) &&
7433 AOP_SIZE (result) > 1)
7436 size = AOP_SIZE (result);
7440 l = aopGet (AOP (left), offset, FALSE, TRUE);
7441 if (*l == '@' && (IS_AOP_PREG (result)))
7444 emitcode ("mov", "a,%s", l);
7445 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7448 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7453 tlbl = newiTempLabel (NULL);
7454 size = AOP_SIZE (result);
7456 tlbl1 = newiTempLabel (NULL);
7458 /* if it is only one byte then */
7461 symbol *tlbl1 = newiTempLabel (NULL);
7463 l = aopGet (AOP (left), 0, FALSE, FALSE);
7465 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7466 emitcode ("", "%05d$:", tlbl->key + 100);
7467 emitcode ("add", "a,acc");
7468 emitcode ("", "%05d$:", tlbl1->key + 100);
7469 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7470 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7474 reAdjustPreg (AOP (result));
7476 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7477 emitcode ("", "%05d$:", tlbl->key + 100);
7478 l = aopGet (AOP (result), offset, FALSE, FALSE);
7480 emitcode ("add", "a,acc");
7481 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7484 l = aopGet (AOP (result), offset, FALSE, FALSE);
7486 emitcode ("rlc", "a");
7487 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7489 reAdjustPreg (AOP (result));
7491 emitcode ("", "%05d$:", tlbl1->key + 100);
7492 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7494 freeAsmop (left, NULL, ic, TRUE);
7495 freeAsmop (result, NULL, ic, TRUE);
7498 /*-----------------------------------------------------------------*/
7499 /* genrshOne - right shift a one byte quantity by known count */
7500 /*-----------------------------------------------------------------*/
7502 genrshOne (operand * result, operand * left,
7503 int shCount, int sign)
7505 D(emitcode ("; genrshOne",""));
7507 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7510 /*-----------------------------------------------------------------*/
7511 /* genrshTwo - right shift two bytes by known amount != 0 */
7512 /*-----------------------------------------------------------------*/
7514 genrshTwo (operand * result, operand * left,
7515 int shCount, int sign)
7517 D(emitcode ("; genrshTwo",""));
7519 /* if shCount >= 8 */
7524 shiftR1Left2Result (left, MSB16, result, LSB,
7527 movLeft2Result (left, MSB16, result, LSB, sign);
7528 addSign (result, MSB16, sign);
7531 /* 1 <= shCount <= 7 */
7533 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7536 /*-----------------------------------------------------------------*/
7537 /* shiftRLong - shift right one long from left to result */
7538 /* offl = LSB or MSB16 */
7539 /*-----------------------------------------------------------------*/
7541 shiftRLong (operand * left, int offl,
7542 operand * result, int sign)
7544 int isSameRegs=sameRegs(AOP(left),AOP(result));
7546 if (isSameRegs && offl>1) {
7547 // we are in big trouble, but this shouldn't happen
7548 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7551 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7556 emitcode ("rlc", "a");
7557 emitcode ("subb", "a,acc");
7559 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7561 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7562 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7565 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7570 emitcode ("clr", "c");
7572 emitcode ("mov", "c,acc.7");
7575 emitcode ("rrc", "a");
7577 if (isSameRegs && offl==MSB16) {
7578 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7580 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7581 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7584 emitcode ("rrc", "a");
7585 if (isSameRegs && offl==1) {
7586 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7588 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7589 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7591 emitcode ("rrc", "a");
7592 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7596 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7597 emitcode ("rrc", "a");
7598 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7602 /*-----------------------------------------------------------------*/
7603 /* genrshFour - shift four byte by a known amount != 0 */
7604 /*-----------------------------------------------------------------*/
7606 genrshFour (operand * result, operand * left,
7607 int shCount, int sign)
7609 D(emitcode ("; genrshFour",""));
7611 /* if shifting more that 3 bytes */
7616 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7618 movLeft2Result (left, MSB32, result, LSB, sign);
7619 addSign (result, MSB16, sign);
7621 else if (shCount >= 16)
7625 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7628 movLeft2Result (left, MSB24, result, LSB, 0);
7629 movLeft2Result (left, MSB32, result, MSB16, sign);
7631 addSign (result, MSB24, sign);
7633 else if (shCount >= 8)
7637 shiftRLong (left, MSB16, result, sign);
7638 else if (shCount == 0)
7640 movLeft2Result (left, MSB16, result, LSB, 0);
7641 movLeft2Result (left, MSB24, result, MSB16, 0);
7642 movLeft2Result (left, MSB32, result, MSB24, sign);
7643 addSign (result, MSB32, sign);
7647 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7648 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7649 /* the last shift is signed */
7650 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7651 addSign (result, MSB32, sign);
7655 { /* 1 <= shCount <= 7 */
7658 shiftRLong (left, LSB, result, sign);
7660 shiftRLong (result, LSB, result, sign);
7664 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7665 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7666 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7671 /*-----------------------------------------------------------------*/
7672 /* genRightShiftLiteral - right shifting by known count */
7673 /*-----------------------------------------------------------------*/
7675 genRightShiftLiteral (operand * left,
7681 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7684 D(emitcode ("; genRightShiftLiteral",""));
7686 freeAsmop (right, NULL, ic, TRUE);
7688 aopOp (left, ic, FALSE);
7689 aopOp (result, ic, FALSE);
7692 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7696 size = getDataSize (left);
7697 /* test the LEFT size !!! */
7699 /* I suppose that the left size >= result size */
7702 size = getDataSize (result);
7704 movLeft2Result (left, size, result, size, 0);
7707 else if (shCount >= (size * 8))
7710 /* get sign in acc.7 */
7711 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7713 addSign (result, LSB, sign);
7720 genrshOne (result, left, shCount, sign);
7724 genrshTwo (result, left, shCount, sign);
7728 genrshFour (result, left, shCount, sign);
7734 freeAsmop (left, NULL, ic, TRUE);
7735 freeAsmop (result, NULL, ic, TRUE);
7738 /*-----------------------------------------------------------------*/
7739 /* genSignedRightShift - right shift of signed number */
7740 /*-----------------------------------------------------------------*/
7742 genSignedRightShift (iCode * ic)
7744 operand *right, *left, *result;
7747 symbol *tlbl, *tlbl1;
7749 D(emitcode ("; genSignedRightShift",""));
7751 /* we do it the hard way put the shift count in b
7752 and loop thru preserving the sign */
7754 right = IC_RIGHT (ic);
7755 left = IC_LEFT (ic);
7756 result = IC_RESULT (ic);
7758 aopOp (right, ic, FALSE);
7761 if (AOP_TYPE (right) == AOP_LIT)
7763 genRightShiftLiteral (left, right, result, ic, 1);
7766 /* shift count is unknown then we have to form
7767 a loop get the loop count in B : Note: we take
7768 only the lower order byte since shifting
7769 more that 32 bits make no sense anyway, ( the
7770 largest size of an object can be only 32 bits ) */
7772 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7773 emitcode ("inc", "b");
7774 freeAsmop (right, NULL, ic, TRUE);
7775 aopOp (left, ic, FALSE);
7776 aopOp (result, ic, FALSE);
7778 /* now move the left to the result if they are not the
7780 if (!sameRegs (AOP (left), AOP (result)) &&
7781 AOP_SIZE (result) > 1)
7784 size = AOP_SIZE (result);
7788 l = aopGet (AOP (left), offset, FALSE, TRUE);
7789 if (*l == '@' && IS_AOP_PREG (result))
7792 emitcode ("mov", "a,%s", l);
7793 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7796 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7801 /* mov the highest order bit to OVR */
7802 tlbl = newiTempLabel (NULL);
7803 tlbl1 = newiTempLabel (NULL);
7805 size = AOP_SIZE (result);
7807 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7808 emitcode ("rlc", "a");
7809 emitcode ("mov", "ov,c");
7810 /* if it is only one byte then */
7813 l = aopGet (AOP (left), 0, FALSE, FALSE);
7815 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7816 emitcode ("", "%05d$:", tlbl->key + 100);
7817 emitcode ("mov", "c,ov");
7818 emitcode ("rrc", "a");
7819 emitcode ("", "%05d$:", tlbl1->key + 100);
7820 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7821 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7825 reAdjustPreg (AOP (result));
7826 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7827 emitcode ("", "%05d$:", tlbl->key + 100);
7828 emitcode ("mov", "c,ov");
7831 l = aopGet (AOP (result), offset, FALSE, FALSE);
7833 emitcode ("rrc", "a");
7834 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7836 reAdjustPreg (AOP (result));
7837 emitcode ("", "%05d$:", tlbl1->key + 100);
7838 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7841 freeAsmop (left, NULL, ic, TRUE);
7842 freeAsmop (result, NULL, ic, TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genRightShift - generate code for right shifting */
7847 /*-----------------------------------------------------------------*/
7849 genRightShift (iCode * ic)
7851 operand *right, *left, *result;
7855 symbol *tlbl, *tlbl1;
7857 D(emitcode ("; genRightShift",""));
7859 /* if signed then we do it the hard way preserve the
7860 sign bit moving it inwards */
7861 letype = getSpec (operandType (IC_LEFT (ic)));
7863 if (!SPEC_USIGN (letype))
7865 genSignedRightShift (ic);
7869 /* signed & unsigned types are treated the same : i.e. the
7870 signed is NOT propagated inwards : quoting from the
7871 ANSI - standard : "for E1 >> E2, is equivalent to division
7872 by 2**E2 if unsigned or if it has a non-negative value,
7873 otherwise the result is implementation defined ", MY definition
7874 is that the sign does not get propagated */
7876 right = IC_RIGHT (ic);
7877 left = IC_LEFT (ic);
7878 result = IC_RESULT (ic);
7880 aopOp (right, ic, FALSE);
7882 /* if the shift count is known then do it
7883 as efficiently as possible */
7884 if (AOP_TYPE (right) == AOP_LIT)
7886 genRightShiftLiteral (left, right, result, ic, 0);
7890 /* shift count is unknown then we have to form
7891 a loop get the loop count in B : Note: we take
7892 only the lower order byte since shifting
7893 more that 32 bits make no sense anyway, ( the
7894 largest size of an object can be only 32 bits ) */
7896 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7897 emitcode ("inc", "b");
7898 freeAsmop (right, NULL, ic, TRUE);
7899 aopOp (left, ic, FALSE);
7900 aopOp (result, ic, FALSE);
7902 /* now move the left to the result if they are not the
7904 if (!sameRegs (AOP (left), AOP (result)) &&
7905 AOP_SIZE (result) > 1)
7908 size = AOP_SIZE (result);
7912 l = aopGet (AOP (left), offset, FALSE, TRUE);
7913 if (*l == '@' && IS_AOP_PREG (result))
7916 emitcode ("mov", "a,%s", l);
7917 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7920 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7925 tlbl = newiTempLabel (NULL);
7926 tlbl1 = newiTempLabel (NULL);
7927 size = AOP_SIZE (result);
7930 /* if it is only one byte then */
7933 l = aopGet (AOP (left), 0, FALSE, FALSE);
7935 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7936 emitcode ("", "%05d$:", tlbl->key + 100);
7938 emitcode ("rrc", "a");
7939 emitcode ("", "%05d$:", tlbl1->key + 100);
7940 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7941 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7945 reAdjustPreg (AOP (result));
7946 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7947 emitcode ("", "%05d$:", tlbl->key + 100);
7951 l = aopGet (AOP (result), offset, FALSE, FALSE);
7953 emitcode ("rrc", "a");
7954 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7956 reAdjustPreg (AOP (result));
7958 emitcode ("", "%05d$:", tlbl1->key + 100);
7959 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7962 freeAsmop (left, NULL, ic, TRUE);
7963 freeAsmop (result, NULL, ic, TRUE);
7966 /*-----------------------------------------------------------------*/
7967 /* emitPtrByteGet - emits code to get a byte into A through a */
7968 /* pointer register (R0, R1, or DPTR). The */
7969 /* original value of A can be preserved in B. */
7970 /*-----------------------------------------------------------------*/
7972 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7979 emitcode ("mov", "b,a");
7980 emitcode ("mov", "a,@%s", rname);
7985 emitcode ("mov", "b,a");
7986 emitcode ("movx", "a,@%s", rname);
7991 emitcode ("mov", "b,a");
7992 emitcode ("movx", "a,@dptr");
7997 emitcode ("mov", "b,a");
7998 emitcode ("clr", "a");
7999 emitcode ("movc", "a,@a+dptr");
8005 emitcode ("push", "b");
8006 emitcode ("push", "acc");
8008 emitcode ("lcall", "__gptrget");
8010 emitcode ("pop", "b");
8015 /*-----------------------------------------------------------------*/
8016 /* emitPtrByteSet - emits code to set a byte from src through a */
8017 /* pointer register (R0, R1, or DPTR). */
8018 /*-----------------------------------------------------------------*/
8020 emitPtrByteSet (char *rname, int p_type, char *src)
8029 emitcode ("mov", "@%s,a", rname);
8032 emitcode ("mov", "@%s,%s", rname, src);
8037 emitcode ("movx", "@%s,a", rname);
8042 emitcode ("movx", "@dptr,a");
8047 emitcode ("lcall", "__gptrput");
8052 /*-----------------------------------------------------------------*/
8053 /* genUnpackBits - generates code for unpacking bits */
8054 /*-----------------------------------------------------------------*/
8056 genUnpackBits (operand * result, char *rname, int ptype)
8058 int offset = 0; /* result byte offset */
8059 int rsize; /* result size */
8060 int rlen = 0; /* remaining bitfield length */
8061 sym_link *etype; /* bitfield type information */
8062 int blen; /* bitfield length */
8063 int bstr; /* bitfield starting bit within byte */
8065 D(emitcode ("; genUnpackBits",""));
8067 etype = getSpec (operandType (result));
8068 rsize = getSize (operandType (result));
8069 blen = SPEC_BLEN (etype);
8070 bstr = SPEC_BSTR (etype);
8072 /* If the bitfield length is less than a byte */
8075 emitPtrByteGet (rname, ptype, FALSE);
8077 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8078 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8082 /* Bit field did not fit in a byte. Copy all
8083 but the partial byte at the end. */
8084 for (rlen=blen;rlen>=8;rlen-=8)
8086 emitPtrByteGet (rname, ptype, FALSE);
8087 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8089 emitcode ("inc", "%s", rname);
8092 /* Handle the partial byte at the end */
8095 emitPtrByteGet (rname, ptype, FALSE);
8096 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8097 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8105 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8110 /*-----------------------------------------------------------------*/
8111 /* genDataPointerGet - generates code when ptr offset is known */
8112 /*-----------------------------------------------------------------*/
8114 genDataPointerGet (operand * left,
8120 int size, offset = 0;
8122 D(emitcode ("; genDataPointerGet",""));
8124 aopOp (result, ic, TRUE);
8126 /* get the string representation of the name */
8127 l = aopGet (AOP (left), 0, FALSE, TRUE);
8128 size = AOP_SIZE (result);
8132 sprintf (buffer, "(%s + %d)", l + 1, offset);
8134 sprintf (buffer, "%s", l + 1);
8135 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8138 freeAsmop (left, NULL, ic, TRUE);
8139 freeAsmop (result, NULL, ic, TRUE);
8142 /*-----------------------------------------------------------------*/
8143 /* genNearPointerGet - emitcode for near pointer fetch */
8144 /*-----------------------------------------------------------------*/
8146 genNearPointerGet (operand * left,
8154 sym_link *rtype, *retype;
8155 sym_link *ltype = operandType (left);
8158 D(emitcode ("; genNearPointerGet",""));
8160 rtype = operandType (result);
8161 retype = getSpec (rtype);
8163 aopOp (left, ic, FALSE);
8165 /* if left is rematerialisable and
8166 result is not bitfield variable type and
8167 the left is pointer to data space i.e
8168 lower 128 bytes of space */
8169 if (AOP_TYPE (left) == AOP_IMMD &&
8170 !IS_BITFIELD (retype) &&
8171 DCL_TYPE (ltype) == POINTER)
8173 genDataPointerGet (left, result, ic);
8177 /* if the value is already in a pointer register
8178 then don't need anything more */
8179 if (!AOP_INPREG (AOP (left)))
8181 if (IS_AOP_PREG (left))
8183 // Aha, it is a pointer, just in disguise.
8184 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8187 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8188 __FILE__, __LINE__);
8193 emitcode ("mov", "a%s,%s", rname + 1, rname);
8194 rname++; // skip the '@'.
8199 /* otherwise get a free pointer register */
8201 preg = getFreePtr (ic, &aop, FALSE);
8202 emitcode ("mov", "%s,%s",
8204 aopGet (AOP (left), 0, FALSE, TRUE));
8209 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8211 //aopOp (result, ic, FALSE);
8212 aopOp (result, ic, result?TRUE:FALSE);
8214 /* if bitfield then unpack the bits */
8215 if (IS_BITFIELD (retype))
8216 genUnpackBits (result, rname, POINTER);
8219 /* we have can just get the values */
8220 int size = AOP_SIZE (result);
8225 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8228 emitcode ("mov", "a,@%s", rname);
8229 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8233 sprintf (buffer, "@%s", rname);
8234 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8238 emitcode ("inc", "%s", rname);
8242 /* now some housekeeping stuff */
8243 if (aop) /* we had to allocate for this iCode */
8245 if (pi) { /* post increment present */
8246 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8248 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8252 /* we did not allocate which means left
8253 already in a pointer register, then
8254 if size > 0 && this could be used again
8255 we have to point it back to where it
8257 if ((AOP_SIZE (result) > 1 &&
8258 !OP_SYMBOL (left)->remat &&
8259 (OP_SYMBOL (left)->liveTo > ic->seq ||
8263 int size = AOP_SIZE (result) - 1;
8265 emitcode ("dec", "%s", rname);
8270 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8271 freeAsmop (left, NULL, ic, TRUE);
8272 if (pi) pi->generated = 1;
8275 /*-----------------------------------------------------------------*/
8276 /* genPagedPointerGet - emitcode for paged pointer fetch */
8277 /*-----------------------------------------------------------------*/
8279 genPagedPointerGet (operand * left,
8287 sym_link *rtype, *retype;
8289 D(emitcode ("; genPagedPointerGet",""));
8291 rtype = operandType (result);
8292 retype = getSpec (rtype);
8294 aopOp (left, ic, FALSE);
8296 /* if the value is already in a pointer register
8297 then don't need anything more */
8298 if (!AOP_INPREG (AOP (left)))
8300 /* otherwise get a free pointer register */
8302 preg = getFreePtr (ic, &aop, FALSE);
8303 emitcode ("mov", "%s,%s",
8305 aopGet (AOP (left), 0, FALSE, TRUE));
8309 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8311 aopOp (result, ic, FALSE);
8313 /* if bitfield then unpack the bits */
8314 if (IS_BITFIELD (retype))
8315 genUnpackBits (result, rname, PPOINTER);
8318 /* we have can just get the values */
8319 int size = AOP_SIZE (result);
8325 emitcode ("movx", "a,@%s", rname);
8326 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8331 emitcode ("inc", "%s", rname);
8335 /* now some housekeeping stuff */
8336 if (aop) /* we had to allocate for this iCode */
8338 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8339 freeAsmop (NULL, aop, ic, TRUE);
8343 /* we did not allocate which means left
8344 already in a pointer register, then
8345 if size > 0 && this could be used again
8346 we have to point it back to where it
8348 if ((AOP_SIZE (result) > 1 &&
8349 !OP_SYMBOL (left)->remat &&
8350 (OP_SYMBOL (left)->liveTo > ic->seq ||
8354 int size = AOP_SIZE (result) - 1;
8356 emitcode ("dec", "%s", rname);
8361 freeAsmop (left, NULL, ic, TRUE);
8362 freeAsmop (result, NULL, ic, TRUE);
8363 if (pi) pi->generated = 1;
8367 /*--------------------------------------------------------------------*/
8368 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8369 /*--------------------------------------------------------------------*/
8371 loadDptrFromOperand (operand *op, bool loadBToo)
8373 if (AOP_TYPE (op) != AOP_STR)
8375 /* if this is remateriazable */
8376 if (AOP_TYPE (op) == AOP_IMMD)
8378 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8381 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8382 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8385 wassertl(FALSE, "need pointerCode");
8386 emitcode ("", "; mov b,???");
8387 /* genPointerGet and genPointerSet originally did different
8388 ** things for this case. Both seem wrong.
8389 ** from genPointerGet:
8390 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8391 ** from genPointerSet:
8392 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8397 else if (AOP_TYPE (op) == AOP_DPTR)
8401 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8402 emitcode ("push", "acc");
8403 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8404 emitcode ("push", "acc");
8405 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8406 emitcode ("pop", "dph");
8407 emitcode ("pop", "dpl");
8411 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8412 emitcode ("push", "acc");
8413 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8414 emitcode ("pop", "dpl");
8418 { /* we need to get it byte by byte */
8419 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8420 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8422 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8427 /*-----------------------------------------------------------------*/
8428 /* genFarPointerGet - gget value from far space */
8429 /*-----------------------------------------------------------------*/
8431 genFarPointerGet (operand * left,
8432 operand * result, iCode * ic, iCode * pi)
8435 sym_link *retype = getSpec (operandType (result));
8437 D(emitcode ("; genFarPointerGet",""));
8439 aopOp (left, ic, FALSE);
8440 loadDptrFromOperand (left, FALSE);
8442 /* so dptr now contains the address */
8443 aopOp (result, ic, FALSE);
8445 /* if bit then unpack */
8446 if (IS_BITFIELD (retype))
8447 genUnpackBits (result, "dptr", FPOINTER);
8450 size = AOP_SIZE (result);
8455 emitcode ("movx", "a,@dptr");
8456 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8458 emitcode ("inc", "dptr");
8462 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8463 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8464 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8467 freeAsmop (left, NULL, ic, TRUE);
8468 freeAsmop (result, NULL, ic, TRUE);
8471 /*-----------------------------------------------------------------*/
8472 /* genCodePointerGet - gget value from code space */
8473 /*-----------------------------------------------------------------*/
8475 genCodePointerGet (operand * left,
8476 operand * result, iCode * ic, iCode *pi)
8479 sym_link *retype = getSpec (operandType (result));
8481 D(emitcode ("; genCodePointerGet",""));
8483 aopOp (left, ic, FALSE);
8484 loadDptrFromOperand (left, FALSE);
8486 /* so dptr now contains the address */
8487 aopOp (result, ic, FALSE);
8489 /* if bit then unpack */
8490 if (IS_BITFIELD (retype))
8491 genUnpackBits (result, "dptr", CPOINTER);
8494 size = AOP_SIZE (result);
8501 emitcode ("clr", "a");
8502 emitcode ("movc", "a,@a+dptr");
8503 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8504 emitcode ("inc", "dptr");
8508 emitcode ("mov", "a,#0x%02x", offset);
8509 emitcode ("movc", "a,@a+dptr");
8510 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8515 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8516 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8517 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8520 freeAsmop (left, NULL, ic, TRUE);
8521 freeAsmop (result, NULL, ic, TRUE);
8524 /*-----------------------------------------------------------------*/
8525 /* genGenPointerGet - gget value from generic pointer space */
8526 /*-----------------------------------------------------------------*/
8528 genGenPointerGet (operand * left,
8529 operand * result, iCode * ic, iCode *pi)
8532 sym_link *retype = getSpec (operandType (result));
8534 D(emitcode ("; genGenPointerGet",""));
8536 aopOp (left, ic, FALSE);
8537 loadDptrFromOperand (left, TRUE);
8539 /* so dptr know contains the address */
8540 aopOp (result, ic, FALSE);
8542 /* if bit then unpack */
8543 if (IS_BITFIELD (retype))
8544 genUnpackBits (result, "dptr", GPOINTER);
8547 size = AOP_SIZE (result);
8552 emitcode ("lcall", "__gptrget");
8553 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8555 emitcode ("inc", "dptr");
8559 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8560 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8561 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8564 freeAsmop (left, NULL, ic, TRUE);
8565 freeAsmop (result, NULL, ic, TRUE);
8568 /*-----------------------------------------------------------------*/
8569 /* genPointerGet - generate code for pointer get */
8570 /*-----------------------------------------------------------------*/
8572 genPointerGet (iCode * ic, iCode *pi)
8574 operand *left, *result;
8575 sym_link *type, *etype;
8578 D(emitcode ("; genPointerGet",""));
8580 left = IC_LEFT (ic);
8581 result = IC_RESULT (ic);
8583 /* depending on the type of pointer we need to
8584 move it to the correct pointer register */
8585 type = operandType (left);
8586 etype = getSpec (type);
8587 /* if left is of type of pointer then it is simple */
8588 if (IS_PTR (type) && !IS_FUNC (type->next))
8589 p_type = DCL_TYPE (type);
8592 /* we have to go by the storage class */
8593 p_type = PTR_TYPE (SPEC_OCLS (etype));
8596 /* special case when cast remat */
8597 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8598 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8599 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8600 type = operandType (left);
8601 p_type = DCL_TYPE (type);
8603 /* now that we have the pointer type we assign
8604 the pointer values */
8610 genNearPointerGet (left, result, ic, pi);
8614 genPagedPointerGet (left, result, ic, pi);
8618 genFarPointerGet (left, result, ic, pi);
8622 genCodePointerGet (left, result, ic, pi);
8626 genGenPointerGet (left, result, ic, pi);
8634 /*-----------------------------------------------------------------*/
8635 /* genPackBits - generates code for packed bit storage */
8636 /*-----------------------------------------------------------------*/
8638 genPackBits (sym_link * etype,
8640 char *rname, int p_type)
8642 int offset = 0; /* source byte offset */
8643 int rlen = 0; /* remaining bitfield length */
8644 int blen; /* bitfield length */
8645 int bstr; /* bitfield starting bit within byte */
8646 int litval; /* source literal value (if AOP_LIT) */
8647 unsigned char mask; /* bitmask within current byte */
8649 D(emitcode ("; genPackBits",""));
8651 blen = SPEC_BLEN (etype);
8652 bstr = SPEC_BSTR (etype);
8654 /* If the bitfield length is less than a byte */
8657 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8658 (unsigned char) (0xFF >> (8 - bstr)));
8660 if (AOP_TYPE (right) == AOP_LIT)
8662 /* Case with a bitfield length <8 and literal source
8664 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8666 litval &= (~mask) & 0xff;
8667 emitPtrByteGet (rname, p_type, FALSE);
8668 if ((mask|litval)!=0xff)
8669 emitcode ("anl","a,#0x%02x", mask);
8671 emitcode ("orl","a,#0x%02x", litval);
8675 if ((blen==1) && (p_type!=GPOINTER))
8677 /* Case with a bitfield length == 1 and no generic pointer
8679 if (AOP_TYPE (right) == AOP_CRY)
8680 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8683 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8684 emitcode ("rrc","a");
8686 emitPtrByteGet (rname, p_type, FALSE);
8687 emitcode ("mov","acc.%d,c",bstr);
8691 /* Case with a bitfield length < 8 and arbitrary source
8693 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8694 /* shift and mask source value */
8696 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8698 /* transfer A to B and get next byte */
8699 emitPtrByteGet (rname, p_type, TRUE);
8701 emitcode ("anl", "a,#0x%02x", mask);
8702 emitcode ("orl", "a,b");
8703 if (p_type == GPOINTER)
8704 emitcode ("pop", "b");
8708 emitPtrByteSet (rname, p_type, "a");
8712 /* Bit length is greater than 7 bits. In this case, copy */
8713 /* all except the partial byte at the end */
8714 for (rlen=blen;rlen>=8;rlen-=8)
8716 emitPtrByteSet (rname, p_type,
8717 aopGet (AOP (right), offset++, FALSE, TRUE) );
8719 emitcode ("inc", "%s", rname);
8722 /* If there was a partial byte at the end */
8725 mask = (((unsigned char) -1 << rlen) & 0xff);
8727 if (AOP_TYPE (right) == AOP_LIT)
8729 /* Case with partial byte and literal source
8731 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8732 litval >>= (blen-rlen);
8733 litval &= (~mask) & 0xff;
8734 emitPtrByteGet (rname, p_type, FALSE);
8735 if ((mask|litval)!=0xff)
8736 emitcode ("anl","a,#0x%02x", mask);
8738 emitcode ("orl","a,#0x%02x", litval);
8742 /* Case with partial byte and arbitrary source
8744 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8745 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8747 /* transfer A to B and get next byte */
8748 emitPtrByteGet (rname, p_type, TRUE);
8750 emitcode ("anl", "a,#0x%02x", mask);
8751 emitcode ("orl", "a,b");
8752 if (p_type == GPOINTER)
8753 emitcode ("pop", "b");
8755 emitPtrByteSet (rname, p_type, "a");
8761 /*-----------------------------------------------------------------*/
8762 /* genDataPointerSet - remat pointer to data space */
8763 /*-----------------------------------------------------------------*/
8765 genDataPointerSet (operand * right,
8769 int size, offset = 0;
8770 char *l, buffer[256];
8772 D(emitcode ("; genDataPointerSet",""));
8774 aopOp (right, ic, FALSE);
8776 l = aopGet (AOP (result), 0, FALSE, TRUE);
8777 size = AOP_SIZE (right);
8781 sprintf (buffer, "(%s + %d)", l + 1, offset);
8783 sprintf (buffer, "%s", l + 1);
8784 emitcode ("mov", "%s,%s", buffer,
8785 aopGet (AOP (right), offset++, FALSE, FALSE));
8788 freeAsmop (right, NULL, ic, TRUE);
8789 freeAsmop (result, NULL, ic, TRUE);
8792 /*-----------------------------------------------------------------*/
8793 /* genNearPointerSet - emitcode for near pointer put */
8794 /*-----------------------------------------------------------------*/
8796 genNearPointerSet (operand * right,
8804 sym_link *retype, *letype;
8805 sym_link *ptype = operandType (result);
8807 D(emitcode ("; genNearPointerSet",""));
8809 retype = getSpec (operandType (right));
8810 letype = getSpec (ptype);
8811 aopOp (result, ic, FALSE);
8813 /* if the result is rematerializable &
8814 in data space & not a bit variable */
8815 if (AOP_TYPE (result) == AOP_IMMD &&
8816 DCL_TYPE (ptype) == POINTER &&
8817 !IS_BITVAR (retype) &&
8818 !IS_BITVAR (letype))
8820 genDataPointerSet (right, result, ic);
8824 /* if the value is already in a pointer register
8825 then don't need anything more */
8826 if (!AOP_INPREG (AOP (result)))
8829 //AOP_TYPE (result) == AOP_STK
8833 // Aha, it is a pointer, just in disguise.
8834 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8837 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8838 __FILE__, __LINE__);
8843 emitcode ("mov", "a%s,%s", rname + 1, rname);
8844 rname++; // skip the '@'.
8849 /* otherwise get a free pointer register */
8851 preg = getFreePtr (ic, &aop, FALSE);
8852 emitcode ("mov", "%s,%s",
8854 aopGet (AOP (result), 0, FALSE, TRUE));
8860 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8863 aopOp (right, ic, FALSE);
8865 /* if bitfield then unpack the bits */
8866 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8867 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8870 /* we have can just get the values */
8871 int size = AOP_SIZE (right);
8876 l = aopGet (AOP (right), offset, FALSE, TRUE);
8880 emitcode ("mov", "@%s,a", rname);
8883 emitcode ("mov", "@%s,%s", rname, l);
8885 emitcode ("inc", "%s", rname);
8890 /* now some housekeeping stuff */
8891 if (aop) /* we had to allocate for this iCode */
8894 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8895 freeAsmop (NULL, aop, ic, TRUE);
8899 /* we did not allocate which means left
8900 already in a pointer register, then
8901 if size > 0 && this could be used again
8902 we have to point it back to where it
8904 if ((AOP_SIZE (right) > 1 &&
8905 !OP_SYMBOL (result)->remat &&
8906 (OP_SYMBOL (result)->liveTo > ic->seq ||
8910 int size = AOP_SIZE (right) - 1;
8912 emitcode ("dec", "%s", rname);
8917 if (pi) pi->generated = 1;
8918 freeAsmop (result, NULL, ic, TRUE);
8919 freeAsmop (right, NULL, ic, TRUE);
8922 /*-----------------------------------------------------------------*/
8923 /* genPagedPointerSet - emitcode for Paged pointer put */
8924 /*-----------------------------------------------------------------*/
8926 genPagedPointerSet (operand * right,
8934 sym_link *retype, *letype;
8936 D(emitcode ("; genPagedPointerSet",""));
8938 retype = getSpec (operandType (right));
8939 letype = getSpec (operandType (result));
8941 aopOp (result, ic, FALSE);
8943 /* if the value is already in a pointer register
8944 then don't need anything more */
8945 if (!AOP_INPREG (AOP (result)))
8947 /* otherwise get a free pointer register */
8949 preg = getFreePtr (ic, &aop, FALSE);
8950 emitcode ("mov", "%s,%s",
8952 aopGet (AOP (result), 0, FALSE, TRUE));
8956 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8958 aopOp (right, ic, FALSE);
8960 /* if bitfield then unpack the bits */
8961 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8962 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8965 /* we have can just get the values */
8966 int size = AOP_SIZE (right);
8971 l = aopGet (AOP (right), offset, FALSE, TRUE);
8974 emitcode ("movx", "@%s,a", rname);
8977 emitcode ("inc", "%s", rname);
8983 /* now some housekeeping stuff */
8984 if (aop) /* we had to allocate for this iCode */
8987 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8988 freeAsmop (NULL, aop, ic, TRUE);
8992 /* we did not allocate which means left
8993 already in a pointer register, then
8994 if size > 0 && this could be used again
8995 we have to point it back to where it
8997 if (AOP_SIZE (right) > 1 &&
8998 !OP_SYMBOL (result)->remat &&
8999 (OP_SYMBOL (result)->liveTo > ic->seq ||
9002 int size = AOP_SIZE (right) - 1;
9004 emitcode ("dec", "%s", rname);
9009 if (pi) pi->generated = 1;
9010 freeAsmop (result, NULL, ic, TRUE);
9011 freeAsmop (right, NULL, ic, TRUE);
9016 /*-----------------------------------------------------------------*/
9017 /* genFarPointerSet - set value from far space */
9018 /*-----------------------------------------------------------------*/
9020 genFarPointerSet (operand * right,
9021 operand * result, iCode * ic, iCode * pi)
9024 sym_link *retype = getSpec (operandType (right));
9025 sym_link *letype = getSpec (operandType (result));
9027 D(emitcode ("; genFarPointerSet",""));
9029 aopOp (result, ic, FALSE);
9030 loadDptrFromOperand (result, FALSE);
9032 /* so dptr know contains the address */
9033 aopOp (right, ic, FALSE);
9035 /* if bit then unpack */
9036 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9037 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9040 size = AOP_SIZE (right);
9045 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9047 emitcode ("movx", "@dptr,a");
9049 emitcode ("inc", "dptr");
9052 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9053 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9054 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9057 freeAsmop (result, NULL, ic, TRUE);
9058 freeAsmop (right, NULL, ic, TRUE);
9061 /*-----------------------------------------------------------------*/
9062 /* genGenPointerSet - set value from generic pointer space */
9063 /*-----------------------------------------------------------------*/
9065 genGenPointerSet (operand * right,
9066 operand * result, iCode * ic, iCode * pi)
9069 sym_link *retype = getSpec (operandType (right));
9070 sym_link *letype = getSpec (operandType (result));
9072 D(emitcode ("; genGenPointerSet",""));
9074 aopOp (result, ic, FALSE);
9075 loadDptrFromOperand (result, TRUE);
9077 /* so dptr know contains the address */
9078 aopOp (right, ic, FALSE);
9080 /* if bit then unpack */
9081 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9082 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9085 size = AOP_SIZE (right);
9090 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9092 emitcode ("lcall", "__gptrput");
9094 emitcode ("inc", "dptr");
9098 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9099 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9100 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9103 freeAsmop (result, NULL, ic, TRUE);
9104 freeAsmop (right, NULL, ic, TRUE);
9107 /*-----------------------------------------------------------------*/
9108 /* genPointerSet - stores the value into a pointer location */
9109 /*-----------------------------------------------------------------*/
9111 genPointerSet (iCode * ic, iCode *pi)
9113 operand *right, *result;
9114 sym_link *type, *etype;
9117 D(emitcode ("; genPointerSet",""));
9119 right = IC_RIGHT (ic);
9120 result = IC_RESULT (ic);
9122 /* depending on the type of pointer we need to
9123 move it to the correct pointer register */
9124 type = operandType (result);
9125 etype = getSpec (type);
9126 /* if left is of type of pointer then it is simple */
9127 if (IS_PTR (type) && !IS_FUNC (type->next))
9129 p_type = DCL_TYPE (type);
9133 /* we have to go by the storage class */
9134 p_type = PTR_TYPE (SPEC_OCLS (etype));
9137 /* special case when cast remat */
9138 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9139 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9140 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9141 type = operandType (result);
9142 p_type = DCL_TYPE (type);
9144 /* now that we have the pointer type we assign
9145 the pointer values */
9151 genNearPointerSet (right, result, ic, pi);
9155 genPagedPointerSet (right, result, ic, pi);
9159 genFarPointerSet (right, result, ic, pi);
9163 genGenPointerSet (right, result, ic, pi);
9167 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9168 "genPointerSet: illegal pointer type");
9173 /*-----------------------------------------------------------------*/
9174 /* genIfx - generate code for Ifx statement */
9175 /*-----------------------------------------------------------------*/
9177 genIfx (iCode * ic, iCode * popIc)
9179 operand *cond = IC_COND (ic);
9182 D(emitcode ("; genIfx",""));
9184 aopOp (cond, ic, FALSE);
9186 /* get the value into acc */
9187 if (AOP_TYPE (cond) != AOP_CRY)
9191 /* the result is now in the accumulator */
9192 freeAsmop (cond, NULL, ic, TRUE);
9194 /* if there was something to be popped then do it */
9198 /* if the condition is a bit variable */
9199 if (isbit && IS_ITEMP (cond) &&
9201 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9202 else if (isbit && !IS_ITEMP (cond))
9203 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9205 genIfxJump (ic, "a", NULL, NULL, NULL);
9210 /*-----------------------------------------------------------------*/
9211 /* genAddrOf - generates code for address of */
9212 /*-----------------------------------------------------------------*/
9214 genAddrOf (iCode * ic)
9216 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9219 D(emitcode ("; genAddrOf",""));
9221 aopOp (IC_RESULT (ic), ic, FALSE);
9223 /* if the operand is on the stack then we
9224 need to get the stack offset of this
9228 /* if it has an offset then we need to compute
9232 emitcode ("mov", "a,_bp");
9233 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9234 ((char) (sym->stack - _G.nRegsSaved)) :
9235 ((char) sym->stack)) & 0xff);
9236 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9240 /* we can just move _bp */
9241 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9243 /* fill the result with zero */
9244 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9249 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9255 /* object not on stack then we need the name */
9256 size = AOP_SIZE (IC_RESULT (ic));
9261 char s[SDCC_NAME_MAX];
9263 sprintf (s, "#(%s >> %d)",
9267 sprintf (s, "#%s", sym->rname);
9268 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9272 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9276 /*-----------------------------------------------------------------*/
9277 /* genFarFarAssign - assignment when both are in far space */
9278 /*-----------------------------------------------------------------*/
9280 genFarFarAssign (operand * result, operand * right, iCode * ic)
9282 int size = AOP_SIZE (right);
9286 D(emitcode ("; genFarFarAssign",""));
9288 /* first push the right side on to the stack */
9291 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9293 emitcode ("push", "acc");
9296 freeAsmop (right, NULL, ic, FALSE);
9297 /* now assign DPTR to result */
9298 aopOp (result, ic, FALSE);
9299 size = AOP_SIZE (result);
9302 emitcode ("pop", "acc");
9303 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9305 freeAsmop (result, NULL, ic, FALSE);
9309 /*-----------------------------------------------------------------*/
9310 /* genAssign - generate code for assignment */
9311 /*-----------------------------------------------------------------*/
9313 genAssign (iCode * ic)
9315 operand *result, *right;
9317 unsigned long lit = 0L;
9319 D(emitcode("; genAssign",""));
9321 result = IC_RESULT (ic);
9322 right = IC_RIGHT (ic);
9324 /* if they are the same */
9325 if (operandsEqu (result, right) &&
9326 !isOperandVolatile (result, FALSE) &&
9327 !isOperandVolatile (right, FALSE))
9330 aopOp (right, ic, FALSE);
9332 /* special case both in far space */
9333 if (AOP_TYPE (right) == AOP_DPTR &&
9334 IS_TRUE_SYMOP (result) &&
9335 isOperandInFarSpace (result))
9338 genFarFarAssign (result, right, ic);
9342 aopOp (result, ic, TRUE);
9344 /* if they are the same registers */
9345 if (sameRegs (AOP (right), AOP (result)) &&
9346 !isOperandVolatile (result, FALSE) &&
9347 !isOperandVolatile (right, FALSE))
9350 /* if the result is a bit */
9351 if (AOP_TYPE (result) == AOP_CRY)
9354 /* if the right size is a literal then
9355 we know what the value is */
9356 if (AOP_TYPE (right) == AOP_LIT)
9358 if (((int) operandLitValue (right)))
9359 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9361 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9365 /* the right is also a bit variable */
9366 if (AOP_TYPE (right) == AOP_CRY)
9368 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9369 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9375 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9379 /* bit variables done */
9381 size = AOP_SIZE (result);
9383 if (AOP_TYPE (right) == AOP_LIT)
9384 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9386 (AOP_TYPE (result) != AOP_REG) &&
9387 (AOP_TYPE (right) == AOP_LIT) &&
9388 !IS_FLOAT (operandType (right)) &&
9391 emitcode ("clr", "a");
9394 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9395 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9397 aopPut (AOP (result),
9398 aopGet (AOP (right), size, FALSE, FALSE),
9400 isOperandVolatile (result, FALSE));
9407 aopPut (AOP (result),
9408 aopGet (AOP (right), offset, FALSE, FALSE),
9410 isOperandVolatile (result, FALSE));
9416 freeAsmop (right, NULL, ic, TRUE);
9417 freeAsmop (result, NULL, ic, TRUE);
9420 /*-----------------------------------------------------------------*/
9421 /* genJumpTab - genrates code for jump table */
9422 /*-----------------------------------------------------------------*/
9424 genJumpTab (iCode * ic)
9426 symbol *jtab,*jtablo,*jtabhi;
9430 D(emitcode ("; genJumpTab",""));
9432 count = elementsInSet( IC_JTLABELS (ic) );
9436 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9437 if the switch argument is in an register.
9438 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9439 aopOp (IC_JTCOND (ic), ic, FALSE);
9440 /* get the condition into accumulator */
9441 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9443 /* multiply by three */
9444 emitcode ("add", "a,acc");
9445 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9446 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9448 jtab = newiTempLabel (NULL);
9449 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9450 emitcode ("jmp", "@a+dptr");
9451 emitcode ("", "%05d$:", jtab->key + 100);
9452 /* now generate the jump labels */
9453 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9454 jtab = setNextItem (IC_JTLABELS (ic)))
9455 emitcode ("ljmp", "%05d$", jtab->key + 100);
9459 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9460 if the switch argument is in an register.
9461 For n>6 this algorithm may be more compact */
9462 jtablo = newiTempLabel (NULL);
9463 jtabhi = newiTempLabel (NULL);
9465 /* get the condition into accumulator.
9466 Using b as temporary storage, if register push/pop is needed */
9467 aopOp (IC_JTCOND (ic), ic, FALSE);
9468 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9469 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9470 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9472 emitcode ("mov", "b,%s", l);
9475 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9479 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9480 emitcode ("movc", "a,@a+pc");
9481 emitcode ("push", "acc");
9484 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9485 emitcode ("movc", "a,@a+pc");
9486 emitcode ("push", "acc");
9490 /* this scales up to n<=255, but needs two more bytes
9492 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9493 emitcode ("movc", "a,@a+dptr");
9494 emitcode ("push", "acc");
9497 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9498 emitcode ("movc", "a,@a+dptr");
9499 emitcode ("push", "acc");
9502 emitcode ("ret", "");
9504 /* now generate jump table, LSB */
9505 emitcode ("", "%05d$:", jtablo->key + 100);
9506 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9507 jtab = setNextItem (IC_JTLABELS (ic)))
9508 emitcode (".db", "%05d$", jtab->key + 100);
9510 /* now generate jump table, MSB */
9511 emitcode ("", "%05d$:", jtabhi->key + 100);
9512 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9513 jtab = setNextItem (IC_JTLABELS (ic)))
9514 emitcode (".db", "%05d$>>8", jtab->key + 100);
9520 /*-----------------------------------------------------------------*/
9521 /* genCast - gen code for casting */
9522 /*-----------------------------------------------------------------*/
9524 genCast (iCode * ic)
9526 operand *result = IC_RESULT (ic);
9527 sym_link *ctype = operandType (IC_LEFT (ic));
9528 sym_link *rtype = operandType (IC_RIGHT (ic));
9529 operand *right = IC_RIGHT (ic);
9532 D(emitcode("; genCast",""));
9534 /* if they are equivalent then do nothing */
9535 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9538 aopOp (right, ic, FALSE);
9539 aopOp (result, ic, FALSE);
9541 /* if the result is a bit (and not a bitfield) */
9542 // if (AOP_TYPE (result) == AOP_CRY)
9543 if (IS_BITVAR (OP_SYMBOL (result)->type)
9544 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9546 /* if the right size is a literal then
9547 we know what the value is */
9548 if (AOP_TYPE (right) == AOP_LIT)
9550 if (((int) operandLitValue (right)))
9551 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9553 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9558 /* the right is also a bit variable */
9559 if (AOP_TYPE (right) == AOP_CRY)
9561 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9562 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9568 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9573 /* if they are the same size : or less */
9574 if (AOP_SIZE (result) <= AOP_SIZE (right))
9577 /* if they are in the same place */
9578 if (sameRegs (AOP (right), AOP (result)))
9581 /* if they in different places then copy */
9582 size = AOP_SIZE (result);
9586 aopPut (AOP (result),
9587 aopGet (AOP (right), offset, FALSE, FALSE),
9589 isOperandVolatile (result, FALSE));
9596 /* if the result is of type pointer */
9601 sym_link *type = operandType (right);
9602 sym_link *etype = getSpec (type);
9604 /* pointer to generic pointer */
9605 if (IS_GENPTR (ctype))
9608 p_type = DCL_TYPE (type);
9611 if (SPEC_SCLS(etype)==S_REGISTER) {
9612 // let's assume it is a generic pointer
9615 /* we have to go by the storage class */
9616 p_type = PTR_TYPE (SPEC_OCLS (etype));
9620 /* the first two bytes are known */
9621 size = GPTRSIZE - 1;
9625 aopPut (AOP (result),
9626 aopGet (AOP (right), offset, FALSE, FALSE),
9628 isOperandVolatile (result, FALSE));
9631 /* the last byte depending on type */
9633 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9638 // pointerTypeToGPByte will have bitched.
9642 sprintf(gpValStr, "#0x%d", gpVal);
9643 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9648 /* just copy the pointers */
9649 size = AOP_SIZE (result);
9653 aopPut (AOP (result),
9654 aopGet (AOP (right), offset, FALSE, FALSE),
9656 isOperandVolatile (result, FALSE));
9662 /* so we now know that the size of destination is greater
9663 than the size of the source */
9664 /* we move to result for the size of source */
9665 size = AOP_SIZE (right);
9669 aopPut (AOP (result),
9670 aopGet (AOP (right), offset, FALSE, FALSE),
9672 isOperandVolatile (result, FALSE));
9676 /* now depending on the sign of the source && destination */
9677 size = AOP_SIZE (result) - AOP_SIZE (right);
9678 /* if unsigned or not an integral type */
9679 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9682 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9686 /* we need to extend the sign :{ */
9687 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9690 emitcode ("rlc", "a");
9691 emitcode ("subb", "a,acc");
9693 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9696 /* we are done hurray !!!! */
9699 freeAsmop (right, NULL, ic, TRUE);
9700 freeAsmop (result, NULL, ic, TRUE);
9704 /*-----------------------------------------------------------------*/
9705 /* genDjnz - generate decrement & jump if not zero instrucion */
9706 /*-----------------------------------------------------------------*/
9708 genDjnz (iCode * ic, iCode * ifx)
9714 D(emitcode ("; genDjnz",""));
9716 /* if the if condition has a false label
9717 then we cannot save */
9721 /* if the minus is not of the form
9723 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9724 !IS_OP_LITERAL (IC_RIGHT (ic)))
9727 if (operandLitValue (IC_RIGHT (ic)) != 1)
9730 /* if the size of this greater than one then no
9732 if (getSize (operandType (IC_RESULT (ic))) > 1)
9735 /* otherwise we can save BIG */
9736 lbl = newiTempLabel (NULL);
9737 lbl1 = newiTempLabel (NULL);
9739 aopOp (IC_RESULT (ic), ic, FALSE);
9741 if (AOP_NEEDSACC(IC_RESULT(ic)))
9743 /* If the result is accessed indirectly via
9744 * the accumulator, we must explicitly write
9745 * it back after the decrement.
9747 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9749 if (strcmp(rByte, "a"))
9751 /* Something is hopelessly wrong */
9752 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9753 __FILE__, __LINE__);
9754 /* We can just give up; the generated code will be inefficient,
9757 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9760 emitcode ("dec", "%s", rByte);
9761 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9762 emitcode ("jnz", "%05d$", lbl->key + 100);
9764 else if (IS_AOP_PREG (IC_RESULT (ic)))
9766 emitcode ("dec", "%s",
9767 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9768 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9769 emitcode ("jnz", "%05d$", lbl->key + 100);
9773 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9776 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9777 emitcode ("", "%05d$:", lbl->key + 100);
9778 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9779 emitcode ("", "%05d$:", lbl1->key + 100);
9781 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9786 /*-----------------------------------------------------------------*/
9787 /* genReceive - generate code for a receive iCode */
9788 /*-----------------------------------------------------------------*/
9790 genReceive (iCode * ic)
9792 int size = getSize (operandType (IC_RESULT (ic)));
9794 D(emitcode ("; genReceive",""));
9796 if (ic->argreg == 1) { /* first parameter */
9797 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9798 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9799 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9805 for (offset = 0; offset<size; offset++)
9806 if (!strcmp (fReturn[offset], "a"))
9811 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9813 for (offset = size-1; offset>0; offset--)
9814 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9815 emitcode("mov","a,%s", fReturn[0]);
9817 aopOp (IC_RESULT (ic), ic, FALSE);
9819 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9820 isOperandVolatile (IC_RESULT (ic), FALSE));
9821 for (offset = 1; offset<size; offset++)
9822 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9823 isOperandVolatile (IC_RESULT (ic), FALSE));
9829 if (getTempRegs(tempRegs, size, ic))
9831 for (offset = 0; offset<size; offset++)
9832 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9833 aopOp (IC_RESULT (ic), ic, FALSE);
9834 for (offset = 0; offset<size; offset++)
9835 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9836 isOperandVolatile (IC_RESULT (ic), FALSE));
9841 offset = fReturnSizeMCS51 - size;
9843 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9844 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9847 aopOp (IC_RESULT (ic), ic, FALSE);
9848 size = AOP_SIZE (IC_RESULT (ic));
9851 emitcode ("pop", "acc");
9852 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9857 aopOp (IC_RESULT (ic), ic, FALSE);
9859 assignResultValue (IC_RESULT (ic));
9861 } else { /* second receive onwards */
9863 aopOp (IC_RESULT (ic), ic, FALSE);
9864 rb1off = ic->argreg;
9866 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9871 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9874 /*-----------------------------------------------------------------*/
9875 /* genDummyRead - generate code for dummy read of volatiles */
9876 /*-----------------------------------------------------------------*/
9878 genDummyRead (iCode * ic)
9883 D(emitcode("; genDummyRead",""));
9886 if (op && IS_SYMOP (op))
9888 aopOp (op, ic, FALSE);
9890 /* if the result is a bit */
9891 if (AOP_TYPE (op) == AOP_CRY)
9892 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9895 /* bit variables done */
9897 size = AOP_SIZE (op);
9901 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9906 freeAsmop (op, NULL, ic, TRUE);
9910 if (op && IS_SYMOP (op))
9912 aopOp (op, ic, FALSE);
9914 /* if the result is a bit */
9915 if (AOP_TYPE (op) == AOP_CRY)
9916 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9919 /* bit variables done */
9921 size = AOP_SIZE (op);
9925 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9930 freeAsmop (op, NULL, ic, TRUE);
9934 /*-----------------------------------------------------------------*/
9935 /* genCritical - generate code for start of a critical sequence */
9936 /*-----------------------------------------------------------------*/
9938 genCritical (iCode *ic)
9940 symbol *tlbl = newiTempLabel (NULL);
9942 D(emitcode("; genCritical",""));
9945 aopOp (IC_RESULT (ic), ic, TRUE);
9947 emitcode ("setb", "c");
9948 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9949 emitcode ("clr", "c");
9950 emitcode ("", "%05d$:", (tlbl->key + 100));
9953 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9955 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9961 /*-----------------------------------------------------------------*/
9962 /* genEndCritical - generate code for end of a critical sequence */
9963 /*-----------------------------------------------------------------*/
9965 genEndCritical (iCode *ic)
9967 D(emitcode("; genEndCritical",""));
9971 aopOp (IC_RIGHT (ic), ic, FALSE);
9972 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9974 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9975 emitcode ("mov", "ea,c");
9979 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9980 emitcode ("rrc", "a");
9981 emitcode ("mov", "ea,c");
9983 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9987 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9988 emitcode ("mov", "ea,c");
9992 /*-----------------------------------------------------------------*/
9993 /* gen51Code - generate code for 8051 based controllers */
9994 /*-----------------------------------------------------------------*/
9996 gen51Code (iCode * lic)
10000 /* int cseq = 0; */
10002 _G.currentFunc = NULL;
10003 lineHead = lineCurr = NULL;
10005 /* print the allocation information */
10006 if (allocInfo && currFunc)
10007 printAllocInfo (currFunc, codeOutFile);
10008 /* if debug information required */
10009 if (options.debug && currFunc)
10011 debugFile->writeFunction (currFunc, lic);
10013 /* stack pointer name */
10014 if (options.useXstack)
10020 for (ic = lic; ic; ic = ic->next)
10022 _G.current_iCode = ic;
10024 if (ic->lineno && cln != ic->lineno)
10028 debugFile->writeCLine(ic);
10030 if (!options.noCcodeInAsm) {
10031 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10032 printCLine(ic->filename, ic->lineno));
10037 if (ic->seqPoint && ic->seqPoint != cseq)
10039 emitcode ("", "; sequence point %d", ic->seqPoint);
10040 cseq = ic->seqPoint;
10043 if (options.iCodeInAsm) {
10044 char regsInUse[80];
10047 for (i=0; i<8; i++) {
10048 sprintf (®sInUse[i],
10049 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10052 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10054 /* if the result is marked as
10055 spilt and rematerializable or code for
10056 this has already been generated then
10058 if (resultRemat (ic) || ic->generated)
10061 /* depending on the operation */
10081 /* IPOP happens only when trying to restore a
10082 spilt live range, if there is an ifx statement
10083 following this pop then the if statement might
10084 be using some of the registers being popped which
10085 would destory the contents of the register so
10086 we need to check for this condition and handle it */
10088 ic->next->op == IFX &&
10089 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10090 genIfx (ic->next, ic);
10108 genEndFunction (ic);
10128 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10145 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10149 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10156 /* note these two are xlated by algebraic equivalence
10157 during parsing SDCC.y */
10158 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10159 "got '>=' or '<=' shouldn't have come here");
10163 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10175 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10179 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10183 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10207 genRightShift (ic);
10210 case GET_VALUE_AT_ADDRESS:
10211 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10215 if (POINTER_SET (ic))
10216 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10242 addSet (&_G.sendSet, ic);
10245 case DUMMY_READ_VOLATILE:
10254 genEndCritical (ic);
10266 _G.current_iCode = NULL;
10268 /* now we are ready to call the
10269 peep hole optimizer */
10270 if (!options.nopeep)
10271 peepHole (&lineHead);
10273 /* now do the actual printing */
10274 printLine (lineHead, codeOutFile);