1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
83 static char *rb1regs[] = {
84 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
96 #define CLRC emitcode("clr","c")
97 #define SETC emitcode("setb","c")
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104 0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple */
116 /*-----------------------------------------------------------------*/
118 emitcode (char *inst, const char *fmt,...)
121 char lb[INITIAL_INLINEASM];
129 sprintf (lb, "%s\t", inst);
131 sprintf (lb, "%s", inst);
132 vsprintf (lb + (strlen (lb)), fmt, ap);
135 vsprintf (lb, fmt, ap);
137 while (isspace (*lbp))
140 //printf ("%s\n", lb);
143 lineCurr = (lineCurr ?
144 connectLine (lineCurr, newLineNode (lb)) :
145 (lineHead = newLineNode (lb)));
146 lineCurr->isInline = _G.inLine;
147 lineCurr->isDebug = _G.debugLine;
148 lineCurr->ic = _G.current_iCode;
149 lineCurr->isComment = (*lbp==';');
153 /*-----------------------------------------------------------------*/
154 /* mcs51_emitDebuggerSymbol - associate the current code location */
155 /* with a debugger symbol */
156 /*-----------------------------------------------------------------*/
158 mcs51_emitDebuggerSymbol (char * debugSym)
161 emitcode ("", "%s ==.", debugSym);
165 /*-----------------------------------------------------------------*/
166 /* mova - moves specified value into accumulator */
167 /*-----------------------------------------------------------------*/
171 /* do some early peephole optimization */
172 if (!strcmp(x, "a") || !strcmp(x, "acc"))
175 emitcode("mov","a,%s", x);
178 /*-----------------------------------------------------------------*/
179 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
180 /*-----------------------------------------------------------------*/
182 getFreePtr (iCode * ic, asmop ** aopp, bool result)
184 bool r0iu = FALSE, r1iu = FALSE;
185 bool r0ou = FALSE, r1ou = FALSE;
187 /* the logic: if r0 & r1 used in the instruction
188 then we are in trouble otherwise */
190 /* first check if r0 & r1 are used by this
191 instruction, in which case we are in trouble */
192 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
193 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
198 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
199 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
201 /* if no usage of r0 then return it */
204 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205 (*aopp)->type = AOP_R0;
207 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
210 /* if no usage of r1 then return it */
213 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
214 (*aopp)->type = AOP_R1;
216 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
219 /* now we know they both have usage */
220 /* if r0 not used in this instruction */
223 /* push it if not already pushed */
226 emitcode ("mov", "b,%s",
227 mcs51_regWithIdx (R0_IDX)->dname);
230 else if (!_G.r0Pushed)
232 emitcode ("push", "%s",
233 mcs51_regWithIdx (R0_IDX)->dname);
237 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
238 (*aopp)->type = AOP_R0;
240 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
243 /* if r1 not used then */
247 /* push it if not already pushed */
250 emitcode ("mov", "b,%s",
251 mcs51_regWithIdx (R1_IDX)->dname);
254 else if (!_G.r1Pushed)
256 emitcode ("push", "%s",
257 mcs51_regWithIdx (R1_IDX)->dname);
261 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262 (*aopp)->type = AOP_R1;
263 return mcs51_regWithIdx (R1_IDX);
266 /* I said end of world, but not quite end of world yet */
268 /* we can push it on the stack */
269 (*aopp)->type = AOP_STK;
272 /* in the case that result AND left AND right needs a pointer reg
273 we can safely use the result's */
274 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
275 (*aopp)->type = AOP_R0;
276 return mcs51_regWithIdx (R0_IDX);
278 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
279 (*aopp)->type = AOP_R1;
280 return mcs51_regWithIdx (R1_IDX);
284 /* now this is REALLY the end of the world */
285 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
286 "getFreePtr should never reach here");
291 /*-----------------------------------------------------------------*/
292 /* getTempRegs - initialize an array of pointers to GPR registers */
293 /* that are not in use. Returns 1 if the requested */
294 /* number of registers were available, 0 otherwise. */
295 /*-----------------------------------------------------------------*/
297 getTempRegs(regs **tempRegs, int size, iCode *ic)
304 ic = _G.current_iCode;
310 freeRegs = newBitVect(8);
311 bitVectSetBit (freeRegs, R2_IDX);
312 bitVectSetBit (freeRegs, R3_IDX);
313 bitVectSetBit (freeRegs, R4_IDX);
314 bitVectSetBit (freeRegs, R5_IDX);
315 bitVectSetBit (freeRegs, R6_IDX);
316 bitVectSetBit (freeRegs, R7_IDX);
318 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
320 bitVect * newfreeRegs;
321 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
322 freeBitVect(freeRegs);
323 freeRegs = newfreeRegs;
325 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
328 for (i=0; i<freeRegs->size; i++)
330 if (bitVectBitValue(freeRegs,i))
331 tempRegs[offset++] = mcs51_regWithIdx(i);
334 freeBitVect(freeRegs);
339 freeBitVect(freeRegs);
344 /*-----------------------------------------------------------------*/
345 /* newAsmop - creates a new asmOp */
346 /*-----------------------------------------------------------------*/
348 newAsmop (short type)
352 aop = Safe_calloc (1, sizeof (asmop));
357 /*-----------------------------------------------------------------*/
358 /* pointerCode - returns the code for a pointer type */
359 /*-----------------------------------------------------------------*/
361 pointerCode (sym_link * etype)
364 return PTR_TYPE (SPEC_OCLS (etype));
369 /*-----------------------------------------------------------------*/
370 /* leftRightUseAcc - returns size of accumulator use by operands */
371 /*-----------------------------------------------------------------*/
373 leftRightUseAcc(iCode *ic)
382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383 "null iCode pointer");
390 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
393 size = getSize (OP_SYMBOL (op)->type);
398 else if (ic->op == JUMPTABLE)
401 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
404 size = getSize (OP_SYMBOL (op)->type);
412 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
415 size = getSize (OP_SYMBOL (op)->type);
420 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
423 size = getSize (OP_SYMBOL (op)->type);
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol */
438 /*-----------------------------------------------------------------*/
440 aopForSym (iCode * ic, symbol * sym, bool result)
445 wassertl (ic != NULL, "Got a null iCode");
446 wassertl (sym != NULL, "Got a null symbol");
448 space = SPEC_OCLS (sym->etype);
450 /* if already has one */
454 /* assign depending on the storage class */
455 /* if it is on the stack or indirectly addressable */
456 /* space we need to assign either r0 or r1 to it */
457 if (sym->onStack || sym->iaccess)
459 sym->aop = aop = newAsmop (0);
460 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461 aop->size = getSize (sym->type);
463 /* now assign the address of the variable to
464 the pointer register */
465 if (aop->type != AOP_STK)
470 if (_G.accInUse || leftRightUseAcc (ic))
471 emitcode ("push", "acc");
473 emitcode ("mov", "a,_bp");
474 emitcode ("add", "a,#0x%02x",
476 ((char) (sym->stack - _G.nRegsSaved)) :
477 ((char) sym->stack)) & 0xff);
478 emitcode ("mov", "%s,a",
479 aop->aopu.aop_ptr->name);
481 if (_G.accInUse || leftRightUseAcc (ic))
482 emitcode ("pop", "acc");
485 emitcode ("mov", "%s,#%s",
486 aop->aopu.aop_ptr->name,
488 aop->paged = space->paged;
491 aop->aopu.aop_stk = sym->stack;
495 /* if in bit space */
496 if (IN_BITSPACE (space))
498 sym->aop = aop = newAsmop (AOP_CRY);
499 aop->aopu.aop_dir = sym->rname;
500 aop->size = getSize (sym->type);
503 /* if it is in direct space */
504 if (IN_DIRSPACE (space))
506 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
507 //printTypeChainRaw(sym->type, NULL);
508 //printf("space = %s\n", space ? space->sname : "NULL");
509 sym->aop = aop = newAsmop (AOP_DIR);
510 aop->aopu.aop_dir = sym->rname;
511 aop->size = getSize (sym->type);
515 /* special case for a function */
516 if (IS_FUNC (sym->type))
518 sym->aop = aop = newAsmop (AOP_IMMD);
519 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
520 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
521 aop->size = FPTRSIZE;
525 /* only remaining is far space */
526 /* in which case DPTR gets the address */
527 sym->aop = aop = newAsmop (AOP_DPTR);
528 emitcode ("mov", "dptr,#%s", sym->rname);
529 aop->size = getSize (sym->type);
531 /* if it is in code space */
532 if (IN_CODESPACE (space))
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object */
540 /*-----------------------------------------------------------------*/
542 aopForRemat (symbol * sym)
544 iCode *ic = sym->rematiCode;
545 asmop *aop = newAsmop (AOP_IMMD);
552 val += (int) operandLitValue (IC_RIGHT (ic));
553 else if (ic->op == '-')
554 val -= (int) operandLitValue (IC_RIGHT (ic));
555 else if (IS_CAST_ICODE(ic)) {
556 sym_link *from_type = operandType(IC_RIGHT(ic));
557 aop->aopu.aop_immd.from_cast_remat = 1;
558 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
559 ptr_type = DCL_TYPE(from_type);
560 if (ptr_type == IPOINTER) {
567 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
571 sprintf (buffer, "(%s %c 0x%04x)",
572 OP_SYMBOL (IC_LEFT (ic))->rname,
573 val >= 0 ? '+' : '-',
576 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
579 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
580 /* set immd2 field if required */
581 if (aop->aopu.aop_immd.from_cast_remat) {
582 sprintf(buffer,"#0x%02x",ptr_type);
583 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
584 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
590 /*-----------------------------------------------------------------*/
591 /* regsInCommon - two operands have some registers in common */
592 /*-----------------------------------------------------------------*/
594 regsInCommon (operand * op1, operand * op2)
599 /* if they have registers in common */
600 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
603 sym1 = OP_SYMBOL (op1);
604 sym2 = OP_SYMBOL (op2);
606 if (sym1->nRegs == 0 || sym2->nRegs == 0)
609 for (i = 0; i < sym1->nRegs; i++)
615 for (j = 0; j < sym2->nRegs; j++)
620 if (sym2->regs[j] == sym1->regs[i])
628 /*-----------------------------------------------------------------*/
629 /* operandsEqu - equivalent */
630 /*-----------------------------------------------------------------*/
632 operandsEqu (operand * op1, operand * op2)
636 /* if they not symbols */
637 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
640 sym1 = OP_SYMBOL (op1);
641 sym2 = OP_SYMBOL (op2);
643 /* if both are itemps & one is spilt
644 and the other is not then false */
645 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
646 sym1->isspilt != sym2->isspilt)
649 /* if they are the same */
653 if (sym1->rname[0] && sym2->rname[0]
654 && strcmp (sym1->rname, sym2->rname) == 0)
657 /* if left is a tmp & right is not */
658 if (IS_ITEMP (op1) &&
661 (sym1->usl.spillLoc == sym2))
664 if (IS_ITEMP (op2) &&
668 (sym2->usl.spillLoc == sym1))
674 /*-----------------------------------------------------------------*/
675 /* sameRegs - two asmops have the same registers */
676 /*-----------------------------------------------------------------*/
678 sameRegs (asmop * aop1, asmop * aop2)
685 if (aop1->type != AOP_REG ||
686 aop2->type != AOP_REG)
689 if (aop1->size != aop2->size)
692 for (i = 0; i < aop1->size; i++)
693 if (aop1->aopu.aop_reg[i] !=
694 aop2->aopu.aop_reg[i])
700 /*-----------------------------------------------------------------*/
701 /* aopOp - allocates an asmop for an operand : */
702 /*-----------------------------------------------------------------*/
704 aopOp (operand * op, iCode * ic, bool result)
713 /* if this a literal */
714 if (IS_OP_LITERAL (op))
716 op->aop = aop = newAsmop (AOP_LIT);
717 aop->aopu.aop_lit = op->operand.valOperand;
718 aop->size = getSize (operandType (op));
722 /* if already has a asmop then continue */
726 /* if the underlying symbol has a aop */
727 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
729 op->aop = OP_SYMBOL (op)->aop;
733 /* if this is a true symbol */
734 if (IS_TRUE_SYMOP (op))
736 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
740 /* this is a temporary : this has
746 e) can be a return use only */
748 sym = OP_SYMBOL (op);
750 /* if the type is a conditional */
751 if (sym->regType == REG_CND)
753 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
758 /* if it is spilt then two situations
760 b) has a spill location */
761 if (sym->isspilt || sym->nRegs == 0)
764 /* rematerialize it NOW */
767 sym->aop = op->aop = aop =
769 aop->size = getSize (sym->type);
776 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
777 aop->size = getSize (sym->type);
778 for (i = 0; i < 2; i++)
779 aop->aopu.aop_str[i] = accUse[i];
787 aop = op->aop = sym->aop = newAsmop (AOP_STR);
788 aop->size = getSize (sym->type);
789 for (i = 0; i < fReturnSizeMCS51; i++)
790 aop->aopu.aop_str[i] = fReturn[i];
794 if (sym->usl.spillLoc)
796 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
798 /* force a new aop if sizes differ */
799 sym->usl.spillLoc->aop = NULL;
801 sym->aop = op->aop = aop =
802 aopForSym (ic, sym->usl.spillLoc, result);
803 aop->size = getSize (sym->type);
807 /* else must be a dummy iTemp */
808 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
809 aop->size = getSize (sym->type);
813 /* must be in a register */
814 sym->aop = op->aop = aop = newAsmop (AOP_REG);
815 aop->size = sym->nRegs;
816 for (i = 0; i < sym->nRegs; i++)
817 aop->aopu.aop_reg[i] = sym->regs[i];
820 /*-----------------------------------------------------------------*/
821 /* freeAsmop - free up the asmop given to an operand */
822 /*----------------------------------------------------------------*/
824 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
841 /* depending on the asmop type only three cases need work AOP_RO
842 , AOP_R1 && AOP_STK */
848 emitcode ("mov", "r0,b");
851 else if (_G.r0Pushed)
855 emitcode ("pop", "ar0");
859 bitVectUnSetBit (ic->rUsed, R0_IDX);
865 emitcode ("mov", "r1,b");
872 emitcode ("pop", "ar1");
876 bitVectUnSetBit (ic->rUsed, R1_IDX);
882 int stk = aop->aopu.aop_stk + aop->size - 1;
883 bitVectUnSetBit (ic->rUsed, R0_IDX);
884 bitVectUnSetBit (ic->rUsed, R1_IDX);
886 getFreePtr (ic, &aop, FALSE);
890 emitcode ("mov", "a,_bp");
891 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
892 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
901 emitcode ("pop", "acc");
902 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
905 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
908 freeAsmop (op, NULL, ic, TRUE);
911 emitcode ("pop", "ar1");
917 emitcode ("pop", "ar0");
924 /* all other cases just dealloc */
930 OP_SYMBOL (op)->aop = NULL;
931 /* if the symbol has a spill */
933 SPIL_LOC (op)->aop = NULL;
938 /*------------------------------------------------------------------*/
939 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
940 /* pop r0 or r1 off stack if pushed */
941 /*------------------------------------------------------------------*/
943 freeForBranchAsmop (operand * op)
963 emitcode ("mov", "r0,b");
965 else if (_G.r0Pushed)
967 emitcode ("pop", "ar0");
974 emitcode ("mov", "r1,b");
976 else if (_G.r1Pushed)
978 emitcode ("pop", "ar1");
985 int stk = aop->aopu.aop_stk + aop->size - 1;
987 emitcode ("mov", "b,r0");
990 emitcode ("mov", "a,_bp");
991 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
992 emitcode ("mov", "r0,a");
996 emitcode ("mov", "r0,_bp");
1001 emitcode ("pop", "acc");
1002 emitcode ("mov", "@r0,a");
1005 emitcode ("dec", "r0");
1007 emitcode ("mov", "r0,b");
1013 /*-----------------------------------------------------------------*/
1014 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1015 /* clobber the accumulator */
1016 /*-----------------------------------------------------------------*/
1018 aopGetUsesAcc (asmop *aop, int offset)
1020 if (offset > (aop->size - 1))
1038 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1047 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1053 /* Error case --- will have been caught already */
1059 /*-----------------------------------------------------------------*/
1060 /* aopGet - for fetching value of the aop */
1061 /*-----------------------------------------------------------------*/
1063 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1068 /* offset is greater than
1070 if (offset > (aop->size - 1) &&
1071 aop->type != AOP_LIT)
1074 /* depending on type */
1082 /* if we need to increment it */
1083 while (offset > aop->coff)
1085 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1089 while (offset < aop->coff)
1091 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1098 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1099 return (dname ? "acc" : "a");
1101 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1102 rs = Safe_calloc (1, strlen (s) + 1);
1107 if (aop->code && aop->coff==0 && offset>=1) {
1108 emitcode ("mov", "a,#0x%02x", offset);
1109 emitcode ("movc", "a,@a+dptr");
1110 return (dname ? "acc" : "a");
1113 while (offset > aop->coff)
1115 emitcode ("inc", "dptr");
1119 while (offset < aop->coff)
1121 emitcode ("lcall", "__decdptr");
1128 emitcode ("clr", "a");
1129 emitcode ("movc", "a,@a+dptr");
1133 emitcode ("movx", "a,@dptr");
1135 return (dname ? "acc" : "a");
1139 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1142 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1144 sprintf (s, "#(%s >> %d)",
1145 aop->aopu.aop_immd.aop_immd1,
1149 aop->aopu.aop_immd.aop_immd1);
1150 rs = Safe_calloc (1, strlen (s) + 1);
1156 sprintf (s, "(%s + %d)",
1160 sprintf (s, "%s", aop->aopu.aop_dir);
1161 rs = Safe_calloc (1, strlen (s) + 1);
1167 return aop->aopu.aop_reg[offset]->dname;
1169 return aop->aopu.aop_reg[offset]->name;
1172 emitcode ("clr", "a");
1173 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1174 emitcode ("rlc", "a");
1175 return (dname ? "acc" : "a");
1178 if (!offset && dname)
1180 return aop->aopu.aop_str[offset];
1183 return aopLiteral (aop->aopu.aop_lit, offset);
1187 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1191 return aop->aopu.aop_str[offset];
1195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1196 "aopget got unsupported aop->type");
1199 /*-----------------------------------------------------------------*/
1200 /* aopPut - puts a string for a aop */
1201 /*-----------------------------------------------------------------*/
1203 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1207 if (aop->size && offset > (aop->size - 1))
1209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1210 "aopPut got offset > aop->size");
1214 /* will assign value to value */
1215 /* depending on where it is ofcourse */
1219 MOVA (s); /* read s in case it was volatile */
1224 sprintf (d, "(%s + %d)",
1225 aop->aopu.aop_dir, offset);
1227 sprintf (d, "%s", aop->aopu.aop_dir);
1229 if (strcmp (d, s) ||
1231 emitcode ("mov", "%s,%s", d, s);
1236 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1237 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1240 strcmp (s, "r0") == 0 ||
1241 strcmp (s, "r1") == 0 ||
1242 strcmp (s, "r2") == 0 ||
1243 strcmp (s, "r3") == 0 ||
1244 strcmp (s, "r4") == 0 ||
1245 strcmp (s, "r5") == 0 ||
1246 strcmp (s, "r6") == 0 ||
1247 strcmp (s, "r7") == 0)
1248 emitcode ("mov", "%s,%s",
1249 aop->aopu.aop_reg[offset]->dname, s);
1251 emitcode ("mov", "%s,%s",
1252 aop->aopu.aop_reg[offset]->name, s);
1259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260 "aopPut writing to code space");
1264 while (offset > aop->coff)
1267 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1273 emitcode ("lcall", "__decdptr");
1278 /* if not in accumulater */
1281 emitcode ("movx", "@dptr,a");
1286 while (offset > aop->coff)
1289 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1291 while (offset < aop->coff)
1294 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1301 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1307 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1309 else if (strcmp (s, "r0") == 0 ||
1310 strcmp (s, "r1") == 0 ||
1311 strcmp (s, "r2") == 0 ||
1312 strcmp (s, "r3") == 0 ||
1313 strcmp (s, "r4") == 0 ||
1314 strcmp (s, "r5") == 0 ||
1315 strcmp (s, "r6") == 0 ||
1316 strcmp (s, "r7") == 0)
1319 sprintf (buffer, "a%s", s);
1320 emitcode ("mov", "@%s,%s",
1321 aop->aopu.aop_ptr->name, buffer);
1324 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1329 if (strcmp (s, "a") == 0)
1330 emitcode ("push", "acc");
1334 emitcode ("push", "acc");
1336 emitcode ("push", s);
1342 /* if bit variable */
1343 if (!aop->aopu.aop_dir)
1345 emitcode ("clr", "a");
1346 emitcode ("rlc", "a");
1351 emitcode ("clr", "%s", aop->aopu.aop_dir);
1353 emitcode ("setb", "%s", aop->aopu.aop_dir);
1354 else if (!strcmp (s, "c"))
1355 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1358 if (strcmp (s, "a"))
1363 /* set C, if a >= 1 */
1364 emitcode ("add", "a,#0xff");
1365 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1373 if (strcmp (aop->aopu.aop_str[offset], s) ||
1375 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1380 if (!offset && (strcmp (s, "acc") == 0) &&
1384 if (strcmp (aop->aopu.aop_str[offset], s) &&
1386 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1390 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1391 "aopPut got unsupported aop->type");
1399 /*-----------------------------------------------------------------*/
1400 /* pointToEnd :- points to the last byte of the operand */
1401 /*-----------------------------------------------------------------*/
1403 pointToEnd (asmop * aop)
1409 aop->coff = count = (aop->size - 1);
1415 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1419 emitcode ("inc", "dptr");
1426 /*-----------------------------------------------------------------*/
1427 /* reAdjustPreg - points a register back to where it should */
1428 /*-----------------------------------------------------------------*/
1430 reAdjustPreg (asmop * aop)
1432 if ((aop->coff==0) || aop->size <= 1)
1440 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1445 emitcode ("lcall", "__decdptr");
1452 #define AOP(op) op->aop
1453 #define AOP_TYPE(op) AOP(op)->type
1454 #define AOP_SIZE(op) AOP(op)->size
1455 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1456 AOP_TYPE(x) == AOP_R0))
1458 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1459 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1461 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1462 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1463 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1466 /*-----------------------------------------------------------------*/
1467 /* opIsGptr: returns non-zero if the passed operand is */
1468 /* a generic pointer type. */
1469 /*-----------------------------------------------------------------*/
1471 opIsGptr (operand * op)
1473 sym_link *type = operandType (op);
1475 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1482 /*-----------------------------------------------------------------*/
1483 /* getDataSize - get the operand data size */
1484 /*-----------------------------------------------------------------*/
1486 getDataSize (operand * op)
1489 size = AOP_SIZE (op);
1490 if (size == GPTRSIZE)
1492 sym_link *type = operandType (op);
1493 if (IS_GENPTR (type))
1495 /* generic pointer; arithmetic operations
1496 * should ignore the high byte (pointer type).
1504 /*-----------------------------------------------------------------*/
1505 /* outAcc - output Acc */
1506 /*-----------------------------------------------------------------*/
1508 outAcc (operand * result)
1511 size = getDataSize (result);
1514 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1517 /* unsigned or positive */
1520 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1525 /*-----------------------------------------------------------------*/
1526 /* outBitC - output a bit C */
1527 /*-----------------------------------------------------------------*/
1529 outBitC (operand * result)
1531 /* if the result is bit */
1532 if (AOP_TYPE (result) == AOP_CRY)
1533 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1536 emitcode ("clr", "a");
1537 emitcode ("rlc", "a");
1542 /*-----------------------------------------------------------------*/
1543 /* toBoolean - emit code for orl a,operator(sizeop) */
1544 /*-----------------------------------------------------------------*/
1546 toBoolean (operand * oper)
1548 int size = AOP_SIZE (oper) - 1;
1550 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1552 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1556 /*-----------------------------------------------------------------*/
1557 /* genNot - generate code for ! operation */
1558 /*-----------------------------------------------------------------*/
1564 D(emitcode ("; genNot",""));
1566 /* assign asmOps to operand & result */
1567 aopOp (IC_LEFT (ic), ic, FALSE);
1568 aopOp (IC_RESULT (ic), ic, TRUE);
1570 /* if in bit space then a special case */
1571 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1573 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1574 emitcode ("cpl", "c");
1575 outBitC (IC_RESULT (ic));
1579 toBoolean (IC_LEFT (ic));
1581 tlbl = newiTempLabel (NULL);
1582 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1583 emitcode ("", "%05d$:", tlbl->key + 100);
1584 outBitC (IC_RESULT (ic));
1587 /* release the aops */
1588 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1593 /*-----------------------------------------------------------------*/
1594 /* genCpl - generate code for complement */
1595 /*-----------------------------------------------------------------*/
1603 D(emitcode ("; genCpl",""));
1605 /* assign asmOps to operand & result */
1606 aopOp (IC_LEFT (ic), ic, FALSE);
1607 aopOp (IC_RESULT (ic), ic, TRUE);
1609 /* special case if in bit space */
1610 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1612 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1614 /* promotion rules are responsible for this strange result: */
1615 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1619 tlbl=newiTempLabel(NULL);
1620 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1621 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1622 IS_AOP_PREG (IC_LEFT (ic)))
1624 emitcode ("cjne", "%s,#0x01,%05d$",
1625 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1630 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1632 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1634 emitcode ("", "%05d$:", tlbl->key + 100);
1635 outBitC (IC_RESULT(ic));
1639 size = AOP_SIZE (IC_RESULT (ic));
1642 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1644 emitcode ("cpl", "a");
1645 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1650 /* release the aops */
1651 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1652 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* genUminusFloat - unary minus for floating points */
1657 /*-----------------------------------------------------------------*/
1659 genUminusFloat (operand * op, operand * result)
1661 int size, offset = 0;
1664 D(emitcode ("; genUminusFloat",""));
1666 /* for this we just copy and then flip the bit */
1668 size = AOP_SIZE (op) - 1;
1672 aopPut (AOP (result),
1673 aopGet (AOP (op), offset, FALSE, FALSE),
1675 isOperandVolatile (result, FALSE));
1679 l = aopGet (AOP (op), offset, FALSE, FALSE);
1683 emitcode ("cpl", "acc.7");
1684 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1687 /*-----------------------------------------------------------------*/
1688 /* genUminus - unary minus code generation */
1689 /*-----------------------------------------------------------------*/
1691 genUminus (iCode * ic)
1694 sym_link *optype, *rtype;
1697 D(emitcode ("; genUminus",""));
1700 aopOp (IC_LEFT (ic), ic, FALSE);
1701 aopOp (IC_RESULT (ic), ic, TRUE);
1703 /* if both in bit space then special
1705 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1706 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1709 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1710 emitcode ("cpl", "c");
1711 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1715 optype = operandType (IC_LEFT (ic));
1716 rtype = operandType (IC_RESULT (ic));
1718 /* if float then do float stuff */
1719 if (IS_FLOAT (optype))
1721 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1725 /* otherwise subtract from zero */
1726 size = AOP_SIZE (IC_LEFT (ic));
1731 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1732 if (!strcmp (l, "a"))
1736 emitcode ("cpl", "a");
1737 emitcode ("addc", "a,#0");
1743 emitcode ("clr", "a");
1744 emitcode ("subb", "a,%s", l);
1746 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1749 /* if any remaining bytes in the result */
1750 /* we just need to propagate the sign */
1751 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1753 emitcode ("rlc", "a");
1754 emitcode ("subb", "a,acc");
1756 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1760 /* release the aops */
1761 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1762 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1765 /*-----------------------------------------------------------------*/
1766 /* saveRegisters - will look for a call and save the registers */
1767 /*-----------------------------------------------------------------*/
1769 saveRegisters (iCode * lic)
1776 for (ic = lic; ic; ic = ic->next)
1777 if (ic->op == CALL || ic->op == PCALL)
1782 fprintf (stderr, "found parameter push with no function call\n");
1786 /* if the registers have been saved already or don't need to be then
1790 if (IS_SYMOP(IC_LEFT(ic)) &&
1791 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1792 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1795 /* safe the registers in use at this time but skip the
1796 ones for the result */
1797 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1798 mcs51_rUmaskForOp (IC_RESULT(ic)));
1801 if (options.useXstack)
1803 if (bitVectBitValue (rsave, R0_IDX))
1804 emitcode ("mov", "b,r0");
1805 emitcode ("mov", "r0,%s", spname);
1806 for (i = 0; i < mcs51_nRegs; i++)
1808 if (bitVectBitValue (rsave, i))
1811 emitcode ("mov", "a,b");
1813 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1814 emitcode ("movx", "@r0,a");
1815 emitcode ("inc", "r0");
1818 emitcode ("mov", "%s,r0", spname);
1819 if (bitVectBitValue (rsave, R0_IDX))
1820 emitcode ("mov", "r0,b");
1823 for (i = 0; i < mcs51_nRegs; i++)
1825 if (bitVectBitValue (rsave, i))
1826 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1830 /*-----------------------------------------------------------------*/
1831 /* unsaveRegisters - pop the pushed registers */
1832 /*-----------------------------------------------------------------*/
1834 unsaveRegisters (iCode * ic)
1839 /* restore the registers in use at this time but skip the
1840 ones for the result */
1841 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1842 mcs51_rUmaskForOp (IC_RESULT(ic)));
1844 if (options.useXstack)
1846 emitcode ("mov", "r0,%s", spname);
1847 for (i = mcs51_nRegs; i >= 0; i--)
1849 if (bitVectBitValue (rsave, i))
1851 emitcode ("dec", "r0");
1852 emitcode ("movx", "a,@r0");
1854 emitcode ("mov", "b,a");
1856 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1860 emitcode ("mov", "%s,r0", spname);
1861 if (bitVectBitValue (rsave, R0_IDX))
1862 emitcode ("mov", "r0,b");
1865 for (i = mcs51_nRegs; i >= 0; i--)
1867 if (bitVectBitValue (rsave, i))
1868 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1874 /*-----------------------------------------------------------------*/
1876 /*-----------------------------------------------------------------*/
1878 pushSide (operand * oper, int size)
1883 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1884 if (AOP_TYPE (oper) != AOP_REG &&
1885 AOP_TYPE (oper) != AOP_DIR &&
1889 emitcode ("push", "acc");
1892 emitcode ("push", "%s", l);
1896 /*-----------------------------------------------------------------*/
1897 /* assignResultValue - */
1898 /*-----------------------------------------------------------------*/
1900 assignResultValue (operand * oper)
1903 int size = AOP_SIZE (oper);
1906 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1912 /*-----------------------------------------------------------------*/
1913 /* genXpush - pushes onto the external stack */
1914 /*-----------------------------------------------------------------*/
1916 genXpush (iCode * ic)
1918 asmop *aop = newAsmop (0);
1920 int size, offset = 0;
1922 D(emitcode ("; genXpush",""));
1924 aopOp (IC_LEFT (ic), ic, FALSE);
1925 r = getFreePtr (ic, &aop, FALSE);
1928 emitcode ("mov", "%s,_spx", r->name);
1930 size = AOP_SIZE (IC_LEFT (ic));
1934 char *l = aopGet (AOP (IC_LEFT (ic)),
1935 offset++, FALSE, FALSE);
1937 emitcode ("movx", "@%s,a", r->name);
1938 emitcode ("inc", "%s", r->name);
1943 emitcode ("mov", "_spx,%s", r->name);
1945 freeAsmop (NULL, aop, ic, TRUE);
1946 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1949 /*-----------------------------------------------------------------*/
1950 /* genIpush - genrate code for pushing this gets a little complex */
1951 /*-----------------------------------------------------------------*/
1953 genIpush (iCode * ic)
1955 int size, offset = 0;
1958 D(emitcode ("; genIpush",""));
1960 /* if this is not a parm push : ie. it is spill push
1961 and spill push is always done on the local stack */
1965 /* and the item is spilt then do nothing */
1966 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1969 aopOp (IC_LEFT (ic), ic, FALSE);
1970 size = AOP_SIZE (IC_LEFT (ic));
1971 /* push it on the stack */
1974 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1980 emitcode ("push", "%s", l);
1985 /* this is a paramter push: in this case we call
1986 the routine to find the call and save those
1987 registers that need to be saved */
1990 /* if use external stack then call the external
1991 stack pushing routine */
1992 if (options.useXstack)
1998 /* then do the push */
1999 aopOp (IC_LEFT (ic), ic, FALSE);
2002 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2003 size = AOP_SIZE (IC_LEFT (ic));
2007 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2008 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2009 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2013 emitcode ("push", "acc");
2016 emitcode ("push", "%s", l);
2019 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2022 /*-----------------------------------------------------------------*/
2023 /* genIpop - recover the registers: can happen only for spilling */
2024 /*-----------------------------------------------------------------*/
2026 genIpop (iCode * ic)
2030 D(emitcode ("; genIpop",""));
2032 /* if the temp was not pushed then */
2033 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2037 size = AOP_SIZE (IC_LEFT (ic));
2038 offset = (size - 1);
2040 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2043 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2046 /*-----------------------------------------------------------------*/
2047 /* unsaveRBank - restores the resgister bank from stack */
2048 /*-----------------------------------------------------------------*/
2050 unsaveRBank (int bank, iCode * ic, bool popPsw)
2056 if (options.useXstack)
2060 /* Assume r0 is available for use. */
2061 r = mcs51_regWithIdx (R0_IDX);;
2066 r = getFreePtr (ic, &aop, FALSE);
2068 emitcode ("mov", "%s,_spx", r->name);
2073 if (options.useXstack)
2075 emitcode ("movx", "a,@%s", r->name);
2076 emitcode ("mov", "psw,a");
2077 emitcode ("dec", "%s", r->name);
2081 emitcode ("pop", "psw");
2085 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2087 if (options.useXstack)
2089 emitcode ("movx", "a,@%s", r->name);
2090 emitcode ("mov", "(%s+%d),a",
2091 regs8051[i].base, 8 * bank + regs8051[i].offset);
2092 emitcode ("dec", "%s", r->name);
2096 emitcode ("pop", "(%s+%d)",
2097 regs8051[i].base, 8 * bank + regs8051[i].offset);
2100 if (options.useXstack)
2102 emitcode ("mov", "_spx,%s", r->name);
2107 freeAsmop (NULL, aop, ic, TRUE);
2111 /*-----------------------------------------------------------------*/
2112 /* saveRBank - saves an entire register bank on the stack */
2113 /*-----------------------------------------------------------------*/
2115 saveRBank (int bank, iCode * ic, bool pushPsw)
2121 if (options.useXstack)
2125 /* Assume r0 is available for use. */
2126 r = mcs51_regWithIdx (R0_IDX);;
2131 r = getFreePtr (ic, &aop, FALSE);
2133 emitcode ("mov", "%s,_spx", r->name);
2136 for (i = 0; i < mcs51_nRegs; i++)
2138 if (options.useXstack)
2140 emitcode ("inc", "%s", r->name);
2141 emitcode ("mov", "a,(%s+%d)",
2142 regs8051[i].base, 8 * bank + regs8051[i].offset);
2143 emitcode ("movx", "@%s,a", r->name);
2146 emitcode ("push", "(%s+%d)",
2147 regs8051[i].base, 8 * bank + regs8051[i].offset);
2152 if (options.useXstack)
2154 emitcode ("mov", "a,psw");
2155 emitcode ("movx", "@%s,a", r->name);
2156 emitcode ("inc", "%s", r->name);
2157 emitcode ("mov", "_spx,%s", r->name);
2162 emitcode ("push", "psw");
2165 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2170 freeAsmop (NULL, aop, ic, TRUE);
2179 /*-----------------------------------------------------------------*/
2180 /* genSend - gen code for SEND */
2181 /*-----------------------------------------------------------------*/
2182 static void genSend(set *sendSet)
2187 for (sic = setFirstItem (_G.sendSet); sic;
2188 sic = setNextItem (_G.sendSet)) {
2189 int size, offset = 0;
2190 aopOp (IC_LEFT (sic), sic, FALSE);
2191 size = AOP_SIZE (IC_LEFT (sic));
2193 if (sic->argreg == 1) {
2195 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2197 if (strcmp (l, fReturn[offset]))
2198 emitcode ("mov", "%s,%s", fReturn[offset], l);
2204 emitcode ("mov","b1_%d,%s",rb1_count++,
2205 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2208 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2212 /*-----------------------------------------------------------------*/
2213 /* genCall - generates a call statement */
2214 /*-----------------------------------------------------------------*/
2216 genCall (iCode * ic)
2219 // bool restoreBank = FALSE;
2220 bool swapBanks = FALSE;
2222 D(emitcode("; genCall",""));
2224 dtype = operandType (IC_LEFT (ic));
2225 /* if send set is not empty the assign */
2228 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2229 genSend(reverseSet(_G.sendSet));
2231 genSend(_G.sendSet);
2237 /* if we are calling a not _naked function that is not using
2238 the same register bank then we need to save the
2239 destination registers on the stack */
2240 dtype = operandType (IC_LEFT (ic));
2241 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2242 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2243 !IFFUNC_ISISR (dtype))
2248 /* if caller saves & we have not saved then */
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2259 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2260 OP_SYMBOL (IC_LEFT (ic))->rname :
2261 OP_SYMBOL (IC_LEFT (ic))->name));
2265 emitcode ("mov", "psw,#0x%02x",
2266 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2269 /* if we need assign a result value */
2270 if ((IS_ITEMP (IC_RESULT (ic)) &&
2271 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2272 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2273 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2274 IS_TRUE_SYMOP (IC_RESULT (ic)))
2278 aopOp (IC_RESULT (ic), ic, FALSE);
2281 assignResultValue (IC_RESULT (ic));
2283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2286 /* adjust the stack for parameters if
2291 if (ic->parmBytes > 3)
2293 emitcode ("mov", "a,%s", spname);
2294 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2295 emitcode ("mov", "%s,a", spname);
2298 for (i = 0; i < ic->parmBytes; i++)
2299 emitcode ("dec", "%s", spname);
2302 /* if we hade saved some registers then unsave them */
2303 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2304 unsaveRegisters (ic);
2306 // /* if register bank was saved then pop them */
2308 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2311 /*-----------------------------------------------------------------*/
2312 /* -10l - generates a call by pointer statement */
2313 /*-----------------------------------------------------------------*/
2315 genPcall (iCode * ic)
2318 symbol *rlbl = newiTempLabel (NULL);
2319 // bool restoreBank=FALSE;
2320 bool swapBanks = FALSE;
2322 D(emitcode("; genPCall",""));
2324 /* if caller saves & we have not saved then */
2328 /* if we are calling a not _naked function that is not using
2329 the same register bank then we need to save the
2330 destination registers on the stack */
2331 dtype = operandType (IC_LEFT (ic))->next;
2332 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2333 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2334 !IFFUNC_ISISR (dtype))
2336 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2337 // restoreBank=TRUE;
2339 // need caution message to user here
2342 /* push the return address on to the stack */
2343 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2344 emitcode ("push", "acc");
2345 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2346 emitcode ("push", "acc");
2348 /* now push the calling address */
2349 aopOp (IC_LEFT (ic), ic, FALSE);
2351 pushSide (IC_LEFT (ic), FPTRSIZE);
2353 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2355 /* if send set is not empty the assign */
2358 genSend(reverseSet(_G.sendSet));
2364 emitcode ("mov", "psw,#0x%02x",
2365 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2369 emitcode ("ret", "");
2370 emitcode ("", "%05d$:", (rlbl->key + 100));
2375 emitcode ("mov", "psw,#0x%02x",
2376 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2379 /* if we need assign a result value */
2380 if ((IS_ITEMP (IC_RESULT (ic)) &&
2381 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2382 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2383 IS_TRUE_SYMOP (IC_RESULT (ic)))
2387 aopOp (IC_RESULT (ic), ic, FALSE);
2390 assignResultValue (IC_RESULT (ic));
2392 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2395 /* adjust the stack for parameters if
2400 if (ic->parmBytes > 3)
2402 emitcode ("mov", "a,%s", spname);
2403 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2404 emitcode ("mov", "%s,a", spname);
2407 for (i = 0; i < ic->parmBytes; i++)
2408 emitcode ("dec", "%s", spname);
2412 // /* if register bank was saved then unsave them */
2414 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2416 /* if we hade saved some registers then
2418 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2419 unsaveRegisters (ic);
2422 /*-----------------------------------------------------------------*/
2423 /* resultRemat - result is rematerializable */
2424 /*-----------------------------------------------------------------*/
2426 resultRemat (iCode * ic)
2428 if (SKIP_IC (ic) || ic->op == IFX)
2431 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2433 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2434 if (sym->remat && !POINTER_SET (ic))
2441 #if defined(__BORLANDC__) || defined(_MSC_VER)
2442 #define STRCASECMP stricmp
2444 #define STRCASECMP strcasecmp
2447 /*-----------------------------------------------------------------*/
2448 /* inExcludeList - return 1 if the string is in exclude Reg list */
2449 /*-----------------------------------------------------------------*/
2451 regsCmp(void *p1, void *p2)
2453 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2457 inExcludeList (char *s)
2459 const char *p = setFirstItem(options.excludeRegsSet);
2461 if (p == NULL || STRCASECMP(p, "none") == 0)
2465 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2468 /*-----------------------------------------------------------------*/
2469 /* genFunction - generated code for function entry */
2470 /*-----------------------------------------------------------------*/
2472 genFunction (iCode * ic)
2474 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2476 bool switchedPSW = FALSE;
2477 int calleesaves_saved_register = -1;
2478 int stackAdjust = sym->stack;
2479 int accIsFree = sym->recvSize < 4;
2480 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2483 /* create the function header */
2484 emitcode (";", "-----------------------------------------");
2485 emitcode (";", " function %s", sym->name);
2486 emitcode (";", "-----------------------------------------");
2488 emitcode ("", "%s:", sym->rname);
2489 ftype = operandType (IC_LEFT (ic));
2490 _G.currentFunc = sym;
2492 if (IFFUNC_ISNAKED(ftype))
2494 emitcode(";", "naked function: no prologue.");
2498 /* here we need to generate the equates for the
2499 register bank if required */
2500 if (FUNC_REGBANK (ftype) != rbank)
2504 rbank = FUNC_REGBANK (ftype);
2505 for (i = 0; i < mcs51_nRegs; i++)
2507 if (strcmp (regs8051[i].base, "0") == 0)
2508 emitcode ("", "%s = 0x%02x",
2510 8 * rbank + regs8051[i].offset);
2512 emitcode ("", "%s = %s + 0x%02x",
2515 8 * rbank + regs8051[i].offset);
2519 /* if this is an interrupt service routine then
2520 save acc, b, dpl, dph */
2521 if (IFFUNC_ISISR (sym->type))
2524 if (!inExcludeList ("acc"))
2525 emitcode ("push", "acc");
2526 if (!inExcludeList ("b"))
2527 emitcode ("push", "b");
2528 if (!inExcludeList ("dpl"))
2529 emitcode ("push", "dpl");
2530 if (!inExcludeList ("dph"))
2531 emitcode ("push", "dph");
2532 /* if this isr has no bank i.e. is going to
2533 run with bank 0 , then we need to save more
2535 if (!FUNC_REGBANK (sym->type))
2538 /* if this function does not call any other
2539 function then we can be economical and
2540 save only those registers that are used */
2541 if (!IFFUNC_HASFCALL(sym->type))
2545 /* if any registers used */
2548 /* save the registers used */
2549 for (i = 0; i < sym->regsUsed->size; i++)
2551 if (bitVectBitValue (sym->regsUsed, i))
2552 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2559 /* this function has a function call. We cannot
2560 determines register usage so we will have to push the
2562 saveRBank (0, ic, FALSE);
2563 if (options.parms_in_bank1) {
2565 for (i=0; i < 8 ; i++ ) {
2566 emitcode ("push","%s",rb1regs[i]);
2573 /* This ISR uses a non-zero bank.
2575 * We assume that the bank is available for our
2578 * However, if this ISR calls a function which uses some
2579 * other bank, we must save that bank entirely.
2581 unsigned long banksToSave = 0;
2583 if (IFFUNC_HASFCALL(sym->type))
2586 #define MAX_REGISTER_BANKS 4
2591 for (i = ic; i; i = i->next)
2593 if (i->op == ENDFUNCTION)
2595 /* we got to the end OK. */
2603 dtype = operandType (IC_LEFT(i));
2605 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2607 /* Mark this bank for saving. */
2608 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2610 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2614 banksToSave |= (1 << FUNC_REGBANK(dtype));
2617 /* And note that we don't need to do it in
2625 /* This is a mess; we have no idea what
2626 * register bank the called function might
2629 * The only thing I can think of to do is
2630 * throw a warning and hope.
2632 werror(W_FUNCPTR_IN_USING_ISR);
2636 if (banksToSave && options.useXstack)
2638 /* Since we aren't passing it an ic,
2639 * saveRBank will assume r0 is available to abuse.
2641 * So switch to our (trashable) bank now, so
2642 * the caller's R0 isn't trashed.
2644 emitcode ("push", "psw");
2645 emitcode ("mov", "psw,#0x%02x",
2646 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2650 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2652 if (banksToSave & (1 << ix))
2654 saveRBank(ix, NULL, FALSE);
2658 // TODO: this needs a closer look
2659 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2662 /* Set the register bank to the desired value if nothing else */
2663 /* has done so yet. */
2666 emitcode ("push", "psw");
2667 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2672 /* This is a non-ISR function. The caller has already switched register */
2673 /* banks, if necessary, so just handle the callee-saves option. */
2675 /* if callee-save to be used for this function
2676 then save the registers being used in this function */
2677 if (IFFUNC_CALLEESAVES(sym->type))
2681 /* if any registers used */
2684 /* save the registers used */
2685 for (i = 0; i < sym->regsUsed->size; i++)
2687 if (bitVectBitValue (sym->regsUsed, i))
2689 /* remember one saved register for later usage */
2690 if (calleesaves_saved_register < 0)
2691 calleesaves_saved_register = i;
2692 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2701 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2704 if (options.useXstack)
2707 emitcode ("push", "acc");
2708 emitcode ("mov", "r0,%s", spname);
2709 emitcode ("mov", "a,_bp");
2710 emitcode ("movx", "@r0,a");
2711 emitcode ("inc", "%s", spname);
2713 emitcode ("pop", "acc");
2717 /* set up the stack */
2718 emitcode ("push", "_bp"); /* save the callers stack */
2720 emitcode ("mov", "_bp,%s", spname);
2723 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2724 /* before setting up the stack frame completely. */
2725 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2727 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2731 if (rsym && rsym->regType == REG_CND)
2733 if (rsym && (rsym->accuse || rsym->ruonly))
2735 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2736 rsym = rsym->usl.spillLoc;
2739 /* If the RECEIVE operand immediately spills to the first entry on the */
2740 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2741 /* rather than the usual @r0/r1 machinations. */
2742 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2746 _G.current_iCode = ric;
2747 D(emitcode ("; genReceive",""));
2748 for (ofs=0; ofs < sym->recvSize; ofs++)
2750 if (!strcmp (fReturn[ofs], "a"))
2751 emitcode ("push", "acc");
2753 emitcode ("push", fReturn[ofs]);
2755 stackAdjust -= sym->recvSize;
2758 assert (stackAdjust>=0);
2761 _G.current_iCode = ic;
2765 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2766 /* to free up the accumulator. */
2767 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2771 _G.current_iCode = ric;
2772 D(emitcode ("; genReceive",""));
2773 for (ofs=0; ofs < sym->recvSize; ofs++)
2775 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2777 _G.current_iCode = ic;
2783 /* adjust the stack for the function */
2787 int i = stackAdjust;
2789 werror (W_STACK_OVERFLOW, sym->name);
2791 if (i > 3 && accIsFree)
2794 emitcode ("mov", "a,sp");
2795 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796 emitcode ("mov", "sp,a");
2801 /* The accumulator is not free, so we will need another register */
2802 /* to clobber. No need to worry about a possible conflict with */
2803 /* the above early RECEIVE optimizations since they would have */
2804 /* freed the accumulator if they were generated. */
2806 if (IFFUNC_CALLEESAVES(sym->type))
2808 /* if it's a callee-saves function we need a saved register */
2809 if (calleesaves_saved_register >= 0)
2811 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2812 emitcode ("mov", "a,sp");
2813 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2814 emitcode ("mov", "sp,a");
2815 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2818 /* do it the hard way */
2820 emitcode ("inc", "sp");
2824 /* not callee-saves, we can clobber r0 */
2825 emitcode ("mov", "r0,a");
2826 emitcode ("mov", "a,sp");
2827 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2828 emitcode ("mov", "sp,a");
2829 emitcode ("mov", "a,r0");
2834 emitcode ("inc", "sp");
2841 emitcode ("push", "acc");
2842 emitcode ("mov", "a,_spx");
2843 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2844 emitcode ("mov", "_spx,a");
2846 emitcode ("pop", "acc");
2849 /* if critical function then turn interrupts off */
2850 if (IFFUNC_ISCRITICAL (ftype))
2852 symbol *tlbl = newiTempLabel (NULL);
2853 emitcode ("setb", "c");
2854 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2855 emitcode ("clr", "c");
2856 emitcode ("", "%05d$:", (tlbl->key + 100));
2857 emitcode ("push", "psw"); /* save old ea via c in psw */
2861 /*-----------------------------------------------------------------*/
2862 /* genEndFunction - generates epilogue for functions */
2863 /*-----------------------------------------------------------------*/
2865 genEndFunction (iCode * ic)
2867 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 lineNode *lnp = lineCurr;
2870 bitVect *regsUsedPrologue;
2871 bitVect *regsUnneeded;
2874 _G.currentFunc = NULL;
2875 if (IFFUNC_ISNAKED(sym->type))
2877 emitcode(";", "naked function: no epilogue.");
2878 if (options.debug && currFunc)
2879 debugFile->writeEndFunction (currFunc, ic, 0);
2883 if (IFFUNC_ISCRITICAL (sym->type))
2885 emitcode ("pop", "psw"); /* restore ea via c in psw */
2886 emitcode ("mov", "ea,c");
2889 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2891 emitcode ("mov", "%s,_bp", spname);
2894 /* if use external stack but some variables were
2895 added to the local stack then decrement the
2897 if (options.useXstack && sym->stack)
2899 emitcode ("mov", "a,sp");
2900 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2901 emitcode ("mov", "sp,a");
2905 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2907 if (options.useXstack)
2909 emitcode ("mov", "r0,%s", spname);
2910 emitcode ("movx", "a,@r0");
2911 emitcode ("mov", "_bp,a");
2912 emitcode ("dec", "%s", spname);
2916 emitcode ("pop", "_bp");
2920 /* restore the register bank */
2921 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2923 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2924 || !options.useXstack)
2926 /* Special case of ISR using non-zero bank with useXstack
2929 emitcode ("pop", "psw");
2933 if (IFFUNC_ISISR (sym->type))
2936 /* now we need to restore the registers */
2937 /* if this isr has no bank i.e. is going to
2938 run with bank 0 , then we need to save more
2940 if (!FUNC_REGBANK (sym->type))
2942 /* if this function does not call any other
2943 function then we can be economical and
2944 save only those registers that are used */
2945 if (!IFFUNC_HASFCALL(sym->type))
2949 /* if any registers used */
2952 /* save the registers used */
2953 for (i = sym->regsUsed->size; i >= 0; i--)
2955 if (bitVectBitValue (sym->regsUsed, i))
2956 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2962 if (options.parms_in_bank1) {
2964 for (i = 7 ; i >= 0 ; i-- ) {
2965 emitcode ("pop","%s",rb1regs[i]);
2968 /* this function has a function call cannot
2969 determines register usage so we will have to pop the
2971 unsaveRBank (0, ic, FALSE);
2976 /* This ISR uses a non-zero bank.
2978 * Restore any register banks saved by genFunction
2981 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2984 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2986 if (savedBanks & (1 << ix))
2988 unsaveRBank(ix, NULL, FALSE);
2992 if (options.useXstack)
2994 /* Restore bank AFTER calling unsaveRBank,
2995 * since it can trash r0.
2997 emitcode ("pop", "psw");
3001 if (!inExcludeList ("dph"))
3002 emitcode ("pop", "dph");
3003 if (!inExcludeList ("dpl"))
3004 emitcode ("pop", "dpl");
3005 if (!inExcludeList ("b"))
3006 emitcode ("pop", "b");
3007 if (!inExcludeList ("acc"))
3008 emitcode ("pop", "acc");
3010 /* if debug then send end of function */
3011 if (options.debug && currFunc)
3013 debugFile->writeEndFunction (currFunc, ic, 1);
3016 emitcode ("reti", "");
3020 if (IFFUNC_CALLEESAVES(sym->type))
3024 /* if any registers used */
3027 /* save the registers used */
3028 for (i = sym->regsUsed->size; i >= 0; i--)
3030 if (bitVectBitValue (sym->regsUsed, i) ||
3031 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3032 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3035 else if (mcs51_ptrRegReq)
3037 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3038 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3043 /* if debug then send end of function */
3044 if (options.debug && currFunc)
3046 debugFile->writeEndFunction (currFunc, ic, 1);
3049 emitcode ("ret", "");
3052 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3055 /* If this was an interrupt handler using bank 0 that called another */
3056 /* function, then all registers must be saved; nothing to optimized. */
3057 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3058 && !FUNC_REGBANK(sym->type))
3061 /* There are no push/pops to optimize if not callee-saves or ISR */
3062 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3065 /* If there were stack parameters, we cannot optimize without also */
3066 /* fixing all of the stack offsets; this is too dificult to consider. */
3067 if (FUNC_HASSTACKPARM(sym->type))
3070 /* Compute the registers actually used */
3071 regsUsed = newBitVect (mcs51_nRegs);
3072 regsUsedPrologue = newBitVect (mcs51_nRegs);
3075 if (lnp->ic && lnp->ic->op == FUNCTION)
3076 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3078 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3080 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3081 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3088 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3089 && !bitVectBitValue (regsUsed, CND_IDX))
3091 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3092 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3093 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3094 bitVectUnSetBit (regsUsed, CND_IDX);
3097 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3099 /* If this was an interrupt handler that called another function */
3100 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3101 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3103 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3104 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3105 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3106 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3107 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3110 /* Remove the unneeded push/pops */
3111 regsUnneeded = newBitVect (mcs51_nRegs);
3114 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3116 if (!strncmp(lnp->line, "push", 4))
3118 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3119 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3121 connectLine (lnp->prev, lnp->next);
3122 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3125 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3127 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3128 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3130 connectLine (lnp->prev, lnp->next);
3131 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3138 for (idx = 0; idx < regsUnneeded->size; idx++)
3139 if (bitVectBitValue (regsUnneeded, idx))
3140 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3142 freeBitVect (regsUnneeded);
3143 freeBitVect (regsUsed);
3144 freeBitVect (regsUsedPrologue);
3147 /*-----------------------------------------------------------------*/
3148 /* genRet - generate code for return statement */
3149 /*-----------------------------------------------------------------*/
3153 int size, offset = 0, pushed = 0;
3155 D(emitcode ("; genRet",""));
3157 /* if we have no return value then
3158 just generate the "ret" */
3162 /* we have something to return then
3163 move the return value into place */
3164 aopOp (IC_LEFT (ic), ic, FALSE);
3165 size = AOP_SIZE (IC_LEFT (ic));
3170 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3173 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3175 emitcode ("push", "%s", l);
3180 l = aopGet (AOP (IC_LEFT (ic)), offset,
3182 if (strcmp (fReturn[offset], l))
3183 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3192 if (strcmp (fReturn[pushed], "a"))
3193 emitcode ("pop", fReturn[pushed]);
3195 emitcode ("pop", "acc");
3198 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3201 /* generate a jump to the return label
3202 if the next is not the return statement */
3203 if (!(ic->next && ic->next->op == LABEL &&
3204 IC_LABEL (ic->next) == returnLabel))
3206 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3210 /*-----------------------------------------------------------------*/
3211 /* genLabel - generates a label */
3212 /*-----------------------------------------------------------------*/
3214 genLabel (iCode * ic)
3216 /* special case never generate */
3217 if (IC_LABEL (ic) == entryLabel)
3220 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3223 /*-----------------------------------------------------------------*/
3224 /* genGoto - generates a ljmp */
3225 /*-----------------------------------------------------------------*/
3227 genGoto (iCode * ic)
3229 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3232 /*-----------------------------------------------------------------*/
3233 /* findLabelBackwards: walks back through the iCode chain looking */
3234 /* for the given label. Returns number of iCode instructions */
3235 /* between that label and given ic. */
3236 /* Returns zero if label not found. */
3237 /*-----------------------------------------------------------------*/
3239 findLabelBackwards (iCode * ic, int key)
3248 /* If we have any pushes or pops, we cannot predict the distance.
3249 I don't like this at all, this should be dealt with in the
3251 if (ic->op == IPUSH || ic->op == IPOP) {
3255 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3264 /*-----------------------------------------------------------------*/
3265 /* genPlusIncr :- does addition with increment if possible */
3266 /*-----------------------------------------------------------------*/
3268 genPlusIncr (iCode * ic)
3270 unsigned int icount;
3271 unsigned int size = getDataSize (IC_RESULT (ic));
3273 /* will try to generate an increment */
3274 /* if the right side is not a literal
3276 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3279 /* if the literal value of the right hand side
3280 is greater than 4 then it is not worth it */
3281 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3284 D(emitcode ("; genPlusIncr",""));
3286 /* if increment >=16 bits in register or direct space */
3287 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3288 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3296 /* If the next instruction is a goto and the goto target
3297 * is < 10 instructions previous to this, we can generate
3298 * jumps straight to that target.
3300 if (ic->next && ic->next->op == GOTO
3301 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3302 && labelRange <= 10)
3304 emitcode (";", "tail increment optimized");
3305 tlbl = IC_LABEL (ic->next);
3310 tlbl = newiTempLabel (NULL);
3313 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3314 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3315 IS_AOP_PREG (IC_RESULT (ic)))
3316 emitcode ("cjne", "%s,#0x00,%05d$",
3317 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3321 emitcode ("clr", "a");
3322 emitcode ("cjne", "a,%s,%05d$",
3323 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3327 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3330 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3331 IS_AOP_PREG (IC_RESULT (ic)))
3332 emitcode ("cjne", "%s,#0x00,%05d$",
3333 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3336 emitcode ("cjne", "a,%s,%05d$",
3337 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3340 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3344 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3345 IS_AOP_PREG (IC_RESULT (ic)))
3346 emitcode ("cjne", "%s,#0x00,%05d$",
3347 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3351 emitcode ("cjne", "a,%s,%05d$",
3352 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3355 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3360 emitcode ("", "%05d$:", tlbl->key + 100);
3365 /* if the sizes are greater than 1 then we cannot */
3366 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3367 AOP_SIZE (IC_LEFT (ic)) > 1)
3370 /* we can if the aops of the left & result match or
3371 if they are in registers and the registers are the
3373 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3378 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3379 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3380 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3386 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3395 /*-----------------------------------------------------------------*/
3396 /* outBitAcc - output a bit in acc */
3397 /*-----------------------------------------------------------------*/
3399 outBitAcc (operand * result)
3401 symbol *tlbl = newiTempLabel (NULL);
3402 /* if the result is a bit */
3403 if (AOP_TYPE (result) == AOP_CRY)
3405 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3409 emitcode ("jz", "%05d$", tlbl->key + 100);
3410 emitcode ("mov", "a,%s", one);
3411 emitcode ("", "%05d$:", tlbl->key + 100);
3416 /*-----------------------------------------------------------------*/
3417 /* genPlusBits - generates code for addition of two bits */
3418 /*-----------------------------------------------------------------*/
3420 genPlusBits (iCode * ic)
3422 D(emitcode ("; genPlusBits",""));
3424 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3426 symbol *lbl = newiTempLabel (NULL);
3427 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3428 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3429 emitcode ("cpl", "c");
3430 emitcode ("", "%05d$:", (lbl->key + 100));
3431 outBitC (IC_RESULT (ic));
3435 emitcode ("clr", "a");
3436 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3437 emitcode ("rlc", "a");
3438 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3439 emitcode ("addc", "a,#0x00");
3440 outAcc (IC_RESULT (ic));
3445 /* This is the original version of this code.
3447 * This is being kept around for reference,
3448 * because I am not entirely sure I got it right...
3451 adjustArithmeticResult (iCode * ic)
3453 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3454 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3455 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3456 aopPut (AOP (IC_RESULT (ic)),
3457 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3459 isOperandVolatile (IC_RESULT (ic), FALSE));
3461 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3462 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3463 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3464 aopPut (AOP (IC_RESULT (ic)),
3465 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3467 isOperandVolatile (IC_RESULT (ic), FALSE));
3469 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3470 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3471 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3476 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3477 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3481 /* This is the pure and virtuous version of this code.
3482 * I'm pretty certain it's right, but not enough to toss the old
3486 adjustArithmeticResult (iCode * ic)
3488 if (opIsGptr (IC_RESULT (ic)) &&
3489 opIsGptr (IC_LEFT (ic)) &&
3490 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3492 aopPut (AOP (IC_RESULT (ic)),
3493 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3495 isOperandVolatile (IC_RESULT (ic), FALSE));
3498 if (opIsGptr (IC_RESULT (ic)) &&
3499 opIsGptr (IC_RIGHT (ic)) &&
3500 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3502 aopPut (AOP (IC_RESULT (ic)),
3503 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3505 isOperandVolatile (IC_RESULT (ic), FALSE));
3508 if (opIsGptr (IC_RESULT (ic)) &&
3509 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3510 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3511 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3512 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3515 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3516 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3521 /*-----------------------------------------------------------------*/
3522 /* genPlus - generates code for addition */
3523 /*-----------------------------------------------------------------*/
3525 genPlus (iCode * ic)
3527 int size, offset = 0;
3530 asmop *leftOp, *rightOp;
3533 /* special cases :- */
3535 D(emitcode ("; genPlus",""));
3537 aopOp (IC_LEFT (ic), ic, FALSE);
3538 aopOp (IC_RIGHT (ic), ic, FALSE);
3539 aopOp (IC_RESULT (ic), ic, TRUE);
3541 /* if literal, literal on the right or
3542 if left requires ACC or right is already
3544 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3545 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3546 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3548 operand *t = IC_RIGHT (ic);
3549 IC_RIGHT (ic) = IC_LEFT (ic);
3553 /* if both left & right are in bit
3555 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3556 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3562 /* if left in bit space & right literal */
3563 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3564 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3566 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3567 /* if result in bit space */
3568 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3570 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3571 emitcode ("cpl", "c");
3572 outBitC (IC_RESULT (ic));
3576 size = getDataSize (IC_RESULT (ic));
3579 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3580 emitcode ("addc", "a,#00");
3581 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3587 /* if I can do an increment instead
3588 of add then GOOD for ME */
3589 if (genPlusIncr (ic) == TRUE)
3592 size = getDataSize (IC_RESULT (ic));
3593 leftOp = AOP(IC_LEFT(ic));
3594 rightOp = AOP(IC_RIGHT(ic));
3597 /* if this is an add for an array access
3598 at a 256 byte boundary */
3600 && AOP_TYPE (op) == AOP_IMMD
3602 && IS_SPEC (OP_SYM_ETYPE (op))
3603 && SPEC_ABSA (OP_SYM_ETYPE (op))
3604 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3607 D(emitcode ("; genPlus aligned array",""));
3608 aopPut (AOP (IC_RESULT (ic)),
3609 aopGet (rightOp, 0, FALSE, FALSE),
3611 isOperandVolatile (IC_RESULT (ic), FALSE));
3613 if( 1 == getDataSize (IC_RIGHT (ic)) )
3615 aopPut (AOP (IC_RESULT (ic)),
3616 aopGet (leftOp, 1, FALSE, FALSE),
3618 isOperandVolatile (IC_RESULT (ic), FALSE));
3622 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3623 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3624 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3629 /* if the lower bytes of a literal are zero skip the addition */
3630 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3632 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3633 (skip_bytes+1 < size))
3638 D(emitcode ("; genPlus shortcut",""));
3643 if( offset >= skip_bytes )
3645 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3647 emitcode("mov", "b,a");
3648 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3649 emitcode("xch", "a,b");
3650 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3651 emitcode (add, "a,b");
3653 else if (aopGetUsesAcc (leftOp, offset))
3655 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3656 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3660 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3661 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3663 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3664 add = "addc"; /* further adds must propagate carry */
3668 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3669 isOperandVolatile (IC_RESULT (ic), FALSE))
3672 aopPut (AOP (IC_RESULT (ic)),
3673 aopGet (leftOp, offset, FALSE, FALSE),
3675 isOperandVolatile (IC_RESULT (ic), FALSE));
3681 adjustArithmeticResult (ic);
3684 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3685 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3689 /*-----------------------------------------------------------------*/
3690 /* genMinusDec :- does subtraction with deccrement if possible */
3691 /*-----------------------------------------------------------------*/
3693 genMinusDec (iCode * ic)
3695 unsigned int icount;
3696 unsigned int size = getDataSize (IC_RESULT (ic));
3698 /* will try to generate an increment */
3699 /* if the right side is not a literal
3701 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3704 /* if the literal value of the right hand side
3705 is greater than 4 then it is not worth it */
3706 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3709 D(emitcode ("; genMinusDec",""));
3711 /* if decrement >=16 bits in register or direct space */
3712 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3713 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3721 /* If the next instruction is a goto and the goto target
3722 * is <= 10 instructions previous to this, we can generate
3723 * jumps straight to that target.
3725 if (ic->next && ic->next->op == GOTO
3726 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3727 && labelRange <= 10)
3729 emitcode (";", "tail decrement optimized");
3730 tlbl = IC_LABEL (ic->next);
3735 tlbl = newiTempLabel (NULL);
3739 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3740 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3741 IS_AOP_PREG (IC_RESULT (ic)))
3742 emitcode ("cjne", "%s,#0xff,%05d$"
3743 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3747 emitcode ("mov", "a,#0xff");
3748 emitcode ("cjne", "a,%s,%05d$"
3749 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3752 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3755 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3756 IS_AOP_PREG (IC_RESULT (ic)))
3757 emitcode ("cjne", "%s,#0xff,%05d$"
3758 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3762 emitcode ("cjne", "a,%s,%05d$"
3763 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3766 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3770 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3771 IS_AOP_PREG (IC_RESULT (ic)))
3772 emitcode ("cjne", "%s,#0xff,%05d$"
3773 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3777 emitcode ("cjne", "a,%s,%05d$"
3778 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3781 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3785 emitcode ("", "%05d$:", tlbl->key + 100);
3790 /* if the sizes are greater than 1 then we cannot */
3791 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3792 AOP_SIZE (IC_LEFT (ic)) > 1)
3795 /* we can if the aops of the left & result match or
3796 if they are in registers and the registers are the
3798 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3802 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3810 /*-----------------------------------------------------------------*/
3811 /* addSign - complete with sign */
3812 /*-----------------------------------------------------------------*/
3814 addSign (operand * result, int offset, int sign)
3816 int size = (getDataSize (result) - offset);
3821 emitcode ("rlc", "a");
3822 emitcode ("subb", "a,acc");
3824 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3828 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3832 /*-----------------------------------------------------------------*/
3833 /* genMinusBits - generates code for subtraction of two bits */
3834 /*-----------------------------------------------------------------*/
3836 genMinusBits (iCode * ic)
3838 symbol *lbl = newiTempLabel (NULL);
3840 D(emitcode ("; genMinusBits",""));
3842 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3844 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3845 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3846 emitcode ("cpl", "c");
3847 emitcode ("", "%05d$:", (lbl->key + 100));
3848 outBitC (IC_RESULT (ic));
3852 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3853 emitcode ("subb", "a,acc");
3854 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3855 emitcode ("inc", "a");
3856 emitcode ("", "%05d$:", (lbl->key + 100));
3857 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3858 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3862 /*-----------------------------------------------------------------*/
3863 /* genMinus - generates code for subtraction */
3864 /*-----------------------------------------------------------------*/
3866 genMinus (iCode * ic)
3868 int size, offset = 0;
3870 D(emitcode ("; genMinus",""));
3872 aopOp (IC_LEFT (ic), ic, FALSE);
3873 aopOp (IC_RIGHT (ic), ic, FALSE);
3874 aopOp (IC_RESULT (ic), ic, TRUE);
3876 /* special cases :- */
3877 /* if both left & right are in bit space */
3878 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3879 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3885 /* if I can do an decrement instead
3886 of subtract then GOOD for ME */
3887 if (genMinusDec (ic) == TRUE)
3890 size = getDataSize (IC_RESULT (ic));
3892 /* if literal, add a,#-lit, else normal subb */
3893 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3895 unsigned long lit = 0L;
3897 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3902 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3903 /* first add without previous c */
3905 if (!size && lit== (unsigned long) -1) {
3906 emitcode ("dec", "a");
3908 emitcode ("add", "a,#0x%02x",
3909 (unsigned int) (lit & 0x0FFL));
3912 emitcode ("addc", "a,#0x%02x",
3913 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3915 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3920 asmop *leftOp, *rightOp;
3922 leftOp = AOP(IC_LEFT(ic));
3923 rightOp = AOP(IC_RIGHT(ic));
3927 if (aopGetUsesAcc(rightOp, offset)) {
3928 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3929 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3931 emitcode( "setb", "c");
3933 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3934 emitcode("cpl", "a");
3936 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3939 emitcode ("subb", "a,%s",
3940 aopGet(rightOp, offset, FALSE, TRUE));
3943 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3948 adjustArithmeticResult (ic);
3951 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3952 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3957 /*-----------------------------------------------------------------*/
3958 /* genMultbits :- multiplication of bits */
3959 /*-----------------------------------------------------------------*/
3961 genMultbits (operand * left,
3965 D(emitcode ("; genMultbits",""));
3967 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3968 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3972 /*-----------------------------------------------------------------*/
3973 /* genMultOneByte : 8*8=8/16 bit multiplication */
3974 /*-----------------------------------------------------------------*/
3976 genMultOneByte (operand * left,
3981 int size = AOP_SIZE (result);
3982 bool runtimeSign, compiletimeSign;
3983 bool lUnsigned, rUnsigned;
3985 D(emitcode ("; genMultOneByte",""));
3987 if (size < 1 || size > 2)
3989 /* this should never happen */
3990 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3991 AOP_SIZE(result), __FILE__, lineno);
3995 /* (if two literals: the value is computed before) */
3996 /* if one literal, literal on the right */
3997 if (AOP_TYPE (left) == AOP_LIT)
4002 /* emitcode (";", "swapped left and right"); */
4004 /* if no literal, unsigned on the right: shorter code */
4005 if ( AOP_TYPE (right) != AOP_LIT
4006 && SPEC_USIGN (getSpec (operandType (left))))
4013 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4014 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4016 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4017 no need to take care about the signedness! */
4018 || (lUnsigned && rUnsigned))
4020 /* just an unsigned 8 * 8 = 8 multiply
4022 /* emitcode (";","unsigned"); */
4023 /* TODO: check for accumulator clash between left & right aops? */
4025 if (AOP_TYPE (right) == AOP_LIT)
4027 /* moving to accumulator first helps peepholes */
4028 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4029 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4033 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4034 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4037 emitcode ("mul", "ab");
4038 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4040 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4044 /* we have to do a signed multiply */
4045 /* emitcode (";", "signed"); */
4047 /* now sign adjust for both left & right */
4049 /* let's see what's needed: */
4050 /* apply negative sign during runtime */
4051 runtimeSign = FALSE;
4052 /* negative sign from literals */
4053 compiletimeSign = FALSE;
4057 if (AOP_TYPE(left) == AOP_LIT)
4059 /* signed literal */
4060 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4062 compiletimeSign = TRUE;
4065 /* signed but not literal */
4071 if (AOP_TYPE(right) == AOP_LIT)
4073 /* signed literal */
4074 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4076 compiletimeSign ^= TRUE;
4079 /* signed but not literal */
4083 /* initialize F0, which stores the runtime sign */
4086 if (compiletimeSign)
4087 emitcode ("setb", "F0"); /* set sign flag */
4089 emitcode ("clr", "F0"); /* reset sign flag */
4092 /* save the signs of the operands */
4093 if (AOP_TYPE(right) == AOP_LIT)
4095 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4097 if (!rUnsigned && val < 0)
4098 emitcode ("mov", "b,#0x%02x", -val);
4100 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4102 else /* ! literal */
4104 if (rUnsigned) /* emitcode (";", "signed"); */
4106 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4109 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4110 lbl = newiTempLabel (NULL);
4111 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4112 emitcode ("cpl", "F0"); /* complement sign flag */
4113 emitcode ("cpl", "a"); /* 2's complement */
4114 emitcode ("inc", "a");
4115 emitcode ("", "%05d$:", (lbl->key + 100));
4116 emitcode ("mov", "b,a");
4120 if (AOP_TYPE(left) == AOP_LIT)
4122 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4124 if (!lUnsigned && val < 0)
4125 emitcode ("mov", "a,#0x%02x", -val);
4127 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4129 else /* ! literal */
4131 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4135 lbl = newiTempLabel (NULL);
4136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4137 emitcode ("cpl", "F0"); /* complement sign flag */
4138 emitcode ("cpl", "a"); /* 2's complement */
4139 emitcode ("inc", "a");
4140 emitcode ("", "%05d$:", (lbl->key + 100));
4144 /* now the multiplication */
4145 emitcode ("mul", "ab");
4146 if (runtimeSign || compiletimeSign)
4148 lbl = newiTempLabel (NULL);
4150 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4151 emitcode ("cpl", "a"); /* lsb 2's complement */
4153 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4156 emitcode ("add", "a,#1"); /* this sets carry flag */
4157 emitcode ("xch", "a,b");
4158 emitcode ("cpl", "a"); /* msb 2's complement */
4159 emitcode ("addc", "a,#0");
4160 emitcode ("xch", "a,b");
4162 emitcode ("", "%05d$:", (lbl->key + 100));
4164 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4166 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4169 /*-----------------------------------------------------------------*/
4170 /* genMult - generates code for multiplication */
4171 /*-----------------------------------------------------------------*/
4173 genMult (iCode * ic)
4175 operand *left = IC_LEFT (ic);
4176 operand *right = IC_RIGHT (ic);
4177 operand *result = IC_RESULT (ic);
4179 D(emitcode ("; genMult",""));
4181 /* assign the amsops */
4182 aopOp (left, ic, FALSE);
4183 aopOp (right, ic, FALSE);
4184 aopOp (result, ic, TRUE);
4186 /* special cases first */
4188 if (AOP_TYPE (left) == AOP_CRY &&
4189 AOP_TYPE (right) == AOP_CRY)
4191 genMultbits (left, right, result);
4195 /* if both are of size == 1 */
4196 #if 0 // one of them can be a sloc shared with the result
4197 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4199 if (getSize(operandType(left)) == 1 &&
4200 getSize(operandType(right)) == 1)
4203 genMultOneByte (left, right, result);
4207 /* should have been converted to function call */
4208 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4209 getSize(OP_SYMBOL(right)->type));
4213 freeAsmop (result, NULL, ic, TRUE);
4214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4218 /*-----------------------------------------------------------------*/
4219 /* genDivbits :- division of bits */
4220 /*-----------------------------------------------------------------*/
4222 genDivbits (operand * left,
4229 D(emitcode ("; genDivbits",""));
4231 /* the result must be bit */
4232 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4233 l = aopGet (AOP (left), 0, FALSE, FALSE);
4237 emitcode ("div", "ab");
4238 emitcode ("rrc", "a");
4239 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4242 /*-----------------------------------------------------------------*/
4243 /* genDivOneByte : 8 bit division */
4244 /*-----------------------------------------------------------------*/
4246 genDivOneByte (operand * left,
4250 bool lUnsigned, rUnsigned;
4251 bool runtimeSign, compiletimeSign;
4255 D(emitcode ("; genDivOneByte",""));
4257 /* Why is it necessary that genDivOneByte() can return an int result?
4260 volatile unsigned char uc;
4261 volatile signed char sc1, sc2;
4274 In all cases a one byte result would overflow, the following cast to int
4275 would return the wrong result.
4277 Two possible solution:
4278 a) cast operands to int, if ((unsigned) / (signed)) or
4279 ((signed) / (signed))
4280 b) return an 16 bit signed int; this is what we're doing here!
4283 size = AOP_SIZE (result) - 1;
4285 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4286 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4288 /* signed or unsigned */
4289 if (lUnsigned && rUnsigned)
4291 /* unsigned is easy */
4292 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4293 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4294 emitcode ("div", "ab");
4295 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4297 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4301 /* signed is a little bit more difficult */
4303 /* now sign adjust for both left & right */
4305 /* let's see what's needed: */
4306 /* apply negative sign during runtime */
4307 runtimeSign = FALSE;
4308 /* negative sign from literals */
4309 compiletimeSign = FALSE;
4313 if (AOP_TYPE(left) == AOP_LIT)
4315 /* signed literal */
4316 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4318 compiletimeSign = TRUE;
4321 /* signed but not literal */
4327 if (AOP_TYPE(right) == AOP_LIT)
4329 /* signed literal */
4330 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4332 compiletimeSign ^= TRUE;
4335 /* signed but not literal */
4339 /* initialize F0, which stores the runtime sign */
4342 if (compiletimeSign)
4343 emitcode ("setb", "F0"); /* set sign flag */
4345 emitcode ("clr", "F0"); /* reset sign flag */
4348 /* save the signs of the operands */
4349 if (AOP_TYPE(right) == AOP_LIT)
4351 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4353 if (!rUnsigned && val < 0)
4354 emitcode ("mov", "b,#0x%02x", -val);
4356 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4358 else /* ! literal */
4361 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4364 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4365 lbl = newiTempLabel (NULL);
4366 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4367 emitcode ("cpl", "F0"); /* complement sign flag */
4368 emitcode ("cpl", "a"); /* 2's complement */
4369 emitcode ("inc", "a");
4370 emitcode ("", "%05d$:", (lbl->key + 100));
4371 emitcode ("mov", "b,a");
4375 if (AOP_TYPE(left) == AOP_LIT)
4377 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4379 if (!lUnsigned && val < 0)
4380 emitcode ("mov", "a,#0x%02x", -val);
4382 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4384 else /* ! literal */
4386 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4390 lbl = newiTempLabel (NULL);
4391 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4392 emitcode ("cpl", "F0"); /* complement sign flag */
4393 emitcode ("cpl", "a"); /* 2's complement */
4394 emitcode ("inc", "a");
4395 emitcode ("", "%05d$:", (lbl->key + 100));
4399 /* now the division */
4400 emitcode ("div", "ab");
4402 if (runtimeSign || compiletimeSign)
4404 lbl = newiTempLabel (NULL);
4406 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4407 emitcode ("cpl", "a"); /* lsb 2's complement */
4408 emitcode ("inc", "a");
4409 emitcode ("", "%05d$:", (lbl->key + 100));
4411 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4414 /* msb is 0x00 or 0xff depending on the sign */
4417 emitcode ("mov", "c,F0");
4418 emitcode ("subb", "a,acc");
4420 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4422 else /* compiletimeSign */
4424 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4429 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4431 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4435 /*-----------------------------------------------------------------*/
4436 /* genDiv - generates code for division */
4437 /*-----------------------------------------------------------------*/
4441 operand *left = IC_LEFT (ic);
4442 operand *right = IC_RIGHT (ic);
4443 operand *result = IC_RESULT (ic);
4445 D(emitcode ("; genDiv",""));
4447 /* assign the amsops */
4448 aopOp (left, ic, FALSE);
4449 aopOp (right, ic, FALSE);
4450 aopOp (result, ic, TRUE);
4452 /* special cases first */
4454 if (AOP_TYPE (left) == AOP_CRY &&
4455 AOP_TYPE (right) == AOP_CRY)
4457 genDivbits (left, right, result);
4461 /* if both are of size == 1 */
4462 if (AOP_SIZE (left) == 1 &&
4463 AOP_SIZE (right) == 1)
4465 genDivOneByte (left, right, result);
4469 /* should have been converted to function call */
4472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474 freeAsmop (result, NULL, ic, TRUE);
4477 /*-----------------------------------------------------------------*/
4478 /* genModbits :- modulus of bits */
4479 /*-----------------------------------------------------------------*/
4481 genModbits (operand * left,
4488 D(emitcode ("; genModbits",""));
4490 /* the result must be bit */
4491 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4492 l = aopGet (AOP (left), 0, FALSE, FALSE);
4496 emitcode ("div", "ab");
4497 emitcode ("mov", "a,b");
4498 emitcode ("rrc", "a");
4499 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4502 /*-----------------------------------------------------------------*/
4503 /* genModOneByte : 8 bit modulus */
4504 /*-----------------------------------------------------------------*/
4506 genModOneByte (operand * left,
4510 bool lUnsigned, rUnsigned;
4511 bool runtimeSign, compiletimeSign;
4515 D(emitcode ("; genModOneByte",""));
4517 size = AOP_SIZE (result) - 1;
4519 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4520 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4522 /* signed or unsigned */
4523 if (lUnsigned && rUnsigned)
4525 /* unsigned is easy */
4526 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4527 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4528 emitcode ("div", "ab");
4529 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4531 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4535 /* signed is a little bit more difficult */
4537 /* now sign adjust for both left & right */
4539 /* modulus: sign of the right operand has no influence on the result! */
4540 if (AOP_TYPE(right) == AOP_LIT)
4542 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4544 if (!rUnsigned && val < 0)
4545 emitcode ("mov", "b,#0x%02x", -val);
4547 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4549 else /* not literal */
4552 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4555 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4556 lbl = newiTempLabel (NULL);
4557 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4558 emitcode ("cpl", "a"); /* 2's complement */
4559 emitcode ("inc", "a");
4560 emitcode ("", "%05d$:", (lbl->key + 100));
4561 emitcode ("mov", "b,a");
4565 /* let's see what's needed: */
4566 /* apply negative sign during runtime */
4567 runtimeSign = FALSE;
4568 /* negative sign from literals */
4569 compiletimeSign = FALSE;
4571 /* sign adjust left side */
4572 if (AOP_TYPE(left) == AOP_LIT)
4574 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4576 if (!lUnsigned && val < 0)
4578 compiletimeSign = TRUE; /* set sign flag */
4579 emitcode ("mov", "a,#0x%02x", -val);
4582 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4584 else /* ! literal */
4586 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4591 emitcode ("clr", "F0"); /* clear sign flag */
4593 lbl = newiTempLabel (NULL);
4594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4595 emitcode ("setb", "F0"); /* set sign flag */
4596 emitcode ("cpl", "a"); /* 2's complement */
4597 emitcode ("inc", "a");
4598 emitcode ("", "%05d$:", (lbl->key + 100));
4602 /* now the modulus */
4603 emitcode ("div", "ab");
4605 if (runtimeSign || compiletimeSign)
4607 emitcode ("mov", "a,b");
4608 lbl = newiTempLabel (NULL);
4610 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4611 emitcode ("cpl", "a"); /* 2's complement */
4612 emitcode ("inc", "a");
4613 emitcode ("", "%05d$:", (lbl->key + 100));
4615 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4618 /* msb is 0x00 or 0xff depending on the sign */
4621 emitcode ("mov", "c,F0");
4622 emitcode ("subb", "a,acc");
4624 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4626 else /* compiletimeSign */
4628 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4633 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4635 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4639 /*-----------------------------------------------------------------*/
4640 /* genMod - generates code for division */
4641 /*-----------------------------------------------------------------*/
4645 operand *left = IC_LEFT (ic);
4646 operand *right = IC_RIGHT (ic);
4647 operand *result = IC_RESULT (ic);
4649 D(emitcode ("; genMod",""));
4651 /* assign the amsops */
4652 aopOp (left, ic, FALSE);
4653 aopOp (right, ic, FALSE);
4654 aopOp (result, ic, TRUE);
4656 /* special cases first */
4658 if (AOP_TYPE (left) == AOP_CRY &&
4659 AOP_TYPE (right) == AOP_CRY)
4661 genModbits (left, right, result);
4665 /* if both are of size == 1 */
4666 if (AOP_SIZE (left) == 1 &&
4667 AOP_SIZE (right) == 1)
4669 genModOneByte (left, right, result);
4673 /* should have been converted to function call */
4677 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (result, NULL, ic, TRUE);
4682 /*-----------------------------------------------------------------*/
4683 /* genIfxJump :- will create a jump depending on the ifx */
4684 /*-----------------------------------------------------------------*/
4686 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4689 symbol *tlbl = newiTempLabel (NULL);
4692 D(emitcode ("; genIfxJump",""));
4694 /* if true label then we jump if condition
4698 jlbl = IC_TRUE (ic);
4699 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4700 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4704 /* false label is present */
4705 jlbl = IC_FALSE (ic);
4706 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4707 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4709 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4710 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4712 emitcode (inst, "%05d$", tlbl->key + 100);
4713 freeForBranchAsmop (result);
4714 freeForBranchAsmop (right);
4715 freeForBranchAsmop (left);
4716 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4717 emitcode ("", "%05d$:", tlbl->key + 100);
4719 /* mark the icode as generated */
4723 /*-----------------------------------------------------------------*/
4724 /* genCmp :- greater or less than comparison */
4725 /*-----------------------------------------------------------------*/
4727 genCmp (operand * left, operand * right,
4728 operand * result, iCode * ifx, int sign, iCode *ic)
4730 int size, offset = 0;
4731 unsigned long lit = 0L;
4734 D(emitcode ("; genCmp",""));
4736 /* if left & right are bit variables */
4737 if (AOP_TYPE (left) == AOP_CRY &&
4738 AOP_TYPE (right) == AOP_CRY)
4740 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4741 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4745 /* subtract right from left if at the
4746 end the carry flag is set then we know that
4747 left is greater than right */
4748 size = max (AOP_SIZE (left), AOP_SIZE (right));
4750 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4751 if ((size == 1) && !sign &&
4752 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4754 symbol *lbl = newiTempLabel (NULL);
4755 emitcode ("cjne", "%s,%s,%05d$",
4756 aopGet (AOP (left), offset, FALSE, FALSE),
4757 aopGet (AOP (right), offset, FALSE, FALSE),
4759 emitcode ("", "%05d$:", lbl->key + 100);
4763 if (AOP_TYPE (right) == AOP_LIT)
4765 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4766 /* optimize if(x < 0) or if(x >= 0) */
4775 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4776 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4778 genIfxJump (ifx, "acc.7", left, right, result);
4779 freeAsmop (right, NULL, ic, TRUE);
4780 freeAsmop (left, NULL, ic, TRUE);
4785 emitcode ("rlc", "a");
4793 rightInB = aopGetUsesAcc(AOP (right), offset);
4795 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4796 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4797 if (sign && size == 0)
4799 emitcode ("xrl", "a,#0x80");
4800 if (AOP_TYPE (right) == AOP_LIT)
4802 unsigned long lit = (unsigned long)
4803 floatFromVal (AOP (right)->aopu.aop_lit);
4804 emitcode ("subb", "a,#0x%02x",
4805 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4810 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4811 emitcode ("xrl", "b,#0x80");
4812 emitcode ("subb", "a,b");
4818 emitcode ("subb", "a,b");
4820 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4836 /* if the result is used in the next
4837 ifx conditional branch then generate
4838 code a little differently */
4840 genIfxJump (ifx, "c", NULL, NULL, result);
4843 /* leave the result in acc */
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpGt :- greater than comparison */
4849 /*-----------------------------------------------------------------*/
4851 genCmpGt (iCode * ic, iCode * ifx)
4853 operand *left, *right, *result;
4854 sym_link *letype, *retype;
4857 D(emitcode ("; genCmpGt",""));
4859 left = IC_LEFT (ic);
4860 right = IC_RIGHT (ic);
4861 result = IC_RESULT (ic);
4863 letype = getSpec (operandType (left));
4864 retype = getSpec (operandType (right));
4865 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4866 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4867 /* assign the amsops */
4868 aopOp (left, ic, FALSE);
4869 aopOp (right, ic, FALSE);
4870 aopOp (result, ic, TRUE);
4872 genCmp (right, left, result, ifx, sign,ic);
4874 freeAsmop (result, NULL, ic, TRUE);
4877 /*-----------------------------------------------------------------*/
4878 /* genCmpLt - less than comparisons */
4879 /*-----------------------------------------------------------------*/
4881 genCmpLt (iCode * ic, iCode * ifx)
4883 operand *left, *right, *result;
4884 sym_link *letype, *retype;
4887 D(emitcode ("; genCmpLt",""));
4889 left = IC_LEFT (ic);
4890 right = IC_RIGHT (ic);
4891 result = IC_RESULT (ic);
4893 letype = getSpec (operandType (left));
4894 retype = getSpec (operandType (right));
4895 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4896 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4897 /* assign the amsops */
4898 aopOp (left, ic, FALSE);
4899 aopOp (right, ic, FALSE);
4900 aopOp (result, ic, TRUE);
4902 genCmp (left, right, result, ifx, sign,ic);
4904 freeAsmop (result, NULL, ic, TRUE);
4907 /*-----------------------------------------------------------------*/
4908 /* gencjneshort - compare and jump if not equal */
4909 /*-----------------------------------------------------------------*/
4911 gencjneshort (operand * left, operand * right, symbol * lbl)
4913 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4915 unsigned long lit = 0L;
4917 /* if the left side is a literal or
4918 if the right is in a pointer register and left
4920 if ((AOP_TYPE (left) == AOP_LIT) ||
4921 (AOP_TYPE (left) == AOP_IMMD) ||
4922 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4929 if (AOP_TYPE (right) == AOP_LIT)
4930 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4932 /* if the right side is a literal then anything goes */
4933 if (AOP_TYPE (right) == AOP_LIT &&
4934 AOP_TYPE (left) != AOP_DIR &&
4935 AOP_TYPE (left) != AOP_IMMD)
4939 emitcode ("cjne", "%s,%s,%05d$",
4940 aopGet (AOP (left), offset, FALSE, FALSE),
4941 aopGet (AOP (right), offset, FALSE, FALSE),
4947 /* if the right side is in a register or in direct space or
4948 if the left is a pointer register & right is not */
4949 else if (AOP_TYPE (right) == AOP_REG ||
4950 AOP_TYPE (right) == AOP_DIR ||
4951 AOP_TYPE (right) == AOP_LIT ||
4952 AOP_TYPE (right) == AOP_IMMD ||
4953 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4954 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4958 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4959 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4960 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4961 emitcode ("jnz", "%05d$", lbl->key + 100);
4963 emitcode ("cjne", "a,%s,%05d$",
4964 aopGet (AOP (right), offset, FALSE, TRUE),
4971 /* right is a pointer reg need both a & b */
4974 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4975 if (strcmp (l, "b"))
4976 emitcode ("mov", "b,%s", l);
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4984 /*-----------------------------------------------------------------*/
4985 /* gencjne - compare and jump if not equal */
4986 /*-----------------------------------------------------------------*/
4988 gencjne (operand * left, operand * right, symbol * lbl)
4990 symbol *tlbl = newiTempLabel (NULL);
4992 gencjneshort (left, right, lbl);
4994 emitcode ("mov", "a,%s", one);
4995 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4996 emitcode ("", "%05d$:", lbl->key + 100);
4997 emitcode ("clr", "a");
4998 emitcode ("", "%05d$:", tlbl->key + 100);
5001 /*-----------------------------------------------------------------*/
5002 /* genCmpEq - generates code for equal to */
5003 /*-----------------------------------------------------------------*/
5005 genCmpEq (iCode * ic, iCode * ifx)
5007 operand *left, *right, *result;
5009 D(emitcode ("; genCmpEq",""));
5011 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5012 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5013 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5015 /* if literal, literal on the right or
5016 if the right is in a pointer register and left
5018 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5019 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5021 operand *t = IC_RIGHT (ic);
5022 IC_RIGHT (ic) = IC_LEFT (ic);
5026 if (ifx && !AOP_SIZE (result))
5029 /* if they are both bit variables */
5030 if (AOP_TYPE (left) == AOP_CRY &&
5031 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5033 if (AOP_TYPE (right) == AOP_LIT)
5035 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5039 emitcode ("cpl", "c");
5043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5047 emitcode ("clr", "c");
5049 /* AOP_TYPE(right) == AOP_CRY */
5053 symbol *lbl = newiTempLabel (NULL);
5054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5055 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5056 emitcode ("cpl", "c");
5057 emitcode ("", "%05d$:", (lbl->key + 100));
5059 /* if true label then we jump if condition
5061 tlbl = newiTempLabel (NULL);
5064 emitcode ("jnc", "%05d$", tlbl->key + 100);
5065 freeForBranchAsmop (result);
5066 freeForBranchAsmop (right);
5067 freeForBranchAsmop (left);
5068 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5072 emitcode ("jc", "%05d$", tlbl->key + 100);
5073 freeForBranchAsmop (result);
5074 freeForBranchAsmop (right);
5075 freeForBranchAsmop (left);
5076 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5082 tlbl = newiTempLabel (NULL);
5083 gencjneshort (left, right, tlbl);
5086 freeForBranchAsmop (result);
5087 freeForBranchAsmop (right);
5088 freeForBranchAsmop (left);
5089 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5090 emitcode ("", "%05d$:", tlbl->key + 100);
5094 symbol *lbl = newiTempLabel (NULL);
5095 emitcode ("sjmp", "%05d$", lbl->key + 100);
5096 emitcode ("", "%05d$:", tlbl->key + 100);
5097 freeForBranchAsmop (result);
5098 freeForBranchAsmop (right);
5099 freeForBranchAsmop (left);
5100 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5101 emitcode ("", "%05d$:", lbl->key + 100);
5104 /* mark the icode as generated */
5109 /* if they are both bit variables */
5110 if (AOP_TYPE (left) == AOP_CRY &&
5111 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5113 if (AOP_TYPE (right) == AOP_LIT)
5115 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5118 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119 emitcode ("cpl", "c");
5123 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5127 emitcode ("clr", "c");
5129 /* AOP_TYPE(right) == AOP_CRY */
5133 symbol *lbl = newiTempLabel (NULL);
5134 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5135 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5136 emitcode ("cpl", "c");
5137 emitcode ("", "%05d$:", (lbl->key + 100));
5140 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5147 genIfxJump (ifx, "c", left, right, result);
5150 /* if the result is used in an arithmetic operation
5151 then put the result in place */
5156 gencjne (left, right, newiTempLabel (NULL));
5157 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5159 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5164 genIfxJump (ifx, "a", left, right, result);
5167 /* if the result is used in an arithmetic operation
5168 then put the result in place */
5169 if (AOP_TYPE (result) != AOP_CRY)
5171 /* leave the result in acc */
5175 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177 freeAsmop (result, NULL, ic, TRUE);
5180 /*-----------------------------------------------------------------*/
5181 /* ifxForOp - returns the icode containing the ifx for operand */
5182 /*-----------------------------------------------------------------*/
5184 ifxForOp (operand * op, iCode * ic)
5186 /* if true symbol then needs to be assigned */
5187 if (IS_TRUE_SYMOP (op))
5190 /* if this has register type condition and
5191 the next instruction is ifx with the same operand
5192 and live to of the operand is upto the ifx only then */
5194 ic->next->op == IFX &&
5195 IC_COND (ic->next)->key == op->key &&
5196 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5202 /*-----------------------------------------------------------------*/
5203 /* hasInc - operand is incremented before any other use */
5204 /*-----------------------------------------------------------------*/
5206 hasInc (operand *op, iCode *ic,int osize)
5208 sym_link *type = operandType(op);
5209 sym_link *retype = getSpec (type);
5210 iCode *lic = ic->next;
5213 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5214 if (!IS_SYMOP(op)) return NULL;
5216 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5217 if (IS_AGGREGATE(type->next)) return NULL;
5218 if (osize != (isize = getSize(type->next))) return NULL;
5221 /* if operand of the form op = op + <sizeof *op> */
5222 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5223 isOperandEqual(IC_RESULT(lic),op) &&
5224 isOperandLiteral(IC_RIGHT(lic)) &&
5225 operandLitValue(IC_RIGHT(lic)) == isize) {
5228 /* if the operand used or deffed */
5229 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5232 /* if GOTO or IFX */
5233 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5239 /*-----------------------------------------------------------------*/
5240 /* genAndOp - for && operation */
5241 /*-----------------------------------------------------------------*/
5243 genAndOp (iCode * ic)
5245 operand *left, *right, *result;
5248 D(emitcode ("; genAndOp",""));
5250 /* note here that && operations that are in an
5251 if statement are taken away by backPatchLabels
5252 only those used in arthmetic operations remain */
5253 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5254 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5255 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5257 /* if both are bit variables */
5258 if (AOP_TYPE (left) == AOP_CRY &&
5259 AOP_TYPE (right) == AOP_CRY)
5261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5267 tlbl = newiTempLabel (NULL);
5269 emitcode ("jz", "%05d$", tlbl->key + 100);
5271 emitcode ("", "%05d$:", tlbl->key + 100);
5275 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5276 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277 freeAsmop (result, NULL, ic, TRUE);
5281 /*-----------------------------------------------------------------*/
5282 /* genOrOp - for || operation */
5283 /*-----------------------------------------------------------------*/
5285 genOrOp (iCode * ic)
5287 operand *left, *right, *result;
5290 D(emitcode ("; genOrOp",""));
5292 /* note here that || operations that are in an
5293 if statement are taken away by backPatchLabels
5294 only those used in arthmetic operations remain */
5295 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5296 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5297 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5299 /* if both are bit variables */
5300 if (AOP_TYPE (left) == AOP_CRY &&
5301 AOP_TYPE (right) == AOP_CRY)
5303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5309 tlbl = newiTempLabel (NULL);
5311 emitcode ("jnz", "%05d$", tlbl->key + 100);
5313 emitcode ("", "%05d$:", tlbl->key + 100);
5317 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5319 freeAsmop (result, NULL, ic, TRUE);
5322 /*-----------------------------------------------------------------*/
5323 /* isLiteralBit - test if lit == 2^n */
5324 /*-----------------------------------------------------------------*/
5326 isLiteralBit (unsigned long lit)
5328 unsigned long pw[32] =
5329 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5330 0x100L, 0x200L, 0x400L, 0x800L,
5331 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5332 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5333 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5334 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5335 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5338 for (idx = 0; idx < 32; idx++)
5344 /*-----------------------------------------------------------------*/
5345 /* continueIfTrue - */
5346 /*-----------------------------------------------------------------*/
5348 continueIfTrue (iCode * ic)
5351 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5355 /*-----------------------------------------------------------------*/
5357 /*-----------------------------------------------------------------*/
5359 jumpIfTrue (iCode * ic)
5362 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5366 /*-----------------------------------------------------------------*/
5367 /* jmpTrueOrFalse - */
5368 /*-----------------------------------------------------------------*/
5370 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5372 // ugly but optimized by peephole
5375 symbol *nlbl = newiTempLabel (NULL);
5376 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5377 emitcode ("", "%05d$:", tlbl->key + 100);
5378 freeForBranchAsmop (result);
5379 freeForBranchAsmop (right);
5380 freeForBranchAsmop (left);
5381 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5382 emitcode ("", "%05d$:", nlbl->key + 100);
5386 freeForBranchAsmop (result);
5387 freeForBranchAsmop (right);
5388 freeForBranchAsmop (left);
5389 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5390 emitcode ("", "%05d$:", tlbl->key + 100);
5395 /*-----------------------------------------------------------------*/
5396 /* genAnd - code for and */
5397 /*-----------------------------------------------------------------*/
5399 genAnd (iCode * ic, iCode * ifx)
5401 operand *left, *right, *result;
5402 int size, offset = 0;
5403 unsigned long lit = 0L;
5407 D(emitcode ("; genAnd",""));
5409 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5410 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5411 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5414 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5416 AOP_TYPE (left), AOP_TYPE (right));
5417 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5419 AOP_SIZE (left), AOP_SIZE (right));
5422 /* if left is a literal & right is not then exchange them */
5423 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5424 AOP_NEEDSACC (left))
5426 operand *tmp = right;
5431 /* if result = right then exchange them */
5432 if (sameRegs (AOP (result), AOP (right)))
5434 operand *tmp = right;
5439 /* if right is bit then exchange them */
5440 if (AOP_TYPE (right) == AOP_CRY &&
5441 AOP_TYPE (left) != AOP_CRY)
5443 operand *tmp = right;
5447 if (AOP_TYPE (right) == AOP_LIT)
5448 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5450 size = AOP_SIZE (result);
5453 // result = bit & yy;
5454 if (AOP_TYPE (left) == AOP_CRY)
5456 // c = bit & literal;
5457 if (AOP_TYPE (right) == AOP_LIT)
5461 if (size && sameRegs (AOP (result), AOP (left)))
5464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5469 if (size && (AOP_TYPE (result) == AOP_CRY))
5471 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5474 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5479 emitcode ("clr", "c");
5484 if (AOP_TYPE (right) == AOP_CRY)
5487 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5488 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5493 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5495 emitcode ("rrc", "a");
5496 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5504 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5505 genIfxJump (ifx, "c", left, right, result);
5509 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5510 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5511 if ((AOP_TYPE (right) == AOP_LIT) &&
5512 (AOP_TYPE (result) == AOP_CRY) &&
5513 (AOP_TYPE (left) != AOP_CRY))
5515 int posbit = isLiteralBit (lit);
5520 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5523 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5529 sprintf (buffer, "acc.%d", posbit & 0x07);
5530 genIfxJump (ifx, buffer, left, right, result);
5537 symbol *tlbl = newiTempLabel (NULL);
5538 int sizel = AOP_SIZE (left);
5540 emitcode ("setb", "c");
5543 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5545 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5547 if ((posbit = isLiteralBit (bytelit)) != 0)
5548 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5551 if (bytelit != 0x0FFL)
5552 emitcode ("anl", "a,%s",
5553 aopGet (AOP (right), offset, FALSE, TRUE));
5554 emitcode ("jnz", "%05d$", tlbl->key + 100);
5559 // bit = left & literal
5562 emitcode ("clr", "c");
5563 emitcode ("", "%05d$:", tlbl->key + 100);
5565 // if(left & literal)
5569 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5571 emitcode ("", "%05d$:", tlbl->key + 100);
5579 /* if left is same as result */
5580 if (sameRegs (AOP (result), AOP (left)))
5582 for (; size--; offset++)
5584 if (AOP_TYPE (right) == AOP_LIT)
5586 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5588 else if (bytelit == 0)
5590 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5592 else if (IS_AOP_PREG (result))
5594 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5595 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5596 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5599 emitcode ("anl", "%s,%s",
5600 aopGet (AOP (left), offset, FALSE, TRUE),
5601 aopGet (AOP (right), offset, FALSE, FALSE));
5605 if (AOP_TYPE (left) == AOP_ACC)
5606 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5609 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5610 if (IS_AOP_PREG (result))
5612 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5613 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5617 emitcode ("anl", "%s,a",
5618 aopGet (AOP (left), offset, FALSE, TRUE));
5625 // left & result in different registers
5626 if (AOP_TYPE (result) == AOP_CRY)
5629 // if(size), result in bit
5630 // if(!size && ifx), conditional oper: if(left & right)
5631 symbol *tlbl = newiTempLabel (NULL);
5632 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5634 emitcode ("setb", "c");
5637 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5638 emitcode ("anl", "a,%s",
5639 aopGet (AOP (right), offset, FALSE, FALSE));
5641 if (AOP_TYPE(left)==AOP_ACC) {
5642 emitcode("mov", "b,a");
5643 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5644 emitcode("anl", "a,b");
5646 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5647 emitcode ("anl", "a,%s",
5648 aopGet (AOP (left), offset, FALSE, FALSE));
5651 emitcode ("jnz", "%05d$", tlbl->key + 100);
5657 emitcode ("", "%05d$:", tlbl->key + 100);
5661 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5663 emitcode ("", "%05d$:", tlbl->key + 100);
5667 for (; (size--); offset++)
5670 // result = left & right
5671 if (AOP_TYPE (right) == AOP_LIT)
5673 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5675 aopPut (AOP (result),
5676 aopGet (AOP (left), offset, FALSE, FALSE),
5678 isOperandVolatile (result, FALSE));
5681 else if (bytelit == 0)
5683 /* dummy read of volatile operand */
5684 if (isOperandVolatile (left, FALSE))
5685 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5686 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5690 // faster than result <- left, anl result,right
5691 // and better if result is SFR
5692 if (AOP_TYPE (left) == AOP_ACC)
5693 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5696 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5697 emitcode ("anl", "a,%s",
5698 aopGet (AOP (left), offset, FALSE, FALSE));
5700 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708 freeAsmop (result, NULL, ic, TRUE);
5711 /*-----------------------------------------------------------------*/
5712 /* genOr - code for or */
5713 /*-----------------------------------------------------------------*/
5715 genOr (iCode * ic, iCode * ifx)
5717 operand *left, *right, *result;
5718 int size, offset = 0;
5719 unsigned long lit = 0L;
5721 D(emitcode ("; genOr",""));
5723 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5724 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5725 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5728 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5730 AOP_TYPE (left), AOP_TYPE (right));
5731 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5733 AOP_SIZE (left), AOP_SIZE (right));
5736 /* if left is a literal & right is not then exchange them */
5737 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5738 AOP_NEEDSACC (left))
5740 operand *tmp = right;
5745 /* if result = right then exchange them */
5746 if (sameRegs (AOP (result), AOP (right)))
5748 operand *tmp = right;
5753 /* if right is bit then exchange them */
5754 if (AOP_TYPE (right) == AOP_CRY &&
5755 AOP_TYPE (left) != AOP_CRY)
5757 operand *tmp = right;
5761 if (AOP_TYPE (right) == AOP_LIT)
5762 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5764 size = AOP_SIZE (result);
5768 if (AOP_TYPE (left) == AOP_CRY)
5770 if (AOP_TYPE (right) == AOP_LIT)
5772 // c = bit | literal;
5775 // lit != 0 => result = 1
5776 if (AOP_TYPE (result) == AOP_CRY)
5779 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5781 continueIfTrue (ifx);
5784 emitcode ("setb", "c");
5788 // lit == 0 => result = left
5789 if (size && sameRegs (AOP (result), AOP (left)))
5791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796 if (AOP_TYPE (right) == AOP_CRY)
5799 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5800 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5805 symbol *tlbl = newiTempLabel (NULL);
5806 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5807 emitcode ("setb", "c");
5808 emitcode ("jb", "%s,%05d$",
5809 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5811 emitcode ("jnz", "%05d$", tlbl->key + 100);
5812 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5814 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5820 emitcode ("", "%05d$:", tlbl->key + 100);
5829 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5830 genIfxJump (ifx, "c", left, right, result);
5834 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5835 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5836 if ((AOP_TYPE (right) == AOP_LIT) &&
5837 (AOP_TYPE (result) == AOP_CRY) &&
5838 (AOP_TYPE (left) != AOP_CRY))
5844 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5846 continueIfTrue (ifx);
5851 // lit = 0, result = boolean(left)
5853 emitcode ("setb", "c");
5857 symbol *tlbl = newiTempLabel (NULL);
5858 emitcode ("jnz", "%05d$", tlbl->key + 100);
5860 emitcode ("", "%05d$:", tlbl->key + 100);
5864 genIfxJump (ifx, "a", left, right, result);
5872 /* if left is same as result */
5873 if (sameRegs (AOP (result), AOP (left)))
5875 for (; size--; offset++)
5877 if (AOP_TYPE (right) == AOP_LIT)
5879 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5881 /* dummy read of volatile operand */
5882 if (isOperandVolatile (left, FALSE))
5883 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5887 else if (IS_AOP_PREG (left))
5889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5890 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5891 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5894 emitcode ("orl", "%s,%s",
5895 aopGet (AOP (left), offset, FALSE, TRUE),
5896 aopGet (AOP (right), offset, FALSE, FALSE));
5900 if (AOP_TYPE (left) == AOP_ACC)
5901 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5904 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5905 if (IS_AOP_PREG (left))
5907 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5908 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5911 emitcode ("orl", "%s,a",
5912 aopGet (AOP (left), offset, FALSE, TRUE));
5919 // left & result in different registers
5920 if (AOP_TYPE (result) == AOP_CRY)
5923 // if(size), result in bit
5924 // if(!size && ifx), conditional oper: if(left | right)
5925 symbol *tlbl = newiTempLabel (NULL);
5926 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5928 emitcode ("setb", "c");
5931 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5932 emitcode ("orl", "a,%s",
5933 aopGet (AOP (right), offset, FALSE, FALSE));
5935 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5936 emitcode ("orl", "a,%s",
5937 aopGet (AOP (left), offset, FALSE, FALSE));
5939 emitcode ("jnz", "%05d$", tlbl->key + 100);
5945 emitcode ("", "%05d$:", tlbl->key + 100);
5949 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5951 emitcode ("", "%05d$:", tlbl->key + 100);
5954 for (; (size--); offset++)
5957 // result = left & right
5958 if (AOP_TYPE (right) == AOP_LIT)
5960 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5962 aopPut (AOP (result),
5963 aopGet (AOP (left), offset, FALSE, FALSE),
5965 isOperandVolatile (result, FALSE));
5969 // faster than result <- left, anl result,right
5970 // and better if result is SFR
5971 if (AOP_TYPE (left) == AOP_ACC)
5972 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5975 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5976 emitcode ("orl", "a,%s",
5977 aopGet (AOP (left), offset, FALSE, FALSE));
5979 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5984 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986 freeAsmop (result, NULL, ic, TRUE);
5989 /*-----------------------------------------------------------------*/
5990 /* genXor - code for xclusive or */
5991 /*-----------------------------------------------------------------*/
5993 genXor (iCode * ic, iCode * ifx)
5995 operand *left, *right, *result;
5996 int size, offset = 0;
5997 unsigned long lit = 0L;
5999 D(emitcode ("; genXor",""));
6001 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6002 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6003 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6006 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6008 AOP_TYPE (left), AOP_TYPE (right));
6009 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6011 AOP_SIZE (left), AOP_SIZE (right));
6014 /* if left is a literal & right is not ||
6015 if left needs acc & right does not */
6016 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6017 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6019 operand *tmp = right;
6024 /* if result = right then exchange them */
6025 if (sameRegs (AOP (result), AOP (right)))
6027 operand *tmp = right;
6032 /* if right is bit then exchange them */
6033 if (AOP_TYPE (right) == AOP_CRY &&
6034 AOP_TYPE (left) != AOP_CRY)
6036 operand *tmp = right;
6040 if (AOP_TYPE (right) == AOP_LIT)
6041 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6043 size = AOP_SIZE (result);
6047 if (AOP_TYPE (left) == AOP_CRY)
6049 if (AOP_TYPE (right) == AOP_LIT)
6051 // c = bit & literal;
6054 // lit>>1 != 0 => result = 1
6055 if (AOP_TYPE (result) == AOP_CRY)
6058 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6060 continueIfTrue (ifx);
6063 emitcode ("setb", "c");
6070 // lit == 0, result = left
6071 if (size && sameRegs (AOP (result), AOP (left)))
6073 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6077 // lit == 1, result = not(left)
6078 if (size && sameRegs (AOP (result), AOP (left)))
6080 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6085 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6086 emitcode ("cpl", "c");
6095 symbol *tlbl = newiTempLabel (NULL);
6096 if (AOP_TYPE (right) == AOP_CRY)
6099 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6103 int sizer = AOP_SIZE (right);
6105 // if val>>1 != 0, result = 1
6106 emitcode ("setb", "c");
6109 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6111 // test the msb of the lsb
6112 emitcode ("anl", "a,#0xfe");
6113 emitcode ("jnz", "%05d$", tlbl->key + 100);
6117 emitcode ("rrc", "a");
6119 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6120 emitcode ("cpl", "c");
6121 emitcode ("", "%05d$:", (tlbl->key + 100));
6128 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6129 genIfxJump (ifx, "c", left, right, result);
6133 if (sameRegs (AOP (result), AOP (left)))
6135 /* if left is same as result */
6136 for (; size--; offset++)
6138 if (AOP_TYPE (right) == AOP_LIT)
6140 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6142 else if (IS_AOP_PREG (left))
6144 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6145 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6146 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6149 emitcode ("xrl", "%s,%s",
6150 aopGet (AOP (left), offset, FALSE, TRUE),
6151 aopGet (AOP (right), offset, FALSE, FALSE));
6155 if (AOP_TYPE (left) == AOP_ACC)
6156 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6159 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6160 if (IS_AOP_PREG (left))
6162 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6163 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6166 emitcode ("xrl", "%s,a",
6167 aopGet (AOP (left), offset, FALSE, TRUE));
6174 // left & result in different registers
6175 if (AOP_TYPE (result) == AOP_CRY)
6178 // if(size), result in bit
6179 // if(!size && ifx), conditional oper: if(left ^ right)
6180 symbol *tlbl = newiTempLabel (NULL);
6181 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6183 emitcode ("setb", "c");
6186 if ((AOP_TYPE (right) == AOP_LIT) &&
6187 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6189 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6193 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6194 emitcode ("xrl", "a,%s",
6195 aopGet (AOP (right), offset, FALSE, FALSE));
6197 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6198 emitcode ("xrl", "a,%s",
6199 aopGet (AOP (left), offset, FALSE, FALSE));
6202 emitcode ("jnz", "%05d$", tlbl->key + 100);
6208 emitcode ("", "%05d$:", tlbl->key + 100);
6212 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6215 for (; (size--); offset++)
6218 // result = left & right
6219 if (AOP_TYPE (right) == AOP_LIT)
6221 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6223 aopPut (AOP (result),
6224 aopGet (AOP (left), offset, FALSE, FALSE),
6226 isOperandVolatile (result, FALSE));
6230 // faster than result <- left, anl result,right
6231 // and better if result is SFR
6232 if (AOP_TYPE (left) == AOP_ACC)
6233 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6236 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6237 emitcode ("xrl", "a,%s",
6238 aopGet (AOP (left), offset, FALSE, TRUE));
6240 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6245 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6246 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6247 freeAsmop (result, NULL, ic, TRUE);
6250 /*-----------------------------------------------------------------*/
6251 /* genInline - write the inline code out */
6252 /*-----------------------------------------------------------------*/
6254 genInline (iCode * ic)
6256 char *buffer, *bp, *bp1;
6258 D(emitcode ("; genInline",""));
6260 _G.inLine += (!options.asmpeep);
6262 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6263 strcpy (buffer, IC_INLINE (ic));
6265 /* emit each line as a code */
6290 /* emitcode("",buffer); */
6291 _G.inLine -= (!options.asmpeep);
6294 /*-----------------------------------------------------------------*/
6295 /* genRRC - rotate right with carry */
6296 /*-----------------------------------------------------------------*/
6300 operand *left, *result;
6301 int size, offset = 0;
6304 D(emitcode ("; genRRC",""));
6306 /* rotate right with carry */
6307 left = IC_LEFT (ic);
6308 result = IC_RESULT (ic);
6309 aopOp (left, ic, FALSE);
6310 aopOp (result, ic, FALSE);
6312 /* move it to the result */
6313 size = AOP_SIZE (result);
6315 if (size == 1) { /* special case for 1 byte */
6316 l = aopGet (AOP (left), offset, FALSE, FALSE);
6318 emitcode ("rr", "a");
6324 l = aopGet (AOP (left), offset, FALSE, FALSE);
6326 emitcode ("rrc", "a");
6327 if (AOP_SIZE (result) > 1)
6328 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6330 /* now we need to put the carry into the
6331 highest order byte of the result */
6332 if (AOP_SIZE (result) > 1)
6334 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6337 emitcode ("mov", "acc.7,c");
6339 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6340 freeAsmop (left, NULL, ic, TRUE);
6341 freeAsmop (result, NULL, ic, TRUE);
6344 /*-----------------------------------------------------------------*/
6345 /* genRLC - generate code for rotate left with carry */
6346 /*-----------------------------------------------------------------*/
6350 operand *left, *result;
6351 int size, offset = 0;
6354 D(emitcode ("; genRLC",""));
6356 /* rotate right with carry */
6357 left = IC_LEFT (ic);
6358 result = IC_RESULT (ic);
6359 aopOp (left, ic, FALSE);
6360 aopOp (result, ic, FALSE);
6362 /* move it to the result */
6363 size = AOP_SIZE (result);
6367 l = aopGet (AOP (left), offset, FALSE, FALSE);
6369 if (size == 0) { /* special case for 1 byte */
6373 emitcode ("add", "a,acc");
6374 if (AOP_SIZE (result) > 1)
6375 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6378 l = aopGet (AOP (left), offset, FALSE, FALSE);
6380 emitcode ("rlc", "a");
6381 if (AOP_SIZE (result) > 1)
6382 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6385 /* now we need to put the carry into the
6386 highest order byte of the result */
6387 if (AOP_SIZE (result) > 1)
6389 l = aopGet (AOP (result), 0, FALSE, FALSE);
6392 emitcode ("mov", "acc.0,c");
6394 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6395 freeAsmop (left, NULL, ic, TRUE);
6396 freeAsmop (result, NULL, ic, TRUE);
6399 /*-----------------------------------------------------------------*/
6400 /* genGetHbit - generates code get highest order bit */
6401 /*-----------------------------------------------------------------*/
6403 genGetHbit (iCode * ic)
6405 operand *left, *result;
6407 D(emitcode ("; genGetHbit",""));
6409 left = IC_LEFT (ic);
6410 result = IC_RESULT (ic);
6411 aopOp (left, ic, FALSE);
6412 aopOp (result, ic, FALSE);
6414 /* get the highest order byte into a */
6415 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6416 if (AOP_TYPE (result) == AOP_CRY)
6418 emitcode ("rlc", "a");
6423 emitcode ("rl", "a");
6424 emitcode ("anl", "a,#0x01");
6429 freeAsmop (left, NULL, ic, TRUE);
6430 freeAsmop (result, NULL, ic, TRUE);
6433 /*-----------------------------------------------------------------*/
6434 /* genSwap - generates code to swap nibbles or bytes */
6435 /*-----------------------------------------------------------------*/
6437 genSwap (iCode * ic)
6439 operand *left, *result;
6441 D(emitcode ("; genSwap",""));
6443 left = IC_LEFT (ic);
6444 result = IC_RESULT (ic);
6445 aopOp (left, ic, FALSE);
6446 aopOp (result, ic, FALSE);
6448 switch (AOP_SIZE (left))
6450 case 1: /* swap nibbles in byte */
6451 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6452 emitcode ("swap", "a");
6453 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6455 case 2: /* swap bytes in word */
6456 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6458 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6459 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6460 0, isOperandVolatile (result, FALSE));
6461 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6463 else if (operandsEqu (left, result))
6466 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6467 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6469 emitcode ("mov", "b,a");
6472 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6473 0, isOperandVolatile (result, FALSE));
6474 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6478 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6479 0, isOperandVolatile (result, FALSE));
6480 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6481 1, isOperandVolatile (result, FALSE));
6485 wassertl(FALSE, "unsupported SWAP operand size");
6488 freeAsmop (left, NULL, ic, TRUE);
6489 freeAsmop (result, NULL, ic, TRUE);
6493 /*-----------------------------------------------------------------*/
6494 /* AccRol - rotate left accumulator by known count */
6495 /*-----------------------------------------------------------------*/
6497 AccRol (int shCount)
6499 shCount &= 0x0007; // shCount : 0..7
6506 emitcode ("rl", "a");
6509 emitcode ("rl", "a");
6510 emitcode ("rl", "a");
6513 emitcode ("swap", "a");
6514 emitcode ("rr", "a");
6517 emitcode ("swap", "a");
6520 emitcode ("swap", "a");
6521 emitcode ("rl", "a");
6524 emitcode ("rr", "a");
6525 emitcode ("rr", "a");
6528 emitcode ("rr", "a");
6533 /*-----------------------------------------------------------------*/
6534 /* AccLsh - left shift accumulator by known count */
6535 /*-----------------------------------------------------------------*/
6537 AccLsh (int shCount)
6542 emitcode ("add", "a,acc");
6543 else if (shCount == 2)
6545 emitcode ("add", "a,acc");
6546 emitcode ("add", "a,acc");
6550 /* rotate left accumulator */
6552 /* and kill the lower order bits */
6553 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6558 /*-----------------------------------------------------------------*/
6559 /* AccRsh - right shift accumulator by known count */
6560 /*-----------------------------------------------------------------*/
6562 AccRsh (int shCount)
6569 emitcode ("rrc", "a");
6573 /* rotate right accumulator */
6574 AccRol (8 - shCount);
6575 /* and kill the higher order bits */
6576 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6581 /*-----------------------------------------------------------------*/
6582 /* AccSRsh - signed right shift accumulator by known count */
6583 /*-----------------------------------------------------------------*/
6585 AccSRsh (int shCount)
6592 emitcode ("mov", "c,acc.7");
6593 emitcode ("rrc", "a");
6595 else if (shCount == 2)
6597 emitcode ("mov", "c,acc.7");
6598 emitcode ("rrc", "a");
6599 emitcode ("mov", "c,acc.7");
6600 emitcode ("rrc", "a");
6604 tlbl = newiTempLabel (NULL);
6605 /* rotate right accumulator */
6606 AccRol (8 - shCount);
6607 /* and kill the higher order bits */
6608 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6609 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6610 emitcode ("orl", "a,#0x%02x",
6611 (unsigned char) ~SRMask[shCount]);
6612 emitcode ("", "%05d$:", tlbl->key + 100);
6617 /*-----------------------------------------------------------------*/
6618 /* shiftR1Left2Result - shift right one byte from left to result */
6619 /*-----------------------------------------------------------------*/
6621 shiftR1Left2Result (operand * left, int offl,
6622 operand * result, int offr,
6623 int shCount, int sign)
6625 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6626 /* shift right accumulator */
6631 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6634 /*-----------------------------------------------------------------*/
6635 /* shiftL1Left2Result - shift left one byte from left to result */
6636 /*-----------------------------------------------------------------*/
6638 shiftL1Left2Result (operand * left, int offl,
6639 operand * result, int offr, int shCount)
6642 l = aopGet (AOP (left), offl, FALSE, FALSE);
6644 /* shift left accumulator */
6646 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6649 /*-----------------------------------------------------------------*/
6650 /* movLeft2Result - move byte from left to result */
6651 /*-----------------------------------------------------------------*/
6653 movLeft2Result (operand * left, int offl,
6654 operand * result, int offr, int sign)
6657 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6659 l = aopGet (AOP (left), offl, FALSE, FALSE);
6661 if (*l == '@' && (IS_AOP_PREG (result)))
6663 emitcode ("mov", "a,%s", l);
6664 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6669 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6672 /* MSB sign in acc.7 ! */
6673 if (getDataSize (left) == offl + 1)
6675 emitcode ("mov", "a,%s", l);
6676 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6683 /*-----------------------------------------------------------------*/
6684 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6685 /*-----------------------------------------------------------------*/
6689 emitcode ("rrc", "a");
6690 emitcode ("xch", "a,%s", x);
6691 emitcode ("rrc", "a");
6692 emitcode ("xch", "a,%s", x);
6695 /*-----------------------------------------------------------------*/
6696 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6697 /*-----------------------------------------------------------------*/
6701 emitcode ("xch", "a,%s", x);
6702 emitcode ("rlc", "a");
6703 emitcode ("xch", "a,%s", x);
6704 emitcode ("rlc", "a");
6707 /*-----------------------------------------------------------------*/
6708 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6709 /*-----------------------------------------------------------------*/
6713 emitcode ("xch", "a,%s", x);
6714 emitcode ("add", "a,acc");
6715 emitcode ("xch", "a,%s", x);
6716 emitcode ("rlc", "a");
6719 /*-----------------------------------------------------------------*/
6720 /* AccAXLsh - left shift a:x by known count (0..7) */
6721 /*-----------------------------------------------------------------*/
6723 AccAXLsh (char *x, int shCount)
6738 case 5: // AAAAABBB:CCCCCDDD
6740 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6742 emitcode ("anl", "a,#0x%02x",
6743 SLMask[shCount]); // BBB00000:CCCCCDDD
6745 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6747 AccRol (shCount); // DDDCCCCC:BBB00000
6749 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6751 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6753 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6755 emitcode ("anl", "a,#0x%02x",
6756 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6758 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6760 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6763 case 6: // AAAAAABB:CCCCCCDD
6764 emitcode ("anl", "a,#0x%02x",
6765 SRMask[shCount]); // 000000BB:CCCCCCDD
6766 emitcode ("mov", "c,acc.0"); // c = B
6767 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6769 AccAXRrl1 (x); // BCCCCCCD:D000000B
6770 AccAXRrl1 (x); // BBCCCCCC:DD000000
6772 emitcode("rrc","a");
6773 emitcode("xch","a,%s", x);
6774 emitcode("rrc","a");
6775 emitcode("mov","c,acc.0"); //<< get correct bit
6776 emitcode("xch","a,%s", x);
6778 emitcode("rrc","a");
6779 emitcode("xch","a,%s", x);
6780 emitcode("rrc","a");
6781 emitcode("xch","a,%s", x);
6784 case 7: // a:x <<= 7
6786 emitcode ("anl", "a,#0x%02x",
6787 SRMask[shCount]); // 0000000B:CCCCCCCD
6789 emitcode ("mov", "c,acc.0"); // c = B
6791 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6793 AccAXRrl1 (x); // BCCCCCCC:D0000000
6801 /*-----------------------------------------------------------------*/
6802 /* AccAXRsh - right shift a:x known count (0..7) */
6803 /*-----------------------------------------------------------------*/
6805 AccAXRsh (char *x, int shCount)
6813 AccAXRrl1 (x); // 0->a:x
6818 AccAXRrl1 (x); // 0->a:x
6821 AccAXRrl1 (x); // 0->a:x
6826 case 5: // AAAAABBB:CCCCCDDD = a:x
6828 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6830 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6832 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6834 emitcode ("anl", "a,#0x%02x",
6835 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6837 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6839 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6841 emitcode ("anl", "a,#0x%02x",
6842 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6844 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6846 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6848 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6851 case 6: // AABBBBBB:CCDDDDDD
6853 emitcode ("mov", "c,acc.7");
6854 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6856 emitcode ("mov", "c,acc.7");
6857 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6859 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6861 emitcode ("anl", "a,#0x%02x",
6862 SRMask[shCount]); // 000000AA:BBBBBBCC
6865 case 7: // ABBBBBBB:CDDDDDDD
6867 emitcode ("mov", "c,acc.7"); // c = A
6869 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6871 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6873 emitcode ("anl", "a,#0x%02x",
6874 SRMask[shCount]); // 0000000A:BBBBBBBC
6882 /*-----------------------------------------------------------------*/
6883 /* AccAXRshS - right shift signed a:x known count (0..7) */
6884 /*-----------------------------------------------------------------*/
6886 AccAXRshS (char *x, int shCount)
6894 emitcode ("mov", "c,acc.7");
6895 AccAXRrl1 (x); // s->a:x
6899 emitcode ("mov", "c,acc.7");
6900 AccAXRrl1 (x); // s->a:x
6902 emitcode ("mov", "c,acc.7");
6903 AccAXRrl1 (x); // s->a:x
6908 case 5: // AAAAABBB:CCCCCDDD = a:x
6910 tlbl = newiTempLabel (NULL);
6911 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6913 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6915 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6917 emitcode ("anl", "a,#0x%02x",
6918 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6920 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6922 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6924 emitcode ("anl", "a,#0x%02x",
6925 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6927 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6929 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6931 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6933 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6934 emitcode ("orl", "a,#0x%02x",
6935 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6937 emitcode ("", "%05d$:", tlbl->key + 100);
6938 break; // SSSSAAAA:BBBCCCCC
6940 case 6: // AABBBBBB:CCDDDDDD
6942 tlbl = newiTempLabel (NULL);
6943 emitcode ("mov", "c,acc.7");
6944 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6946 emitcode ("mov", "c,acc.7");
6947 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6949 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6951 emitcode ("anl", "a,#0x%02x",
6952 SRMask[shCount]); // 000000AA:BBBBBBCC
6954 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6955 emitcode ("orl", "a,#0x%02x",
6956 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6958 emitcode ("", "%05d$:", tlbl->key + 100);
6960 case 7: // ABBBBBBB:CDDDDDDD
6962 tlbl = newiTempLabel (NULL);
6963 emitcode ("mov", "c,acc.7"); // c = A
6965 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6967 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6969 emitcode ("anl", "a,#0x%02x",
6970 SRMask[shCount]); // 0000000A:BBBBBBBC
6972 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6973 emitcode ("orl", "a,#0x%02x",
6974 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6976 emitcode ("", "%05d$:", tlbl->key + 100);
6983 /*-----------------------------------------------------------------*/
6984 /* shiftL2Left2Result - shift left two bytes from left to result */
6985 /*-----------------------------------------------------------------*/
6987 shiftL2Left2Result (operand * left, int offl,
6988 operand * result, int offr, int shCount)
6990 if (sameRegs (AOP (result), AOP (left)) &&
6991 ((offl + MSB16) == offr))
6993 /* don't crash result[offr] */
6994 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6995 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6999 movLeft2Result (left, offl, result, offr, 0);
7000 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7002 /* ax << shCount (x = lsb(result)) */
7003 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7004 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7008 /*-----------------------------------------------------------------*/
7009 /* shiftR2Left2Result - shift right two bytes from left to result */
7010 /*-----------------------------------------------------------------*/
7012 shiftR2Left2Result (operand * left, int offl,
7013 operand * result, int offr,
7014 int shCount, int sign)
7016 if (sameRegs (AOP (result), AOP (left)) &&
7017 ((offl + MSB16) == offr))
7019 /* don't crash result[offr] */
7020 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7021 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7025 movLeft2Result (left, offl, result, offr, 0);
7026 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7028 /* a:x >> shCount (x = lsb(result)) */
7030 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7032 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7033 if (getDataSize (result) > 1)
7034 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7037 /*-----------------------------------------------------------------*/
7038 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7039 /*-----------------------------------------------------------------*/
7041 shiftLLeftOrResult (operand * left, int offl,
7042 operand * result, int offr, int shCount)
7044 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7045 /* shift left accumulator */
7047 /* or with result */
7048 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7049 /* back to result */
7050 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7053 /*-----------------------------------------------------------------*/
7054 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7055 /*-----------------------------------------------------------------*/
7057 shiftRLeftOrResult (operand * left, int offl,
7058 operand * result, int offr, int shCount)
7060 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7061 /* shift right accumulator */
7063 /* or with result */
7064 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7065 /* back to result */
7066 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7069 /*-----------------------------------------------------------------*/
7070 /* genlshOne - left shift a one byte quantity by known count */
7071 /*-----------------------------------------------------------------*/
7073 genlshOne (operand * result, operand * left, int shCount)
7075 D(emitcode ("; genlshOne",""));
7077 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7080 /*-----------------------------------------------------------------*/
7081 /* genlshTwo - left shift two bytes by known amount != 0 */
7082 /*-----------------------------------------------------------------*/
7084 genlshTwo (operand * result, operand * left, int shCount)
7088 D(emitcode ("; genlshTwo",""));
7090 size = getDataSize (result);
7092 /* if shCount >= 8 */
7100 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7102 movLeft2Result (left, LSB, result, MSB16, 0);
7104 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7107 /* 1 <= shCount <= 7 */
7111 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7113 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7117 /*-----------------------------------------------------------------*/
7118 /* shiftLLong - shift left one long from left to result */
7119 /* offl = LSB or MSB16 */
7120 /*-----------------------------------------------------------------*/
7122 shiftLLong (operand * left, operand * result, int offr)
7125 int size = AOP_SIZE (result);
7127 if (size >= LSB + offr)
7129 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7131 emitcode ("add", "a,acc");
7132 if (sameRegs (AOP (left), AOP (result)) &&
7133 size >= MSB16 + offr && offr != LSB)
7134 emitcode ("xch", "a,%s",
7135 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7137 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7140 if (size >= MSB16 + offr)
7142 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7144 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7147 emitcode ("rlc", "a");
7148 if (sameRegs (AOP (left), AOP (result)) &&
7149 size >= MSB24 + offr && offr != LSB)
7150 emitcode ("xch", "a,%s",
7151 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7153 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7156 if (size >= MSB24 + offr)
7158 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7160 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7163 emitcode ("rlc", "a");
7164 if (sameRegs (AOP (left), AOP (result)) &&
7165 size >= MSB32 + offr && offr != LSB)
7166 emitcode ("xch", "a,%s",
7167 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7169 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7172 if (size > MSB32 + offr)
7174 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7176 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7179 emitcode ("rlc", "a");
7180 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7183 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7186 /*-----------------------------------------------------------------*/
7187 /* genlshFour - shift four byte by a known amount != 0 */
7188 /*-----------------------------------------------------------------*/
7190 genlshFour (operand * result, operand * left, int shCount)
7194 D(emitcode ("; genlshFour",""));
7196 size = AOP_SIZE (result);
7198 /* if shifting more that 3 bytes */
7203 /* lowest order of left goes to the highest
7204 order of the destination */
7205 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7207 movLeft2Result (left, LSB, result, MSB32, 0);
7208 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7209 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7210 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7214 /* more than two bytes */
7215 else if (shCount >= 16)
7217 /* lower order two bytes goes to higher order two bytes */
7219 /* if some more remaining */
7221 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7224 movLeft2Result (left, MSB16, result, MSB32, 0);
7225 movLeft2Result (left, LSB, result, MSB24, 0);
7227 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7228 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7232 /* if more than 1 byte */
7233 else if (shCount >= 8)
7235 /* lower order three bytes goes to higher order three bytes */
7240 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7242 movLeft2Result (left, LSB, result, MSB16, 0);
7248 movLeft2Result (left, MSB24, result, MSB32, 0);
7249 movLeft2Result (left, MSB16, result, MSB24, 0);
7250 movLeft2Result (left, LSB, result, MSB16, 0);
7251 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7253 else if (shCount == 1)
7254 shiftLLong (left, result, MSB16);
7257 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7258 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7259 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7260 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7265 /* 1 <= shCount <= 7 */
7266 else if (shCount <= 2)
7268 shiftLLong (left, result, LSB);
7270 shiftLLong (result, result, LSB);
7272 /* 3 <= shCount <= 7, optimize */
7275 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7276 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7277 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7281 /*-----------------------------------------------------------------*/
7282 /* genLeftShiftLiteral - left shifting by known count */
7283 /*-----------------------------------------------------------------*/
7285 genLeftShiftLiteral (operand * left,
7290 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7293 D(emitcode ("; genLeftShiftLiteral",""));
7295 freeAsmop (right, NULL, ic, TRUE);
7297 aopOp (left, ic, FALSE);
7298 aopOp (result, ic, FALSE);
7300 size = getSize (operandType (result));
7303 emitcode ("; shift left ", "result %d, left %d", size,
7307 /* I suppose that the left size >= result size */
7312 movLeft2Result (left, size, result, size, 0);
7316 else if (shCount >= (size * 8))
7318 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7324 genlshOne (result, left, shCount);
7328 genlshTwo (result, left, shCount);
7332 genlshFour (result, left, shCount);
7335 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7336 "*** ack! mystery literal shift!\n");
7340 freeAsmop (left, NULL, ic, TRUE);
7341 freeAsmop (result, NULL, ic, TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genLeftShift - generates code for left shifting */
7346 /*-----------------------------------------------------------------*/
7348 genLeftShift (iCode * ic)
7350 operand *left, *right, *result;
7353 symbol *tlbl, *tlbl1;
7355 D(emitcode ("; genLeftShift",""));
7357 right = IC_RIGHT (ic);
7358 left = IC_LEFT (ic);
7359 result = IC_RESULT (ic);
7361 aopOp (right, ic, FALSE);
7363 /* if the shift count is known then do it
7364 as efficiently as possible */
7365 if (AOP_TYPE (right) == AOP_LIT)
7367 genLeftShiftLiteral (left, right, result, ic);
7371 /* shift count is unknown then we have to form
7372 a loop get the loop count in B : Note: we take
7373 only the lower order byte since shifting
7374 more that 32 bits make no sense anyway, ( the
7375 largest size of an object can be only 32 bits ) */
7377 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7378 emitcode ("inc", "b");
7379 freeAsmop (right, NULL, ic, TRUE);
7380 aopOp (left, ic, FALSE);
7381 aopOp (result, ic, FALSE);
7383 /* now move the left to the result if they are not the
7385 if (!sameRegs (AOP (left), AOP (result)) &&
7386 AOP_SIZE (result) > 1)
7389 size = AOP_SIZE (result);
7393 l = aopGet (AOP (left), offset, FALSE, TRUE);
7394 if (*l == '@' && (IS_AOP_PREG (result)))
7397 emitcode ("mov", "a,%s", l);
7398 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7401 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7406 tlbl = newiTempLabel (NULL);
7407 size = AOP_SIZE (result);
7409 tlbl1 = newiTempLabel (NULL);
7411 /* if it is only one byte then */
7414 symbol *tlbl1 = newiTempLabel (NULL);
7416 l = aopGet (AOP (left), 0, FALSE, FALSE);
7418 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7419 emitcode ("", "%05d$:", tlbl->key + 100);
7420 emitcode ("add", "a,acc");
7421 emitcode ("", "%05d$:", tlbl1->key + 100);
7422 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7423 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7427 reAdjustPreg (AOP (result));
7429 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7430 emitcode ("", "%05d$:", tlbl->key + 100);
7431 l = aopGet (AOP (result), offset, FALSE, FALSE);
7433 emitcode ("add", "a,acc");
7434 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7437 l = aopGet (AOP (result), offset, FALSE, FALSE);
7439 emitcode ("rlc", "a");
7440 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7442 reAdjustPreg (AOP (result));
7444 emitcode ("", "%05d$:", tlbl1->key + 100);
7445 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7447 freeAsmop (left, NULL, ic, TRUE);
7448 freeAsmop (result, NULL, ic, TRUE);
7451 /*-----------------------------------------------------------------*/
7452 /* genrshOne - right shift a one byte quantity by known count */
7453 /*-----------------------------------------------------------------*/
7455 genrshOne (operand * result, operand * left,
7456 int shCount, int sign)
7458 D(emitcode ("; genrshOne",""));
7460 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7463 /*-----------------------------------------------------------------*/
7464 /* genrshTwo - right shift two bytes by known amount != 0 */
7465 /*-----------------------------------------------------------------*/
7467 genrshTwo (operand * result, operand * left,
7468 int shCount, int sign)
7470 D(emitcode ("; genrshTwo",""));
7472 /* if shCount >= 8 */
7477 shiftR1Left2Result (left, MSB16, result, LSB,
7480 movLeft2Result (left, MSB16, result, LSB, sign);
7481 addSign (result, MSB16, sign);
7484 /* 1 <= shCount <= 7 */
7486 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7489 /*-----------------------------------------------------------------*/
7490 /* shiftRLong - shift right one long from left to result */
7491 /* offl = LSB or MSB16 */
7492 /*-----------------------------------------------------------------*/
7494 shiftRLong (operand * left, int offl,
7495 operand * result, int sign)
7497 int isSameRegs=sameRegs(AOP(left),AOP(result));
7499 if (isSameRegs && offl>1) {
7500 // we are in big trouble, but this shouldn't happen
7501 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7504 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7509 emitcode ("rlc", "a");
7510 emitcode ("subb", "a,acc");
7512 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7514 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7515 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7518 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7523 emitcode ("clr", "c");
7525 emitcode ("mov", "c,acc.7");
7528 emitcode ("rrc", "a");
7530 if (isSameRegs && offl==MSB16) {
7531 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7533 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7534 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7537 emitcode ("rrc", "a");
7538 if (isSameRegs && offl==1) {
7539 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7541 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7542 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7544 emitcode ("rrc", "a");
7545 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7549 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7550 emitcode ("rrc", "a");
7551 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7555 /*-----------------------------------------------------------------*/
7556 /* genrshFour - shift four byte by a known amount != 0 */
7557 /*-----------------------------------------------------------------*/
7559 genrshFour (operand * result, operand * left,
7560 int shCount, int sign)
7562 D(emitcode ("; genrshFour",""));
7564 /* if shifting more that 3 bytes */
7569 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7571 movLeft2Result (left, MSB32, result, LSB, sign);
7572 addSign (result, MSB16, sign);
7574 else if (shCount >= 16)
7578 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7581 movLeft2Result (left, MSB24, result, LSB, 0);
7582 movLeft2Result (left, MSB32, result, MSB16, sign);
7584 addSign (result, MSB24, sign);
7586 else if (shCount >= 8)
7590 shiftRLong (left, MSB16, result, sign);
7591 else if (shCount == 0)
7593 movLeft2Result (left, MSB16, result, LSB, 0);
7594 movLeft2Result (left, MSB24, result, MSB16, 0);
7595 movLeft2Result (left, MSB32, result, MSB24, sign);
7596 addSign (result, MSB32, sign);
7600 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7601 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7602 /* the last shift is signed */
7603 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7604 addSign (result, MSB32, sign);
7608 { /* 1 <= shCount <= 7 */
7611 shiftRLong (left, LSB, result, sign);
7613 shiftRLong (result, LSB, result, sign);
7617 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7618 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7619 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7624 /*-----------------------------------------------------------------*/
7625 /* genRightShiftLiteral - right shifting by known count */
7626 /*-----------------------------------------------------------------*/
7628 genRightShiftLiteral (operand * left,
7634 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7637 D(emitcode ("; genRightShiftLiteral",""));
7639 freeAsmop (right, NULL, ic, TRUE);
7641 aopOp (left, ic, FALSE);
7642 aopOp (result, ic, FALSE);
7645 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7649 size = getDataSize (left);
7650 /* test the LEFT size !!! */
7652 /* I suppose that the left size >= result size */
7655 size = getDataSize (result);
7657 movLeft2Result (left, size, result, size, 0);
7660 else if (shCount >= (size * 8))
7663 /* get sign in acc.7 */
7664 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7666 addSign (result, LSB, sign);
7673 genrshOne (result, left, shCount, sign);
7677 genrshTwo (result, left, shCount, sign);
7681 genrshFour (result, left, shCount, sign);
7687 freeAsmop (left, NULL, ic, TRUE);
7688 freeAsmop (result, NULL, ic, TRUE);
7691 /*-----------------------------------------------------------------*/
7692 /* genSignedRightShift - right shift of signed number */
7693 /*-----------------------------------------------------------------*/
7695 genSignedRightShift (iCode * ic)
7697 operand *right, *left, *result;
7700 symbol *tlbl, *tlbl1;
7702 D(emitcode ("; genSignedRightShift",""));
7704 /* we do it the hard way put the shift count in b
7705 and loop thru preserving the sign */
7707 right = IC_RIGHT (ic);
7708 left = IC_LEFT (ic);
7709 result = IC_RESULT (ic);
7711 aopOp (right, ic, FALSE);
7714 if (AOP_TYPE (right) == AOP_LIT)
7716 genRightShiftLiteral (left, right, result, ic, 1);
7719 /* shift count is unknown then we have to form
7720 a loop get the loop count in B : Note: we take
7721 only the lower order byte since shifting
7722 more that 32 bits make no sense anyway, ( the
7723 largest size of an object can be only 32 bits ) */
7725 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7726 emitcode ("inc", "b");
7727 freeAsmop (right, NULL, ic, TRUE);
7728 aopOp (left, ic, FALSE);
7729 aopOp (result, ic, FALSE);
7731 /* now move the left to the result if they are not the
7733 if (!sameRegs (AOP (left), AOP (result)) &&
7734 AOP_SIZE (result) > 1)
7737 size = AOP_SIZE (result);
7741 l = aopGet (AOP (left), offset, FALSE, TRUE);
7742 if (*l == '@' && IS_AOP_PREG (result))
7745 emitcode ("mov", "a,%s", l);
7746 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7749 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7754 /* mov the highest order bit to OVR */
7755 tlbl = newiTempLabel (NULL);
7756 tlbl1 = newiTempLabel (NULL);
7758 size = AOP_SIZE (result);
7760 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7761 emitcode ("rlc", "a");
7762 emitcode ("mov", "ov,c");
7763 /* if it is only one byte then */
7766 l = aopGet (AOP (left), 0, FALSE, FALSE);
7768 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7769 emitcode ("", "%05d$:", tlbl->key + 100);
7770 emitcode ("mov", "c,ov");
7771 emitcode ("rrc", "a");
7772 emitcode ("", "%05d$:", tlbl1->key + 100);
7773 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7774 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7778 reAdjustPreg (AOP (result));
7779 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7780 emitcode ("", "%05d$:", tlbl->key + 100);
7781 emitcode ("mov", "c,ov");
7784 l = aopGet (AOP (result), offset, FALSE, FALSE);
7786 emitcode ("rrc", "a");
7787 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7789 reAdjustPreg (AOP (result));
7790 emitcode ("", "%05d$:", tlbl1->key + 100);
7791 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7794 freeAsmop (left, NULL, ic, TRUE);
7795 freeAsmop (result, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genRightShift - generate code for right shifting */
7800 /*-----------------------------------------------------------------*/
7802 genRightShift (iCode * ic)
7804 operand *right, *left, *result;
7808 symbol *tlbl, *tlbl1;
7810 D(emitcode ("; genRightShift",""));
7812 /* if signed then we do it the hard way preserve the
7813 sign bit moving it inwards */
7814 letype = getSpec (operandType (IC_LEFT (ic)));
7816 if (!SPEC_USIGN (letype))
7818 genSignedRightShift (ic);
7822 /* signed & unsigned types are treated the same : i.e. the
7823 signed is NOT propagated inwards : quoting from the
7824 ANSI - standard : "for E1 >> E2, is equivalent to division
7825 by 2**E2 if unsigned or if it has a non-negative value,
7826 otherwise the result is implementation defined ", MY definition
7827 is that the sign does not get propagated */
7829 right = IC_RIGHT (ic);
7830 left = IC_LEFT (ic);
7831 result = IC_RESULT (ic);
7833 aopOp (right, ic, FALSE);
7835 /* if the shift count is known then do it
7836 as efficiently as possible */
7837 if (AOP_TYPE (right) == AOP_LIT)
7839 genRightShiftLiteral (left, right, result, ic, 0);
7843 /* shift count is unknown then we have to form
7844 a loop get the loop count in B : Note: we take
7845 only the lower order byte since shifting
7846 more that 32 bits make no sense anyway, ( the
7847 largest size of an object can be only 32 bits ) */
7849 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7850 emitcode ("inc", "b");
7851 freeAsmop (right, NULL, ic, TRUE);
7852 aopOp (left, ic, FALSE);
7853 aopOp (result, ic, FALSE);
7855 /* now move the left to the result if they are not the
7857 if (!sameRegs (AOP (left), AOP (result)) &&
7858 AOP_SIZE (result) > 1)
7861 size = AOP_SIZE (result);
7865 l = aopGet (AOP (left), offset, FALSE, TRUE);
7866 if (*l == '@' && IS_AOP_PREG (result))
7869 emitcode ("mov", "a,%s", l);
7870 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7873 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7878 tlbl = newiTempLabel (NULL);
7879 tlbl1 = newiTempLabel (NULL);
7880 size = AOP_SIZE (result);
7883 /* if it is only one byte then */
7886 l = aopGet (AOP (left), 0, FALSE, FALSE);
7888 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7889 emitcode ("", "%05d$:", tlbl->key + 100);
7891 emitcode ("rrc", "a");
7892 emitcode ("", "%05d$:", tlbl1->key + 100);
7893 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7894 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7898 reAdjustPreg (AOP (result));
7899 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7900 emitcode ("", "%05d$:", tlbl->key + 100);
7904 l = aopGet (AOP (result), offset, FALSE, FALSE);
7906 emitcode ("rrc", "a");
7907 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7909 reAdjustPreg (AOP (result));
7911 emitcode ("", "%05d$:", tlbl1->key + 100);
7912 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7915 freeAsmop (left, NULL, ic, TRUE);
7916 freeAsmop (result, NULL, ic, TRUE);
7919 /*-----------------------------------------------------------------*/
7920 /* emitPtrByteGet - emits code to get a byte into A through a */
7921 /* pointer register (R0, R1, or DPTR). The */
7922 /* original value of A can be preserved in B. */
7923 /*-----------------------------------------------------------------*/
7925 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7932 emitcode ("mov", "b,a");
7933 emitcode ("mov", "a,@%s", rname);
7938 emitcode ("mov", "b,a");
7939 emitcode ("movx", "a,@%s", rname);
7944 emitcode ("mov", "b,a");
7945 emitcode ("movx", "a,@dptr");
7950 emitcode ("mov", "b,a");
7951 emitcode ("clr", "a");
7952 emitcode ("movc", "a,@a+dptr");
7958 emitcode ("push", "b");
7959 emitcode ("push", "acc");
7961 emitcode ("lcall", "__gptrget");
7963 emitcode ("pop", "b");
7968 /*-----------------------------------------------------------------*/
7969 /* emitPtrByteSet - emits code to set a byte from src through a */
7970 /* pointer register (R0, R1, or DPTR). */
7971 /*-----------------------------------------------------------------*/
7973 emitPtrByteSet (char *rname, int p_type, char *src)
7982 emitcode ("mov", "@%s,a", rname);
7985 emitcode ("mov", "@%s,%s", rname, src);
7990 emitcode ("movx", "@%s,a", rname);
7995 emitcode ("movx", "@dptr,a");
8000 emitcode ("lcall", "__gptrput");
8005 /*-----------------------------------------------------------------*/
8006 /* genUnpackBits - generates code for unpacking bits */
8007 /*-----------------------------------------------------------------*/
8009 genUnpackBits (operand * result, char *rname, int ptype)
8011 int offset = 0; /* result byte offset */
8012 int rsize; /* result size */
8013 int rlen = 0; /* remaining bitfield length */
8014 sym_link *etype; /* bitfield type information */
8015 int blen; /* bitfield length */
8016 int bstr; /* bitfield starting bit within byte */
8018 D(emitcode ("; genUnpackBits",""));
8020 etype = getSpec (operandType (result));
8021 rsize = getSize (operandType (result));
8022 blen = SPEC_BLEN (etype);
8023 bstr = SPEC_BSTR (etype);
8025 /* If the bitfield length is less than a byte */
8028 emitPtrByteGet (rname, ptype, FALSE);
8030 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8031 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8035 /* Bit field did not fit in a byte. Copy all
8036 but the partial byte at the end. */
8037 for (rlen=blen;rlen>=8;rlen-=8)
8039 emitPtrByteGet (rname, ptype, FALSE);
8040 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8042 emitcode ("inc", "%s", rname);
8045 /* Handle the partial byte at the end */
8048 emitPtrByteGet (rname, ptype, FALSE);
8049 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8050 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8058 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8063 /*-----------------------------------------------------------------*/
8064 /* genDataPointerGet - generates code when ptr offset is known */
8065 /*-----------------------------------------------------------------*/
8067 genDataPointerGet (operand * left,
8073 int size, offset = 0;
8075 D(emitcode ("; genDataPointerGet",""));
8077 aopOp (result, ic, TRUE);
8079 /* get the string representation of the name */
8080 l = aopGet (AOP (left), 0, FALSE, TRUE);
8081 size = AOP_SIZE (result);
8085 sprintf (buffer, "(%s + %d)", l + 1, offset);
8087 sprintf (buffer, "%s", l + 1);
8088 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8091 freeAsmop (left, NULL, ic, TRUE);
8092 freeAsmop (result, NULL, ic, TRUE);
8095 /*-----------------------------------------------------------------*/
8096 /* genNearPointerGet - emitcode for near pointer fetch */
8097 /*-----------------------------------------------------------------*/
8099 genNearPointerGet (operand * left,
8107 sym_link *rtype, *retype;
8108 sym_link *ltype = operandType (left);
8111 D(emitcode ("; genNearPointerGet",""));
8113 rtype = operandType (result);
8114 retype = getSpec (rtype);
8116 aopOp (left, ic, FALSE);
8118 /* if left is rematerialisable and
8119 result is not bitfield variable type and
8120 the left is pointer to data space i.e
8121 lower 128 bytes of space */
8122 if (AOP_TYPE (left) == AOP_IMMD &&
8123 !IS_BITFIELD (retype) &&
8124 DCL_TYPE (ltype) == POINTER)
8126 genDataPointerGet (left, result, ic);
8130 /* if the value is already in a pointer register
8131 then don't need anything more */
8132 if (!AOP_INPREG (AOP (left)))
8134 if (IS_AOP_PREG (left))
8136 // Aha, it is a pointer, just in disguise.
8137 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8140 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8141 __FILE__, __LINE__);
8146 emitcode ("mov", "a%s,%s", rname + 1, rname);
8147 rname++; // skip the '@'.
8152 /* otherwise get a free pointer register */
8154 preg = getFreePtr (ic, &aop, FALSE);
8155 emitcode ("mov", "%s,%s",
8157 aopGet (AOP (left), 0, FALSE, TRUE));
8162 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8164 //aopOp (result, ic, FALSE);
8165 aopOp (result, ic, result?TRUE:FALSE);
8167 /* if bitfield then unpack the bits */
8168 if (IS_BITFIELD (retype))
8169 genUnpackBits (result, rname, POINTER);
8172 /* we have can just get the values */
8173 int size = AOP_SIZE (result);
8178 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8181 emitcode ("mov", "a,@%s", rname);
8182 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8186 sprintf (buffer, "@%s", rname);
8187 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8191 emitcode ("inc", "%s", rname);
8195 /* now some housekeeping stuff */
8196 if (aop) /* we had to allocate for this iCode */
8198 if (pi) { /* post increment present */
8199 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8201 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8205 /* we did not allocate which means left
8206 already in a pointer register, then
8207 if size > 0 && this could be used again
8208 we have to point it back to where it
8210 if ((AOP_SIZE (result) > 1 &&
8211 !OP_SYMBOL (left)->remat &&
8212 (OP_SYMBOL (left)->liveTo > ic->seq ||
8216 int size = AOP_SIZE (result) - 1;
8218 emitcode ("dec", "%s", rname);
8223 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8224 freeAsmop (left, NULL, ic, TRUE);
8225 if (pi) pi->generated = 1;
8228 /*-----------------------------------------------------------------*/
8229 /* genPagedPointerGet - emitcode for paged pointer fetch */
8230 /*-----------------------------------------------------------------*/
8232 genPagedPointerGet (operand * left,
8240 sym_link *rtype, *retype;
8242 D(emitcode ("; genPagedPointerGet",""));
8244 rtype = operandType (result);
8245 retype = getSpec (rtype);
8247 aopOp (left, ic, FALSE);
8249 /* if the value is already in a pointer register
8250 then don't need anything more */
8251 if (!AOP_INPREG (AOP (left)))
8253 /* otherwise get a free pointer register */
8255 preg = getFreePtr (ic, &aop, FALSE);
8256 emitcode ("mov", "%s,%s",
8258 aopGet (AOP (left), 0, FALSE, TRUE));
8262 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8264 aopOp (result, ic, FALSE);
8266 /* if bitfield then unpack the bits */
8267 if (IS_BITFIELD (retype))
8268 genUnpackBits (result, rname, PPOINTER);
8271 /* we have can just get the values */
8272 int size = AOP_SIZE (result);
8278 emitcode ("movx", "a,@%s", rname);
8279 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8284 emitcode ("inc", "%s", rname);
8288 /* now some housekeeping stuff */
8289 if (aop) /* we had to allocate for this iCode */
8291 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8292 freeAsmop (NULL, aop, ic, TRUE);
8296 /* we did not allocate which means left
8297 already in a pointer register, then
8298 if size > 0 && this could be used again
8299 we have to point it back to where it
8301 if ((AOP_SIZE (result) > 1 &&
8302 !OP_SYMBOL (left)->remat &&
8303 (OP_SYMBOL (left)->liveTo > ic->seq ||
8307 int size = AOP_SIZE (result) - 1;
8309 emitcode ("dec", "%s", rname);
8314 freeAsmop (left, NULL, ic, TRUE);
8315 freeAsmop (result, NULL, ic, TRUE);
8316 if (pi) pi->generated = 1;
8320 /*--------------------------------------------------------------------*/
8321 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8322 /*--------------------------------------------------------------------*/
8324 loadDptrFromOperand (operand *op, bool loadBToo)
8326 if (AOP_TYPE (op) != AOP_STR)
8328 /* if this is remateriazable */
8329 if (AOP_TYPE (op) == AOP_IMMD)
8331 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8334 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8335 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8338 wassertl(FALSE, "need pointerCode");
8339 emitcode ("", "; mov b,???");
8340 /* genPointerGet and genPointerSet originally did different
8341 ** things for this case. Both seem wrong.
8342 ** from genPointerGet:
8343 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8344 ** from genPointerSet:
8345 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8350 else if (AOP_TYPE (op) == AOP_DPTR)
8354 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8355 emitcode ("push", "acc");
8356 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8357 emitcode ("push", "acc");
8358 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8359 emitcode ("pop", "dph");
8360 emitcode ("pop", "dpl");
8364 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8365 emitcode ("push", "acc");
8366 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8367 emitcode ("pop", "dpl");
8371 { /* we need to get it byte by byte */
8372 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8373 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8375 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8380 /*-----------------------------------------------------------------*/
8381 /* genFarPointerGet - gget value from far space */
8382 /*-----------------------------------------------------------------*/
8384 genFarPointerGet (operand * left,
8385 operand * result, iCode * ic, iCode * pi)
8388 sym_link *retype = getSpec (operandType (result));
8390 D(emitcode ("; genFarPointerGet",""));
8392 aopOp (left, ic, FALSE);
8393 loadDptrFromOperand (left, FALSE);
8395 /* so dptr now contains the address */
8396 aopOp (result, ic, FALSE);
8398 /* if bit then unpack */
8399 if (IS_BITFIELD (retype))
8400 genUnpackBits (result, "dptr", FPOINTER);
8403 size = AOP_SIZE (result);
8408 emitcode ("movx", "a,@dptr");
8409 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8411 emitcode ("inc", "dptr");
8415 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8416 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8417 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8420 freeAsmop (left, NULL, ic, TRUE);
8421 freeAsmop (result, NULL, ic, TRUE);
8424 /*-----------------------------------------------------------------*/
8425 /* genCodePointerGet - gget value from code space */
8426 /*-----------------------------------------------------------------*/
8428 genCodePointerGet (operand * left,
8429 operand * result, iCode * ic, iCode *pi)
8432 sym_link *retype = getSpec (operandType (result));
8434 D(emitcode ("; genCodePointerGet",""));
8436 aopOp (left, ic, FALSE);
8437 loadDptrFromOperand (left, FALSE);
8439 /* so dptr now contains the address */
8440 aopOp (result, ic, FALSE);
8442 /* if bit then unpack */
8443 if (IS_BITFIELD (retype))
8444 genUnpackBits (result, "dptr", CPOINTER);
8447 size = AOP_SIZE (result);
8454 emitcode ("clr", "a");
8455 emitcode ("movc", "a,@a+dptr");
8456 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8457 emitcode ("inc", "dptr");
8461 emitcode ("mov", "a,#0x%02x", offset);
8462 emitcode ("movc", "a,@a+dptr");
8463 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8468 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8469 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8470 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8473 freeAsmop (left, NULL, ic, TRUE);
8474 freeAsmop (result, NULL, ic, TRUE);
8477 /*-----------------------------------------------------------------*/
8478 /* genGenPointerGet - gget value from generic pointer space */
8479 /*-----------------------------------------------------------------*/
8481 genGenPointerGet (operand * left,
8482 operand * result, iCode * ic, iCode *pi)
8485 sym_link *retype = getSpec (operandType (result));
8487 D(emitcode ("; genGenPointerGet",""));
8489 aopOp (left, ic, FALSE);
8490 loadDptrFromOperand (left, TRUE);
8492 /* so dptr know contains the address */
8493 aopOp (result, ic, FALSE);
8495 /* if bit then unpack */
8496 if (IS_BITFIELD (retype))
8497 genUnpackBits (result, "dptr", GPOINTER);
8500 size = AOP_SIZE (result);
8505 emitcode ("lcall", "__gptrget");
8506 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8508 emitcode ("inc", "dptr");
8512 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8513 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8514 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8517 freeAsmop (left, NULL, ic, TRUE);
8518 freeAsmop (result, NULL, ic, TRUE);
8521 /*-----------------------------------------------------------------*/
8522 /* genPointerGet - generate code for pointer get */
8523 /*-----------------------------------------------------------------*/
8525 genPointerGet (iCode * ic, iCode *pi)
8527 operand *left, *result;
8528 sym_link *type, *etype;
8531 D(emitcode ("; genPointerGet",""));
8533 left = IC_LEFT (ic);
8534 result = IC_RESULT (ic);
8536 /* depending on the type of pointer we need to
8537 move it to the correct pointer register */
8538 type = operandType (left);
8539 etype = getSpec (type);
8540 /* if left is of type of pointer then it is simple */
8541 if (IS_PTR (type) && !IS_FUNC (type->next))
8542 p_type = DCL_TYPE (type);
8545 /* we have to go by the storage class */
8546 p_type = PTR_TYPE (SPEC_OCLS (etype));
8549 /* special case when cast remat */
8550 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8551 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8552 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8553 type = operandType (left);
8554 p_type = DCL_TYPE (type);
8556 /* now that we have the pointer type we assign
8557 the pointer values */
8563 genNearPointerGet (left, result, ic, pi);
8567 genPagedPointerGet (left, result, ic, pi);
8571 genFarPointerGet (left, result, ic, pi);
8575 genCodePointerGet (left, result, ic, pi);
8579 genGenPointerGet (left, result, ic, pi);
8587 /*-----------------------------------------------------------------*/
8588 /* genPackBits - generates code for packed bit storage */
8589 /*-----------------------------------------------------------------*/
8591 genPackBits (sym_link * etype,
8593 char *rname, int p_type)
8595 int offset = 0; /* source byte offset */
8596 int rlen = 0; /* remaining bitfield length */
8597 int blen; /* bitfield length */
8598 int bstr; /* bitfield starting bit within byte */
8599 int litval; /* source literal value (if AOP_LIT) */
8600 unsigned char mask; /* bitmask within current byte */
8602 D(emitcode ("; genPackBits",""));
8604 blen = SPEC_BLEN (etype);
8605 bstr = SPEC_BSTR (etype);
8607 /* If the bitfield length is less than a byte */
8610 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8611 (unsigned char) (0xFF >> (8 - bstr)));
8613 if (AOP_TYPE (right) == AOP_LIT)
8615 /* Case with a bitfield length <8 and literal source
8617 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8619 litval &= (~mask) & 0xff;
8620 emitPtrByteGet (rname, p_type, FALSE);
8621 if ((mask|litval)!=0xff)
8622 emitcode ("anl","a,#0x%02x", mask);
8624 emitcode ("orl","a,#0x%02x", litval);
8628 if ((blen==1) && (p_type!=GPOINTER))
8630 /* Case with a bitfield length == 1 and no generic pointer
8632 if (AOP_TYPE (right) == AOP_CRY)
8633 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8636 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8637 emitcode ("rrc","a");
8639 emitPtrByteGet (rname, p_type, FALSE);
8640 emitcode ("mov","acc.%d,c",bstr);
8644 /* Case with a bitfield length < 8 and arbitrary source
8646 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8647 /* shift and mask source value */
8649 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8651 /* transfer A to B and get next byte */
8652 emitPtrByteGet (rname, p_type, TRUE);
8654 emitcode ("anl", "a,#0x%02x", mask);
8655 emitcode ("orl", "a,b");
8656 if (p_type == GPOINTER)
8657 emitcode ("pop", "b");
8661 emitPtrByteSet (rname, p_type, "a");
8665 /* Bit length is greater than 7 bits. In this case, copy */
8666 /* all except the partial byte at the end */
8667 for (rlen=blen;rlen>=8;rlen-=8)
8669 emitPtrByteSet (rname, p_type,
8670 aopGet (AOP (right), offset++, FALSE, TRUE) );
8672 emitcode ("inc", "%s", rname);
8675 /* If there was a partial byte at the end */
8678 mask = (((unsigned char) -1 << rlen) & 0xff);
8680 if (AOP_TYPE (right) == AOP_LIT)
8682 /* Case with partial byte and literal source
8684 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8685 litval >>= (blen-rlen);
8686 litval &= (~mask) & 0xff;
8687 emitPtrByteGet (rname, p_type, FALSE);
8688 if ((mask|litval)!=0xff)
8689 emitcode ("anl","a,#0x%02x", mask);
8691 emitcode ("orl","a,#0x%02x", litval);
8695 /* Case with partial byte and arbitrary source
8697 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8698 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8700 /* transfer A to B and get next byte */
8701 emitPtrByteGet (rname, p_type, TRUE);
8703 emitcode ("anl", "a,#0x%02x", mask);
8704 emitcode ("orl", "a,b");
8705 if (p_type == GPOINTER)
8706 emitcode ("pop", "b");
8708 emitPtrByteSet (rname, p_type, "a");
8714 /*-----------------------------------------------------------------*/
8715 /* genDataPointerSet - remat pointer to data space */
8716 /*-----------------------------------------------------------------*/
8718 genDataPointerSet (operand * right,
8722 int size, offset = 0;
8723 char *l, buffer[256];
8725 D(emitcode ("; genDataPointerSet",""));
8727 aopOp (right, ic, FALSE);
8729 l = aopGet (AOP (result), 0, FALSE, TRUE);
8730 size = AOP_SIZE (right);
8734 sprintf (buffer, "(%s + %d)", l + 1, offset);
8736 sprintf (buffer, "%s", l + 1);
8737 emitcode ("mov", "%s,%s", buffer,
8738 aopGet (AOP (right), offset++, FALSE, FALSE));
8741 freeAsmop (right, NULL, ic, TRUE);
8742 freeAsmop (result, NULL, ic, TRUE);
8745 /*-----------------------------------------------------------------*/
8746 /* genNearPointerSet - emitcode for near pointer put */
8747 /*-----------------------------------------------------------------*/
8749 genNearPointerSet (operand * right,
8757 sym_link *retype, *letype;
8758 sym_link *ptype = operandType (result);
8760 D(emitcode ("; genNearPointerSet",""));
8762 retype = getSpec (operandType (right));
8763 letype = getSpec (ptype);
8764 aopOp (result, ic, FALSE);
8766 /* if the result is rematerializable &
8767 in data space & not a bit variable */
8768 if (AOP_TYPE (result) == AOP_IMMD &&
8769 DCL_TYPE (ptype) == POINTER &&
8770 !IS_BITVAR (retype) &&
8771 !IS_BITVAR (letype))
8773 genDataPointerSet (right, result, ic);
8777 /* if the value is already in a pointer register
8778 then don't need anything more */
8779 if (!AOP_INPREG (AOP (result)))
8782 //AOP_TYPE (result) == AOP_STK
8786 // Aha, it is a pointer, just in disguise.
8787 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8790 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8791 __FILE__, __LINE__);
8796 emitcode ("mov", "a%s,%s", rname + 1, rname);
8797 rname++; // skip the '@'.
8802 /* otherwise get a free pointer register */
8804 preg = getFreePtr (ic, &aop, FALSE);
8805 emitcode ("mov", "%s,%s",
8807 aopGet (AOP (result), 0, FALSE, TRUE));
8813 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8816 aopOp (right, ic, FALSE);
8818 /* if bitfield then unpack the bits */
8819 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8820 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8823 /* we have can just get the values */
8824 int size = AOP_SIZE (right);
8829 l = aopGet (AOP (right), offset, FALSE, TRUE);
8833 emitcode ("mov", "@%s,a", rname);
8836 emitcode ("mov", "@%s,%s", rname, l);
8838 emitcode ("inc", "%s", rname);
8843 /* now some housekeeping stuff */
8844 if (aop) /* we had to allocate for this iCode */
8847 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8848 freeAsmop (NULL, aop, ic, TRUE);
8852 /* we did not allocate which means left
8853 already in a pointer register, then
8854 if size > 0 && this could be used again
8855 we have to point it back to where it
8857 if ((AOP_SIZE (right) > 1 &&
8858 !OP_SYMBOL (result)->remat &&
8859 (OP_SYMBOL (result)->liveTo > ic->seq ||
8863 int size = AOP_SIZE (right) - 1;
8865 emitcode ("dec", "%s", rname);
8870 if (pi) pi->generated = 1;
8871 freeAsmop (result, NULL, ic, TRUE);
8872 freeAsmop (right, NULL, ic, TRUE);
8875 /*-----------------------------------------------------------------*/
8876 /* genPagedPointerSet - emitcode for Paged pointer put */
8877 /*-----------------------------------------------------------------*/
8879 genPagedPointerSet (operand * right,
8887 sym_link *retype, *letype;
8889 D(emitcode ("; genPagedPointerSet",""));
8891 retype = getSpec (operandType (right));
8892 letype = getSpec (operandType (result));
8894 aopOp (result, ic, FALSE);
8896 /* if the value is already in a pointer register
8897 then don't need anything more */
8898 if (!AOP_INPREG (AOP (result)))
8900 /* otherwise get a free pointer register */
8902 preg = getFreePtr (ic, &aop, FALSE);
8903 emitcode ("mov", "%s,%s",
8905 aopGet (AOP (result), 0, FALSE, TRUE));
8909 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8911 aopOp (right, ic, FALSE);
8913 /* if bitfield then unpack the bits */
8914 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8915 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8918 /* we have can just get the values */
8919 int size = AOP_SIZE (right);
8924 l = aopGet (AOP (right), offset, FALSE, TRUE);
8927 emitcode ("movx", "@%s,a", rname);
8930 emitcode ("inc", "%s", rname);
8936 /* now some housekeeping stuff */
8937 if (aop) /* we had to allocate for this iCode */
8940 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8941 freeAsmop (NULL, aop, ic, TRUE);
8945 /* we did not allocate which means left
8946 already in a pointer register, then
8947 if size > 0 && this could be used again
8948 we have to point it back to where it
8950 if (AOP_SIZE (right) > 1 &&
8951 !OP_SYMBOL (result)->remat &&
8952 (OP_SYMBOL (result)->liveTo > ic->seq ||
8955 int size = AOP_SIZE (right) - 1;
8957 emitcode ("dec", "%s", rname);
8962 if (pi) pi->generated = 1;
8963 freeAsmop (result, NULL, ic, TRUE);
8964 freeAsmop (right, NULL, ic, TRUE);
8969 /*-----------------------------------------------------------------*/
8970 /* genFarPointerSet - set value from far space */
8971 /*-----------------------------------------------------------------*/
8973 genFarPointerSet (operand * right,
8974 operand * result, iCode * ic, iCode * pi)
8977 sym_link *retype = getSpec (operandType (right));
8978 sym_link *letype = getSpec (operandType (result));
8980 D(emitcode ("; genFarPointerSet",""));
8982 aopOp (result, ic, FALSE);
8983 loadDptrFromOperand (result, FALSE);
8985 /* so dptr know contains the address */
8986 aopOp (right, ic, FALSE);
8988 /* if bit then unpack */
8989 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8990 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8993 size = AOP_SIZE (right);
8998 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9000 emitcode ("movx", "@dptr,a");
9002 emitcode ("inc", "dptr");
9005 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9006 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9007 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9010 freeAsmop (result, NULL, ic, TRUE);
9011 freeAsmop (right, NULL, ic, TRUE);
9014 /*-----------------------------------------------------------------*/
9015 /* genGenPointerSet - set value from generic pointer space */
9016 /*-----------------------------------------------------------------*/
9018 genGenPointerSet (operand * right,
9019 operand * result, iCode * ic, iCode * pi)
9022 sym_link *retype = getSpec (operandType (right));
9023 sym_link *letype = getSpec (operandType (result));
9025 D(emitcode ("; genGenPointerSet",""));
9027 aopOp (result, ic, FALSE);
9028 loadDptrFromOperand (result, TRUE);
9030 /* so dptr know contains the address */
9031 aopOp (right, ic, FALSE);
9033 /* if bit then unpack */
9034 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9035 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9038 size = AOP_SIZE (right);
9043 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9045 emitcode ("lcall", "__gptrput");
9047 emitcode ("inc", "dptr");
9051 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9052 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9053 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9056 freeAsmop (result, NULL, ic, TRUE);
9057 freeAsmop (right, NULL, ic, TRUE);
9060 /*-----------------------------------------------------------------*/
9061 /* genPointerSet - stores the value into a pointer location */
9062 /*-----------------------------------------------------------------*/
9064 genPointerSet (iCode * ic, iCode *pi)
9066 operand *right, *result;
9067 sym_link *type, *etype;
9070 D(emitcode ("; genPointerSet",""));
9072 right = IC_RIGHT (ic);
9073 result = IC_RESULT (ic);
9075 /* depending on the type of pointer we need to
9076 move it to the correct pointer register */
9077 type = operandType (result);
9078 etype = getSpec (type);
9079 /* if left is of type of pointer then it is simple */
9080 if (IS_PTR (type) && !IS_FUNC (type->next))
9082 p_type = DCL_TYPE (type);
9086 /* we have to go by the storage class */
9087 p_type = PTR_TYPE (SPEC_OCLS (etype));
9090 /* special case when cast remat */
9091 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9092 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9093 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9094 type = operandType (result);
9095 p_type = DCL_TYPE (type);
9097 /* now that we have the pointer type we assign
9098 the pointer values */
9104 genNearPointerSet (right, result, ic, pi);
9108 genPagedPointerSet (right, result, ic, pi);
9112 genFarPointerSet (right, result, ic, pi);
9116 genGenPointerSet (right, result, ic, pi);
9120 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9121 "genPointerSet: illegal pointer type");
9126 /*-----------------------------------------------------------------*/
9127 /* genIfx - generate code for Ifx statement */
9128 /*-----------------------------------------------------------------*/
9130 genIfx (iCode * ic, iCode * popIc)
9132 operand *cond = IC_COND (ic);
9135 D(emitcode ("; genIfx",""));
9137 aopOp (cond, ic, FALSE);
9139 /* get the value into acc */
9140 if (AOP_TYPE (cond) != AOP_CRY)
9144 /* the result is now in the accumulator */
9145 freeAsmop (cond, NULL, ic, TRUE);
9147 /* if there was something to be popped then do it */
9151 /* if the condition is a bit variable */
9152 if (isbit && IS_ITEMP (cond) &&
9154 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9155 else if (isbit && !IS_ITEMP (cond))
9156 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9158 genIfxJump (ic, "a", NULL, NULL, NULL);
9163 /*-----------------------------------------------------------------*/
9164 /* genAddrOf - generates code for address of */
9165 /*-----------------------------------------------------------------*/
9167 genAddrOf (iCode * ic)
9169 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9172 D(emitcode ("; genAddrOf",""));
9174 aopOp (IC_RESULT (ic), ic, FALSE);
9176 /* if the operand is on the stack then we
9177 need to get the stack offset of this
9181 /* if it has an offset then we need to compute
9185 emitcode ("mov", "a,_bp");
9186 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9187 ((char) (sym->stack - _G.nRegsSaved)) :
9188 ((char) sym->stack)) & 0xff);
9189 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9193 /* we can just move _bp */
9194 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9196 /* fill the result with zero */
9197 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9202 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9208 /* object not on stack then we need the name */
9209 size = AOP_SIZE (IC_RESULT (ic));
9214 char s[SDCC_NAME_MAX];
9216 sprintf (s, "#(%s >> %d)",
9220 sprintf (s, "#%s", sym->rname);
9221 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9229 /*-----------------------------------------------------------------*/
9230 /* genFarFarAssign - assignment when both are in far space */
9231 /*-----------------------------------------------------------------*/
9233 genFarFarAssign (operand * result, operand * right, iCode * ic)
9235 int size = AOP_SIZE (right);
9239 D(emitcode ("; genFarFarAssign",""));
9241 /* first push the right side on to the stack */
9244 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9246 emitcode ("push", "acc");
9249 freeAsmop (right, NULL, ic, FALSE);
9250 /* now assign DPTR to result */
9251 aopOp (result, ic, FALSE);
9252 size = AOP_SIZE (result);
9255 emitcode ("pop", "acc");
9256 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9258 freeAsmop (result, NULL, ic, FALSE);
9262 /*-----------------------------------------------------------------*/
9263 /* genAssign - generate code for assignment */
9264 /*-----------------------------------------------------------------*/
9266 genAssign (iCode * ic)
9268 operand *result, *right;
9270 unsigned long lit = 0L;
9272 D(emitcode("; genAssign",""));
9274 result = IC_RESULT (ic);
9275 right = IC_RIGHT (ic);
9277 /* if they are the same */
9278 if (operandsEqu (result, right) &&
9279 !isOperandVolatile (result, FALSE) &&
9280 !isOperandVolatile (right, FALSE))
9283 aopOp (right, ic, FALSE);
9285 /* special case both in far space */
9286 if (AOP_TYPE (right) == AOP_DPTR &&
9287 IS_TRUE_SYMOP (result) &&
9288 isOperandInFarSpace (result))
9291 genFarFarAssign (result, right, ic);
9295 aopOp (result, ic, TRUE);
9297 /* if they are the same registers */
9298 if (sameRegs (AOP (right), AOP (result)) &&
9299 !isOperandVolatile (result, FALSE) &&
9300 !isOperandVolatile (right, FALSE))
9303 /* if the result is a bit */
9304 if (AOP_TYPE (result) == AOP_CRY)
9307 /* if the right size is a literal then
9308 we know what the value is */
9309 if (AOP_TYPE (right) == AOP_LIT)
9311 if (((int) operandLitValue (right)))
9312 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9314 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9318 /* the right is also a bit variable */
9319 if (AOP_TYPE (right) == AOP_CRY)
9321 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9322 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9328 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9332 /* bit variables done */
9334 size = AOP_SIZE (result);
9336 if (AOP_TYPE (right) == AOP_LIT)
9337 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9339 (AOP_TYPE (result) != AOP_REG) &&
9340 (AOP_TYPE (right) == AOP_LIT) &&
9341 !IS_FLOAT (operandType (right)) &&
9344 emitcode ("clr", "a");
9347 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9348 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9350 aopPut (AOP (result),
9351 aopGet (AOP (right), size, FALSE, FALSE),
9353 isOperandVolatile (result, FALSE));
9360 aopPut (AOP (result),
9361 aopGet (AOP (right), offset, FALSE, FALSE),
9363 isOperandVolatile (result, FALSE));
9369 freeAsmop (right, NULL, ic, TRUE);
9370 freeAsmop (result, NULL, ic, TRUE);
9373 /*-----------------------------------------------------------------*/
9374 /* genJumpTab - genrates code for jump table */
9375 /*-----------------------------------------------------------------*/
9377 genJumpTab (iCode * ic)
9382 D(emitcode ("; genJumpTab",""));
9384 aopOp (IC_JTCOND (ic), ic, FALSE);
9385 /* get the condition into accumulator */
9386 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9388 /* multiply by three */
9389 emitcode ("add", "a,acc");
9390 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9391 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9393 jtab = newiTempLabel (NULL);
9394 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9395 emitcode ("jmp", "@a+dptr");
9396 emitcode ("", "%05d$:", jtab->key + 100);
9397 /* now generate the jump labels */
9398 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9399 jtab = setNextItem (IC_JTLABELS (ic)))
9400 emitcode ("ljmp", "%05d$", jtab->key + 100);
9404 /*-----------------------------------------------------------------*/
9405 /* genCast - gen code for casting */
9406 /*-----------------------------------------------------------------*/
9408 genCast (iCode * ic)
9410 operand *result = IC_RESULT (ic);
9411 sym_link *ctype = operandType (IC_LEFT (ic));
9412 sym_link *rtype = operandType (IC_RIGHT (ic));
9413 operand *right = IC_RIGHT (ic);
9416 D(emitcode("; genCast",""));
9418 /* if they are equivalent then do nothing */
9419 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9422 aopOp (right, ic, FALSE);
9423 aopOp (result, ic, FALSE);
9425 /* if the result is a bit (and not a bitfield) */
9426 // if (AOP_TYPE (result) == AOP_CRY)
9427 if (IS_BITVAR (OP_SYMBOL (result)->type)
9428 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9430 /* if the right size is a literal then
9431 we know what the value is */
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 if (((int) operandLitValue (right)))
9435 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9437 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9442 /* the right is also a bit variable */
9443 if (AOP_TYPE (right) == AOP_CRY)
9445 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9446 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9452 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9457 /* if they are the same size : or less */
9458 if (AOP_SIZE (result) <= AOP_SIZE (right))
9461 /* if they are in the same place */
9462 if (sameRegs (AOP (right), AOP (result)))
9465 /* if they in different places then copy */
9466 size = AOP_SIZE (result);
9470 aopPut (AOP (result),
9471 aopGet (AOP (right), offset, FALSE, FALSE),
9473 isOperandVolatile (result, FALSE));
9480 /* if the result is of type pointer */
9485 sym_link *type = operandType (right);
9486 sym_link *etype = getSpec (type);
9488 /* pointer to generic pointer */
9489 if (IS_GENPTR (ctype))
9492 p_type = DCL_TYPE (type);
9495 if (SPEC_SCLS(etype)==S_REGISTER) {
9496 // let's assume it is a generic pointer
9499 /* we have to go by the storage class */
9500 p_type = PTR_TYPE (SPEC_OCLS (etype));
9504 /* the first two bytes are known */
9505 size = GPTRSIZE - 1;
9509 aopPut (AOP (result),
9510 aopGet (AOP (right), offset, FALSE, FALSE),
9512 isOperandVolatile (result, FALSE));
9515 /* the last byte depending on type */
9517 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9522 // pointerTypeToGPByte will have bitched.
9526 sprintf(gpValStr, "#0x%d", gpVal);
9527 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9532 /* just copy the pointers */
9533 size = AOP_SIZE (result);
9537 aopPut (AOP (result),
9538 aopGet (AOP (right), offset, FALSE, FALSE),
9540 isOperandVolatile (result, FALSE));
9546 /* so we now know that the size of destination is greater
9547 than the size of the source */
9548 /* we move to result for the size of source */
9549 size = AOP_SIZE (right);
9553 aopPut (AOP (result),
9554 aopGet (AOP (right), offset, FALSE, FALSE),
9556 isOperandVolatile (result, FALSE));
9560 /* now depending on the sign of the source && destination */
9561 size = AOP_SIZE (result) - AOP_SIZE (right);
9562 /* if unsigned or not an integral type */
9563 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9566 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9570 /* we need to extend the sign :{ */
9571 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9574 emitcode ("rlc", "a");
9575 emitcode ("subb", "a,acc");
9577 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9580 /* we are done hurray !!!! */
9583 freeAsmop (right, NULL, ic, TRUE);
9584 freeAsmop (result, NULL, ic, TRUE);
9588 /*-----------------------------------------------------------------*/
9589 /* genDjnz - generate decrement & jump if not zero instrucion */
9590 /*-----------------------------------------------------------------*/
9592 genDjnz (iCode * ic, iCode * ifx)
9598 D(emitcode ("; genDjnz",""));
9600 /* if the if condition has a false label
9601 then we cannot save */
9605 /* if the minus is not of the form
9607 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9608 !IS_OP_LITERAL (IC_RIGHT (ic)))
9611 if (operandLitValue (IC_RIGHT (ic)) != 1)
9614 /* if the size of this greater than one then no
9616 if (getSize (operandType (IC_RESULT (ic))) > 1)
9619 /* otherwise we can save BIG */
9620 lbl = newiTempLabel (NULL);
9621 lbl1 = newiTempLabel (NULL);
9623 aopOp (IC_RESULT (ic), ic, FALSE);
9625 if (AOP_NEEDSACC(IC_RESULT(ic)))
9627 /* If the result is accessed indirectly via
9628 * the accumulator, we must explicitly write
9629 * it back after the decrement.
9631 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9633 if (strcmp(rByte, "a"))
9635 /* Something is hopelessly wrong */
9636 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9637 __FILE__, __LINE__);
9638 /* We can just give up; the generated code will be inefficient,
9641 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9644 emitcode ("dec", "%s", rByte);
9645 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9646 emitcode ("jnz", "%05d$", lbl->key + 100);
9648 else if (IS_AOP_PREG (IC_RESULT (ic)))
9650 emitcode ("dec", "%s",
9651 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9652 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9653 emitcode ("jnz", "%05d$", lbl->key + 100);
9657 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9660 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9661 emitcode ("", "%05d$:", lbl->key + 100);
9662 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9663 emitcode ("", "%05d$:", lbl1->key + 100);
9665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9670 /*-----------------------------------------------------------------*/
9671 /* genReceive - generate code for a receive iCode */
9672 /*-----------------------------------------------------------------*/
9674 genReceive (iCode * ic)
9676 int size = getSize (operandType (IC_RESULT (ic)));
9678 D(emitcode ("; genReceive",""));
9680 if (ic->argreg == 1) { /* first parameter */
9681 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9682 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9683 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9689 for (offset = 0; offset<size; offset++)
9690 if (!strcmp (fReturn[offset], "a"))
9695 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9697 for (offset = size-1; offset>0; offset--)
9698 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9699 emitcode("mov","a,%s", fReturn[0]);
9701 aopOp (IC_RESULT (ic), ic, FALSE);
9703 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9704 isOperandVolatile (IC_RESULT (ic), FALSE));
9705 for (offset = 1; offset<size; offset++)
9706 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9707 isOperandVolatile (IC_RESULT (ic), FALSE));
9713 if (getTempRegs(tempRegs, size, ic))
9715 for (offset = 0; offset<size; offset++)
9716 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9717 aopOp (IC_RESULT (ic), ic, FALSE);
9718 for (offset = 0; offset<size; offset++)
9719 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9720 isOperandVolatile (IC_RESULT (ic), FALSE));
9725 offset = fReturnSizeMCS51 - size;
9727 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9728 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9731 aopOp (IC_RESULT (ic), ic, FALSE);
9732 size = AOP_SIZE (IC_RESULT (ic));
9735 emitcode ("pop", "acc");
9736 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9741 aopOp (IC_RESULT (ic), ic, FALSE);
9743 assignResultValue (IC_RESULT (ic));
9745 } else { /* second receive onwards */
9747 aopOp (IC_RESULT (ic), ic, FALSE);
9748 rb1off = ic->argreg;
9750 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9755 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9758 /*-----------------------------------------------------------------*/
9759 /* genDummyRead - generate code for dummy read of volatiles */
9760 /*-----------------------------------------------------------------*/
9762 genDummyRead (iCode * ic)
9767 D(emitcode("; genDummyRead",""));
9770 if (op && IS_SYMOP (op))
9772 aopOp (op, ic, FALSE);
9774 /* if the result is a bit */
9775 if (AOP_TYPE (op) == AOP_CRY)
9776 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9779 /* bit variables done */
9781 size = AOP_SIZE (op);
9785 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9790 freeAsmop (op, NULL, ic, TRUE);
9794 if (op && IS_SYMOP (op))
9796 aopOp (op, ic, FALSE);
9798 /* if the result is a bit */
9799 if (AOP_TYPE (op) == AOP_CRY)
9800 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9803 /* bit variables done */
9805 size = AOP_SIZE (op);
9809 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9814 freeAsmop (op, NULL, ic, TRUE);
9818 /*-----------------------------------------------------------------*/
9819 /* genCritical - generate code for start of a critical sequence */
9820 /*-----------------------------------------------------------------*/
9822 genCritical (iCode *ic)
9824 symbol *tlbl = newiTempLabel (NULL);
9826 D(emitcode("; genCritical",""));
9829 aopOp (IC_RESULT (ic), ic, TRUE);
9831 emitcode ("setb", "c");
9832 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9833 emitcode ("clr", "c");
9834 emitcode ("", "%05d$:", (tlbl->key + 100));
9837 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9839 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9845 /*-----------------------------------------------------------------*/
9846 /* genEndCritical - generate code for end of a critical sequence */
9847 /*-----------------------------------------------------------------*/
9849 genEndCritical (iCode *ic)
9851 D(emitcode("; genEndCritical",""));
9855 aopOp (IC_RIGHT (ic), ic, FALSE);
9856 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9858 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9859 emitcode ("mov", "ea,c");
9863 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9864 emitcode ("rrc", "a");
9865 emitcode ("mov", "ea,c");
9867 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9871 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9872 emitcode ("mov", "ea,c");
9876 /*-----------------------------------------------------------------*/
9877 /* gen51Code - generate code for 8051 based controllers */
9878 /*-----------------------------------------------------------------*/
9880 gen51Code (iCode * lic)
9886 _G.currentFunc = NULL;
9887 lineHead = lineCurr = NULL;
9889 /* print the allocation information */
9890 if (allocInfo && currFunc)
9891 printAllocInfo (currFunc, codeOutFile);
9892 /* if debug information required */
9893 if (options.debug && currFunc)
9895 debugFile->writeFunction (currFunc, lic);
9897 /* stack pointer name */
9898 if (options.useXstack)
9904 for (ic = lic; ic; ic = ic->next)
9906 _G.current_iCode = ic;
9908 if (ic->lineno && cln != ic->lineno)
9912 debugFile->writeCLine(ic);
9914 if (!options.noCcodeInAsm) {
9915 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9916 printCLine(ic->filename, ic->lineno));
9921 if (ic->seqPoint && ic->seqPoint != cseq)
9923 emitcode ("", "; sequence point %d", ic->seqPoint);
9924 cseq = ic->seqPoint;
9927 if (options.iCodeInAsm) {
9931 for (i=0; i<8; i++) {
9932 sprintf (®sInUse[i],
9933 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9936 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9938 /* if the result is marked as
9939 spilt and rematerializable or code for
9940 this has already been generated then
9942 if (resultRemat (ic) || ic->generated)
9945 /* depending on the operation */
9965 /* IPOP happens only when trying to restore a
9966 spilt live range, if there is an ifx statement
9967 following this pop then the if statement might
9968 be using some of the registers being popped which
9969 would destory the contents of the register so
9970 we need to check for this condition and handle it */
9972 ic->next->op == IFX &&
9973 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9974 genIfx (ic->next, ic);
9992 genEndFunction (ic);
10012 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10029 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10033 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10040 /* note these two are xlated by algebraic equivalence
10041 during parsing SDCC.y */
10042 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10043 "got '>=' or '<=' shouldn't have come here");
10047 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10059 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10063 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10067 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10091 genRightShift (ic);
10094 case GET_VALUE_AT_ADDRESS:
10095 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10099 if (POINTER_SET (ic))
10100 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10126 addSet (&_G.sendSet, ic);
10129 case DUMMY_READ_VOLATILE:
10138 genEndCritical (ic);
10150 _G.current_iCode = NULL;
10152 /* now we are ready to call the
10153 peep hole optimizer */
10154 if (!options.nopeep)
10155 peepHole (&lineHead);
10157 /* now do the actual printing */
10158 printLine (lineHead, codeOutFile);