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;
81 static char *rb1regs[] = {
82 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
85 extern int mcs51_ptrRegReq;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saveRBank (int, iCode *, bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
94 #define CLRC emitcode("clr","c")
95 #define SETC emitcode("setb","c")
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
100 static unsigned char SLMask[] =
101 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] =
104 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105 0x07, 0x03, 0x01, 0x00};
112 /*-----------------------------------------------------------------*/
113 /* emitcode - writes the code into a file : for now it is simple */
114 /*-----------------------------------------------------------------*/
116 emitcode (char *inst, const char *fmt,...)
119 char lb[INITIAL_INLINEASM];
127 sprintf (lb, "%s\t", inst);
129 sprintf (lb, "%s", inst);
130 vsprintf (lb + (strlen (lb)), fmt, ap);
133 vsprintf (lb, fmt, ap);
135 while (isspace (*lbp))
138 // printf ("%s\n", lb);
141 lineCurr = (lineCurr ?
142 connectLine (lineCurr, newLineNode (lb)) :
143 (lineHead = newLineNode (lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
146 lineCurr->ic = _G.current_iCode;
147 lineCurr->isComment = (*lbp==';');
151 /*-----------------------------------------------------------------*/
152 /* mova - moves specified value into accumulator */
153 /*-----------------------------------------------------------------*/
157 /* do some early peephole optimization */
158 if (!strcmp(x, "a") || !strcmp(x, "acc"))
161 emitcode("mov","a,%s", x);
164 /*-----------------------------------------------------------------*/
165 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
166 /*-----------------------------------------------------------------*/
168 getFreePtr (iCode * ic, asmop ** aopp, bool result)
170 bool r0iu = FALSE, r1iu = FALSE;
171 bool r0ou = FALSE, r1ou = FALSE;
173 /* the logic: if r0 & r1 used in the instruction
174 then we are in trouble otherwise */
176 /* first check if r0 & r1 are used by this
177 instruction, in which case we are in trouble */
178 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
179 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
185 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
187 /* if no usage of r0 then return it */
190 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
191 (*aopp)->type = AOP_R0;
193 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
196 /* if no usage of r1 then return it */
199 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
200 (*aopp)->type = AOP_R1;
202 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
205 /* now we know they both have usage */
206 /* if r0 not used in this instruction */
209 /* push it if not already pushed */
212 emitcode ("push", "%s",
213 mcs51_regWithIdx (R0_IDX)->dname);
217 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
218 (*aopp)->type = AOP_R0;
220 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
223 /* if r1 not used then */
227 /* push it if not already pushed */
230 emitcode ("push", "%s",
231 mcs51_regWithIdx (R1_IDX)->dname);
235 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
236 (*aopp)->type = AOP_R1;
237 return mcs51_regWithIdx (R1_IDX);
240 /* I said end of world, but not quite end of world yet */
242 /* we can push it on the stack */
243 (*aopp)->type = AOP_STK;
246 /* in the case that result AND left AND right needs a pointer reg
247 we can safely use the result's */
248 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
249 (*aopp)->type = AOP_R0;
250 return mcs51_regWithIdx (R0_IDX);
252 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
253 (*aopp)->type = AOP_R1;
254 return mcs51_regWithIdx (R1_IDX);
258 /* now this is REALLY the end of the world */
259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
260 "getFreePtr should never reach here");
265 /*-----------------------------------------------------------------*/
266 /* getTempRegs - initialize an array of pointers to GPR registers */
267 /* that are not in use. Returns 1 if the requested */
268 /* number of registers were available, 0 otherwise. */
269 /*-----------------------------------------------------------------*/
271 getTempRegs(regs **tempRegs, int size, iCode *ic)
278 ic = _G.current_iCode;
284 freeRegs = newBitVect(8);
285 bitVectSetBit (freeRegs, R2_IDX);
286 bitVectSetBit (freeRegs, R3_IDX);
287 bitVectSetBit (freeRegs, R4_IDX);
288 bitVectSetBit (freeRegs, R5_IDX);
289 bitVectSetBit (freeRegs, R6_IDX);
290 bitVectSetBit (freeRegs, R7_IDX);
292 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
294 bitVect * newfreeRegs;
295 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
296 freeBitVect(freeRegs);
297 freeRegs = newfreeRegs;
299 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
302 for (i=0; i<freeRegs->size; i++)
304 if (bitVectBitValue(freeRegs,i))
305 tempRegs[offset++] = mcs51_regWithIdx(i);
308 freeBitVect(freeRegs);
313 freeBitVect(freeRegs);
318 /*-----------------------------------------------------------------*/
319 /* newAsmop - creates a new asmOp */
320 /*-----------------------------------------------------------------*/
322 newAsmop (short type)
326 aop = Safe_calloc (1, sizeof (asmop));
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type */
333 /*-----------------------------------------------------------------*/
335 pointerCode (sym_link * etype)
338 return PTR_TYPE (SPEC_OCLS (etype));
343 /*-----------------------------------------------------------------*/
344 /* leftRightUseAcc - returns size of accumulator use by operands */
345 /*-----------------------------------------------------------------*/
347 leftRightUseAcc(iCode *ic)
356 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
357 "null iCode pointer");
364 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
367 size = getSize (OP_SYMBOL (op)->type);
372 else if (ic->op == JUMPTABLE)
375 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
378 size = getSize (OP_SYMBOL (op)->type);
386 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
389 size = getSize (OP_SYMBOL (op)->type);
394 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
397 size = getSize (OP_SYMBOL (op)->type);
410 /*-----------------------------------------------------------------*/
411 /* aopForSym - for a true symbol */
412 /*-----------------------------------------------------------------*/
414 aopForSym (iCode * ic, symbol * sym, bool result)
419 wassertl (ic != NULL, "Got a null iCode");
420 wassertl (sym != NULL, "Got a null symbol");
422 space = SPEC_OCLS (sym->etype);
424 /* if already has one */
428 /* assign depending on the storage class */
429 /* if it is on the stack or indirectly addressable */
430 /* space we need to assign either r0 or r1 to it */
431 if (sym->onStack || sym->iaccess)
433 sym->aop = aop = newAsmop (0);
434 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
435 aop->size = getSize (sym->type);
437 /* now assign the address of the variable to
438 the pointer register */
439 if (aop->type != AOP_STK)
444 if (_G.accInUse || leftRightUseAcc (ic))
445 emitcode ("push", "acc");
447 emitcode ("mov", "a,_bp");
448 emitcode ("add", "a,#0x%02x",
450 ((char) (sym->stack - _G.nRegsSaved)) :
451 ((char) sym->stack)) & 0xff);
452 emitcode ("mov", "%s,a",
453 aop->aopu.aop_ptr->name);
455 if (_G.accInUse || leftRightUseAcc (ic))
456 emitcode ("pop", "acc");
459 emitcode ("mov", "%s,#%s",
460 aop->aopu.aop_ptr->name,
462 aop->paged = space->paged;
465 aop->aopu.aop_stk = sym->stack;
469 /* if in bit space */
470 if (IN_BITSPACE (space))
472 sym->aop = aop = newAsmop (AOP_CRY);
473 aop->aopu.aop_dir = sym->rname;
474 aop->size = getSize (sym->type);
477 /* if it is in direct space */
478 if (IN_DIRSPACE (space))
480 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
481 //printTypeChainRaw(sym->type, NULL);
482 //printf("space = %s\n", space ? space->sname : "NULL");
483 sym->aop = aop = newAsmop (AOP_DIR);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
489 /* special case for a function */
490 if (IS_FUNC (sym->type))
492 sym->aop = aop = newAsmop (AOP_IMMD);
493 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
494 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
495 aop->size = FPTRSIZE;
499 /* only remaining is far space */
500 /* in which case DPTR gets the address */
501 sym->aop = aop = newAsmop (AOP_DPTR);
502 emitcode ("mov", "dptr,#%s", sym->rname);
503 aop->size = getSize (sym->type);
505 /* if it is in code space */
506 if (IN_CODESPACE (space))
512 /*-----------------------------------------------------------------*/
513 /* aopForRemat - rematerialzes an object */
514 /*-----------------------------------------------------------------*/
516 aopForRemat (symbol * sym)
518 iCode *ic = sym->rematiCode;
519 asmop *aop = newAsmop (AOP_IMMD);
526 val += (int) operandLitValue (IC_RIGHT (ic));
527 else if (ic->op == '-')
528 val -= (int) operandLitValue (IC_RIGHT (ic));
529 else if (IS_CAST_ICODE(ic)) {
530 sym_link *from_type = operandType(IC_RIGHT(ic));
531 aop->aopu.aop_immd.from_cast_remat = 1;
532 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
533 ptr_type = DCL_TYPE(from_type);
534 if (ptr_type == IPOINTER) {
541 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
545 sprintf (buffer, "(%s %c 0x%04x)",
546 OP_SYMBOL (IC_LEFT (ic))->rname,
547 val >= 0 ? '+' : '-',
550 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
552 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
553 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
554 /* set immd2 field if required */
555 if (aop->aopu.aop_immd.from_cast_remat) {
556 sprintf(buffer,"#0x%02x",ptr_type);
557 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
558 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
659 if (aop1->type != AOP_REG ||
660 aop2->type != AOP_REG)
663 if (aop1->size != aop2->size)
666 for (i = 0; i < aop1->size; i++)
667 if (aop1->aopu.aop_reg[i] !=
668 aop2->aopu.aop_reg[i])
674 /*-----------------------------------------------------------------*/
675 /* aopOp - allocates an asmop for an operand : */
676 /*-----------------------------------------------------------------*/
678 aopOp (operand * op, iCode * ic, bool result)
687 /* if this a literal */
688 if (IS_OP_LITERAL (op))
690 op->aop = aop = newAsmop (AOP_LIT);
691 aop->aopu.aop_lit = op->operand.valOperand;
692 aop->size = getSize (operandType (op));
696 /* if already has a asmop then continue */
700 /* if the underlying symbol has a aop */
701 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
703 op->aop = OP_SYMBOL (op)->aop;
707 /* if this is a true symbol */
708 if (IS_TRUE_SYMOP (op))
710 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
714 /* this is a temporary : this has
720 e) can be a return use only */
722 sym = OP_SYMBOL (op);
724 /* if the type is a conditional */
725 if (sym->regType == REG_CND)
727 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
732 /* if it is spilt then two situations
734 b) has a spill location */
735 if (sym->isspilt || sym->nRegs == 0)
738 /* rematerialize it NOW */
741 sym->aop = op->aop = aop =
743 aop->size = getSize (sym->type);
750 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
751 aop->size = getSize (sym->type);
752 for (i = 0; i < 2; i++)
753 aop->aopu.aop_str[i] = accUse[i];
761 aop = op->aop = sym->aop = newAsmop (AOP_STR);
762 aop->size = getSize (sym->type);
763 for (i = 0; i < fReturnSizeMCS51; i++)
764 aop->aopu.aop_str[i] = fReturn[i];
768 if (sym->usl.spillLoc)
770 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
772 /* force a new aop if sizes differ */
773 sym->usl.spillLoc->aop = NULL;
775 sym->aop = op->aop = aop =
776 aopForSym (ic, sym->usl.spillLoc, result);
777 aop->size = getSize (sym->type);
781 /* else must be a dummy iTemp */
782 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
783 aop->size = getSize (sym->type);
787 /* must be in a register */
788 sym->aop = op->aop = aop = newAsmop (AOP_REG);
789 aop->size = sym->nRegs;
790 for (i = 0; i < sym->nRegs; i++)
791 aop->aopu.aop_reg[i] = sym->regs[i];
794 /*-----------------------------------------------------------------*/
795 /* freeAsmop - free up the asmop given to an operand */
796 /*----------------------------------------------------------------*/
798 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
815 /* depending on the asmop type only three cases need work AOP_RO
816 , AOP_R1 && AOP_STK */
824 emitcode ("pop", "ar0");
828 bitVectUnSetBit (ic->rUsed, R0_IDX);
836 emitcode ("pop", "ar1");
840 bitVectUnSetBit (ic->rUsed, R1_IDX);
846 int stk = aop->aopu.aop_stk + aop->size - 1;
847 bitVectUnSetBit (ic->rUsed, R0_IDX);
848 bitVectUnSetBit (ic->rUsed, R1_IDX);
850 getFreePtr (ic, &aop, FALSE);
854 emitcode ("mov", "a,_bp");
855 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
856 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
860 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
865 emitcode ("pop", "acc");
866 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
869 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
872 freeAsmop (op, NULL, ic, TRUE);
875 emitcode ("pop", "ar1");
881 emitcode ("pop", "ar0");
888 /* all other cases just dealloc */
894 OP_SYMBOL (op)->aop = NULL;
895 /* if the symbol has a spill */
897 SPIL_LOC (op)->aop = NULL;
902 /*-----------------------------------------------------------------*/
903 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
904 /* clobber the accumulator */
905 /*-----------------------------------------------------------------*/
907 aopGetUsesAcc (asmop *aop, int offset)
909 if (offset > (aop->size - 1))
927 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
936 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
942 /* Error case --- will have been caught already */
948 /*-----------------------------------------------------------------*/
949 /* aopGet - for fetching value of the aop */
950 /*-----------------------------------------------------------------*/
952 aopGet (asmop * aop, int offset, bool bit16, bool dname)
957 /* offset is greater than
959 if (offset > (aop->size - 1) &&
960 aop->type != AOP_LIT)
963 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
996 if (aop->code && aop->coff==0 && offset>=1) {
997 emitcode ("mov", "a,#0x%02x", offset);
998 emitcode ("movc", "a,@a+dptr");
999 return (dname ? "acc" : "a");
1002 while (offset > aop->coff)
1004 emitcode ("inc", "dptr");
1008 while (offset < aop->coff)
1010 emitcode ("lcall", "__decdptr");
1017 emitcode ("clr", "a");
1018 emitcode ("movc", "a,@a+dptr");
1022 emitcode ("movx", "a,@dptr");
1024 return (dname ? "acc" : "a");
1028 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1029 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1031 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1033 sprintf (s, "#(%s >> %d)",
1034 aop->aopu.aop_immd.aop_immd1,
1038 aop->aopu.aop_immd.aop_immd1);
1039 rs = Safe_calloc (1, strlen (s) + 1);
1045 sprintf (s, "(%s + %d)",
1049 sprintf (s, "%s", aop->aopu.aop_dir);
1050 rs = Safe_calloc (1, strlen (s) + 1);
1056 return aop->aopu.aop_reg[offset]->dname;
1058 return aop->aopu.aop_reg[offset]->name;
1061 emitcode ("clr", "a");
1062 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1063 emitcode ("rlc", "a");
1064 return (dname ? "acc" : "a");
1067 if (!offset && dname)
1069 return aop->aopu.aop_str[offset];
1072 return aopLiteral (aop->aopu.aop_lit, offset);
1076 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1080 return aop->aopu.aop_str[offset];
1084 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1085 "aopget got unsupported aop->type");
1088 /*-----------------------------------------------------------------*/
1089 /* aopPut - puts a string for a aop */
1090 /*-----------------------------------------------------------------*/
1092 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1096 if (aop->size && offset > (aop->size - 1))
1098 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1099 "aopPut got offset > aop->size");
1103 /* will assign value to value */
1104 /* depending on where it is ofcourse */
1108 MOVA (s); /* read s in case it was volatile */
1113 sprintf (d, "(%s + %d)",
1114 aop->aopu.aop_dir, offset);
1116 sprintf (d, "%s", aop->aopu.aop_dir);
1118 if (strcmp (d, s) ||
1120 emitcode ("mov", "%s,%s", d, s);
1125 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1126 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1129 strcmp (s, "r0") == 0 ||
1130 strcmp (s, "r1") == 0 ||
1131 strcmp (s, "r2") == 0 ||
1132 strcmp (s, "r3") == 0 ||
1133 strcmp (s, "r4") == 0 ||
1134 strcmp (s, "r5") == 0 ||
1135 strcmp (s, "r6") == 0 ||
1136 strcmp (s, "r7") == 0)
1137 emitcode ("mov", "%s,%s",
1138 aop->aopu.aop_reg[offset]->dname, s);
1140 emitcode ("mov", "%s,%s",
1141 aop->aopu.aop_reg[offset]->name, s);
1148 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1149 "aopPut writing to code space");
1153 while (offset > aop->coff)
1156 emitcode ("inc", "dptr");
1159 while (offset < aop->coff)
1162 emitcode ("lcall", "__decdptr");
1167 /* if not in accumulater */
1170 emitcode ("movx", "@dptr,a");
1175 while (offset > aop->coff)
1178 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1180 while (offset < aop->coff)
1183 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1190 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1196 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1198 else if (strcmp (s, "r0") == 0 ||
1199 strcmp (s, "r1") == 0 ||
1200 strcmp (s, "r2") == 0 ||
1201 strcmp (s, "r3") == 0 ||
1202 strcmp (s, "r4") == 0 ||
1203 strcmp (s, "r5") == 0 ||
1204 strcmp (s, "r6") == 0 ||
1205 strcmp (s, "r7") == 0)
1208 sprintf (buffer, "a%s", s);
1209 emitcode ("mov", "@%s,%s",
1210 aop->aopu.aop_ptr->name, buffer);
1213 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1218 if (strcmp (s, "a") == 0)
1219 emitcode ("push", "acc");
1223 emitcode ("push", "acc");
1225 emitcode ("push", s);
1231 /* if bit variable */
1232 if (!aop->aopu.aop_dir)
1234 emitcode ("clr", "a");
1235 emitcode ("rlc", "a");
1240 emitcode ("clr", "%s", aop->aopu.aop_dir);
1242 emitcode ("setb", "%s", aop->aopu.aop_dir);
1243 else if (!strcmp (s, "c"))
1244 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1247 if (strcmp (s, "a"))
1252 /* set C, if a >= 1 */
1253 emitcode ("add", "a,#0xff");
1254 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1262 if (strcmp (aop->aopu.aop_str[offset], s) ||
1264 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 if (!offset && (strcmp (s, "acc") == 0) &&
1273 if (strcmp (aop->aopu.aop_str[offset], s) &&
1275 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1279 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280 "aopPut got unsupported aop->type");
1288 /*-----------------------------------------------------------------*/
1289 /* pointToEnd :- points to the last byte of the operand */
1290 /*-----------------------------------------------------------------*/
1292 pointToEnd (asmop * aop)
1298 aop->coff = count = (aop->size - 1);
1304 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308 emitcode ("inc", "dptr");
1315 /*-----------------------------------------------------------------*/
1316 /* reAdjustPreg - points a register back to where it should */
1317 /*-----------------------------------------------------------------*/
1319 reAdjustPreg (asmop * aop)
1321 if ((aop->coff==0) || aop->size <= 1)
1329 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1334 emitcode ("lcall", "__decdptr");
1341 #define AOP(op) op->aop
1342 #define AOP_TYPE(op) AOP(op)->type
1343 #define AOP_SIZE(op) AOP(op)->size
1344 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1345 AOP_TYPE(x) == AOP_R0))
1347 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1348 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1350 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1351 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1352 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1355 /*-----------------------------------------------------------------*/
1356 /* opIsGptr: returns non-zero if the passed operand is */
1357 /* a generic pointer type. */
1358 /*-----------------------------------------------------------------*/
1360 opIsGptr (operand * op)
1362 sym_link *type = operandType (op);
1364 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1371 /*-----------------------------------------------------------------*/
1372 /* getDataSize - get the operand data size */
1373 /*-----------------------------------------------------------------*/
1375 getDataSize (operand * op)
1378 size = AOP_SIZE (op);
1379 if (size == GPTRSIZE)
1381 sym_link *type = operandType (op);
1382 if (IS_GENPTR (type))
1384 /* generic pointer; arithmetic operations
1385 * should ignore the high byte (pointer type).
1393 /*-----------------------------------------------------------------*/
1394 /* outAcc - output Acc */
1395 /*-----------------------------------------------------------------*/
1397 outAcc (operand * result)
1400 size = getDataSize (result);
1403 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1406 /* unsigned or positive */
1409 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1414 /*-----------------------------------------------------------------*/
1415 /* outBitC - output a bit C */
1416 /*-----------------------------------------------------------------*/
1418 outBitC (operand * result)
1420 /* if the result is bit */
1421 if (AOP_TYPE (result) == AOP_CRY)
1422 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1425 emitcode ("clr", "a");
1426 emitcode ("rlc", "a");
1431 /*-----------------------------------------------------------------*/
1432 /* toBoolean - emit code for orl a,operator(sizeop) */
1433 /*-----------------------------------------------------------------*/
1435 toBoolean (operand * oper)
1437 int size = AOP_SIZE (oper) - 1;
1439 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1441 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1445 /*-----------------------------------------------------------------*/
1446 /* genNot - generate code for ! operation */
1447 /*-----------------------------------------------------------------*/
1453 D(emitcode ("; genNot",""));
1455 /* assign asmOps to operand & result */
1456 aopOp (IC_LEFT (ic), ic, FALSE);
1457 aopOp (IC_RESULT (ic), ic, TRUE);
1459 /* if in bit space then a special case */
1460 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1462 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1463 emitcode ("cpl", "c");
1464 outBitC (IC_RESULT (ic));
1468 toBoolean (IC_LEFT (ic));
1470 tlbl = newiTempLabel (NULL);
1471 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1472 emitcode ("", "%05d$:", tlbl->key + 100);
1473 outBitC (IC_RESULT (ic));
1476 /* release the aops */
1477 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* genCpl - generate code for complement */
1484 /*-----------------------------------------------------------------*/
1492 D(emitcode ("; genCpl",""));
1494 /* assign asmOps to operand & result */
1495 aopOp (IC_LEFT (ic), ic, FALSE);
1496 aopOp (IC_RESULT (ic), ic, TRUE);
1498 /* special case if in bit space */
1499 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1501 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1503 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1504 emitcode ("cpl", "c");
1505 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1509 tlbl=newiTempLabel(NULL);
1510 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1511 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1512 IS_AOP_PREG (IC_LEFT (ic)))
1514 emitcode ("cjne", "%s,#0x01,%05d$",
1515 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1520 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1522 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1524 emitcode ("", "%05d$:", tlbl->key + 100);
1525 outBitC (IC_RESULT(ic));
1529 size = AOP_SIZE (IC_RESULT (ic));
1532 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1534 emitcode ("cpl", "a");
1535 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1540 /* release the aops */
1541 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* genUminusFloat - unary minus for floating points */
1547 /*-----------------------------------------------------------------*/
1549 genUminusFloat (operand * op, operand * result)
1551 int size, offset = 0;
1554 D(emitcode ("; genUminusFloat",""));
1556 /* for this we just copy and then flip the bit */
1558 size = AOP_SIZE (op) - 1;
1562 aopPut (AOP (result),
1563 aopGet (AOP (op), offset, FALSE, FALSE),
1565 isOperandVolatile (result, FALSE));
1569 l = aopGet (AOP (op), offset, FALSE, FALSE);
1573 emitcode ("cpl", "acc.7");
1574 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1577 /*-----------------------------------------------------------------*/
1578 /* genUminus - unary minus code generation */
1579 /*-----------------------------------------------------------------*/
1581 genUminus (iCode * ic)
1584 sym_link *optype, *rtype;
1587 D(emitcode ("; genUminus",""));
1590 aopOp (IC_LEFT (ic), ic, FALSE);
1591 aopOp (IC_RESULT (ic), ic, TRUE);
1593 /* if both in bit space then special
1595 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1596 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1599 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1600 emitcode ("cpl", "c");
1601 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1605 optype = operandType (IC_LEFT (ic));
1606 rtype = operandType (IC_RESULT (ic));
1608 /* if float then do float stuff */
1609 if (IS_FLOAT (optype))
1611 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1615 /* otherwise subtract from zero */
1616 size = AOP_SIZE (IC_LEFT (ic));
1621 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1622 if (!strcmp (l, "a"))
1626 emitcode ("cpl", "a");
1627 emitcode ("addc", "a,#0");
1633 emitcode ("clr", "a");
1634 emitcode ("subb", "a,%s", l);
1636 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1639 /* if any remaining bytes in the result */
1640 /* we just need to propagate the sign */
1641 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1643 emitcode ("rlc", "a");
1644 emitcode ("subb", "a,acc");
1646 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 /* saveRegisters - will look for a call and save the registers */
1657 /*-----------------------------------------------------------------*/
1659 saveRegisters (iCode * lic)
1666 for (ic = lic; ic; ic = ic->next)
1667 if (ic->op == CALL || ic->op == PCALL)
1672 fprintf (stderr, "found parameter push with no function call\n");
1676 /* if the registers have been saved already or don't need to be then
1680 if (IS_SYMOP(IC_LEFT(ic)) &&
1681 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1682 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1685 /* safe the registers in use at this time but skip the
1686 ones for the result */
1687 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1688 mcs51_rUmaskForOp (IC_RESULT(ic)));
1691 if (options.useXstack)
1693 if (bitVectBitValue (rsave, R0_IDX))
1694 emitcode ("mov", "b,r0");
1695 emitcode ("mov", "r0,%s", spname);
1696 for (i = 0; i < mcs51_nRegs; i++)
1698 if (bitVectBitValue (rsave, i))
1701 emitcode ("mov", "a,b");
1703 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1704 emitcode ("movx", "@r0,a");
1705 emitcode ("inc", "r0");
1708 emitcode ("mov", "%s,r0", spname);
1709 if (bitVectBitValue (rsave, R0_IDX))
1710 emitcode ("mov", "r0,b");
1713 for (i = 0; i < mcs51_nRegs; i++)
1715 if (bitVectBitValue (rsave, i))
1716 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1720 /*-----------------------------------------------------------------*/
1721 /* unsaveRegisters - pop the pushed registers */
1722 /*-----------------------------------------------------------------*/
1724 unsaveRegisters (iCode * ic)
1729 /* restore the registers in use at this time but skip the
1730 ones for the result */
1731 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1732 mcs51_rUmaskForOp (IC_RESULT(ic)));
1734 if (options.useXstack)
1736 emitcode ("mov", "r0,%s", spname);
1737 for (i = mcs51_nRegs; i >= 0; i--)
1739 if (bitVectBitValue (rsave, i))
1741 emitcode ("dec", "r0");
1742 emitcode ("movx", "a,@r0");
1744 emitcode ("mov", "b,a");
1746 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1750 emitcode ("mov", "%s,r0", spname);
1751 if (bitVectBitValue (rsave, R0_IDX))
1752 emitcode ("mov", "r0,b");
1755 for (i = mcs51_nRegs; i >= 0; i--)
1757 if (bitVectBitValue (rsave, i))
1758 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1764 /*-----------------------------------------------------------------*/
1766 /*-----------------------------------------------------------------*/
1768 pushSide (operand * oper, int size)
1773 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1774 if (AOP_TYPE (oper) != AOP_REG &&
1775 AOP_TYPE (oper) != AOP_DIR &&
1778 emitcode ("mov", "a,%s", l);
1779 emitcode ("push", "acc");
1782 emitcode ("push", "%s", l);
1786 /*-----------------------------------------------------------------*/
1787 /* assignResultValue - */
1788 /*-----------------------------------------------------------------*/
1790 assignResultValue (operand * oper)
1793 int size = AOP_SIZE (oper);
1796 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1802 /*-----------------------------------------------------------------*/
1803 /* genXpush - pushes onto the external stack */
1804 /*-----------------------------------------------------------------*/
1806 genXpush (iCode * ic)
1808 asmop *aop = newAsmop (0);
1810 int size, offset = 0;
1812 D(emitcode ("; genXpush",""));
1814 aopOp (IC_LEFT (ic), ic, FALSE);
1815 r = getFreePtr (ic, &aop, FALSE);
1818 emitcode ("mov", "%s,_spx", r->name);
1820 size = AOP_SIZE (IC_LEFT (ic));
1824 char *l = aopGet (AOP (IC_LEFT (ic)),
1825 offset++, FALSE, FALSE);
1827 emitcode ("movx", "@%s,a", r->name);
1828 emitcode ("inc", "%s", r->name);
1833 emitcode ("mov", "_spx,%s", r->name);
1835 freeAsmop (NULL, aop, ic, TRUE);
1836 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genIpush - genrate code for pushing this gets a little complex */
1841 /*-----------------------------------------------------------------*/
1843 genIpush (iCode * ic)
1845 int size, offset = 0;
1848 D(emitcode ("; genIpush",""));
1850 /* if this is not a parm push : ie. it is spill push
1851 and spill push is always done on the local stack */
1855 /* and the item is spilt then do nothing */
1856 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1861 /* push it on the stack */
1864 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1870 emitcode ("push", "%s", l);
1875 /* this is a paramter push: in this case we call
1876 the routine to find the call and save those
1877 registers that need to be saved */
1880 /* if use external stack then call the external
1881 stack pushing routine */
1882 if (options.useXstack)
1888 /* then do the push */
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1892 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1893 size = AOP_SIZE (IC_LEFT (ic));
1897 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1898 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1899 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1909 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* genIpop - recover the registers: can happen only for spilling */
1914 /*-----------------------------------------------------------------*/
1916 genIpop (iCode * ic)
1920 D(emitcode ("; genIpop",""));
1922 /* if the temp was not pushed then */
1923 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1926 aopOp (IC_LEFT (ic), ic, FALSE);
1927 size = AOP_SIZE (IC_LEFT (ic));
1928 offset = (size - 1);
1930 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1933 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1936 /*-----------------------------------------------------------------*/
1937 /* unsaveRBank - restores the resgister bank from stack */
1938 /*-----------------------------------------------------------------*/
1940 unsaveRBank (int bank, iCode * ic, bool popPsw)
1946 if (options.useXstack)
1950 /* Assume r0 is available for use. */
1951 r = mcs51_regWithIdx (R0_IDX);;
1956 r = getFreePtr (ic, &aop, FALSE);
1958 emitcode ("mov", "%s,_spx", r->name);
1963 if (options.useXstack)
1965 emitcode ("movx", "a,@%s", r->name);
1966 emitcode ("mov", "psw,a");
1967 emitcode ("dec", "%s", r->name);
1971 emitcode ("pop", "psw");
1975 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1977 if (options.useXstack)
1979 emitcode ("movx", "a,@%s", r->name);
1980 emitcode ("mov", "(%s+%d),a",
1981 regs8051[i].base, 8 * bank + regs8051[i].offset);
1982 emitcode ("dec", "%s", r->name);
1986 emitcode ("pop", "(%s+%d)",
1987 regs8051[i].base, 8 * bank + regs8051[i].offset);
1990 if (options.useXstack)
1992 emitcode ("mov", "_spx,%s", r->name);
1997 freeAsmop (NULL, aop, ic, TRUE);
2001 /*-----------------------------------------------------------------*/
2002 /* saveRBank - saves an entire register bank on the stack */
2003 /*-----------------------------------------------------------------*/
2005 saveRBank (int bank, iCode * ic, bool pushPsw)
2011 if (options.useXstack)
2015 /* Assume r0 is available for use. */
2016 r = mcs51_regWithIdx (R0_IDX);;
2021 r = getFreePtr (ic, &aop, FALSE);
2023 emitcode ("mov", "%s,_spx", r->name);
2026 for (i = 0; i < mcs51_nRegs; i++)
2028 if (options.useXstack)
2030 emitcode ("inc", "%s", r->name);
2031 emitcode ("mov", "a,(%s+%d)",
2032 regs8051[i].base, 8 * bank + regs8051[i].offset);
2033 emitcode ("movx", "@%s,a", r->name);
2036 emitcode ("push", "(%s+%d)",
2037 regs8051[i].base, 8 * bank + regs8051[i].offset);
2042 if (options.useXstack)
2044 emitcode ("mov", "a,psw");
2045 emitcode ("movx", "@%s,a", r->name);
2046 emitcode ("inc", "%s", r->name);
2047 emitcode ("mov", "_spx,%s", r->name);
2052 emitcode ("push", "psw");
2055 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2060 freeAsmop (NULL, aop, ic, TRUE);
2069 /*-----------------------------------------------------------------*/
2070 /* genSend - gen code for SEND */
2071 /*-----------------------------------------------------------------*/
2072 static void genSend(set *sendSet)
2077 for (sic = setFirstItem (_G.sendSet); sic;
2078 sic = setNextItem (_G.sendSet)) {
2079 int size, offset = 0;
2080 aopOp (IC_LEFT (sic), sic, FALSE);
2081 size = AOP_SIZE (IC_LEFT (sic));
2083 if (sic->argreg == 1) {
2085 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2087 if (strcmp (l, fReturn[offset]))
2088 emitcode ("mov", "%s,%s", fReturn[offset], l);
2094 emitcode ("mov","b1_%d,%s",rb1_count++,
2095 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2098 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2102 /*-----------------------------------------------------------------*/
2103 /* genCall - generates a call statement */
2104 /*-----------------------------------------------------------------*/
2106 genCall (iCode * ic)
2109 // bool restoreBank = FALSE;
2110 bool swapBanks = FALSE;
2112 D(emitcode("; genCall",""));
2114 dtype = operandType (IC_LEFT (ic));
2115 /* if send set is not empty the assign */
2118 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2119 genSend(reverseSet(_G.sendSet));
2121 genSend(_G.sendSet);
2127 /* if we are calling a not _naked function that is not using
2128 the same register bank then we need to save the
2129 destination registers on the stack */
2130 dtype = operandType (IC_LEFT (ic));
2131 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2132 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2133 !IFFUNC_ISISR (dtype))
2138 /* if caller saves & we have not saved then */
2144 emitcode ("mov", "psw,#0x%02x",
2145 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2149 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2150 OP_SYMBOL (IC_LEFT (ic))->rname :
2151 OP_SYMBOL (IC_LEFT (ic))->name));
2155 emitcode ("mov", "psw,#0x%02x",
2156 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2159 /* if we need assign a result value */
2160 if ((IS_ITEMP (IC_RESULT (ic)) &&
2161 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2162 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2163 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2164 IS_TRUE_SYMOP (IC_RESULT (ic)))
2168 aopOp (IC_RESULT (ic), ic, FALSE);
2171 assignResultValue (IC_RESULT (ic));
2173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2176 /* adjust the stack for parameters if
2181 if (ic->parmBytes > 3)
2183 emitcode ("mov", "a,%s", spname);
2184 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2185 emitcode ("mov", "%s,a", spname);
2188 for (i = 0; i < ic->parmBytes; i++)
2189 emitcode ("dec", "%s", spname);
2192 /* if we hade saved some registers then unsave them */
2193 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2194 unsaveRegisters (ic);
2196 // /* if register bank was saved then pop them */
2198 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2201 /*-----------------------------------------------------------------*/
2202 /* -10l - generates a call by pointer statement */
2203 /*-----------------------------------------------------------------*/
2205 genPcall (iCode * ic)
2208 symbol *rlbl = newiTempLabel (NULL);
2209 // bool restoreBank=FALSE;
2210 bool swapBanks = FALSE;
2212 D(emitcode("; genPCall",""));
2214 /* if caller saves & we have not saved then */
2218 /* if we are calling a not _naked function that is not using
2219 the same register bank then we need to save the
2220 destination registers on the stack */
2221 dtype = operandType (IC_LEFT (ic))->next;
2222 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2223 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2224 !IFFUNC_ISISR (dtype))
2226 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2227 // restoreBank=TRUE;
2229 // need caution message to user here
2232 /* push the return address on to the stack */
2233 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2234 emitcode ("push", "acc");
2235 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2236 emitcode ("push", "acc");
2238 /* now push the calling address */
2239 aopOp (IC_LEFT (ic), ic, FALSE);
2241 pushSide (IC_LEFT (ic), FPTRSIZE);
2243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2245 /* if send set is not empty the assign */
2248 genSend(reverseSet(_G.sendSet));
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2259 emitcode ("ret", "");
2260 emitcode ("", "%05d$:", (rlbl->key + 100));
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))->spildir)) ||
2273 IS_TRUE_SYMOP (IC_RESULT (ic)))
2277 aopOp (IC_RESULT (ic), ic, FALSE);
2280 assignResultValue (IC_RESULT (ic));
2282 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2285 /* adjust the stack for parameters if
2290 if (ic->parmBytes > 3)
2292 emitcode ("mov", "a,%s", spname);
2293 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2294 emitcode ("mov", "%s,a", spname);
2297 for (i = 0; i < ic->parmBytes; i++)
2298 emitcode ("dec", "%s", spname);
2302 // /* if register bank was saved then unsave them */
2304 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2306 /* if we hade saved some registers then
2308 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2309 unsaveRegisters (ic);
2312 /*-----------------------------------------------------------------*/
2313 /* resultRemat - result is rematerializable */
2314 /*-----------------------------------------------------------------*/
2316 resultRemat (iCode * ic)
2318 if (SKIP_IC (ic) || ic->op == IFX)
2321 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2323 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2324 if (sym->remat && !POINTER_SET (ic))
2331 #if defined(__BORLANDC__) || defined(_MSC_VER)
2332 #define STRCASECMP stricmp
2334 #define STRCASECMP strcasecmp
2337 /*-----------------------------------------------------------------*/
2338 /* inExcludeList - return 1 if the string is in exclude Reg list */
2339 /*-----------------------------------------------------------------*/
2341 regsCmp(void *p1, void *p2)
2343 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2347 inExcludeList (char *s)
2349 const char *p = setFirstItem(options.excludeRegsSet);
2351 if (p == NULL || STRCASECMP(p, "none") == 0)
2355 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2358 /*-----------------------------------------------------------------*/
2359 /* genFunction - generated code for function entry */
2360 /*-----------------------------------------------------------------*/
2362 genFunction (iCode * ic)
2366 bool switchedPSW = FALSE;
2367 int calleesaves_saved_register = -1;
2370 /* create the function header */
2371 emitcode (";", "-----------------------------------------");
2372 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2373 emitcode (";", "-----------------------------------------");
2375 emitcode ("", "%s:", sym->rname);
2376 ftype = operandType (IC_LEFT (ic));
2377 _G.currentFunc = sym;
2379 if (IFFUNC_ISNAKED(ftype))
2381 emitcode(";", "naked function: no prologue.");
2385 /* here we need to generate the equates for the
2386 register bank if required */
2387 if (FUNC_REGBANK (ftype) != rbank)
2391 rbank = FUNC_REGBANK (ftype);
2392 for (i = 0; i < mcs51_nRegs; i++)
2394 if (strcmp (regs8051[i].base, "0") == 0)
2395 emitcode ("", "%s = 0x%02x",
2397 8 * rbank + regs8051[i].offset);
2399 emitcode ("", "%s = %s + 0x%02x",
2402 8 * rbank + regs8051[i].offset);
2406 /* if this is an interrupt service routine then
2407 save acc, b, dpl, dph */
2408 if (IFFUNC_ISISR (sym->type))
2411 if (!inExcludeList ("acc"))
2412 emitcode ("push", "acc");
2413 if (!inExcludeList ("b"))
2414 emitcode ("push", "b");
2415 if (!inExcludeList ("dpl"))
2416 emitcode ("push", "dpl");
2417 if (!inExcludeList ("dph"))
2418 emitcode ("push", "dph");
2419 /* if this isr has no bank i.e. is going to
2420 run with bank 0 , then we need to save more
2422 if (!FUNC_REGBANK (sym->type))
2425 /* if this function does not call any other
2426 function then we can be economical and
2427 save only those registers that are used */
2428 if (!IFFUNC_HASFCALL(sym->type))
2432 /* if any registers used */
2435 /* save the registers used */
2436 for (i = 0; i < sym->regsUsed->size; i++)
2438 if (bitVectBitValue (sym->regsUsed, i) ||
2439 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2440 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2448 /* this function has a function call cannot
2449 determines register usage so we will have to push the
2451 saveRBank (0, ic, FALSE);
2452 if (options.parms_in_bank1) {
2454 for (i=0; i < 8 ; i++ ) {
2455 emitcode ("push","%s",rb1regs[i]);
2462 /* This ISR uses a non-zero bank.
2464 * We assume that the bank is available for our
2467 * However, if this ISR calls a function which uses some
2468 * other bank, we must save that bank entirely.
2470 unsigned long banksToSave = 0;
2472 if (IFFUNC_HASFCALL(sym->type))
2475 #define MAX_REGISTER_BANKS 4
2480 for (i = ic; i; i = i->next)
2482 if (i->op == ENDFUNCTION)
2484 /* we got to the end OK. */
2492 dtype = operandType (IC_LEFT(i));
2494 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2496 /* Mark this bank for saving. */
2497 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2499 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2503 banksToSave |= (1 << FUNC_REGBANK(dtype));
2506 /* And note that we don't need to do it in
2514 /* This is a mess; we have no idea what
2515 * register bank the called function might
2518 * The only thing I can think of to do is
2519 * throw a warning and hope.
2521 werror(W_FUNCPTR_IN_USING_ISR);
2525 if (banksToSave && options.useXstack)
2527 /* Since we aren't passing it an ic,
2528 * saveRBank will assume r0 is available to abuse.
2530 * So switch to our (trashable) bank now, so
2531 * the caller's R0 isn't trashed.
2533 emitcode ("push", "psw");
2534 emitcode ("mov", "psw,#0x%02x",
2535 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2539 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2541 if (banksToSave & (1 << ix))
2543 saveRBank(ix, NULL, FALSE);
2547 // TODO: this needs a closer look
2548 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2553 /* if callee-save to be used for this function
2554 then save the registers being used in this function */
2555 if (IFFUNC_CALLEESAVES(sym->type))
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = 0; i < sym->regsUsed->size; i++)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2568 /* remember one saved register for later usage */
2569 if (calleesaves_saved_register < 0)
2570 calleesaves_saved_register = i;
2571 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2579 /* set the register bank to the desired value */
2580 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2583 emitcode ("push", "psw");
2584 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2587 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2590 if (options.useXstack)
2592 emitcode ("mov", "r0,%s", spname);
2593 emitcode ("mov", "a,_bp");
2594 emitcode ("movx", "@r0,a");
2595 emitcode ("inc", "%s", spname);
2599 /* set up the stack */
2600 emitcode ("push", "_bp"); /* save the callers stack */
2602 emitcode ("mov", "_bp,%s", spname);
2605 /* adjust the stack for the function */
2611 werror (W_STACK_OVERFLOW, sym->name);
2613 if (i > 3 && sym->recvSize < 4)
2616 emitcode ("mov", "a,sp");
2617 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2618 emitcode ("mov", "sp,a");
2623 if (IFFUNC_CALLEESAVES(sym->type))
2625 /* if it's a callee-saves function we need a saved register */
2626 if (calleesaves_saved_register >= 0)
2628 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2629 emitcode ("mov", "a,sp");
2630 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2631 emitcode ("mov", "sp,a");
2632 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2635 /* do it the hard way */
2637 emitcode ("inc", "sp");
2641 /* not callee-saves, we can clobber r0 */
2642 emitcode ("mov", "r0,a");
2643 emitcode ("mov", "a,sp");
2644 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2645 emitcode ("mov", "sp,a");
2646 emitcode ("mov", "a,r0");
2651 emitcode ("inc", "sp");
2657 emitcode ("mov", "a,_spx");
2658 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2659 emitcode ("mov", "_spx,a");
2662 /* if critical function then turn interrupts off */
2663 if (IFFUNC_ISCRITICAL (ftype))
2665 symbol *tlbl = newiTempLabel (NULL);
2666 emitcode ("setb", "c");
2667 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2668 emitcode ("clr", "c");
2669 emitcode ("", "%05d$:", (tlbl->key + 100));
2670 emitcode ("push", "psw"); /* save old ea via c in psw */
2674 /*-----------------------------------------------------------------*/
2675 /* genEndFunction - generates epilogue for functions */
2676 /*-----------------------------------------------------------------*/
2678 genEndFunction (iCode * ic)
2680 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2682 _G.currentFunc = NULL;
2683 if (IFFUNC_ISNAKED(sym->type))
2685 emitcode(";", "naked function: no epilogue.");
2689 if (IFFUNC_ISCRITICAL (sym->type))
2691 emitcode ("pop", "psw"); /* restore ea via c in psw */
2692 emitcode ("mov", "ea,c");
2695 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2697 emitcode ("mov", "%s,_bp", spname);
2700 /* if use external stack but some variables were
2701 added to the local stack then decrement the
2703 if (options.useXstack && sym->stack)
2705 emitcode ("mov", "a,sp");
2706 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2707 emitcode ("mov", "sp,a");
2711 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2713 if (options.useXstack)
2715 emitcode ("mov", "r0,%s", spname);
2716 emitcode ("movx", "a,@r0");
2717 emitcode ("mov", "_bp,a");
2718 emitcode ("dec", "%s", spname);
2722 emitcode ("pop", "_bp");
2726 /* restore the register bank */
2727 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2729 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2730 || !options.useXstack)
2732 /* Special case of ISR using non-zero bank with useXstack
2735 emitcode ("pop", "psw");
2739 if (IFFUNC_ISISR (sym->type))
2742 /* now we need to restore the registers */
2743 /* if this isr has no bank i.e. is going to
2744 run with bank 0 , then we need to save more
2746 if (!FUNC_REGBANK (sym->type))
2748 /* if this function does not call any other
2749 function then we can be economical and
2750 save only those registers that are used */
2751 if (!IFFUNC_HASFCALL(sym->type))
2755 /* if any registers used */
2758 /* save the registers used */
2759 for (i = sym->regsUsed->size; i >= 0; i--)
2761 if (bitVectBitValue (sym->regsUsed, i) ||
2762 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2763 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2770 if (options.parms_in_bank1) {
2772 for (i = 7 ; i >= 0 ; i-- ) {
2773 emitcode ("pop","%s",rb1regs[i]);
2776 /* this function has a function call cannot
2777 determines register usage so we will have to pop the
2779 unsaveRBank (0, ic, FALSE);
2784 /* This ISR uses a non-zero bank.
2786 * Restore any register banks saved by genFunction
2789 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2792 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2794 if (savedBanks & (1 << ix))
2796 unsaveRBank(ix, NULL, FALSE);
2800 if (options.useXstack)
2802 /* Restore bank AFTER calling unsaveRBank,
2803 * since it can trash r0.
2805 emitcode ("pop", "psw");
2809 if (!inExcludeList ("dph"))
2810 emitcode ("pop", "dph");
2811 if (!inExcludeList ("dpl"))
2812 emitcode ("pop", "dpl");
2813 if (!inExcludeList ("b"))
2814 emitcode ("pop", "b");
2815 if (!inExcludeList ("acc"))
2816 emitcode ("pop", "acc");
2818 /* if debug then send end of function */
2819 if (options.debug && currFunc)
2822 emitcode ("", "C$%s$%d$%d$%d ==.",
2823 FileBaseName (ic->filename), currFunc->lastLine,
2824 ic->level, ic->block);
2825 if (IS_STATIC (currFunc->etype))
2826 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2828 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2832 emitcode ("reti", "");
2836 if (IFFUNC_CALLEESAVES(sym->type))
2840 /* if any registers used */
2843 /* save the registers used */
2844 for (i = sym->regsUsed->size; i >= 0; i--)
2846 if (bitVectBitValue (sym->regsUsed, i) ||
2847 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2848 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2854 /* if debug then send end of function */
2855 if (options.debug && currFunc)
2858 emitcode ("", "C$%s$%d$%d$%d ==.",
2859 FileBaseName (ic->filename), currFunc->lastLine,
2860 ic->level, ic->block);
2861 if (IS_STATIC (currFunc->etype))
2862 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2864 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2868 emitcode ("ret", "");
2873 /*-----------------------------------------------------------------*/
2874 /* genRet - generate code for return statement */
2875 /*-----------------------------------------------------------------*/
2879 int size, offset = 0, pushed = 0;
2881 D(emitcode ("; genRet",""));
2883 /* if we have no return value then
2884 just generate the "ret" */
2888 /* we have something to return then
2889 move the return value into place */
2890 aopOp (IC_LEFT (ic), ic, FALSE);
2891 size = AOP_SIZE (IC_LEFT (ic));
2896 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2899 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2901 emitcode ("push", "%s", l);
2906 l = aopGet (AOP (IC_LEFT (ic)), offset,
2908 if (strcmp (fReturn[offset], l))
2909 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2918 if (strcmp (fReturn[pushed], "a"))
2919 emitcode ("pop", fReturn[pushed]);
2921 emitcode ("pop", "acc");
2924 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2927 /* generate a jump to the return label
2928 if the next is not the return statement */
2929 if (!(ic->next && ic->next->op == LABEL &&
2930 IC_LABEL (ic->next) == returnLabel))
2932 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2936 /*-----------------------------------------------------------------*/
2937 /* genLabel - generates a label */
2938 /*-----------------------------------------------------------------*/
2940 genLabel (iCode * ic)
2942 /* special case never generate */
2943 if (IC_LABEL (ic) == entryLabel)
2946 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2949 /*-----------------------------------------------------------------*/
2950 /* genGoto - generates a ljmp */
2951 /*-----------------------------------------------------------------*/
2953 genGoto (iCode * ic)
2955 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2958 /*-----------------------------------------------------------------*/
2959 /* findLabelBackwards: walks back through the iCode chain looking */
2960 /* for the given label. Returns number of iCode instructions */
2961 /* between that label and given ic. */
2962 /* Returns zero if label not found. */
2963 /*-----------------------------------------------------------------*/
2965 findLabelBackwards (iCode * ic, int key)
2974 /* If we have any pushes or pops, we cannot predict the distance.
2975 I don't like this at all, this should be dealt with in the
2977 if (ic->op == IPUSH || ic->op == IPOP) {
2981 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2990 /*-----------------------------------------------------------------*/
2991 /* genPlusIncr :- does addition with increment if possible */
2992 /*-----------------------------------------------------------------*/
2994 genPlusIncr (iCode * ic)
2996 unsigned int icount;
2997 unsigned int size = getDataSize (IC_RESULT (ic));
2999 /* will try to generate an increment */
3000 /* if the right side is not a literal
3002 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3005 /* if the literal value of the right hand side
3006 is greater than 4 then it is not worth it */
3007 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3010 D(emitcode ("; genPlusIncr",""));
3012 /* if increment >=16 bits in register or direct space */
3013 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3014 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3022 /* If the next instruction is a goto and the goto target
3023 * is < 10 instructions previous to this, we can generate
3024 * jumps straight to that target.
3026 if (ic->next && ic->next->op == GOTO
3027 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3028 && labelRange <= 10)
3030 emitcode (";", "tail increment optimized");
3031 tlbl = IC_LABEL (ic->next);
3036 tlbl = newiTempLabel (NULL);
3039 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3040 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3041 IS_AOP_PREG (IC_RESULT (ic)))
3042 emitcode ("cjne", "%s,#0x00,%05d$",
3043 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3047 emitcode ("clr", "a");
3048 emitcode ("cjne", "a,%s,%05d$",
3049 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3053 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3056 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3057 IS_AOP_PREG (IC_RESULT (ic)))
3058 emitcode ("cjne", "%s,#0x00,%05d$",
3059 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3062 emitcode ("cjne", "a,%s,%05d$",
3063 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3066 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3070 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3071 IS_AOP_PREG (IC_RESULT (ic)))
3072 emitcode ("cjne", "%s,#0x00,%05d$",
3073 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3077 emitcode ("cjne", "a,%s,%05d$",
3078 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3081 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3086 emitcode ("", "%05d$:", tlbl->key + 100);
3091 /* if the sizes are greater than 1 then we cannot */
3092 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3093 AOP_SIZE (IC_LEFT (ic)) > 1)
3096 /* we can if the aops of the left & result match or
3097 if they are in registers and the registers are the
3099 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3104 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3105 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3106 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3112 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3121 /*-----------------------------------------------------------------*/
3122 /* outBitAcc - output a bit in acc */
3123 /*-----------------------------------------------------------------*/
3125 outBitAcc (operand * result)
3127 symbol *tlbl = newiTempLabel (NULL);
3128 /* if the result is a bit */
3129 if (AOP_TYPE (result) == AOP_CRY)
3131 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3135 emitcode ("jz", "%05d$", tlbl->key + 100);
3136 emitcode ("mov", "a,%s", one);
3137 emitcode ("", "%05d$:", tlbl->key + 100);
3142 /*-----------------------------------------------------------------*/
3143 /* genPlusBits - generates code for addition of two bits */
3144 /*-----------------------------------------------------------------*/
3146 genPlusBits (iCode * ic)
3148 D(emitcode ("; genPlusBits",""));
3150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3152 symbol *lbl = newiTempLabel (NULL);
3153 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3154 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3155 emitcode ("cpl", "c");
3156 emitcode ("", "%05d$:", (lbl->key + 100));
3157 outBitC (IC_RESULT (ic));
3161 emitcode ("clr", "a");
3162 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3163 emitcode ("rlc", "a");
3164 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3165 emitcode ("addc", "a,#0x00");
3166 outAcc (IC_RESULT (ic));
3171 /* This is the original version of this code.
3173 * This is being kept around for reference,
3174 * because I am not entirely sure I got it right...
3177 adjustArithmeticResult (iCode * ic)
3179 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3180 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3181 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3182 aopPut (AOP (IC_RESULT (ic)),
3183 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3185 isOperandVolatile (IC_RESULT (ic), FALSE));
3187 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3188 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3189 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3190 aopPut (AOP (IC_RESULT (ic)),
3191 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3193 isOperandVolatile (IC_RESULT (ic), FALSE));
3195 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3196 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3197 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3198 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3199 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3202 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3203 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3207 /* This is the pure and virtuous version of this code.
3208 * I'm pretty certain it's right, but not enough to toss the old
3212 adjustArithmeticResult (iCode * ic)
3214 if (opIsGptr (IC_RESULT (ic)) &&
3215 opIsGptr (IC_LEFT (ic)) &&
3216 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3218 aopPut (AOP (IC_RESULT (ic)),
3219 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3221 isOperandVolatile (IC_RESULT (ic), FALSE));
3224 if (opIsGptr (IC_RESULT (ic)) &&
3225 opIsGptr (IC_RIGHT (ic)) &&
3226 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3228 aopPut (AOP (IC_RESULT (ic)),
3229 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3231 isOperandVolatile (IC_RESULT (ic), FALSE));
3234 if (opIsGptr (IC_RESULT (ic)) &&
3235 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3236 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3237 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3238 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3241 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3242 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3247 /*-----------------------------------------------------------------*/
3248 /* genPlus - generates code for addition */
3249 /*-----------------------------------------------------------------*/
3251 genPlus (iCode * ic)
3253 int size, offset = 0;
3256 asmop *leftOp, *rightOp;
3259 /* special cases :- */
3261 D(emitcode ("; genPlus",""));
3263 aopOp (IC_LEFT (ic), ic, FALSE);
3264 aopOp (IC_RIGHT (ic), ic, FALSE);
3265 aopOp (IC_RESULT (ic), ic, TRUE);
3267 /* if literal, literal on the right or
3268 if left requires ACC or right is already
3270 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3271 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3272 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3274 operand *t = IC_RIGHT (ic);
3275 IC_RIGHT (ic) = IC_LEFT (ic);
3279 /* if both left & right are in bit
3281 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3282 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3288 /* if left in bit space & right literal */
3289 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3290 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3292 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3293 /* if result in bit space */
3294 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3296 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3297 emitcode ("cpl", "c");
3298 outBitC (IC_RESULT (ic));
3302 size = getDataSize (IC_RESULT (ic));
3305 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3306 emitcode ("addc", "a,#00");
3307 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3313 /* if I can do an increment instead
3314 of add then GOOD for ME */
3315 if (genPlusIncr (ic) == TRUE)
3318 size = getDataSize (IC_RESULT (ic));
3319 leftOp = AOP(IC_LEFT(ic));
3320 rightOp = AOP(IC_RIGHT(ic));
3323 /* if this is an add for an array access
3324 at a 256 byte boundary */
3326 && AOP_TYPE (op) == AOP_IMMD
3328 && IS_SPEC (OP_SYM_ETYPE (op))
3329 && SPEC_ABSA (OP_SYM_ETYPE (op))
3330 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3333 D(emitcode ("; genPlus aligned array",""));
3334 aopPut (AOP (IC_RESULT (ic)),
3335 aopGet (rightOp, 0, FALSE, FALSE),
3337 isOperandVolatile (IC_RESULT (ic), FALSE));
3339 if( 1 == getDataSize (IC_RIGHT (ic)) )
3341 aopPut (AOP (IC_RESULT (ic)),
3342 aopGet (leftOp, 1, FALSE, FALSE),
3344 isOperandVolatile (IC_RESULT (ic), FALSE));
3348 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3349 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3350 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3355 /* if the lower bytes of a literal are zero skip the addition */
3356 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3358 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3359 (skip_bytes+1 < size))
3364 D(emitcode ("; genPlus shortcut",""));
3369 if( offset >= skip_bytes )
3371 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3373 emitcode("mov", "b,a");
3374 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3375 emitcode("xch", "a,b");
3376 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3377 emitcode (add, "a,b");
3379 else if (aopGetUsesAcc (leftOp, offset))
3381 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3382 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3386 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3387 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3389 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3390 add = "addc"; /* further adds must propagate carry */
3394 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3395 isOperandVolatile (IC_RESULT (ic), FALSE))
3398 aopPut (AOP (IC_RESULT (ic)),
3399 aopGet (leftOp, offset, FALSE, FALSE),
3401 isOperandVolatile (IC_RESULT (ic), FALSE));
3407 adjustArithmeticResult (ic);
3410 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3411 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3412 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3415 /*-----------------------------------------------------------------*/
3416 /* genMinusDec :- does subtraction with deccrement if possible */
3417 /*-----------------------------------------------------------------*/
3419 genMinusDec (iCode * ic)
3421 unsigned int icount;
3422 unsigned int size = getDataSize (IC_RESULT (ic));
3424 /* will try to generate an increment */
3425 /* if the right side is not a literal
3427 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3430 /* if the literal value of the right hand side
3431 is greater than 4 then it is not worth it */
3432 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3435 D(emitcode ("; genMinusDec",""));
3437 /* if decrement >=16 bits in register or direct space */
3438 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3439 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3447 /* If the next instruction is a goto and the goto target
3448 * is <= 10 instructions previous to this, we can generate
3449 * jumps straight to that target.
3451 if (ic->next && ic->next->op == GOTO
3452 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3453 && labelRange <= 10)
3455 emitcode (";", "tail decrement optimized");
3456 tlbl = IC_LABEL (ic->next);
3461 tlbl = newiTempLabel (NULL);
3465 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3466 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3467 IS_AOP_PREG (IC_RESULT (ic)))
3468 emitcode ("cjne", "%s,#0xff,%05d$"
3469 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3473 emitcode ("mov", "a,#0xff");
3474 emitcode ("cjne", "a,%s,%05d$"
3475 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3478 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3481 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3482 IS_AOP_PREG (IC_RESULT (ic)))
3483 emitcode ("cjne", "%s,#0xff,%05d$"
3484 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3488 emitcode ("cjne", "a,%s,%05d$"
3489 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3492 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3496 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3497 IS_AOP_PREG (IC_RESULT (ic)))
3498 emitcode ("cjne", "%s,#0xff,%05d$"
3499 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3503 emitcode ("cjne", "a,%s,%05d$"
3504 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3507 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3511 emitcode ("", "%05d$:", tlbl->key + 100);
3516 /* if the sizes are greater than 1 then we cannot */
3517 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3518 AOP_SIZE (IC_LEFT (ic)) > 1)
3521 /* we can if the aops of the left & result match or
3522 if they are in registers and the registers are the
3524 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3528 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3536 /*-----------------------------------------------------------------*/
3537 /* addSign - complete with sign */
3538 /*-----------------------------------------------------------------*/
3540 addSign (operand * result, int offset, int sign)
3542 int size = (getDataSize (result) - offset);
3547 emitcode ("rlc", "a");
3548 emitcode ("subb", "a,acc");
3550 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3554 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3558 /*-----------------------------------------------------------------*/
3559 /* genMinusBits - generates code for subtraction of two bits */
3560 /*-----------------------------------------------------------------*/
3562 genMinusBits (iCode * ic)
3564 symbol *lbl = newiTempLabel (NULL);
3566 D(emitcode ("; genMinusBits",""));
3568 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3570 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3571 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3572 emitcode ("cpl", "c");
3573 emitcode ("", "%05d$:", (lbl->key + 100));
3574 outBitC (IC_RESULT (ic));
3578 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3579 emitcode ("subb", "a,acc");
3580 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3581 emitcode ("inc", "a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3583 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3584 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3588 /*-----------------------------------------------------------------*/
3589 /* genMinus - generates code for subtraction */
3590 /*-----------------------------------------------------------------*/
3592 genMinus (iCode * ic)
3594 int size, offset = 0;
3596 D(emitcode ("; genMinus",""));
3598 aopOp (IC_LEFT (ic), ic, FALSE);
3599 aopOp (IC_RIGHT (ic), ic, FALSE);
3600 aopOp (IC_RESULT (ic), ic, TRUE);
3602 /* special cases :- */
3603 /* if both left & right are in bit space */
3604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3605 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3611 /* if I can do an decrement instead
3612 of subtract then GOOD for ME */
3613 if (genMinusDec (ic) == TRUE)
3616 size = getDataSize (IC_RESULT (ic));
3618 /* if literal, add a,#-lit, else normal subb */
3619 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3621 unsigned long lit = 0L;
3623 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3628 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3629 /* first add without previous c */
3631 if (!size && lit== (unsigned long) -1) {
3632 emitcode ("dec", "a");
3634 emitcode ("add", "a,#0x%02x",
3635 (unsigned int) (lit & 0x0FFL));
3638 emitcode ("addc", "a,#0x%02x",
3639 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3641 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3646 asmop *leftOp, *rightOp;
3648 leftOp = AOP(IC_LEFT(ic));
3649 rightOp = AOP(IC_RIGHT(ic));
3653 if (aopGetUsesAcc(rightOp, offset)) {
3654 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3655 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3657 emitcode( "setb", "c");
3659 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3660 emitcode("cpl", "a");
3662 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3665 emitcode ("subb", "a,%s",
3666 aopGet(rightOp, offset, FALSE, TRUE));
3669 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3674 adjustArithmeticResult (ic);
3677 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3678 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3683 /*-----------------------------------------------------------------*/
3684 /* genMultbits :- multiplication of bits */
3685 /*-----------------------------------------------------------------*/
3687 genMultbits (operand * left,
3691 D(emitcode ("; genMultbits",""));
3693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3694 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3698 /*-----------------------------------------------------------------*/
3699 /* genMultOneByte : 8*8=8/16 bit multiplication */
3700 /*-----------------------------------------------------------------*/
3702 genMultOneByte (operand * left,
3707 int size = AOP_SIZE (result);
3708 bool runtimeSign, compiletimeSign;
3709 bool lUnsigned, rUnsigned;
3711 D(emitcode ("; genMultOneByte",""));
3713 if (size < 1 || size > 2)
3715 /* this should never happen */
3716 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3717 AOP_SIZE(result), __FILE__, lineno);
3721 /* (if two literals: the value is computed before) */
3722 /* if one literal, literal on the right */
3723 if (AOP_TYPE (left) == AOP_LIT)
3728 /* emitcode (";", "swapped left and right"); */
3730 /* if no literal, unsigned on the right: shorter code */
3731 if ( AOP_TYPE (right) != AOP_LIT
3732 && SPEC_USIGN (getSpec (operandType (left))))
3739 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3740 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3742 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
3743 no need to take care about the signedness! */
3744 || (lUnsigned && rUnsigned))
3746 /* just an unsigned 8 * 8 = 8 multiply
3748 /* emitcode (";","unsigned"); */
3749 /* TODO: check for accumulator clash between left & right aops? */
3751 if (AOP_TYPE (right) == AOP_LIT)
3753 /* moving to accumulator first helps peepholes */
3754 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3755 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3759 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3760 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3763 emitcode ("mul", "ab");
3764 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3766 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3770 /* we have to do a signed multiply */
3771 /* emitcode (";", "signed"); */
3773 /* now sign adjust for both left & right */
3775 /* let's see what's needed: */
3776 /* apply negative sign during runtime */
3777 runtimeSign = FALSE;
3778 /* negative sign from literals */
3779 compiletimeSign = FALSE;
3783 if (AOP_TYPE(left) == AOP_LIT)
3785 /* signed literal */
3786 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3788 compiletimeSign = TRUE;
3791 /* signed but not literal */
3797 if (AOP_TYPE(right) == AOP_LIT)
3799 /* signed literal */
3800 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3802 compiletimeSign ^= TRUE;
3805 /* signed but not literal */
3809 /* initialize F0, which stores the runtime sign */
3812 if (compiletimeSign)
3813 emitcode ("setb", "F0"); /* set sign flag */
3815 emitcode ("clr", "F0"); /* reset sign flag */
3818 /* save the signs of the operands */
3819 if (AOP_TYPE(right) == AOP_LIT)
3821 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3823 if (!rUnsigned && val < 0)
3824 emitcode ("mov", "b,#0x%02x", -val);
3826 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
3828 else /* ! literal */
3830 if (rUnsigned) /* emitcode (";", "signed"); */
3832 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3835 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
3836 lbl = newiTempLabel (NULL);
3837 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3838 emitcode ("cpl", "F0"); /* complement sign flag */
3839 emitcode ("cpl", "a"); /* 2's complement */
3840 emitcode ("inc", "a");
3841 emitcode ("", "%05d$:", (lbl->key + 100));
3842 emitcode ("mov", "b,a");
3846 if (AOP_TYPE(left) == AOP_LIT)
3848 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3850 if (!lUnsigned && val < 0)
3851 emitcode ("mov", "a,#0x%02x", -val);
3853 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
3855 else /* ! literal */
3857 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3861 lbl = newiTempLabel (NULL);
3862 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3863 emitcode ("cpl", "F0"); /* complement sign flag */
3864 emitcode ("cpl", "a"); /* 2's complement */
3865 emitcode ("inc", "a");
3866 emitcode ("", "%05d$:", (lbl->key + 100));
3870 /* now the multiplication */
3871 emitcode ("mul", "ab");
3872 if (runtimeSign || compiletimeSign)
3874 lbl = newiTempLabel (NULL);
3876 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
3877 emitcode ("cpl", "a"); /* lsb 2's complement */
3879 emitcode ("inc", "a"); /* inc doesn't set carry flag */
3882 emitcode ("add", "a,#1"); /* this sets carry flag */
3883 emitcode ("xch", "a,b");
3884 emitcode ("cpl", "a"); /* msb 2's complement */
3885 emitcode ("addc", "a,#0");
3886 emitcode ("xch", "a,b");
3888 emitcode ("", "%05d$:", (lbl->key + 100));
3890 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3892 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3895 /*-----------------------------------------------------------------*/
3896 /* genMult - generates code for multiplication */
3897 /*-----------------------------------------------------------------*/
3899 genMult (iCode * ic)
3901 operand *left = IC_LEFT (ic);
3902 operand *right = IC_RIGHT (ic);
3903 operand *result = IC_RESULT (ic);
3905 D(emitcode ("; genMult",""));
3907 /* assign the amsops */
3908 aopOp (left, ic, FALSE);
3909 aopOp (right, ic, FALSE);
3910 aopOp (result, ic, TRUE);
3912 /* special cases first */
3914 if (AOP_TYPE (left) == AOP_CRY &&
3915 AOP_TYPE (right) == AOP_CRY)
3917 genMultbits (left, right, result);
3921 /* if both are of size == 1 */
3922 #if 0 // one of them can be a sloc shared with the result
3923 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3925 if (getSize(operandType(left)) == 1 &&
3926 getSize(operandType(right)) == 1)
3929 genMultOneByte (left, right, result);
3933 /* should have been converted to function call */
3934 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3935 getSize(OP_SYMBOL(right)->type));
3939 freeAsmop (result, NULL, ic, TRUE);
3940 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3944 /*-----------------------------------------------------------------*/
3945 /* genDivbits :- division of bits */
3946 /*-----------------------------------------------------------------*/
3948 genDivbits (operand * left,
3955 D(emitcode ("; genDivbits",""));
3957 /* the result must be bit */
3958 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3959 l = aopGet (AOP (left), 0, FALSE, FALSE);
3963 emitcode ("div", "ab");
3964 emitcode ("rrc", "a");
3965 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3968 /*-----------------------------------------------------------------*/
3969 /* genDivOneByte : 8 bit division */
3970 /*-----------------------------------------------------------------*/
3972 genDivOneByte (operand * left,
3976 bool lUnsigned, rUnsigned;
3977 bool runtimeSign, compiletimeSign;
3981 D(emitcode ("; genDivOneByte",""));
3983 /* Why is it necessary that genDivOneByte() can return an int result?
3986 volatile unsigned char uc;
3987 volatile signed char sc1, sc2;
4000 In all cases a one byte result would overflow, the following cast to int
4001 would return the wrong result.
4003 Two possible solution:
4004 a) cast operands to int, if ((unsigned) / (signed)) or
4005 ((signed) / (signed))
4006 b) return an 16 bit signed int; this is what we're doing here!
4009 size = AOP_SIZE (result) - 1;
4011 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4012 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4014 /* signed or unsigned */
4015 if (lUnsigned && rUnsigned)
4017 /* unsigned is easy */
4018 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4019 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4020 emitcode ("div", "ab");
4021 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4023 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4027 /* signed is a little bit more difficult */
4029 /* now sign adjust for both left & right */
4031 /* let's see what's needed: */
4032 /* apply negative sign during runtime */
4033 runtimeSign = FALSE;
4034 /* negative sign from literals */
4035 compiletimeSign = FALSE;
4039 if (AOP_TYPE(left) == AOP_LIT)
4041 /* signed literal */
4042 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4044 compiletimeSign = TRUE;
4047 /* signed but not literal */
4053 if (AOP_TYPE(right) == AOP_LIT)
4055 /* signed literal */
4056 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4058 compiletimeSign ^= TRUE;
4061 /* signed but not literal */
4065 /* initialize F0, which stores the runtime sign */
4068 if (compiletimeSign)
4069 emitcode ("setb", "F0"); /* set sign flag */
4071 emitcode ("clr", "F0"); /* reset sign flag */
4074 /* save the signs of the operands */
4075 if (AOP_TYPE(right) == AOP_LIT)
4077 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4079 if (!rUnsigned && val < 0)
4080 emitcode ("mov", "b,#0x%02x", -val);
4082 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4084 else /* ! literal */
4087 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4090 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4091 lbl = newiTempLabel (NULL);
4092 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4093 emitcode ("cpl", "F0"); /* complement sign flag */
4094 emitcode ("cpl", "a"); /* 2's complement */
4095 emitcode ("inc", "a");
4096 emitcode ("", "%05d$:", (lbl->key + 100));
4097 emitcode ("mov", "b,a");
4101 if (AOP_TYPE(left) == AOP_LIT)
4103 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4105 if (!lUnsigned && val < 0)
4106 emitcode ("mov", "a,#0x%02x", -val);
4108 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4110 else /* ! literal */
4112 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4116 lbl = newiTempLabel (NULL);
4117 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4118 emitcode ("cpl", "F0"); /* complement sign flag */
4119 emitcode ("cpl", "a"); /* 2's complement */
4120 emitcode ("inc", "a");
4121 emitcode ("", "%05d$:", (lbl->key + 100));
4125 /* now the division */
4126 emitcode ("div", "ab");
4128 if (runtimeSign || compiletimeSign)
4130 lbl = newiTempLabel (NULL);
4132 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4133 emitcode ("cpl", "a"); /* lsb 2's complement */
4134 emitcode ("inc", "a");
4135 emitcode ("", "%05d$:", (lbl->key + 100));
4137 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4140 /* msb is 0x00 or 0xff depending on the sign */
4143 emitcode ("mov", "c,F0");
4144 emitcode ("subb", "a,acc");
4146 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4148 else /* compiletimeSign */
4150 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4155 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4157 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4161 /*-----------------------------------------------------------------*/
4162 /* genDiv - generates code for division */
4163 /*-----------------------------------------------------------------*/
4167 operand *left = IC_LEFT (ic);
4168 operand *right = IC_RIGHT (ic);
4169 operand *result = IC_RESULT (ic);
4171 D(emitcode ("; genDiv",""));
4173 /* assign the amsops */
4174 aopOp (left, ic, FALSE);
4175 aopOp (right, ic, FALSE);
4176 aopOp (result, ic, TRUE);
4178 /* special cases first */
4180 if (AOP_TYPE (left) == AOP_CRY &&
4181 AOP_TYPE (right) == AOP_CRY)
4183 genDivbits (left, right, result);
4187 /* if both are of size == 1 */
4188 if (AOP_SIZE (left) == 1 &&
4189 AOP_SIZE (right) == 1)
4191 genDivOneByte (left, right, result);
4195 /* should have been converted to function call */
4198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4199 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4200 freeAsmop (result, NULL, ic, TRUE);
4203 /*-----------------------------------------------------------------*/
4204 /* genModbits :- modulus of bits */
4205 /*-----------------------------------------------------------------*/
4207 genModbits (operand * left,
4214 D(emitcode ("; genModbits",""));
4216 /* the result must be bit */
4217 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4218 l = aopGet (AOP (left), 0, FALSE, FALSE);
4222 emitcode ("div", "ab");
4223 emitcode ("mov", "a,b");
4224 emitcode ("rrc", "a");
4225 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4228 /*-----------------------------------------------------------------*/
4229 /* genModOneByte : 8 bit modulus */
4230 /*-----------------------------------------------------------------*/
4232 genModOneByte (operand * left,
4236 bool lUnsigned, rUnsigned;
4237 bool runtimeSign, compiletimeSign;
4241 D(emitcode ("; genModOneByte",""));
4243 size = AOP_SIZE (result) - 1;
4245 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4246 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4248 /* signed or unsigned */
4249 if (lUnsigned && rUnsigned)
4251 /* unsigned is easy */
4252 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4253 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4254 emitcode ("div", "ab");
4255 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4257 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4261 /* signed is a little bit more difficult */
4263 /* now sign adjust for both left & right */
4265 /* modulus: sign of the right operand has no influence on the result! */
4266 if (AOP_TYPE(right) == AOP_LIT)
4268 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4270 if (!rUnsigned && val < 0)
4271 emitcode ("mov", "b,#0x%02x", -val);
4273 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4275 else /* not literal */
4278 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4281 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4282 lbl = newiTempLabel (NULL);
4283 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4284 emitcode ("cpl", "a"); /* 2's complement */
4285 emitcode ("inc", "a");
4286 emitcode ("", "%05d$:", (lbl->key + 100));
4287 emitcode ("mov", "b,a");
4291 /* let's see what's needed: */
4292 /* apply negative sign during runtime */
4293 runtimeSign = FALSE;
4294 /* negative sign from literals */
4295 compiletimeSign = FALSE;
4297 /* sign adjust left side */
4298 if (AOP_TYPE(left) == AOP_LIT)
4300 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4302 if (!lUnsigned && val < 0)
4304 compiletimeSign = TRUE; /* set sign flag */
4305 emitcode ("mov", "a,#0x%02x", -val);
4308 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4310 else /* ! literal */
4312 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4317 emitcode ("clr", "F0"); /* clear sign flag */
4319 lbl = newiTempLabel (NULL);
4320 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4321 emitcode ("setb", "F0"); /* set sign flag */
4322 emitcode ("cpl", "a"); /* 2's complement */
4323 emitcode ("inc", "a");
4324 emitcode ("", "%05d$:", (lbl->key + 100));
4328 /* now the modulus */
4329 emitcode ("div", "ab");
4331 if (runtimeSign || compiletimeSign)
4333 emitcode ("mov", "a,b");
4334 lbl = newiTempLabel (NULL);
4336 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4337 emitcode ("cpl", "a"); /* 2's complement */
4338 emitcode ("inc", "a");
4339 emitcode ("", "%05d$:", (lbl->key + 100));
4341 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4344 /* msb is 0x00 or 0xff depending on the sign */
4347 emitcode ("mov", "c,F0");
4348 emitcode ("subb", "a,acc");
4350 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4352 else /* compiletimeSign */
4354 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4359 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4361 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4365 /*-----------------------------------------------------------------*/
4366 /* genMod - generates code for division */
4367 /*-----------------------------------------------------------------*/
4371 operand *left = IC_LEFT (ic);
4372 operand *right = IC_RIGHT (ic);
4373 operand *result = IC_RESULT (ic);
4375 D(emitcode ("; genMod",""));
4377 /* assign the amsops */
4378 aopOp (left, ic, FALSE);
4379 aopOp (right, ic, FALSE);
4380 aopOp (result, ic, TRUE);
4382 /* special cases first */
4384 if (AOP_TYPE (left) == AOP_CRY &&
4385 AOP_TYPE (right) == AOP_CRY)
4387 genModbits (left, right, result);
4391 /* if both are of size == 1 */
4392 if (AOP_SIZE (left) == 1 &&
4393 AOP_SIZE (right) == 1)
4395 genModOneByte (left, right, result);
4399 /* should have been converted to function call */
4403 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4404 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4405 freeAsmop (result, NULL, ic, TRUE);
4408 /*-----------------------------------------------------------------*/
4409 /* genIfxJump :- will create a jump depending on the ifx */
4410 /*-----------------------------------------------------------------*/
4412 genIfxJump (iCode * ic, char *jval)
4415 symbol *tlbl = newiTempLabel (NULL);
4418 D(emitcode ("; genIfxJump",""));
4420 /* if true label then we jump if condition
4424 jlbl = IC_TRUE (ic);
4425 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4426 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4430 /* false label is present */
4431 jlbl = IC_FALSE (ic);
4432 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4433 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4435 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4436 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4438 emitcode (inst, "%05d$", tlbl->key + 100);
4439 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4440 emitcode ("", "%05d$:", tlbl->key + 100);
4442 /* mark the icode as generated */
4446 /*-----------------------------------------------------------------*/
4447 /* genCmp :- greater or less than comparison */
4448 /*-----------------------------------------------------------------*/
4450 genCmp (operand * left, operand * right,
4451 operand * result, iCode * ifx, int sign, iCode *ic)
4453 int size, offset = 0;
4454 unsigned long lit = 0L;
4457 D(emitcode ("; genCmp",""));
4459 /* if left & right are bit variables */
4460 if (AOP_TYPE (left) == AOP_CRY &&
4461 AOP_TYPE (right) == AOP_CRY)
4463 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4464 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4468 /* subtract right from left if at the
4469 end the carry flag is set then we know that
4470 left is greater than right */
4471 size = max (AOP_SIZE (left), AOP_SIZE (right));
4473 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4474 if ((size == 1) && !sign &&
4475 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4477 symbol *lbl = newiTempLabel (NULL);
4478 emitcode ("cjne", "%s,%s,%05d$",
4479 aopGet (AOP (left), offset, FALSE, FALSE),
4480 aopGet (AOP (right), offset, FALSE, FALSE),
4482 emitcode ("", "%05d$:", lbl->key + 100);
4486 if (AOP_TYPE (right) == AOP_LIT)
4488 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4489 /* optimize if(x < 0) or if(x >= 0) */
4498 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4499 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4501 genIfxJump (ifx, "acc.7");
4505 emitcode ("rlc", "a");
4513 rightInB = aopGetUsesAcc(AOP (right), offset);
4515 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4516 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4517 if (sign && size == 0)
4519 emitcode ("xrl", "a,#0x80");
4520 if (AOP_TYPE (right) == AOP_LIT)
4522 unsigned long lit = (unsigned long)
4523 floatFromVal (AOP (right)->aopu.aop_lit);
4524 emitcode ("subb", "a,#0x%02x",
4525 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4530 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4531 emitcode ("xrl", "b,#0x80");
4532 emitcode ("subb", "a,b");
4538 emitcode ("subb", "a,b");
4540 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4548 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4549 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4550 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4556 /* if the result is used in the next
4557 ifx conditional branch then generate
4558 code a little differently */
4560 genIfxJump (ifx, "c");
4563 /* leave the result in acc */
4567 /*-----------------------------------------------------------------*/
4568 /* genCmpGt :- greater than comparison */
4569 /*-----------------------------------------------------------------*/
4571 genCmpGt (iCode * ic, iCode * ifx)
4573 operand *left, *right, *result;
4574 sym_link *letype, *retype;
4577 D(emitcode ("; genCmpGt",""));
4579 left = IC_LEFT (ic);
4580 right = IC_RIGHT (ic);
4581 result = IC_RESULT (ic);
4583 letype = getSpec (operandType (left));
4584 retype = getSpec (operandType (right));
4585 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4586 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4587 /* assign the amsops */
4588 aopOp (left, ic, FALSE);
4589 aopOp (right, ic, FALSE);
4590 aopOp (result, ic, TRUE);
4592 genCmp (right, left, result, ifx, sign,ic);
4594 freeAsmop (result, NULL, ic, TRUE);
4597 /*-----------------------------------------------------------------*/
4598 /* genCmpLt - less than comparisons */
4599 /*-----------------------------------------------------------------*/
4601 genCmpLt (iCode * ic, iCode * ifx)
4603 operand *left, *right, *result;
4604 sym_link *letype, *retype;
4607 D(emitcode ("; genCmpLt",""));
4609 left = IC_LEFT (ic);
4610 right = IC_RIGHT (ic);
4611 result = IC_RESULT (ic);
4613 letype = getSpec (operandType (left));
4614 retype = getSpec (operandType (right));
4615 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4616 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4617 /* assign the amsops */
4618 aopOp (left, ic, FALSE);
4619 aopOp (right, ic, FALSE);
4620 aopOp (result, ic, TRUE);
4622 genCmp (left, right, result, ifx, sign,ic);
4624 freeAsmop (result, NULL, ic, TRUE);
4627 /*-----------------------------------------------------------------*/
4628 /* gencjneshort - compare and jump if not equal */
4629 /*-----------------------------------------------------------------*/
4631 gencjneshort (operand * left, operand * right, symbol * lbl)
4633 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4635 unsigned long lit = 0L;
4637 /* if the left side is a literal or
4638 if the right is in a pointer register and left
4640 if ((AOP_TYPE (left) == AOP_LIT) ||
4641 (AOP_TYPE (left) == AOP_IMMD) ||
4642 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4649 if (AOP_TYPE (right) == AOP_LIT)
4650 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4652 /* if the right side is a literal then anything goes */
4653 if (AOP_TYPE (right) == AOP_LIT &&
4654 AOP_TYPE (left) != AOP_DIR &&
4655 AOP_TYPE (left) != AOP_IMMD)
4659 emitcode ("cjne", "%s,%s,%05d$",
4660 aopGet (AOP (left), offset, FALSE, FALSE),
4661 aopGet (AOP (right), offset, FALSE, FALSE),
4667 /* if the right side is in a register or in direct space or
4668 if the left is a pointer register & right is not */
4669 else if (AOP_TYPE (right) == AOP_REG ||
4670 AOP_TYPE (right) == AOP_DIR ||
4671 AOP_TYPE (right) == AOP_LIT ||
4672 AOP_TYPE (right) == AOP_IMMD ||
4673 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4674 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4678 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4679 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4680 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4681 emitcode ("jnz", "%05d$", lbl->key + 100);
4683 emitcode ("cjne", "a,%s,%05d$",
4684 aopGet (AOP (right), offset, FALSE, TRUE),
4691 /* right is a pointer reg need both a & b */
4694 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4695 if (strcmp (l, "b"))
4696 emitcode ("mov", "b,%s", l);
4697 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4698 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4704 /*-----------------------------------------------------------------*/
4705 /* gencjne - compare and jump if not equal */
4706 /*-----------------------------------------------------------------*/
4708 gencjne (operand * left, operand * right, symbol * lbl)
4710 symbol *tlbl = newiTempLabel (NULL);
4712 gencjneshort (left, right, lbl);
4714 emitcode ("mov", "a,%s", one);
4715 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4716 emitcode ("", "%05d$:", lbl->key + 100);
4717 emitcode ("clr", "a");
4718 emitcode ("", "%05d$:", tlbl->key + 100);
4721 /*-----------------------------------------------------------------*/
4722 /* genCmpEq - generates code for equal to */
4723 /*-----------------------------------------------------------------*/
4725 genCmpEq (iCode * ic, iCode * ifx)
4727 operand *left, *right, *result;
4729 D(emitcode ("; genCmpEq",""));
4731 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4732 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4733 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4735 /* if literal, literal on the right or
4736 if the right is in a pointer register and left
4738 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4739 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4741 operand *t = IC_RIGHT (ic);
4742 IC_RIGHT (ic) = IC_LEFT (ic);
4746 if (ifx && !AOP_SIZE (result))
4749 /* if they are both bit variables */
4750 if (AOP_TYPE (left) == AOP_CRY &&
4751 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4753 if (AOP_TYPE (right) == AOP_LIT)
4755 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4758 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4759 emitcode ("cpl", "c");
4763 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4767 emitcode ("clr", "c");
4769 /* AOP_TYPE(right) == AOP_CRY */
4773 symbol *lbl = newiTempLabel (NULL);
4774 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4775 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4776 emitcode ("cpl", "c");
4777 emitcode ("", "%05d$:", (lbl->key + 100));
4779 /* if true label then we jump if condition
4781 tlbl = newiTempLabel (NULL);
4784 emitcode ("jnc", "%05d$", tlbl->key + 100);
4785 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4789 emitcode ("jc", "%05d$", tlbl->key + 100);
4790 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4792 emitcode ("", "%05d$:", tlbl->key + 100);
4796 tlbl = newiTempLabel (NULL);
4797 gencjneshort (left, right, tlbl);
4800 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4801 emitcode ("", "%05d$:", tlbl->key + 100);
4805 symbol *lbl = newiTempLabel (NULL);
4806 emitcode ("sjmp", "%05d$", lbl->key + 100);
4807 emitcode ("", "%05d$:", tlbl->key + 100);
4808 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4809 emitcode ("", "%05d$:", lbl->key + 100);
4812 /* mark the icode as generated */
4817 /* if they are both bit variables */
4818 if (AOP_TYPE (left) == AOP_CRY &&
4819 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4821 if (AOP_TYPE (right) == AOP_LIT)
4823 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4826 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4827 emitcode ("cpl", "c");
4831 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4835 emitcode ("clr", "c");
4837 /* AOP_TYPE(right) == AOP_CRY */
4841 symbol *lbl = newiTempLabel (NULL);
4842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4843 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4844 emitcode ("cpl", "c");
4845 emitcode ("", "%05d$:", (lbl->key + 100));
4848 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4855 genIfxJump (ifx, "c");
4858 /* if the result is used in an arithmetic operation
4859 then put the result in place */
4864 gencjne (left, right, newiTempLabel (NULL));
4865 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4867 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4872 genIfxJump (ifx, "a");
4875 /* if the result is used in an arithmetic operation
4876 then put the result in place */
4877 if (AOP_TYPE (result) != AOP_CRY)
4879 /* leave the result in acc */
4883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885 freeAsmop (result, NULL, ic, TRUE);
4888 /*-----------------------------------------------------------------*/
4889 /* ifxForOp - returns the icode containing the ifx for operand */
4890 /*-----------------------------------------------------------------*/
4892 ifxForOp (operand * op, iCode * ic)
4894 /* if true symbol then needs to be assigned */
4895 if (IS_TRUE_SYMOP (op))
4898 /* if this has register type condition and
4899 the next instruction is ifx with the same operand
4900 and live to of the operand is upto the ifx only then */
4902 ic->next->op == IFX &&
4903 IC_COND (ic->next)->key == op->key &&
4904 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4910 /*-----------------------------------------------------------------*/
4911 /* hasInc - operand is incremented before any other use */
4912 /*-----------------------------------------------------------------*/
4914 hasInc (operand *op, iCode *ic,int osize)
4916 sym_link *type = operandType(op);
4917 sym_link *retype = getSpec (type);
4918 iCode *lic = ic->next;
4921 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4922 if (!IS_SYMOP(op)) return NULL;
4924 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4925 if (IS_AGGREGATE(type->next)) return NULL;
4926 if (osize != (isize = getSize(type->next))) return NULL;
4929 /* if operand of the form op = op + <sizeof *op> */
4930 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4931 isOperandEqual(IC_RESULT(lic),op) &&
4932 isOperandLiteral(IC_RIGHT(lic)) &&
4933 operandLitValue(IC_RIGHT(lic)) == isize) {
4936 /* if the operand used or deffed */
4937 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4940 /* if GOTO or IFX */
4941 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4947 /*-----------------------------------------------------------------*/
4948 /* genAndOp - for && operation */
4949 /*-----------------------------------------------------------------*/
4951 genAndOp (iCode * ic)
4953 operand *left, *right, *result;
4956 D(emitcode ("; genAndOp",""));
4958 /* note here that && operations that are in an
4959 if statement are taken away by backPatchLabels
4960 only those used in arthmetic operations remain */
4961 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4962 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4963 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4965 /* if both are bit variables */
4966 if (AOP_TYPE (left) == AOP_CRY &&
4967 AOP_TYPE (right) == AOP_CRY)
4969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4970 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4975 tlbl = newiTempLabel (NULL);
4977 emitcode ("jz", "%05d$", tlbl->key + 100);
4979 emitcode ("", "%05d$:", tlbl->key + 100);
4983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4985 freeAsmop (result, NULL, ic, TRUE);
4989 /*-----------------------------------------------------------------*/
4990 /* genOrOp - for || operation */
4991 /*-----------------------------------------------------------------*/
4993 genOrOp (iCode * ic)
4995 operand *left, *right, *result;
4998 D(emitcode ("; genOrOp",""));
5000 /* note here that || operations that are in an
5001 if statement are taken away by backPatchLabels
5002 only those used in arthmetic operations remain */
5003 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5004 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5005 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5007 /* if both are bit variables */
5008 if (AOP_TYPE (left) == AOP_CRY &&
5009 AOP_TYPE (right) == AOP_CRY)
5011 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5012 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5017 tlbl = newiTempLabel (NULL);
5019 emitcode ("jnz", "%05d$", tlbl->key + 100);
5021 emitcode ("", "%05d$:", tlbl->key + 100);
5025 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5026 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5027 freeAsmop (result, NULL, ic, TRUE);
5030 /*-----------------------------------------------------------------*/
5031 /* isLiteralBit - test if lit == 2^n */
5032 /*-----------------------------------------------------------------*/
5034 isLiteralBit (unsigned long lit)
5036 unsigned long pw[32] =
5037 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5038 0x100L, 0x200L, 0x400L, 0x800L,
5039 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5040 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5041 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5042 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5043 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5046 for (idx = 0; idx < 32; idx++)
5052 /*-----------------------------------------------------------------*/
5053 /* continueIfTrue - */
5054 /*-----------------------------------------------------------------*/
5056 continueIfTrue (iCode * ic)
5059 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5063 /*-----------------------------------------------------------------*/
5065 /*-----------------------------------------------------------------*/
5067 jumpIfTrue (iCode * ic)
5070 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5074 /*-----------------------------------------------------------------*/
5075 /* jmpTrueOrFalse - */
5076 /*-----------------------------------------------------------------*/
5078 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5080 // ugly but optimized by peephole
5083 symbol *nlbl = newiTempLabel (NULL);
5084 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5085 emitcode ("", "%05d$:", tlbl->key + 100);
5086 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5087 emitcode ("", "%05d$:", nlbl->key + 100);
5091 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5092 emitcode ("", "%05d$:", tlbl->key + 100);
5097 /*-----------------------------------------------------------------*/
5098 /* genAnd - code for and */
5099 /*-----------------------------------------------------------------*/
5101 genAnd (iCode * ic, iCode * ifx)
5103 operand *left, *right, *result;
5104 int size, offset = 0;
5105 unsigned long lit = 0L;
5109 D(emitcode ("; genAnd",""));
5111 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5112 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5113 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5116 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5118 AOP_TYPE (left), AOP_TYPE (right));
5119 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5121 AOP_SIZE (left), AOP_SIZE (right));
5124 /* if left is a literal & right is not then exchange them */
5125 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5126 AOP_NEEDSACC (left))
5128 operand *tmp = right;
5133 /* if result = right then exchange them */
5134 if (sameRegs (AOP (result), AOP (right)))
5136 operand *tmp = right;
5141 /* if right is bit then exchange them */
5142 if (AOP_TYPE (right) == AOP_CRY &&
5143 AOP_TYPE (left) != AOP_CRY)
5145 operand *tmp = right;
5149 if (AOP_TYPE (right) == AOP_LIT)
5150 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5152 size = AOP_SIZE (result);
5155 // result = bit & yy;
5156 if (AOP_TYPE (left) == AOP_CRY)
5158 // c = bit & literal;
5159 if (AOP_TYPE (right) == AOP_LIT)
5163 if (size && sameRegs (AOP (result), AOP (left)))
5166 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5171 if (size && (AOP_TYPE (result) == AOP_CRY))
5173 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5176 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5181 emitcode ("clr", "c");
5186 if (AOP_TYPE (right) == AOP_CRY)
5189 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5190 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5195 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5197 emitcode ("rrc", "a");
5198 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5206 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5207 genIfxJump (ifx, "c");
5211 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5212 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5213 if ((AOP_TYPE (right) == AOP_LIT) &&
5214 (AOP_TYPE (result) == AOP_CRY) &&
5215 (AOP_TYPE (left) != AOP_CRY))
5217 int posbit = isLiteralBit (lit);
5222 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5225 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5231 sprintf (buffer, "acc.%d", posbit & 0x07);
5232 genIfxJump (ifx, buffer);
5239 symbol *tlbl = newiTempLabel (NULL);
5240 int sizel = AOP_SIZE (left);
5242 emitcode ("setb", "c");
5245 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5247 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5249 if ((posbit = isLiteralBit (bytelit)) != 0)
5250 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5253 if (bytelit != 0x0FFL)
5254 emitcode ("anl", "a,%s",
5255 aopGet (AOP (right), offset, FALSE, TRUE));
5256 emitcode ("jnz", "%05d$", tlbl->key + 100);
5261 // bit = left & literal
5264 emitcode ("clr", "c");
5265 emitcode ("", "%05d$:", tlbl->key + 100);
5267 // if(left & literal)
5271 jmpTrueOrFalse (ifx, tlbl);
5273 emitcode ("", "%05d$:", tlbl->key + 100);
5281 /* if left is same as result */
5282 if (sameRegs (AOP (result), AOP (left)))
5284 for (; size--; offset++)
5286 if (AOP_TYPE (right) == AOP_LIT)
5288 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5290 else if (bytelit == 0)
5292 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5294 else if (IS_AOP_PREG (result))
5296 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5297 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5298 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5301 emitcode ("anl", "%s,%s",
5302 aopGet (AOP (left), offset, FALSE, TRUE),
5303 aopGet (AOP (right), offset, FALSE, FALSE));
5307 if (AOP_TYPE (left) == AOP_ACC)
5308 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5311 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5312 if (IS_AOP_PREG (result))
5314 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5315 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5319 emitcode ("anl", "%s,a",
5320 aopGet (AOP (left), offset, FALSE, TRUE));
5327 // left & result in different registers
5328 if (AOP_TYPE (result) == AOP_CRY)
5331 // if(size), result in bit
5332 // if(!size && ifx), conditional oper: if(left & right)
5333 symbol *tlbl = newiTempLabel (NULL);
5334 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5336 emitcode ("setb", "c");
5339 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5340 emitcode ("anl", "a,%s",
5341 aopGet (AOP (right), offset, FALSE, FALSE));
5343 if (AOP_TYPE(left)==AOP_ACC) {
5344 emitcode("mov", "b,a");
5345 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5346 emitcode("anl", "a,b");
5348 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5349 emitcode ("anl", "a,%s",
5350 aopGet (AOP (left), offset, FALSE, FALSE));
5353 emitcode ("jnz", "%05d$", tlbl->key + 100);
5359 emitcode ("", "%05d$:", tlbl->key + 100);
5363 jmpTrueOrFalse (ifx, tlbl);
5365 emitcode ("", "%05d$:", tlbl->key + 100);
5369 for (; (size--); offset++)
5372 // result = left & right
5373 if (AOP_TYPE (right) == AOP_LIT)
5375 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5377 aopPut (AOP (result),
5378 aopGet (AOP (left), offset, FALSE, FALSE),
5380 isOperandVolatile (result, FALSE));
5383 else if (bytelit == 0)
5385 /* dummy read of volatile operand */
5386 if (isOperandVolatile (left, FALSE))
5387 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5388 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5392 // faster than result <- left, anl result,right
5393 // and better if result is SFR
5394 if (AOP_TYPE (left) == AOP_ACC)
5395 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5398 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5399 emitcode ("anl", "a,%s",
5400 aopGet (AOP (left), offset, FALSE, FALSE));
5402 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5408 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5409 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410 freeAsmop (result, NULL, ic, TRUE);
5413 /*-----------------------------------------------------------------*/
5414 /* genOr - code for or */
5415 /*-----------------------------------------------------------------*/
5417 genOr (iCode * ic, iCode * ifx)
5419 operand *left, *right, *result;
5420 int size, offset = 0;
5421 unsigned long lit = 0L;
5423 D(emitcode ("; genOr",""));
5425 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5426 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5427 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5430 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5432 AOP_TYPE (left), AOP_TYPE (right));
5433 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5435 AOP_SIZE (left), AOP_SIZE (right));
5438 /* if left is a literal & right is not then exchange them */
5439 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5440 AOP_NEEDSACC (left))
5442 operand *tmp = right;
5447 /* if result = right then exchange them */
5448 if (sameRegs (AOP (result), AOP (right)))
5450 operand *tmp = right;
5455 /* if right is bit then exchange them */
5456 if (AOP_TYPE (right) == AOP_CRY &&
5457 AOP_TYPE (left) != AOP_CRY)
5459 operand *tmp = right;
5463 if (AOP_TYPE (right) == AOP_LIT)
5464 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5466 size = AOP_SIZE (result);
5470 if (AOP_TYPE (left) == AOP_CRY)
5472 if (AOP_TYPE (right) == AOP_LIT)
5474 // c = bit | literal;
5477 // lit != 0 => result = 1
5478 if (AOP_TYPE (result) == AOP_CRY)
5481 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5483 continueIfTrue (ifx);
5486 emitcode ("setb", "c");
5490 // lit == 0 => result = left
5491 if (size && sameRegs (AOP (result), AOP (left)))
5493 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5498 if (AOP_TYPE (right) == AOP_CRY)
5501 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5502 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5507 symbol *tlbl = newiTempLabel (NULL);
5508 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5509 emitcode ("setb", "c");
5510 emitcode ("jb", "%s,%05d$",
5511 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5513 emitcode ("jnz", "%05d$", tlbl->key + 100);
5514 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5516 jmpTrueOrFalse (ifx, tlbl);
5522 emitcode ("", "%05d$:", tlbl->key + 100);
5531 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5532 genIfxJump (ifx, "c");
5536 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5537 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5538 if ((AOP_TYPE (right) == AOP_LIT) &&
5539 (AOP_TYPE (result) == AOP_CRY) &&
5540 (AOP_TYPE (left) != AOP_CRY))
5546 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5548 continueIfTrue (ifx);
5553 // lit = 0, result = boolean(left)
5555 emitcode ("setb", "c");
5559 symbol *tlbl = newiTempLabel (NULL);
5560 emitcode ("jnz", "%05d$", tlbl->key + 100);
5562 emitcode ("", "%05d$:", tlbl->key + 100);
5566 genIfxJump (ifx, "a");
5574 /* if left is same as result */
5575 if (sameRegs (AOP (result), AOP (left)))
5577 for (; size--; offset++)
5579 if (AOP_TYPE (right) == AOP_LIT)
5581 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5583 /* dummy read of volatile operand */
5584 if (isOperandVolatile (left, FALSE))
5585 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5589 else if (IS_AOP_PREG (left))
5591 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5592 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5593 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5596 emitcode ("orl", "%s,%s",
5597 aopGet (AOP (left), offset, FALSE, TRUE),
5598 aopGet (AOP (right), offset, FALSE, FALSE));
5602 if (AOP_TYPE (left) == AOP_ACC)
5603 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5606 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5607 if (IS_AOP_PREG (left))
5609 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5610 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5613 emitcode ("orl", "%s,a",
5614 aopGet (AOP (left), offset, FALSE, TRUE));
5621 // left & result in different registers
5622 if (AOP_TYPE (result) == AOP_CRY)
5625 // if(size), result in bit
5626 // if(!size && ifx), conditional oper: if(left | right)
5627 symbol *tlbl = newiTempLabel (NULL);
5628 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5630 emitcode ("setb", "c");
5633 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5634 emitcode ("orl", "a,%s",
5635 aopGet (AOP (right), offset, FALSE, FALSE));
5637 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5638 emitcode ("orl", "a,%s",
5639 aopGet (AOP (left), offset, FALSE, FALSE));
5641 emitcode ("jnz", "%05d$", tlbl->key + 100);
5647 emitcode ("", "%05d$:", tlbl->key + 100);
5651 jmpTrueOrFalse (ifx, tlbl);
5653 emitcode ("", "%05d$:", tlbl->key + 100);
5656 for (; (size--); offset++)
5659 // result = left & right
5660 if (AOP_TYPE (right) == AOP_LIT)
5662 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5664 aopPut (AOP (result),
5665 aopGet (AOP (left), offset, FALSE, FALSE),
5667 isOperandVolatile (result, FALSE));
5671 // faster than result <- left, anl result,right
5672 // and better if result is SFR
5673 if (AOP_TYPE (left) == AOP_ACC)
5674 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5677 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5678 emitcode ("orl", "a,%s",
5679 aopGet (AOP (left), offset, FALSE, FALSE));
5681 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5686 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5687 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688 freeAsmop (result, NULL, ic, TRUE);
5691 /*-----------------------------------------------------------------*/
5692 /* genXor - code for xclusive or */
5693 /*-----------------------------------------------------------------*/
5695 genXor (iCode * ic, iCode * ifx)
5697 operand *left, *right, *result;
5698 int size, offset = 0;
5699 unsigned long lit = 0L;
5701 D(emitcode ("; genXor",""));
5703 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5704 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5705 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5708 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5710 AOP_TYPE (left), AOP_TYPE (right));
5711 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5713 AOP_SIZE (left), AOP_SIZE (right));
5716 /* if left is a literal & right is not ||
5717 if left needs acc & right does not */
5718 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5719 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5721 operand *tmp = right;
5726 /* if result = right then exchange them */
5727 if (sameRegs (AOP (result), AOP (right)))
5729 operand *tmp = right;
5734 /* if right is bit then exchange them */
5735 if (AOP_TYPE (right) == AOP_CRY &&
5736 AOP_TYPE (left) != AOP_CRY)
5738 operand *tmp = right;
5742 if (AOP_TYPE (right) == AOP_LIT)
5743 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5745 size = AOP_SIZE (result);
5749 if (AOP_TYPE (left) == AOP_CRY)
5751 if (AOP_TYPE (right) == AOP_LIT)
5753 // c = bit & literal;
5756 // lit>>1 != 0 => result = 1
5757 if (AOP_TYPE (result) == AOP_CRY)
5760 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5762 continueIfTrue (ifx);
5765 emitcode ("setb", "c");
5772 // lit == 0, result = left
5773 if (size && sameRegs (AOP (result), AOP (left)))
5775 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5779 // lit == 1, result = not(left)
5780 if (size && sameRegs (AOP (result), AOP (left)))
5782 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5787 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5788 emitcode ("cpl", "c");
5797 symbol *tlbl = newiTempLabel (NULL);
5798 if (AOP_TYPE (right) == AOP_CRY)
5801 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5805 int sizer = AOP_SIZE (right);
5807 // if val>>1 != 0, result = 1
5808 emitcode ("setb", "c");
5811 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5813 // test the msb of the lsb
5814 emitcode ("anl", "a,#0xfe");
5815 emitcode ("jnz", "%05d$", tlbl->key + 100);
5819 emitcode ("rrc", "a");
5821 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5822 emitcode ("cpl", "c");
5823 emitcode ("", "%05d$:", (tlbl->key + 100));
5830 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5831 genIfxJump (ifx, "c");
5835 if (sameRegs (AOP (result), AOP (left)))
5837 /* if left is same as result */
5838 for (; size--; offset++)
5840 if (AOP_TYPE (right) == AOP_LIT)
5842 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5844 else if (IS_AOP_PREG (left))
5846 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5847 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5848 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5851 emitcode ("xrl", "%s,%s",
5852 aopGet (AOP (left), offset, FALSE, TRUE),
5853 aopGet (AOP (right), offset, FALSE, FALSE));
5857 if (AOP_TYPE (left) == AOP_ACC)
5858 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5861 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5862 if (IS_AOP_PREG (left))
5864 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5865 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5868 emitcode ("xrl", "%s,a",
5869 aopGet (AOP (left), offset, FALSE, TRUE));
5876 // left & result in different registers
5877 if (AOP_TYPE (result) == AOP_CRY)
5880 // if(size), result in bit
5881 // if(!size && ifx), conditional oper: if(left ^ right)
5882 symbol *tlbl = newiTempLabel (NULL);
5883 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5885 emitcode ("setb", "c");
5888 if ((AOP_TYPE (right) == AOP_LIT) &&
5889 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5891 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5895 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5896 emitcode ("xrl", "a,%s",
5897 aopGet (AOP (right), offset, FALSE, FALSE));
5899 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5900 emitcode ("xrl", "a,%s",
5901 aopGet (AOP (left), offset, FALSE, FALSE));
5904 emitcode ("jnz", "%05d$", tlbl->key + 100);
5910 emitcode ("", "%05d$:", tlbl->key + 100);
5914 jmpTrueOrFalse (ifx, tlbl);
5917 for (; (size--); offset++)
5920 // result = left & right
5921 if (AOP_TYPE (right) == AOP_LIT)
5923 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5925 aopPut (AOP (result),
5926 aopGet (AOP (left), offset, FALSE, FALSE),
5928 isOperandVolatile (result, FALSE));
5932 // faster than result <- left, anl result,right
5933 // and better if result is SFR
5934 if (AOP_TYPE (left) == AOP_ACC)
5935 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5938 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5939 emitcode ("xrl", "a,%s",
5940 aopGet (AOP (left), offset, FALSE, TRUE));
5942 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5947 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5948 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5949 freeAsmop (result, NULL, ic, TRUE);
5952 /*-----------------------------------------------------------------*/
5953 /* genInline - write the inline code out */
5954 /*-----------------------------------------------------------------*/
5956 genInline (iCode * ic)
5958 char *buffer, *bp, *bp1;
5960 D(emitcode ("; genInline",""));
5962 _G.inLine += (!options.asmpeep);
5964 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5965 strcpy (buffer, IC_INLINE (ic));
5967 /* emit each line as a code */
5992 /* emitcode("",buffer); */
5993 _G.inLine -= (!options.asmpeep);
5996 /*-----------------------------------------------------------------*/
5997 /* genRRC - rotate right with carry */
5998 /*-----------------------------------------------------------------*/
6002 operand *left, *result;
6003 int size, offset = 0;
6006 D(emitcode ("; genRRC",""));
6008 /* rotate right with carry */
6009 left = IC_LEFT (ic);
6010 result = IC_RESULT (ic);
6011 aopOp (left, ic, FALSE);
6012 aopOp (result, ic, FALSE);
6014 /* move it to the result */
6015 size = AOP_SIZE (result);
6017 if (size == 1) { /* special case for 1 byte */
6018 l = aopGet (AOP (left), offset, FALSE, FALSE);
6020 emitcode ("rr", "a");
6026 l = aopGet (AOP (left), offset, FALSE, FALSE);
6028 emitcode ("rrc", "a");
6029 if (AOP_SIZE (result) > 1)
6030 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6032 /* now we need to put the carry into the
6033 highest order byte of the result */
6034 if (AOP_SIZE (result) > 1)
6036 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6039 emitcode ("mov", "acc.7,c");
6041 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6042 freeAsmop (left, NULL, ic, TRUE);
6043 freeAsmop (result, NULL, ic, TRUE);
6046 /*-----------------------------------------------------------------*/
6047 /* genRLC - generate code for rotate left with carry */
6048 /*-----------------------------------------------------------------*/
6052 operand *left, *result;
6053 int size, offset = 0;
6056 D(emitcode ("; genRLC",""));
6058 /* rotate right with carry */
6059 left = IC_LEFT (ic);
6060 result = IC_RESULT (ic);
6061 aopOp (left, ic, FALSE);
6062 aopOp (result, ic, FALSE);
6064 /* move it to the result */
6065 size = AOP_SIZE (result);
6069 l = aopGet (AOP (left), offset, FALSE, FALSE);
6071 if (size == 0) { /* special case for 1 byte */
6075 emitcode ("add", "a,acc");
6076 if (AOP_SIZE (result) > 1)
6077 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6080 l = aopGet (AOP (left), offset, FALSE, FALSE);
6082 emitcode ("rlc", "a");
6083 if (AOP_SIZE (result) > 1)
6084 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6087 /* now we need to put the carry into the
6088 highest order byte of the result */
6089 if (AOP_SIZE (result) > 1)
6091 l = aopGet (AOP (result), 0, FALSE, FALSE);
6094 emitcode ("mov", "acc.0,c");
6096 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6097 freeAsmop (left, NULL, ic, TRUE);
6098 freeAsmop (result, NULL, ic, TRUE);
6101 /*-----------------------------------------------------------------*/
6102 /* genGetHbit - generates code get highest order bit */
6103 /*-----------------------------------------------------------------*/
6105 genGetHbit (iCode * ic)
6107 operand *left, *result;
6109 D(emitcode ("; genGetHbit",""));
6111 left = IC_LEFT (ic);
6112 result = IC_RESULT (ic);
6113 aopOp (left, ic, FALSE);
6114 aopOp (result, ic, FALSE);
6116 /* get the highest order byte into a */
6117 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6118 if (AOP_TYPE (result) == AOP_CRY)
6120 emitcode ("rlc", "a");
6125 emitcode ("rl", "a");
6126 emitcode ("anl", "a,#0x01");
6131 freeAsmop (left, NULL, ic, TRUE);
6132 freeAsmop (result, NULL, ic, TRUE);
6135 /*-----------------------------------------------------------------*/
6136 /* genSwap - generates code to swap nibbles or bytes */
6137 /*-----------------------------------------------------------------*/
6139 genSwap (iCode * ic)
6141 operand *left, *result;
6143 D(emitcode ("; genSwap",""));
6145 left = IC_LEFT (ic);
6146 result = IC_RESULT (ic);
6147 aopOp (left, ic, FALSE);
6148 aopOp (result, ic, FALSE);
6150 switch (AOP_SIZE (left))
6152 case 1: /* swap nibbles in byte */
6153 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6154 emitcode ("swap", "a");
6155 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6157 case 2: /* swap bytes in word */
6158 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6160 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6161 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6162 0, isOperandVolatile (result, FALSE));
6163 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6165 else if (operandsEqu (left, result))
6168 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6169 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6171 emitcode ("mov", "b,a");
6174 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6175 0, isOperandVolatile (result, FALSE));
6176 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6180 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6181 0, isOperandVolatile (result, FALSE));
6182 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6183 1, isOperandVolatile (result, FALSE));
6187 wassertl(FALSE, "unsupported SWAP operand size");
6190 freeAsmop (left, NULL, ic, TRUE);
6191 freeAsmop (result, NULL, ic, TRUE);
6195 /*-----------------------------------------------------------------*/
6196 /* AccRol - rotate left accumulator by known count */
6197 /*-----------------------------------------------------------------*/
6199 AccRol (int shCount)
6201 shCount &= 0x0007; // shCount : 0..7
6208 emitcode ("rl", "a");
6211 emitcode ("rl", "a");
6212 emitcode ("rl", "a");
6215 emitcode ("swap", "a");
6216 emitcode ("rr", "a");
6219 emitcode ("swap", "a");
6222 emitcode ("swap", "a");
6223 emitcode ("rl", "a");
6226 emitcode ("rr", "a");
6227 emitcode ("rr", "a");
6230 emitcode ("rr", "a");
6235 /*-----------------------------------------------------------------*/
6236 /* AccLsh - left shift accumulator by known count */
6237 /*-----------------------------------------------------------------*/
6239 AccLsh (int shCount)
6244 emitcode ("add", "a,acc");
6245 else if (shCount == 2)
6247 emitcode ("add", "a,acc");
6248 emitcode ("add", "a,acc");
6252 /* rotate left accumulator */
6254 /* and kill the lower order bits */
6255 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6260 /*-----------------------------------------------------------------*/
6261 /* AccRsh - right shift accumulator by known count */
6262 /*-----------------------------------------------------------------*/
6264 AccRsh (int shCount)
6271 emitcode ("rrc", "a");
6275 /* rotate right accumulator */
6276 AccRol (8 - shCount);
6277 /* and kill the higher order bits */
6278 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6283 /*-----------------------------------------------------------------*/
6284 /* AccSRsh - signed right shift accumulator by known count */
6285 /*-----------------------------------------------------------------*/
6287 AccSRsh (int shCount)
6294 emitcode ("mov", "c,acc.7");
6295 emitcode ("rrc", "a");
6297 else if (shCount == 2)
6299 emitcode ("mov", "c,acc.7");
6300 emitcode ("rrc", "a");
6301 emitcode ("mov", "c,acc.7");
6302 emitcode ("rrc", "a");
6306 tlbl = newiTempLabel (NULL);
6307 /* rotate right accumulator */
6308 AccRol (8 - shCount);
6309 /* and kill the higher order bits */
6310 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6311 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6312 emitcode ("orl", "a,#0x%02x",
6313 (unsigned char) ~SRMask[shCount]);
6314 emitcode ("", "%05d$:", tlbl->key + 100);
6319 /*-----------------------------------------------------------------*/
6320 /* shiftR1Left2Result - shift right one byte from left to result */
6321 /*-----------------------------------------------------------------*/
6323 shiftR1Left2Result (operand * left, int offl,
6324 operand * result, int offr,
6325 int shCount, int sign)
6327 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6328 /* shift right accumulator */
6333 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6336 /*-----------------------------------------------------------------*/
6337 /* shiftL1Left2Result - shift left one byte from left to result */
6338 /*-----------------------------------------------------------------*/
6340 shiftL1Left2Result (operand * left, int offl,
6341 operand * result, int offr, int shCount)
6344 l = aopGet (AOP (left), offl, FALSE, FALSE);
6346 /* shift left accumulator */
6348 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6351 /*-----------------------------------------------------------------*/
6352 /* movLeft2Result - move byte from left to result */
6353 /*-----------------------------------------------------------------*/
6355 movLeft2Result (operand * left, int offl,
6356 operand * result, int offr, int sign)
6359 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6361 l = aopGet (AOP (left), offl, FALSE, FALSE);
6363 if (*l == '@' && (IS_AOP_PREG (result)))
6365 emitcode ("mov", "a,%s", l);
6366 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6371 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6374 /* MSB sign in acc.7 ! */
6375 if (getDataSize (left) == offl + 1)
6377 emitcode ("mov", "a,%s", l);
6378 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6385 /*-----------------------------------------------------------------*/
6386 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6387 /*-----------------------------------------------------------------*/
6391 emitcode ("rrc", "a");
6392 emitcode ("xch", "a,%s", x);
6393 emitcode ("rrc", "a");
6394 emitcode ("xch", "a,%s", x);
6397 /*-----------------------------------------------------------------*/
6398 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6399 /*-----------------------------------------------------------------*/
6403 emitcode ("xch", "a,%s", x);
6404 emitcode ("rlc", "a");
6405 emitcode ("xch", "a,%s", x);
6406 emitcode ("rlc", "a");
6409 /*-----------------------------------------------------------------*/
6410 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6411 /*-----------------------------------------------------------------*/
6415 emitcode ("xch", "a,%s", x);
6416 emitcode ("add", "a,acc");
6417 emitcode ("xch", "a,%s", x);
6418 emitcode ("rlc", "a");
6421 /*-----------------------------------------------------------------*/
6422 /* AccAXLsh - left shift a:x by known count (0..7) */
6423 /*-----------------------------------------------------------------*/
6425 AccAXLsh (char *x, int shCount)
6440 case 5: // AAAAABBB:CCCCCDDD
6442 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6444 emitcode ("anl", "a,#0x%02x",
6445 SLMask[shCount]); // BBB00000:CCCCCDDD
6447 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6449 AccRol (shCount); // DDDCCCCC:BBB00000
6451 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6453 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6455 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6457 emitcode ("anl", "a,#0x%02x",
6458 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6460 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6462 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6465 case 6: // AAAAAABB:CCCCCCDD
6466 emitcode ("anl", "a,#0x%02x",
6467 SRMask[shCount]); // 000000BB:CCCCCCDD
6468 emitcode ("mov", "c,acc.0"); // c = B
6469 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6471 AccAXRrl1 (x); // BCCCCCCD:D000000B
6472 AccAXRrl1 (x); // BBCCCCCC:DD000000
6474 emitcode("rrc","a");
6475 emitcode("xch","a,%s", x);
6476 emitcode("rrc","a");
6477 emitcode("mov","c,acc.0"); //<< get correct bit
6478 emitcode("xch","a,%s", x);
6480 emitcode("rrc","a");
6481 emitcode("xch","a,%s", x);
6482 emitcode("rrc","a");
6483 emitcode("xch","a,%s", x);
6486 case 7: // a:x <<= 7
6488 emitcode ("anl", "a,#0x%02x",
6489 SRMask[shCount]); // 0000000B:CCCCCCCD
6491 emitcode ("mov", "c,acc.0"); // c = B
6493 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6495 AccAXRrl1 (x); // BCCCCCCC:D0000000
6503 /*-----------------------------------------------------------------*/
6504 /* AccAXRsh - right shift a:x known count (0..7) */
6505 /*-----------------------------------------------------------------*/
6507 AccAXRsh (char *x, int shCount)
6515 AccAXRrl1 (x); // 0->a:x
6520 AccAXRrl1 (x); // 0->a:x
6523 AccAXRrl1 (x); // 0->a:x
6528 case 5: // AAAAABBB:CCCCCDDD = a:x
6530 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6532 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6534 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6536 emitcode ("anl", "a,#0x%02x",
6537 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6539 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6541 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6543 emitcode ("anl", "a,#0x%02x",
6544 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6546 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6548 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6550 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6553 case 6: // AABBBBBB:CCDDDDDD
6555 emitcode ("mov", "c,acc.7");
6556 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6558 emitcode ("mov", "c,acc.7");
6559 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6561 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6563 emitcode ("anl", "a,#0x%02x",
6564 SRMask[shCount]); // 000000AA:BBBBBBCC
6567 case 7: // ABBBBBBB:CDDDDDDD
6569 emitcode ("mov", "c,acc.7"); // c = A
6571 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6573 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6575 emitcode ("anl", "a,#0x%02x",
6576 SRMask[shCount]); // 0000000A:BBBBBBBC
6584 /*-----------------------------------------------------------------*/
6585 /* AccAXRshS - right shift signed a:x known count (0..7) */
6586 /*-----------------------------------------------------------------*/
6588 AccAXRshS (char *x, int shCount)
6596 emitcode ("mov", "c,acc.7");
6597 AccAXRrl1 (x); // s->a:x
6601 emitcode ("mov", "c,acc.7");
6602 AccAXRrl1 (x); // s->a:x
6604 emitcode ("mov", "c,acc.7");
6605 AccAXRrl1 (x); // s->a:x
6610 case 5: // AAAAABBB:CCCCCDDD = a:x
6612 tlbl = newiTempLabel (NULL);
6613 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6615 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6617 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6619 emitcode ("anl", "a,#0x%02x",
6620 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6622 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6624 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6626 emitcode ("anl", "a,#0x%02x",
6627 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6629 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6631 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6633 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6635 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6636 emitcode ("orl", "a,#0x%02x",
6637 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6639 emitcode ("", "%05d$:", tlbl->key + 100);
6640 break; // SSSSAAAA:BBBCCCCC
6642 case 6: // AABBBBBB:CCDDDDDD
6644 tlbl = newiTempLabel (NULL);
6645 emitcode ("mov", "c,acc.7");
6646 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6648 emitcode ("mov", "c,acc.7");
6649 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6651 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6653 emitcode ("anl", "a,#0x%02x",
6654 SRMask[shCount]); // 000000AA:BBBBBBCC
6656 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6657 emitcode ("orl", "a,#0x%02x",
6658 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6660 emitcode ("", "%05d$:", tlbl->key + 100);
6662 case 7: // ABBBBBBB:CDDDDDDD
6664 tlbl = newiTempLabel (NULL);
6665 emitcode ("mov", "c,acc.7"); // c = A
6667 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6669 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6671 emitcode ("anl", "a,#0x%02x",
6672 SRMask[shCount]); // 0000000A:BBBBBBBC
6674 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6675 emitcode ("orl", "a,#0x%02x",
6676 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6678 emitcode ("", "%05d$:", tlbl->key + 100);
6685 /*-----------------------------------------------------------------*/
6686 /* shiftL2Left2Result - shift left two bytes from left to result */
6687 /*-----------------------------------------------------------------*/
6689 shiftL2Left2Result (operand * left, int offl,
6690 operand * result, int offr, int shCount)
6692 if (sameRegs (AOP (result), AOP (left)) &&
6693 ((offl + MSB16) == offr))
6695 /* don't crash result[offr] */
6696 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6697 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6701 movLeft2Result (left, offl, result, offr, 0);
6702 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6704 /* ax << shCount (x = lsb(result)) */
6705 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6706 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6710 /*-----------------------------------------------------------------*/
6711 /* shiftR2Left2Result - shift right two bytes from left to result */
6712 /*-----------------------------------------------------------------*/
6714 shiftR2Left2Result (operand * left, int offl,
6715 operand * result, int offr,
6716 int shCount, int sign)
6718 if (sameRegs (AOP (result), AOP (left)) &&
6719 ((offl + MSB16) == offr))
6721 /* don't crash result[offr] */
6722 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6723 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6727 movLeft2Result (left, offl, result, offr, 0);
6728 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6730 /* a:x >> shCount (x = lsb(result)) */
6732 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6734 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6735 if (getDataSize (result) > 1)
6736 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6739 /*-----------------------------------------------------------------*/
6740 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6741 /*-----------------------------------------------------------------*/
6743 shiftLLeftOrResult (operand * left, int offl,
6744 operand * result, int offr, int shCount)
6746 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6747 /* shift left accumulator */
6749 /* or with result */
6750 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6751 /* back to result */
6752 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6755 /*-----------------------------------------------------------------*/
6756 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6757 /*-----------------------------------------------------------------*/
6759 shiftRLeftOrResult (operand * left, int offl,
6760 operand * result, int offr, int shCount)
6762 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6763 /* shift right accumulator */
6765 /* or with result */
6766 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6767 /* back to result */
6768 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6771 /*-----------------------------------------------------------------*/
6772 /* genlshOne - left shift a one byte quantity by known count */
6773 /*-----------------------------------------------------------------*/
6775 genlshOne (operand * result, operand * left, int shCount)
6777 D(emitcode ("; genlshOne",""));
6779 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6782 /*-----------------------------------------------------------------*/
6783 /* genlshTwo - left shift two bytes by known amount != 0 */
6784 /*-----------------------------------------------------------------*/
6786 genlshTwo (operand * result, operand * left, int shCount)
6790 D(emitcode ("; genlshTwo",""));
6792 size = getDataSize (result);
6794 /* if shCount >= 8 */
6802 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6804 movLeft2Result (left, LSB, result, MSB16, 0);
6806 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6809 /* 1 <= shCount <= 7 */
6813 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6815 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6819 /*-----------------------------------------------------------------*/
6820 /* shiftLLong - shift left one long from left to result */
6821 /* offl = LSB or MSB16 */
6822 /*-----------------------------------------------------------------*/
6824 shiftLLong (operand * left, operand * result, int offr)
6827 int size = AOP_SIZE (result);
6829 if (size >= LSB + offr)
6831 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6833 emitcode ("add", "a,acc");
6834 if (sameRegs (AOP (left), AOP (result)) &&
6835 size >= MSB16 + offr && offr != LSB)
6836 emitcode ("xch", "a,%s",
6837 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6839 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6842 if (size >= MSB16 + offr)
6844 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6846 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6849 emitcode ("rlc", "a");
6850 if (sameRegs (AOP (left), AOP (result)) &&
6851 size >= MSB24 + offr && offr != LSB)
6852 emitcode ("xch", "a,%s",
6853 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6855 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6858 if (size >= MSB24 + offr)
6860 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6862 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6865 emitcode ("rlc", "a");
6866 if (sameRegs (AOP (left), AOP (result)) &&
6867 size >= MSB32 + offr && offr != LSB)
6868 emitcode ("xch", "a,%s",
6869 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6871 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6874 if (size > MSB32 + offr)
6876 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6878 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6881 emitcode ("rlc", "a");
6882 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6885 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6888 /*-----------------------------------------------------------------*/
6889 /* genlshFour - shift four byte by a known amount != 0 */
6890 /*-----------------------------------------------------------------*/
6892 genlshFour (operand * result, operand * left, int shCount)
6896 D(emitcode ("; genlshFour",""));
6898 size = AOP_SIZE (result);
6900 /* if shifting more that 3 bytes */
6905 /* lowest order of left goes to the highest
6906 order of the destination */
6907 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6909 movLeft2Result (left, LSB, result, MSB32, 0);
6910 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6911 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6912 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6916 /* more than two bytes */
6917 else if (shCount >= 16)
6919 /* lower order two bytes goes to higher order two bytes */
6921 /* if some more remaining */
6923 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6926 movLeft2Result (left, MSB16, result, MSB32, 0);
6927 movLeft2Result (left, LSB, result, MSB24, 0);
6929 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6930 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6934 /* if more than 1 byte */
6935 else if (shCount >= 8)
6937 /* lower order three bytes goes to higher order three bytes */
6942 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6944 movLeft2Result (left, LSB, result, MSB16, 0);
6950 movLeft2Result (left, MSB24, result, MSB32, 0);
6951 movLeft2Result (left, MSB16, result, MSB24, 0);
6952 movLeft2Result (left, LSB, result, MSB16, 0);
6953 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6955 else if (shCount == 1)
6956 shiftLLong (left, result, MSB16);
6959 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6960 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6961 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6962 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6967 /* 1 <= shCount <= 7 */
6968 else if (shCount <= 2)
6970 shiftLLong (left, result, LSB);
6972 shiftLLong (result, result, LSB);
6974 /* 3 <= shCount <= 7, optimize */
6977 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6978 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6979 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6983 /*-----------------------------------------------------------------*/
6984 /* genLeftShiftLiteral - left shifting by known count */
6985 /*-----------------------------------------------------------------*/
6987 genLeftShiftLiteral (operand * left,
6992 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6995 D(emitcode ("; genLeftShiftLiteral",""));
6997 freeAsmop (right, NULL, ic, TRUE);
6999 aopOp (left, ic, FALSE);
7000 aopOp (result, ic, FALSE);
7002 size = getSize (operandType (result));
7005 emitcode ("; shift left ", "result %d, left %d", size,
7009 /* I suppose that the left size >= result size */
7014 movLeft2Result (left, size, result, size, 0);
7018 else if (shCount >= (size * 8))
7020 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7026 genlshOne (result, left, shCount);
7030 genlshTwo (result, left, shCount);
7034 genlshFour (result, left, shCount);
7037 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7038 "*** ack! mystery literal shift!\n");
7042 freeAsmop (left, NULL, ic, TRUE);
7043 freeAsmop (result, NULL, ic, TRUE);
7046 /*-----------------------------------------------------------------*/
7047 /* genLeftShift - generates code for left shifting */
7048 /*-----------------------------------------------------------------*/
7050 genLeftShift (iCode * ic)
7052 operand *left, *right, *result;
7055 symbol *tlbl, *tlbl1;
7057 D(emitcode ("; genLeftShift",""));
7059 right = IC_RIGHT (ic);
7060 left = IC_LEFT (ic);
7061 result = IC_RESULT (ic);
7063 aopOp (right, ic, FALSE);
7065 /* if the shift count is known then do it
7066 as efficiently as possible */
7067 if (AOP_TYPE (right) == AOP_LIT)
7069 genLeftShiftLiteral (left, right, result, ic);
7073 /* shift count is unknown then we have to form
7074 a loop get the loop count in B : Note: we take
7075 only the lower order byte since shifting
7076 more that 32 bits make no sense anyway, ( the
7077 largest size of an object can be only 32 bits ) */
7079 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7080 emitcode ("inc", "b");
7081 freeAsmop (right, NULL, ic, TRUE);
7082 aopOp (left, ic, FALSE);
7083 aopOp (result, ic, FALSE);
7085 /* now move the left to the result if they are not the
7087 if (!sameRegs (AOP (left), AOP (result)) &&
7088 AOP_SIZE (result) > 1)
7091 size = AOP_SIZE (result);
7095 l = aopGet (AOP (left), offset, FALSE, TRUE);
7096 if (*l == '@' && (IS_AOP_PREG (result)))
7099 emitcode ("mov", "a,%s", l);
7100 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7103 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7108 tlbl = newiTempLabel (NULL);
7109 size = AOP_SIZE (result);
7111 tlbl1 = newiTempLabel (NULL);
7113 /* if it is only one byte then */
7116 symbol *tlbl1 = newiTempLabel (NULL);
7118 l = aopGet (AOP (left), 0, FALSE, FALSE);
7120 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7121 emitcode ("", "%05d$:", tlbl->key + 100);
7122 emitcode ("add", "a,acc");
7123 emitcode ("", "%05d$:", tlbl1->key + 100);
7124 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7125 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7129 reAdjustPreg (AOP (result));
7131 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7132 emitcode ("", "%05d$:", tlbl->key + 100);
7133 l = aopGet (AOP (result), offset, FALSE, FALSE);
7135 emitcode ("add", "a,acc");
7136 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7139 l = aopGet (AOP (result), offset, FALSE, FALSE);
7141 emitcode ("rlc", "a");
7142 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7144 reAdjustPreg (AOP (result));
7146 emitcode ("", "%05d$:", tlbl1->key + 100);
7147 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7149 freeAsmop (left, NULL, ic, TRUE);
7150 freeAsmop (result, NULL, ic, TRUE);
7153 /*-----------------------------------------------------------------*/
7154 /* genrshOne - right shift a one byte quantity by known count */
7155 /*-----------------------------------------------------------------*/
7157 genrshOne (operand * result, operand * left,
7158 int shCount, int sign)
7160 D(emitcode ("; genrshOne",""));
7162 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7165 /*-----------------------------------------------------------------*/
7166 /* genrshTwo - right shift two bytes by known amount != 0 */
7167 /*-----------------------------------------------------------------*/
7169 genrshTwo (operand * result, operand * left,
7170 int shCount, int sign)
7172 D(emitcode ("; genrshTwo",""));
7174 /* if shCount >= 8 */
7179 shiftR1Left2Result (left, MSB16, result, LSB,
7182 movLeft2Result (left, MSB16, result, LSB, sign);
7183 addSign (result, MSB16, sign);
7186 /* 1 <= shCount <= 7 */
7188 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7191 /*-----------------------------------------------------------------*/
7192 /* shiftRLong - shift right one long from left to result */
7193 /* offl = LSB or MSB16 */
7194 /*-----------------------------------------------------------------*/
7196 shiftRLong (operand * left, int offl,
7197 operand * result, int sign)
7199 int isSameRegs=sameRegs(AOP(left),AOP(result));
7201 if (isSameRegs && offl>1) {
7202 // we are in big trouble, but this shouldn't happen
7203 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7206 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7211 emitcode ("rlc", "a");
7212 emitcode ("subb", "a,acc");
7214 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7216 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7217 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7220 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7225 emitcode ("clr", "c");
7227 emitcode ("mov", "c,acc.7");
7230 emitcode ("rrc", "a");
7232 if (isSameRegs && offl==MSB16) {
7233 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7235 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7236 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7239 emitcode ("rrc", "a");
7240 if (isSameRegs && offl==1) {
7241 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7243 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7244 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7246 emitcode ("rrc", "a");
7247 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7251 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7252 emitcode ("rrc", "a");
7253 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7257 /*-----------------------------------------------------------------*/
7258 /* genrshFour - shift four byte by a known amount != 0 */
7259 /*-----------------------------------------------------------------*/
7261 genrshFour (operand * result, operand * left,
7262 int shCount, int sign)
7264 D(emitcode ("; genrshFour",""));
7266 /* if shifting more that 3 bytes */
7271 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7273 movLeft2Result (left, MSB32, result, LSB, sign);
7274 addSign (result, MSB16, sign);
7276 else if (shCount >= 16)
7280 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7283 movLeft2Result (left, MSB24, result, LSB, 0);
7284 movLeft2Result (left, MSB32, result, MSB16, sign);
7286 addSign (result, MSB24, sign);
7288 else if (shCount >= 8)
7292 shiftRLong (left, MSB16, result, sign);
7293 else if (shCount == 0)
7295 movLeft2Result (left, MSB16, result, LSB, 0);
7296 movLeft2Result (left, MSB24, result, MSB16, 0);
7297 movLeft2Result (left, MSB32, result, MSB24, sign);
7298 addSign (result, MSB32, sign);
7302 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7303 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7304 /* the last shift is signed */
7305 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7306 addSign (result, MSB32, sign);
7310 { /* 1 <= shCount <= 7 */
7313 shiftRLong (left, LSB, result, sign);
7315 shiftRLong (result, LSB, result, sign);
7319 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7320 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7321 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7326 /*-----------------------------------------------------------------*/
7327 /* genRightShiftLiteral - right shifting by known count */
7328 /*-----------------------------------------------------------------*/
7330 genRightShiftLiteral (operand * left,
7336 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7339 D(emitcode ("; genRightShiftLiteral",""));
7341 freeAsmop (right, NULL, ic, TRUE);
7343 aopOp (left, ic, FALSE);
7344 aopOp (result, ic, FALSE);
7347 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7351 size = getDataSize (left);
7352 /* test the LEFT size !!! */
7354 /* I suppose that the left size >= result size */
7357 size = getDataSize (result);
7359 movLeft2Result (left, size, result, size, 0);
7362 else if (shCount >= (size * 8))
7365 /* get sign in acc.7 */
7366 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7368 addSign (result, LSB, sign);
7375 genrshOne (result, left, shCount, sign);
7379 genrshTwo (result, left, shCount, sign);
7383 genrshFour (result, left, shCount, sign);
7389 freeAsmop (left, NULL, ic, TRUE);
7390 freeAsmop (result, NULL, ic, TRUE);
7393 /*-----------------------------------------------------------------*/
7394 /* genSignedRightShift - right shift of signed number */
7395 /*-----------------------------------------------------------------*/
7397 genSignedRightShift (iCode * ic)
7399 operand *right, *left, *result;
7402 symbol *tlbl, *tlbl1;
7404 D(emitcode ("; genSignedRightShift",""));
7406 /* we do it the hard way put the shift count in b
7407 and loop thru preserving the sign */
7409 right = IC_RIGHT (ic);
7410 left = IC_LEFT (ic);
7411 result = IC_RESULT (ic);
7413 aopOp (right, ic, FALSE);
7416 if (AOP_TYPE (right) == AOP_LIT)
7418 genRightShiftLiteral (left, right, result, ic, 1);
7421 /* shift count is unknown then we have to form
7422 a loop get the loop count in B : Note: we take
7423 only the lower order byte since shifting
7424 more that 32 bits make no sense anyway, ( the
7425 largest size of an object can be only 32 bits ) */
7427 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7428 emitcode ("inc", "b");
7429 freeAsmop (right, NULL, ic, TRUE);
7430 aopOp (left, ic, FALSE);
7431 aopOp (result, ic, FALSE);
7433 /* now move the left to the result if they are not the
7435 if (!sameRegs (AOP (left), AOP (result)) &&
7436 AOP_SIZE (result) > 1)
7439 size = AOP_SIZE (result);
7443 l = aopGet (AOP (left), offset, FALSE, TRUE);
7444 if (*l == '@' && IS_AOP_PREG (result))
7447 emitcode ("mov", "a,%s", l);
7448 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7451 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7456 /* mov the highest order bit to OVR */
7457 tlbl = newiTempLabel (NULL);
7458 tlbl1 = newiTempLabel (NULL);
7460 size = AOP_SIZE (result);
7462 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7463 emitcode ("rlc", "a");
7464 emitcode ("mov", "ov,c");
7465 /* if it is only one byte then */
7468 l = aopGet (AOP (left), 0, FALSE, FALSE);
7470 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7471 emitcode ("", "%05d$:", tlbl->key + 100);
7472 emitcode ("mov", "c,ov");
7473 emitcode ("rrc", "a");
7474 emitcode ("", "%05d$:", tlbl1->key + 100);
7475 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7476 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7480 reAdjustPreg (AOP (result));
7481 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7482 emitcode ("", "%05d$:", tlbl->key + 100);
7483 emitcode ("mov", "c,ov");
7486 l = aopGet (AOP (result), offset, FALSE, FALSE);
7488 emitcode ("rrc", "a");
7489 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7491 reAdjustPreg (AOP (result));
7492 emitcode ("", "%05d$:", tlbl1->key + 100);
7493 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7496 freeAsmop (left, NULL, ic, TRUE);
7497 freeAsmop (result, NULL, ic, TRUE);
7500 /*-----------------------------------------------------------------*/
7501 /* genRightShift - generate code for right shifting */
7502 /*-----------------------------------------------------------------*/
7504 genRightShift (iCode * ic)
7506 operand *right, *left, *result;
7510 symbol *tlbl, *tlbl1;
7512 D(emitcode ("; genRightShift",""));
7514 /* if signed then we do it the hard way preserve the
7515 sign bit moving it inwards */
7516 letype = getSpec (operandType (IC_LEFT (ic)));
7518 if (!SPEC_USIGN (letype))
7520 genSignedRightShift (ic);
7524 /* signed & unsigned types are treated the same : i.e. the
7525 signed is NOT propagated inwards : quoting from the
7526 ANSI - standard : "for E1 >> E2, is equivalent to division
7527 by 2**E2 if unsigned or if it has a non-negative value,
7528 otherwise the result is implementation defined ", MY definition
7529 is that the sign does not get propagated */
7531 right = IC_RIGHT (ic);
7532 left = IC_LEFT (ic);
7533 result = IC_RESULT (ic);
7535 aopOp (right, ic, FALSE);
7537 /* if the shift count is known then do it
7538 as efficiently as possible */
7539 if (AOP_TYPE (right) == AOP_LIT)
7541 genRightShiftLiteral (left, right, result, ic, 0);
7545 /* shift count is unknown then we have to form
7546 a loop get the loop count in B : Note: we take
7547 only the lower order byte since shifting
7548 more that 32 bits make no sense anyway, ( the
7549 largest size of an object can be only 32 bits ) */
7551 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7552 emitcode ("inc", "b");
7553 freeAsmop (right, NULL, ic, TRUE);
7554 aopOp (left, ic, FALSE);
7555 aopOp (result, ic, FALSE);
7557 /* now move the left to the result if they are not the
7559 if (!sameRegs (AOP (left), AOP (result)) &&
7560 AOP_SIZE (result) > 1)
7563 size = AOP_SIZE (result);
7567 l = aopGet (AOP (left), offset, FALSE, TRUE);
7568 if (*l == '@' && IS_AOP_PREG (result))
7571 emitcode ("mov", "a,%s", l);
7572 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7575 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7580 tlbl = newiTempLabel (NULL);
7581 tlbl1 = newiTempLabel (NULL);
7582 size = AOP_SIZE (result);
7585 /* if it is only one byte then */
7588 l = aopGet (AOP (left), 0, FALSE, FALSE);
7590 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7591 emitcode ("", "%05d$:", tlbl->key + 100);
7593 emitcode ("rrc", "a");
7594 emitcode ("", "%05d$:", tlbl1->key + 100);
7595 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7596 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7600 reAdjustPreg (AOP (result));
7601 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7602 emitcode ("", "%05d$:", tlbl->key + 100);
7606 l = aopGet (AOP (result), offset, FALSE, FALSE);
7608 emitcode ("rrc", "a");
7609 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7611 reAdjustPreg (AOP (result));
7613 emitcode ("", "%05d$:", tlbl1->key + 100);
7614 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7617 freeAsmop (left, NULL, ic, TRUE);
7618 freeAsmop (result, NULL, ic, TRUE);
7621 /*-----------------------------------------------------------------*/
7622 /* emitPtrByteGet - emits code to get a byte into A through a */
7623 /* pointer register (R0, R1, or DPTR). The */
7624 /* original value of A can be preserved in B. */
7625 /*-----------------------------------------------------------------*/
7627 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7634 emitcode ("mov", "b,a");
7635 emitcode ("mov", "a,@%s", rname);
7640 emitcode ("mov", "b,a");
7641 emitcode ("movx", "a,@%s", rname);
7646 emitcode ("mov", "b,a");
7647 emitcode ("movx", "a,@dptr");
7652 emitcode ("mov", "b,a");
7653 emitcode ("clr", "a");
7654 emitcode ("movc", "a,@a+dptr");
7660 emitcode ("push", "b");
7661 emitcode ("push", "acc");
7663 emitcode ("lcall", "__gptrget");
7665 emitcode ("pop", "b");
7670 /*-----------------------------------------------------------------*/
7671 /* emitPtrByteSet - emits code to set a byte from src through a */
7672 /* pointer register (R0, R1, or DPTR). */
7673 /*-----------------------------------------------------------------*/
7675 emitPtrByteSet (char *rname, int p_type, char *src)
7684 emitcode ("mov", "@%s,a", rname);
7687 emitcode ("mov", "@%s,%s", rname, src);
7692 emitcode ("movx", "@%s,a", rname);
7697 emitcode ("movx", "@dptr,a");
7702 emitcode ("lcall", "__gptrput");
7707 /*-----------------------------------------------------------------*/
7708 /* genUnpackBits - generates code for unpacking bits */
7709 /*-----------------------------------------------------------------*/
7711 genUnpackBits (operand * result, char *rname, int ptype)
7713 int offset = 0; /* result byte offset */
7714 int rsize; /* result size */
7715 int rlen = 0; /* remaining bitfield length */
7716 sym_link *etype; /* bitfield type information */
7717 int blen; /* bitfield length */
7718 int bstr; /* bitfield starting bit within byte */
7720 D(emitcode ("; genUnpackBits",""));
7722 etype = getSpec (operandType (result));
7723 rsize = getSize (operandType (result));
7724 blen = SPEC_BLEN (etype);
7725 bstr = SPEC_BSTR (etype);
7727 /* If the bitfield length is less than a byte */
7730 emitPtrByteGet (rname, ptype, FALSE);
7732 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7733 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7737 /* Bit field did not fit in a byte. Copy all
7738 but the partial byte at the end. */
7739 for (rlen=blen;rlen>=8;rlen-=8)
7741 emitPtrByteGet (rname, ptype, FALSE);
7742 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7744 emitcode ("inc", "%s", rname);
7747 /* Handle the partial byte at the end */
7750 emitPtrByteGet (rname, ptype, FALSE);
7751 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7752 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7760 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7765 /*-----------------------------------------------------------------*/
7766 /* genDataPointerGet - generates code when ptr offset is known */
7767 /*-----------------------------------------------------------------*/
7769 genDataPointerGet (operand * left,
7775 int size, offset = 0;
7777 D(emitcode ("; genDataPointerGet",""));
7779 aopOp (result, ic, TRUE);
7781 /* get the string representation of the name */
7782 l = aopGet (AOP (left), 0, FALSE, TRUE);
7783 size = AOP_SIZE (result);
7787 sprintf (buffer, "(%s + %d)", l + 1, offset);
7789 sprintf (buffer, "%s", l + 1);
7790 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7793 freeAsmop (left, NULL, ic, TRUE);
7794 freeAsmop (result, NULL, ic, TRUE);
7797 /*-----------------------------------------------------------------*/
7798 /* genNearPointerGet - emitcode for near pointer fetch */
7799 /*-----------------------------------------------------------------*/
7801 genNearPointerGet (operand * left,
7809 sym_link *rtype, *retype;
7810 sym_link *ltype = operandType (left);
7813 D(emitcode ("; genNearPointerGet",""));
7815 rtype = operandType (result);
7816 retype = getSpec (rtype);
7818 aopOp (left, ic, FALSE);
7820 /* if left is rematerialisable and
7821 result is not bitfield variable type and
7822 the left is pointer to data space i.e
7823 lower 128 bytes of space */
7824 if (AOP_TYPE (left) == AOP_IMMD &&
7825 !IS_BITFIELD (retype) &&
7826 DCL_TYPE (ltype) == POINTER)
7828 genDataPointerGet (left, result, ic);
7832 /* if the value is already in a pointer register
7833 then don't need anything more */
7834 if (!AOP_INPREG (AOP (left)))
7836 if (IS_AOP_PREG (left))
7838 // Aha, it is a pointer, just in disguise.
7839 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7842 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7843 __FILE__, __LINE__);
7848 emitcode ("mov", "a%s,%s", rname + 1, rname);
7849 rname++; // skip the '@'.
7854 /* otherwise get a free pointer register */
7856 preg = getFreePtr (ic, &aop, FALSE);
7857 emitcode ("mov", "%s,%s",
7859 aopGet (AOP (left), 0, FALSE, TRUE));
7864 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7866 //aopOp (result, ic, FALSE);
7867 aopOp (result, ic, result?TRUE:FALSE);
7869 /* if bitfield then unpack the bits */
7870 if (IS_BITFIELD (retype))
7871 genUnpackBits (result, rname, POINTER);
7874 /* we have can just get the values */
7875 int size = AOP_SIZE (result);
7880 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7883 emitcode ("mov", "a,@%s", rname);
7884 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7888 sprintf (buffer, "@%s", rname);
7889 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7893 emitcode ("inc", "%s", rname);
7897 /* now some housekeeping stuff */
7898 if (aop) /* we had to allocate for this iCode */
7900 if (pi) { /* post increment present */
7901 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7903 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7907 /* we did not allocate which means left
7908 already in a pointer register, then
7909 if size > 0 && this could be used again
7910 we have to point it back to where it
7912 if ((AOP_SIZE (result) > 1 &&
7913 !OP_SYMBOL (left)->remat &&
7914 (OP_SYMBOL (left)->liveTo > ic->seq ||
7918 int size = AOP_SIZE (result) - 1;
7920 emitcode ("dec", "%s", rname);
7925 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7926 freeAsmop (left, NULL, ic, TRUE);
7927 if (pi) pi->generated = 1;
7930 /*-----------------------------------------------------------------*/
7931 /* genPagedPointerGet - emitcode for paged pointer fetch */
7932 /*-----------------------------------------------------------------*/
7934 genPagedPointerGet (operand * left,
7942 sym_link *rtype, *retype;
7944 D(emitcode ("; genPagedPointerGet",""));
7946 rtype = operandType (result);
7947 retype = getSpec (rtype);
7949 aopOp (left, ic, FALSE);
7951 /* if the value is already in a pointer register
7952 then don't need anything more */
7953 if (!AOP_INPREG (AOP (left)))
7955 /* otherwise get a free pointer register */
7957 preg = getFreePtr (ic, &aop, FALSE);
7958 emitcode ("mov", "%s,%s",
7960 aopGet (AOP (left), 0, FALSE, TRUE));
7964 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7966 aopOp (result, ic, FALSE);
7968 /* if bitfield then unpack the bits */
7969 if (IS_BITFIELD (retype))
7970 genUnpackBits (result, rname, PPOINTER);
7973 /* we have can just get the values */
7974 int size = AOP_SIZE (result);
7980 emitcode ("movx", "a,@%s", rname);
7981 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7986 emitcode ("inc", "%s", rname);
7990 /* now some housekeeping stuff */
7991 if (aop) /* we had to allocate for this iCode */
7993 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7994 freeAsmop (NULL, aop, ic, TRUE);
7998 /* we did not allocate which means left
7999 already in a pointer register, then
8000 if size > 0 && this could be used again
8001 we have to point it back to where it
8003 if ((AOP_SIZE (result) > 1 &&
8004 !OP_SYMBOL (left)->remat &&
8005 (OP_SYMBOL (left)->liveTo > ic->seq ||
8009 int size = AOP_SIZE (result) - 1;
8011 emitcode ("dec", "%s", rname);
8016 freeAsmop (left, NULL, ic, TRUE);
8017 freeAsmop (result, NULL, ic, TRUE);
8018 if (pi) pi->generated = 1;
8022 /*--------------------------------------------------------------------*/
8023 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8024 /*--------------------------------------------------------------------*/
8026 loadDptrFromOperand (operand *op, bool loadBToo)
8028 if (AOP_TYPE (op) != AOP_STR)
8030 /* if this is remateriazable */
8031 if (AOP_TYPE (op) == AOP_IMMD)
8033 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8036 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8037 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8040 wassertl(FALSE, "need pointerCode");
8041 emitcode ("", "; mov b,???");
8042 /* genPointerGet and genPointerSet originally did different
8043 ** things for this case. Both seem wrong.
8044 ** from genPointerGet:
8045 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8046 ** from genPointerSet:
8047 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8052 else if (AOP_TYPE (op) == AOP_DPTR)
8056 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8057 emitcode ("push", "acc");
8058 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8059 emitcode ("push", "acc");
8060 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8061 emitcode ("pop", "dph");
8062 emitcode ("pop", "dpl");
8066 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8067 emitcode ("push", "acc");
8068 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8069 emitcode ("pop", "dpl");
8073 { /* we need to get it byte by byte */
8074 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8075 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8077 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8082 /*-----------------------------------------------------------------*/
8083 /* genFarPointerGet - gget value from far space */
8084 /*-----------------------------------------------------------------*/
8086 genFarPointerGet (operand * left,
8087 operand * result, iCode * ic, iCode * pi)
8090 sym_link *retype = getSpec (operandType (result));
8092 D(emitcode ("; genFarPointerGet",""));
8094 aopOp (left, ic, FALSE);
8095 loadDptrFromOperand (left, FALSE);
8097 /* so dptr now contains the address */
8098 aopOp (result, ic, FALSE);
8100 /* if bit then unpack */
8101 if (IS_BITFIELD (retype))
8102 genUnpackBits (result, "dptr", FPOINTER);
8105 size = AOP_SIZE (result);
8110 emitcode ("movx", "a,@dptr");
8111 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8113 emitcode ("inc", "dptr");
8117 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8118 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8119 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8122 freeAsmop (left, NULL, ic, TRUE);
8123 freeAsmop (result, NULL, ic, TRUE);
8126 /*-----------------------------------------------------------------*/
8127 /* genCodePointerGet - gget value from code space */
8128 /*-----------------------------------------------------------------*/
8130 genCodePointerGet (operand * left,
8131 operand * result, iCode * ic, iCode *pi)
8134 sym_link *retype = getSpec (operandType (result));
8136 D(emitcode ("; genCodePointerGet",""));
8138 aopOp (left, ic, FALSE);
8139 loadDptrFromOperand (left, FALSE);
8141 /* so dptr now contains the address */
8142 aopOp (result, ic, FALSE);
8144 /* if bit then unpack */
8145 if (IS_BITFIELD (retype))
8146 genUnpackBits (result, "dptr", CPOINTER);
8149 size = AOP_SIZE (result);
8156 emitcode ("clr", "a");
8157 emitcode ("movc", "a,@a+dptr");
8158 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8159 emitcode ("inc", "dptr");
8163 emitcode ("mov", "a,#0x%02x", offset);
8164 emitcode ("movc", "a,@a+dptr");
8165 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8170 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8171 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8172 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8175 freeAsmop (left, NULL, ic, TRUE);
8176 freeAsmop (result, NULL, ic, TRUE);
8179 /*-----------------------------------------------------------------*/
8180 /* genGenPointerGet - gget value from generic pointer space */
8181 /*-----------------------------------------------------------------*/
8183 genGenPointerGet (operand * left,
8184 operand * result, iCode * ic, iCode *pi)
8187 sym_link *retype = getSpec (operandType (result));
8189 D(emitcode ("; genGenPointerGet",""));
8191 aopOp (left, ic, FALSE);
8192 loadDptrFromOperand (left, TRUE);
8194 /* so dptr know contains the address */
8195 aopOp (result, ic, FALSE);
8197 /* if bit then unpack */
8198 if (IS_BITFIELD (retype))
8199 genUnpackBits (result, "dptr", GPOINTER);
8202 size = AOP_SIZE (result);
8207 emitcode ("lcall", "__gptrget");
8208 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8210 emitcode ("inc", "dptr");
8214 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8215 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8216 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8219 freeAsmop (left, NULL, ic, TRUE);
8220 freeAsmop (result, NULL, ic, TRUE);
8223 /*-----------------------------------------------------------------*/
8224 /* genPointerGet - generate code for pointer get */
8225 /*-----------------------------------------------------------------*/
8227 genPointerGet (iCode * ic, iCode *pi)
8229 operand *left, *result;
8230 sym_link *type, *etype;
8233 D(emitcode ("; genPointerGet",""));
8235 left = IC_LEFT (ic);
8236 result = IC_RESULT (ic);
8238 /* depending on the type of pointer we need to
8239 move it to the correct pointer register */
8240 type = operandType (left);
8241 etype = getSpec (type);
8242 /* if left is of type of pointer then it is simple */
8243 if (IS_PTR (type) && !IS_FUNC (type->next))
8244 p_type = DCL_TYPE (type);
8247 /* we have to go by the storage class */
8248 p_type = PTR_TYPE (SPEC_OCLS (etype));
8251 /* special case when cast remat */
8252 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8253 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8254 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8255 type = operandType (left);
8256 p_type = DCL_TYPE (type);
8258 /* now that we have the pointer type we assign
8259 the pointer values */
8265 genNearPointerGet (left, result, ic, pi);
8269 genPagedPointerGet (left, result, ic, pi);
8273 genFarPointerGet (left, result, ic, pi);
8277 genCodePointerGet (left, result, ic, pi);
8281 genGenPointerGet (left, result, ic, pi);
8289 /*-----------------------------------------------------------------*/
8290 /* genPackBits - generates code for packed bit storage */
8291 /*-----------------------------------------------------------------*/
8293 genPackBits (sym_link * etype,
8295 char *rname, int p_type)
8297 int offset = 0; /* source byte offset */
8298 int rlen = 0; /* remaining bitfield length */
8299 int blen; /* bitfield length */
8300 int bstr; /* bitfield starting bit within byte */
8301 int litval; /* source literal value (if AOP_LIT) */
8302 unsigned char mask; /* bitmask within current byte */
8304 D(emitcode ("; genPackBits",""));
8306 blen = SPEC_BLEN (etype);
8307 bstr = SPEC_BSTR (etype);
8309 /* If the bitfield length is less than a byte */
8312 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8313 (unsigned char) (0xFF >> (8 - bstr)));
8315 if (AOP_TYPE (right) == AOP_LIT)
8317 /* Case with a bitfield length <8 and literal source
8319 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8321 litval &= (~mask) & 0xff;
8322 emitPtrByteGet (rname, p_type, FALSE);
8323 if ((mask|litval)!=0xff)
8324 emitcode ("anl","a,#0x%02x", mask);
8326 emitcode ("orl","a,#0x%02x", litval);
8330 if ((blen==1) && (p_type!=GPOINTER))
8332 /* Case with a bitfield length == 1 and no generic pointer
8334 if (AOP_TYPE (right) == AOP_CRY)
8335 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8338 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8339 emitcode ("rrc","a");
8341 emitPtrByteGet (rname, p_type, FALSE);
8342 emitcode ("mov","acc.%d,c",bstr);
8346 /* Case with a bitfield length < 8 and arbitrary source
8348 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8349 /* shift and mask source value */
8351 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8353 /* transfer A to B and get next byte */
8354 emitPtrByteGet (rname, p_type, TRUE);
8356 emitcode ("anl", "a,#0x%02x", mask);
8357 emitcode ("orl", "a,b");
8358 if (p_type == GPOINTER)
8359 emitcode ("pop", "b");
8363 emitPtrByteSet (rname, p_type, "a");
8367 /* Bit length is greater than 7 bits. In this case, copy */
8368 /* all except the partial byte at the end */
8369 for (rlen=blen;rlen>=8;rlen-=8)
8371 emitPtrByteSet (rname, p_type,
8372 aopGet (AOP (right), offset++, FALSE, TRUE) );
8374 emitcode ("inc", "%s", rname);
8377 /* If there was a partial byte at the end */
8380 mask = (((unsigned char) -1 << rlen) & 0xff);
8382 if (AOP_TYPE (right) == AOP_LIT)
8384 /* Case with partial byte and literal source
8386 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8387 litval >>= (blen-rlen);
8388 litval &= (~mask) & 0xff;
8389 emitPtrByteGet (rname, p_type, FALSE);
8390 if ((mask|litval)!=0xff)
8391 emitcode ("anl","a,#0x%02x", mask);
8393 emitcode ("orl","a,#0x%02x", litval);
8397 /* Case with partial byte and arbitrary source
8399 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8400 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8402 /* transfer A to B and get next byte */
8403 emitPtrByteGet (rname, p_type, TRUE);
8405 emitcode ("anl", "a,#0x%02x", mask);
8406 emitcode ("orl", "a,b");
8407 if (p_type == GPOINTER)
8408 emitcode ("pop", "b");
8410 emitPtrByteSet (rname, p_type, "a");
8416 /*-----------------------------------------------------------------*/
8417 /* genDataPointerSet - remat pointer to data space */
8418 /*-----------------------------------------------------------------*/
8420 genDataPointerSet (operand * right,
8424 int size, offset = 0;
8425 char *l, buffer[256];
8427 D(emitcode ("; genDataPointerSet",""));
8429 aopOp (right, ic, FALSE);
8431 l = aopGet (AOP (result), 0, FALSE, TRUE);
8432 size = AOP_SIZE (right);
8436 sprintf (buffer, "(%s + %d)", l + 1, offset);
8438 sprintf (buffer, "%s", l + 1);
8439 emitcode ("mov", "%s,%s", buffer,
8440 aopGet (AOP (right), offset++, FALSE, FALSE));
8443 freeAsmop (right, NULL, ic, TRUE);
8444 freeAsmop (result, NULL, ic, TRUE);
8447 /*-----------------------------------------------------------------*/
8448 /* genNearPointerSet - emitcode for near pointer put */
8449 /*-----------------------------------------------------------------*/
8451 genNearPointerSet (operand * right,
8459 sym_link *retype, *letype;
8460 sym_link *ptype = operandType (result);
8462 D(emitcode ("; genNearPointerSet",""));
8464 retype = getSpec (operandType (right));
8465 letype = getSpec (ptype);
8466 aopOp (result, ic, FALSE);
8468 /* if the result is rematerializable &
8469 in data space & not a bit variable */
8470 if (AOP_TYPE (result) == AOP_IMMD &&
8471 DCL_TYPE (ptype) == POINTER &&
8472 !IS_BITVAR (retype) &&
8473 !IS_BITVAR (letype))
8475 genDataPointerSet (right, result, ic);
8479 /* if the value is already in a pointer register
8480 then don't need anything more */
8481 if (!AOP_INPREG (AOP (result)))
8484 //AOP_TYPE (result) == AOP_STK
8488 // Aha, it is a pointer, just in disguise.
8489 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8492 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8493 __FILE__, __LINE__);
8498 emitcode ("mov", "a%s,%s", rname + 1, rname);
8499 rname++; // skip the '@'.
8504 /* otherwise get a free pointer register */
8506 preg = getFreePtr (ic, &aop, FALSE);
8507 emitcode ("mov", "%s,%s",
8509 aopGet (AOP (result), 0, FALSE, TRUE));
8515 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8518 aopOp (right, ic, FALSE);
8520 /* if bitfield then unpack the bits */
8521 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8522 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8525 /* we have can just get the values */
8526 int size = AOP_SIZE (right);
8531 l = aopGet (AOP (right), offset, FALSE, TRUE);
8535 emitcode ("mov", "@%s,a", rname);
8538 emitcode ("mov", "@%s,%s", rname, l);
8540 emitcode ("inc", "%s", rname);
8545 /* now some housekeeping stuff */
8546 if (aop) /* we had to allocate for this iCode */
8549 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8550 freeAsmop (NULL, aop, ic, TRUE);
8554 /* we did not allocate which means left
8555 already in a pointer register, then
8556 if size > 0 && this could be used again
8557 we have to point it back to where it
8559 if ((AOP_SIZE (right) > 1 &&
8560 !OP_SYMBOL (result)->remat &&
8561 (OP_SYMBOL (result)->liveTo > ic->seq ||
8565 int size = AOP_SIZE (right) - 1;
8567 emitcode ("dec", "%s", rname);
8572 if (pi) pi->generated = 1;
8573 freeAsmop (result, NULL, ic, TRUE);
8574 freeAsmop (right, NULL, ic, TRUE);
8577 /*-----------------------------------------------------------------*/
8578 /* genPagedPointerSet - emitcode for Paged pointer put */
8579 /*-----------------------------------------------------------------*/
8581 genPagedPointerSet (operand * right,
8589 sym_link *retype, *letype;
8591 D(emitcode ("; genPagedPointerSet",""));
8593 retype = getSpec (operandType (right));
8594 letype = getSpec (operandType (result));
8596 aopOp (result, ic, FALSE);
8598 /* if the value is already in a pointer register
8599 then don't need anything more */
8600 if (!AOP_INPREG (AOP (result)))
8602 /* otherwise get a free pointer register */
8604 preg = getFreePtr (ic, &aop, FALSE);
8605 emitcode ("mov", "%s,%s",
8607 aopGet (AOP (result), 0, FALSE, TRUE));
8611 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8613 aopOp (right, ic, FALSE);
8615 /* if bitfield then unpack the bits */
8616 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8617 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8620 /* we have can just get the values */
8621 int size = AOP_SIZE (right);
8626 l = aopGet (AOP (right), offset, FALSE, TRUE);
8629 emitcode ("movx", "@%s,a", rname);
8632 emitcode ("inc", "%s", rname);
8638 /* now some housekeeping stuff */
8639 if (aop) /* we had to allocate for this iCode */
8642 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8643 freeAsmop (NULL, aop, ic, TRUE);
8647 /* we did not allocate which means left
8648 already in a pointer register, then
8649 if size > 0 && this could be used again
8650 we have to point it back to where it
8652 if (AOP_SIZE (right) > 1 &&
8653 !OP_SYMBOL (result)->remat &&
8654 (OP_SYMBOL (result)->liveTo > ic->seq ||
8657 int size = AOP_SIZE (right) - 1;
8659 emitcode ("dec", "%s", rname);
8664 if (pi) pi->generated = 1;
8665 freeAsmop (result, NULL, ic, TRUE);
8666 freeAsmop (right, NULL, ic, TRUE);
8671 /*-----------------------------------------------------------------*/
8672 /* genFarPointerSet - set value from far space */
8673 /*-----------------------------------------------------------------*/
8675 genFarPointerSet (operand * right,
8676 operand * result, iCode * ic, iCode * pi)
8679 sym_link *retype = getSpec (operandType (right));
8680 sym_link *letype = getSpec (operandType (result));
8682 D(emitcode ("; genFarPointerSet",""));
8684 aopOp (result, ic, FALSE);
8685 loadDptrFromOperand (result, FALSE);
8687 /* so dptr know contains the address */
8688 aopOp (right, ic, FALSE);
8690 /* if bit then unpack */
8691 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8692 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8695 size = AOP_SIZE (right);
8700 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8702 emitcode ("movx", "@dptr,a");
8704 emitcode ("inc", "dptr");
8707 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8708 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8709 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8712 freeAsmop (result, NULL, ic, TRUE);
8713 freeAsmop (right, NULL, ic, TRUE);
8716 /*-----------------------------------------------------------------*/
8717 /* genGenPointerSet - set value from generic pointer space */
8718 /*-----------------------------------------------------------------*/
8720 genGenPointerSet (operand * right,
8721 operand * result, iCode * ic, iCode * pi)
8724 sym_link *retype = getSpec (operandType (right));
8725 sym_link *letype = getSpec (operandType (result));
8727 D(emitcode ("; genGenPointerSet",""));
8729 aopOp (result, ic, FALSE);
8730 loadDptrFromOperand (result, TRUE);
8732 /* so dptr know contains the address */
8733 aopOp (right, ic, FALSE);
8735 /* if bit then unpack */
8736 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8737 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
8740 size = AOP_SIZE (right);
8745 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8747 emitcode ("lcall", "__gptrput");
8749 emitcode ("inc", "dptr");
8753 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8754 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8755 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8758 freeAsmop (result, NULL, ic, TRUE);
8759 freeAsmop (right, NULL, ic, TRUE);
8762 /*-----------------------------------------------------------------*/
8763 /* genPointerSet - stores the value into a pointer location */
8764 /*-----------------------------------------------------------------*/
8766 genPointerSet (iCode * ic, iCode *pi)
8768 operand *right, *result;
8769 sym_link *type, *etype;
8772 D(emitcode ("; genPointerSet",""));
8774 right = IC_RIGHT (ic);
8775 result = IC_RESULT (ic);
8777 /* depending on the type of pointer we need to
8778 move it to the correct pointer register */
8779 type = operandType (result);
8780 etype = getSpec (type);
8781 /* if left is of type of pointer then it is simple */
8782 if (IS_PTR (type) && !IS_FUNC (type->next))
8784 p_type = DCL_TYPE (type);
8788 /* we have to go by the storage class */
8789 p_type = PTR_TYPE (SPEC_OCLS (etype));
8792 /* special case when cast remat */
8793 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8794 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8795 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8796 type = operandType (result);
8797 p_type = DCL_TYPE (type);
8799 /* now that we have the pointer type we assign
8800 the pointer values */
8806 genNearPointerSet (right, result, ic, pi);
8810 genPagedPointerSet (right, result, ic, pi);
8814 genFarPointerSet (right, result, ic, pi);
8818 genGenPointerSet (right, result, ic, pi);
8822 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8823 "genPointerSet: illegal pointer type");
8828 /*-----------------------------------------------------------------*/
8829 /* genIfx - generate code for Ifx statement */
8830 /*-----------------------------------------------------------------*/
8832 genIfx (iCode * ic, iCode * popIc)
8834 operand *cond = IC_COND (ic);
8837 D(emitcode ("; genIfx",""));
8839 aopOp (cond, ic, FALSE);
8841 /* get the value into acc */
8842 if (AOP_TYPE (cond) != AOP_CRY)
8846 /* the result is now in the accumulator */
8847 freeAsmop (cond, NULL, ic, TRUE);
8849 /* if there was something to be popped then do it */
8853 /* if the condition is a bit variable */
8854 if (isbit && IS_ITEMP (cond) &&
8856 genIfxJump (ic, SPIL_LOC (cond)->rname);
8857 else if (isbit && !IS_ITEMP (cond))
8858 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8860 genIfxJump (ic, "a");
8865 /*-----------------------------------------------------------------*/
8866 /* genAddrOf - generates code for address of */
8867 /*-----------------------------------------------------------------*/
8869 genAddrOf (iCode * ic)
8871 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8874 D(emitcode ("; genAddrOf",""));
8876 aopOp (IC_RESULT (ic), ic, FALSE);
8878 /* if the operand is on the stack then we
8879 need to get the stack offset of this
8883 /* if it has an offset then we need to compute
8887 emitcode ("mov", "a,_bp");
8888 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8889 ((char) (sym->stack - _G.nRegsSaved)) :
8890 ((char) sym->stack)) & 0xff);
8891 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8895 /* we can just move _bp */
8896 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8898 /* fill the result with zero */
8899 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8904 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8910 /* object not on stack then we need the name */
8911 size = AOP_SIZE (IC_RESULT (ic));
8916 char s[SDCC_NAME_MAX];
8918 sprintf (s, "#(%s >> %d)",
8922 sprintf (s, "#%s", sym->rname);
8923 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8927 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8931 /*-----------------------------------------------------------------*/
8932 /* genFarFarAssign - assignment when both are in far space */
8933 /*-----------------------------------------------------------------*/
8935 genFarFarAssign (operand * result, operand * right, iCode * ic)
8937 int size = AOP_SIZE (right);
8941 D(emitcode ("; genFarFarAssign",""));
8943 /* first push the right side on to the stack */
8946 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8948 emitcode ("push", "acc");
8951 freeAsmop (right, NULL, ic, FALSE);
8952 /* now assign DPTR to result */
8953 aopOp (result, ic, FALSE);
8954 size = AOP_SIZE (result);
8957 emitcode ("pop", "acc");
8958 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8960 freeAsmop (result, NULL, ic, FALSE);
8964 /*-----------------------------------------------------------------*/
8965 /* genAssign - generate code for assignment */
8966 /*-----------------------------------------------------------------*/
8968 genAssign (iCode * ic)
8970 operand *result, *right;
8972 unsigned long lit = 0L;
8974 D(emitcode("; genAssign",""));
8976 result = IC_RESULT (ic);
8977 right = IC_RIGHT (ic);
8979 /* if they are the same */
8980 if (operandsEqu (result, right) &&
8981 !isOperandVolatile (result, FALSE) &&
8982 !isOperandVolatile (right, FALSE))
8985 aopOp (right, ic, FALSE);
8987 /* special case both in far space */
8988 if (AOP_TYPE (right) == AOP_DPTR &&
8989 IS_TRUE_SYMOP (result) &&
8990 isOperandInFarSpace (result))
8993 genFarFarAssign (result, right, ic);
8997 aopOp (result, ic, TRUE);
8999 /* if they are the same registers */
9000 if (sameRegs (AOP (right), AOP (result)) &&
9001 !isOperandVolatile (result, FALSE) &&
9002 !isOperandVolatile (right, FALSE))
9005 /* if the result is a bit */
9006 if (AOP_TYPE (result) == AOP_CRY)
9009 /* if the right size is a literal then
9010 we know what the value is */
9011 if (AOP_TYPE (right) == AOP_LIT)
9013 if (((int) operandLitValue (right)))
9014 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9016 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9020 /* the right is also a bit variable */
9021 if (AOP_TYPE (right) == AOP_CRY)
9023 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9024 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9030 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9034 /* bit variables done */
9036 size = AOP_SIZE (result);
9038 if (AOP_TYPE (right) == AOP_LIT)
9039 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9041 (AOP_TYPE (result) != AOP_REG) &&
9042 (AOP_TYPE (right) == AOP_LIT) &&
9043 !IS_FLOAT (operandType (right)) &&
9046 emitcode ("clr", "a");
9049 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9050 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9052 aopPut (AOP (result),
9053 aopGet (AOP (right), size, FALSE, FALSE),
9055 isOperandVolatile (result, FALSE));
9062 aopPut (AOP (result),
9063 aopGet (AOP (right), offset, FALSE, FALSE),
9065 isOperandVolatile (result, FALSE));
9071 freeAsmop (right, NULL, ic, TRUE);
9072 freeAsmop (result, NULL, ic, TRUE);
9075 /*-----------------------------------------------------------------*/
9076 /* genJumpTab - genrates code for jump table */
9077 /*-----------------------------------------------------------------*/
9079 genJumpTab (iCode * ic)
9084 D(emitcode ("; genJumpTab",""));
9086 aopOp (IC_JTCOND (ic), ic, FALSE);
9087 /* get the condition into accumulator */
9088 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9090 /* multiply by three */
9091 emitcode ("add", "a,acc");
9092 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9093 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9095 jtab = newiTempLabel (NULL);
9096 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9097 emitcode ("jmp", "@a+dptr");
9098 emitcode ("", "%05d$:", jtab->key + 100);
9099 /* now generate the jump labels */
9100 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9101 jtab = setNextItem (IC_JTLABELS (ic)))
9102 emitcode ("ljmp", "%05d$", jtab->key + 100);
9106 /*-----------------------------------------------------------------*/
9107 /* genCast - gen code for casting */
9108 /*-----------------------------------------------------------------*/
9110 genCast (iCode * ic)
9112 operand *result = IC_RESULT (ic);
9113 sym_link *ctype = operandType (IC_LEFT (ic));
9114 sym_link *rtype = operandType (IC_RIGHT (ic));
9115 operand *right = IC_RIGHT (ic);
9118 D(emitcode("; genCast",""));
9120 /* if they are equivalent then do nothing */
9121 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9124 aopOp (right, ic, FALSE);
9125 aopOp (result, ic, FALSE);
9127 /* if the result is a bit (and not a bitfield) */
9128 // if (AOP_TYPE (result) == AOP_CRY)
9129 if (IS_BITVAR (OP_SYMBOL (result)->type)
9130 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9132 /* if the right size is a literal then
9133 we know what the value is */
9134 if (AOP_TYPE (right) == AOP_LIT)
9136 if (((int) operandLitValue (right)))
9137 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9139 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9144 /* the right is also a bit variable */
9145 if (AOP_TYPE (right) == AOP_CRY)
9147 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9148 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9154 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9159 /* if they are the same size : or less */
9160 if (AOP_SIZE (result) <= AOP_SIZE (right))
9163 /* if they are in the same place */
9164 if (sameRegs (AOP (right), AOP (result)))
9167 /* if they in different places then copy */
9168 size = AOP_SIZE (result);
9172 aopPut (AOP (result),
9173 aopGet (AOP (right), offset, FALSE, FALSE),
9175 isOperandVolatile (result, FALSE));
9182 /* if the result is of type pointer */
9187 sym_link *type = operandType (right);
9188 sym_link *etype = getSpec (type);
9190 /* pointer to generic pointer */
9191 if (IS_GENPTR (ctype))
9194 p_type = DCL_TYPE (type);
9197 if (SPEC_SCLS(etype)==S_REGISTER) {
9198 // let's assume it is a generic pointer
9201 /* we have to go by the storage class */
9202 p_type = PTR_TYPE (SPEC_OCLS (etype));
9206 /* the first two bytes are known */
9207 size = GPTRSIZE - 1;
9211 aopPut (AOP (result),
9212 aopGet (AOP (right), offset, FALSE, FALSE),
9214 isOperandVolatile (result, FALSE));
9217 /* the last byte depending on type */
9219 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9224 // pointerTypeToGPByte will have bitched.
9228 sprintf(gpValStr, "#0x%d", gpVal);
9229 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9234 /* just copy the pointers */
9235 size = AOP_SIZE (result);
9239 aopPut (AOP (result),
9240 aopGet (AOP (right), offset, FALSE, FALSE),
9242 isOperandVolatile (result, FALSE));
9248 /* so we now know that the size of destination is greater
9249 than the size of the source */
9250 /* we move to result for the size of source */
9251 size = AOP_SIZE (right);
9255 aopPut (AOP (result),
9256 aopGet (AOP (right), offset, FALSE, FALSE),
9258 isOperandVolatile (result, FALSE));
9262 /* now depending on the sign of the source && destination */
9263 size = AOP_SIZE (result) - AOP_SIZE (right);
9264 /* if unsigned or not an integral type */
9265 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9268 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9272 /* we need to extend the sign :{ */
9273 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9276 emitcode ("rlc", "a");
9277 emitcode ("subb", "a,acc");
9279 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9282 /* we are done hurray !!!! */
9285 freeAsmop (right, NULL, ic, TRUE);
9286 freeAsmop (result, NULL, ic, TRUE);
9290 /*-----------------------------------------------------------------*/
9291 /* genDjnz - generate decrement & jump if not zero instrucion */
9292 /*-----------------------------------------------------------------*/
9294 genDjnz (iCode * ic, iCode * ifx)
9300 D(emitcode ("; genDjnz",""));
9302 /* if the if condition has a false label
9303 then we cannot save */
9307 /* if the minus is not of the form
9309 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9310 !IS_OP_LITERAL (IC_RIGHT (ic)))
9313 if (operandLitValue (IC_RIGHT (ic)) != 1)
9316 /* if the size of this greater than one then no
9318 if (getSize (operandType (IC_RESULT (ic))) > 1)
9321 /* otherwise we can save BIG */
9322 lbl = newiTempLabel (NULL);
9323 lbl1 = newiTempLabel (NULL);
9325 aopOp (IC_RESULT (ic), ic, FALSE);
9327 if (AOP_NEEDSACC(IC_RESULT(ic)))
9329 /* If the result is accessed indirectly via
9330 * the accumulator, we must explicitly write
9331 * it back after the decrement.
9333 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9335 if (strcmp(rByte, "a"))
9337 /* Something is hopelessly wrong */
9338 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9339 __FILE__, __LINE__);
9340 /* We can just give up; the generated code will be inefficient,
9343 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9346 emitcode ("dec", "%s", rByte);
9347 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9348 emitcode ("jnz", "%05d$", lbl->key + 100);
9350 else if (IS_AOP_PREG (IC_RESULT (ic)))
9352 emitcode ("dec", "%s",
9353 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9354 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9355 emitcode ("jnz", "%05d$", lbl->key + 100);
9359 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9362 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9363 emitcode ("", "%05d$:", lbl->key + 100);
9364 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9365 emitcode ("", "%05d$:", lbl1->key + 100);
9367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9372 /*-----------------------------------------------------------------*/
9373 /* genReceive - generate code for a receive iCode */
9374 /*-----------------------------------------------------------------*/
9376 genReceive (iCode * ic)
9378 int size = getSize (operandType (IC_RESULT (ic)));
9380 D(emitcode ("; genReceive",""));
9382 if (ic->argreg == 1) { /* first parameter */
9383 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9384 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9385 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9391 for (offset = 0; offset<size; offset++)
9392 if (!strcmp (fReturn[offset], "a"))
9397 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9399 for (offset = size-1; offset>0; offset--)
9400 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9401 emitcode("mov","a,%s", fReturn[0]);
9403 aopOp (IC_RESULT (ic), ic, FALSE);
9405 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9406 isOperandVolatile (IC_RESULT (ic), FALSE));
9407 for (offset = 1; offset<size; offset++)
9408 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9409 isOperandVolatile (IC_RESULT (ic), FALSE));
9415 if (getTempRegs(tempRegs, size, ic))
9417 for (offset = 0; offset<size; offset++)
9418 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9419 aopOp (IC_RESULT (ic), ic, FALSE);
9420 for (offset = 0; offset<size; offset++)
9421 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9422 isOperandVolatile (IC_RESULT (ic), FALSE));
9427 offset = fReturnSizeMCS51 - size;
9429 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9430 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9433 aopOp (IC_RESULT (ic), ic, FALSE);
9434 size = AOP_SIZE (IC_RESULT (ic));
9437 emitcode ("pop", "acc");
9438 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9443 aopOp (IC_RESULT (ic), ic, FALSE);
9445 assignResultValue (IC_RESULT (ic));
9447 } else { /* second receive onwards */
9449 aopOp (IC_RESULT (ic), ic, FALSE);
9450 rb1off = ic->argreg;
9452 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9457 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9460 /*-----------------------------------------------------------------*/
9461 /* genDummyRead - generate code for dummy read of volatiles */
9462 /*-----------------------------------------------------------------*/
9464 genDummyRead (iCode * ic)
9469 D(emitcode("; genDummyRead",""));
9472 if (op && IS_SYMOP (op))
9474 aopOp (op, ic, FALSE);
9476 /* if the result is a bit */
9477 if (AOP_TYPE (op) == AOP_CRY)
9478 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9481 /* bit variables done */
9483 size = AOP_SIZE (op);
9487 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9492 freeAsmop (op, NULL, ic, TRUE);
9496 if (op && IS_SYMOP (op))
9498 aopOp (op, ic, FALSE);
9500 /* if the result is a bit */
9501 if (AOP_TYPE (op) == AOP_CRY)
9502 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9505 /* bit variables done */
9507 size = AOP_SIZE (op);
9511 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9516 freeAsmop (op, NULL, ic, TRUE);
9520 /*-----------------------------------------------------------------*/
9521 /* genCritical - generate code for start of a critical sequence */
9522 /*-----------------------------------------------------------------*/
9524 genCritical (iCode *ic)
9526 symbol *tlbl = newiTempLabel (NULL);
9528 D(emitcode("; genCritical",""));
9531 aopOp (IC_RESULT (ic), ic, TRUE);
9533 emitcode ("setb", "c");
9534 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9535 emitcode ("clr", "c");
9536 emitcode ("", "%05d$:", (tlbl->key + 100));
9539 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9541 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9544 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9547 /*-----------------------------------------------------------------*/
9548 /* genEndCritical - generate code for end of a critical sequence */
9549 /*-----------------------------------------------------------------*/
9551 genEndCritical (iCode *ic)
9553 D(emitcode("; genEndCritical",""));
9557 aopOp (IC_RIGHT (ic), ic, FALSE);
9558 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9560 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9561 emitcode ("mov", "ea,c");
9565 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9566 emitcode ("rrc", "a");
9567 emitcode ("mov", "ea,c");
9569 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9573 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9574 emitcode ("mov", "ea,c");
9579 /*-----------------------------------------------------------------*/
9580 /* gen51Code - generate code for 8051 based controllers */
9581 /*-----------------------------------------------------------------*/
9583 gen51Code (iCode * lic)
9588 _G.currentFunc = NULL;
9589 lineHead = lineCurr = NULL;
9591 /* print the allocation information */
9592 if (allocInfo && currFunc)
9593 printAllocInfo (currFunc, codeOutFile);
9594 /* if debug information required */
9595 if (options.debug && currFunc)
9597 debugFile->writeFunction(currFunc);
9599 if (IS_STATIC (currFunc->etype))
9600 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9602 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9605 /* stack pointer name */
9606 if (options.useXstack)
9612 for (ic = lic; ic; ic = ic->next)
9614 _G.current_iCode = ic;
9616 if (ic->lineno && cln != ic->lineno)
9621 emitcode ("", "C$%s$%d$%d$%d ==.",
9622 FileBaseName (ic->filename), ic->lineno,
9623 ic->level, ic->block);
9626 if (!options.noCcodeInAsm) {
9627 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9628 printCLine(ic->filename, ic->lineno));
9632 if (options.iCodeInAsm) {
9636 for (i=0; i<8; i++) {
9637 sprintf (®sInUse[i],
9638 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9641 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9643 /* if the result is marked as
9644 spilt and rematerializable or code for
9645 this has already been generated then
9647 if (resultRemat (ic) || ic->generated)
9650 /* depending on the operation */
9670 /* IPOP happens only when trying to restore a
9671 spilt live range, if there is an ifx statement
9672 following this pop then the if statement might
9673 be using some of the registers being popped which
9674 would destory the contents of the register so
9675 we need to check for this condition and handle it */
9677 ic->next->op == IFX &&
9678 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9679 genIfx (ic->next, ic);
9697 genEndFunction (ic);
9717 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9734 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9738 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9745 /* note these two are xlated by algebraic equivalence
9746 during parsing SDCC.y */
9747 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9748 "got '>=' or '<=' shouldn't have come here");
9752 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9764 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9768 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9772 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9799 case GET_VALUE_AT_ADDRESS:
9800 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9804 if (POINTER_SET (ic))
9805 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9831 addSet (&_G.sendSet, ic);
9834 case DUMMY_READ_VOLATILE:
9843 genEndCritical (ic);
9855 _G.current_iCode = NULL;
9857 /* now we are ready to call the
9858 peep hole optimizer */
9859 if (!options.nopeep)
9860 peepHole (&lineHead);
9862 /* now do the actual printing */
9863 printLine (lineHead, codeOutFile);