1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
83 static char *rb1regs[] = {
84 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
96 #define CLRC emitcode("clr","c")
97 #define SETC emitcode("setb","c")
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, const char *fmt,...)
121 char lb[INITIAL_INLINEASM];
129 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
140 //printf ("%s\n", lb);
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
148 lineCurr->ic = _G.current_iCode;
149 lineCurr->isComment = (*lbp==';');
153 /*-----------------------------------------------------------------*/
154 /* mcs51_emitDebuggerSymbol - associate the current code location */
155 /* with a debugger symbol */
156 /*-----------------------------------------------------------------*/
158 mcs51_emitDebuggerSymbol (char * debugSym)
161 emitcode ("", "%s ==.", debugSym);
165 /*-----------------------------------------------------------------*/
166 /* mova - moves specified value into accumulator */
167 /*-----------------------------------------------------------------*/
171 /* do some early peephole optimization */
172 if (!strcmp(x, "a") || !strcmp(x, "acc"))
175 emitcode("mov","a,%s", x);
178 /*-----------------------------------------------------------------*/
179 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
180 /*-----------------------------------------------------------------*/
182 getFreePtr (iCode * ic, asmop ** aopp, bool result)
184 bool r0iu = FALSE, r1iu = FALSE;
185 bool r0ou = FALSE, r1ou = FALSE;
187 /* the logic: if r0 & r1 used in the instruction
188 then we are in trouble otherwise */
190 /* first check if r0 & r1 are used by this
191 instruction, in which case we are in trouble */
192 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
193 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
198 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
199 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
201 /* if no usage of r0 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if no usage of r1 then return it */
213 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
214 (*aopp)->type = AOP_R1;
216 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
219 /* now we know they both have usage */
220 /* if r0 not used in this instruction */
223 /* push it if not already pushed */
226 emitcode ("mov", "b,%s",
227 mcs51_regWithIdx (R0_IDX)->dname);
230 else if (!_G.r0Pushed)
232 emitcode ("push", "%s",
233 mcs51_regWithIdx (R0_IDX)->dname);
237 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
238 (*aopp)->type = AOP_R0;
240 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
243 /* if r1 not used then */
247 /* push it if not already pushed */
250 emitcode ("mov", "b,%s",
251 mcs51_regWithIdx (R1_IDX)->dname);
254 else if (!_G.r1Pushed)
256 emitcode ("push", "%s",
257 mcs51_regWithIdx (R1_IDX)->dname);
261 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262 (*aopp)->type = AOP_R1;
263 return mcs51_regWithIdx (R1_IDX);
266 /* I said end of world, but not quite end of world yet */
268 /* we can push it on the stack */
269 (*aopp)->type = AOP_STK;
272 /* in the case that result AND left AND right needs a pointer reg
273 we can safely use the result's */
274 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
275 (*aopp)->type = AOP_R0;
276 return mcs51_regWithIdx (R0_IDX);
278 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
279 (*aopp)->type = AOP_R1;
280 return mcs51_regWithIdx (R1_IDX);
284 /* now this is REALLY the end of the world */
285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
286 "getFreePtr should never reach here");
291 /*-----------------------------------------------------------------*/
292 /* getTempRegs - initialize an array of pointers to GPR registers */
293 /* that are not in use. Returns 1 if the requested */
294 /* number of registers were available, 0 otherwise. */
295 /*-----------------------------------------------------------------*/
297 getTempRegs(regs **tempRegs, int size, iCode *ic)
304 ic = _G.current_iCode;
310 freeRegs = newBitVect(8);
311 bitVectSetBit (freeRegs, R2_IDX);
312 bitVectSetBit (freeRegs, R3_IDX);
313 bitVectSetBit (freeRegs, R4_IDX);
314 bitVectSetBit (freeRegs, R5_IDX);
315 bitVectSetBit (freeRegs, R6_IDX);
316 bitVectSetBit (freeRegs, R7_IDX);
318 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
320 bitVect * newfreeRegs;
321 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
322 freeBitVect(freeRegs);
323 freeRegs = newfreeRegs;
325 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
328 for (i=0; i<freeRegs->size; i++)
330 if (bitVectBitValue(freeRegs,i))
331 tempRegs[offset++] = mcs51_regWithIdx(i);
334 freeBitVect(freeRegs);
339 freeBitVect(freeRegs);
344 /*-----------------------------------------------------------------*/
345 /* newAsmop - creates a new asmOp */
346 /*-----------------------------------------------------------------*/
348 newAsmop (short type)
352 aop = Safe_calloc (1, sizeof (asmop));
357 /*-----------------------------------------------------------------*/
358 /* pointerCode - returns the code for a pointer type */
359 /*-----------------------------------------------------------------*/
361 pointerCode (sym_link * etype)
364 return PTR_TYPE (SPEC_OCLS (etype));
369 /*-----------------------------------------------------------------*/
370 /* leftRightUseAcc - returns size of accumulator use by operands */
371 /*-----------------------------------------------------------------*/
373 leftRightUseAcc(iCode *ic)
382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383 "null iCode pointer");
390 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
393 size = getSize (OP_SYMBOL (op)->type);
398 else if (ic->op == JUMPTABLE)
401 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
404 size = getSize (OP_SYMBOL (op)->type);
412 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
415 size = getSize (OP_SYMBOL (op)->type);
420 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
423 size = getSize (OP_SYMBOL (op)->type);
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
445 wassertl (ic != NULL, "Got a null iCode");
446 wassertl (sym != NULL, "Got a null symbol");
448 space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if (sym->onStack || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
470 if (_G.accInUse || leftRightUseAcc (ic))
471 emitcode ("push", "acc");
473 emitcode ("mov", "a,_bp");
474 emitcode ("add", "a,#0x%02x",
476 ((char) (sym->stack - _G.nRegsSaved)) :
477 ((char) sym->stack)) & 0xff);
478 emitcode ("mov", "%s,a",
479 aop->aopu.aop_ptr->name);
481 if (_G.accInUse || leftRightUseAcc (ic))
482 emitcode ("pop", "acc");
485 emitcode ("mov", "%s,#%s",
486 aop->aopu.aop_ptr->name,
488 aop->paged = space->paged;
491 aop->aopu.aop_stk = sym->stack;
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
507 //printTypeChainRaw(sym->type, NULL);
508 //printf("space = %s\n", space ? space->sname : "NULL");
509 sym->aop = aop = newAsmop (AOP_DIR);
510 aop->aopu.aop_dir = sym->rname;
511 aop->size = getSize (sym->type);
515 /* special case for a function */
516 if (IS_FUNC (sym->type))
518 sym->aop = aop = newAsmop (AOP_IMMD);
519 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
520 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
521 aop->size = FPTRSIZE;
525 /* only remaining is far space */
526 /* in which case DPTR gets the address */
527 sym->aop = aop = newAsmop (AOP_DPTR);
528 emitcode ("mov", "dptr,#%s", sym->rname);
529 aop->size = getSize (sym->type);
531 /* if it is in code space */
532 if (IN_CODESPACE (space))
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object */
540 /*-----------------------------------------------------------------*/
542 aopForRemat (symbol * sym)
544 iCode *ic = sym->rematiCode;
545 asmop *aop = newAsmop (AOP_IMMD);
552 val += (int) operandLitValue (IC_RIGHT (ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue (IC_RIGHT (ic));
555 else if (IS_CAST_ICODE(ic)) {
556 sym_link *from_type = operandType(IC_RIGHT(ic));
557 aop->aopu.aop_immd.from_cast_remat = 1;
558 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
559 ptr_type = DCL_TYPE(from_type);
560 if (ptr_type == IPOINTER) {
567 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
571 sprintf (buffer, "(%s %c 0x%04x)",
572 OP_SYMBOL (IC_LEFT (ic))->rname,
573 val >= 0 ? '+' : '-',
576 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
579 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
580 /* set immd2 field if required */
581 if (aop->aopu.aop_immd.from_cast_remat) {
582 sprintf(buffer,"#0x%02x",ptr_type);
583 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
584 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
590 /*-----------------------------------------------------------------*/
591 /* regsInCommon - two operands have some registers in common */
592 /*-----------------------------------------------------------------*/
594 regsInCommon (operand * op1, operand * op2)
599 /* if they have registers in common */
600 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
603 sym1 = OP_SYMBOL (op1);
604 sym2 = OP_SYMBOL (op2);
606 if (sym1->nRegs == 0 || sym2->nRegs == 0)
609 for (i = 0; i < sym1->nRegs; i++)
615 for (j = 0; j < sym2->nRegs; j++)
620 if (sym2->regs[j] == sym1->regs[i])
628 /*-----------------------------------------------------------------*/
629 /* operandsEqu - equivalent */
630 /*-----------------------------------------------------------------*/
632 operandsEqu (operand * op1, operand * op2)
636 /* if they not symbols */
637 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
640 sym1 = OP_SYMBOL (op1);
641 sym2 = OP_SYMBOL (op2);
643 /* if both are itemps & one is spilt
644 and the other is not then false */
645 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
646 sym1->isspilt != sym2->isspilt)
649 /* if they are the same */
653 if (sym1->rname[0] && sym2->rname[0]
654 && strcmp (sym1->rname, sym2->rname) == 0)
657 /* if left is a tmp & right is not */
658 if (IS_ITEMP (op1) &&
661 (sym1->usl.spillLoc == sym2))
664 if (IS_ITEMP (op2) &&
668 (sym2->usl.spillLoc == sym1))
674 /*-----------------------------------------------------------------*/
675 /* sameRegs - two asmops have the same registers */
676 /*-----------------------------------------------------------------*/
678 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type != AOP_REG ||
686 aop2->type != AOP_REG)
689 if (aop1->size != aop2->size)
692 for (i = 0; i < aop1->size; i++)
693 if (aop1->aopu.aop_reg[i] !=
694 aop2->aopu.aop_reg[i])
700 /*-----------------------------------------------------------------*/
701 /* aopOp - allocates an asmop for an operand : */
702 /*-----------------------------------------------------------------*/
704 aopOp (operand * op, iCode * ic, bool result)
713 /* if this a literal */
714 if (IS_OP_LITERAL (op))
716 op->aop = aop = newAsmop (AOP_LIT);
717 aop->aopu.aop_lit = op->operand.valOperand;
718 aop->size = getSize (operandType (op));
722 /* if already has a asmop then continue */
726 /* if the underlying symbol has a aop */
727 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
729 op->aop = OP_SYMBOL (op)->aop;
733 /* if this is a true symbol */
734 if (IS_TRUE_SYMOP (op))
736 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
740 /* this is a temporary : this has
746 e) can be a return use only */
748 sym = OP_SYMBOL (op);
750 /* if the type is a conditional */
751 if (sym->regType == REG_CND)
753 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
758 /* if it is spilt then two situations
760 b) has a spill location */
761 if (sym->isspilt || sym->nRegs == 0)
764 /* rematerialize it NOW */
767 sym->aop = op->aop = aop =
769 aop->size = getSize (sym->type);
776 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < 2; i++)
779 aop->aopu.aop_str[i] = accUse[i];
787 aop = op->aop = sym->aop = newAsmop (AOP_STR);
788 aop->size = getSize (sym->type);
789 for (i = 0; i < fReturnSizeMCS51; i++)
790 aop->aopu.aop_str[i] = fReturn[i];
794 if (sym->usl.spillLoc)
796 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
798 /* force a new aop if sizes differ */
799 sym->usl.spillLoc->aop = NULL;
801 sym->aop = op->aop = aop =
802 aopForSym (ic, sym->usl.spillLoc, result);
803 aop->size = getSize (sym->type);
807 /* else must be a dummy iTemp */
808 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
809 aop->size = getSize (sym->type);
813 /* must be in a register */
814 sym->aop = op->aop = aop = newAsmop (AOP_REG);
815 aop->size = sym->nRegs;
816 for (i = 0; i < sym->nRegs; i++)
817 aop->aopu.aop_reg[i] = sym->regs[i];
820 /*-----------------------------------------------------------------*/
821 /* freeAsmop - free up the asmop given to an operand */
822 /*----------------------------------------------------------------*/
824 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
841 /* depending on the asmop type only three cases need work AOP_RO
842 , AOP_R1 && AOP_STK */
848 emitcode ("mov", "r0,b");
851 else if (_G.r0Pushed)
855 emitcode ("pop", "ar0");
859 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 emitcode ("mov", "r1,b");
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size - 1;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
890 emitcode ("mov", "a,_bp");
891 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
892 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
901 emitcode ("pop", "acc");
902 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
908 freeAsmop (op, NULL, ic, TRUE);
911 emitcode ("pop", "ar1");
917 emitcode ("pop", "ar0");
924 /* all other cases just dealloc */
930 OP_SYMBOL (op)->aop = NULL;
931 /* if the symbol has a spill */
933 SPIL_LOC (op)->aop = NULL;
938 /*------------------------------------------------------------------*/
939 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
940 /* pop r0 or r1 off stack if pushed */
941 /*------------------------------------------------------------------*/
943 freeForBranchAsmop (operand * op)
963 emitcode ("mov", "r0,b");
965 else if (_G.r0Pushed)
967 emitcode ("pop", "ar0");
974 emitcode ("mov", "r1,b");
976 else if (_G.r1Pushed)
978 emitcode ("pop", "ar1");
985 int stk = aop->aopu.aop_stk + aop->size - 1;
987 emitcode ("mov", "b,r0");
990 emitcode ("mov", "a,_bp");
991 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
992 emitcode ("mov", "r0,a");
996 emitcode ("mov", "r0,_bp");
1001 emitcode ("pop", "acc");
1002 emitcode ("mov", "@r0,a");
1005 emitcode ("dec", "r0");
1007 emitcode ("mov", "r0,b");
1013 /*-----------------------------------------------------------------*/
1014 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1015 /* clobber the accumulator */
1016 /*-----------------------------------------------------------------*/
1018 aopGetUsesAcc (asmop *aop, int offset)
1020 if (offset > (aop->size - 1))
1038 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1047 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1053 /* Error case --- will have been caught already */
1059 /*-----------------------------------------------------------------*/
1060 /* aopGet - for fetching value of the aop */
1061 /*-----------------------------------------------------------------*/
1063 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1068 /* offset is greater than
1070 if (offset > (aop->size - 1) &&
1071 aop->type != AOP_LIT)
1074 /* depending on type */
1082 /* if we need to increment it */
1083 while (offset > aop->coff)
1085 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1089 while (offset < aop->coff)
1091 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1098 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1099 return (dname ? "acc" : "a");
1101 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1102 rs = Safe_calloc (1, strlen (s) + 1);
1107 if (aop->code && aop->coff==0 && offset>=1) {
1108 emitcode ("mov", "a,#0x%02x", offset);
1109 emitcode ("movc", "a,@a+dptr");
1110 return (dname ? "acc" : "a");
1113 while (offset > aop->coff)
1115 emitcode ("inc", "dptr");
1119 while (offset < aop->coff)
1121 emitcode ("lcall", "__decdptr");
1128 emitcode ("clr", "a");
1129 emitcode ("movc", "a,@a+dptr");
1133 emitcode ("movx", "a,@dptr");
1135 return (dname ? "acc" : "a");
1139 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1142 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1144 sprintf (s, "#(%s >> %d)",
1145 aop->aopu.aop_immd.aop_immd1,
1149 aop->aopu.aop_immd.aop_immd1);
1150 rs = Safe_calloc (1, strlen (s) + 1);
1156 sprintf (s, "(%s + %d)",
1160 sprintf (s, "%s", aop->aopu.aop_dir);
1161 rs = Safe_calloc (1, strlen (s) + 1);
1167 return aop->aopu.aop_reg[offset]->dname;
1169 return aop->aopu.aop_reg[offset]->name;
1172 emitcode ("clr", "a");
1173 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1174 emitcode ("rlc", "a");
1175 return (dname ? "acc" : "a");
1178 if (!offset && dname)
1180 return aop->aopu.aop_str[offset];
1183 return aopLiteral (aop->aopu.aop_lit, offset);
1187 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1191 return aop->aopu.aop_str[offset];
1195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1196 "aopget got unsupported aop->type");
1199 /*-----------------------------------------------------------------*/
1200 /* aopPut - puts a string for a aop */
1201 /*-----------------------------------------------------------------*/
1203 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1207 if (aop->size && offset > (aop->size - 1))
1209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1210 "aopPut got offset > aop->size");
1214 /* will assign value to value */
1215 /* depending on where it is ofcourse */
1219 MOVA (s); /* read s in case it was volatile */
1224 sprintf (d, "(%s + %d)",
1225 aop->aopu.aop_dir, offset);
1227 sprintf (d, "%s", aop->aopu.aop_dir);
1229 if (strcmp (d, s) ||
1231 emitcode ("mov", "%s,%s", d, s);
1236 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1237 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1240 strcmp (s, "r0") == 0 ||
1241 strcmp (s, "r1") == 0 ||
1242 strcmp (s, "r2") == 0 ||
1243 strcmp (s, "r3") == 0 ||
1244 strcmp (s, "r4") == 0 ||
1245 strcmp (s, "r5") == 0 ||
1246 strcmp (s, "r6") == 0 ||
1247 strcmp (s, "r7") == 0)
1248 emitcode ("mov", "%s,%s",
1249 aop->aopu.aop_reg[offset]->dname, s);
1251 emitcode ("mov", "%s,%s",
1252 aop->aopu.aop_reg[offset]->name, s);
1259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260 "aopPut writing to code space");
1264 while (offset > aop->coff)
1267 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1273 emitcode ("lcall", "__decdptr");
1278 /* if not in accumulater */
1281 emitcode ("movx", "@dptr,a");
1286 while (offset > aop->coff)
1289 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1291 while (offset < aop->coff)
1294 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1301 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1307 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1309 else if (strcmp (s, "r0") == 0 ||
1310 strcmp (s, "r1") == 0 ||
1311 strcmp (s, "r2") == 0 ||
1312 strcmp (s, "r3") == 0 ||
1313 strcmp (s, "r4") == 0 ||
1314 strcmp (s, "r5") == 0 ||
1315 strcmp (s, "r6") == 0 ||
1316 strcmp (s, "r7") == 0)
1319 sprintf (buffer, "a%s", s);
1320 emitcode ("mov", "@%s,%s",
1321 aop->aopu.aop_ptr->name, buffer);
1324 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1329 if (strcmp (s, "a") == 0)
1330 emitcode ("push", "acc");
1334 emitcode ("push", "acc");
1336 emitcode ("push", s);
1342 /* if bit variable */
1343 if (!aop->aopu.aop_dir)
1345 emitcode ("clr", "a");
1346 emitcode ("rlc", "a");
1351 emitcode ("clr", "%s", aop->aopu.aop_dir);
1353 emitcode ("setb", "%s", aop->aopu.aop_dir);
1354 else if (!strcmp (s, "c"))
1355 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1358 if (strcmp (s, "a"))
1363 /* set C, if a >= 1 */
1364 emitcode ("add", "a,#0xff");
1365 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1373 if (strcmp (aop->aopu.aop_str[offset], s) ||
1375 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1380 if (!offset && (strcmp (s, "acc") == 0) &&
1384 if (strcmp (aop->aopu.aop_str[offset], s) &&
1386 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1390 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1391 "aopPut got unsupported aop->type");
1399 /*-----------------------------------------------------------------*/
1400 /* pointToEnd :- points to the last byte of the operand */
1401 /*-----------------------------------------------------------------*/
1403 pointToEnd (asmop * aop)
1409 aop->coff = count = (aop->size - 1);
1415 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1419 emitcode ("inc", "dptr");
1426 /*-----------------------------------------------------------------*/
1427 /* reAdjustPreg - points a register back to where it should */
1428 /*-----------------------------------------------------------------*/
1430 reAdjustPreg (asmop * aop)
1432 if ((aop->coff==0) || aop->size <= 1)
1440 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1445 emitcode ("lcall", "__decdptr");
1452 #define AOP(op) op->aop
1453 #define AOP_TYPE(op) AOP(op)->type
1454 #define AOP_SIZE(op) AOP(op)->size
1455 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1456 AOP_TYPE(x) == AOP_R0))
1458 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1459 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1461 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1462 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1463 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1466 /*-----------------------------------------------------------------*/
1467 /* opIsGptr: returns non-zero if the passed operand is */
1468 /* a generic pointer type. */
1469 /*-----------------------------------------------------------------*/
1471 opIsGptr (operand * op)
1473 sym_link *type = operandType (op);
1475 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1482 /*-----------------------------------------------------------------*/
1483 /* getDataSize - get the operand data size */
1484 /*-----------------------------------------------------------------*/
1486 getDataSize (operand * op)
1489 size = AOP_SIZE (op);
1490 if (size == GPTRSIZE)
1492 sym_link *type = operandType (op);
1493 if (IS_GENPTR (type))
1495 /* generic pointer; arithmetic operations
1496 * should ignore the high byte (pointer type).
1504 /*-----------------------------------------------------------------*/
1505 /* outAcc - output Acc */
1506 /*-----------------------------------------------------------------*/
1508 outAcc (operand * result)
1511 size = getDataSize (result);
1514 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1517 /* unsigned or positive */
1520 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1525 /*-----------------------------------------------------------------*/
1526 /* outBitC - output a bit C */
1527 /*-----------------------------------------------------------------*/
1529 outBitC (operand * result)
1531 /* if the result is bit */
1532 if (AOP_TYPE (result) == AOP_CRY)
1533 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1536 emitcode ("clr", "a");
1537 emitcode ("rlc", "a");
1542 /*-----------------------------------------------------------------*/
1543 /* toBoolean - emit code for orl a,operator(sizeop) */
1544 /*-----------------------------------------------------------------*/
1546 toBoolean (operand * oper)
1548 int size = AOP_SIZE (oper) - 1;
1550 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1552 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1556 /*-----------------------------------------------------------------*/
1557 /* genNot - generate code for ! operation */
1558 /*-----------------------------------------------------------------*/
1564 D(emitcode ("; genNot",""));
1566 /* assign asmOps to operand & result */
1567 aopOp (IC_LEFT (ic), ic, FALSE);
1568 aopOp (IC_RESULT (ic), ic, TRUE);
1570 /* if in bit space then a special case */
1571 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1573 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1574 emitcode ("cpl", "c");
1575 outBitC (IC_RESULT (ic));
1579 toBoolean (IC_LEFT (ic));
1581 tlbl = newiTempLabel (NULL);
1582 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1583 emitcode ("", "%05d$:", tlbl->key + 100);
1584 outBitC (IC_RESULT (ic));
1587 /* release the aops */
1588 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1593 /*-----------------------------------------------------------------*/
1594 /* genCpl - generate code for complement */
1595 /*-----------------------------------------------------------------*/
1603 D(emitcode ("; genCpl",""));
1605 /* assign asmOps to operand & result */
1606 aopOp (IC_LEFT (ic), ic, FALSE);
1607 aopOp (IC_RESULT (ic), ic, TRUE);
1609 /* special case if in bit space */
1610 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1612 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1614 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 || options.nopeep)
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)
3094 && !sym->stack && !FUNC_ISCRITICAL (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);
4780 freeAsmop (right, NULL, ic, TRUE);
4781 freeAsmop (left, NULL, ic, TRUE);
4786 emitcode ("rlc", "a");
4794 rightInB = aopGetUsesAcc(AOP (right), offset);
4796 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4797 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4798 if (sign && size == 0)
4800 emitcode ("xrl", "a,#0x80");
4801 if (AOP_TYPE (right) == AOP_LIT)
4803 unsigned long lit = (unsigned long)
4804 floatFromVal (AOP (right)->aopu.aop_lit);
4805 emitcode ("subb", "a,#0x%02x",
4806 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4811 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4812 emitcode ("xrl", "b,#0x80");
4813 emitcode ("subb", "a,b");
4819 emitcode ("subb", "a,b");
4821 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4829 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4831 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4837 /* if the result is used in the next
4838 ifx conditional branch then generate
4839 code a little differently */
4841 genIfxJump (ifx, "c", NULL, NULL, result);
4844 /* leave the result in acc */
4848 /*-----------------------------------------------------------------*/
4849 /* genCmpGt :- greater than comparison */
4850 /*-----------------------------------------------------------------*/
4852 genCmpGt (iCode * ic, iCode * ifx)
4854 operand *left, *right, *result;
4855 sym_link *letype, *retype;
4858 D(emitcode ("; genCmpGt",""));
4860 left = IC_LEFT (ic);
4861 right = IC_RIGHT (ic);
4862 result = IC_RESULT (ic);
4864 letype = getSpec (operandType (left));
4865 retype = getSpec (operandType (right));
4866 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4867 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4868 /* assign the amsops */
4869 aopOp (left, ic, FALSE);
4870 aopOp (right, ic, FALSE);
4871 aopOp (result, ic, TRUE);
4873 genCmp (right, left, result, ifx, sign,ic);
4875 freeAsmop (result, NULL, ic, TRUE);
4878 /*-----------------------------------------------------------------*/
4879 /* genCmpLt - less than comparisons */
4880 /*-----------------------------------------------------------------*/
4882 genCmpLt (iCode * ic, iCode * ifx)
4884 operand *left, *right, *result;
4885 sym_link *letype, *retype;
4888 D(emitcode ("; genCmpLt",""));
4890 left = IC_LEFT (ic);
4891 right = IC_RIGHT (ic);
4892 result = IC_RESULT (ic);
4894 letype = getSpec (operandType (left));
4895 retype = getSpec (operandType (right));
4896 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4897 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4898 /* assign the amsops */
4899 aopOp (left, ic, FALSE);
4900 aopOp (right, ic, FALSE);
4901 aopOp (result, ic, TRUE);
4903 genCmp (left, right, result, ifx, sign,ic);
4905 freeAsmop (result, NULL, ic, TRUE);
4908 /*-----------------------------------------------------------------*/
4909 /* gencjneshort - compare and jump if not equal */
4910 /*-----------------------------------------------------------------*/
4912 gencjneshort (operand * left, operand * right, symbol * lbl)
4914 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4916 unsigned long lit = 0L;
4918 /* if the left side is a literal or
4919 if the right is in a pointer register and left
4921 if ((AOP_TYPE (left) == AOP_LIT) ||
4922 (AOP_TYPE (left) == AOP_IMMD) ||
4923 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4930 if (AOP_TYPE (right) == AOP_LIT)
4931 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4933 /* if the right side is a literal then anything goes */
4934 if (AOP_TYPE (right) == AOP_LIT &&
4935 AOP_TYPE (left) != AOP_DIR &&
4936 AOP_TYPE (left) != AOP_IMMD)
4940 emitcode ("cjne", "%s,%s,%05d$",
4941 aopGet (AOP (left), offset, FALSE, FALSE),
4942 aopGet (AOP (right), offset, FALSE, FALSE),
4948 /* if the right side is in a register or in direct space or
4949 if the left is a pointer register & right is not */
4950 else if (AOP_TYPE (right) == AOP_REG ||
4951 AOP_TYPE (right) == AOP_DIR ||
4952 AOP_TYPE (right) == AOP_LIT ||
4953 AOP_TYPE (right) == AOP_IMMD ||
4954 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4955 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4959 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4960 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4961 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4962 emitcode ("jnz", "%05d$", lbl->key + 100);
4964 emitcode ("cjne", "a,%s,%05d$",
4965 aopGet (AOP (right), offset, FALSE, TRUE),
4972 /* right is a pointer reg need both a & b */
4975 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4976 if (strcmp (l, "b"))
4977 emitcode ("mov", "b,%s", l);
4978 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4979 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4985 /*-----------------------------------------------------------------*/
4986 /* gencjne - compare and jump if not equal */
4987 /*-----------------------------------------------------------------*/
4989 gencjne (operand * left, operand * right, symbol * lbl)
4991 symbol *tlbl = newiTempLabel (NULL);
4993 gencjneshort (left, right, lbl);
4995 emitcode ("mov", "a,%s", one);
4996 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4997 emitcode ("", "%05d$:", lbl->key + 100);
4998 emitcode ("clr", "a");
4999 emitcode ("", "%05d$:", tlbl->key + 100);
5002 /*-----------------------------------------------------------------*/
5003 /* genCmpEq - generates code for equal to */
5004 /*-----------------------------------------------------------------*/
5006 genCmpEq (iCode * ic, iCode * ifx)
5008 operand *left, *right, *result;
5010 D(emitcode ("; genCmpEq",""));
5012 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5013 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5014 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5016 /* if literal, literal on the right or
5017 if the right is in a pointer register and left
5019 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5020 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5022 operand *t = IC_RIGHT (ic);
5023 IC_RIGHT (ic) = IC_LEFT (ic);
5027 if (ifx && !AOP_SIZE (result))
5030 /* if they are both bit variables */
5031 if (AOP_TYPE (left) == AOP_CRY &&
5032 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5034 if (AOP_TYPE (right) == AOP_LIT)
5036 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5039 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5040 emitcode ("cpl", "c");
5044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5048 emitcode ("clr", "c");
5050 /* AOP_TYPE(right) == AOP_CRY */
5054 symbol *lbl = newiTempLabel (NULL);
5055 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5056 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5057 emitcode ("cpl", "c");
5058 emitcode ("", "%05d$:", (lbl->key + 100));
5060 /* if true label then we jump if condition
5062 tlbl = newiTempLabel (NULL);
5065 emitcode ("jnc", "%05d$", tlbl->key + 100);
5066 freeForBranchAsmop (result);
5067 freeForBranchAsmop (right);
5068 freeForBranchAsmop (left);
5069 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5073 emitcode ("jc", "%05d$", tlbl->key + 100);
5074 freeForBranchAsmop (result);
5075 freeForBranchAsmop (right);
5076 freeForBranchAsmop (left);
5077 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5079 emitcode ("", "%05d$:", tlbl->key + 100);
5083 tlbl = newiTempLabel (NULL);
5084 gencjneshort (left, right, tlbl);
5087 freeForBranchAsmop (result);
5088 freeForBranchAsmop (right);
5089 freeForBranchAsmop (left);
5090 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5091 emitcode ("", "%05d$:", tlbl->key + 100);
5095 symbol *lbl = newiTempLabel (NULL);
5096 emitcode ("sjmp", "%05d$", lbl->key + 100);
5097 emitcode ("", "%05d$:", tlbl->key + 100);
5098 freeForBranchAsmop (result);
5099 freeForBranchAsmop (right);
5100 freeForBranchAsmop (left);
5101 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5102 emitcode ("", "%05d$:", lbl->key + 100);
5105 /* mark the icode as generated */
5110 /* if they are both bit variables */
5111 if (AOP_TYPE (left) == AOP_CRY &&
5112 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5114 if (AOP_TYPE (right) == AOP_LIT)
5116 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5119 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5120 emitcode ("cpl", "c");
5124 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5128 emitcode ("clr", "c");
5130 /* AOP_TYPE(right) == AOP_CRY */
5134 symbol *lbl = newiTempLabel (NULL);
5135 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5136 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5137 emitcode ("cpl", "c");
5138 emitcode ("", "%05d$:", (lbl->key + 100));
5141 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5148 genIfxJump (ifx, "c", left, right, result);
5151 /* if the result is used in an arithmetic operation
5152 then put the result in place */
5157 gencjne (left, right, newiTempLabel (NULL));
5158 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5160 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5165 genIfxJump (ifx, "a", left, right, result);
5168 /* if the result is used in an arithmetic operation
5169 then put the result in place */
5170 if (AOP_TYPE (result) != AOP_CRY)
5172 /* leave the result in acc */
5176 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5178 freeAsmop (result, NULL, ic, TRUE);
5181 /*-----------------------------------------------------------------*/
5182 /* ifxForOp - returns the icode containing the ifx for operand */
5183 /*-----------------------------------------------------------------*/
5185 ifxForOp (operand * op, iCode * ic)
5187 /* if true symbol then needs to be assigned */
5188 if (IS_TRUE_SYMOP (op))
5191 /* if this has register type condition and
5192 the next instruction is ifx with the same operand
5193 and live to of the operand is upto the ifx only then */
5195 ic->next->op == IFX &&
5196 IC_COND (ic->next)->key == op->key &&
5197 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5203 /*-----------------------------------------------------------------*/
5204 /* hasInc - operand is incremented before any other use */
5205 /*-----------------------------------------------------------------*/
5207 hasInc (operand *op, iCode *ic,int osize)
5209 sym_link *type = operandType(op);
5210 sym_link *retype = getSpec (type);
5211 iCode *lic = ic->next;
5214 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5215 if (!IS_SYMOP(op)) return NULL;
5217 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5218 if (IS_AGGREGATE(type->next)) return NULL;
5219 if (osize != (isize = getSize(type->next))) return NULL;
5222 /* if operand of the form op = op + <sizeof *op> */
5223 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5224 isOperandEqual(IC_RESULT(lic),op) &&
5225 isOperandLiteral(IC_RIGHT(lic)) &&
5226 operandLitValue(IC_RIGHT(lic)) == isize) {
5229 /* if the operand used or deffed */
5230 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5233 /* if GOTO or IFX */
5234 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5240 /*-----------------------------------------------------------------*/
5241 /* genAndOp - for && operation */
5242 /*-----------------------------------------------------------------*/
5244 genAndOp (iCode * ic)
5246 operand *left, *right, *result;
5249 D(emitcode ("; genAndOp",""));
5251 /* note here that && operations that are in an
5252 if statement are taken away by backPatchLabels
5253 only those used in arthmetic operations remain */
5254 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5255 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5256 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5258 /* if both are bit variables */
5259 if (AOP_TYPE (left) == AOP_CRY &&
5260 AOP_TYPE (right) == AOP_CRY)
5262 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5263 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5268 tlbl = newiTempLabel (NULL);
5270 emitcode ("jz", "%05d$", tlbl->key + 100);
5272 emitcode ("", "%05d$:", tlbl->key + 100);
5276 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5278 freeAsmop (result, NULL, ic, TRUE);
5282 /*-----------------------------------------------------------------*/
5283 /* genOrOp - for || operation */
5284 /*-----------------------------------------------------------------*/
5286 genOrOp (iCode * ic)
5288 operand *left, *right, *result;
5291 D(emitcode ("; genOrOp",""));
5293 /* note here that || operations that are in an
5294 if statement are taken away by backPatchLabels
5295 only those used in arthmetic operations remain */
5296 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5297 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5298 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5300 /* if both are bit variables */
5301 if (AOP_TYPE (left) == AOP_CRY &&
5302 AOP_TYPE (right) == AOP_CRY)
5304 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5305 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5310 tlbl = newiTempLabel (NULL);
5312 emitcode ("jnz", "%05d$", tlbl->key + 100);
5314 emitcode ("", "%05d$:", tlbl->key + 100);
5318 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5319 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5320 freeAsmop (result, NULL, ic, TRUE);
5323 /*-----------------------------------------------------------------*/
5324 /* isLiteralBit - test if lit == 2^n */
5325 /*-----------------------------------------------------------------*/
5327 isLiteralBit (unsigned long lit)
5329 unsigned long pw[32] =
5330 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5331 0x100L, 0x200L, 0x400L, 0x800L,
5332 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5333 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5334 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5335 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5336 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5339 for (idx = 0; idx < 32; idx++)
5345 /*-----------------------------------------------------------------*/
5346 /* continueIfTrue - */
5347 /*-----------------------------------------------------------------*/
5349 continueIfTrue (iCode * ic)
5352 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5356 /*-----------------------------------------------------------------*/
5358 /*-----------------------------------------------------------------*/
5360 jumpIfTrue (iCode * ic)
5363 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5367 /*-----------------------------------------------------------------*/
5368 /* jmpTrueOrFalse - */
5369 /*-----------------------------------------------------------------*/
5371 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5373 // ugly but optimized by peephole
5376 symbol *nlbl = newiTempLabel (NULL);
5377 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5378 emitcode ("", "%05d$:", tlbl->key + 100);
5379 freeForBranchAsmop (result);
5380 freeForBranchAsmop (right);
5381 freeForBranchAsmop (left);
5382 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5383 emitcode ("", "%05d$:", nlbl->key + 100);
5387 freeForBranchAsmop (result);
5388 freeForBranchAsmop (right);
5389 freeForBranchAsmop (left);
5390 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5391 emitcode ("", "%05d$:", tlbl->key + 100);
5396 /*-----------------------------------------------------------------*/
5397 /* genAnd - code for and */
5398 /*-----------------------------------------------------------------*/
5400 genAnd (iCode * ic, iCode * ifx)
5402 operand *left, *right, *result;
5403 int size, offset = 0;
5404 unsigned long lit = 0L;
5408 D(emitcode ("; genAnd",""));
5410 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5411 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5412 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5415 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5417 AOP_TYPE (left), AOP_TYPE (right));
5418 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5420 AOP_SIZE (left), AOP_SIZE (right));
5423 /* if left is a literal & right is not then exchange them */
5424 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5425 AOP_NEEDSACC (left))
5427 operand *tmp = right;
5432 /* if result = right then exchange them */
5433 if (sameRegs (AOP (result), AOP (right)))
5435 operand *tmp = right;
5440 /* if right is bit then exchange them */
5441 if (AOP_TYPE (right) == AOP_CRY &&
5442 AOP_TYPE (left) != AOP_CRY)
5444 operand *tmp = right;
5448 if (AOP_TYPE (right) == AOP_LIT)
5449 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5451 size = AOP_SIZE (result);
5454 // result = bit & yy;
5455 if (AOP_TYPE (left) == AOP_CRY)
5457 // c = bit & literal;
5458 if (AOP_TYPE (right) == AOP_LIT)
5462 if (size && sameRegs (AOP (result), AOP (left)))
5465 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5470 if (size && (AOP_TYPE (result) == AOP_CRY))
5472 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5475 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5480 emitcode ("clr", "c");
5485 if (AOP_TYPE (right) == AOP_CRY)
5488 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5489 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5494 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5496 emitcode ("rrc", "a");
5497 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5505 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5506 genIfxJump (ifx, "c", left, right, result);
5510 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5511 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5512 if ((AOP_TYPE (right) == AOP_LIT) &&
5513 (AOP_TYPE (result) == AOP_CRY) &&
5514 (AOP_TYPE (left) != AOP_CRY))
5516 int posbit = isLiteralBit (lit);
5521 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5524 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5530 sprintf (buffer, "acc.%d", posbit & 0x07);
5531 genIfxJump (ifx, buffer, left, right, result);
5538 symbol *tlbl = newiTempLabel (NULL);
5539 int sizel = AOP_SIZE (left);
5541 emitcode ("setb", "c");
5544 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5546 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5548 if ((posbit = isLiteralBit (bytelit)) != 0)
5549 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5552 if (bytelit != 0x0FFL)
5553 emitcode ("anl", "a,%s",
5554 aopGet (AOP (right), offset, FALSE, TRUE));
5555 emitcode ("jnz", "%05d$", tlbl->key + 100);
5560 // bit = left & literal
5563 emitcode ("clr", "c");
5564 emitcode ("", "%05d$:", tlbl->key + 100);
5566 // if(left & literal)
5570 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5572 emitcode ("", "%05d$:", tlbl->key + 100);
5580 /* if left is same as result */
5581 if (sameRegs (AOP (result), AOP (left)))
5583 for (; size--; offset++)
5585 if (AOP_TYPE (right) == AOP_LIT)
5587 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5589 else if (bytelit == 0)
5591 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5593 else if (IS_AOP_PREG (result))
5595 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5596 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5597 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5600 emitcode ("anl", "%s,%s",
5601 aopGet (AOP (left), offset, FALSE, TRUE),
5602 aopGet (AOP (right), offset, FALSE, FALSE));
5606 if (AOP_TYPE (left) == AOP_ACC)
5607 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5610 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5611 if (IS_AOP_PREG (result))
5613 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5614 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5618 emitcode ("anl", "%s,a",
5619 aopGet (AOP (left), offset, FALSE, TRUE));
5626 // left & result in different registers
5627 if (AOP_TYPE (result) == AOP_CRY)
5630 // if(size), result in bit
5631 // if(!size && ifx), conditional oper: if(left & right)
5632 symbol *tlbl = newiTempLabel (NULL);
5633 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5635 emitcode ("setb", "c");
5638 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5639 emitcode ("anl", "a,%s",
5640 aopGet (AOP (right), offset, FALSE, FALSE));
5642 if (AOP_TYPE(left)==AOP_ACC) {
5643 emitcode("mov", "b,a");
5644 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5645 emitcode("anl", "a,b");
5647 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5648 emitcode ("anl", "a,%s",
5649 aopGet (AOP (left), offset, FALSE, FALSE));
5652 emitcode ("jnz", "%05d$", tlbl->key + 100);
5658 emitcode ("", "%05d$:", tlbl->key + 100);
5662 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5664 emitcode ("", "%05d$:", tlbl->key + 100);
5668 for (; (size--); offset++)
5671 // result = left & right
5672 if (AOP_TYPE (right) == AOP_LIT)
5674 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5676 aopPut (AOP (result),
5677 aopGet (AOP (left), offset, FALSE, FALSE),
5679 isOperandVolatile (result, FALSE));
5682 else if (bytelit == 0)
5684 /* dummy read of volatile operand */
5685 if (isOperandVolatile (left, FALSE))
5686 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5687 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5691 // faster than result <- left, anl result,right
5692 // and better if result is SFR
5693 if (AOP_TYPE (left) == AOP_ACC)
5694 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5697 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5698 emitcode ("anl", "a,%s",
5699 aopGet (AOP (left), offset, FALSE, FALSE));
5701 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5707 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709 freeAsmop (result, NULL, ic, TRUE);
5712 /*-----------------------------------------------------------------*/
5713 /* genOr - code for or */
5714 /*-----------------------------------------------------------------*/
5716 genOr (iCode * ic, iCode * ifx)
5718 operand *left, *right, *result;
5719 int size, offset = 0;
5720 unsigned long lit = 0L;
5722 D(emitcode ("; genOr",""));
5724 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5725 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5726 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5729 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5731 AOP_TYPE (left), AOP_TYPE (right));
5732 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5734 AOP_SIZE (left), AOP_SIZE (right));
5737 /* if left is a literal & right is not then exchange them */
5738 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5739 AOP_NEEDSACC (left))
5741 operand *tmp = right;
5746 /* if result = right then exchange them */
5747 if (sameRegs (AOP (result), AOP (right)))
5749 operand *tmp = right;
5754 /* if right is bit then exchange them */
5755 if (AOP_TYPE (right) == AOP_CRY &&
5756 AOP_TYPE (left) != AOP_CRY)
5758 operand *tmp = right;
5762 if (AOP_TYPE (right) == AOP_LIT)
5763 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5765 size = AOP_SIZE (result);
5769 if (AOP_TYPE (left) == AOP_CRY)
5771 if (AOP_TYPE (right) == AOP_LIT)
5773 // c = bit | literal;
5776 // lit != 0 => result = 1
5777 if (AOP_TYPE (result) == AOP_CRY)
5780 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5782 continueIfTrue (ifx);
5785 emitcode ("setb", "c");
5789 // lit == 0 => result = left
5790 if (size && sameRegs (AOP (result), AOP (left)))
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5797 if (AOP_TYPE (right) == AOP_CRY)
5800 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5801 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5806 symbol *tlbl = newiTempLabel (NULL);
5807 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5808 emitcode ("setb", "c");
5809 emitcode ("jb", "%s,%05d$",
5810 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5812 emitcode ("jnz", "%05d$", tlbl->key + 100);
5813 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5815 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5821 emitcode ("", "%05d$:", tlbl->key + 100);
5830 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5831 genIfxJump (ifx, "c", left, right, result);
5835 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5836 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5837 if ((AOP_TYPE (right) == AOP_LIT) &&
5838 (AOP_TYPE (result) == AOP_CRY) &&
5839 (AOP_TYPE (left) != AOP_CRY))
5845 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5847 continueIfTrue (ifx);
5852 // lit = 0, result = boolean(left)
5854 emitcode ("setb", "c");
5858 symbol *tlbl = newiTempLabel (NULL);
5859 emitcode ("jnz", "%05d$", tlbl->key + 100);
5861 emitcode ("", "%05d$:", tlbl->key + 100);
5865 genIfxJump (ifx, "a", left, right, result);
5873 /* if left is same as result */
5874 if (sameRegs (AOP (result), AOP (left)))
5876 for (; size--; offset++)
5878 if (AOP_TYPE (right) == AOP_LIT)
5880 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5882 /* dummy read of volatile operand */
5883 if (isOperandVolatile (left, FALSE))
5884 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5888 else if (IS_AOP_PREG (left))
5890 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5891 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5892 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5895 emitcode ("orl", "%s,%s",
5896 aopGet (AOP (left), offset, FALSE, TRUE),
5897 aopGet (AOP (right), offset, FALSE, FALSE));
5901 if (AOP_TYPE (left) == AOP_ACC)
5902 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5905 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5906 if (IS_AOP_PREG (left))
5908 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5909 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5912 emitcode ("orl", "%s,a",
5913 aopGet (AOP (left), offset, FALSE, TRUE));
5920 // left & result in different registers
5921 if (AOP_TYPE (result) == AOP_CRY)
5924 // if(size), result in bit
5925 // if(!size && ifx), conditional oper: if(left | right)
5926 symbol *tlbl = newiTempLabel (NULL);
5927 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5929 emitcode ("setb", "c");
5932 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5933 emitcode ("orl", "a,%s",
5934 aopGet (AOP (right), offset, FALSE, FALSE));
5936 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5937 emitcode ("orl", "a,%s",
5938 aopGet (AOP (left), offset, FALSE, FALSE));
5940 emitcode ("jnz", "%05d$", tlbl->key + 100);
5946 emitcode ("", "%05d$:", tlbl->key + 100);
5950 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5952 emitcode ("", "%05d$:", tlbl->key + 100);
5955 for (; (size--); offset++)
5958 // result = left & right
5959 if (AOP_TYPE (right) == AOP_LIT)
5961 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5963 aopPut (AOP (result),
5964 aopGet (AOP (left), offset, FALSE, FALSE),
5966 isOperandVolatile (result, FALSE));
5970 // faster than result <- left, anl result,right
5971 // and better if result is SFR
5972 if (AOP_TYPE (left) == AOP_ACC)
5973 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5976 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5977 emitcode ("orl", "a,%s",
5978 aopGet (AOP (left), offset, FALSE, FALSE));
5980 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5987 freeAsmop (result, NULL, ic, TRUE);
5990 /*-----------------------------------------------------------------*/
5991 /* genXor - code for xclusive or */
5992 /*-----------------------------------------------------------------*/
5994 genXor (iCode * ic, iCode * ifx)
5996 operand *left, *right, *result;
5997 int size, offset = 0;
5998 unsigned long lit = 0L;
6000 D(emitcode ("; genXor",""));
6002 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6003 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6004 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6007 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6009 AOP_TYPE (left), AOP_TYPE (right));
6010 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6012 AOP_SIZE (left), AOP_SIZE (right));
6015 /* if left is a literal & right is not ||
6016 if left needs acc & right does not */
6017 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6018 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6020 operand *tmp = right;
6025 /* if result = right then exchange them */
6026 if (sameRegs (AOP (result), AOP (right)))
6028 operand *tmp = right;
6033 /* if right is bit then exchange them */
6034 if (AOP_TYPE (right) == AOP_CRY &&
6035 AOP_TYPE (left) != AOP_CRY)
6037 operand *tmp = right;
6041 if (AOP_TYPE (right) == AOP_LIT)
6042 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6044 size = AOP_SIZE (result);
6048 if (AOP_TYPE (left) == AOP_CRY)
6050 if (AOP_TYPE (right) == AOP_LIT)
6052 // c = bit & literal;
6055 // lit>>1 != 0 => result = 1
6056 if (AOP_TYPE (result) == AOP_CRY)
6059 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6061 continueIfTrue (ifx);
6064 emitcode ("setb", "c");
6071 // lit == 0, result = left
6072 if (size && sameRegs (AOP (result), AOP (left)))
6074 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6078 // lit == 1, result = not(left)
6079 if (size && sameRegs (AOP (result), AOP (left)))
6081 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6086 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6087 emitcode ("cpl", "c");
6096 symbol *tlbl = newiTempLabel (NULL);
6097 if (AOP_TYPE (right) == AOP_CRY)
6100 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6104 int sizer = AOP_SIZE (right);
6106 // if val>>1 != 0, result = 1
6107 emitcode ("setb", "c");
6110 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6112 // test the msb of the lsb
6113 emitcode ("anl", "a,#0xfe");
6114 emitcode ("jnz", "%05d$", tlbl->key + 100);
6118 emitcode ("rrc", "a");
6120 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6121 emitcode ("cpl", "c");
6122 emitcode ("", "%05d$:", (tlbl->key + 100));
6129 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6130 genIfxJump (ifx, "c", left, right, result);
6134 if (sameRegs (AOP (result), AOP (left)))
6136 /* if left is same as result */
6137 for (; size--; offset++)
6139 if (AOP_TYPE (right) == AOP_LIT)
6141 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6143 else if (IS_AOP_PREG (left))
6145 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6146 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6147 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6150 emitcode ("xrl", "%s,%s",
6151 aopGet (AOP (left), offset, FALSE, TRUE),
6152 aopGet (AOP (right), offset, FALSE, FALSE));
6156 if (AOP_TYPE (left) == AOP_ACC)
6157 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6160 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6161 if (IS_AOP_PREG (left))
6163 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6164 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6167 emitcode ("xrl", "%s,a",
6168 aopGet (AOP (left), offset, FALSE, TRUE));
6175 // left & result in different registers
6176 if (AOP_TYPE (result) == AOP_CRY)
6179 // if(size), result in bit
6180 // if(!size && ifx), conditional oper: if(left ^ right)
6181 symbol *tlbl = newiTempLabel (NULL);
6182 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6184 emitcode ("setb", "c");
6187 if ((AOP_TYPE (right) == AOP_LIT) &&
6188 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6190 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6194 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6195 emitcode ("xrl", "a,%s",
6196 aopGet (AOP (right), offset, FALSE, FALSE));
6198 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6199 emitcode ("xrl", "a,%s",
6200 aopGet (AOP (left), offset, FALSE, FALSE));
6203 emitcode ("jnz", "%05d$", tlbl->key + 100);
6209 emitcode ("", "%05d$:", tlbl->key + 100);
6213 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6216 for (; (size--); offset++)
6219 // result = left & right
6220 if (AOP_TYPE (right) == AOP_LIT)
6222 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6224 aopPut (AOP (result),
6225 aopGet (AOP (left), offset, FALSE, FALSE),
6227 isOperandVolatile (result, FALSE));
6231 // faster than result <- left, anl result,right
6232 // and better if result is SFR
6233 if (AOP_TYPE (left) == AOP_ACC)
6234 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6238 emitcode ("xrl", "a,%s",
6239 aopGet (AOP (left), offset, FALSE, TRUE));
6241 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6246 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6247 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6248 freeAsmop (result, NULL, ic, TRUE);
6251 /*-----------------------------------------------------------------*/
6252 /* genInline - write the inline code out */
6253 /*-----------------------------------------------------------------*/
6255 genInline (iCode * ic)
6257 char *buffer, *bp, *bp1;
6259 D(emitcode ("; genInline",""));
6261 _G.inLine += (!options.asmpeep);
6263 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6264 strcpy (buffer, IC_INLINE (ic));
6266 /* emit each line as a code */
6291 /* emitcode("",buffer); */
6292 _G.inLine -= (!options.asmpeep);
6295 /*-----------------------------------------------------------------*/
6296 /* genRRC - rotate right with carry */
6297 /*-----------------------------------------------------------------*/
6301 operand *left, *result;
6302 int size, offset = 0;
6305 D(emitcode ("; genRRC",""));
6307 /* rotate right with carry */
6308 left = IC_LEFT (ic);
6309 result = IC_RESULT (ic);
6310 aopOp (left, ic, FALSE);
6311 aopOp (result, ic, FALSE);
6313 /* move it to the result */
6314 size = AOP_SIZE (result);
6316 if (size == 1) { /* special case for 1 byte */
6317 l = aopGet (AOP (left), offset, FALSE, FALSE);
6319 emitcode ("rr", "a");
6325 l = aopGet (AOP (left), offset, FALSE, FALSE);
6327 emitcode ("rrc", "a");
6328 if (AOP_SIZE (result) > 1)
6329 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6331 /* now we need to put the carry into the
6332 highest order byte of the result */
6333 if (AOP_SIZE (result) > 1)
6335 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6338 emitcode ("mov", "acc.7,c");
6340 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6341 freeAsmop (left, NULL, ic, TRUE);
6342 freeAsmop (result, NULL, ic, TRUE);
6345 /*-----------------------------------------------------------------*/
6346 /* genRLC - generate code for rotate left with carry */
6347 /*-----------------------------------------------------------------*/
6351 operand *left, *result;
6352 int size, offset = 0;
6355 D(emitcode ("; genRLC",""));
6357 /* rotate right with carry */
6358 left = IC_LEFT (ic);
6359 result = IC_RESULT (ic);
6360 aopOp (left, ic, FALSE);
6361 aopOp (result, ic, FALSE);
6363 /* move it to the result */
6364 size = AOP_SIZE (result);
6368 l = aopGet (AOP (left), offset, FALSE, FALSE);
6370 if (size == 0) { /* special case for 1 byte */
6374 emitcode ("add", "a,acc");
6375 if (AOP_SIZE (result) > 1)
6376 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6379 l = aopGet (AOP (left), offset, FALSE, FALSE);
6381 emitcode ("rlc", "a");
6382 if (AOP_SIZE (result) > 1)
6383 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6386 /* now we need to put the carry into the
6387 highest order byte of the result */
6388 if (AOP_SIZE (result) > 1)
6390 l = aopGet (AOP (result), 0, FALSE, FALSE);
6393 emitcode ("mov", "acc.0,c");
6395 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6396 freeAsmop (left, NULL, ic, TRUE);
6397 freeAsmop (result, NULL, ic, TRUE);
6400 /*-----------------------------------------------------------------*/
6401 /* genGetHbit - generates code get highest order bit */
6402 /*-----------------------------------------------------------------*/
6404 genGetHbit (iCode * ic)
6406 operand *left, *result;
6408 D(emitcode ("; genGetHbit",""));
6410 left = IC_LEFT (ic);
6411 result = IC_RESULT (ic);
6412 aopOp (left, ic, FALSE);
6413 aopOp (result, ic, FALSE);
6415 /* get the highest order byte into a */
6416 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6417 if (AOP_TYPE (result) == AOP_CRY)
6419 emitcode ("rlc", "a");
6424 emitcode ("rl", "a");
6425 emitcode ("anl", "a,#0x01");
6430 freeAsmop (left, NULL, ic, TRUE);
6431 freeAsmop (result, NULL, ic, TRUE);
6434 /*-----------------------------------------------------------------*/
6435 /* genSwap - generates code to swap nibbles or bytes */
6436 /*-----------------------------------------------------------------*/
6438 genSwap (iCode * ic)
6440 operand *left, *result;
6442 D(emitcode ("; genSwap",""));
6444 left = IC_LEFT (ic);
6445 result = IC_RESULT (ic);
6446 aopOp (left, ic, FALSE);
6447 aopOp (result, ic, FALSE);
6449 switch (AOP_SIZE (left))
6451 case 1: /* swap nibbles in byte */
6452 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6453 emitcode ("swap", "a");
6454 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6456 case 2: /* swap bytes in word */
6457 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6459 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6460 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6461 0, isOperandVolatile (result, FALSE));
6462 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6464 else if (operandsEqu (left, result))
6467 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6468 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6470 emitcode ("mov", "b,a");
6473 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6474 0, isOperandVolatile (result, FALSE));
6475 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6479 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6480 0, isOperandVolatile (result, FALSE));
6481 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6482 1, isOperandVolatile (result, FALSE));
6486 wassertl(FALSE, "unsupported SWAP operand size");
6489 freeAsmop (left, NULL, ic, TRUE);
6490 freeAsmop (result, NULL, ic, TRUE);
6494 /*-----------------------------------------------------------------*/
6495 /* AccRol - rotate left accumulator by known count */
6496 /*-----------------------------------------------------------------*/
6498 AccRol (int shCount)
6500 shCount &= 0x0007; // shCount : 0..7
6507 emitcode ("rl", "a");
6510 emitcode ("rl", "a");
6511 emitcode ("rl", "a");
6514 emitcode ("swap", "a");
6515 emitcode ("rr", "a");
6518 emitcode ("swap", "a");
6521 emitcode ("swap", "a");
6522 emitcode ("rl", "a");
6525 emitcode ("rr", "a");
6526 emitcode ("rr", "a");
6529 emitcode ("rr", "a");
6534 /*-----------------------------------------------------------------*/
6535 /* AccLsh - left shift accumulator by known count */
6536 /*-----------------------------------------------------------------*/
6538 AccLsh (int shCount)
6543 emitcode ("add", "a,acc");
6544 else if (shCount == 2)
6546 emitcode ("add", "a,acc");
6547 emitcode ("add", "a,acc");
6551 /* rotate left accumulator */
6553 /* and kill the lower order bits */
6554 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6559 /*-----------------------------------------------------------------*/
6560 /* AccRsh - right shift accumulator by known count */
6561 /*-----------------------------------------------------------------*/
6563 AccRsh (int shCount)
6570 emitcode ("rrc", "a");
6574 /* rotate right accumulator */
6575 AccRol (8 - shCount);
6576 /* and kill the higher order bits */
6577 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6582 /*-----------------------------------------------------------------*/
6583 /* AccSRsh - signed right shift accumulator by known count */
6584 /*-----------------------------------------------------------------*/
6586 AccSRsh (int shCount)
6593 emitcode ("mov", "c,acc.7");
6594 emitcode ("rrc", "a");
6596 else if (shCount == 2)
6598 emitcode ("mov", "c,acc.7");
6599 emitcode ("rrc", "a");
6600 emitcode ("mov", "c,acc.7");
6601 emitcode ("rrc", "a");
6605 tlbl = newiTempLabel (NULL);
6606 /* rotate right accumulator */
6607 AccRol (8 - shCount);
6608 /* and kill the higher order bits */
6609 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6610 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6611 emitcode ("orl", "a,#0x%02x",
6612 (unsigned char) ~SRMask[shCount]);
6613 emitcode ("", "%05d$:", tlbl->key + 100);
6618 /*-----------------------------------------------------------------*/
6619 /* shiftR1Left2Result - shift right one byte from left to result */
6620 /*-----------------------------------------------------------------*/
6622 shiftR1Left2Result (operand * left, int offl,
6623 operand * result, int offr,
6624 int shCount, int sign)
6626 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6627 /* shift right accumulator */
6632 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6635 /*-----------------------------------------------------------------*/
6636 /* shiftL1Left2Result - shift left one byte from left to result */
6637 /*-----------------------------------------------------------------*/
6639 shiftL1Left2Result (operand * left, int offl,
6640 operand * result, int offr, int shCount)
6643 l = aopGet (AOP (left), offl, FALSE, FALSE);
6645 /* shift left accumulator */
6647 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6650 /*-----------------------------------------------------------------*/
6651 /* movLeft2Result - move byte from left to result */
6652 /*-----------------------------------------------------------------*/
6654 movLeft2Result (operand * left, int offl,
6655 operand * result, int offr, int sign)
6658 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6660 l = aopGet (AOP (left), offl, FALSE, FALSE);
6662 if (*l == '@' && (IS_AOP_PREG (result)))
6664 emitcode ("mov", "a,%s", l);
6665 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6670 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6673 /* MSB sign in acc.7 ! */
6674 if (getDataSize (left) == offl + 1)
6676 emitcode ("mov", "a,%s", l);
6677 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6684 /*-----------------------------------------------------------------*/
6685 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6686 /*-----------------------------------------------------------------*/
6690 emitcode ("rrc", "a");
6691 emitcode ("xch", "a,%s", x);
6692 emitcode ("rrc", "a");
6693 emitcode ("xch", "a,%s", x);
6696 /*-----------------------------------------------------------------*/
6697 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6698 /*-----------------------------------------------------------------*/
6702 emitcode ("xch", "a,%s", x);
6703 emitcode ("rlc", "a");
6704 emitcode ("xch", "a,%s", x);
6705 emitcode ("rlc", "a");
6708 /*-----------------------------------------------------------------*/
6709 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6710 /*-----------------------------------------------------------------*/
6714 emitcode ("xch", "a,%s", x);
6715 emitcode ("add", "a,acc");
6716 emitcode ("xch", "a,%s", x);
6717 emitcode ("rlc", "a");
6720 /*-----------------------------------------------------------------*/
6721 /* AccAXLsh - left shift a:x by known count (0..7) */
6722 /*-----------------------------------------------------------------*/
6724 AccAXLsh (char *x, int shCount)
6739 case 5: // AAAAABBB:CCCCCDDD
6741 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6743 emitcode ("anl", "a,#0x%02x",
6744 SLMask[shCount]); // BBB00000:CCCCCDDD
6746 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6748 AccRol (shCount); // DDDCCCCC:BBB00000
6750 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6752 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6754 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6756 emitcode ("anl", "a,#0x%02x",
6757 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6759 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6761 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6764 case 6: // AAAAAABB:CCCCCCDD
6765 emitcode ("anl", "a,#0x%02x",
6766 SRMask[shCount]); // 000000BB:CCCCCCDD
6767 emitcode ("mov", "c,acc.0"); // c = B
6768 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6770 AccAXRrl1 (x); // BCCCCCCD:D000000B
6771 AccAXRrl1 (x); // BBCCCCCC:DD000000
6773 emitcode("rrc","a");
6774 emitcode("xch","a,%s", x);
6775 emitcode("rrc","a");
6776 emitcode("mov","c,acc.0"); //<< get correct bit
6777 emitcode("xch","a,%s", x);
6779 emitcode("rrc","a");
6780 emitcode("xch","a,%s", x);
6781 emitcode("rrc","a");
6782 emitcode("xch","a,%s", x);
6785 case 7: // a:x <<= 7
6787 emitcode ("anl", "a,#0x%02x",
6788 SRMask[shCount]); // 0000000B:CCCCCCCD
6790 emitcode ("mov", "c,acc.0"); // c = B
6792 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6794 AccAXRrl1 (x); // BCCCCCCC:D0000000
6802 /*-----------------------------------------------------------------*/
6803 /* AccAXRsh - right shift a:x known count (0..7) */
6804 /*-----------------------------------------------------------------*/
6806 AccAXRsh (char *x, int shCount)
6814 AccAXRrl1 (x); // 0->a:x
6819 AccAXRrl1 (x); // 0->a:x
6822 AccAXRrl1 (x); // 0->a:x
6827 case 5: // AAAAABBB:CCCCCDDD = a:x
6829 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6831 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6833 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6835 emitcode ("anl", "a,#0x%02x",
6836 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6838 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6840 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6842 emitcode ("anl", "a,#0x%02x",
6843 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6845 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6847 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6849 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6852 case 6: // AABBBBBB:CCDDDDDD
6854 emitcode ("mov", "c,acc.7");
6855 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6857 emitcode ("mov", "c,acc.7");
6858 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6860 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6862 emitcode ("anl", "a,#0x%02x",
6863 SRMask[shCount]); // 000000AA:BBBBBBCC
6866 case 7: // ABBBBBBB:CDDDDDDD
6868 emitcode ("mov", "c,acc.7"); // c = A
6870 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6872 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6874 emitcode ("anl", "a,#0x%02x",
6875 SRMask[shCount]); // 0000000A:BBBBBBBC
6883 /*-----------------------------------------------------------------*/
6884 /* AccAXRshS - right shift signed a:x known count (0..7) */
6885 /*-----------------------------------------------------------------*/
6887 AccAXRshS (char *x, int shCount)
6895 emitcode ("mov", "c,acc.7");
6896 AccAXRrl1 (x); // s->a:x
6900 emitcode ("mov", "c,acc.7");
6901 AccAXRrl1 (x); // s->a:x
6903 emitcode ("mov", "c,acc.7");
6904 AccAXRrl1 (x); // s->a:x
6909 case 5: // AAAAABBB:CCCCCDDD = a:x
6911 tlbl = newiTempLabel (NULL);
6912 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6914 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6916 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6918 emitcode ("anl", "a,#0x%02x",
6919 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6921 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6923 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6925 emitcode ("anl", "a,#0x%02x",
6926 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6928 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6930 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6932 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6934 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6935 emitcode ("orl", "a,#0x%02x",
6936 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6938 emitcode ("", "%05d$:", tlbl->key + 100);
6939 break; // SSSSAAAA:BBBCCCCC
6941 case 6: // AABBBBBB:CCDDDDDD
6943 tlbl = newiTempLabel (NULL);
6944 emitcode ("mov", "c,acc.7");
6945 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6947 emitcode ("mov", "c,acc.7");
6948 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6950 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6952 emitcode ("anl", "a,#0x%02x",
6953 SRMask[shCount]); // 000000AA:BBBBBBCC
6955 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6956 emitcode ("orl", "a,#0x%02x",
6957 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6959 emitcode ("", "%05d$:", tlbl->key + 100);
6961 case 7: // ABBBBBBB:CDDDDDDD
6963 tlbl = newiTempLabel (NULL);
6964 emitcode ("mov", "c,acc.7"); // c = A
6966 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6968 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6970 emitcode ("anl", "a,#0x%02x",
6971 SRMask[shCount]); // 0000000A:BBBBBBBC
6973 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6974 emitcode ("orl", "a,#0x%02x",
6975 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6977 emitcode ("", "%05d$:", tlbl->key + 100);
6984 /*-----------------------------------------------------------------*/
6985 /* shiftL2Left2Result - shift left two bytes from left to result */
6986 /*-----------------------------------------------------------------*/
6988 shiftL2Left2Result (operand * left, int offl,
6989 operand * result, int offr, int shCount)
6991 if (sameRegs (AOP (result), AOP (left)) &&
6992 ((offl + MSB16) == offr))
6994 /* don't crash result[offr] */
6995 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6996 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7000 movLeft2Result (left, offl, result, offr, 0);
7001 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7003 /* ax << shCount (x = lsb(result)) */
7004 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7005 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7009 /*-----------------------------------------------------------------*/
7010 /* shiftR2Left2Result - shift right two bytes from left to result */
7011 /*-----------------------------------------------------------------*/
7013 shiftR2Left2Result (operand * left, int offl,
7014 operand * result, int offr,
7015 int shCount, int sign)
7017 if (sameRegs (AOP (result), AOP (left)) &&
7018 ((offl + MSB16) == offr))
7020 /* don't crash result[offr] */
7021 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7022 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7026 movLeft2Result (left, offl, result, offr, 0);
7027 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7029 /* a:x >> shCount (x = lsb(result)) */
7031 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7033 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7034 if (getDataSize (result) > 1)
7035 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7038 /*-----------------------------------------------------------------*/
7039 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7040 /*-----------------------------------------------------------------*/
7042 shiftLLeftOrResult (operand * left, int offl,
7043 operand * result, int offr, int shCount)
7045 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7046 /* shift left accumulator */
7048 /* or with result */
7049 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7050 /* back to result */
7051 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7054 /*-----------------------------------------------------------------*/
7055 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7056 /*-----------------------------------------------------------------*/
7058 shiftRLeftOrResult (operand * left, int offl,
7059 operand * result, int offr, int shCount)
7061 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7062 /* shift right accumulator */
7064 /* or with result */
7065 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7066 /* back to result */
7067 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7070 /*-----------------------------------------------------------------*/
7071 /* genlshOne - left shift a one byte quantity by known count */
7072 /*-----------------------------------------------------------------*/
7074 genlshOne (operand * result, operand * left, int shCount)
7076 D(emitcode ("; genlshOne",""));
7078 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7081 /*-----------------------------------------------------------------*/
7082 /* genlshTwo - left shift two bytes by known amount != 0 */
7083 /*-----------------------------------------------------------------*/
7085 genlshTwo (operand * result, operand * left, int shCount)
7089 D(emitcode ("; genlshTwo",""));
7091 size = getDataSize (result);
7093 /* if shCount >= 8 */
7101 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7103 movLeft2Result (left, LSB, result, MSB16, 0);
7105 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7108 /* 1 <= shCount <= 7 */
7112 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7114 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7118 /*-----------------------------------------------------------------*/
7119 /* shiftLLong - shift left one long from left to result */
7120 /* offl = LSB or MSB16 */
7121 /*-----------------------------------------------------------------*/
7123 shiftLLong (operand * left, operand * result, int offr)
7126 int size = AOP_SIZE (result);
7128 if (size >= LSB + offr)
7130 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7132 emitcode ("add", "a,acc");
7133 if (sameRegs (AOP (left), AOP (result)) &&
7134 size >= MSB16 + offr && offr != LSB)
7135 emitcode ("xch", "a,%s",
7136 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7138 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7141 if (size >= MSB16 + offr)
7143 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7145 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7148 emitcode ("rlc", "a");
7149 if (sameRegs (AOP (left), AOP (result)) &&
7150 size >= MSB24 + offr && offr != LSB)
7151 emitcode ("xch", "a,%s",
7152 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7154 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7157 if (size >= MSB24 + offr)
7159 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7161 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7164 emitcode ("rlc", "a");
7165 if (sameRegs (AOP (left), AOP (result)) &&
7166 size >= MSB32 + offr && offr != LSB)
7167 emitcode ("xch", "a,%s",
7168 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7170 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7173 if (size > MSB32 + offr)
7175 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7177 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7180 emitcode ("rlc", "a");
7181 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7184 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7187 /*-----------------------------------------------------------------*/
7188 /* genlshFour - shift four byte by a known amount != 0 */
7189 /*-----------------------------------------------------------------*/
7191 genlshFour (operand * result, operand * left, int shCount)
7195 D(emitcode ("; genlshFour",""));
7197 size = AOP_SIZE (result);
7199 /* if shifting more that 3 bytes */
7204 /* lowest order of left goes to the highest
7205 order of the destination */
7206 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7208 movLeft2Result (left, LSB, result, MSB32, 0);
7209 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7210 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7211 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7215 /* more than two bytes */
7216 else if (shCount >= 16)
7218 /* lower order two bytes goes to higher order two bytes */
7220 /* if some more remaining */
7222 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7225 movLeft2Result (left, MSB16, result, MSB32, 0);
7226 movLeft2Result (left, LSB, result, MSB24, 0);
7228 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7229 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7233 /* if more than 1 byte */
7234 else if (shCount >= 8)
7236 /* lower order three bytes goes to higher order three bytes */
7241 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7243 movLeft2Result (left, LSB, result, MSB16, 0);
7249 movLeft2Result (left, MSB24, result, MSB32, 0);
7250 movLeft2Result (left, MSB16, result, MSB24, 0);
7251 movLeft2Result (left, LSB, result, MSB16, 0);
7252 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7254 else if (shCount == 1)
7255 shiftLLong (left, result, MSB16);
7258 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7259 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7260 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7261 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7266 /* 1 <= shCount <= 7 */
7267 else if (shCount <= 2)
7269 shiftLLong (left, result, LSB);
7271 shiftLLong (result, result, LSB);
7273 /* 3 <= shCount <= 7, optimize */
7276 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7277 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7278 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7282 /*-----------------------------------------------------------------*/
7283 /* genLeftShiftLiteral - left shifting by known count */
7284 /*-----------------------------------------------------------------*/
7286 genLeftShiftLiteral (operand * left,
7291 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7294 D(emitcode ("; genLeftShiftLiteral",""));
7296 freeAsmop (right, NULL, ic, TRUE);
7298 aopOp (left, ic, FALSE);
7299 aopOp (result, ic, FALSE);
7301 size = getSize (operandType (result));
7304 emitcode ("; shift left ", "result %d, left %d", size,
7308 /* I suppose that the left size >= result size */
7313 movLeft2Result (left, size, result, size, 0);
7317 else if (shCount >= (size * 8))
7319 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7325 genlshOne (result, left, shCount);
7329 genlshTwo (result, left, shCount);
7333 genlshFour (result, left, shCount);
7336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7337 "*** ack! mystery literal shift!\n");
7341 freeAsmop (left, NULL, ic, TRUE);
7342 freeAsmop (result, NULL, ic, TRUE);
7345 /*-----------------------------------------------------------------*/
7346 /* genLeftShift - generates code for left shifting */
7347 /*-----------------------------------------------------------------*/
7349 genLeftShift (iCode * ic)
7351 operand *left, *right, *result;
7354 symbol *tlbl, *tlbl1;
7356 D(emitcode ("; genLeftShift",""));
7358 right = IC_RIGHT (ic);
7359 left = IC_LEFT (ic);
7360 result = IC_RESULT (ic);
7362 aopOp (right, ic, FALSE);
7364 /* if the shift count is known then do it
7365 as efficiently as possible */
7366 if (AOP_TYPE (right) == AOP_LIT)
7368 genLeftShiftLiteral (left, right, result, ic);
7372 /* shift count is unknown then we have to form
7373 a loop get the loop count in B : Note: we take
7374 only the lower order byte since shifting
7375 more that 32 bits make no sense anyway, ( the
7376 largest size of an object can be only 32 bits ) */
7378 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7379 emitcode ("inc", "b");
7380 freeAsmop (right, NULL, ic, TRUE);
7381 aopOp (left, ic, FALSE);
7382 aopOp (result, ic, FALSE);
7384 /* now move the left to the result if they are not the
7386 if (!sameRegs (AOP (left), AOP (result)) &&
7387 AOP_SIZE (result) > 1)
7390 size = AOP_SIZE (result);
7394 l = aopGet (AOP (left), offset, FALSE, TRUE);
7395 if (*l == '@' && (IS_AOP_PREG (result)))
7398 emitcode ("mov", "a,%s", l);
7399 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7402 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7407 tlbl = newiTempLabel (NULL);
7408 size = AOP_SIZE (result);
7410 tlbl1 = newiTempLabel (NULL);
7412 /* if it is only one byte then */
7415 symbol *tlbl1 = newiTempLabel (NULL);
7417 l = aopGet (AOP (left), 0, FALSE, FALSE);
7419 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7420 emitcode ("", "%05d$:", tlbl->key + 100);
7421 emitcode ("add", "a,acc");
7422 emitcode ("", "%05d$:", tlbl1->key + 100);
7423 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7424 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7428 reAdjustPreg (AOP (result));
7430 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7431 emitcode ("", "%05d$:", tlbl->key + 100);
7432 l = aopGet (AOP (result), offset, FALSE, FALSE);
7434 emitcode ("add", "a,acc");
7435 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7438 l = aopGet (AOP (result), offset, FALSE, FALSE);
7440 emitcode ("rlc", "a");
7441 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7443 reAdjustPreg (AOP (result));
7445 emitcode ("", "%05d$:", tlbl1->key + 100);
7446 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7448 freeAsmop (left, NULL, ic, TRUE);
7449 freeAsmop (result, NULL, ic, TRUE);
7452 /*-----------------------------------------------------------------*/
7453 /* genrshOne - right shift a one byte quantity by known count */
7454 /*-----------------------------------------------------------------*/
7456 genrshOne (operand * result, operand * left,
7457 int shCount, int sign)
7459 D(emitcode ("; genrshOne",""));
7461 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7464 /*-----------------------------------------------------------------*/
7465 /* genrshTwo - right shift two bytes by known amount != 0 */
7466 /*-----------------------------------------------------------------*/
7468 genrshTwo (operand * result, operand * left,
7469 int shCount, int sign)
7471 D(emitcode ("; genrshTwo",""));
7473 /* if shCount >= 8 */
7478 shiftR1Left2Result (left, MSB16, result, LSB,
7481 movLeft2Result (left, MSB16, result, LSB, sign);
7482 addSign (result, MSB16, sign);
7485 /* 1 <= shCount <= 7 */
7487 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7490 /*-----------------------------------------------------------------*/
7491 /* shiftRLong - shift right one long from left to result */
7492 /* offl = LSB or MSB16 */
7493 /*-----------------------------------------------------------------*/
7495 shiftRLong (operand * left, int offl,
7496 operand * result, int sign)
7498 int isSameRegs=sameRegs(AOP(left),AOP(result));
7500 if (isSameRegs && offl>1) {
7501 // we are in big trouble, but this shouldn't happen
7502 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7505 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7510 emitcode ("rlc", "a");
7511 emitcode ("subb", "a,acc");
7513 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7515 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7516 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7519 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7524 emitcode ("clr", "c");
7526 emitcode ("mov", "c,acc.7");
7529 emitcode ("rrc", "a");
7531 if (isSameRegs && offl==MSB16) {
7532 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7534 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7535 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7538 emitcode ("rrc", "a");
7539 if (isSameRegs && offl==1) {
7540 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7542 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7543 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7545 emitcode ("rrc", "a");
7546 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7550 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7551 emitcode ("rrc", "a");
7552 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7556 /*-----------------------------------------------------------------*/
7557 /* genrshFour - shift four byte by a known amount != 0 */
7558 /*-----------------------------------------------------------------*/
7560 genrshFour (operand * result, operand * left,
7561 int shCount, int sign)
7563 D(emitcode ("; genrshFour",""));
7565 /* if shifting more that 3 bytes */
7570 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7572 movLeft2Result (left, MSB32, result, LSB, sign);
7573 addSign (result, MSB16, sign);
7575 else if (shCount >= 16)
7579 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7582 movLeft2Result (left, MSB24, result, LSB, 0);
7583 movLeft2Result (left, MSB32, result, MSB16, sign);
7585 addSign (result, MSB24, sign);
7587 else if (shCount >= 8)
7591 shiftRLong (left, MSB16, result, sign);
7592 else if (shCount == 0)
7594 movLeft2Result (left, MSB16, result, LSB, 0);
7595 movLeft2Result (left, MSB24, result, MSB16, 0);
7596 movLeft2Result (left, MSB32, result, MSB24, sign);
7597 addSign (result, MSB32, sign);
7601 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7602 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7603 /* the last shift is signed */
7604 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7605 addSign (result, MSB32, sign);
7609 { /* 1 <= shCount <= 7 */
7612 shiftRLong (left, LSB, result, sign);
7614 shiftRLong (result, LSB, result, sign);
7618 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7619 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7620 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7625 /*-----------------------------------------------------------------*/
7626 /* genRightShiftLiteral - right shifting by known count */
7627 /*-----------------------------------------------------------------*/
7629 genRightShiftLiteral (operand * left,
7635 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7638 D(emitcode ("; genRightShiftLiteral",""));
7640 freeAsmop (right, NULL, ic, TRUE);
7642 aopOp (left, ic, FALSE);
7643 aopOp (result, ic, FALSE);
7646 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7650 size = getDataSize (left);
7651 /* test the LEFT size !!! */
7653 /* I suppose that the left size >= result size */
7656 size = getDataSize (result);
7658 movLeft2Result (left, size, result, size, 0);
7661 else if (shCount >= (size * 8))
7664 /* get sign in acc.7 */
7665 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7667 addSign (result, LSB, sign);
7674 genrshOne (result, left, shCount, sign);
7678 genrshTwo (result, left, shCount, sign);
7682 genrshFour (result, left, shCount, sign);
7688 freeAsmop (left, NULL, ic, TRUE);
7689 freeAsmop (result, NULL, ic, TRUE);
7692 /*-----------------------------------------------------------------*/
7693 /* genSignedRightShift - right shift of signed number */
7694 /*-----------------------------------------------------------------*/
7696 genSignedRightShift (iCode * ic)
7698 operand *right, *left, *result;
7701 symbol *tlbl, *tlbl1;
7703 D(emitcode ("; genSignedRightShift",""));
7705 /* we do it the hard way put the shift count in b
7706 and loop thru preserving the sign */
7708 right = IC_RIGHT (ic);
7709 left = IC_LEFT (ic);
7710 result = IC_RESULT (ic);
7712 aopOp (right, ic, FALSE);
7715 if (AOP_TYPE (right) == AOP_LIT)
7717 genRightShiftLiteral (left, right, result, ic, 1);
7720 /* shift count is unknown then we have to form
7721 a loop get the loop count in B : Note: we take
7722 only the lower order byte since shifting
7723 more that 32 bits make no sense anyway, ( the
7724 largest size of an object can be only 32 bits ) */
7726 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7727 emitcode ("inc", "b");
7728 freeAsmop (right, NULL, ic, TRUE);
7729 aopOp (left, ic, FALSE);
7730 aopOp (result, ic, FALSE);
7732 /* now move the left to the result if they are not the
7734 if (!sameRegs (AOP (left), AOP (result)) &&
7735 AOP_SIZE (result) > 1)
7738 size = AOP_SIZE (result);
7742 l = aopGet (AOP (left), offset, FALSE, TRUE);
7743 if (*l == '@' && IS_AOP_PREG (result))
7746 emitcode ("mov", "a,%s", l);
7747 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7750 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7755 /* mov the highest order bit to OVR */
7756 tlbl = newiTempLabel (NULL);
7757 tlbl1 = newiTempLabel (NULL);
7759 size = AOP_SIZE (result);
7761 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7762 emitcode ("rlc", "a");
7763 emitcode ("mov", "ov,c");
7764 /* if it is only one byte then */
7767 l = aopGet (AOP (left), 0, FALSE, FALSE);
7769 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7770 emitcode ("", "%05d$:", tlbl->key + 100);
7771 emitcode ("mov", "c,ov");
7772 emitcode ("rrc", "a");
7773 emitcode ("", "%05d$:", tlbl1->key + 100);
7774 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7775 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7779 reAdjustPreg (AOP (result));
7780 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7781 emitcode ("", "%05d$:", tlbl->key + 100);
7782 emitcode ("mov", "c,ov");
7785 l = aopGet (AOP (result), offset, FALSE, FALSE);
7787 emitcode ("rrc", "a");
7788 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7790 reAdjustPreg (AOP (result));
7791 emitcode ("", "%05d$:", tlbl1->key + 100);
7792 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7795 freeAsmop (left, NULL, ic, TRUE);
7796 freeAsmop (result, NULL, ic, TRUE);
7799 /*-----------------------------------------------------------------*/
7800 /* genRightShift - generate code for right shifting */
7801 /*-----------------------------------------------------------------*/
7803 genRightShift (iCode * ic)
7805 operand *right, *left, *result;
7809 symbol *tlbl, *tlbl1;
7811 D(emitcode ("; genRightShift",""));
7813 /* if signed then we do it the hard way preserve the
7814 sign bit moving it inwards */
7815 letype = getSpec (operandType (IC_LEFT (ic)));
7817 if (!SPEC_USIGN (letype))
7819 genSignedRightShift (ic);
7823 /* signed & unsigned types are treated the same : i.e. the
7824 signed is NOT propagated inwards : quoting from the
7825 ANSI - standard : "for E1 >> E2, is equivalent to division
7826 by 2**E2 if unsigned or if it has a non-negative value,
7827 otherwise the result is implementation defined ", MY definition
7828 is that the sign does not get propagated */
7830 right = IC_RIGHT (ic);
7831 left = IC_LEFT (ic);
7832 result = IC_RESULT (ic);
7834 aopOp (right, ic, FALSE);
7836 /* if the shift count is known then do it
7837 as efficiently as possible */
7838 if (AOP_TYPE (right) == AOP_LIT)
7840 genRightShiftLiteral (left, right, result, ic, 0);
7844 /* shift count is unknown then we have to form
7845 a loop get the loop count in B : Note: we take
7846 only the lower order byte since shifting
7847 more that 32 bits make no sense anyway, ( the
7848 largest size of an object can be only 32 bits ) */
7850 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7851 emitcode ("inc", "b");
7852 freeAsmop (right, NULL, ic, TRUE);
7853 aopOp (left, ic, FALSE);
7854 aopOp (result, ic, FALSE);
7856 /* now move the left to the result if they are not the
7858 if (!sameRegs (AOP (left), AOP (result)) &&
7859 AOP_SIZE (result) > 1)
7862 size = AOP_SIZE (result);
7866 l = aopGet (AOP (left), offset, FALSE, TRUE);
7867 if (*l == '@' && IS_AOP_PREG (result))
7870 emitcode ("mov", "a,%s", l);
7871 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7874 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7879 tlbl = newiTempLabel (NULL);
7880 tlbl1 = newiTempLabel (NULL);
7881 size = AOP_SIZE (result);
7884 /* if it is only one byte then */
7887 l = aopGet (AOP (left), 0, FALSE, FALSE);
7889 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7890 emitcode ("", "%05d$:", tlbl->key + 100);
7892 emitcode ("rrc", "a");
7893 emitcode ("", "%05d$:", tlbl1->key + 100);
7894 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7895 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7899 reAdjustPreg (AOP (result));
7900 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7901 emitcode ("", "%05d$:", tlbl->key + 100);
7905 l = aopGet (AOP (result), offset, FALSE, FALSE);
7907 emitcode ("rrc", "a");
7908 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7910 reAdjustPreg (AOP (result));
7912 emitcode ("", "%05d$:", tlbl1->key + 100);
7913 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7916 freeAsmop (left, NULL, ic, TRUE);
7917 freeAsmop (result, NULL, ic, TRUE);
7920 /*-----------------------------------------------------------------*/
7921 /* emitPtrByteGet - emits code to get a byte into A through a */
7922 /* pointer register (R0, R1, or DPTR). The */
7923 /* original value of A can be preserved in B. */
7924 /*-----------------------------------------------------------------*/
7926 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7933 emitcode ("mov", "b,a");
7934 emitcode ("mov", "a,@%s", rname);
7939 emitcode ("mov", "b,a");
7940 emitcode ("movx", "a,@%s", rname);
7945 emitcode ("mov", "b,a");
7946 emitcode ("movx", "a,@dptr");
7951 emitcode ("mov", "b,a");
7952 emitcode ("clr", "a");
7953 emitcode ("movc", "a,@a+dptr");
7959 emitcode ("push", "b");
7960 emitcode ("push", "acc");
7962 emitcode ("lcall", "__gptrget");
7964 emitcode ("pop", "b");
7969 /*-----------------------------------------------------------------*/
7970 /* emitPtrByteSet - emits code to set a byte from src through a */
7971 /* pointer register (R0, R1, or DPTR). */
7972 /*-----------------------------------------------------------------*/
7974 emitPtrByteSet (char *rname, int p_type, char *src)
7983 emitcode ("mov", "@%s,a", rname);
7986 emitcode ("mov", "@%s,%s", rname, src);
7991 emitcode ("movx", "@%s,a", rname);
7996 emitcode ("movx", "@dptr,a");
8001 emitcode ("lcall", "__gptrput");
8006 /*-----------------------------------------------------------------*/
8007 /* genUnpackBits - generates code for unpacking bits */
8008 /*-----------------------------------------------------------------*/
8010 genUnpackBits (operand * result, char *rname, int ptype)
8012 int offset = 0; /* result byte offset */
8013 int rsize; /* result size */
8014 int rlen = 0; /* remaining bitfield length */
8015 sym_link *etype; /* bitfield type information */
8016 int blen; /* bitfield length */
8017 int bstr; /* bitfield starting bit within byte */
8019 D(emitcode ("; genUnpackBits",""));
8021 etype = getSpec (operandType (result));
8022 rsize = getSize (operandType (result));
8023 blen = SPEC_BLEN (etype);
8024 bstr = SPEC_BSTR (etype);
8026 /* If the bitfield length is less than a byte */
8029 emitPtrByteGet (rname, ptype, FALSE);
8031 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8032 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8036 /* Bit field did not fit in a byte. Copy all
8037 but the partial byte at the end. */
8038 for (rlen=blen;rlen>=8;rlen-=8)
8040 emitPtrByteGet (rname, ptype, FALSE);
8041 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8043 emitcode ("inc", "%s", rname);
8046 /* Handle the partial byte at the end */
8049 emitPtrByteGet (rname, ptype, FALSE);
8050 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8051 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8059 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8064 /*-----------------------------------------------------------------*/
8065 /* genDataPointerGet - generates code when ptr offset is known */
8066 /*-----------------------------------------------------------------*/
8068 genDataPointerGet (operand * left,
8074 int size, offset = 0;
8076 D(emitcode ("; genDataPointerGet",""));
8078 aopOp (result, ic, TRUE);
8080 /* get the string representation of the name */
8081 l = aopGet (AOP (left), 0, FALSE, TRUE);
8082 size = AOP_SIZE (result);
8086 sprintf (buffer, "(%s + %d)", l + 1, offset);
8088 sprintf (buffer, "%s", l + 1);
8089 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8092 freeAsmop (left, NULL, ic, TRUE);
8093 freeAsmop (result, NULL, ic, TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* genNearPointerGet - emitcode for near pointer fetch */
8098 /*-----------------------------------------------------------------*/
8100 genNearPointerGet (operand * left,
8108 sym_link *rtype, *retype;
8109 sym_link *ltype = operandType (left);
8112 D(emitcode ("; genNearPointerGet",""));
8114 rtype = operandType (result);
8115 retype = getSpec (rtype);
8117 aopOp (left, ic, FALSE);
8119 /* if left is rematerialisable and
8120 result is not bitfield variable type and
8121 the left is pointer to data space i.e
8122 lower 128 bytes of space */
8123 if (AOP_TYPE (left) == AOP_IMMD &&
8124 !IS_BITFIELD (retype) &&
8125 DCL_TYPE (ltype) == POINTER)
8127 genDataPointerGet (left, result, ic);
8131 /* if the value is already in a pointer register
8132 then don't need anything more */
8133 if (!AOP_INPREG (AOP (left)))
8135 if (IS_AOP_PREG (left))
8137 // Aha, it is a pointer, just in disguise.
8138 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8141 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8142 __FILE__, __LINE__);
8147 emitcode ("mov", "a%s,%s", rname + 1, rname);
8148 rname++; // skip the '@'.
8153 /* otherwise get a free pointer register */
8155 preg = getFreePtr (ic, &aop, FALSE);
8156 emitcode ("mov", "%s,%s",
8158 aopGet (AOP (left), 0, FALSE, TRUE));
8163 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8165 //aopOp (result, ic, FALSE);
8166 aopOp (result, ic, result?TRUE:FALSE);
8168 /* if bitfield then unpack the bits */
8169 if (IS_BITFIELD (retype))
8170 genUnpackBits (result, rname, POINTER);
8173 /* we have can just get the values */
8174 int size = AOP_SIZE (result);
8179 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8182 emitcode ("mov", "a,@%s", rname);
8183 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8187 sprintf (buffer, "@%s", rname);
8188 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8192 emitcode ("inc", "%s", rname);
8196 /* now some housekeeping stuff */
8197 if (aop) /* we had to allocate for this iCode */
8199 if (pi) { /* post increment present */
8200 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8202 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8206 /* we did not allocate which means left
8207 already in a pointer register, then
8208 if size > 0 && this could be used again
8209 we have to point it back to where it
8211 if ((AOP_SIZE (result) > 1 &&
8212 !OP_SYMBOL (left)->remat &&
8213 (OP_SYMBOL (left)->liveTo > ic->seq ||
8217 int size = AOP_SIZE (result) - 1;
8219 emitcode ("dec", "%s", rname);
8224 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8225 freeAsmop (left, NULL, ic, TRUE);
8226 if (pi) pi->generated = 1;
8229 /*-----------------------------------------------------------------*/
8230 /* genPagedPointerGet - emitcode for paged pointer fetch */
8231 /*-----------------------------------------------------------------*/
8233 genPagedPointerGet (operand * left,
8241 sym_link *rtype, *retype;
8243 D(emitcode ("; genPagedPointerGet",""));
8245 rtype = operandType (result);
8246 retype = getSpec (rtype);
8248 aopOp (left, ic, FALSE);
8250 /* if the value is already in a pointer register
8251 then don't need anything more */
8252 if (!AOP_INPREG (AOP (left)))
8254 /* otherwise get a free pointer register */
8256 preg = getFreePtr (ic, &aop, FALSE);
8257 emitcode ("mov", "%s,%s",
8259 aopGet (AOP (left), 0, FALSE, TRUE));
8263 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8265 aopOp (result, ic, FALSE);
8267 /* if bitfield then unpack the bits */
8268 if (IS_BITFIELD (retype))
8269 genUnpackBits (result, rname, PPOINTER);
8272 /* we have can just get the values */
8273 int size = AOP_SIZE (result);
8279 emitcode ("movx", "a,@%s", rname);
8280 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8285 emitcode ("inc", "%s", rname);
8289 /* now some housekeeping stuff */
8290 if (aop) /* we had to allocate for this iCode */
8292 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8293 freeAsmop (NULL, aop, ic, TRUE);
8297 /* we did not allocate which means left
8298 already in a pointer register, then
8299 if size > 0 && this could be used again
8300 we have to point it back to where it
8302 if ((AOP_SIZE (result) > 1 &&
8303 !OP_SYMBOL (left)->remat &&
8304 (OP_SYMBOL (left)->liveTo > ic->seq ||
8308 int size = AOP_SIZE (result) - 1;
8310 emitcode ("dec", "%s", rname);
8315 freeAsmop (left, NULL, ic, TRUE);
8316 freeAsmop (result, NULL, ic, TRUE);
8317 if (pi) pi->generated = 1;
8321 /*--------------------------------------------------------------------*/
8322 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8323 /*--------------------------------------------------------------------*/
8325 loadDptrFromOperand (operand *op, bool loadBToo)
8327 if (AOP_TYPE (op) != AOP_STR)
8329 /* if this is remateriazable */
8330 if (AOP_TYPE (op) == AOP_IMMD)
8332 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8335 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8336 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8339 wassertl(FALSE, "need pointerCode");
8340 emitcode ("", "; mov b,???");
8341 /* genPointerGet and genPointerSet originally did different
8342 ** things for this case. Both seem wrong.
8343 ** from genPointerGet:
8344 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8345 ** from genPointerSet:
8346 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8351 else if (AOP_TYPE (op) == AOP_DPTR)
8355 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8356 emitcode ("push", "acc");
8357 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8358 emitcode ("push", "acc");
8359 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8360 emitcode ("pop", "dph");
8361 emitcode ("pop", "dpl");
8365 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8366 emitcode ("push", "acc");
8367 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8368 emitcode ("pop", "dpl");
8372 { /* we need to get it byte by byte */
8373 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8374 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8376 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8381 /*-----------------------------------------------------------------*/
8382 /* genFarPointerGet - gget value from far space */
8383 /*-----------------------------------------------------------------*/
8385 genFarPointerGet (operand * left,
8386 operand * result, iCode * ic, iCode * pi)
8389 sym_link *retype = getSpec (operandType (result));
8391 D(emitcode ("; genFarPointerGet",""));
8393 aopOp (left, ic, FALSE);
8394 loadDptrFromOperand (left, FALSE);
8396 /* so dptr now contains the address */
8397 aopOp (result, ic, FALSE);
8399 /* if bit then unpack */
8400 if (IS_BITFIELD (retype))
8401 genUnpackBits (result, "dptr", FPOINTER);
8404 size = AOP_SIZE (result);
8409 emitcode ("movx", "a,@dptr");
8410 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8412 emitcode ("inc", "dptr");
8416 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8417 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8418 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8421 freeAsmop (left, NULL, ic, TRUE);
8422 freeAsmop (result, NULL, ic, TRUE);
8425 /*-----------------------------------------------------------------*/
8426 /* genCodePointerGet - gget value from code space */
8427 /*-----------------------------------------------------------------*/
8429 genCodePointerGet (operand * left,
8430 operand * result, iCode * ic, iCode *pi)
8433 sym_link *retype = getSpec (operandType (result));
8435 D(emitcode ("; genCodePointerGet",""));
8437 aopOp (left, ic, FALSE);
8438 loadDptrFromOperand (left, FALSE);
8440 /* so dptr now contains the address */
8441 aopOp (result, ic, FALSE);
8443 /* if bit then unpack */
8444 if (IS_BITFIELD (retype))
8445 genUnpackBits (result, "dptr", CPOINTER);
8448 size = AOP_SIZE (result);
8455 emitcode ("clr", "a");
8456 emitcode ("movc", "a,@a+dptr");
8457 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8458 emitcode ("inc", "dptr");
8462 emitcode ("mov", "a,#0x%02x", offset);
8463 emitcode ("movc", "a,@a+dptr");
8464 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8469 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8470 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8471 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8474 freeAsmop (left, NULL, ic, TRUE);
8475 freeAsmop (result, NULL, ic, TRUE);
8478 /*-----------------------------------------------------------------*/
8479 /* genGenPointerGet - gget value from generic pointer space */
8480 /*-----------------------------------------------------------------*/
8482 genGenPointerGet (operand * left,
8483 operand * result, iCode * ic, iCode *pi)
8486 sym_link *retype = getSpec (operandType (result));
8488 D(emitcode ("; genGenPointerGet",""));
8490 aopOp (left, ic, FALSE);
8491 loadDptrFromOperand (left, TRUE);
8493 /* so dptr know contains the address */
8494 aopOp (result, ic, FALSE);
8496 /* if bit then unpack */
8497 if (IS_BITFIELD (retype))
8498 genUnpackBits (result, "dptr", GPOINTER);
8501 size = AOP_SIZE (result);
8506 emitcode ("lcall", "__gptrget");
8507 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8509 emitcode ("inc", "dptr");
8513 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8514 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8515 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8518 freeAsmop (left, NULL, ic, TRUE);
8519 freeAsmop (result, NULL, ic, TRUE);
8522 /*-----------------------------------------------------------------*/
8523 /* genPointerGet - generate code for pointer get */
8524 /*-----------------------------------------------------------------*/
8526 genPointerGet (iCode * ic, iCode *pi)
8528 operand *left, *result;
8529 sym_link *type, *etype;
8532 D(emitcode ("; genPointerGet",""));
8534 left = IC_LEFT (ic);
8535 result = IC_RESULT (ic);
8537 /* depending on the type of pointer we need to
8538 move it to the correct pointer register */
8539 type = operandType (left);
8540 etype = getSpec (type);
8541 /* if left is of type of pointer then it is simple */
8542 if (IS_PTR (type) && !IS_FUNC (type->next))
8543 p_type = DCL_TYPE (type);
8546 /* we have to go by the storage class */
8547 p_type = PTR_TYPE (SPEC_OCLS (etype));
8550 /* special case when cast remat */
8551 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8552 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8553 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8554 type = operandType (left);
8555 p_type = DCL_TYPE (type);
8557 /* now that we have the pointer type we assign
8558 the pointer values */
8564 genNearPointerGet (left, result, ic, pi);
8568 genPagedPointerGet (left, result, ic, pi);
8572 genFarPointerGet (left, result, ic, pi);
8576 genCodePointerGet (left, result, ic, pi);
8580 genGenPointerGet (left, result, ic, pi);
8588 /*-----------------------------------------------------------------*/
8589 /* genPackBits - generates code for packed bit storage */
8590 /*-----------------------------------------------------------------*/
8592 genPackBits (sym_link * etype,
8594 char *rname, int p_type)
8596 int offset = 0; /* source byte offset */
8597 int rlen = 0; /* remaining bitfield length */
8598 int blen; /* bitfield length */
8599 int bstr; /* bitfield starting bit within byte */
8600 int litval; /* source literal value (if AOP_LIT) */
8601 unsigned char mask; /* bitmask within current byte */
8603 D(emitcode ("; genPackBits",""));
8605 blen = SPEC_BLEN (etype);
8606 bstr = SPEC_BSTR (etype);
8608 /* If the bitfield length is less than a byte */
8611 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8612 (unsigned char) (0xFF >> (8 - bstr)));
8614 if (AOP_TYPE (right) == AOP_LIT)
8616 /* Case with a bitfield length <8 and literal source
8618 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8620 litval &= (~mask) & 0xff;
8621 emitPtrByteGet (rname, p_type, FALSE);
8622 if ((mask|litval)!=0xff)
8623 emitcode ("anl","a,#0x%02x", mask);
8625 emitcode ("orl","a,#0x%02x", litval);
8629 if ((blen==1) && (p_type!=GPOINTER))
8631 /* Case with a bitfield length == 1 and no generic pointer
8633 if (AOP_TYPE (right) == AOP_CRY)
8634 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8637 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8638 emitcode ("rrc","a");
8640 emitPtrByteGet (rname, p_type, FALSE);
8641 emitcode ("mov","acc.%d,c",bstr);
8645 /* Case with a bitfield length < 8 and arbitrary source
8647 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8648 /* shift and mask source value */
8650 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8652 /* transfer A to B and get next byte */
8653 emitPtrByteGet (rname, p_type, TRUE);
8655 emitcode ("anl", "a,#0x%02x", mask);
8656 emitcode ("orl", "a,b");
8657 if (p_type == GPOINTER)
8658 emitcode ("pop", "b");
8662 emitPtrByteSet (rname, p_type, "a");
8666 /* Bit length is greater than 7 bits. In this case, copy */
8667 /* all except the partial byte at the end */
8668 for (rlen=blen;rlen>=8;rlen-=8)
8670 emitPtrByteSet (rname, p_type,
8671 aopGet (AOP (right), offset++, FALSE, TRUE) );
8673 emitcode ("inc", "%s", rname);
8676 /* If there was a partial byte at the end */
8679 mask = (((unsigned char) -1 << rlen) & 0xff);
8681 if (AOP_TYPE (right) == AOP_LIT)
8683 /* Case with partial byte and literal source
8685 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8686 litval >>= (blen-rlen);
8687 litval &= (~mask) & 0xff;
8688 emitPtrByteGet (rname, p_type, FALSE);
8689 if ((mask|litval)!=0xff)
8690 emitcode ("anl","a,#0x%02x", mask);
8692 emitcode ("orl","a,#0x%02x", litval);
8696 /* Case with partial byte and arbitrary source
8698 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8699 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8701 /* transfer A to B and get next byte */
8702 emitPtrByteGet (rname, p_type, TRUE);
8704 emitcode ("anl", "a,#0x%02x", mask);
8705 emitcode ("orl", "a,b");
8706 if (p_type == GPOINTER)
8707 emitcode ("pop", "b");
8709 emitPtrByteSet (rname, p_type, "a");
8715 /*-----------------------------------------------------------------*/
8716 /* genDataPointerSet - remat pointer to data space */
8717 /*-----------------------------------------------------------------*/
8719 genDataPointerSet (operand * right,
8723 int size, offset = 0;
8724 char *l, buffer[256];
8726 D(emitcode ("; genDataPointerSet",""));
8728 aopOp (right, ic, FALSE);
8730 l = aopGet (AOP (result), 0, FALSE, TRUE);
8731 size = AOP_SIZE (right);
8735 sprintf (buffer, "(%s + %d)", l + 1, offset);
8737 sprintf (buffer, "%s", l + 1);
8738 emitcode ("mov", "%s,%s", buffer,
8739 aopGet (AOP (right), offset++, FALSE, FALSE));
8742 freeAsmop (right, NULL, ic, TRUE);
8743 freeAsmop (result, NULL, ic, TRUE);
8746 /*-----------------------------------------------------------------*/
8747 /* genNearPointerSet - emitcode for near pointer put */
8748 /*-----------------------------------------------------------------*/
8750 genNearPointerSet (operand * right,
8758 sym_link *retype, *letype;
8759 sym_link *ptype = operandType (result);
8761 D(emitcode ("; genNearPointerSet",""));
8763 retype = getSpec (operandType (right));
8764 letype = getSpec (ptype);
8765 aopOp (result, ic, FALSE);
8767 /* if the result is rematerializable &
8768 in data space & not a bit variable */
8769 if (AOP_TYPE (result) == AOP_IMMD &&
8770 DCL_TYPE (ptype) == POINTER &&
8771 !IS_BITVAR (retype) &&
8772 !IS_BITVAR (letype))
8774 genDataPointerSet (right, result, ic);
8778 /* if the value is already in a pointer register
8779 then don't need anything more */
8780 if (!AOP_INPREG (AOP (result)))
8783 //AOP_TYPE (result) == AOP_STK
8787 // Aha, it is a pointer, just in disguise.
8788 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8791 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8792 __FILE__, __LINE__);
8797 emitcode ("mov", "a%s,%s", rname + 1, rname);
8798 rname++; // skip the '@'.
8803 /* otherwise get a free pointer register */
8805 preg = getFreePtr (ic, &aop, FALSE);
8806 emitcode ("mov", "%s,%s",
8808 aopGet (AOP (result), 0, FALSE, TRUE));
8814 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8817 aopOp (right, ic, FALSE);
8819 /* if bitfield then unpack the bits */
8820 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8821 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8824 /* we have can just get the values */
8825 int size = AOP_SIZE (right);
8830 l = aopGet (AOP (right), offset, FALSE, TRUE);
8834 emitcode ("mov", "@%s,a", rname);
8837 emitcode ("mov", "@%s,%s", rname, l);
8839 emitcode ("inc", "%s", rname);
8844 /* now some housekeeping stuff */
8845 if (aop) /* we had to allocate for this iCode */
8848 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8849 freeAsmop (NULL, aop, ic, TRUE);
8853 /* we did not allocate which means left
8854 already in a pointer register, then
8855 if size > 0 && this could be used again
8856 we have to point it back to where it
8858 if ((AOP_SIZE (right) > 1 &&
8859 !OP_SYMBOL (result)->remat &&
8860 (OP_SYMBOL (result)->liveTo > ic->seq ||
8864 int size = AOP_SIZE (right) - 1;
8866 emitcode ("dec", "%s", rname);
8871 if (pi) pi->generated = 1;
8872 freeAsmop (result, NULL, ic, TRUE);
8873 freeAsmop (right, NULL, ic, TRUE);
8876 /*-----------------------------------------------------------------*/
8877 /* genPagedPointerSet - emitcode for Paged pointer put */
8878 /*-----------------------------------------------------------------*/
8880 genPagedPointerSet (operand * right,
8888 sym_link *retype, *letype;
8890 D(emitcode ("; genPagedPointerSet",""));
8892 retype = getSpec (operandType (right));
8893 letype = getSpec (operandType (result));
8895 aopOp (result, ic, FALSE);
8897 /* if the value is already in a pointer register
8898 then don't need anything more */
8899 if (!AOP_INPREG (AOP (result)))
8901 /* otherwise get a free pointer register */
8903 preg = getFreePtr (ic, &aop, FALSE);
8904 emitcode ("mov", "%s,%s",
8906 aopGet (AOP (result), 0, FALSE, TRUE));
8910 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8912 aopOp (right, ic, FALSE);
8914 /* if bitfield then unpack the bits */
8915 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8916 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8919 /* we have can just get the values */
8920 int size = AOP_SIZE (right);
8925 l = aopGet (AOP (right), offset, FALSE, TRUE);
8928 emitcode ("movx", "@%s,a", rname);
8931 emitcode ("inc", "%s", rname);
8937 /* now some housekeeping stuff */
8938 if (aop) /* we had to allocate for this iCode */
8941 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8942 freeAsmop (NULL, aop, ic, TRUE);
8946 /* we did not allocate which means left
8947 already in a pointer register, then
8948 if size > 0 && this could be used again
8949 we have to point it back to where it
8951 if (AOP_SIZE (right) > 1 &&
8952 !OP_SYMBOL (result)->remat &&
8953 (OP_SYMBOL (result)->liveTo > ic->seq ||
8956 int size = AOP_SIZE (right) - 1;
8958 emitcode ("dec", "%s", rname);
8963 if (pi) pi->generated = 1;
8964 freeAsmop (result, NULL, ic, TRUE);
8965 freeAsmop (right, NULL, ic, TRUE);
8970 /*-----------------------------------------------------------------*/
8971 /* genFarPointerSet - set value from far space */
8972 /*-----------------------------------------------------------------*/
8974 genFarPointerSet (operand * right,
8975 operand * result, iCode * ic, iCode * pi)
8978 sym_link *retype = getSpec (operandType (right));
8979 sym_link *letype = getSpec (operandType (result));
8981 D(emitcode ("; genFarPointerSet",""));
8983 aopOp (result, ic, FALSE);
8984 loadDptrFromOperand (result, FALSE);
8986 /* so dptr know contains the address */
8987 aopOp (right, ic, FALSE);
8989 /* if bit then unpack */
8990 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8991 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8994 size = AOP_SIZE (right);
8999 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9001 emitcode ("movx", "@dptr,a");
9003 emitcode ("inc", "dptr");
9006 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9007 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9008 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9011 freeAsmop (result, NULL, ic, TRUE);
9012 freeAsmop (right, NULL, ic, TRUE);
9015 /*-----------------------------------------------------------------*/
9016 /* genGenPointerSet - set value from generic pointer space */
9017 /*-----------------------------------------------------------------*/
9019 genGenPointerSet (operand * right,
9020 operand * result, iCode * ic, iCode * pi)
9023 sym_link *retype = getSpec (operandType (right));
9024 sym_link *letype = getSpec (operandType (result));
9026 D(emitcode ("; genGenPointerSet",""));
9028 aopOp (result, ic, FALSE);
9029 loadDptrFromOperand (result, TRUE);
9031 /* so dptr know contains the address */
9032 aopOp (right, ic, FALSE);
9034 /* if bit then unpack */
9035 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9036 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9039 size = AOP_SIZE (right);
9044 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9046 emitcode ("lcall", "__gptrput");
9048 emitcode ("inc", "dptr");
9052 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9053 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9054 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9057 freeAsmop (result, NULL, ic, TRUE);
9058 freeAsmop (right, NULL, ic, TRUE);
9061 /*-----------------------------------------------------------------*/
9062 /* genPointerSet - stores the value into a pointer location */
9063 /*-----------------------------------------------------------------*/
9065 genPointerSet (iCode * ic, iCode *pi)
9067 operand *right, *result;
9068 sym_link *type, *etype;
9071 D(emitcode ("; genPointerSet",""));
9073 right = IC_RIGHT (ic);
9074 result = IC_RESULT (ic);
9076 /* depending on the type of pointer we need to
9077 move it to the correct pointer register */
9078 type = operandType (result);
9079 etype = getSpec (type);
9080 /* if left is of type of pointer then it is simple */
9081 if (IS_PTR (type) && !IS_FUNC (type->next))
9083 p_type = DCL_TYPE (type);
9087 /* we have to go by the storage class */
9088 p_type = PTR_TYPE (SPEC_OCLS (etype));
9091 /* special case when cast remat */
9092 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9093 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9094 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9095 type = operandType (result);
9096 p_type = DCL_TYPE (type);
9098 /* now that we have the pointer type we assign
9099 the pointer values */
9105 genNearPointerSet (right, result, ic, pi);
9109 genPagedPointerSet (right, result, ic, pi);
9113 genFarPointerSet (right, result, ic, pi);
9117 genGenPointerSet (right, result, ic, pi);
9121 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9122 "genPointerSet: illegal pointer type");
9127 /*-----------------------------------------------------------------*/
9128 /* genIfx - generate code for Ifx statement */
9129 /*-----------------------------------------------------------------*/
9131 genIfx (iCode * ic, iCode * popIc)
9133 operand *cond = IC_COND (ic);
9136 D(emitcode ("; genIfx",""));
9138 aopOp (cond, ic, FALSE);
9140 /* get the value into acc */
9141 if (AOP_TYPE (cond) != AOP_CRY)
9145 /* the result is now in the accumulator */
9146 freeAsmop (cond, NULL, ic, TRUE);
9148 /* if there was something to be popped then do it */
9152 /* if the condition is a bit variable */
9153 if (isbit && IS_ITEMP (cond) &&
9155 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9156 else if (isbit && !IS_ITEMP (cond))
9157 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9159 genIfxJump (ic, "a", NULL, NULL, NULL);
9164 /*-----------------------------------------------------------------*/
9165 /* genAddrOf - generates code for address of */
9166 /*-----------------------------------------------------------------*/
9168 genAddrOf (iCode * ic)
9170 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9173 D(emitcode ("; genAddrOf",""));
9175 aopOp (IC_RESULT (ic), ic, FALSE);
9177 /* if the operand is on the stack then we
9178 need to get the stack offset of this
9182 /* if it has an offset then we need to compute
9186 emitcode ("mov", "a,_bp");
9187 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9188 ((char) (sym->stack - _G.nRegsSaved)) :
9189 ((char) sym->stack)) & 0xff);
9190 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9194 /* we can just move _bp */
9195 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9197 /* fill the result with zero */
9198 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9203 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9209 /* object not on stack then we need the name */
9210 size = AOP_SIZE (IC_RESULT (ic));
9215 char s[SDCC_NAME_MAX];
9217 sprintf (s, "#(%s >> %d)",
9221 sprintf (s, "#%s", sym->rname);
9222 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9230 /*-----------------------------------------------------------------*/
9231 /* genFarFarAssign - assignment when both are in far space */
9232 /*-----------------------------------------------------------------*/
9234 genFarFarAssign (operand * result, operand * right, iCode * ic)
9236 int size = AOP_SIZE (right);
9240 D(emitcode ("; genFarFarAssign",""));
9242 /* first push the right side on to the stack */
9245 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9247 emitcode ("push", "acc");
9250 freeAsmop (right, NULL, ic, FALSE);
9251 /* now assign DPTR to result */
9252 aopOp (result, ic, FALSE);
9253 size = AOP_SIZE (result);
9256 emitcode ("pop", "acc");
9257 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9259 freeAsmop (result, NULL, ic, FALSE);
9263 /*-----------------------------------------------------------------*/
9264 /* genAssign - generate code for assignment */
9265 /*-----------------------------------------------------------------*/
9267 genAssign (iCode * ic)
9269 operand *result, *right;
9271 unsigned long lit = 0L;
9273 D(emitcode("; genAssign",""));
9275 result = IC_RESULT (ic);
9276 right = IC_RIGHT (ic);
9278 /* if they are the same */
9279 if (operandsEqu (result, right) &&
9280 !isOperandVolatile (result, FALSE) &&
9281 !isOperandVolatile (right, FALSE))
9284 aopOp (right, ic, FALSE);
9286 /* special case both in far space */
9287 if (AOP_TYPE (right) == AOP_DPTR &&
9288 IS_TRUE_SYMOP (result) &&
9289 isOperandInFarSpace (result))
9292 genFarFarAssign (result, right, ic);
9296 aopOp (result, ic, TRUE);
9298 /* if they are the same registers */
9299 if (sameRegs (AOP (right), AOP (result)) &&
9300 !isOperandVolatile (result, FALSE) &&
9301 !isOperandVolatile (right, FALSE))
9304 /* if the result is a bit */
9305 if (AOP_TYPE (result) == AOP_CRY)
9308 /* if the right size is a literal then
9309 we know what the value is */
9310 if (AOP_TYPE (right) == AOP_LIT)
9312 if (((int) operandLitValue (right)))
9313 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9315 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9319 /* the right is also a bit variable */
9320 if (AOP_TYPE (right) == AOP_CRY)
9322 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9323 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9329 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9333 /* bit variables done */
9335 size = AOP_SIZE (result);
9337 if (AOP_TYPE (right) == AOP_LIT)
9338 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9340 (AOP_TYPE (result) != AOP_REG) &&
9341 (AOP_TYPE (right) == AOP_LIT) &&
9342 !IS_FLOAT (operandType (right)) &&
9345 emitcode ("clr", "a");
9348 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9349 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9351 aopPut (AOP (result),
9352 aopGet (AOP (right), size, FALSE, FALSE),
9354 isOperandVolatile (result, FALSE));
9361 aopPut (AOP (result),
9362 aopGet (AOP (right), offset, FALSE, FALSE),
9364 isOperandVolatile (result, FALSE));
9370 freeAsmop (right, NULL, ic, TRUE);
9371 freeAsmop (result, NULL, ic, TRUE);
9374 /*-----------------------------------------------------------------*/
9375 /* genJumpTab - genrates code for jump table */
9376 /*-----------------------------------------------------------------*/
9378 genJumpTab (iCode * ic)
9383 D(emitcode ("; genJumpTab",""));
9385 aopOp (IC_JTCOND (ic), ic, FALSE);
9386 /* get the condition into accumulator */
9387 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9389 /* multiply by three */
9390 emitcode ("add", "a,acc");
9391 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9392 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9394 jtab = newiTempLabel (NULL);
9395 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9396 emitcode ("jmp", "@a+dptr");
9397 emitcode ("", "%05d$:", jtab->key + 100);
9398 /* now generate the jump labels */
9399 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9400 jtab = setNextItem (IC_JTLABELS (ic)))
9401 emitcode ("ljmp", "%05d$", jtab->key + 100);
9405 /*-----------------------------------------------------------------*/
9406 /* genCast - gen code for casting */
9407 /*-----------------------------------------------------------------*/
9409 genCast (iCode * ic)
9411 operand *result = IC_RESULT (ic);
9412 sym_link *ctype = operandType (IC_LEFT (ic));
9413 sym_link *rtype = operandType (IC_RIGHT (ic));
9414 operand *right = IC_RIGHT (ic);
9417 D(emitcode("; genCast",""));
9419 /* if they are equivalent then do nothing */
9420 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9423 aopOp (right, ic, FALSE);
9424 aopOp (result, ic, FALSE);
9426 /* if the result is a bit (and not a bitfield) */
9427 // if (AOP_TYPE (result) == AOP_CRY)
9428 if (IS_BITVAR (OP_SYMBOL (result)->type)
9429 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9431 /* if the right size is a literal then
9432 we know what the value is */
9433 if (AOP_TYPE (right) == AOP_LIT)
9435 if (((int) operandLitValue (right)))
9436 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9438 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9443 /* the right is also a bit variable */
9444 if (AOP_TYPE (right) == AOP_CRY)
9446 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9447 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9453 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9458 /* if they are the same size : or less */
9459 if (AOP_SIZE (result) <= AOP_SIZE (right))
9462 /* if they are in the same place */
9463 if (sameRegs (AOP (right), AOP (result)))
9466 /* if they in different places then copy */
9467 size = AOP_SIZE (result);
9471 aopPut (AOP (result),
9472 aopGet (AOP (right), offset, FALSE, FALSE),
9474 isOperandVolatile (result, FALSE));
9481 /* if the result is of type pointer */
9486 sym_link *type = operandType (right);
9487 sym_link *etype = getSpec (type);
9489 /* pointer to generic pointer */
9490 if (IS_GENPTR (ctype))
9493 p_type = DCL_TYPE (type);
9496 if (SPEC_SCLS(etype)==S_REGISTER) {
9497 // let's assume it is a generic pointer
9500 /* we have to go by the storage class */
9501 p_type = PTR_TYPE (SPEC_OCLS (etype));
9505 /* the first two bytes are known */
9506 size = GPTRSIZE - 1;
9510 aopPut (AOP (result),
9511 aopGet (AOP (right), offset, FALSE, FALSE),
9513 isOperandVolatile (result, FALSE));
9516 /* the last byte depending on type */
9518 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9523 // pointerTypeToGPByte will have bitched.
9527 sprintf(gpValStr, "#0x%d", gpVal);
9528 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9533 /* just copy the pointers */
9534 size = AOP_SIZE (result);
9538 aopPut (AOP (result),
9539 aopGet (AOP (right), offset, FALSE, FALSE),
9541 isOperandVolatile (result, FALSE));
9547 /* so we now know that the size of destination is greater
9548 than the size of the source */
9549 /* we move to result for the size of source */
9550 size = AOP_SIZE (right);
9554 aopPut (AOP (result),
9555 aopGet (AOP (right), offset, FALSE, FALSE),
9557 isOperandVolatile (result, FALSE));
9561 /* now depending on the sign of the source && destination */
9562 size = AOP_SIZE (result) - AOP_SIZE (right);
9563 /* if unsigned or not an integral type */
9564 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9567 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9571 /* we need to extend the sign :{ */
9572 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9575 emitcode ("rlc", "a");
9576 emitcode ("subb", "a,acc");
9578 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9581 /* we are done hurray !!!! */
9584 freeAsmop (right, NULL, ic, TRUE);
9585 freeAsmop (result, NULL, ic, TRUE);
9589 /*-----------------------------------------------------------------*/
9590 /* genDjnz - generate decrement & jump if not zero instrucion */
9591 /*-----------------------------------------------------------------*/
9593 genDjnz (iCode * ic, iCode * ifx)
9599 D(emitcode ("; genDjnz",""));
9601 /* if the if condition has a false label
9602 then we cannot save */
9606 /* if the minus is not of the form
9608 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9609 !IS_OP_LITERAL (IC_RIGHT (ic)))
9612 if (operandLitValue (IC_RIGHT (ic)) != 1)
9615 /* if the size of this greater than one then no
9617 if (getSize (operandType (IC_RESULT (ic))) > 1)
9620 /* otherwise we can save BIG */
9621 lbl = newiTempLabel (NULL);
9622 lbl1 = newiTempLabel (NULL);
9624 aopOp (IC_RESULT (ic), ic, FALSE);
9626 if (AOP_NEEDSACC(IC_RESULT(ic)))
9628 /* If the result is accessed indirectly via
9629 * the accumulator, we must explicitly write
9630 * it back after the decrement.
9632 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9634 if (strcmp(rByte, "a"))
9636 /* Something is hopelessly wrong */
9637 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9638 __FILE__, __LINE__);
9639 /* We can just give up; the generated code will be inefficient,
9642 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9645 emitcode ("dec", "%s", rByte);
9646 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9647 emitcode ("jnz", "%05d$", lbl->key + 100);
9649 else if (IS_AOP_PREG (IC_RESULT (ic)))
9651 emitcode ("dec", "%s",
9652 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9653 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9654 emitcode ("jnz", "%05d$", lbl->key + 100);
9658 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9661 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9662 emitcode ("", "%05d$:", lbl->key + 100);
9663 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9664 emitcode ("", "%05d$:", lbl1->key + 100);
9666 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9671 /*-----------------------------------------------------------------*/
9672 /* genReceive - generate code for a receive iCode */
9673 /*-----------------------------------------------------------------*/
9675 genReceive (iCode * ic)
9677 int size = getSize (operandType (IC_RESULT (ic)));
9679 D(emitcode ("; genReceive",""));
9681 if (ic->argreg == 1) { /* first parameter */
9682 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9683 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9684 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9690 for (offset = 0; offset<size; offset++)
9691 if (!strcmp (fReturn[offset], "a"))
9696 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9698 for (offset = size-1; offset>0; offset--)
9699 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9700 emitcode("mov","a,%s", fReturn[0]);
9702 aopOp (IC_RESULT (ic), ic, FALSE);
9704 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9705 isOperandVolatile (IC_RESULT (ic), FALSE));
9706 for (offset = 1; offset<size; offset++)
9707 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9708 isOperandVolatile (IC_RESULT (ic), FALSE));
9714 if (getTempRegs(tempRegs, size, ic))
9716 for (offset = 0; offset<size; offset++)
9717 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9718 aopOp (IC_RESULT (ic), ic, FALSE);
9719 for (offset = 0; offset<size; offset++)
9720 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9721 isOperandVolatile (IC_RESULT (ic), FALSE));
9726 offset = fReturnSizeMCS51 - size;
9728 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9729 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9732 aopOp (IC_RESULT (ic), ic, FALSE);
9733 size = AOP_SIZE (IC_RESULT (ic));
9736 emitcode ("pop", "acc");
9737 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9742 aopOp (IC_RESULT (ic), ic, FALSE);
9744 assignResultValue (IC_RESULT (ic));
9746 } else { /* second receive onwards */
9748 aopOp (IC_RESULT (ic), ic, FALSE);
9749 rb1off = ic->argreg;
9751 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9756 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9759 /*-----------------------------------------------------------------*/
9760 /* genDummyRead - generate code for dummy read of volatiles */
9761 /*-----------------------------------------------------------------*/
9763 genDummyRead (iCode * ic)
9768 D(emitcode("; genDummyRead",""));
9771 if (op && IS_SYMOP (op))
9773 aopOp (op, ic, FALSE);
9775 /* if the result is a bit */
9776 if (AOP_TYPE (op) == AOP_CRY)
9777 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9780 /* bit variables done */
9782 size = AOP_SIZE (op);
9786 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9791 freeAsmop (op, NULL, ic, TRUE);
9795 if (op && IS_SYMOP (op))
9797 aopOp (op, ic, FALSE);
9799 /* if the result is a bit */
9800 if (AOP_TYPE (op) == AOP_CRY)
9801 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9804 /* bit variables done */
9806 size = AOP_SIZE (op);
9810 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9815 freeAsmop (op, NULL, ic, TRUE);
9819 /*-----------------------------------------------------------------*/
9820 /* genCritical - generate code for start of a critical sequence */
9821 /*-----------------------------------------------------------------*/
9823 genCritical (iCode *ic)
9825 symbol *tlbl = newiTempLabel (NULL);
9827 D(emitcode("; genCritical",""));
9830 aopOp (IC_RESULT (ic), ic, TRUE);
9832 emitcode ("setb", "c");
9833 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9834 emitcode ("clr", "c");
9835 emitcode ("", "%05d$:", (tlbl->key + 100));
9838 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9840 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9846 /*-----------------------------------------------------------------*/
9847 /* genEndCritical - generate code for end of a critical sequence */
9848 /*-----------------------------------------------------------------*/
9850 genEndCritical (iCode *ic)
9852 D(emitcode("; genEndCritical",""));
9856 aopOp (IC_RIGHT (ic), ic, FALSE);
9857 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9859 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9860 emitcode ("mov", "ea,c");
9864 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9865 emitcode ("rrc", "a");
9866 emitcode ("mov", "ea,c");
9868 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9872 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9873 emitcode ("mov", "ea,c");
9877 /*-----------------------------------------------------------------*/
9878 /* gen51Code - generate code for 8051 based controllers */
9879 /*-----------------------------------------------------------------*/
9881 gen51Code (iCode * lic)
9887 _G.currentFunc = NULL;
9888 lineHead = lineCurr = NULL;
9890 /* print the allocation information */
9891 if (allocInfo && currFunc)
9892 printAllocInfo (currFunc, codeOutFile);
9893 /* if debug information required */
9894 if (options.debug && currFunc)
9896 debugFile->writeFunction (currFunc, lic);
9898 /* stack pointer name */
9899 if (options.useXstack)
9905 for (ic = lic; ic; ic = ic->next)
9907 _G.current_iCode = ic;
9909 if (ic->lineno && cln != ic->lineno)
9913 debugFile->writeCLine(ic);
9915 if (!options.noCcodeInAsm) {
9916 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9917 printCLine(ic->filename, ic->lineno));
9922 if (ic->seqPoint && ic->seqPoint != cseq)
9924 emitcode ("", "; sequence point %d", ic->seqPoint);
9925 cseq = ic->seqPoint;
9928 if (options.iCodeInAsm) {
9932 for (i=0; i<8; i++) {
9933 sprintf (®sInUse[i],
9934 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9937 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9939 /* if the result is marked as
9940 spilt and rematerializable or code for
9941 this has already been generated then
9943 if (resultRemat (ic) || ic->generated)
9946 /* depending on the operation */
9966 /* IPOP happens only when trying to restore a
9967 spilt live range, if there is an ifx statement
9968 following this pop then the if statement might
9969 be using some of the registers being popped which
9970 would destory the contents of the register so
9971 we need to check for this condition and handle it */
9973 ic->next->op == IFX &&
9974 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9975 genIfx (ic->next, ic);
9993 genEndFunction (ic);
10013 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10030 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10034 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10041 /* note these two are xlated by algebraic equivalence
10042 during parsing SDCC.y */
10043 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10044 "got '>=' or '<=' shouldn't have come here");
10048 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10060 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10064 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10068 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10092 genRightShift (ic);
10095 case GET_VALUE_AT_ADDRESS:
10096 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10100 if (POINTER_SET (ic))
10101 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10127 addSet (&_G.sendSet, ic);
10130 case DUMMY_READ_VOLATILE:
10139 genEndCritical (ic);
10151 _G.current_iCode = NULL;
10153 /* now we are ready to call the
10154 peep hole optimizer */
10155 if (!options.nopeep)
10156 peepHole (&lineHead);
10158 /* now do the actual printing */
10159 printLine (lineHead, codeOutFile);