1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
83 static char *rb1regs[] = {
84 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
96 #define CLRC emitcode("clr","c")
97 #define SETC emitcode("setb","c")
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, const char *fmt,...)
121 char lb[INITIAL_INLINEASM];
129 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
140 //printf ("%s\n", lb);
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
148 lineCurr->ic = _G.current_iCode;
149 lineCurr->isComment = (*lbp==';');
153 /*-----------------------------------------------------------------*/
154 /* mcs51_emitDebuggerSymbol - associate the current code location */
155 /* with a debugger symbol */
156 /*-----------------------------------------------------------------*/
158 mcs51_emitDebuggerSymbol (char * debugSym)
161 emitcode ("", "%s ==.", debugSym);
165 /*-----------------------------------------------------------------*/
166 /* mova - moves specified value into accumulator */
167 /*-----------------------------------------------------------------*/
171 /* do some early peephole optimization */
172 if (!strcmp(x, "a") || !strcmp(x, "acc"))
175 emitcode("mov","a,%s", x);
178 /*-----------------------------------------------------------------*/
179 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
180 /*-----------------------------------------------------------------*/
182 getFreePtr (iCode * ic, asmop ** aopp, bool result)
184 bool r0iu = FALSE, r1iu = FALSE;
185 bool r0ou = FALSE, r1ou = FALSE;
187 /* the logic: if r0 & r1 used in the instruction
188 then we are in trouble otherwise */
190 /* first check if r0 & r1 are used by this
191 instruction, in which case we are in trouble */
192 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
193 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
198 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
199 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
201 /* if no usage of r0 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if no usage of r1 then return it */
213 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
214 (*aopp)->type = AOP_R1;
216 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
219 /* now we know they both have usage */
220 /* if r0 not used in this instruction */
223 /* push it if not already pushed */
226 emitcode ("mov", "b,%s",
227 mcs51_regWithIdx (R0_IDX)->dname);
230 else if (!_G.r0Pushed)
232 emitcode ("push", "%s",
233 mcs51_regWithIdx (R0_IDX)->dname);
237 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
238 (*aopp)->type = AOP_R0;
240 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
243 /* if r1 not used then */
247 /* push it if not already pushed */
250 emitcode ("mov", "b,%s",
251 mcs51_regWithIdx (R1_IDX)->dname);
254 else if (!_G.r1Pushed)
256 emitcode ("push", "%s",
257 mcs51_regWithIdx (R1_IDX)->dname);
261 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262 (*aopp)->type = AOP_R1;
263 return mcs51_regWithIdx (R1_IDX);
266 /* I said end of world, but not quite end of world yet */
268 /* we can push it on the stack */
269 (*aopp)->type = AOP_STK;
272 /* in the case that result AND left AND right needs a pointer reg
273 we can safely use the result's */
274 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
275 (*aopp)->type = AOP_R0;
276 return mcs51_regWithIdx (R0_IDX);
278 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
279 (*aopp)->type = AOP_R1;
280 return mcs51_regWithIdx (R1_IDX);
284 /* now this is REALLY the end of the world */
285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
286 "getFreePtr should never reach here");
291 /*-----------------------------------------------------------------*/
292 /* getTempRegs - initialize an array of pointers to GPR registers */
293 /* that are not in use. Returns 1 if the requested */
294 /* number of registers were available, 0 otherwise. */
295 /*-----------------------------------------------------------------*/
297 getTempRegs(regs **tempRegs, int size, iCode *ic)
304 ic = _G.current_iCode;
310 freeRegs = newBitVect(8);
311 bitVectSetBit (freeRegs, R2_IDX);
312 bitVectSetBit (freeRegs, R3_IDX);
313 bitVectSetBit (freeRegs, R4_IDX);
314 bitVectSetBit (freeRegs, R5_IDX);
315 bitVectSetBit (freeRegs, R6_IDX);
316 bitVectSetBit (freeRegs, R7_IDX);
318 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
320 bitVect * newfreeRegs;
321 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
322 freeBitVect(freeRegs);
323 freeRegs = newfreeRegs;
325 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
328 for (i=0; i<freeRegs->size; i++)
330 if (bitVectBitValue(freeRegs,i))
331 tempRegs[offset++] = mcs51_regWithIdx(i);
334 freeBitVect(freeRegs);
339 freeBitVect(freeRegs);
344 /*-----------------------------------------------------------------*/
345 /* newAsmop - creates a new asmOp */
346 /*-----------------------------------------------------------------*/
348 newAsmop (short type)
352 aop = Safe_calloc (1, sizeof (asmop));
357 /*-----------------------------------------------------------------*/
358 /* pointerCode - returns the code for a pointer type */
359 /*-----------------------------------------------------------------*/
361 pointerCode (sym_link * etype)
364 return PTR_TYPE (SPEC_OCLS (etype));
369 /*-----------------------------------------------------------------*/
370 /* leftRightUseAcc - returns size of accumulator use by operands */
371 /*-----------------------------------------------------------------*/
373 leftRightUseAcc(iCode *ic)
382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383 "null iCode pointer");
390 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
393 size = getSize (OP_SYMBOL (op)->type);
398 else if (ic->op == JUMPTABLE)
401 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
404 size = getSize (OP_SYMBOL (op)->type);
412 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
415 size = getSize (OP_SYMBOL (op)->type);
420 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
423 size = getSize (OP_SYMBOL (op)->type);
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
445 wassertl (ic != NULL, "Got a null iCode");
446 wassertl (sym != NULL, "Got a null symbol");
448 space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if (sym->onStack || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
470 if (_G.accInUse || leftRightUseAcc (ic))
471 emitcode ("push", "acc");
473 emitcode ("mov", "a,_bp");
474 emitcode ("add", "a,#0x%02x",
476 ((char) (sym->stack - _G.nRegsSaved)) :
477 ((char) sym->stack)) & 0xff);
478 emitcode ("mov", "%s,a",
479 aop->aopu.aop_ptr->name);
481 if (_G.accInUse || leftRightUseAcc (ic))
482 emitcode ("pop", "acc");
485 emitcode ("mov", "%s,#%s",
486 aop->aopu.aop_ptr->name,
488 aop->paged = space->paged;
491 aop->aopu.aop_stk = sym->stack;
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
507 //printTypeChainRaw(sym->type, NULL);
508 //printf("space = %s\n", space ? space->sname : "NULL");
509 sym->aop = aop = newAsmop (AOP_DIR);
510 aop->aopu.aop_dir = sym->rname;
511 aop->size = getSize (sym->type);
515 /* special case for a function */
516 if (IS_FUNC (sym->type))
518 sym->aop = aop = newAsmop (AOP_IMMD);
519 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
520 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
521 aop->size = FPTRSIZE;
525 /* only remaining is far space */
526 /* in which case DPTR gets the address */
527 sym->aop = aop = newAsmop (AOP_DPTR);
528 emitcode ("mov", "dptr,#%s", sym->rname);
529 aop->size = getSize (sym->type);
531 /* if it is in code space */
532 if (IN_CODESPACE (space))
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object */
540 /*-----------------------------------------------------------------*/
542 aopForRemat (symbol * sym)
544 iCode *ic = sym->rematiCode;
545 asmop *aop = newAsmop (AOP_IMMD);
552 val += (int) operandLitValue (IC_RIGHT (ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue (IC_RIGHT (ic));
555 else if (IS_CAST_ICODE(ic)) {
556 sym_link *from_type = operandType(IC_RIGHT(ic));
557 aop->aopu.aop_immd.from_cast_remat = 1;
558 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
559 ptr_type = DCL_TYPE(from_type);
560 if (ptr_type == IPOINTER) {
567 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
571 sprintf (buffer, "(%s %c 0x%04x)",
572 OP_SYMBOL (IC_LEFT (ic))->rname,
573 val >= 0 ? '+' : '-',
576 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
579 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
580 /* set immd2 field if required */
581 if (aop->aopu.aop_immd.from_cast_remat) {
582 sprintf(buffer,"#0x%02x",ptr_type);
583 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
584 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
590 /*-----------------------------------------------------------------*/
591 /* regsInCommon - two operands have some registers in common */
592 /*-----------------------------------------------------------------*/
594 regsInCommon (operand * op1, operand * op2)
599 /* if they have registers in common */
600 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
603 sym1 = OP_SYMBOL (op1);
604 sym2 = OP_SYMBOL (op2);
606 if (sym1->nRegs == 0 || sym2->nRegs == 0)
609 for (i = 0; i < sym1->nRegs; i++)
615 for (j = 0; j < sym2->nRegs; j++)
620 if (sym2->regs[j] == sym1->regs[i])
628 /*-----------------------------------------------------------------*/
629 /* operandsEqu - equivalent */
630 /*-----------------------------------------------------------------*/
632 operandsEqu (operand * op1, operand * op2)
636 /* if they not symbols */
637 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
640 sym1 = OP_SYMBOL (op1);
641 sym2 = OP_SYMBOL (op2);
643 /* if both are itemps & one is spilt
644 and the other is not then false */
645 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
646 sym1->isspilt != sym2->isspilt)
649 /* if they are the same */
653 if (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 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1615 emitcode ("cpl", "c");
1616 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1620 tlbl=newiTempLabel(NULL);
1621 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1622 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1623 IS_AOP_PREG (IC_LEFT (ic)))
1625 emitcode ("cjne", "%s,#0x01,%05d$",
1626 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1631 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1633 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1635 emitcode ("", "%05d$:", tlbl->key + 100);
1636 outBitC (IC_RESULT(ic));
1640 size = AOP_SIZE (IC_RESULT (ic));
1643 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1645 emitcode ("cpl", "a");
1646 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1651 /* release the aops */
1652 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1653 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1656 /*-----------------------------------------------------------------*/
1657 /* genUminusFloat - unary minus for floating points */
1658 /*-----------------------------------------------------------------*/
1660 genUminusFloat (operand * op, operand * result)
1662 int size, offset = 0;
1665 D(emitcode ("; genUminusFloat",""));
1667 /* for this we just copy and then flip the bit */
1669 size = AOP_SIZE (op) - 1;
1673 aopPut (AOP (result),
1674 aopGet (AOP (op), offset, FALSE, FALSE),
1676 isOperandVolatile (result, FALSE));
1680 l = aopGet (AOP (op), offset, FALSE, FALSE);
1684 emitcode ("cpl", "acc.7");
1685 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1688 /*-----------------------------------------------------------------*/
1689 /* genUminus - unary minus code generation */
1690 /*-----------------------------------------------------------------*/
1692 genUminus (iCode * ic)
1695 sym_link *optype, *rtype;
1698 D(emitcode ("; genUminus",""));
1701 aopOp (IC_LEFT (ic), ic, FALSE);
1702 aopOp (IC_RESULT (ic), ic, TRUE);
1704 /* if both in bit space then special
1706 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1707 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1710 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1711 emitcode ("cpl", "c");
1712 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1716 optype = operandType (IC_LEFT (ic));
1717 rtype = operandType (IC_RESULT (ic));
1719 /* if float then do float stuff */
1720 if (IS_FLOAT (optype))
1722 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1726 /* otherwise subtract from zero */
1727 size = AOP_SIZE (IC_LEFT (ic));
1732 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1733 if (!strcmp (l, "a"))
1737 emitcode ("cpl", "a");
1738 emitcode ("addc", "a,#0");
1744 emitcode ("clr", "a");
1745 emitcode ("subb", "a,%s", l);
1747 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1750 /* if any remaining bytes in the result */
1751 /* we just need to propagate the sign */
1752 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1754 emitcode ("rlc", "a");
1755 emitcode ("subb", "a,acc");
1757 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1761 /* release the aops */
1762 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1763 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1766 /*-----------------------------------------------------------------*/
1767 /* saveRegisters - will look for a call and save the registers */
1768 /*-----------------------------------------------------------------*/
1770 saveRegisters (iCode * lic)
1777 for (ic = lic; ic; ic = ic->next)
1778 if (ic->op == CALL || ic->op == PCALL)
1783 fprintf (stderr, "found parameter push with no function call\n");
1787 /* if the registers have been saved already or don't need to be then
1791 if (IS_SYMOP(IC_LEFT(ic)) &&
1792 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1793 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1796 /* safe the registers in use at this time but skip the
1797 ones for the result */
1798 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1799 mcs51_rUmaskForOp (IC_RESULT(ic)));
1802 if (options.useXstack)
1804 if (bitVectBitValue (rsave, R0_IDX))
1805 emitcode ("mov", "b,r0");
1806 emitcode ("mov", "r0,%s", spname);
1807 for (i = 0; i < mcs51_nRegs; i++)
1809 if (bitVectBitValue (rsave, i))
1812 emitcode ("mov", "a,b");
1814 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1815 emitcode ("movx", "@r0,a");
1816 emitcode ("inc", "r0");
1819 emitcode ("mov", "%s,r0", spname);
1820 if (bitVectBitValue (rsave, R0_IDX))
1821 emitcode ("mov", "r0,b");
1824 for (i = 0; i < mcs51_nRegs; i++)
1826 if (bitVectBitValue (rsave, i))
1827 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1831 /*-----------------------------------------------------------------*/
1832 /* unsaveRegisters - pop the pushed registers */
1833 /*-----------------------------------------------------------------*/
1835 unsaveRegisters (iCode * ic)
1840 /* restore the registers in use at this time but skip the
1841 ones for the result */
1842 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1843 mcs51_rUmaskForOp (IC_RESULT(ic)));
1845 if (options.useXstack)
1847 emitcode ("mov", "r0,%s", spname);
1848 for (i = mcs51_nRegs; i >= 0; i--)
1850 if (bitVectBitValue (rsave, i))
1852 emitcode ("dec", "r0");
1853 emitcode ("movx", "a,@r0");
1855 emitcode ("mov", "b,a");
1857 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1861 emitcode ("mov", "%s,r0", spname);
1862 if (bitVectBitValue (rsave, R0_IDX))
1863 emitcode ("mov", "r0,b");
1866 for (i = mcs51_nRegs; i >= 0; i--)
1868 if (bitVectBitValue (rsave, i))
1869 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1875 /*-----------------------------------------------------------------*/
1877 /*-----------------------------------------------------------------*/
1879 pushSide (operand * oper, int size)
1884 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1885 if (AOP_TYPE (oper) != AOP_REG &&
1886 AOP_TYPE (oper) != AOP_DIR &&
1890 emitcode ("push", "acc");
1893 emitcode ("push", "%s", l);
1897 /*-----------------------------------------------------------------*/
1898 /* assignResultValue - */
1899 /*-----------------------------------------------------------------*/
1901 assignResultValue (operand * oper)
1904 int size = AOP_SIZE (oper);
1907 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1913 /*-----------------------------------------------------------------*/
1914 /* genXpush - pushes onto the external stack */
1915 /*-----------------------------------------------------------------*/
1917 genXpush (iCode * ic)
1919 asmop *aop = newAsmop (0);
1921 int size, offset = 0;
1923 D(emitcode ("; genXpush",""));
1925 aopOp (IC_LEFT (ic), ic, FALSE);
1926 r = getFreePtr (ic, &aop, FALSE);
1929 emitcode ("mov", "%s,_spx", r->name);
1931 size = AOP_SIZE (IC_LEFT (ic));
1935 char *l = aopGet (AOP (IC_LEFT (ic)),
1936 offset++, FALSE, FALSE);
1938 emitcode ("movx", "@%s,a", r->name);
1939 emitcode ("inc", "%s", r->name);
1944 emitcode ("mov", "_spx,%s", r->name);
1946 freeAsmop (NULL, aop, ic, TRUE);
1947 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1950 /*-----------------------------------------------------------------*/
1951 /* genIpush - genrate code for pushing this gets a little complex */
1952 /*-----------------------------------------------------------------*/
1954 genIpush (iCode * ic)
1956 int size, offset = 0;
1959 D(emitcode ("; genIpush",""));
1961 /* if this is not a parm push : ie. it is spill push
1962 and spill push is always done on the local stack */
1966 /* and the item is spilt then do nothing */
1967 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1970 aopOp (IC_LEFT (ic), ic, FALSE);
1971 size = AOP_SIZE (IC_LEFT (ic));
1972 /* push it on the stack */
1975 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1981 emitcode ("push", "%s", l);
1986 /* this is a paramter push: in this case we call
1987 the routine to find the call and save those
1988 registers that need to be saved */
1991 /* if use external stack then call the external
1992 stack pushing routine */
1993 if (options.useXstack)
1999 /* then do the push */
2000 aopOp (IC_LEFT (ic), ic, FALSE);
2003 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2004 size = AOP_SIZE (IC_LEFT (ic));
2008 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2009 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2010 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2014 emitcode ("push", "acc");
2017 emitcode ("push", "%s", l);
2020 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2023 /*-----------------------------------------------------------------*/
2024 /* genIpop - recover the registers: can happen only for spilling */
2025 /*-----------------------------------------------------------------*/
2027 genIpop (iCode * ic)
2031 D(emitcode ("; genIpop",""));
2033 /* if the temp was not pushed then */
2034 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2037 aopOp (IC_LEFT (ic), ic, FALSE);
2038 size = AOP_SIZE (IC_LEFT (ic));
2039 offset = (size - 1);
2041 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /*-----------------------------------------------------------------*/
2048 /* unsaveRBank - restores the resgister bank from stack */
2049 /*-----------------------------------------------------------------*/
2051 unsaveRBank (int bank, iCode * ic, bool popPsw)
2057 if (options.useXstack)
2061 /* Assume r0 is available for use. */
2062 r = mcs51_regWithIdx (R0_IDX);;
2067 r = getFreePtr (ic, &aop, FALSE);
2069 emitcode ("mov", "%s,_spx", r->name);
2074 if (options.useXstack)
2076 emitcode ("movx", "a,@%s", r->name);
2077 emitcode ("mov", "psw,a");
2078 emitcode ("dec", "%s", r->name);
2082 emitcode ("pop", "psw");
2086 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2088 if (options.useXstack)
2090 emitcode ("movx", "a,@%s", r->name);
2091 emitcode ("mov", "(%s+%d),a",
2092 regs8051[i].base, 8 * bank + regs8051[i].offset);
2093 emitcode ("dec", "%s", r->name);
2097 emitcode ("pop", "(%s+%d)",
2098 regs8051[i].base, 8 * bank + regs8051[i].offset);
2101 if (options.useXstack)
2103 emitcode ("mov", "_spx,%s", r->name);
2108 freeAsmop (NULL, aop, ic, TRUE);
2112 /*-----------------------------------------------------------------*/
2113 /* saveRBank - saves an entire register bank on the stack */
2114 /*-----------------------------------------------------------------*/
2116 saveRBank (int bank, iCode * ic, bool pushPsw)
2122 if (options.useXstack)
2126 /* Assume r0 is available for use. */
2127 r = mcs51_regWithIdx (R0_IDX);;
2132 r = getFreePtr (ic, &aop, FALSE);
2134 emitcode ("mov", "%s,_spx", r->name);
2137 for (i = 0; i < mcs51_nRegs; i++)
2139 if (options.useXstack)
2141 emitcode ("inc", "%s", r->name);
2142 emitcode ("mov", "a,(%s+%d)",
2143 regs8051[i].base, 8 * bank + regs8051[i].offset);
2144 emitcode ("movx", "@%s,a", r->name);
2147 emitcode ("push", "(%s+%d)",
2148 regs8051[i].base, 8 * bank + regs8051[i].offset);
2153 if (options.useXstack)
2155 emitcode ("mov", "a,psw");
2156 emitcode ("movx", "@%s,a", r->name);
2157 emitcode ("inc", "%s", r->name);
2158 emitcode ("mov", "_spx,%s", r->name);
2163 emitcode ("push", "psw");
2166 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2171 freeAsmop (NULL, aop, ic, TRUE);
2180 /*-----------------------------------------------------------------*/
2181 /* genSend - gen code for SEND */
2182 /*-----------------------------------------------------------------*/
2183 static void genSend(set *sendSet)
2188 for (sic = setFirstItem (_G.sendSet); sic;
2189 sic = setNextItem (_G.sendSet)) {
2190 int size, offset = 0;
2191 aopOp (IC_LEFT (sic), sic, FALSE);
2192 size = AOP_SIZE (IC_LEFT (sic));
2194 if (sic->argreg == 1) {
2196 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2198 if (strcmp (l, fReturn[offset]))
2199 emitcode ("mov", "%s,%s", fReturn[offset], l);
2205 emitcode ("mov","b1_%d,%s",rb1_count++,
2206 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2209 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2213 /*-----------------------------------------------------------------*/
2214 /* genCall - generates a call statement */
2215 /*-----------------------------------------------------------------*/
2217 genCall (iCode * ic)
2220 // bool restoreBank = FALSE;
2221 bool swapBanks = FALSE;
2223 D(emitcode("; genCall",""));
2225 dtype = operandType (IC_LEFT (ic));
2226 /* if send set is not empty the assign */
2229 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2230 genSend(reverseSet(_G.sendSet));
2232 genSend(_G.sendSet);
2238 /* if we are calling a not _naked function that is not using
2239 the same register bank then we need to save the
2240 destination registers on the stack */
2241 dtype = operandType (IC_LEFT (ic));
2242 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2243 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2244 !IFFUNC_ISISR (dtype))
2249 /* if caller saves & we have not saved then */
2255 emitcode ("mov", "psw,#0x%02x",
2256 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2260 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2261 OP_SYMBOL (IC_LEFT (ic))->rname :
2262 OP_SYMBOL (IC_LEFT (ic))->name));
2266 emitcode ("mov", "psw,#0x%02x",
2267 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2270 /* if we need assign a result value */
2271 if ((IS_ITEMP (IC_RESULT (ic)) &&
2272 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2273 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2274 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2275 IS_TRUE_SYMOP (IC_RESULT (ic)))
2279 aopOp (IC_RESULT (ic), ic, FALSE);
2282 assignResultValue (IC_RESULT (ic));
2284 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2287 /* adjust the stack for parameters if
2292 if (ic->parmBytes > 3)
2294 emitcode ("mov", "a,%s", spname);
2295 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2296 emitcode ("mov", "%s,a", spname);
2299 for (i = 0; i < ic->parmBytes; i++)
2300 emitcode ("dec", "%s", spname);
2303 /* if we hade saved some registers then unsave them */
2304 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2305 unsaveRegisters (ic);
2307 // /* if register bank was saved then pop them */
2309 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2312 /*-----------------------------------------------------------------*/
2313 /* -10l - generates a call by pointer statement */
2314 /*-----------------------------------------------------------------*/
2316 genPcall (iCode * ic)
2319 symbol *rlbl = newiTempLabel (NULL);
2320 // bool restoreBank=FALSE;
2321 bool swapBanks = FALSE;
2323 D(emitcode("; genPCall",""));
2325 /* if caller saves & we have not saved then */
2329 /* if we are calling a not _naked function that is not using
2330 the same register bank then we need to save the
2331 destination registers on the stack */
2332 dtype = operandType (IC_LEFT (ic))->next;
2333 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2334 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2335 !IFFUNC_ISISR (dtype))
2337 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2338 // restoreBank=TRUE;
2340 // need caution message to user here
2343 /* push the return address on to the stack */
2344 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2345 emitcode ("push", "acc");
2346 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2347 emitcode ("push", "acc");
2349 /* now push the calling address */
2350 aopOp (IC_LEFT (ic), ic, FALSE);
2352 pushSide (IC_LEFT (ic), FPTRSIZE);
2354 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2356 /* if send set is not empty the assign */
2359 genSend(reverseSet(_G.sendSet));
2365 emitcode ("mov", "psw,#0x%02x",
2366 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2370 emitcode ("ret", "");
2371 emitcode ("", "%05d$:", (rlbl->key + 100));
2376 emitcode ("mov", "psw,#0x%02x",
2377 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2380 /* if we need assign a result value */
2381 if ((IS_ITEMP (IC_RESULT (ic)) &&
2382 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2383 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2384 IS_TRUE_SYMOP (IC_RESULT (ic)))
2388 aopOp (IC_RESULT (ic), ic, FALSE);
2391 assignResultValue (IC_RESULT (ic));
2393 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2396 /* adjust the stack for parameters if
2401 if (ic->parmBytes > 3)
2403 emitcode ("mov", "a,%s", spname);
2404 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2405 emitcode ("mov", "%s,a", spname);
2408 for (i = 0; i < ic->parmBytes; i++)
2409 emitcode ("dec", "%s", spname);
2413 // /* if register bank was saved then unsave them */
2415 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2417 /* if we hade saved some registers then
2419 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2420 unsaveRegisters (ic);
2423 /*-----------------------------------------------------------------*/
2424 /* resultRemat - result is rematerializable */
2425 /*-----------------------------------------------------------------*/
2427 resultRemat (iCode * ic)
2429 if (SKIP_IC (ic) || ic->op == IFX)
2432 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2434 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2435 if (sym->remat && !POINTER_SET (ic))
2442 #if defined(__BORLANDC__) || defined(_MSC_VER)
2443 #define STRCASECMP stricmp
2445 #define STRCASECMP strcasecmp
2448 /*-----------------------------------------------------------------*/
2449 /* inExcludeList - return 1 if the string is in exclude Reg list */
2450 /*-----------------------------------------------------------------*/
2452 regsCmp(void *p1, void *p2)
2454 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2458 inExcludeList (char *s)
2460 const char *p = setFirstItem(options.excludeRegsSet);
2462 if (p == NULL || STRCASECMP(p, "none") == 0)
2466 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2469 /*-----------------------------------------------------------------*/
2470 /* genFunction - generated code for function entry */
2471 /*-----------------------------------------------------------------*/
2473 genFunction (iCode * ic)
2475 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2477 bool switchedPSW = FALSE;
2478 int calleesaves_saved_register = -1;
2479 int stackAdjust = sym->stack;
2480 int accIsFree = sym->recvSize < 4;
2481 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2484 /* create the function header */
2485 emitcode (";", "-----------------------------------------");
2486 emitcode (";", " function %s", sym->name);
2487 emitcode (";", "-----------------------------------------");
2489 emitcode ("", "%s:", sym->rname);
2490 ftype = operandType (IC_LEFT (ic));
2491 _G.currentFunc = sym;
2493 if (IFFUNC_ISNAKED(ftype))
2495 emitcode(";", "naked function: no prologue.");
2499 /* here we need to generate the equates for the
2500 register bank if required */
2501 if (FUNC_REGBANK (ftype) != rbank)
2505 rbank = FUNC_REGBANK (ftype);
2506 for (i = 0; i < mcs51_nRegs; i++)
2508 if (strcmp (regs8051[i].base, "0") == 0)
2509 emitcode ("", "%s = 0x%02x",
2511 8 * rbank + regs8051[i].offset);
2513 emitcode ("", "%s = %s + 0x%02x",
2516 8 * rbank + regs8051[i].offset);
2520 /* if this is an interrupt service routine then
2521 save acc, b, dpl, dph */
2522 if (IFFUNC_ISISR (sym->type))
2525 if (!inExcludeList ("acc"))
2526 emitcode ("push", "acc");
2527 if (!inExcludeList ("b"))
2528 emitcode ("push", "b");
2529 if (!inExcludeList ("dpl"))
2530 emitcode ("push", "dpl");
2531 if (!inExcludeList ("dph"))
2532 emitcode ("push", "dph");
2533 /* if this isr has no bank i.e. is going to
2534 run with bank 0 , then we need to save more
2536 if (!FUNC_REGBANK (sym->type))
2539 /* if this function does not call any other
2540 function then we can be economical and
2541 save only those registers that are used */
2542 if (!IFFUNC_HASFCALL(sym->type))
2546 /* if any registers used */
2549 /* save the registers used */
2550 for (i = 0; i < sym->regsUsed->size; i++)
2552 if (bitVectBitValue (sym->regsUsed, i))
2553 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2560 /* this function has a function call. We cannot
2561 determines register usage so we will have to push the
2563 saveRBank (0, ic, FALSE);
2564 if (options.parms_in_bank1) {
2566 for (i=0; i < 8 ; i++ ) {
2567 emitcode ("push","%s",rb1regs[i]);
2574 /* This ISR uses a non-zero bank.
2576 * We assume that the bank is available for our
2579 * However, if this ISR calls a function which uses some
2580 * other bank, we must save that bank entirely.
2582 unsigned long banksToSave = 0;
2584 if (IFFUNC_HASFCALL(sym->type))
2587 #define MAX_REGISTER_BANKS 4
2592 for (i = ic; i; i = i->next)
2594 if (i->op == ENDFUNCTION)
2596 /* we got to the end OK. */
2604 dtype = operandType (IC_LEFT(i));
2606 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2608 /* Mark this bank for saving. */
2609 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2611 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2615 banksToSave |= (1 << FUNC_REGBANK(dtype));
2618 /* And note that we don't need to do it in
2626 /* This is a mess; we have no idea what
2627 * register bank the called function might
2630 * The only thing I can think of to do is
2631 * throw a warning and hope.
2633 werror(W_FUNCPTR_IN_USING_ISR);
2637 if (banksToSave && options.useXstack)
2639 /* Since we aren't passing it an ic,
2640 * saveRBank will assume r0 is available to abuse.
2642 * So switch to our (trashable) bank now, so
2643 * the caller's R0 isn't trashed.
2645 emitcode ("push", "psw");
2646 emitcode ("mov", "psw,#0x%02x",
2647 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2651 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2653 if (banksToSave & (1 << ix))
2655 saveRBank(ix, NULL, FALSE);
2659 // TODO: this needs a closer look
2660 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2663 /* Set the register bank to the desired value if nothing else */
2664 /* has done so yet. */
2667 emitcode ("push", "psw");
2668 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2673 /* This is a non-ISR function. The caller has already switched register */
2674 /* banks, if necessary, so just handle the callee-saves option. */
2676 /* if callee-save to be used for this function
2677 then save the registers being used in this function */
2678 if (IFFUNC_CALLEESAVES(sym->type))
2682 /* if any registers used */
2685 /* save the registers used */
2686 for (i = 0; i < sym->regsUsed->size; i++)
2688 if (bitVectBitValue (sym->regsUsed, i))
2690 /* remember one saved register for later usage */
2691 if (calleesaves_saved_register < 0)
2692 calleesaves_saved_register = i;
2693 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2702 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2705 if (options.useXstack)
2708 emitcode ("push", "acc");
2709 emitcode ("mov", "r0,%s", spname);
2710 emitcode ("mov", "a,_bp");
2711 emitcode ("movx", "@r0,a");
2712 emitcode ("inc", "%s", spname);
2714 emitcode ("pop", "acc");
2718 /* set up the stack */
2719 emitcode ("push", "_bp"); /* save the callers stack */
2721 emitcode ("mov", "_bp,%s", spname);
2724 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2725 /* before setting up the stack frame completely. */
2726 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2728 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2732 if (rsym && rsym->regType == REG_CND)
2734 if (rsym && (rsym->accuse || rsym->ruonly))
2736 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2737 rsym = rsym->usl.spillLoc;
2740 /* If the RECEIVE operand immediately spills to the first entry on the */
2741 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2742 /* rather than the usual @r0/r1 machinations. */
2743 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2747 _G.current_iCode = ric;
2748 D(emitcode ("; genReceive",""));
2749 for (ofs=0; ofs < sym->recvSize; ofs++)
2751 if (!strcmp (fReturn[ofs], "a"))
2752 emitcode ("push", "acc");
2754 emitcode ("push", fReturn[ofs]);
2756 stackAdjust -= sym->recvSize;
2759 assert (stackAdjust>=0);
2762 _G.current_iCode = ic;
2766 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2767 /* to free up the accumulator. */
2768 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2772 _G.current_iCode = ric;
2773 D(emitcode ("; genReceive",""));
2774 for (ofs=0; ofs < sym->recvSize; ofs++)
2776 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2778 _G.current_iCode = ic;
2784 /* adjust the stack for the function */
2788 int i = stackAdjust;
2790 werror (W_STACK_OVERFLOW, sym->name);
2792 if (i > 3 && accIsFree)
2795 emitcode ("mov", "a,sp");
2796 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2797 emitcode ("mov", "sp,a");
2802 /* The accumulator is not free, so we will need another register */
2803 /* to clobber. No need to worry about a possible conflict with */
2804 /* the above early RECEIVE optimizations since they would have */
2805 /* freed the accumulator if they were generated. */
2807 if (IFFUNC_CALLEESAVES(sym->type))
2809 /* if it's a callee-saves function we need a saved register */
2810 if (calleesaves_saved_register >= 0)
2812 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2813 emitcode ("mov", "a,sp");
2814 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2815 emitcode ("mov", "sp,a");
2816 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2819 /* do it the hard way */
2821 emitcode ("inc", "sp");
2825 /* not callee-saves, we can clobber r0 */
2826 emitcode ("mov", "r0,a");
2827 emitcode ("mov", "a,sp");
2828 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2829 emitcode ("mov", "sp,a");
2830 emitcode ("mov", "a,r0");
2835 emitcode ("inc", "sp");
2842 emitcode ("push", "acc");
2843 emitcode ("mov", "a,_spx");
2844 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2845 emitcode ("mov", "_spx,a");
2847 emitcode ("pop", "acc");
2850 /* if critical function then turn interrupts off */
2851 if (IFFUNC_ISCRITICAL (ftype))
2853 symbol *tlbl = newiTempLabel (NULL);
2854 emitcode ("setb", "c");
2855 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2856 emitcode ("clr", "c");
2857 emitcode ("", "%05d$:", (tlbl->key + 100));
2858 emitcode ("push", "psw"); /* save old ea via c in psw */
2862 /*-----------------------------------------------------------------*/
2863 /* genEndFunction - generates epilogue for functions */
2864 /*-----------------------------------------------------------------*/
2866 genEndFunction (iCode * ic)
2868 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2869 lineNode *lnp = lineCurr;
2871 bitVect *regsUsedPrologue;
2872 bitVect *regsUnneeded;
2875 _G.currentFunc = NULL;
2876 if (IFFUNC_ISNAKED(sym->type))
2878 emitcode(";", "naked function: no epilogue.");
2879 if (options.debug && currFunc)
2880 debugFile->writeEndFunction (currFunc, ic, 0);
2884 if (IFFUNC_ISCRITICAL (sym->type))
2886 emitcode ("pop", "psw"); /* restore ea via c in psw */
2887 emitcode ("mov", "ea,c");
2890 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2892 emitcode ("mov", "%s,_bp", spname);
2895 /* if use external stack but some variables were
2896 added to the local stack then decrement the
2898 if (options.useXstack && sym->stack)
2900 emitcode ("mov", "a,sp");
2901 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2902 emitcode ("mov", "sp,a");
2906 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2908 if (options.useXstack)
2910 emitcode ("mov", "r0,%s", spname);
2911 emitcode ("movx", "a,@r0");
2912 emitcode ("mov", "_bp,a");
2913 emitcode ("dec", "%s", spname);
2917 emitcode ("pop", "_bp");
2921 /* restore the register bank */
2922 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2924 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2925 || !options.useXstack)
2927 /* Special case of ISR using non-zero bank with useXstack
2930 emitcode ("pop", "psw");
2934 if (IFFUNC_ISISR (sym->type))
2937 /* now we need to restore the registers */
2938 /* if this isr has no bank i.e. is going to
2939 run with bank 0 , then we need to save more
2941 if (!FUNC_REGBANK (sym->type))
2943 /* if this function does not call any other
2944 function then we can be economical and
2945 save only those registers that are used */
2946 if (!IFFUNC_HASFCALL(sym->type))
2950 /* if any registers used */
2953 /* save the registers used */
2954 for (i = sym->regsUsed->size; i >= 0; i--)
2956 if (bitVectBitValue (sym->regsUsed, i))
2957 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2963 if (options.parms_in_bank1) {
2965 for (i = 7 ; i >= 0 ; i-- ) {
2966 emitcode ("pop","%s",rb1regs[i]);
2969 /* this function has a function call cannot
2970 determines register usage so we will have to pop the
2972 unsaveRBank (0, ic, FALSE);
2977 /* This ISR uses a non-zero bank.
2979 * Restore any register banks saved by genFunction
2982 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2985 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2987 if (savedBanks & (1 << ix))
2989 unsaveRBank(ix, NULL, FALSE);
2993 if (options.useXstack)
2995 /* Restore bank AFTER calling unsaveRBank,
2996 * since it can trash r0.
2998 emitcode ("pop", "psw");
3002 if (!inExcludeList ("dph"))
3003 emitcode ("pop", "dph");
3004 if (!inExcludeList ("dpl"))
3005 emitcode ("pop", "dpl");
3006 if (!inExcludeList ("b"))
3007 emitcode ("pop", "b");
3008 if (!inExcludeList ("acc"))
3009 emitcode ("pop", "acc");
3011 /* if debug then send end of function */
3012 if (options.debug && currFunc)
3014 debugFile->writeEndFunction (currFunc, ic, 1);
3017 emitcode ("reti", "");
3021 if (IFFUNC_CALLEESAVES(sym->type))
3025 /* if any registers used */
3028 /* save the registers used */
3029 for (i = sym->regsUsed->size; i >= 0; i--)
3031 if (bitVectBitValue (sym->regsUsed, i) ||
3032 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3033 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3036 else if (mcs51_ptrRegReq)
3038 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3039 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3044 /* if debug then send end of function */
3045 if (options.debug && currFunc)
3047 debugFile->writeEndFunction (currFunc, ic, 1);
3050 emitcode ("ret", "");
3053 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3056 /* If this was an interrupt handler using bank 0 that called another */
3057 /* function, then all registers must be saved; nothing to optimized. */
3058 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3059 && !FUNC_REGBANK(sym->type))
3062 /* There are no push/pops to optimize if not callee-saves or ISR */
3063 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3066 /* If there were stack parameters, we cannot optimize without also */
3067 /* fixing all of the stack offsets; this is too dificult to consider. */
3068 if (FUNC_HASSTACKPARM(sym->type))
3071 /* Compute the registers actually used */
3072 regsUsed = newBitVect (mcs51_nRegs);
3073 regsUsedPrologue = newBitVect (mcs51_nRegs);
3076 if (lnp->ic && lnp->ic->op == FUNCTION)
3077 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3079 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3081 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3082 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3089 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3090 && !bitVectBitValue (regsUsed, CND_IDX))
3092 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3093 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3095 bitVectUnSetBit (regsUsed, CND_IDX);
3098 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3100 /* If this was an interrupt handler that called another function */
3101 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3102 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3104 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3105 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3106 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3107 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3108 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3111 /* Remove the unneeded push/pops */
3112 regsUnneeded = newBitVect (mcs51_nRegs);
3115 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3117 if (!strncmp(lnp->line, "push", 4))
3119 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3120 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3122 connectLine (lnp->prev, lnp->next);
3123 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3126 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3128 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3129 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3131 connectLine (lnp->prev, lnp->next);
3132 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3139 for (idx = 0; idx < regsUnneeded->size; idx++)
3140 if (bitVectBitValue (regsUnneeded, idx))
3141 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3143 freeBitVect (regsUnneeded);
3144 freeBitVect (regsUsed);
3145 freeBitVect (regsUsedPrologue);
3148 /*-----------------------------------------------------------------*/
3149 /* genRet - generate code for return statement */
3150 /*-----------------------------------------------------------------*/
3154 int size, offset = 0, pushed = 0;
3156 D(emitcode ("; genRet",""));
3158 /* if we have no return value then
3159 just generate the "ret" */
3163 /* we have something to return then
3164 move the return value into place */
3165 aopOp (IC_LEFT (ic), ic, FALSE);
3166 size = AOP_SIZE (IC_LEFT (ic));
3171 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3174 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3176 emitcode ("push", "%s", l);
3181 l = aopGet (AOP (IC_LEFT (ic)), offset,
3183 if (strcmp (fReturn[offset], l))
3184 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3193 if (strcmp (fReturn[pushed], "a"))
3194 emitcode ("pop", fReturn[pushed]);
3196 emitcode ("pop", "acc");
3199 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3202 /* generate a jump to the return label
3203 if the next is not the return statement */
3204 if (!(ic->next && ic->next->op == LABEL &&
3205 IC_LABEL (ic->next) == returnLabel))
3207 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3211 /*-----------------------------------------------------------------*/
3212 /* genLabel - generates a label */
3213 /*-----------------------------------------------------------------*/
3215 genLabel (iCode * ic)
3217 /* special case never generate */
3218 if (IC_LABEL (ic) == entryLabel)
3221 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3224 /*-----------------------------------------------------------------*/
3225 /* genGoto - generates a ljmp */
3226 /*-----------------------------------------------------------------*/
3228 genGoto (iCode * ic)
3230 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3233 /*-----------------------------------------------------------------*/
3234 /* findLabelBackwards: walks back through the iCode chain looking */
3235 /* for the given label. Returns number of iCode instructions */
3236 /* between that label and given ic. */
3237 /* Returns zero if label not found. */
3238 /*-----------------------------------------------------------------*/
3240 findLabelBackwards (iCode * ic, int key)
3249 /* If we have any pushes or pops, we cannot predict the distance.
3250 I don't like this at all, this should be dealt with in the
3252 if (ic->op == IPUSH || ic->op == IPOP) {
3256 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3265 /*-----------------------------------------------------------------*/
3266 /* genPlusIncr :- does addition with increment if possible */
3267 /*-----------------------------------------------------------------*/
3269 genPlusIncr (iCode * ic)
3271 unsigned int icount;
3272 unsigned int size = getDataSize (IC_RESULT (ic));
3274 /* will try to generate an increment */
3275 /* if the right side is not a literal
3277 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3280 /* if the literal value of the right hand side
3281 is greater than 4 then it is not worth it */
3282 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3285 D(emitcode ("; genPlusIncr",""));
3287 /* if increment >=16 bits in register or direct space */
3288 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3289 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3297 /* If the next instruction is a goto and the goto target
3298 * is < 10 instructions previous to this, we can generate
3299 * jumps straight to that target.
3301 if (ic->next && ic->next->op == GOTO
3302 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3303 && labelRange <= 10)
3305 emitcode (";", "tail increment optimized");
3306 tlbl = IC_LABEL (ic->next);
3311 tlbl = newiTempLabel (NULL);
3314 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3315 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3316 IS_AOP_PREG (IC_RESULT (ic)))
3317 emitcode ("cjne", "%s,#0x00,%05d$",
3318 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3322 emitcode ("clr", "a");
3323 emitcode ("cjne", "a,%s,%05d$",
3324 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3328 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3331 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3332 IS_AOP_PREG (IC_RESULT (ic)))
3333 emitcode ("cjne", "%s,#0x00,%05d$",
3334 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3337 emitcode ("cjne", "a,%s,%05d$",
3338 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3341 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3345 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3346 IS_AOP_PREG (IC_RESULT (ic)))
3347 emitcode ("cjne", "%s,#0x00,%05d$",
3348 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3352 emitcode ("cjne", "a,%s,%05d$",
3353 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3356 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3361 emitcode ("", "%05d$:", tlbl->key + 100);
3366 /* if the sizes are greater than 1 then we cannot */
3367 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3368 AOP_SIZE (IC_LEFT (ic)) > 1)
3371 /* we can if the aops of the left & result match or
3372 if they are in registers and the registers are the
3374 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3379 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3380 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3381 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3387 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3396 /*-----------------------------------------------------------------*/
3397 /* outBitAcc - output a bit in acc */
3398 /*-----------------------------------------------------------------*/
3400 outBitAcc (operand * result)
3402 symbol *tlbl = newiTempLabel (NULL);
3403 /* if the result is a bit */
3404 if (AOP_TYPE (result) == AOP_CRY)
3406 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3410 emitcode ("jz", "%05d$", tlbl->key + 100);
3411 emitcode ("mov", "a,%s", one);
3412 emitcode ("", "%05d$:", tlbl->key + 100);
3417 /*-----------------------------------------------------------------*/
3418 /* genPlusBits - generates code for addition of two bits */
3419 /*-----------------------------------------------------------------*/
3421 genPlusBits (iCode * ic)
3423 D(emitcode ("; genPlusBits",""));
3425 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3427 symbol *lbl = newiTempLabel (NULL);
3428 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3429 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3430 emitcode ("cpl", "c");
3431 emitcode ("", "%05d$:", (lbl->key + 100));
3432 outBitC (IC_RESULT (ic));
3436 emitcode ("clr", "a");
3437 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3438 emitcode ("rlc", "a");
3439 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3440 emitcode ("addc", "a,#0x00");
3441 outAcc (IC_RESULT (ic));
3446 /* This is the original version of this code.
3448 * This is being kept around for reference,
3449 * because I am not entirely sure I got it right...
3452 adjustArithmeticResult (iCode * ic)
3454 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3455 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3456 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3457 aopPut (AOP (IC_RESULT (ic)),
3458 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3460 isOperandVolatile (IC_RESULT (ic), FALSE));
3462 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3463 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3464 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3465 aopPut (AOP (IC_RESULT (ic)),
3466 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3468 isOperandVolatile (IC_RESULT (ic), FALSE));
3470 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3471 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3472 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3474 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3477 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3478 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3482 /* This is the pure and virtuous version of this code.
3483 * I'm pretty certain it's right, but not enough to toss the old
3487 adjustArithmeticResult (iCode * ic)
3489 if (opIsGptr (IC_RESULT (ic)) &&
3490 opIsGptr (IC_LEFT (ic)) &&
3491 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3493 aopPut (AOP (IC_RESULT (ic)),
3494 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3496 isOperandVolatile (IC_RESULT (ic), FALSE));
3499 if (opIsGptr (IC_RESULT (ic)) &&
3500 opIsGptr (IC_RIGHT (ic)) &&
3501 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3503 aopPut (AOP (IC_RESULT (ic)),
3504 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3506 isOperandVolatile (IC_RESULT (ic), FALSE));
3509 if (opIsGptr (IC_RESULT (ic)) &&
3510 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3511 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3512 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3513 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3516 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3517 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3522 /*-----------------------------------------------------------------*/
3523 /* genPlus - generates code for addition */
3524 /*-----------------------------------------------------------------*/
3526 genPlus (iCode * ic)
3528 int size, offset = 0;
3531 asmop *leftOp, *rightOp;
3534 /* special cases :- */
3536 D(emitcode ("; genPlus",""));
3538 aopOp (IC_LEFT (ic), ic, FALSE);
3539 aopOp (IC_RIGHT (ic), ic, FALSE);
3540 aopOp (IC_RESULT (ic), ic, TRUE);
3542 /* if literal, literal on the right or
3543 if left requires ACC or right is already
3545 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3546 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3547 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3549 operand *t = IC_RIGHT (ic);
3550 IC_RIGHT (ic) = IC_LEFT (ic);
3554 /* if both left & right are in bit
3556 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3557 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3563 /* if left in bit space & right literal */
3564 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3565 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3567 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3568 /* if result in bit space */
3569 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3571 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3572 emitcode ("cpl", "c");
3573 outBitC (IC_RESULT (ic));
3577 size = getDataSize (IC_RESULT (ic));
3580 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3581 emitcode ("addc", "a,#00");
3582 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3588 /* if I can do an increment instead
3589 of add then GOOD for ME */
3590 if (genPlusIncr (ic) == TRUE)
3593 size = getDataSize (IC_RESULT (ic));
3594 leftOp = AOP(IC_LEFT(ic));
3595 rightOp = AOP(IC_RIGHT(ic));
3598 /* if this is an add for an array access
3599 at a 256 byte boundary */
3601 && AOP_TYPE (op) == AOP_IMMD
3603 && IS_SPEC (OP_SYM_ETYPE (op))
3604 && SPEC_ABSA (OP_SYM_ETYPE (op))
3605 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3608 D(emitcode ("; genPlus aligned array",""));
3609 aopPut (AOP (IC_RESULT (ic)),
3610 aopGet (rightOp, 0, FALSE, FALSE),
3612 isOperandVolatile (IC_RESULT (ic), FALSE));
3614 if( 1 == getDataSize (IC_RIGHT (ic)) )
3616 aopPut (AOP (IC_RESULT (ic)),
3617 aopGet (leftOp, 1, FALSE, FALSE),
3619 isOperandVolatile (IC_RESULT (ic), FALSE));
3623 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3624 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3625 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3630 /* if the lower bytes of a literal are zero skip the addition */
3631 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3633 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3634 (skip_bytes+1 < size))
3639 D(emitcode ("; genPlus shortcut",""));
3644 if( offset >= skip_bytes )
3646 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3648 emitcode("mov", "b,a");
3649 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3650 emitcode("xch", "a,b");
3651 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3652 emitcode (add, "a,b");
3654 else if (aopGetUsesAcc (leftOp, offset))
3656 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3657 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3661 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3662 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3664 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3665 add = "addc"; /* further adds must propagate carry */
3669 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3670 isOperandVolatile (IC_RESULT (ic), FALSE))
3673 aopPut (AOP (IC_RESULT (ic)),
3674 aopGet (leftOp, offset, FALSE, FALSE),
3676 isOperandVolatile (IC_RESULT (ic), FALSE));
3682 adjustArithmeticResult (ic);
3685 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3686 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3690 /*-----------------------------------------------------------------*/
3691 /* genMinusDec :- does subtraction with deccrement if possible */
3692 /*-----------------------------------------------------------------*/
3694 genMinusDec (iCode * ic)
3696 unsigned int icount;
3697 unsigned int size = getDataSize (IC_RESULT (ic));
3699 /* will try to generate an increment */
3700 /* if the right side is not a literal
3702 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3705 /* if the literal value of the right hand side
3706 is greater than 4 then it is not worth it */
3707 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3710 D(emitcode ("; genMinusDec",""));
3712 /* if decrement >=16 bits in register or direct space */
3713 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3714 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3722 /* If the next instruction is a goto and the goto target
3723 * is <= 10 instructions previous to this, we can generate
3724 * jumps straight to that target.
3726 if (ic->next && ic->next->op == GOTO
3727 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3728 && labelRange <= 10)
3730 emitcode (";", "tail decrement optimized");
3731 tlbl = IC_LABEL (ic->next);
3736 tlbl = newiTempLabel (NULL);
3740 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3741 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3742 IS_AOP_PREG (IC_RESULT (ic)))
3743 emitcode ("cjne", "%s,#0xff,%05d$"
3744 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3748 emitcode ("mov", "a,#0xff");
3749 emitcode ("cjne", "a,%s,%05d$"
3750 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3753 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3756 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3757 IS_AOP_PREG (IC_RESULT (ic)))
3758 emitcode ("cjne", "%s,#0xff,%05d$"
3759 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3763 emitcode ("cjne", "a,%s,%05d$"
3764 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3767 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3771 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3772 IS_AOP_PREG (IC_RESULT (ic)))
3773 emitcode ("cjne", "%s,#0xff,%05d$"
3774 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3778 emitcode ("cjne", "a,%s,%05d$"
3779 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3782 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3786 emitcode ("", "%05d$:", tlbl->key + 100);
3791 /* if the sizes are greater than 1 then we cannot */
3792 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3793 AOP_SIZE (IC_LEFT (ic)) > 1)
3796 /* we can if the aops of the left & result match or
3797 if they are in registers and the registers are the
3799 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3803 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3811 /*-----------------------------------------------------------------*/
3812 /* addSign - complete with sign */
3813 /*-----------------------------------------------------------------*/
3815 addSign (operand * result, int offset, int sign)
3817 int size = (getDataSize (result) - offset);
3822 emitcode ("rlc", "a");
3823 emitcode ("subb", "a,acc");
3825 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3829 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3833 /*-----------------------------------------------------------------*/
3834 /* genMinusBits - generates code for subtraction of two bits */
3835 /*-----------------------------------------------------------------*/
3837 genMinusBits (iCode * ic)
3839 symbol *lbl = newiTempLabel (NULL);
3841 D(emitcode ("; genMinusBits",""));
3843 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3845 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3846 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3847 emitcode ("cpl", "c");
3848 emitcode ("", "%05d$:", (lbl->key + 100));
3849 outBitC (IC_RESULT (ic));
3853 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3854 emitcode ("subb", "a,acc");
3855 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3856 emitcode ("inc", "a");
3857 emitcode ("", "%05d$:", (lbl->key + 100));
3858 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3859 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3863 /*-----------------------------------------------------------------*/
3864 /* genMinus - generates code for subtraction */
3865 /*-----------------------------------------------------------------*/
3867 genMinus (iCode * ic)
3869 int size, offset = 0;
3871 D(emitcode ("; genMinus",""));
3873 aopOp (IC_LEFT (ic), ic, FALSE);
3874 aopOp (IC_RIGHT (ic), ic, FALSE);
3875 aopOp (IC_RESULT (ic), ic, TRUE);
3877 /* special cases :- */
3878 /* if both left & right are in bit space */
3879 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3880 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3886 /* if I can do an decrement instead
3887 of subtract then GOOD for ME */
3888 if (genMinusDec (ic) == TRUE)
3891 size = getDataSize (IC_RESULT (ic));
3893 /* if literal, add a,#-lit, else normal subb */
3894 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3896 unsigned long lit = 0L;
3898 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3903 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3904 /* first add without previous c */
3906 if (!size && lit== (unsigned long) -1) {
3907 emitcode ("dec", "a");
3909 emitcode ("add", "a,#0x%02x",
3910 (unsigned int) (lit & 0x0FFL));
3913 emitcode ("addc", "a,#0x%02x",
3914 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3916 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3921 asmop *leftOp, *rightOp;
3923 leftOp = AOP(IC_LEFT(ic));
3924 rightOp = AOP(IC_RIGHT(ic));
3928 if (aopGetUsesAcc(rightOp, offset)) {
3929 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3930 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3932 emitcode( "setb", "c");
3934 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3935 emitcode("cpl", "a");
3937 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3940 emitcode ("subb", "a,%s",
3941 aopGet(rightOp, offset, FALSE, TRUE));
3944 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3949 adjustArithmeticResult (ic);
3952 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3954 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3958 /*-----------------------------------------------------------------*/
3959 /* genMultbits :- multiplication of bits */
3960 /*-----------------------------------------------------------------*/
3962 genMultbits (operand * left,
3966 D(emitcode ("; genMultbits",""));
3968 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3969 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3973 /*-----------------------------------------------------------------*/
3974 /* genMultOneByte : 8*8=8/16 bit multiplication */
3975 /*-----------------------------------------------------------------*/
3977 genMultOneByte (operand * left,
3982 int size = AOP_SIZE (result);
3983 bool runtimeSign, compiletimeSign;
3984 bool lUnsigned, rUnsigned;
3986 D(emitcode ("; genMultOneByte",""));
3988 if (size < 1 || size > 2)
3990 /* this should never happen */
3991 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3992 AOP_SIZE(result), __FILE__, lineno);
3996 /* (if two literals: the value is computed before) */
3997 /* if one literal, literal on the right */
3998 if (AOP_TYPE (left) == AOP_LIT)
4003 /* emitcode (";", "swapped left and right"); */
4005 /* if no literal, unsigned on the right: shorter code */
4006 if ( AOP_TYPE (right) != AOP_LIT
4007 && SPEC_USIGN (getSpec (operandType (left))))
4014 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4015 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4017 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4018 no need to take care about the signedness! */
4019 || (lUnsigned && rUnsigned))
4021 /* just an unsigned 8 * 8 = 8 multiply
4023 /* emitcode (";","unsigned"); */
4024 /* TODO: check for accumulator clash between left & right aops? */
4026 if (AOP_TYPE (right) == AOP_LIT)
4028 /* moving to accumulator first helps peepholes */
4029 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4030 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4034 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4035 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4038 emitcode ("mul", "ab");
4039 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4041 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4045 /* we have to do a signed multiply */
4046 /* emitcode (";", "signed"); */
4048 /* now sign adjust for both left & right */
4050 /* let's see what's needed: */
4051 /* apply negative sign during runtime */
4052 runtimeSign = FALSE;
4053 /* negative sign from literals */
4054 compiletimeSign = FALSE;
4058 if (AOP_TYPE(left) == AOP_LIT)
4060 /* signed literal */
4061 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4063 compiletimeSign = TRUE;
4066 /* signed but not literal */
4072 if (AOP_TYPE(right) == AOP_LIT)
4074 /* signed literal */
4075 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4077 compiletimeSign ^= TRUE;
4080 /* signed but not literal */
4084 /* initialize F0, which stores the runtime sign */
4087 if (compiletimeSign)
4088 emitcode ("setb", "F0"); /* set sign flag */
4090 emitcode ("clr", "F0"); /* reset sign flag */
4093 /* save the signs of the operands */
4094 if (AOP_TYPE(right) == AOP_LIT)
4096 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4098 if (!rUnsigned && val < 0)
4099 emitcode ("mov", "b,#0x%02x", -val);
4101 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4103 else /* ! literal */
4105 if (rUnsigned) /* emitcode (";", "signed"); */
4107 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4110 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4111 lbl = newiTempLabel (NULL);
4112 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4113 emitcode ("cpl", "F0"); /* complement sign flag */
4114 emitcode ("cpl", "a"); /* 2's complement */
4115 emitcode ("inc", "a");
4116 emitcode ("", "%05d$:", (lbl->key + 100));
4117 emitcode ("mov", "b,a");
4121 if (AOP_TYPE(left) == AOP_LIT)
4123 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4125 if (!lUnsigned && val < 0)
4126 emitcode ("mov", "a,#0x%02x", -val);
4128 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4130 else /* ! literal */
4132 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4136 lbl = newiTempLabel (NULL);
4137 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4138 emitcode ("cpl", "F0"); /* complement sign flag */
4139 emitcode ("cpl", "a"); /* 2's complement */
4140 emitcode ("inc", "a");
4141 emitcode ("", "%05d$:", (lbl->key + 100));
4145 /* now the multiplication */
4146 emitcode ("mul", "ab");
4147 if (runtimeSign || compiletimeSign)
4149 lbl = newiTempLabel (NULL);
4151 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4152 emitcode ("cpl", "a"); /* lsb 2's complement */
4154 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4157 emitcode ("add", "a,#1"); /* this sets carry flag */
4158 emitcode ("xch", "a,b");
4159 emitcode ("cpl", "a"); /* msb 2's complement */
4160 emitcode ("addc", "a,#0");
4161 emitcode ("xch", "a,b");
4163 emitcode ("", "%05d$:", (lbl->key + 100));
4165 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4167 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4170 /*-----------------------------------------------------------------*/
4171 /* genMult - generates code for multiplication */
4172 /*-----------------------------------------------------------------*/
4174 genMult (iCode * ic)
4176 operand *left = IC_LEFT (ic);
4177 operand *right = IC_RIGHT (ic);
4178 operand *result = IC_RESULT (ic);
4180 D(emitcode ("; genMult",""));
4182 /* assign the amsops */
4183 aopOp (left, ic, FALSE);
4184 aopOp (right, ic, FALSE);
4185 aopOp (result, ic, TRUE);
4187 /* special cases first */
4189 if (AOP_TYPE (left) == AOP_CRY &&
4190 AOP_TYPE (right) == AOP_CRY)
4192 genMultbits (left, right, result);
4196 /* if both are of size == 1 */
4197 #if 0 // one of them can be a sloc shared with the result
4198 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4200 if (getSize(operandType(left)) == 1 &&
4201 getSize(operandType(right)) == 1)
4204 genMultOneByte (left, right, result);
4208 /* should have been converted to function call */
4209 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4210 getSize(OP_SYMBOL(right)->type));
4214 freeAsmop (result, NULL, ic, TRUE);
4215 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 /*-----------------------------------------------------------------*/
4220 /* genDivbits :- division of bits */
4221 /*-----------------------------------------------------------------*/
4223 genDivbits (operand * left,
4230 D(emitcode ("; genDivbits",""));
4232 /* the result must be bit */
4233 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4234 l = aopGet (AOP (left), 0, FALSE, FALSE);
4238 emitcode ("div", "ab");
4239 emitcode ("rrc", "a");
4240 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4243 /*-----------------------------------------------------------------*/
4244 /* genDivOneByte : 8 bit division */
4245 /*-----------------------------------------------------------------*/
4247 genDivOneByte (operand * left,
4251 bool lUnsigned, rUnsigned;
4252 bool runtimeSign, compiletimeSign;
4256 D(emitcode ("; genDivOneByte",""));
4258 /* Why is it necessary that genDivOneByte() can return an int result?
4261 volatile unsigned char uc;
4262 volatile signed char sc1, sc2;
4275 In all cases a one byte result would overflow, the following cast to int
4276 would return the wrong result.
4278 Two possible solution:
4279 a) cast operands to int, if ((unsigned) / (signed)) or
4280 ((signed) / (signed))
4281 b) return an 16 bit signed int; this is what we're doing here!
4284 size = AOP_SIZE (result) - 1;
4286 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4287 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4289 /* signed or unsigned */
4290 if (lUnsigned && rUnsigned)
4292 /* unsigned is easy */
4293 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4294 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4295 emitcode ("div", "ab");
4296 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4298 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4302 /* signed is a little bit more difficult */
4304 /* now sign adjust for both left & right */
4306 /* let's see what's needed: */
4307 /* apply negative sign during runtime */
4308 runtimeSign = FALSE;
4309 /* negative sign from literals */
4310 compiletimeSign = FALSE;
4314 if (AOP_TYPE(left) == AOP_LIT)
4316 /* signed literal */
4317 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4319 compiletimeSign = TRUE;
4322 /* signed but not literal */
4328 if (AOP_TYPE(right) == AOP_LIT)
4330 /* signed literal */
4331 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4333 compiletimeSign ^= TRUE;
4336 /* signed but not literal */
4340 /* initialize F0, which stores the runtime sign */
4343 if (compiletimeSign)
4344 emitcode ("setb", "F0"); /* set sign flag */
4346 emitcode ("clr", "F0"); /* reset sign flag */
4349 /* save the signs of the operands */
4350 if (AOP_TYPE(right) == AOP_LIT)
4352 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4354 if (!rUnsigned && val < 0)
4355 emitcode ("mov", "b,#0x%02x", -val);
4357 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4359 else /* ! literal */
4362 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4365 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4366 lbl = newiTempLabel (NULL);
4367 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4368 emitcode ("cpl", "F0"); /* complement sign flag */
4369 emitcode ("cpl", "a"); /* 2's complement */
4370 emitcode ("inc", "a");
4371 emitcode ("", "%05d$:", (lbl->key + 100));
4372 emitcode ("mov", "b,a");
4376 if (AOP_TYPE(left) == AOP_LIT)
4378 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4380 if (!lUnsigned && val < 0)
4381 emitcode ("mov", "a,#0x%02x", -val);
4383 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4385 else /* ! literal */
4387 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4391 lbl = newiTempLabel (NULL);
4392 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4393 emitcode ("cpl", "F0"); /* complement sign flag */
4394 emitcode ("cpl", "a"); /* 2's complement */
4395 emitcode ("inc", "a");
4396 emitcode ("", "%05d$:", (lbl->key + 100));
4400 /* now the division */
4401 emitcode ("div", "ab");
4403 if (runtimeSign || compiletimeSign)
4405 lbl = newiTempLabel (NULL);
4407 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4408 emitcode ("cpl", "a"); /* lsb 2's complement */
4409 emitcode ("inc", "a");
4410 emitcode ("", "%05d$:", (lbl->key + 100));
4412 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4415 /* msb is 0x00 or 0xff depending on the sign */
4418 emitcode ("mov", "c,F0");
4419 emitcode ("subb", "a,acc");
4421 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4423 else /* compiletimeSign */
4425 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4430 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4432 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4436 /*-----------------------------------------------------------------*/
4437 /* genDiv - generates code for division */
4438 /*-----------------------------------------------------------------*/
4442 operand *left = IC_LEFT (ic);
4443 operand *right = IC_RIGHT (ic);
4444 operand *result = IC_RESULT (ic);
4446 D(emitcode ("; genDiv",""));
4448 /* assign the amsops */
4449 aopOp (left, ic, FALSE);
4450 aopOp (right, ic, FALSE);
4451 aopOp (result, ic, TRUE);
4453 /* special cases first */
4455 if (AOP_TYPE (left) == AOP_CRY &&
4456 AOP_TYPE (right) == AOP_CRY)
4458 genDivbits (left, right, result);
4462 /* if both are of size == 1 */
4463 if (AOP_SIZE (left) == 1 &&
4464 AOP_SIZE (right) == 1)
4466 genDivOneByte (left, right, result);
4470 /* should have been converted to function call */
4473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4475 freeAsmop (result, NULL, ic, TRUE);
4478 /*-----------------------------------------------------------------*/
4479 /* genModbits :- modulus of bits */
4480 /*-----------------------------------------------------------------*/
4482 genModbits (operand * left,
4489 D(emitcode ("; genModbits",""));
4491 /* the result must be bit */
4492 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4493 l = aopGet (AOP (left), 0, FALSE, FALSE);
4497 emitcode ("div", "ab");
4498 emitcode ("mov", "a,b");
4499 emitcode ("rrc", "a");
4500 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4503 /*-----------------------------------------------------------------*/
4504 /* genModOneByte : 8 bit modulus */
4505 /*-----------------------------------------------------------------*/
4507 genModOneByte (operand * left,
4511 bool lUnsigned, rUnsigned;
4512 bool runtimeSign, compiletimeSign;
4516 D(emitcode ("; genModOneByte",""));
4518 size = AOP_SIZE (result) - 1;
4520 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4521 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4523 /* signed or unsigned */
4524 if (lUnsigned && rUnsigned)
4526 /* unsigned is easy */
4527 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4528 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4529 emitcode ("div", "ab");
4530 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4532 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4536 /* signed is a little bit more difficult */
4538 /* now sign adjust for both left & right */
4540 /* modulus: sign of the right operand has no influence on the result! */
4541 if (AOP_TYPE(right) == AOP_LIT)
4543 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4545 if (!rUnsigned && val < 0)
4546 emitcode ("mov", "b,#0x%02x", -val);
4548 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4550 else /* not literal */
4553 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4556 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4557 lbl = newiTempLabel (NULL);
4558 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4559 emitcode ("cpl", "a"); /* 2's complement */
4560 emitcode ("inc", "a");
4561 emitcode ("", "%05d$:", (lbl->key + 100));
4562 emitcode ("mov", "b,a");
4566 /* let's see what's needed: */
4567 /* apply negative sign during runtime */
4568 runtimeSign = FALSE;
4569 /* negative sign from literals */
4570 compiletimeSign = FALSE;
4572 /* sign adjust left side */
4573 if (AOP_TYPE(left) == AOP_LIT)
4575 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4577 if (!lUnsigned && val < 0)
4579 compiletimeSign = TRUE; /* set sign flag */
4580 emitcode ("mov", "a,#0x%02x", -val);
4583 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4585 else /* ! literal */
4587 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4592 emitcode ("clr", "F0"); /* clear sign flag */
4594 lbl = newiTempLabel (NULL);
4595 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4596 emitcode ("setb", "F0"); /* set sign flag */
4597 emitcode ("cpl", "a"); /* 2's complement */
4598 emitcode ("inc", "a");
4599 emitcode ("", "%05d$:", (lbl->key + 100));
4603 /* now the modulus */
4604 emitcode ("div", "ab");
4606 if (runtimeSign || compiletimeSign)
4608 emitcode ("mov", "a,b");
4609 lbl = newiTempLabel (NULL);
4611 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4612 emitcode ("cpl", "a"); /* 2's complement */
4613 emitcode ("inc", "a");
4614 emitcode ("", "%05d$:", (lbl->key + 100));
4616 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4619 /* msb is 0x00 or 0xff depending on the sign */
4622 emitcode ("mov", "c,F0");
4623 emitcode ("subb", "a,acc");
4625 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4627 else /* compiletimeSign */
4629 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4634 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4636 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4640 /*-----------------------------------------------------------------*/
4641 /* genMod - generates code for division */
4642 /*-----------------------------------------------------------------*/
4646 operand *left = IC_LEFT (ic);
4647 operand *right = IC_RIGHT (ic);
4648 operand *result = IC_RESULT (ic);
4650 D(emitcode ("; genMod",""));
4652 /* assign the amsops */
4653 aopOp (left, ic, FALSE);
4654 aopOp (right, ic, FALSE);
4655 aopOp (result, ic, TRUE);
4657 /* special cases first */
4659 if (AOP_TYPE (left) == AOP_CRY &&
4660 AOP_TYPE (right) == AOP_CRY)
4662 genModbits (left, right, result);
4666 /* if both are of size == 1 */
4667 if (AOP_SIZE (left) == 1 &&
4668 AOP_SIZE (right) == 1)
4670 genModOneByte (left, right, result);
4674 /* should have been converted to function call */
4678 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (result, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* genIfxJump :- will create a jump depending on the ifx */
4685 /*-----------------------------------------------------------------*/
4687 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4690 symbol *tlbl = newiTempLabel (NULL);
4693 D(emitcode ("; genIfxJump",""));
4695 /* if true label then we jump if condition
4699 jlbl = IC_TRUE (ic);
4700 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4701 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4705 /* false label is present */
4706 jlbl = IC_FALSE (ic);
4707 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4708 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4710 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4711 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4713 emitcode (inst, "%05d$", tlbl->key + 100);
4714 freeForBranchAsmop (result);
4715 freeForBranchAsmop (right);
4716 freeForBranchAsmop (left);
4717 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4718 emitcode ("", "%05d$:", tlbl->key + 100);
4720 /* mark the icode as generated */
4724 /*-----------------------------------------------------------------*/
4725 /* genCmp :- greater or less than comparison */
4726 /*-----------------------------------------------------------------*/
4728 genCmp (operand * left, operand * right,
4729 operand * result, iCode * ifx, int sign, iCode *ic)
4731 int size, offset = 0;
4732 unsigned long lit = 0L;
4735 D(emitcode ("; genCmp",""));
4737 /* if left & right are bit variables */
4738 if (AOP_TYPE (left) == AOP_CRY &&
4739 AOP_TYPE (right) == AOP_CRY)
4741 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4742 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4746 /* subtract right from left if at the
4747 end the carry flag is set then we know that
4748 left is greater than right */
4749 size = max (AOP_SIZE (left), AOP_SIZE (right));
4751 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4752 if ((size == 1) && !sign &&
4753 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4755 symbol *lbl = newiTempLabel (NULL);
4756 emitcode ("cjne", "%s,%s,%05d$",
4757 aopGet (AOP (left), offset, FALSE, FALSE),
4758 aopGet (AOP (right), offset, FALSE, FALSE),
4760 emitcode ("", "%05d$:", lbl->key + 100);
4764 if (AOP_TYPE (right) == AOP_LIT)
4766 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4767 /* optimize if(x < 0) or if(x >= 0) */
4776 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4777 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4779 genIfxJump (ifx, "acc.7", left, right, result);
4783 emitcode ("rlc", "a");
4791 rightInB = aopGetUsesAcc(AOP (right), offset);
4793 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4794 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4795 if (sign && size == 0)
4797 emitcode ("xrl", "a,#0x80");
4798 if (AOP_TYPE (right) == AOP_LIT)
4800 unsigned long lit = (unsigned long)
4801 floatFromVal (AOP (right)->aopu.aop_lit);
4802 emitcode ("subb", "a,#0x%02x",
4803 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4808 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4809 emitcode ("xrl", "b,#0x80");
4810 emitcode ("subb", "a,b");
4816 emitcode ("subb", "a,b");
4818 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4834 /* if the result is used in the next
4835 ifx conditional branch then generate
4836 code a little differently */
4838 genIfxJump (ifx, "c", NULL, NULL, result);
4841 /* leave the result in acc */
4845 /*-----------------------------------------------------------------*/
4846 /* genCmpGt :- greater than comparison */
4847 /*-----------------------------------------------------------------*/
4849 genCmpGt (iCode * ic, iCode * ifx)
4851 operand *left, *right, *result;
4852 sym_link *letype, *retype;
4855 D(emitcode ("; genCmpGt",""));
4857 left = IC_LEFT (ic);
4858 right = IC_RIGHT (ic);
4859 result = IC_RESULT (ic);
4861 letype = getSpec (operandType (left));
4862 retype = getSpec (operandType (right));
4863 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4864 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4865 /* assign the amsops */
4866 aopOp (left, ic, FALSE);
4867 aopOp (right, ic, FALSE);
4868 aopOp (result, ic, TRUE);
4870 genCmp (right, left, result, ifx, sign,ic);
4872 freeAsmop (result, NULL, ic, TRUE);
4875 /*-----------------------------------------------------------------*/
4876 /* genCmpLt - less than comparisons */
4877 /*-----------------------------------------------------------------*/
4879 genCmpLt (iCode * ic, iCode * ifx)
4881 operand *left, *right, *result;
4882 sym_link *letype, *retype;
4885 D(emitcode ("; genCmpLt",""));
4887 left = IC_LEFT (ic);
4888 right = IC_RIGHT (ic);
4889 result = IC_RESULT (ic);
4891 letype = getSpec (operandType (left));
4892 retype = getSpec (operandType (right));
4893 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4894 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4895 /* assign the amsops */
4896 aopOp (left, ic, FALSE);
4897 aopOp (right, ic, FALSE);
4898 aopOp (result, ic, TRUE);
4900 genCmp (left, right, result, ifx, sign,ic);
4902 freeAsmop (result, NULL, ic, TRUE);
4905 /*-----------------------------------------------------------------*/
4906 /* gencjneshort - compare and jump if not equal */
4907 /*-----------------------------------------------------------------*/
4909 gencjneshort (operand * left, operand * right, symbol * lbl)
4911 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4913 unsigned long lit = 0L;
4915 /* if the left side is a literal or
4916 if the right is in a pointer register and left
4918 if ((AOP_TYPE (left) == AOP_LIT) ||
4919 (AOP_TYPE (left) == AOP_IMMD) ||
4920 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4927 if (AOP_TYPE (right) == AOP_LIT)
4928 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4930 /* if the right side is a literal then anything goes */
4931 if (AOP_TYPE (right) == AOP_LIT &&
4932 AOP_TYPE (left) != AOP_DIR &&
4933 AOP_TYPE (left) != AOP_IMMD)
4937 emitcode ("cjne", "%s,%s,%05d$",
4938 aopGet (AOP (left), offset, FALSE, FALSE),
4939 aopGet (AOP (right), offset, FALSE, FALSE),
4945 /* if the right side is in a register or in direct space or
4946 if the left is a pointer register & right is not */
4947 else if (AOP_TYPE (right) == AOP_REG ||
4948 AOP_TYPE (right) == AOP_DIR ||
4949 AOP_TYPE (right) == AOP_LIT ||
4950 AOP_TYPE (right) == AOP_IMMD ||
4951 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4952 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4956 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4957 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4958 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4959 emitcode ("jnz", "%05d$", lbl->key + 100);
4961 emitcode ("cjne", "a,%s,%05d$",
4962 aopGet (AOP (right), offset, FALSE, TRUE),
4969 /* right is a pointer reg need both a & b */
4972 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4973 if (strcmp (l, "b"))
4974 emitcode ("mov", "b,%s", l);
4975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4976 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4982 /*-----------------------------------------------------------------*/
4983 /* gencjne - compare and jump if not equal */
4984 /*-----------------------------------------------------------------*/
4986 gencjne (operand * left, operand * right, symbol * lbl)
4988 symbol *tlbl = newiTempLabel (NULL);
4990 gencjneshort (left, right, lbl);
4992 emitcode ("mov", "a,%s", one);
4993 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4994 emitcode ("", "%05d$:", lbl->key + 100);
4995 emitcode ("clr", "a");
4996 emitcode ("", "%05d$:", tlbl->key + 100);
4999 /*-----------------------------------------------------------------*/
5000 /* genCmpEq - generates code for equal to */
5001 /*-----------------------------------------------------------------*/
5003 genCmpEq (iCode * ic, iCode * ifx)
5005 operand *left, *right, *result;
5007 D(emitcode ("; genCmpEq",""));
5009 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5010 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5011 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5013 /* if literal, literal on the right or
5014 if the right is in a pointer register and left
5016 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5017 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5019 operand *t = IC_RIGHT (ic);
5020 IC_RIGHT (ic) = IC_LEFT (ic);
5024 if (ifx && !AOP_SIZE (result))
5027 /* if they are both bit variables */
5028 if (AOP_TYPE (left) == AOP_CRY &&
5029 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5031 if (AOP_TYPE (right) == AOP_LIT)
5033 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5036 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5037 emitcode ("cpl", "c");
5041 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5045 emitcode ("clr", "c");
5047 /* AOP_TYPE(right) == AOP_CRY */
5051 symbol *lbl = newiTempLabel (NULL);
5052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5053 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5054 emitcode ("cpl", "c");
5055 emitcode ("", "%05d$:", (lbl->key + 100));
5057 /* if true label then we jump if condition
5059 tlbl = newiTempLabel (NULL);
5062 emitcode ("jnc", "%05d$", tlbl->key + 100);
5063 freeForBranchAsmop (result);
5064 freeForBranchAsmop (right);
5065 freeForBranchAsmop (left);
5066 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5070 emitcode ("jc", "%05d$", tlbl->key + 100);
5071 freeForBranchAsmop (result);
5072 freeForBranchAsmop (right);
5073 freeForBranchAsmop (left);
5074 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5076 emitcode ("", "%05d$:", tlbl->key + 100);
5080 tlbl = newiTempLabel (NULL);
5081 gencjneshort (left, right, tlbl);
5084 freeForBranchAsmop (result);
5085 freeForBranchAsmop (right);
5086 freeForBranchAsmop (left);
5087 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5088 emitcode ("", "%05d$:", tlbl->key + 100);
5092 symbol *lbl = newiTempLabel (NULL);
5093 emitcode ("sjmp", "%05d$", lbl->key + 100);
5094 emitcode ("", "%05d$:", tlbl->key + 100);
5095 freeForBranchAsmop (result);
5096 freeForBranchAsmop (right);
5097 freeForBranchAsmop (left);
5098 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5099 emitcode ("", "%05d$:", lbl->key + 100);
5102 /* mark the icode as generated */
5107 /* if they are both bit variables */
5108 if (AOP_TYPE (left) == AOP_CRY &&
5109 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5111 if (AOP_TYPE (right) == AOP_LIT)
5113 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5116 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5117 emitcode ("cpl", "c");
5121 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5125 emitcode ("clr", "c");
5127 /* AOP_TYPE(right) == AOP_CRY */
5131 symbol *lbl = newiTempLabel (NULL);
5132 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5133 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5134 emitcode ("cpl", "c");
5135 emitcode ("", "%05d$:", (lbl->key + 100));
5138 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5145 genIfxJump (ifx, "c", left, right, result);
5148 /* if the result is used in an arithmetic operation
5149 then put the result in place */
5154 gencjne (left, right, newiTempLabel (NULL));
5155 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5157 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5162 genIfxJump (ifx, "a", left, right, result);
5165 /* if the result is used in an arithmetic operation
5166 then put the result in place */
5167 if (AOP_TYPE (result) != AOP_CRY)
5169 /* leave the result in acc */
5173 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5174 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5175 freeAsmop (result, NULL, ic, TRUE);
5178 /*-----------------------------------------------------------------*/
5179 /* ifxForOp - returns the icode containing the ifx for operand */
5180 /*-----------------------------------------------------------------*/
5182 ifxForOp (operand * op, iCode * ic)
5184 /* if true symbol then needs to be assigned */
5185 if (IS_TRUE_SYMOP (op))
5188 /* if this has register type condition and
5189 the next instruction is ifx with the same operand
5190 and live to of the operand is upto the ifx only then */
5192 ic->next->op == IFX &&
5193 IC_COND (ic->next)->key == op->key &&
5194 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5200 /*-----------------------------------------------------------------*/
5201 /* hasInc - operand is incremented before any other use */
5202 /*-----------------------------------------------------------------*/
5204 hasInc (operand *op, iCode *ic,int osize)
5206 sym_link *type = operandType(op);
5207 sym_link *retype = getSpec (type);
5208 iCode *lic = ic->next;
5211 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5212 if (!IS_SYMOP(op)) return NULL;
5214 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5215 if (IS_AGGREGATE(type->next)) return NULL;
5216 if (osize != (isize = getSize(type->next))) return NULL;
5219 /* if operand of the form op = op + <sizeof *op> */
5220 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5221 isOperandEqual(IC_RESULT(lic),op) &&
5222 isOperandLiteral(IC_RIGHT(lic)) &&
5223 operandLitValue(IC_RIGHT(lic)) == isize) {
5226 /* if the operand used or deffed */
5227 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5230 /* if GOTO or IFX */
5231 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5237 /*-----------------------------------------------------------------*/
5238 /* genAndOp - for && operation */
5239 /*-----------------------------------------------------------------*/
5241 genAndOp (iCode * ic)
5243 operand *left, *right, *result;
5246 D(emitcode ("; genAndOp",""));
5248 /* note here that && operations that are in an
5249 if statement are taken away by backPatchLabels
5250 only those used in arthmetic operations remain */
5251 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5252 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5253 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5255 /* if both are bit variables */
5256 if (AOP_TYPE (left) == AOP_CRY &&
5257 AOP_TYPE (right) == AOP_CRY)
5259 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5260 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5265 tlbl = newiTempLabel (NULL);
5267 emitcode ("jz", "%05d$", tlbl->key + 100);
5269 emitcode ("", "%05d$:", tlbl->key + 100);
5273 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5274 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5275 freeAsmop (result, NULL, ic, TRUE);
5279 /*-----------------------------------------------------------------*/
5280 /* genOrOp - for || operation */
5281 /*-----------------------------------------------------------------*/
5283 genOrOp (iCode * ic)
5285 operand *left, *right, *result;
5288 D(emitcode ("; genOrOp",""));
5290 /* note here that || operations that are in an
5291 if statement are taken away by backPatchLabels
5292 only those used in arthmetic operations remain */
5293 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5294 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5295 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5297 /* if both are bit variables */
5298 if (AOP_TYPE (left) == AOP_CRY &&
5299 AOP_TYPE (right) == AOP_CRY)
5301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5302 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5307 tlbl = newiTempLabel (NULL);
5309 emitcode ("jnz", "%05d$", tlbl->key + 100);
5311 emitcode ("", "%05d$:", tlbl->key + 100);
5315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5316 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5317 freeAsmop (result, NULL, ic, TRUE);
5320 /*-----------------------------------------------------------------*/
5321 /* isLiteralBit - test if lit == 2^n */
5322 /*-----------------------------------------------------------------*/
5324 isLiteralBit (unsigned long lit)
5326 unsigned long pw[32] =
5327 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5328 0x100L, 0x200L, 0x400L, 0x800L,
5329 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5330 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5331 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5332 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5333 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5336 for (idx = 0; idx < 32; idx++)
5342 /*-----------------------------------------------------------------*/
5343 /* continueIfTrue - */
5344 /*-----------------------------------------------------------------*/
5346 continueIfTrue (iCode * ic)
5349 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5353 /*-----------------------------------------------------------------*/
5355 /*-----------------------------------------------------------------*/
5357 jumpIfTrue (iCode * ic)
5360 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5364 /*-----------------------------------------------------------------*/
5365 /* jmpTrueOrFalse - */
5366 /*-----------------------------------------------------------------*/
5368 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5370 // ugly but optimized by peephole
5373 symbol *nlbl = newiTempLabel (NULL);
5374 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5375 emitcode ("", "%05d$:", tlbl->key + 100);
5376 freeForBranchAsmop (result);
5377 freeForBranchAsmop (right);
5378 freeForBranchAsmop (left);
5379 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5380 emitcode ("", "%05d$:", nlbl->key + 100);
5384 freeForBranchAsmop (result);
5385 freeForBranchAsmop (right);
5386 freeForBranchAsmop (left);
5387 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5388 emitcode ("", "%05d$:", tlbl->key + 100);
5393 /*-----------------------------------------------------------------*/
5394 /* genAnd - code for and */
5395 /*-----------------------------------------------------------------*/
5397 genAnd (iCode * ic, iCode * ifx)
5399 operand *left, *right, *result;
5400 int size, offset = 0;
5401 unsigned long lit = 0L;
5405 D(emitcode ("; genAnd",""));
5407 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5408 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5409 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5412 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5414 AOP_TYPE (left), AOP_TYPE (right));
5415 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5417 AOP_SIZE (left), AOP_SIZE (right));
5420 /* if left is a literal & right is not then exchange them */
5421 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5422 AOP_NEEDSACC (left))
5424 operand *tmp = right;
5429 /* if result = right then exchange them */
5430 if (sameRegs (AOP (result), AOP (right)))
5432 operand *tmp = right;
5437 /* if right is bit then exchange them */
5438 if (AOP_TYPE (right) == AOP_CRY &&
5439 AOP_TYPE (left) != AOP_CRY)
5441 operand *tmp = right;
5445 if (AOP_TYPE (right) == AOP_LIT)
5446 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5448 size = AOP_SIZE (result);
5451 // result = bit & yy;
5452 if (AOP_TYPE (left) == AOP_CRY)
5454 // c = bit & literal;
5455 if (AOP_TYPE (right) == AOP_LIT)
5459 if (size && sameRegs (AOP (result), AOP (left)))
5462 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5467 if (size && (AOP_TYPE (result) == AOP_CRY))
5469 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5472 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5477 emitcode ("clr", "c");
5482 if (AOP_TYPE (right) == AOP_CRY)
5485 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5486 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5491 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5493 emitcode ("rrc", "a");
5494 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5502 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5503 genIfxJump (ifx, "c", left, right, result);
5507 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5508 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5509 if ((AOP_TYPE (right) == AOP_LIT) &&
5510 (AOP_TYPE (result) == AOP_CRY) &&
5511 (AOP_TYPE (left) != AOP_CRY))
5513 int posbit = isLiteralBit (lit);
5518 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5521 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5527 sprintf (buffer, "acc.%d", posbit & 0x07);
5528 genIfxJump (ifx, buffer, left, right, result);
5535 symbol *tlbl = newiTempLabel (NULL);
5536 int sizel = AOP_SIZE (left);
5538 emitcode ("setb", "c");
5541 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5543 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5545 if ((posbit = isLiteralBit (bytelit)) != 0)
5546 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5549 if (bytelit != 0x0FFL)
5550 emitcode ("anl", "a,%s",
5551 aopGet (AOP (right), offset, FALSE, TRUE));
5552 emitcode ("jnz", "%05d$", tlbl->key + 100);
5557 // bit = left & literal
5560 emitcode ("clr", "c");
5561 emitcode ("", "%05d$:", tlbl->key + 100);
5563 // if(left & literal)
5567 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5569 emitcode ("", "%05d$:", tlbl->key + 100);
5577 /* if left is same as result */
5578 if (sameRegs (AOP (result), AOP (left)))
5580 for (; size--; offset++)
5582 if (AOP_TYPE (right) == AOP_LIT)
5584 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5586 else if (bytelit == 0)
5588 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5590 else if (IS_AOP_PREG (result))
5592 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5593 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5594 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5597 emitcode ("anl", "%s,%s",
5598 aopGet (AOP (left), offset, FALSE, TRUE),
5599 aopGet (AOP (right), offset, FALSE, FALSE));
5603 if (AOP_TYPE (left) == AOP_ACC)
5604 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5607 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5608 if (IS_AOP_PREG (result))
5610 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5611 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5615 emitcode ("anl", "%s,a",
5616 aopGet (AOP (left), offset, FALSE, TRUE));
5623 // left & result in different registers
5624 if (AOP_TYPE (result) == AOP_CRY)
5627 // if(size), result in bit
5628 // if(!size && ifx), conditional oper: if(left & right)
5629 symbol *tlbl = newiTempLabel (NULL);
5630 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5632 emitcode ("setb", "c");
5635 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5636 emitcode ("anl", "a,%s",
5637 aopGet (AOP (right), offset, FALSE, FALSE));
5639 if (AOP_TYPE(left)==AOP_ACC) {
5640 emitcode("mov", "b,a");
5641 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5642 emitcode("anl", "a,b");
5644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5645 emitcode ("anl", "a,%s",
5646 aopGet (AOP (left), offset, FALSE, FALSE));
5649 emitcode ("jnz", "%05d$", tlbl->key + 100);
5655 emitcode ("", "%05d$:", tlbl->key + 100);
5659 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5661 emitcode ("", "%05d$:", tlbl->key + 100);
5665 for (; (size--); offset++)
5668 // result = left & right
5669 if (AOP_TYPE (right) == AOP_LIT)
5671 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5673 aopPut (AOP (result),
5674 aopGet (AOP (left), offset, FALSE, FALSE),
5676 isOperandVolatile (result, FALSE));
5679 else if (bytelit == 0)
5681 /* dummy read of volatile operand */
5682 if (isOperandVolatile (left, FALSE))
5683 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5684 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5688 // faster than result <- left, anl result,right
5689 // and better if result is SFR
5690 if (AOP_TYPE (left) == AOP_ACC)
5691 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5694 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5695 emitcode ("anl", "a,%s",
5696 aopGet (AOP (left), offset, FALSE, FALSE));
5698 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5706 freeAsmop (result, NULL, ic, TRUE);
5709 /*-----------------------------------------------------------------*/
5710 /* genOr - code for or */
5711 /*-----------------------------------------------------------------*/
5713 genOr (iCode * ic, iCode * ifx)
5715 operand *left, *right, *result;
5716 int size, offset = 0;
5717 unsigned long lit = 0L;
5719 D(emitcode ("; genOr",""));
5721 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5722 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5723 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5726 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5728 AOP_TYPE (left), AOP_TYPE (right));
5729 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5731 AOP_SIZE (left), AOP_SIZE (right));
5734 /* if left is a literal & right is not then exchange them */
5735 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5736 AOP_NEEDSACC (left))
5738 operand *tmp = right;
5743 /* if result = right then exchange them */
5744 if (sameRegs (AOP (result), AOP (right)))
5746 operand *tmp = right;
5751 /* if right is bit then exchange them */
5752 if (AOP_TYPE (right) == AOP_CRY &&
5753 AOP_TYPE (left) != AOP_CRY)
5755 operand *tmp = right;
5759 if (AOP_TYPE (right) == AOP_LIT)
5760 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5762 size = AOP_SIZE (result);
5766 if (AOP_TYPE (left) == AOP_CRY)
5768 if (AOP_TYPE (right) == AOP_LIT)
5770 // c = bit | literal;
5773 // lit != 0 => result = 1
5774 if (AOP_TYPE (result) == AOP_CRY)
5777 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5779 continueIfTrue (ifx);
5782 emitcode ("setb", "c");
5786 // lit == 0 => result = left
5787 if (size && sameRegs (AOP (result), AOP (left)))
5789 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5794 if (AOP_TYPE (right) == AOP_CRY)
5797 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5798 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5803 symbol *tlbl = newiTempLabel (NULL);
5804 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5805 emitcode ("setb", "c");
5806 emitcode ("jb", "%s,%05d$",
5807 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5809 emitcode ("jnz", "%05d$", tlbl->key + 100);
5810 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5812 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5818 emitcode ("", "%05d$:", tlbl->key + 100);
5827 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5828 genIfxJump (ifx, "c", left, right, result);
5832 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5833 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5834 if ((AOP_TYPE (right) == AOP_LIT) &&
5835 (AOP_TYPE (result) == AOP_CRY) &&
5836 (AOP_TYPE (left) != AOP_CRY))
5842 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5844 continueIfTrue (ifx);
5849 // lit = 0, result = boolean(left)
5851 emitcode ("setb", "c");
5855 symbol *tlbl = newiTempLabel (NULL);
5856 emitcode ("jnz", "%05d$", tlbl->key + 100);
5858 emitcode ("", "%05d$:", tlbl->key + 100);
5862 genIfxJump (ifx, "a", left, right, result);
5870 /* if left is same as result */
5871 if (sameRegs (AOP (result), AOP (left)))
5873 for (; size--; offset++)
5875 if (AOP_TYPE (right) == AOP_LIT)
5877 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5879 /* dummy read of volatile operand */
5880 if (isOperandVolatile (left, FALSE))
5881 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5885 else if (IS_AOP_PREG (left))
5887 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5888 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5889 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5892 emitcode ("orl", "%s,%s",
5893 aopGet (AOP (left), offset, FALSE, TRUE),
5894 aopGet (AOP (right), offset, FALSE, FALSE));
5898 if (AOP_TYPE (left) == AOP_ACC)
5899 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5902 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5903 if (IS_AOP_PREG (left))
5905 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5906 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5909 emitcode ("orl", "%s,a",
5910 aopGet (AOP (left), offset, FALSE, TRUE));
5917 // left & result in different registers
5918 if (AOP_TYPE (result) == AOP_CRY)
5921 // if(size), result in bit
5922 // if(!size && ifx), conditional oper: if(left | right)
5923 symbol *tlbl = newiTempLabel (NULL);
5924 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5926 emitcode ("setb", "c");
5929 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5930 emitcode ("orl", "a,%s",
5931 aopGet (AOP (right), offset, FALSE, FALSE));
5933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5934 emitcode ("orl", "a,%s",
5935 aopGet (AOP (left), offset, FALSE, FALSE));
5937 emitcode ("jnz", "%05d$", tlbl->key + 100);
5943 emitcode ("", "%05d$:", tlbl->key + 100);
5947 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5949 emitcode ("", "%05d$:", tlbl->key + 100);
5952 for (; (size--); offset++)
5955 // result = left & right
5956 if (AOP_TYPE (right) == AOP_LIT)
5958 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5960 aopPut (AOP (result),
5961 aopGet (AOP (left), offset, FALSE, FALSE),
5963 isOperandVolatile (result, FALSE));
5967 // faster than result <- left, anl result,right
5968 // and better if result is SFR
5969 if (AOP_TYPE (left) == AOP_ACC)
5970 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5973 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5974 emitcode ("orl", "a,%s",
5975 aopGet (AOP (left), offset, FALSE, FALSE));
5977 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984 freeAsmop (result, NULL, ic, TRUE);
5987 /*-----------------------------------------------------------------*/
5988 /* genXor - code for xclusive or */
5989 /*-----------------------------------------------------------------*/
5991 genXor (iCode * ic, iCode * ifx)
5993 operand *left, *right, *result;
5994 int size, offset = 0;
5995 unsigned long lit = 0L;
5997 D(emitcode ("; genXor",""));
5999 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6000 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6001 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6004 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6006 AOP_TYPE (left), AOP_TYPE (right));
6007 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6009 AOP_SIZE (left), AOP_SIZE (right));
6012 /* if left is a literal & right is not ||
6013 if left needs acc & right does not */
6014 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6015 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6017 operand *tmp = right;
6022 /* if result = right then exchange them */
6023 if (sameRegs (AOP (result), AOP (right)))
6025 operand *tmp = right;
6030 /* if right is bit then exchange them */
6031 if (AOP_TYPE (right) == AOP_CRY &&
6032 AOP_TYPE (left) != AOP_CRY)
6034 operand *tmp = right;
6038 if (AOP_TYPE (right) == AOP_LIT)
6039 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6041 size = AOP_SIZE (result);
6045 if (AOP_TYPE (left) == AOP_CRY)
6047 if (AOP_TYPE (right) == AOP_LIT)
6049 // c = bit & literal;
6052 // lit>>1 != 0 => result = 1
6053 if (AOP_TYPE (result) == AOP_CRY)
6056 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6058 continueIfTrue (ifx);
6061 emitcode ("setb", "c");
6068 // lit == 0, result = left
6069 if (size && sameRegs (AOP (result), AOP (left)))
6071 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6075 // lit == 1, result = not(left)
6076 if (size && sameRegs (AOP (result), AOP (left)))
6078 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6083 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6084 emitcode ("cpl", "c");
6093 symbol *tlbl = newiTempLabel (NULL);
6094 if (AOP_TYPE (right) == AOP_CRY)
6097 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6101 int sizer = AOP_SIZE (right);
6103 // if val>>1 != 0, result = 1
6104 emitcode ("setb", "c");
6107 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6109 // test the msb of the lsb
6110 emitcode ("anl", "a,#0xfe");
6111 emitcode ("jnz", "%05d$", tlbl->key + 100);
6115 emitcode ("rrc", "a");
6117 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6118 emitcode ("cpl", "c");
6119 emitcode ("", "%05d$:", (tlbl->key + 100));
6126 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6127 genIfxJump (ifx, "c", left, right, result);
6131 if (sameRegs (AOP (result), AOP (left)))
6133 /* if left is same as result */
6134 for (; size--; offset++)
6136 if (AOP_TYPE (right) == AOP_LIT)
6138 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6140 else if (IS_AOP_PREG (left))
6142 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6143 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6144 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6147 emitcode ("xrl", "%s,%s",
6148 aopGet (AOP (left), offset, FALSE, TRUE),
6149 aopGet (AOP (right), offset, FALSE, FALSE));
6153 if (AOP_TYPE (left) == AOP_ACC)
6154 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6157 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6158 if (IS_AOP_PREG (left))
6160 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6161 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6164 emitcode ("xrl", "%s,a",
6165 aopGet (AOP (left), offset, FALSE, TRUE));
6172 // left & result in different registers
6173 if (AOP_TYPE (result) == AOP_CRY)
6176 // if(size), result in bit
6177 // if(!size && ifx), conditional oper: if(left ^ right)
6178 symbol *tlbl = newiTempLabel (NULL);
6179 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6181 emitcode ("setb", "c");
6184 if ((AOP_TYPE (right) == AOP_LIT) &&
6185 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6187 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6191 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6192 emitcode ("xrl", "a,%s",
6193 aopGet (AOP (right), offset, FALSE, FALSE));
6195 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6196 emitcode ("xrl", "a,%s",
6197 aopGet (AOP (left), offset, FALSE, FALSE));
6200 emitcode ("jnz", "%05d$", tlbl->key + 100);
6206 emitcode ("", "%05d$:", tlbl->key + 100);
6210 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6213 for (; (size--); offset++)
6216 // result = left & right
6217 if (AOP_TYPE (right) == AOP_LIT)
6219 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6221 aopPut (AOP (result),
6222 aopGet (AOP (left), offset, FALSE, FALSE),
6224 isOperandVolatile (result, FALSE));
6228 // faster than result <- left, anl result,right
6229 // and better if result is SFR
6230 if (AOP_TYPE (left) == AOP_ACC)
6231 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6234 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6235 emitcode ("xrl", "a,%s",
6236 aopGet (AOP (left), offset, FALSE, TRUE));
6238 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6243 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6245 freeAsmop (result, NULL, ic, TRUE);
6248 /*-----------------------------------------------------------------*/
6249 /* genInline - write the inline code out */
6250 /*-----------------------------------------------------------------*/
6252 genInline (iCode * ic)
6254 char *buffer, *bp, *bp1;
6256 D(emitcode ("; genInline",""));
6258 _G.inLine += (!options.asmpeep);
6260 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6261 strcpy (buffer, IC_INLINE (ic));
6263 /* emit each line as a code */
6288 /* emitcode("",buffer); */
6289 _G.inLine -= (!options.asmpeep);
6292 /*-----------------------------------------------------------------*/
6293 /* genRRC - rotate right with carry */
6294 /*-----------------------------------------------------------------*/
6298 operand *left, *result;
6299 int size, offset = 0;
6302 D(emitcode ("; genRRC",""));
6304 /* rotate right with carry */
6305 left = IC_LEFT (ic);
6306 result = IC_RESULT (ic);
6307 aopOp (left, ic, FALSE);
6308 aopOp (result, ic, FALSE);
6310 /* move it to the result */
6311 size = AOP_SIZE (result);
6313 if (size == 1) { /* special case for 1 byte */
6314 l = aopGet (AOP (left), offset, FALSE, FALSE);
6316 emitcode ("rr", "a");
6322 l = aopGet (AOP (left), offset, FALSE, FALSE);
6324 emitcode ("rrc", "a");
6325 if (AOP_SIZE (result) > 1)
6326 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6328 /* now we need to put the carry into the
6329 highest order byte of the result */
6330 if (AOP_SIZE (result) > 1)
6332 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6335 emitcode ("mov", "acc.7,c");
6337 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6338 freeAsmop (left, NULL, ic, TRUE);
6339 freeAsmop (result, NULL, ic, TRUE);
6342 /*-----------------------------------------------------------------*/
6343 /* genRLC - generate code for rotate left with carry */
6344 /*-----------------------------------------------------------------*/
6348 operand *left, *result;
6349 int size, offset = 0;
6352 D(emitcode ("; genRLC",""));
6354 /* rotate right with carry */
6355 left = IC_LEFT (ic);
6356 result = IC_RESULT (ic);
6357 aopOp (left, ic, FALSE);
6358 aopOp (result, ic, FALSE);
6360 /* move it to the result */
6361 size = AOP_SIZE (result);
6365 l = aopGet (AOP (left), offset, FALSE, FALSE);
6367 if (size == 0) { /* special case for 1 byte */
6371 emitcode ("add", "a,acc");
6372 if (AOP_SIZE (result) > 1)
6373 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6376 l = aopGet (AOP (left), offset, FALSE, FALSE);
6378 emitcode ("rlc", "a");
6379 if (AOP_SIZE (result) > 1)
6380 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6383 /* now we need to put the carry into the
6384 highest order byte of the result */
6385 if (AOP_SIZE (result) > 1)
6387 l = aopGet (AOP (result), 0, FALSE, FALSE);
6390 emitcode ("mov", "acc.0,c");
6392 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6393 freeAsmop (left, NULL, ic, TRUE);
6394 freeAsmop (result, NULL, ic, TRUE);
6397 /*-----------------------------------------------------------------*/
6398 /* genGetHbit - generates code get highest order bit */
6399 /*-----------------------------------------------------------------*/
6401 genGetHbit (iCode * ic)
6403 operand *left, *result;
6405 D(emitcode ("; genGetHbit",""));
6407 left = IC_LEFT (ic);
6408 result = IC_RESULT (ic);
6409 aopOp (left, ic, FALSE);
6410 aopOp (result, ic, FALSE);
6412 /* get the highest order byte into a */
6413 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6414 if (AOP_TYPE (result) == AOP_CRY)
6416 emitcode ("rlc", "a");
6421 emitcode ("rl", "a");
6422 emitcode ("anl", "a,#0x01");
6427 freeAsmop (left, NULL, ic, TRUE);
6428 freeAsmop (result, NULL, ic, TRUE);
6431 /*-----------------------------------------------------------------*/
6432 /* genSwap - generates code to swap nibbles or bytes */
6433 /*-----------------------------------------------------------------*/
6435 genSwap (iCode * ic)
6437 operand *left, *result;
6439 D(emitcode ("; genSwap",""));
6441 left = IC_LEFT (ic);
6442 result = IC_RESULT (ic);
6443 aopOp (left, ic, FALSE);
6444 aopOp (result, ic, FALSE);
6446 switch (AOP_SIZE (left))
6448 case 1: /* swap nibbles in byte */
6449 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6450 emitcode ("swap", "a");
6451 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6453 case 2: /* swap bytes in word */
6454 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6456 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6457 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6458 0, isOperandVolatile (result, FALSE));
6459 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6461 else if (operandsEqu (left, result))
6464 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6465 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6467 emitcode ("mov", "b,a");
6470 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6471 0, isOperandVolatile (result, FALSE));
6472 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6476 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6477 0, isOperandVolatile (result, FALSE));
6478 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6479 1, isOperandVolatile (result, FALSE));
6483 wassertl(FALSE, "unsupported SWAP operand size");
6486 freeAsmop (left, NULL, ic, TRUE);
6487 freeAsmop (result, NULL, ic, TRUE);
6491 /*-----------------------------------------------------------------*/
6492 /* AccRol - rotate left accumulator by known count */
6493 /*-----------------------------------------------------------------*/
6495 AccRol (int shCount)
6497 shCount &= 0x0007; // shCount : 0..7
6504 emitcode ("rl", "a");
6507 emitcode ("rl", "a");
6508 emitcode ("rl", "a");
6511 emitcode ("swap", "a");
6512 emitcode ("rr", "a");
6515 emitcode ("swap", "a");
6518 emitcode ("swap", "a");
6519 emitcode ("rl", "a");
6522 emitcode ("rr", "a");
6523 emitcode ("rr", "a");
6526 emitcode ("rr", "a");
6531 /*-----------------------------------------------------------------*/
6532 /* AccLsh - left shift accumulator by known count */
6533 /*-----------------------------------------------------------------*/
6535 AccLsh (int shCount)
6540 emitcode ("add", "a,acc");
6541 else if (shCount == 2)
6543 emitcode ("add", "a,acc");
6544 emitcode ("add", "a,acc");
6548 /* rotate left accumulator */
6550 /* and kill the lower order bits */
6551 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6556 /*-----------------------------------------------------------------*/
6557 /* AccRsh - right shift accumulator by known count */
6558 /*-----------------------------------------------------------------*/
6560 AccRsh (int shCount)
6567 emitcode ("rrc", "a");
6571 /* rotate right accumulator */
6572 AccRol (8 - shCount);
6573 /* and kill the higher order bits */
6574 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6579 /*-----------------------------------------------------------------*/
6580 /* AccSRsh - signed right shift accumulator by known count */
6581 /*-----------------------------------------------------------------*/
6583 AccSRsh (int shCount)
6590 emitcode ("mov", "c,acc.7");
6591 emitcode ("rrc", "a");
6593 else if (shCount == 2)
6595 emitcode ("mov", "c,acc.7");
6596 emitcode ("rrc", "a");
6597 emitcode ("mov", "c,acc.7");
6598 emitcode ("rrc", "a");
6602 tlbl = newiTempLabel (NULL);
6603 /* rotate right accumulator */
6604 AccRol (8 - shCount);
6605 /* and kill the higher order bits */
6606 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6607 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6608 emitcode ("orl", "a,#0x%02x",
6609 (unsigned char) ~SRMask[shCount]);
6610 emitcode ("", "%05d$:", tlbl->key + 100);
6615 /*-----------------------------------------------------------------*/
6616 /* shiftR1Left2Result - shift right one byte from left to result */
6617 /*-----------------------------------------------------------------*/
6619 shiftR1Left2Result (operand * left, int offl,
6620 operand * result, int offr,
6621 int shCount, int sign)
6623 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6624 /* shift right accumulator */
6629 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6632 /*-----------------------------------------------------------------*/
6633 /* shiftL1Left2Result - shift left one byte from left to result */
6634 /*-----------------------------------------------------------------*/
6636 shiftL1Left2Result (operand * left, int offl,
6637 operand * result, int offr, int shCount)
6640 l = aopGet (AOP (left), offl, FALSE, FALSE);
6642 /* shift left accumulator */
6644 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6647 /*-----------------------------------------------------------------*/
6648 /* movLeft2Result - move byte from left to result */
6649 /*-----------------------------------------------------------------*/
6651 movLeft2Result (operand * left, int offl,
6652 operand * result, int offr, int sign)
6655 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6657 l = aopGet (AOP (left), offl, FALSE, FALSE);
6659 if (*l == '@' && (IS_AOP_PREG (result)))
6661 emitcode ("mov", "a,%s", l);
6662 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6667 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6670 /* MSB sign in acc.7 ! */
6671 if (getDataSize (left) == offl + 1)
6673 emitcode ("mov", "a,%s", l);
6674 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6681 /*-----------------------------------------------------------------*/
6682 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6683 /*-----------------------------------------------------------------*/
6687 emitcode ("rrc", "a");
6688 emitcode ("xch", "a,%s", x);
6689 emitcode ("rrc", "a");
6690 emitcode ("xch", "a,%s", x);
6693 /*-----------------------------------------------------------------*/
6694 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6695 /*-----------------------------------------------------------------*/
6699 emitcode ("xch", "a,%s", x);
6700 emitcode ("rlc", "a");
6701 emitcode ("xch", "a,%s", x);
6702 emitcode ("rlc", "a");
6705 /*-----------------------------------------------------------------*/
6706 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6707 /*-----------------------------------------------------------------*/
6711 emitcode ("xch", "a,%s", x);
6712 emitcode ("add", "a,acc");
6713 emitcode ("xch", "a,%s", x);
6714 emitcode ("rlc", "a");
6717 /*-----------------------------------------------------------------*/
6718 /* AccAXLsh - left shift a:x by known count (0..7) */
6719 /*-----------------------------------------------------------------*/
6721 AccAXLsh (char *x, int shCount)
6736 case 5: // AAAAABBB:CCCCCDDD
6738 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6740 emitcode ("anl", "a,#0x%02x",
6741 SLMask[shCount]); // BBB00000:CCCCCDDD
6743 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6745 AccRol (shCount); // DDDCCCCC:BBB00000
6747 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6749 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6751 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6753 emitcode ("anl", "a,#0x%02x",
6754 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6756 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6758 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6761 case 6: // AAAAAABB:CCCCCCDD
6762 emitcode ("anl", "a,#0x%02x",
6763 SRMask[shCount]); // 000000BB:CCCCCCDD
6764 emitcode ("mov", "c,acc.0"); // c = B
6765 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6767 AccAXRrl1 (x); // BCCCCCCD:D000000B
6768 AccAXRrl1 (x); // BBCCCCCC:DD000000
6770 emitcode("rrc","a");
6771 emitcode("xch","a,%s", x);
6772 emitcode("rrc","a");
6773 emitcode("mov","c,acc.0"); //<< get correct bit
6774 emitcode("xch","a,%s", x);
6776 emitcode("rrc","a");
6777 emitcode("xch","a,%s", x);
6778 emitcode("rrc","a");
6779 emitcode("xch","a,%s", x);
6782 case 7: // a:x <<= 7
6784 emitcode ("anl", "a,#0x%02x",
6785 SRMask[shCount]); // 0000000B:CCCCCCCD
6787 emitcode ("mov", "c,acc.0"); // c = B
6789 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6791 AccAXRrl1 (x); // BCCCCCCC:D0000000
6799 /*-----------------------------------------------------------------*/
6800 /* AccAXRsh - right shift a:x known count (0..7) */
6801 /*-----------------------------------------------------------------*/
6803 AccAXRsh (char *x, int shCount)
6811 AccAXRrl1 (x); // 0->a:x
6816 AccAXRrl1 (x); // 0->a:x
6819 AccAXRrl1 (x); // 0->a:x
6824 case 5: // AAAAABBB:CCCCCDDD = a:x
6826 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6828 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6830 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6832 emitcode ("anl", "a,#0x%02x",
6833 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6835 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6837 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6839 emitcode ("anl", "a,#0x%02x",
6840 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6842 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6844 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6846 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6849 case 6: // AABBBBBB:CCDDDDDD
6851 emitcode ("mov", "c,acc.7");
6852 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6854 emitcode ("mov", "c,acc.7");
6855 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6857 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6859 emitcode ("anl", "a,#0x%02x",
6860 SRMask[shCount]); // 000000AA:BBBBBBCC
6863 case 7: // ABBBBBBB:CDDDDDDD
6865 emitcode ("mov", "c,acc.7"); // c = A
6867 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6869 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6871 emitcode ("anl", "a,#0x%02x",
6872 SRMask[shCount]); // 0000000A:BBBBBBBC
6880 /*-----------------------------------------------------------------*/
6881 /* AccAXRshS - right shift signed a:x known count (0..7) */
6882 /*-----------------------------------------------------------------*/
6884 AccAXRshS (char *x, int shCount)
6892 emitcode ("mov", "c,acc.7");
6893 AccAXRrl1 (x); // s->a:x
6897 emitcode ("mov", "c,acc.7");
6898 AccAXRrl1 (x); // s->a:x
6900 emitcode ("mov", "c,acc.7");
6901 AccAXRrl1 (x); // s->a:x
6906 case 5: // AAAAABBB:CCCCCDDD = a:x
6908 tlbl = newiTempLabel (NULL);
6909 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6911 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6913 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6915 emitcode ("anl", "a,#0x%02x",
6916 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6918 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6920 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6922 emitcode ("anl", "a,#0x%02x",
6923 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6925 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6927 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6929 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6931 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6932 emitcode ("orl", "a,#0x%02x",
6933 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6935 emitcode ("", "%05d$:", tlbl->key + 100);
6936 break; // SSSSAAAA:BBBCCCCC
6938 case 6: // AABBBBBB:CCDDDDDD
6940 tlbl = newiTempLabel (NULL);
6941 emitcode ("mov", "c,acc.7");
6942 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6944 emitcode ("mov", "c,acc.7");
6945 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6947 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6949 emitcode ("anl", "a,#0x%02x",
6950 SRMask[shCount]); // 000000AA:BBBBBBCC
6952 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6953 emitcode ("orl", "a,#0x%02x",
6954 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6956 emitcode ("", "%05d$:", tlbl->key + 100);
6958 case 7: // ABBBBBBB:CDDDDDDD
6960 tlbl = newiTempLabel (NULL);
6961 emitcode ("mov", "c,acc.7"); // c = A
6963 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6965 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6967 emitcode ("anl", "a,#0x%02x",
6968 SRMask[shCount]); // 0000000A:BBBBBBBC
6970 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6971 emitcode ("orl", "a,#0x%02x",
6972 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6974 emitcode ("", "%05d$:", tlbl->key + 100);
6981 /*-----------------------------------------------------------------*/
6982 /* shiftL2Left2Result - shift left two bytes from left to result */
6983 /*-----------------------------------------------------------------*/
6985 shiftL2Left2Result (operand * left, int offl,
6986 operand * result, int offr, int shCount)
6988 if (sameRegs (AOP (result), AOP (left)) &&
6989 ((offl + MSB16) == offr))
6991 /* don't crash result[offr] */
6992 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6993 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6997 movLeft2Result (left, offl, result, offr, 0);
6998 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7000 /* ax << shCount (x = lsb(result)) */
7001 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7002 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7006 /*-----------------------------------------------------------------*/
7007 /* shiftR2Left2Result - shift right two bytes from left to result */
7008 /*-----------------------------------------------------------------*/
7010 shiftR2Left2Result (operand * left, int offl,
7011 operand * result, int offr,
7012 int shCount, int sign)
7014 if (sameRegs (AOP (result), AOP (left)) &&
7015 ((offl + MSB16) == offr))
7017 /* don't crash result[offr] */
7018 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7019 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7023 movLeft2Result (left, offl, result, offr, 0);
7024 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7026 /* a:x >> shCount (x = lsb(result)) */
7028 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7030 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7031 if (getDataSize (result) > 1)
7032 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7035 /*-----------------------------------------------------------------*/
7036 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7037 /*-----------------------------------------------------------------*/
7039 shiftLLeftOrResult (operand * left, int offl,
7040 operand * result, int offr, int shCount)
7042 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7043 /* shift left accumulator */
7045 /* or with result */
7046 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7047 /* back to result */
7048 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7051 /*-----------------------------------------------------------------*/
7052 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7053 /*-----------------------------------------------------------------*/
7055 shiftRLeftOrResult (operand * left, int offl,
7056 operand * result, int offr, int shCount)
7058 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7059 /* shift right accumulator */
7061 /* or with result */
7062 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7063 /* back to result */
7064 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7067 /*-----------------------------------------------------------------*/
7068 /* genlshOne - left shift a one byte quantity by known count */
7069 /*-----------------------------------------------------------------*/
7071 genlshOne (operand * result, operand * left, int shCount)
7073 D(emitcode ("; genlshOne",""));
7075 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7078 /*-----------------------------------------------------------------*/
7079 /* genlshTwo - left shift two bytes by known amount != 0 */
7080 /*-----------------------------------------------------------------*/
7082 genlshTwo (operand * result, operand * left, int shCount)
7086 D(emitcode ("; genlshTwo",""));
7088 size = getDataSize (result);
7090 /* if shCount >= 8 */
7098 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7100 movLeft2Result (left, LSB, result, MSB16, 0);
7102 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7105 /* 1 <= shCount <= 7 */
7109 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7111 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7115 /*-----------------------------------------------------------------*/
7116 /* shiftLLong - shift left one long from left to result */
7117 /* offl = LSB or MSB16 */
7118 /*-----------------------------------------------------------------*/
7120 shiftLLong (operand * left, operand * result, int offr)
7123 int size = AOP_SIZE (result);
7125 if (size >= LSB + offr)
7127 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7129 emitcode ("add", "a,acc");
7130 if (sameRegs (AOP (left), AOP (result)) &&
7131 size >= MSB16 + offr && offr != LSB)
7132 emitcode ("xch", "a,%s",
7133 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7135 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7138 if (size >= MSB16 + offr)
7140 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7142 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7145 emitcode ("rlc", "a");
7146 if (sameRegs (AOP (left), AOP (result)) &&
7147 size >= MSB24 + offr && offr != LSB)
7148 emitcode ("xch", "a,%s",
7149 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7151 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7154 if (size >= MSB24 + offr)
7156 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7158 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7161 emitcode ("rlc", "a");
7162 if (sameRegs (AOP (left), AOP (result)) &&
7163 size >= MSB32 + offr && offr != LSB)
7164 emitcode ("xch", "a,%s",
7165 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7167 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7170 if (size > MSB32 + offr)
7172 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7174 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7177 emitcode ("rlc", "a");
7178 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7181 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7184 /*-----------------------------------------------------------------*/
7185 /* genlshFour - shift four byte by a known amount != 0 */
7186 /*-----------------------------------------------------------------*/
7188 genlshFour (operand * result, operand * left, int shCount)
7192 D(emitcode ("; genlshFour",""));
7194 size = AOP_SIZE (result);
7196 /* if shifting more that 3 bytes */
7201 /* lowest order of left goes to the highest
7202 order of the destination */
7203 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7205 movLeft2Result (left, LSB, result, MSB32, 0);
7206 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7207 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7208 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7212 /* more than two bytes */
7213 else if (shCount >= 16)
7215 /* lower order two bytes goes to higher order two bytes */
7217 /* if some more remaining */
7219 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7222 movLeft2Result (left, MSB16, result, MSB32, 0);
7223 movLeft2Result (left, LSB, result, MSB24, 0);
7225 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7226 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7230 /* if more than 1 byte */
7231 else if (shCount >= 8)
7233 /* lower order three bytes goes to higher order three bytes */
7238 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7240 movLeft2Result (left, LSB, result, MSB16, 0);
7246 movLeft2Result (left, MSB24, result, MSB32, 0);
7247 movLeft2Result (left, MSB16, result, MSB24, 0);
7248 movLeft2Result (left, LSB, result, MSB16, 0);
7249 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7251 else if (shCount == 1)
7252 shiftLLong (left, result, MSB16);
7255 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7256 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7257 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7258 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7263 /* 1 <= shCount <= 7 */
7264 else if (shCount <= 2)
7266 shiftLLong (left, result, LSB);
7268 shiftLLong (result, result, LSB);
7270 /* 3 <= shCount <= 7, optimize */
7273 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7274 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7275 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7279 /*-----------------------------------------------------------------*/
7280 /* genLeftShiftLiteral - left shifting by known count */
7281 /*-----------------------------------------------------------------*/
7283 genLeftShiftLiteral (operand * left,
7288 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7291 D(emitcode ("; genLeftShiftLiteral",""));
7293 freeAsmop (right, NULL, ic, TRUE);
7295 aopOp (left, ic, FALSE);
7296 aopOp (result, ic, FALSE);
7298 size = getSize (operandType (result));
7301 emitcode ("; shift left ", "result %d, left %d", size,
7305 /* I suppose that the left size >= result size */
7310 movLeft2Result (left, size, result, size, 0);
7314 else if (shCount >= (size * 8))
7316 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7322 genlshOne (result, left, shCount);
7326 genlshTwo (result, left, shCount);
7330 genlshFour (result, left, shCount);
7333 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7334 "*** ack! mystery literal shift!\n");
7338 freeAsmop (left, NULL, ic, TRUE);
7339 freeAsmop (result, NULL, ic, TRUE);
7342 /*-----------------------------------------------------------------*/
7343 /* genLeftShift - generates code for left shifting */
7344 /*-----------------------------------------------------------------*/
7346 genLeftShift (iCode * ic)
7348 operand *left, *right, *result;
7351 symbol *tlbl, *tlbl1;
7353 D(emitcode ("; genLeftShift",""));
7355 right = IC_RIGHT (ic);
7356 left = IC_LEFT (ic);
7357 result = IC_RESULT (ic);
7359 aopOp (right, ic, FALSE);
7361 /* if the shift count is known then do it
7362 as efficiently as possible */
7363 if (AOP_TYPE (right) == AOP_LIT)
7365 genLeftShiftLiteral (left, right, result, ic);
7369 /* shift count is unknown then we have to form
7370 a loop get the loop count in B : Note: we take
7371 only the lower order byte since shifting
7372 more that 32 bits make no sense anyway, ( the
7373 largest size of an object can be only 32 bits ) */
7375 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7376 emitcode ("inc", "b");
7377 freeAsmop (right, NULL, ic, TRUE);
7378 aopOp (left, ic, FALSE);
7379 aopOp (result, ic, FALSE);
7381 /* now move the left to the result if they are not the
7383 if (!sameRegs (AOP (left), AOP (result)) &&
7384 AOP_SIZE (result) > 1)
7387 size = AOP_SIZE (result);
7391 l = aopGet (AOP (left), offset, FALSE, TRUE);
7392 if (*l == '@' && (IS_AOP_PREG (result)))
7395 emitcode ("mov", "a,%s", l);
7396 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7399 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7404 tlbl = newiTempLabel (NULL);
7405 size = AOP_SIZE (result);
7407 tlbl1 = newiTempLabel (NULL);
7409 /* if it is only one byte then */
7412 symbol *tlbl1 = newiTempLabel (NULL);
7414 l = aopGet (AOP (left), 0, FALSE, FALSE);
7416 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7417 emitcode ("", "%05d$:", tlbl->key + 100);
7418 emitcode ("add", "a,acc");
7419 emitcode ("", "%05d$:", tlbl1->key + 100);
7420 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7421 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7425 reAdjustPreg (AOP (result));
7427 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7428 emitcode ("", "%05d$:", tlbl->key + 100);
7429 l = aopGet (AOP (result), offset, FALSE, FALSE);
7431 emitcode ("add", "a,acc");
7432 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7435 l = aopGet (AOP (result), offset, FALSE, FALSE);
7437 emitcode ("rlc", "a");
7438 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7440 reAdjustPreg (AOP (result));
7442 emitcode ("", "%05d$:", tlbl1->key + 100);
7443 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7445 freeAsmop (left, NULL, ic, TRUE);
7446 freeAsmop (result, NULL, ic, TRUE);
7449 /*-----------------------------------------------------------------*/
7450 /* genrshOne - right shift a one byte quantity by known count */
7451 /*-----------------------------------------------------------------*/
7453 genrshOne (operand * result, operand * left,
7454 int shCount, int sign)
7456 D(emitcode ("; genrshOne",""));
7458 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7461 /*-----------------------------------------------------------------*/
7462 /* genrshTwo - right shift two bytes by known amount != 0 */
7463 /*-----------------------------------------------------------------*/
7465 genrshTwo (operand * result, operand * left,
7466 int shCount, int sign)
7468 D(emitcode ("; genrshTwo",""));
7470 /* if shCount >= 8 */
7475 shiftR1Left2Result (left, MSB16, result, LSB,
7478 movLeft2Result (left, MSB16, result, LSB, sign);
7479 addSign (result, MSB16, sign);
7482 /* 1 <= shCount <= 7 */
7484 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7487 /*-----------------------------------------------------------------*/
7488 /* shiftRLong - shift right one long from left to result */
7489 /* offl = LSB or MSB16 */
7490 /*-----------------------------------------------------------------*/
7492 shiftRLong (operand * left, int offl,
7493 operand * result, int sign)
7495 int isSameRegs=sameRegs(AOP(left),AOP(result));
7497 if (isSameRegs && offl>1) {
7498 // we are in big trouble, but this shouldn't happen
7499 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7502 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7507 emitcode ("rlc", "a");
7508 emitcode ("subb", "a,acc");
7510 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7512 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7513 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7516 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7521 emitcode ("clr", "c");
7523 emitcode ("mov", "c,acc.7");
7526 emitcode ("rrc", "a");
7528 if (isSameRegs && offl==MSB16) {
7529 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7531 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7532 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7535 emitcode ("rrc", "a");
7536 if (isSameRegs && offl==1) {
7537 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7539 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7540 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7542 emitcode ("rrc", "a");
7543 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7547 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7548 emitcode ("rrc", "a");
7549 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7553 /*-----------------------------------------------------------------*/
7554 /* genrshFour - shift four byte by a known amount != 0 */
7555 /*-----------------------------------------------------------------*/
7557 genrshFour (operand * result, operand * left,
7558 int shCount, int sign)
7560 D(emitcode ("; genrshFour",""));
7562 /* if shifting more that 3 bytes */
7567 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7569 movLeft2Result (left, MSB32, result, LSB, sign);
7570 addSign (result, MSB16, sign);
7572 else if (shCount >= 16)
7576 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7579 movLeft2Result (left, MSB24, result, LSB, 0);
7580 movLeft2Result (left, MSB32, result, MSB16, sign);
7582 addSign (result, MSB24, sign);
7584 else if (shCount >= 8)
7588 shiftRLong (left, MSB16, result, sign);
7589 else if (shCount == 0)
7591 movLeft2Result (left, MSB16, result, LSB, 0);
7592 movLeft2Result (left, MSB24, result, MSB16, 0);
7593 movLeft2Result (left, MSB32, result, MSB24, sign);
7594 addSign (result, MSB32, sign);
7598 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7599 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7600 /* the last shift is signed */
7601 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7602 addSign (result, MSB32, sign);
7606 { /* 1 <= shCount <= 7 */
7609 shiftRLong (left, LSB, result, sign);
7611 shiftRLong (result, LSB, result, sign);
7615 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7616 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7617 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7622 /*-----------------------------------------------------------------*/
7623 /* genRightShiftLiteral - right shifting by known count */
7624 /*-----------------------------------------------------------------*/
7626 genRightShiftLiteral (operand * left,
7632 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7635 D(emitcode ("; genRightShiftLiteral",""));
7637 freeAsmop (right, NULL, ic, TRUE);
7639 aopOp (left, ic, FALSE);
7640 aopOp (result, ic, FALSE);
7643 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7647 size = getDataSize (left);
7648 /* test the LEFT size !!! */
7650 /* I suppose that the left size >= result size */
7653 size = getDataSize (result);
7655 movLeft2Result (left, size, result, size, 0);
7658 else if (shCount >= (size * 8))
7661 /* get sign in acc.7 */
7662 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7664 addSign (result, LSB, sign);
7671 genrshOne (result, left, shCount, sign);
7675 genrshTwo (result, left, shCount, sign);
7679 genrshFour (result, left, shCount, sign);
7685 freeAsmop (left, NULL, ic, TRUE);
7686 freeAsmop (result, NULL, ic, TRUE);
7689 /*-----------------------------------------------------------------*/
7690 /* genSignedRightShift - right shift of signed number */
7691 /*-----------------------------------------------------------------*/
7693 genSignedRightShift (iCode * ic)
7695 operand *right, *left, *result;
7698 symbol *tlbl, *tlbl1;
7700 D(emitcode ("; genSignedRightShift",""));
7702 /* we do it the hard way put the shift count in b
7703 and loop thru preserving the sign */
7705 right = IC_RIGHT (ic);
7706 left = IC_LEFT (ic);
7707 result = IC_RESULT (ic);
7709 aopOp (right, ic, FALSE);
7712 if (AOP_TYPE (right) == AOP_LIT)
7714 genRightShiftLiteral (left, right, result, ic, 1);
7717 /* shift count is unknown then we have to form
7718 a loop get the loop count in B : Note: we take
7719 only the lower order byte since shifting
7720 more that 32 bits make no sense anyway, ( the
7721 largest size of an object can be only 32 bits ) */
7723 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7724 emitcode ("inc", "b");
7725 freeAsmop (right, NULL, ic, TRUE);
7726 aopOp (left, ic, FALSE);
7727 aopOp (result, ic, FALSE);
7729 /* now move the left to the result if they are not the
7731 if (!sameRegs (AOP (left), AOP (result)) &&
7732 AOP_SIZE (result) > 1)
7735 size = AOP_SIZE (result);
7739 l = aopGet (AOP (left), offset, FALSE, TRUE);
7740 if (*l == '@' && IS_AOP_PREG (result))
7743 emitcode ("mov", "a,%s", l);
7744 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7747 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7752 /* mov the highest order bit to OVR */
7753 tlbl = newiTempLabel (NULL);
7754 tlbl1 = newiTempLabel (NULL);
7756 size = AOP_SIZE (result);
7758 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7759 emitcode ("rlc", "a");
7760 emitcode ("mov", "ov,c");
7761 /* if it is only one byte then */
7764 l = aopGet (AOP (left), 0, FALSE, FALSE);
7766 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7767 emitcode ("", "%05d$:", tlbl->key + 100);
7768 emitcode ("mov", "c,ov");
7769 emitcode ("rrc", "a");
7770 emitcode ("", "%05d$:", tlbl1->key + 100);
7771 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7772 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7776 reAdjustPreg (AOP (result));
7777 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7778 emitcode ("", "%05d$:", tlbl->key + 100);
7779 emitcode ("mov", "c,ov");
7782 l = aopGet (AOP (result), offset, FALSE, FALSE);
7784 emitcode ("rrc", "a");
7785 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7787 reAdjustPreg (AOP (result));
7788 emitcode ("", "%05d$:", tlbl1->key + 100);
7789 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7792 freeAsmop (left, NULL, ic, TRUE);
7793 freeAsmop (result, NULL, ic, TRUE);
7796 /*-----------------------------------------------------------------*/
7797 /* genRightShift - generate code for right shifting */
7798 /*-----------------------------------------------------------------*/
7800 genRightShift (iCode * ic)
7802 operand *right, *left, *result;
7806 symbol *tlbl, *tlbl1;
7808 D(emitcode ("; genRightShift",""));
7810 /* if signed then we do it the hard way preserve the
7811 sign bit moving it inwards */
7812 letype = getSpec (operandType (IC_LEFT (ic)));
7814 if (!SPEC_USIGN (letype))
7816 genSignedRightShift (ic);
7820 /* signed & unsigned types are treated the same : i.e. the
7821 signed is NOT propagated inwards : quoting from the
7822 ANSI - standard : "for E1 >> E2, is equivalent to division
7823 by 2**E2 if unsigned or if it has a non-negative value,
7824 otherwise the result is implementation defined ", MY definition
7825 is that the sign does not get propagated */
7827 right = IC_RIGHT (ic);
7828 left = IC_LEFT (ic);
7829 result = IC_RESULT (ic);
7831 aopOp (right, ic, FALSE);
7833 /* if the shift count is known then do it
7834 as efficiently as possible */
7835 if (AOP_TYPE (right) == AOP_LIT)
7837 genRightShiftLiteral (left, right, result, ic, 0);
7841 /* shift count is unknown then we have to form
7842 a loop get the loop count in B : Note: we take
7843 only the lower order byte since shifting
7844 more that 32 bits make no sense anyway, ( the
7845 largest size of an object can be only 32 bits ) */
7847 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7848 emitcode ("inc", "b");
7849 freeAsmop (right, NULL, ic, TRUE);
7850 aopOp (left, ic, FALSE);
7851 aopOp (result, ic, FALSE);
7853 /* now move the left to the result if they are not the
7855 if (!sameRegs (AOP (left), AOP (result)) &&
7856 AOP_SIZE (result) > 1)
7859 size = AOP_SIZE (result);
7863 l = aopGet (AOP (left), offset, FALSE, TRUE);
7864 if (*l == '@' && IS_AOP_PREG (result))
7867 emitcode ("mov", "a,%s", l);
7868 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7871 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7876 tlbl = newiTempLabel (NULL);
7877 tlbl1 = newiTempLabel (NULL);
7878 size = AOP_SIZE (result);
7881 /* if it is only one byte then */
7884 l = aopGet (AOP (left), 0, FALSE, FALSE);
7886 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7887 emitcode ("", "%05d$:", tlbl->key + 100);
7889 emitcode ("rrc", "a");
7890 emitcode ("", "%05d$:", tlbl1->key + 100);
7891 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7892 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7896 reAdjustPreg (AOP (result));
7897 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7898 emitcode ("", "%05d$:", tlbl->key + 100);
7902 l = aopGet (AOP (result), offset, FALSE, FALSE);
7904 emitcode ("rrc", "a");
7905 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7907 reAdjustPreg (AOP (result));
7909 emitcode ("", "%05d$:", tlbl1->key + 100);
7910 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7913 freeAsmop (left, NULL, ic, TRUE);
7914 freeAsmop (result, NULL, ic, TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* emitPtrByteGet - emits code to get a byte into A through a */
7919 /* pointer register (R0, R1, or DPTR). The */
7920 /* original value of A can be preserved in B. */
7921 /*-----------------------------------------------------------------*/
7923 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7930 emitcode ("mov", "b,a");
7931 emitcode ("mov", "a,@%s", rname);
7936 emitcode ("mov", "b,a");
7937 emitcode ("movx", "a,@%s", rname);
7942 emitcode ("mov", "b,a");
7943 emitcode ("movx", "a,@dptr");
7948 emitcode ("mov", "b,a");
7949 emitcode ("clr", "a");
7950 emitcode ("movc", "a,@a+dptr");
7956 emitcode ("push", "b");
7957 emitcode ("push", "acc");
7959 emitcode ("lcall", "__gptrget");
7961 emitcode ("pop", "b");
7966 /*-----------------------------------------------------------------*/
7967 /* emitPtrByteSet - emits code to set a byte from src through a */
7968 /* pointer register (R0, R1, or DPTR). */
7969 /*-----------------------------------------------------------------*/
7971 emitPtrByteSet (char *rname, int p_type, char *src)
7980 emitcode ("mov", "@%s,a", rname);
7983 emitcode ("mov", "@%s,%s", rname, src);
7988 emitcode ("movx", "@%s,a", rname);
7993 emitcode ("movx", "@dptr,a");
7998 emitcode ("lcall", "__gptrput");
8003 /*-----------------------------------------------------------------*/
8004 /* genUnpackBits - generates code for unpacking bits */
8005 /*-----------------------------------------------------------------*/
8007 genUnpackBits (operand * result, char *rname, int ptype)
8009 int offset = 0; /* result byte offset */
8010 int rsize; /* result size */
8011 int rlen = 0; /* remaining bitfield length */
8012 sym_link *etype; /* bitfield type information */
8013 int blen; /* bitfield length */
8014 int bstr; /* bitfield starting bit within byte */
8016 D(emitcode ("; genUnpackBits",""));
8018 etype = getSpec (operandType (result));
8019 rsize = getSize (operandType (result));
8020 blen = SPEC_BLEN (etype);
8021 bstr = SPEC_BSTR (etype);
8023 /* If the bitfield length is less than a byte */
8026 emitPtrByteGet (rname, ptype, FALSE);
8028 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8029 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8033 /* Bit field did not fit in a byte. Copy all
8034 but the partial byte at the end. */
8035 for (rlen=blen;rlen>=8;rlen-=8)
8037 emitPtrByteGet (rname, ptype, FALSE);
8038 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8040 emitcode ("inc", "%s", rname);
8043 /* Handle the partial byte at the end */
8046 emitPtrByteGet (rname, ptype, FALSE);
8047 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8048 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8056 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8061 /*-----------------------------------------------------------------*/
8062 /* genDataPointerGet - generates code when ptr offset is known */
8063 /*-----------------------------------------------------------------*/
8065 genDataPointerGet (operand * left,
8071 int size, offset = 0;
8073 D(emitcode ("; genDataPointerGet",""));
8075 aopOp (result, ic, TRUE);
8077 /* get the string representation of the name */
8078 l = aopGet (AOP (left), 0, FALSE, TRUE);
8079 size = AOP_SIZE (result);
8083 sprintf (buffer, "(%s + %d)", l + 1, offset);
8085 sprintf (buffer, "%s", l + 1);
8086 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8089 freeAsmop (left, NULL, ic, TRUE);
8090 freeAsmop (result, NULL, ic, TRUE);
8093 /*-----------------------------------------------------------------*/
8094 /* genNearPointerGet - emitcode for near pointer fetch */
8095 /*-----------------------------------------------------------------*/
8097 genNearPointerGet (operand * left,
8105 sym_link *rtype, *retype;
8106 sym_link *ltype = operandType (left);
8109 D(emitcode ("; genNearPointerGet",""));
8111 rtype = operandType (result);
8112 retype = getSpec (rtype);
8114 aopOp (left, ic, FALSE);
8116 /* if left is rematerialisable and
8117 result is not bitfield variable type and
8118 the left is pointer to data space i.e
8119 lower 128 bytes of space */
8120 if (AOP_TYPE (left) == AOP_IMMD &&
8121 !IS_BITFIELD (retype) &&
8122 DCL_TYPE (ltype) == POINTER)
8124 genDataPointerGet (left, result, ic);
8128 /* if the value is already in a pointer register
8129 then don't need anything more */
8130 if (!AOP_INPREG (AOP (left)))
8132 if (IS_AOP_PREG (left))
8134 // Aha, it is a pointer, just in disguise.
8135 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8138 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8139 __FILE__, __LINE__);
8144 emitcode ("mov", "a%s,%s", rname + 1, rname);
8145 rname++; // skip the '@'.
8150 /* otherwise get a free pointer register */
8152 preg = getFreePtr (ic, &aop, FALSE);
8153 emitcode ("mov", "%s,%s",
8155 aopGet (AOP (left), 0, FALSE, TRUE));
8160 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8162 //aopOp (result, ic, FALSE);
8163 aopOp (result, ic, result?TRUE:FALSE);
8165 /* if bitfield then unpack the bits */
8166 if (IS_BITFIELD (retype))
8167 genUnpackBits (result, rname, POINTER);
8170 /* we have can just get the values */
8171 int size = AOP_SIZE (result);
8176 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8179 emitcode ("mov", "a,@%s", rname);
8180 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8184 sprintf (buffer, "@%s", rname);
8185 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8189 emitcode ("inc", "%s", rname);
8193 /* now some housekeeping stuff */
8194 if (aop) /* we had to allocate for this iCode */
8196 if (pi) { /* post increment present */
8197 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8199 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8203 /* we did not allocate which means left
8204 already in a pointer register, then
8205 if size > 0 && this could be used again
8206 we have to point it back to where it
8208 if ((AOP_SIZE (result) > 1 &&
8209 !OP_SYMBOL (left)->remat &&
8210 (OP_SYMBOL (left)->liveTo > ic->seq ||
8214 int size = AOP_SIZE (result) - 1;
8216 emitcode ("dec", "%s", rname);
8221 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8222 freeAsmop (left, NULL, ic, TRUE);
8223 if (pi) pi->generated = 1;
8226 /*-----------------------------------------------------------------*/
8227 /* genPagedPointerGet - emitcode for paged pointer fetch */
8228 /*-----------------------------------------------------------------*/
8230 genPagedPointerGet (operand * left,
8238 sym_link *rtype, *retype;
8240 D(emitcode ("; genPagedPointerGet",""));
8242 rtype = operandType (result);
8243 retype = getSpec (rtype);
8245 aopOp (left, ic, FALSE);
8247 /* if the value is already in a pointer register
8248 then don't need anything more */
8249 if (!AOP_INPREG (AOP (left)))
8251 /* otherwise get a free pointer register */
8253 preg = getFreePtr (ic, &aop, FALSE);
8254 emitcode ("mov", "%s,%s",
8256 aopGet (AOP (left), 0, FALSE, TRUE));
8260 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8262 aopOp (result, ic, FALSE);
8264 /* if bitfield then unpack the bits */
8265 if (IS_BITFIELD (retype))
8266 genUnpackBits (result, rname, PPOINTER);
8269 /* we have can just get the values */
8270 int size = AOP_SIZE (result);
8276 emitcode ("movx", "a,@%s", rname);
8277 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8282 emitcode ("inc", "%s", rname);
8286 /* now some housekeeping stuff */
8287 if (aop) /* we had to allocate for this iCode */
8289 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8290 freeAsmop (NULL, aop, ic, TRUE);
8294 /* we did not allocate which means left
8295 already in a pointer register, then
8296 if size > 0 && this could be used again
8297 we have to point it back to where it
8299 if ((AOP_SIZE (result) > 1 &&
8300 !OP_SYMBOL (left)->remat &&
8301 (OP_SYMBOL (left)->liveTo > ic->seq ||
8305 int size = AOP_SIZE (result) - 1;
8307 emitcode ("dec", "%s", rname);
8312 freeAsmop (left, NULL, ic, TRUE);
8313 freeAsmop (result, NULL, ic, TRUE);
8314 if (pi) pi->generated = 1;
8318 /*--------------------------------------------------------------------*/
8319 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8320 /*--------------------------------------------------------------------*/
8322 loadDptrFromOperand (operand *op, bool loadBToo)
8324 if (AOP_TYPE (op) != AOP_STR)
8326 /* if this is remateriazable */
8327 if (AOP_TYPE (op) == AOP_IMMD)
8329 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8332 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8333 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8336 wassertl(FALSE, "need pointerCode");
8337 emitcode ("", "; mov b,???");
8338 /* genPointerGet and genPointerSet originally did different
8339 ** things for this case. Both seem wrong.
8340 ** from genPointerGet:
8341 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8342 ** from genPointerSet:
8343 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8348 else if (AOP_TYPE (op) == AOP_DPTR)
8352 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8353 emitcode ("push", "acc");
8354 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8355 emitcode ("push", "acc");
8356 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8357 emitcode ("pop", "dph");
8358 emitcode ("pop", "dpl");
8362 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8363 emitcode ("push", "acc");
8364 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8365 emitcode ("pop", "dpl");
8369 { /* we need to get it byte by byte */
8370 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8371 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8373 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8378 /*-----------------------------------------------------------------*/
8379 /* genFarPointerGet - gget value from far space */
8380 /*-----------------------------------------------------------------*/
8382 genFarPointerGet (operand * left,
8383 operand * result, iCode * ic, iCode * pi)
8386 sym_link *retype = getSpec (operandType (result));
8388 D(emitcode ("; genFarPointerGet",""));
8390 aopOp (left, ic, FALSE);
8391 loadDptrFromOperand (left, FALSE);
8393 /* so dptr now contains the address */
8394 aopOp (result, ic, FALSE);
8396 /* if bit then unpack */
8397 if (IS_BITFIELD (retype))
8398 genUnpackBits (result, "dptr", FPOINTER);
8401 size = AOP_SIZE (result);
8406 emitcode ("movx", "a,@dptr");
8407 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8409 emitcode ("inc", "dptr");
8413 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8414 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8415 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8418 freeAsmop (left, NULL, ic, TRUE);
8419 freeAsmop (result, NULL, ic, TRUE);
8422 /*-----------------------------------------------------------------*/
8423 /* genCodePointerGet - gget value from code space */
8424 /*-----------------------------------------------------------------*/
8426 genCodePointerGet (operand * left,
8427 operand * result, iCode * ic, iCode *pi)
8430 sym_link *retype = getSpec (operandType (result));
8432 D(emitcode ("; genCodePointerGet",""));
8434 aopOp (left, ic, FALSE);
8435 loadDptrFromOperand (left, FALSE);
8437 /* so dptr now contains the address */
8438 aopOp (result, ic, FALSE);
8440 /* if bit then unpack */
8441 if (IS_BITFIELD (retype))
8442 genUnpackBits (result, "dptr", CPOINTER);
8445 size = AOP_SIZE (result);
8452 emitcode ("clr", "a");
8453 emitcode ("movc", "a,@a+dptr");
8454 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8455 emitcode ("inc", "dptr");
8459 emitcode ("mov", "a,#0x%02x", offset);
8460 emitcode ("movc", "a,@a+dptr");
8461 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8466 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8467 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8468 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8471 freeAsmop (left, NULL, ic, TRUE);
8472 freeAsmop (result, NULL, ic, TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genGenPointerGet - gget value from generic pointer space */
8477 /*-----------------------------------------------------------------*/
8479 genGenPointerGet (operand * left,
8480 operand * result, iCode * ic, iCode *pi)
8483 sym_link *retype = getSpec (operandType (result));
8485 D(emitcode ("; genGenPointerGet",""));
8487 aopOp (left, ic, FALSE);
8488 loadDptrFromOperand (left, TRUE);
8490 /* so dptr know contains the address */
8491 aopOp (result, ic, FALSE);
8493 /* if bit then unpack */
8494 if (IS_BITFIELD (retype))
8495 genUnpackBits (result, "dptr", GPOINTER);
8498 size = AOP_SIZE (result);
8503 emitcode ("lcall", "__gptrget");
8504 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8506 emitcode ("inc", "dptr");
8510 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8511 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8512 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8515 freeAsmop (left, NULL, ic, TRUE);
8516 freeAsmop (result, NULL, ic, TRUE);
8519 /*-----------------------------------------------------------------*/
8520 /* genPointerGet - generate code for pointer get */
8521 /*-----------------------------------------------------------------*/
8523 genPointerGet (iCode * ic, iCode *pi)
8525 operand *left, *result;
8526 sym_link *type, *etype;
8529 D(emitcode ("; genPointerGet",""));
8531 left = IC_LEFT (ic);
8532 result = IC_RESULT (ic);
8534 /* depending on the type of pointer we need to
8535 move it to the correct pointer register */
8536 type = operandType (left);
8537 etype = getSpec (type);
8538 /* if left is of type of pointer then it is simple */
8539 if (IS_PTR (type) && !IS_FUNC (type->next))
8540 p_type = DCL_TYPE (type);
8543 /* we have to go by the storage class */
8544 p_type = PTR_TYPE (SPEC_OCLS (etype));
8547 /* special case when cast remat */
8548 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8549 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8550 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8551 type = operandType (left);
8552 p_type = DCL_TYPE (type);
8554 /* now that we have the pointer type we assign
8555 the pointer values */
8561 genNearPointerGet (left, result, ic, pi);
8565 genPagedPointerGet (left, result, ic, pi);
8569 genFarPointerGet (left, result, ic, pi);
8573 genCodePointerGet (left, result, ic, pi);
8577 genGenPointerGet (left, result, ic, pi);
8585 /*-----------------------------------------------------------------*/
8586 /* genPackBits - generates code for packed bit storage */
8587 /*-----------------------------------------------------------------*/
8589 genPackBits (sym_link * etype,
8591 char *rname, int p_type)
8593 int offset = 0; /* source byte offset */
8594 int rlen = 0; /* remaining bitfield length */
8595 int blen; /* bitfield length */
8596 int bstr; /* bitfield starting bit within byte */
8597 int litval; /* source literal value (if AOP_LIT) */
8598 unsigned char mask; /* bitmask within current byte */
8600 D(emitcode ("; genPackBits",""));
8602 blen = SPEC_BLEN (etype);
8603 bstr = SPEC_BSTR (etype);
8605 /* If the bitfield length is less than a byte */
8608 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8609 (unsigned char) (0xFF >> (8 - bstr)));
8611 if (AOP_TYPE (right) == AOP_LIT)
8613 /* Case with a bitfield length <8 and literal source
8615 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8617 litval &= (~mask) & 0xff;
8618 emitPtrByteGet (rname, p_type, FALSE);
8619 if ((mask|litval)!=0xff)
8620 emitcode ("anl","a,#0x%02x", mask);
8622 emitcode ("orl","a,#0x%02x", litval);
8626 if ((blen==1) && (p_type!=GPOINTER))
8628 /* Case with a bitfield length == 1 and no generic pointer
8630 if (AOP_TYPE (right) == AOP_CRY)
8631 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8634 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8635 emitcode ("rrc","a");
8637 emitPtrByteGet (rname, p_type, FALSE);
8638 emitcode ("mov","acc.%d,c",bstr);
8642 /* Case with a bitfield length < 8 and arbitrary source
8644 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8645 /* shift and mask source value */
8647 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8649 /* transfer A to B and get next byte */
8650 emitPtrByteGet (rname, p_type, TRUE);
8652 emitcode ("anl", "a,#0x%02x", mask);
8653 emitcode ("orl", "a,b");
8654 if (p_type == GPOINTER)
8655 emitcode ("pop", "b");
8659 emitPtrByteSet (rname, p_type, "a");
8663 /* Bit length is greater than 7 bits. In this case, copy */
8664 /* all except the partial byte at the end */
8665 for (rlen=blen;rlen>=8;rlen-=8)
8667 emitPtrByteSet (rname, p_type,
8668 aopGet (AOP (right), offset++, FALSE, TRUE) );
8670 emitcode ("inc", "%s", rname);
8673 /* If there was a partial byte at the end */
8676 mask = (((unsigned char) -1 << rlen) & 0xff);
8678 if (AOP_TYPE (right) == AOP_LIT)
8680 /* Case with partial byte and literal source
8682 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8683 litval >>= (blen-rlen);
8684 litval &= (~mask) & 0xff;
8685 emitPtrByteGet (rname, p_type, FALSE);
8686 if ((mask|litval)!=0xff)
8687 emitcode ("anl","a,#0x%02x", mask);
8689 emitcode ("orl","a,#0x%02x", litval);
8693 /* Case with partial byte and arbitrary source
8695 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
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");
8706 emitPtrByteSet (rname, p_type, "a");
8712 /*-----------------------------------------------------------------*/
8713 /* genDataPointerSet - remat pointer to data space */
8714 /*-----------------------------------------------------------------*/
8716 genDataPointerSet (operand * right,
8720 int size, offset = 0;
8721 char *l, buffer[256];
8723 D(emitcode ("; genDataPointerSet",""));
8725 aopOp (right, ic, FALSE);
8727 l = aopGet (AOP (result), 0, FALSE, TRUE);
8728 size = AOP_SIZE (right);
8732 sprintf (buffer, "(%s + %d)", l + 1, offset);
8734 sprintf (buffer, "%s", l + 1);
8735 emitcode ("mov", "%s,%s", buffer,
8736 aopGet (AOP (right), offset++, FALSE, FALSE));
8739 freeAsmop (right, NULL, ic, TRUE);
8740 freeAsmop (result, NULL, ic, TRUE);
8743 /*-----------------------------------------------------------------*/
8744 /* genNearPointerSet - emitcode for near pointer put */
8745 /*-----------------------------------------------------------------*/
8747 genNearPointerSet (operand * right,
8755 sym_link *retype, *letype;
8756 sym_link *ptype = operandType (result);
8758 D(emitcode ("; genNearPointerSet",""));
8760 retype = getSpec (operandType (right));
8761 letype = getSpec (ptype);
8762 aopOp (result, ic, FALSE);
8764 /* if the result is rematerializable &
8765 in data space & not a bit variable */
8766 if (AOP_TYPE (result) == AOP_IMMD &&
8767 DCL_TYPE (ptype) == POINTER &&
8768 !IS_BITVAR (retype) &&
8769 !IS_BITVAR (letype))
8771 genDataPointerSet (right, result, ic);
8775 /* if the value is already in a pointer register
8776 then don't need anything more */
8777 if (!AOP_INPREG (AOP (result)))
8780 //AOP_TYPE (result) == AOP_STK
8784 // Aha, it is a pointer, just in disguise.
8785 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8788 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8789 __FILE__, __LINE__);
8794 emitcode ("mov", "a%s,%s", rname + 1, rname);
8795 rname++; // skip the '@'.
8800 /* otherwise get a free pointer register */
8802 preg = getFreePtr (ic, &aop, FALSE);
8803 emitcode ("mov", "%s,%s",
8805 aopGet (AOP (result), 0, FALSE, TRUE));
8811 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8814 aopOp (right, ic, FALSE);
8816 /* if bitfield then unpack the bits */
8817 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8818 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8821 /* we have can just get the values */
8822 int size = AOP_SIZE (right);
8827 l = aopGet (AOP (right), offset, FALSE, TRUE);
8831 emitcode ("mov", "@%s,a", rname);
8834 emitcode ("mov", "@%s,%s", rname, l);
8836 emitcode ("inc", "%s", rname);
8841 /* now some housekeeping stuff */
8842 if (aop) /* we had to allocate for this iCode */
8845 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8846 freeAsmop (NULL, aop, ic, TRUE);
8850 /* we did not allocate which means left
8851 already in a pointer register, then
8852 if size > 0 && this could be used again
8853 we have to point it back to where it
8855 if ((AOP_SIZE (right) > 1 &&
8856 !OP_SYMBOL (result)->remat &&
8857 (OP_SYMBOL (result)->liveTo > ic->seq ||
8861 int size = AOP_SIZE (right) - 1;
8863 emitcode ("dec", "%s", rname);
8868 if (pi) pi->generated = 1;
8869 freeAsmop (result, NULL, ic, TRUE);
8870 freeAsmop (right, NULL, ic, TRUE);
8873 /*-----------------------------------------------------------------*/
8874 /* genPagedPointerSet - emitcode for Paged pointer put */
8875 /*-----------------------------------------------------------------*/
8877 genPagedPointerSet (operand * right,
8885 sym_link *retype, *letype;
8887 D(emitcode ("; genPagedPointerSet",""));
8889 retype = getSpec (operandType (right));
8890 letype = getSpec (operandType (result));
8892 aopOp (result, ic, FALSE);
8894 /* if the value is already in a pointer register
8895 then don't need anything more */
8896 if (!AOP_INPREG (AOP (result)))
8898 /* otherwise get a free pointer register */
8900 preg = getFreePtr (ic, &aop, FALSE);
8901 emitcode ("mov", "%s,%s",
8903 aopGet (AOP (result), 0, FALSE, TRUE));
8907 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8909 aopOp (right, ic, FALSE);
8911 /* if bitfield then unpack the bits */
8912 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8913 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8916 /* we have can just get the values */
8917 int size = AOP_SIZE (right);
8922 l = aopGet (AOP (right), offset, FALSE, TRUE);
8925 emitcode ("movx", "@%s,a", rname);
8928 emitcode ("inc", "%s", rname);
8934 /* now some housekeeping stuff */
8935 if (aop) /* we had to allocate for this iCode */
8938 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8939 freeAsmop (NULL, aop, ic, TRUE);
8943 /* we did not allocate which means left
8944 already in a pointer register, then
8945 if size > 0 && this could be used again
8946 we have to point it back to where it
8948 if (AOP_SIZE (right) > 1 &&
8949 !OP_SYMBOL (result)->remat &&
8950 (OP_SYMBOL (result)->liveTo > ic->seq ||
8953 int size = AOP_SIZE (right) - 1;
8955 emitcode ("dec", "%s", rname);
8960 if (pi) pi->generated = 1;
8961 freeAsmop (result, NULL, ic, TRUE);
8962 freeAsmop (right, NULL, ic, TRUE);
8967 /*-----------------------------------------------------------------*/
8968 /* genFarPointerSet - set value from far space */
8969 /*-----------------------------------------------------------------*/
8971 genFarPointerSet (operand * right,
8972 operand * result, iCode * ic, iCode * pi)
8975 sym_link *retype = getSpec (operandType (right));
8976 sym_link *letype = getSpec (operandType (result));
8978 D(emitcode ("; genFarPointerSet",""));
8980 aopOp (result, ic, FALSE);
8981 loadDptrFromOperand (result, FALSE);
8983 /* so dptr know contains the address */
8984 aopOp (right, ic, FALSE);
8986 /* if bit then unpack */
8987 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8988 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8991 size = AOP_SIZE (right);
8996 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8998 emitcode ("movx", "@dptr,a");
9000 emitcode ("inc", "dptr");
9003 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9004 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9005 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9008 freeAsmop (result, NULL, ic, TRUE);
9009 freeAsmop (right, NULL, ic, TRUE);
9012 /*-----------------------------------------------------------------*/
9013 /* genGenPointerSet - set value from generic pointer space */
9014 /*-----------------------------------------------------------------*/
9016 genGenPointerSet (operand * right,
9017 operand * result, iCode * ic, iCode * pi)
9020 sym_link *retype = getSpec (operandType (right));
9021 sym_link *letype = getSpec (operandType (result));
9023 D(emitcode ("; genGenPointerSet",""));
9025 aopOp (result, ic, FALSE);
9026 loadDptrFromOperand (result, TRUE);
9028 /* so dptr know contains the address */
9029 aopOp (right, ic, FALSE);
9031 /* if bit then unpack */
9032 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9033 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9036 size = AOP_SIZE (right);
9041 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9043 emitcode ("lcall", "__gptrput");
9045 emitcode ("inc", "dptr");
9049 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9050 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9051 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9054 freeAsmop (result, NULL, ic, TRUE);
9055 freeAsmop (right, NULL, ic, TRUE);
9058 /*-----------------------------------------------------------------*/
9059 /* genPointerSet - stores the value into a pointer location */
9060 /*-----------------------------------------------------------------*/
9062 genPointerSet (iCode * ic, iCode *pi)
9064 operand *right, *result;
9065 sym_link *type, *etype;
9068 D(emitcode ("; genPointerSet",""));
9070 right = IC_RIGHT (ic);
9071 result = IC_RESULT (ic);
9073 /* depending on the type of pointer we need to
9074 move it to the correct pointer register */
9075 type = operandType (result);
9076 etype = getSpec (type);
9077 /* if left is of type of pointer then it is simple */
9078 if (IS_PTR (type) && !IS_FUNC (type->next))
9080 p_type = DCL_TYPE (type);
9084 /* we have to go by the storage class */
9085 p_type = PTR_TYPE (SPEC_OCLS (etype));
9088 /* special case when cast remat */
9089 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9090 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9091 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9092 type = operandType (result);
9093 p_type = DCL_TYPE (type);
9095 /* now that we have the pointer type we assign
9096 the pointer values */
9102 genNearPointerSet (right, result, ic, pi);
9106 genPagedPointerSet (right, result, ic, pi);
9110 genFarPointerSet (right, result, ic, pi);
9114 genGenPointerSet (right, result, ic, pi);
9118 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9119 "genPointerSet: illegal pointer type");
9124 /*-----------------------------------------------------------------*/
9125 /* genIfx - generate code for Ifx statement */
9126 /*-----------------------------------------------------------------*/
9128 genIfx (iCode * ic, iCode * popIc)
9130 operand *cond = IC_COND (ic);
9133 D(emitcode ("; genIfx",""));
9135 aopOp (cond, ic, FALSE);
9137 /* get the value into acc */
9138 if (AOP_TYPE (cond) != AOP_CRY)
9142 /* the result is now in the accumulator */
9143 freeAsmop (cond, NULL, ic, TRUE);
9145 /* if there was something to be popped then do it */
9149 /* if the condition is a bit variable */
9150 if (isbit && IS_ITEMP (cond) &&
9152 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9153 else if (isbit && !IS_ITEMP (cond))
9154 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9156 genIfxJump (ic, "a", NULL, NULL, NULL);
9161 /*-----------------------------------------------------------------*/
9162 /* genAddrOf - generates code for address of */
9163 /*-----------------------------------------------------------------*/
9165 genAddrOf (iCode * ic)
9167 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9170 D(emitcode ("; genAddrOf",""));
9172 aopOp (IC_RESULT (ic), ic, FALSE);
9174 /* if the operand is on the stack then we
9175 need to get the stack offset of this
9179 /* if it has an offset then we need to compute
9183 emitcode ("mov", "a,_bp");
9184 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9185 ((char) (sym->stack - _G.nRegsSaved)) :
9186 ((char) sym->stack)) & 0xff);
9187 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9191 /* we can just move _bp */
9192 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9194 /* fill the result with zero */
9195 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9200 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9206 /* object not on stack then we need the name */
9207 size = AOP_SIZE (IC_RESULT (ic));
9212 char s[SDCC_NAME_MAX];
9214 sprintf (s, "#(%s >> %d)",
9218 sprintf (s, "#%s", sym->rname);
9219 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9223 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9227 /*-----------------------------------------------------------------*/
9228 /* genFarFarAssign - assignment when both are in far space */
9229 /*-----------------------------------------------------------------*/
9231 genFarFarAssign (operand * result, operand * right, iCode * ic)
9233 int size = AOP_SIZE (right);
9237 D(emitcode ("; genFarFarAssign",""));
9239 /* first push the right side on to the stack */
9242 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9244 emitcode ("push", "acc");
9247 freeAsmop (right, NULL, ic, FALSE);
9248 /* now assign DPTR to result */
9249 aopOp (result, ic, FALSE);
9250 size = AOP_SIZE (result);
9253 emitcode ("pop", "acc");
9254 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9256 freeAsmop (result, NULL, ic, FALSE);
9260 /*-----------------------------------------------------------------*/
9261 /* genAssign - generate code for assignment */
9262 /*-----------------------------------------------------------------*/
9264 genAssign (iCode * ic)
9266 operand *result, *right;
9268 unsigned long lit = 0L;
9270 D(emitcode("; genAssign",""));
9272 result = IC_RESULT (ic);
9273 right = IC_RIGHT (ic);
9275 /* if they are the same */
9276 if (operandsEqu (result, right) &&
9277 !isOperandVolatile (result, FALSE) &&
9278 !isOperandVolatile (right, FALSE))
9281 aopOp (right, ic, FALSE);
9283 /* special case both in far space */
9284 if (AOP_TYPE (right) == AOP_DPTR &&
9285 IS_TRUE_SYMOP (result) &&
9286 isOperandInFarSpace (result))
9289 genFarFarAssign (result, right, ic);
9293 aopOp (result, ic, TRUE);
9295 /* if they are the same registers */
9296 if (sameRegs (AOP (right), AOP (result)) &&
9297 !isOperandVolatile (result, FALSE) &&
9298 !isOperandVolatile (right, FALSE))
9301 /* if the result is a bit */
9302 if (AOP_TYPE (result) == AOP_CRY)
9305 /* if the right size is a literal then
9306 we know what the value is */
9307 if (AOP_TYPE (right) == AOP_LIT)
9309 if (((int) operandLitValue (right)))
9310 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9312 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9316 /* the right is also a bit variable */
9317 if (AOP_TYPE (right) == AOP_CRY)
9319 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9320 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9326 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9330 /* bit variables done */
9332 size = AOP_SIZE (result);
9334 if (AOP_TYPE (right) == AOP_LIT)
9335 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9337 (AOP_TYPE (result) != AOP_REG) &&
9338 (AOP_TYPE (right) == AOP_LIT) &&
9339 !IS_FLOAT (operandType (right)) &&
9342 emitcode ("clr", "a");
9345 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9346 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9348 aopPut (AOP (result),
9349 aopGet (AOP (right), size, FALSE, FALSE),
9351 isOperandVolatile (result, FALSE));
9358 aopPut (AOP (result),
9359 aopGet (AOP (right), offset, FALSE, FALSE),
9361 isOperandVolatile (result, FALSE));
9367 freeAsmop (right, NULL, ic, TRUE);
9368 freeAsmop (result, NULL, ic, TRUE);
9371 /*-----------------------------------------------------------------*/
9372 /* genJumpTab - genrates code for jump table */
9373 /*-----------------------------------------------------------------*/
9375 genJumpTab (iCode * ic)
9380 D(emitcode ("; genJumpTab",""));
9382 aopOp (IC_JTCOND (ic), ic, FALSE);
9383 /* get the condition into accumulator */
9384 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9386 /* multiply by three */
9387 emitcode ("add", "a,acc");
9388 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9389 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9391 jtab = newiTempLabel (NULL);
9392 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9393 emitcode ("jmp", "@a+dptr");
9394 emitcode ("", "%05d$:", jtab->key + 100);
9395 /* now generate the jump labels */
9396 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9397 jtab = setNextItem (IC_JTLABELS (ic)))
9398 emitcode ("ljmp", "%05d$", jtab->key + 100);
9402 /*-----------------------------------------------------------------*/
9403 /* genCast - gen code for casting */
9404 /*-----------------------------------------------------------------*/
9406 genCast (iCode * ic)
9408 operand *result = IC_RESULT (ic);
9409 sym_link *ctype = operandType (IC_LEFT (ic));
9410 sym_link *rtype = operandType (IC_RIGHT (ic));
9411 operand *right = IC_RIGHT (ic);
9414 D(emitcode("; genCast",""));
9416 /* if they are equivalent then do nothing */
9417 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9420 aopOp (right, ic, FALSE);
9421 aopOp (result, ic, FALSE);
9423 /* if the result is a bit (and not a bitfield) */
9424 // if (AOP_TYPE (result) == AOP_CRY)
9425 if (IS_BITVAR (OP_SYMBOL (result)->type)
9426 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9428 /* if the right size is a literal then
9429 we know what the value is */
9430 if (AOP_TYPE (right) == AOP_LIT)
9432 if (((int) operandLitValue (right)))
9433 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9435 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9440 /* the right is also a bit variable */
9441 if (AOP_TYPE (right) == AOP_CRY)
9443 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9444 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9450 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9455 /* if they are the same size : or less */
9456 if (AOP_SIZE (result) <= AOP_SIZE (right))
9459 /* if they are in the same place */
9460 if (sameRegs (AOP (right), AOP (result)))
9463 /* if they in different places then copy */
9464 size = AOP_SIZE (result);
9468 aopPut (AOP (result),
9469 aopGet (AOP (right), offset, FALSE, FALSE),
9471 isOperandVolatile (result, FALSE));
9478 /* if the result is of type pointer */
9483 sym_link *type = operandType (right);
9484 sym_link *etype = getSpec (type);
9486 /* pointer to generic pointer */
9487 if (IS_GENPTR (ctype))
9490 p_type = DCL_TYPE (type);
9493 if (SPEC_SCLS(etype)==S_REGISTER) {
9494 // let's assume it is a generic pointer
9497 /* we have to go by the storage class */
9498 p_type = PTR_TYPE (SPEC_OCLS (etype));
9502 /* the first two bytes are known */
9503 size = GPTRSIZE - 1;
9507 aopPut (AOP (result),
9508 aopGet (AOP (right), offset, FALSE, FALSE),
9510 isOperandVolatile (result, FALSE));
9513 /* the last byte depending on type */
9515 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9520 // pointerTypeToGPByte will have bitched.
9524 sprintf(gpValStr, "#0x%d", gpVal);
9525 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9530 /* just copy the pointers */
9531 size = AOP_SIZE (result);
9535 aopPut (AOP (result),
9536 aopGet (AOP (right), offset, FALSE, FALSE),
9538 isOperandVolatile (result, FALSE));
9544 /* so we now know that the size of destination is greater
9545 than the size of the source */
9546 /* we move to result for the size of source */
9547 size = AOP_SIZE (right);
9551 aopPut (AOP (result),
9552 aopGet (AOP (right), offset, FALSE, FALSE),
9554 isOperandVolatile (result, FALSE));
9558 /* now depending on the sign of the source && destination */
9559 size = AOP_SIZE (result) - AOP_SIZE (right);
9560 /* if unsigned or not an integral type */
9561 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9564 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9568 /* we need to extend the sign :{ */
9569 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9572 emitcode ("rlc", "a");
9573 emitcode ("subb", "a,acc");
9575 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9578 /* we are done hurray !!!! */
9581 freeAsmop (right, NULL, ic, TRUE);
9582 freeAsmop (result, NULL, ic, TRUE);
9586 /*-----------------------------------------------------------------*/
9587 /* genDjnz - generate decrement & jump if not zero instrucion */
9588 /*-----------------------------------------------------------------*/
9590 genDjnz (iCode * ic, iCode * ifx)
9596 D(emitcode ("; genDjnz",""));
9598 /* if the if condition has a false label
9599 then we cannot save */
9603 /* if the minus is not of the form
9605 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9606 !IS_OP_LITERAL (IC_RIGHT (ic)))
9609 if (operandLitValue (IC_RIGHT (ic)) != 1)
9612 /* if the size of this greater than one then no
9614 if (getSize (operandType (IC_RESULT (ic))) > 1)
9617 /* otherwise we can save BIG */
9618 lbl = newiTempLabel (NULL);
9619 lbl1 = newiTempLabel (NULL);
9621 aopOp (IC_RESULT (ic), ic, FALSE);
9623 if (AOP_NEEDSACC(IC_RESULT(ic)))
9625 /* If the result is accessed indirectly via
9626 * the accumulator, we must explicitly write
9627 * it back after the decrement.
9629 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9631 if (strcmp(rByte, "a"))
9633 /* Something is hopelessly wrong */
9634 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9635 __FILE__, __LINE__);
9636 /* We can just give up; the generated code will be inefficient,
9639 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9642 emitcode ("dec", "%s", rByte);
9643 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9644 emitcode ("jnz", "%05d$", lbl->key + 100);
9646 else if (IS_AOP_PREG (IC_RESULT (ic)))
9648 emitcode ("dec", "%s",
9649 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9650 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9651 emitcode ("jnz", "%05d$", lbl->key + 100);
9655 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9658 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9659 emitcode ("", "%05d$:", lbl->key + 100);
9660 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9661 emitcode ("", "%05d$:", lbl1->key + 100);
9663 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9668 /*-----------------------------------------------------------------*/
9669 /* genReceive - generate code for a receive iCode */
9670 /*-----------------------------------------------------------------*/
9672 genReceive (iCode * ic)
9674 int size = getSize (operandType (IC_RESULT (ic)));
9676 D(emitcode ("; genReceive",""));
9678 if (ic->argreg == 1) { /* first parameter */
9679 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9680 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9681 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9687 for (offset = 0; offset<size; offset++)
9688 if (!strcmp (fReturn[offset], "a"))
9693 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9695 for (offset = size-1; offset>0; offset--)
9696 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9697 emitcode("mov","a,%s", fReturn[0]);
9699 aopOp (IC_RESULT (ic), ic, FALSE);
9701 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9702 isOperandVolatile (IC_RESULT (ic), FALSE));
9703 for (offset = 1; offset<size; offset++)
9704 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9705 isOperandVolatile (IC_RESULT (ic), FALSE));
9711 if (getTempRegs(tempRegs, size, ic))
9713 for (offset = 0; offset<size; offset++)
9714 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9715 aopOp (IC_RESULT (ic), ic, FALSE);
9716 for (offset = 0; offset<size; offset++)
9717 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9718 isOperandVolatile (IC_RESULT (ic), FALSE));
9723 offset = fReturnSizeMCS51 - size;
9725 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9726 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9729 aopOp (IC_RESULT (ic), ic, FALSE);
9730 size = AOP_SIZE (IC_RESULT (ic));
9733 emitcode ("pop", "acc");
9734 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9739 aopOp (IC_RESULT (ic), ic, FALSE);
9741 assignResultValue (IC_RESULT (ic));
9743 } else { /* second receive onwards */
9745 aopOp (IC_RESULT (ic), ic, FALSE);
9746 rb1off = ic->argreg;
9748 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9753 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9756 /*-----------------------------------------------------------------*/
9757 /* genDummyRead - generate code for dummy read of volatiles */
9758 /*-----------------------------------------------------------------*/
9760 genDummyRead (iCode * ic)
9765 D(emitcode("; genDummyRead",""));
9768 if (op && IS_SYMOP (op))
9770 aopOp (op, ic, FALSE);
9772 /* if the result is a bit */
9773 if (AOP_TYPE (op) == AOP_CRY)
9774 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9777 /* bit variables done */
9779 size = AOP_SIZE (op);
9783 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9788 freeAsmop (op, NULL, ic, TRUE);
9792 if (op && IS_SYMOP (op))
9794 aopOp (op, ic, FALSE);
9796 /* if the result is a bit */
9797 if (AOP_TYPE (op) == AOP_CRY)
9798 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9801 /* bit variables done */
9803 size = AOP_SIZE (op);
9807 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9812 freeAsmop (op, NULL, ic, TRUE);
9816 /*-----------------------------------------------------------------*/
9817 /* genCritical - generate code for start of a critical sequence */
9818 /*-----------------------------------------------------------------*/
9820 genCritical (iCode *ic)
9822 symbol *tlbl = newiTempLabel (NULL);
9824 D(emitcode("; genCritical",""));
9827 aopOp (IC_RESULT (ic), ic, TRUE);
9829 emitcode ("setb", "c");
9830 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9831 emitcode ("clr", "c");
9832 emitcode ("", "%05d$:", (tlbl->key + 100));
9835 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9837 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9840 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9843 /*-----------------------------------------------------------------*/
9844 /* genEndCritical - generate code for end of a critical sequence */
9845 /*-----------------------------------------------------------------*/
9847 genEndCritical (iCode *ic)
9849 D(emitcode("; genEndCritical",""));
9853 aopOp (IC_RIGHT (ic), ic, FALSE);
9854 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9856 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9857 emitcode ("mov", "ea,c");
9861 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9862 emitcode ("rrc", "a");
9863 emitcode ("mov", "ea,c");
9865 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9869 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9870 emitcode ("mov", "ea,c");
9874 /*-----------------------------------------------------------------*/
9875 /* gen51Code - generate code for 8051 based controllers */
9876 /*-----------------------------------------------------------------*/
9878 gen51Code (iCode * lic)
9884 _G.currentFunc = NULL;
9885 lineHead = lineCurr = NULL;
9887 /* print the allocation information */
9888 if (allocInfo && currFunc)
9889 printAllocInfo (currFunc, codeOutFile);
9890 /* if debug information required */
9891 if (options.debug && currFunc)
9893 debugFile->writeFunction (currFunc, lic);
9895 /* stack pointer name */
9896 if (options.useXstack)
9902 for (ic = lic; ic; ic = ic->next)
9904 _G.current_iCode = ic;
9906 if (ic->lineno && cln != ic->lineno)
9910 debugFile->writeCLine(ic);
9912 if (!options.noCcodeInAsm) {
9913 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9914 printCLine(ic->filename, ic->lineno));
9919 if (ic->seqPoint && ic->seqPoint != cseq)
9921 emitcode ("", "; sequence point %d", ic->seqPoint);
9922 cseq = ic->seqPoint;
9925 if (options.iCodeInAsm) {
9929 for (i=0; i<8; i++) {
9930 sprintf (®sInUse[i],
9931 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9934 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9936 /* if the result is marked as
9937 spilt and rematerializable or code for
9938 this has already been generated then
9940 if (resultRemat (ic) || ic->generated)
9943 /* depending on the operation */
9963 /* IPOP happens only when trying to restore a
9964 spilt live range, if there is an ifx statement
9965 following this pop then the if statement might
9966 be using some of the registers being popped which
9967 would destory the contents of the register so
9968 we need to check for this condition and handle it */
9970 ic->next->op == IFX &&
9971 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9972 genIfx (ic->next, ic);
9990 genEndFunction (ic);
10010 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10027 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10031 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10038 /* note these two are xlated by algebraic equivalence
10039 during parsing SDCC.y */
10040 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10041 "got '>=' or '<=' shouldn't have come here");
10045 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10057 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10061 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10065 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10089 genRightShift (ic);
10092 case GET_VALUE_AT_ADDRESS:
10093 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10097 if (POINTER_SET (ic))
10098 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10124 addSet (&_G.sendSet, ic);
10127 case DUMMY_READ_VOLATILE:
10136 genEndCritical (ic);
10148 _G.current_iCode = NULL;
10150 /* now we are ready to call the
10151 peep hole optimizer */
10152 if (!options.nopeep)
10153 peepHole (&lineHead);
10155 /* now do the actual printing */
10156 printLine (lineHead, codeOutFile);