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 &&
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 &&
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)
2364 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2366 bool switchedPSW = FALSE;
2367 int calleesaves_saved_register = -1;
2368 int stackAdjust = sym->stack;
2369 int accIsFree = sym->recvSize < 4;
2370 iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2373 /* create the function header */
2374 emitcode (";", "-----------------------------------------");
2375 emitcode (";", " function %s", sym->name);
2376 emitcode (";", "-----------------------------------------");
2378 emitcode ("", "%s:", sym->rname);
2379 ftype = operandType (IC_LEFT (ic));
2380 _G.currentFunc = sym;
2382 if (IFFUNC_ISNAKED(ftype))
2384 emitcode(";", "naked function: no prologue.");
2388 /* here we need to generate the equates for the
2389 register bank if required */
2390 if (FUNC_REGBANK (ftype) != rbank)
2394 rbank = FUNC_REGBANK (ftype);
2395 for (i = 0; i < mcs51_nRegs; i++)
2397 if (strcmp (regs8051[i].base, "0") == 0)
2398 emitcode ("", "%s = 0x%02x",
2400 8 * rbank + regs8051[i].offset);
2402 emitcode ("", "%s = %s + 0x%02x",
2405 8 * rbank + regs8051[i].offset);
2409 /* if this is an interrupt service routine then
2410 save acc, b, dpl, dph */
2411 if (IFFUNC_ISISR (sym->type))
2414 if (!inExcludeList ("acc"))
2415 emitcode ("push", "acc");
2416 if (!inExcludeList ("b"))
2417 emitcode ("push", "b");
2418 if (!inExcludeList ("dpl"))
2419 emitcode ("push", "dpl");
2420 if (!inExcludeList ("dph"))
2421 emitcode ("push", "dph");
2422 /* if this isr has no bank i.e. is going to
2423 run with bank 0 , then we need to save more
2425 if (!FUNC_REGBANK (sym->type))
2428 /* if this function does not call any other
2429 function then we can be economical and
2430 save only those registers that are used */
2431 if (!IFFUNC_HASFCALL(sym->type))
2435 /* if any registers used */
2438 /* save the registers used */
2439 for (i = 0; i < sym->regsUsed->size; i++)
2441 if (bitVectBitValue (sym->regsUsed, i))
2442 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2449 /* this function has a function call. We cannot
2450 determines register usage so we will have to push the
2452 saveRBank (0, ic, FALSE);
2453 if (options.parms_in_bank1) {
2455 for (i=0; i < 8 ; i++ ) {
2456 emitcode ("push","%s",rb1regs[i]);
2463 /* This ISR uses a non-zero bank.
2465 * We assume that the bank is available for our
2468 * However, if this ISR calls a function which uses some
2469 * other bank, we must save that bank entirely.
2471 unsigned long banksToSave = 0;
2473 if (IFFUNC_HASFCALL(sym->type))
2476 #define MAX_REGISTER_BANKS 4
2481 for (i = ic; i; i = i->next)
2483 if (i->op == ENDFUNCTION)
2485 /* we got to the end OK. */
2493 dtype = operandType (IC_LEFT(i));
2495 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2497 /* Mark this bank for saving. */
2498 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2500 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2504 banksToSave |= (1 << FUNC_REGBANK(dtype));
2507 /* And note that we don't need to do it in
2515 /* This is a mess; we have no idea what
2516 * register bank the called function might
2519 * The only thing I can think of to do is
2520 * throw a warning and hope.
2522 werror(W_FUNCPTR_IN_USING_ISR);
2526 if (banksToSave && options.useXstack)
2528 /* Since we aren't passing it an ic,
2529 * saveRBank will assume r0 is available to abuse.
2531 * So switch to our (trashable) bank now, so
2532 * the caller's R0 isn't trashed.
2534 emitcode ("push", "psw");
2535 emitcode ("mov", "psw,#0x%02x",
2536 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2540 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2542 if (banksToSave & (1 << ix))
2544 saveRBank(ix, NULL, FALSE);
2548 // TODO: this needs a closer look
2549 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2552 /* Set the register bank to the desired value if nothing else */
2553 /* has done so yet. */
2556 emitcode ("push", "psw");
2557 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2562 /* This is a non-ISR function. The caller has already switched register */
2563 /* banks, if necessary, so just handle the callee-saves option. */
2565 /* if callee-save to be used for this function
2566 then save the registers being used in this function */
2567 if (IFFUNC_CALLEESAVES(sym->type))
2571 /* if any registers used */
2574 /* save the registers used */
2575 for (i = 0; i < sym->regsUsed->size; i++)
2577 if (bitVectBitValue (sym->regsUsed, i))
2579 /* remember one saved register for later usage */
2580 if (calleesaves_saved_register < 0)
2581 calleesaves_saved_register = i;
2582 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2591 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2594 if (options.useXstack)
2597 emitcode ("push", "acc");
2598 emitcode ("mov", "r0,%s", spname);
2599 emitcode ("mov", "a,_bp");
2600 emitcode ("movx", "@r0,a");
2601 emitcode ("inc", "%s", spname);
2603 emitcode ("pop", "acc");
2607 /* set up the stack */
2608 emitcode ("push", "_bp"); /* save the callers stack */
2610 emitcode ("mov", "_bp,%s", spname);
2613 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2614 /* before setting up the stack frame completely. */
2615 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2617 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2621 if (rsym && rsym->regType == REG_CND)
2623 if (rsym && (rsym->accuse || rsym->ruonly))
2625 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2626 rsym = rsym->usl.spillLoc;
2629 /* If the RECEIVE operand immediately spills to the first entry on the */
2630 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2631 /* rather than the usual @r0/r1 machinations. */
2632 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2636 _G.current_iCode = ric;
2637 D(emitcode ("; genReceive",""));
2638 for (ofs=0; ofs < sym->recvSize; ofs++)
2640 if (!strcmp (fReturn[ofs], "a"))
2641 emitcode ("push", "acc");
2643 emitcode ("push", fReturn[ofs]);
2645 stackAdjust -= sym->recvSize;
2648 assert (stackAdjust>=0);
2651 _G.current_iCode = ic;
2655 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2656 /* to free up the accumulator. */
2657 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2661 _G.current_iCode = ric;
2662 D(emitcode ("; genReceive",""));
2663 for (ofs=0; ofs < sym->recvSize; ofs++)
2665 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2667 _G.current_iCode = ic;
2673 /* adjust the stack for the function */
2677 int i = stackAdjust;
2679 werror (W_STACK_OVERFLOW, sym->name);
2681 if (i > 3 && accIsFree)
2684 emitcode ("mov", "a,sp");
2685 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2686 emitcode ("mov", "sp,a");
2691 /* The accumulator is not free, so we will need another register */
2692 /* to clobber. No need to worry about a possible conflict with */
2693 /* the above early RECEIVE optimizations since they would have */
2694 /* freed the accumulator if they were generated. */
2696 if (IFFUNC_CALLEESAVES(sym->type))
2698 /* if it's a callee-saves function we need a saved register */
2699 if (calleesaves_saved_register >= 0)
2701 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2702 emitcode ("mov", "a,sp");
2703 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2704 emitcode ("mov", "sp,a");
2705 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2708 /* do it the hard way */
2710 emitcode ("inc", "sp");
2714 /* not callee-saves, we can clobber r0 */
2715 emitcode ("mov", "r0,a");
2716 emitcode ("mov", "a,sp");
2717 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2718 emitcode ("mov", "sp,a");
2719 emitcode ("mov", "a,r0");
2724 emitcode ("inc", "sp");
2731 emitcode ("push", "acc");
2732 emitcode ("mov", "a,_spx");
2733 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2734 emitcode ("mov", "_spx,a");
2736 emitcode ("pop", "acc");
2739 /* if critical function then turn interrupts off */
2740 if (IFFUNC_ISCRITICAL (ftype))
2742 symbol *tlbl = newiTempLabel (NULL);
2743 emitcode ("setb", "c");
2744 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2745 emitcode ("clr", "c");
2746 emitcode ("", "%05d$:", (tlbl->key + 100));
2747 emitcode ("push", "psw"); /* save old ea via c in psw */
2751 /*-----------------------------------------------------------------*/
2752 /* genEndFunction - generates epilogue for functions */
2753 /*-----------------------------------------------------------------*/
2755 genEndFunction (iCode * ic)
2757 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2758 lineNode *lnp = lineCurr;
2760 bitVect *regsUsedPrologue;
2761 bitVect *regsUnneeded;
2764 _G.currentFunc = NULL;
2765 if (IFFUNC_ISNAKED(sym->type))
2767 emitcode(";", "naked function: no epilogue.");
2771 if (IFFUNC_ISCRITICAL (sym->type))
2773 emitcode ("pop", "psw"); /* restore ea via c in psw */
2774 emitcode ("mov", "ea,c");
2777 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2779 emitcode ("mov", "%s,_bp", spname);
2782 /* if use external stack but some variables were
2783 added to the local stack then decrement the
2785 if (options.useXstack && sym->stack)
2787 emitcode ("mov", "a,sp");
2788 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2789 emitcode ("mov", "sp,a");
2793 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2795 if (options.useXstack)
2797 emitcode ("mov", "r0,%s", spname);
2798 emitcode ("movx", "a,@r0");
2799 emitcode ("mov", "_bp,a");
2800 emitcode ("dec", "%s", spname);
2804 emitcode ("pop", "_bp");
2808 /* restore the register bank */
2809 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2811 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2812 || !options.useXstack)
2814 /* Special case of ISR using non-zero bank with useXstack
2817 emitcode ("pop", "psw");
2821 if (IFFUNC_ISISR (sym->type))
2824 /* now we need to restore the registers */
2825 /* if this isr has no bank i.e. is going to
2826 run with bank 0 , then we need to save more
2828 if (!FUNC_REGBANK (sym->type))
2830 /* if this function does not call any other
2831 function then we can be economical and
2832 save only those registers that are used */
2833 if (!IFFUNC_HASFCALL(sym->type))
2837 /* if any registers used */
2840 /* save the registers used */
2841 for (i = sym->regsUsed->size; i >= 0; i--)
2843 if (bitVectBitValue (sym->regsUsed, i))
2844 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2850 if (options.parms_in_bank1) {
2852 for (i = 7 ; i >= 0 ; i-- ) {
2853 emitcode ("pop","%s",rb1regs[i]);
2856 /* this function has a function call cannot
2857 determines register usage so we will have to pop the
2859 unsaveRBank (0, ic, FALSE);
2864 /* This ISR uses a non-zero bank.
2866 * Restore any register banks saved by genFunction
2869 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2872 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2874 if (savedBanks & (1 << ix))
2876 unsaveRBank(ix, NULL, FALSE);
2880 if (options.useXstack)
2882 /* Restore bank AFTER calling unsaveRBank,
2883 * since it can trash r0.
2885 emitcode ("pop", "psw");
2889 if (!inExcludeList ("dph"))
2890 emitcode ("pop", "dph");
2891 if (!inExcludeList ("dpl"))
2892 emitcode ("pop", "dpl");
2893 if (!inExcludeList ("b"))
2894 emitcode ("pop", "b");
2895 if (!inExcludeList ("acc"))
2896 emitcode ("pop", "acc");
2898 /* if debug then send end of function */
2899 if (options.debug && currFunc)
2902 emitcode ("", "C$%s$%d$%d$%d ==.",
2903 FileBaseName (ic->filename), currFunc->lastLine,
2904 ic->level, ic->block);
2905 if (IS_STATIC (currFunc->etype))
2906 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2908 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2912 emitcode ("reti", "");
2916 if (IFFUNC_CALLEESAVES(sym->type))
2920 /* if any registers used */
2923 /* save the registers used */
2924 for (i = sym->regsUsed->size; i >= 0; i--)
2926 if (bitVectBitValue (sym->regsUsed, i) ||
2927 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2928 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2931 else if (mcs51_ptrRegReq)
2933 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
2934 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2939 /* if debug then send end of function */
2940 if (options.debug && currFunc)
2943 emitcode ("", "C$%s$%d$%d$%d ==.",
2944 FileBaseName (ic->filename), currFunc->lastLine,
2945 ic->level, ic->block);
2946 if (IS_STATIC (currFunc->etype))
2947 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2949 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2953 emitcode ("ret", "");
2956 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
2959 /* If this was an interrupt handler using bank 0 that called another */
2960 /* function, then all registers must be saved; nothing to optimized. */
2961 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
2962 && !FUNC_REGBANK(sym->type))
2965 /* There are no push/pops to optimize if not callee-saves or ISR */
2966 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
2969 /* If there were stack parameters, we cannot optimize without also */
2970 /* fixing all of the stack offsets; this is too dificult to consider. */
2971 if (FUNC_HASSTACKPARM(sym->type))
2974 /* Compute the registers actually used */
2975 regsUsed = newBitVect (mcs51_nRegs);
2976 regsUsedPrologue = newBitVect (mcs51_nRegs);
2979 if (lnp->ic && lnp->ic->op == FUNCTION)
2980 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
2982 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
2984 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
2985 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
2992 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
2993 && !bitVectBitValue (regsUsed, CND_IDX))
2995 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
2996 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
2998 bitVectUnSetBit (regsUsed, CND_IDX);
3001 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3003 /* If this was an interrupt handler that called another function */
3004 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3005 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3007 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3008 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3009 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3010 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3011 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3014 /* Remove the unneeded push/pops */
3015 regsUnneeded = newBitVect (mcs51_nRegs);
3018 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3020 if (!strncmp(lnp->line, "push", 4))
3022 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3023 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3025 connectLine (lnp->prev, lnp->next);
3026 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3029 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3031 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3032 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3034 connectLine (lnp->prev, lnp->next);
3035 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3042 for (idx = 0; idx < regsUnneeded->size; idx++)
3043 if (bitVectBitValue (regsUnneeded, idx))
3044 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3046 freeBitVect (regsUnneeded);
3047 freeBitVect (regsUsed);
3048 freeBitVect (regsUsedPrologue);
3051 /*-----------------------------------------------------------------*/
3052 /* genRet - generate code for return statement */
3053 /*-----------------------------------------------------------------*/
3057 int size, offset = 0, pushed = 0;
3059 D(emitcode ("; genRet",""));
3061 /* if we have no return value then
3062 just generate the "ret" */
3066 /* we have something to return then
3067 move the return value into place */
3068 aopOp (IC_LEFT (ic), ic, FALSE);
3069 size = AOP_SIZE (IC_LEFT (ic));
3074 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3077 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3079 emitcode ("push", "%s", l);
3084 l = aopGet (AOP (IC_LEFT (ic)), offset,
3086 if (strcmp (fReturn[offset], l))
3087 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3096 if (strcmp (fReturn[pushed], "a"))
3097 emitcode ("pop", fReturn[pushed]);
3099 emitcode ("pop", "acc");
3102 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3105 /* generate a jump to the return label
3106 if the next is not the return statement */
3107 if (!(ic->next && ic->next->op == LABEL &&
3108 IC_LABEL (ic->next) == returnLabel))
3110 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3114 /*-----------------------------------------------------------------*/
3115 /* genLabel - generates a label */
3116 /*-----------------------------------------------------------------*/
3118 genLabel (iCode * ic)
3120 /* special case never generate */
3121 if (IC_LABEL (ic) == entryLabel)
3124 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3127 /*-----------------------------------------------------------------*/
3128 /* genGoto - generates a ljmp */
3129 /*-----------------------------------------------------------------*/
3131 genGoto (iCode * ic)
3133 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3136 /*-----------------------------------------------------------------*/
3137 /* findLabelBackwards: walks back through the iCode chain looking */
3138 /* for the given label. Returns number of iCode instructions */
3139 /* between that label and given ic. */
3140 /* Returns zero if label not found. */
3141 /*-----------------------------------------------------------------*/
3143 findLabelBackwards (iCode * ic, int key)
3152 /* If we have any pushes or pops, we cannot predict the distance.
3153 I don't like this at all, this should be dealt with in the
3155 if (ic->op == IPUSH || ic->op == IPOP) {
3159 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3168 /*-----------------------------------------------------------------*/
3169 /* genPlusIncr :- does addition with increment if possible */
3170 /*-----------------------------------------------------------------*/
3172 genPlusIncr (iCode * ic)
3174 unsigned int icount;
3175 unsigned int size = getDataSize (IC_RESULT (ic));
3177 /* will try to generate an increment */
3178 /* if the right side is not a literal
3180 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3183 /* if the literal value of the right hand side
3184 is greater than 4 then it is not worth it */
3185 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3188 D(emitcode ("; genPlusIncr",""));
3190 /* if increment >=16 bits in register or direct space */
3191 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3192 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3200 /* If the next instruction is a goto and the goto target
3201 * is < 10 instructions previous to this, we can generate
3202 * jumps straight to that target.
3204 if (ic->next && ic->next->op == GOTO
3205 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3206 && labelRange <= 10)
3208 emitcode (";", "tail increment optimized");
3209 tlbl = IC_LABEL (ic->next);
3214 tlbl = newiTempLabel (NULL);
3217 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3218 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3219 IS_AOP_PREG (IC_RESULT (ic)))
3220 emitcode ("cjne", "%s,#0x00,%05d$",
3221 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3225 emitcode ("clr", "a");
3226 emitcode ("cjne", "a,%s,%05d$",
3227 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3231 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3235 IS_AOP_PREG (IC_RESULT (ic)))
3236 emitcode ("cjne", "%s,#0x00,%05d$",
3237 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3240 emitcode ("cjne", "a,%s,%05d$",
3241 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3244 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3248 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3249 IS_AOP_PREG (IC_RESULT (ic)))
3250 emitcode ("cjne", "%s,#0x00,%05d$",
3251 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3255 emitcode ("cjne", "a,%s,%05d$",
3256 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3259 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3264 emitcode ("", "%05d$:", tlbl->key + 100);
3269 /* if the sizes are greater than 1 then we cannot */
3270 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3271 AOP_SIZE (IC_LEFT (ic)) > 1)
3274 /* we can if the aops of the left & result match or
3275 if they are in registers and the registers are the
3277 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3282 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3283 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3284 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3290 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc */
3301 /*-----------------------------------------------------------------*/
3303 outBitAcc (operand * result)
3305 symbol *tlbl = newiTempLabel (NULL);
3306 /* if the result is a bit */
3307 if (AOP_TYPE (result) == AOP_CRY)
3309 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3313 emitcode ("jz", "%05d$", tlbl->key + 100);
3314 emitcode ("mov", "a,%s", one);
3315 emitcode ("", "%05d$:", tlbl->key + 100);
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits */
3322 /*-----------------------------------------------------------------*/
3324 genPlusBits (iCode * ic)
3326 D(emitcode ("; genPlusBits",""));
3328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3330 symbol *lbl = newiTempLabel (NULL);
3331 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333 emitcode ("cpl", "c");
3334 emitcode ("", "%05d$:", (lbl->key + 100));
3335 outBitC (IC_RESULT (ic));
3339 emitcode ("clr", "a");
3340 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341 emitcode ("rlc", "a");
3342 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343 emitcode ("addc", "a,#0x00");
3344 outAcc (IC_RESULT (ic));
3349 /* This is the original version of this code.
3351 * This is being kept around for reference,
3352 * because I am not entirely sure I got it right...
3355 adjustArithmeticResult (iCode * ic)
3357 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3358 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3359 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3360 aopPut (AOP (IC_RESULT (ic)),
3361 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3363 isOperandVolatile (IC_RESULT (ic), FALSE));
3365 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3366 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3367 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3368 aopPut (AOP (IC_RESULT (ic)),
3369 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3371 isOperandVolatile (IC_RESULT (ic), FALSE));
3373 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3374 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3375 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3376 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3377 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3380 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3381 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3385 /* This is the pure and virtuous version of this code.
3386 * I'm pretty certain it's right, but not enough to toss the old
3390 adjustArithmeticResult (iCode * ic)
3392 if (opIsGptr (IC_RESULT (ic)) &&
3393 opIsGptr (IC_LEFT (ic)) &&
3394 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3396 aopPut (AOP (IC_RESULT (ic)),
3397 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3399 isOperandVolatile (IC_RESULT (ic), FALSE));
3402 if (opIsGptr (IC_RESULT (ic)) &&
3403 opIsGptr (IC_RIGHT (ic)) &&
3404 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3406 aopPut (AOP (IC_RESULT (ic)),
3407 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3409 isOperandVolatile (IC_RESULT (ic), FALSE));
3412 if (opIsGptr (IC_RESULT (ic)) &&
3413 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3414 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3415 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3416 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3419 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3420 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3425 /*-----------------------------------------------------------------*/
3426 /* genPlus - generates code for addition */
3427 /*-----------------------------------------------------------------*/
3429 genPlus (iCode * ic)
3431 int size, offset = 0;
3434 asmop *leftOp, *rightOp;
3437 /* special cases :- */
3439 D(emitcode ("; genPlus",""));
3441 aopOp (IC_LEFT (ic), ic, FALSE);
3442 aopOp (IC_RIGHT (ic), ic, FALSE);
3443 aopOp (IC_RESULT (ic), ic, TRUE);
3445 /* if literal, literal on the right or
3446 if left requires ACC or right is already
3448 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3449 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3450 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3452 operand *t = IC_RIGHT (ic);
3453 IC_RIGHT (ic) = IC_LEFT (ic);
3457 /* if both left & right are in bit
3459 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3460 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3466 /* if left in bit space & right literal */
3467 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3468 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3470 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3471 /* if result in bit space */
3472 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3474 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3475 emitcode ("cpl", "c");
3476 outBitC (IC_RESULT (ic));
3480 size = getDataSize (IC_RESULT (ic));
3483 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3484 emitcode ("addc", "a,#00");
3485 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3491 /* if I can do an increment instead
3492 of add then GOOD for ME */
3493 if (genPlusIncr (ic) == TRUE)
3496 size = getDataSize (IC_RESULT (ic));
3497 leftOp = AOP(IC_LEFT(ic));
3498 rightOp = AOP(IC_RIGHT(ic));
3501 /* if this is an add for an array access
3502 at a 256 byte boundary */
3504 && AOP_TYPE (op) == AOP_IMMD
3506 && IS_SPEC (OP_SYM_ETYPE (op))
3507 && SPEC_ABSA (OP_SYM_ETYPE (op))
3508 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3511 D(emitcode ("; genPlus aligned array",""));
3512 aopPut (AOP (IC_RESULT (ic)),
3513 aopGet (rightOp, 0, FALSE, FALSE),
3515 isOperandVolatile (IC_RESULT (ic), FALSE));
3517 if( 1 == getDataSize (IC_RIGHT (ic)) )
3519 aopPut (AOP (IC_RESULT (ic)),
3520 aopGet (leftOp, 1, FALSE, FALSE),
3522 isOperandVolatile (IC_RESULT (ic), FALSE));
3526 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3527 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3528 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3533 /* if the lower bytes of a literal are zero skip the addition */
3534 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3536 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3537 (skip_bytes+1 < size))
3542 D(emitcode ("; genPlus shortcut",""));
3547 if( offset >= skip_bytes )
3549 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3551 emitcode("mov", "b,a");
3552 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3553 emitcode("xch", "a,b");
3554 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3555 emitcode (add, "a,b");
3557 else if (aopGetUsesAcc (leftOp, offset))
3559 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3560 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3564 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3565 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3567 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3568 add = "addc"; /* further adds must propagate carry */
3572 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3573 isOperandVolatile (IC_RESULT (ic), FALSE))
3576 aopPut (AOP (IC_RESULT (ic)),
3577 aopGet (leftOp, offset, FALSE, FALSE),
3579 isOperandVolatile (IC_RESULT (ic), FALSE));
3585 adjustArithmeticResult (ic);
3588 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3590 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3593 /*-----------------------------------------------------------------*/
3594 /* genMinusDec :- does subtraction with deccrement if possible */
3595 /*-----------------------------------------------------------------*/
3597 genMinusDec (iCode * ic)
3599 unsigned int icount;
3600 unsigned int size = getDataSize (IC_RESULT (ic));
3602 /* will try to generate an increment */
3603 /* if the right side is not a literal
3605 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3608 /* if the literal value of the right hand side
3609 is greater than 4 then it is not worth it */
3610 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3613 D(emitcode ("; genMinusDec",""));
3615 /* if decrement >=16 bits in register or direct space */
3616 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3617 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3625 /* If the next instruction is a goto and the goto target
3626 * is <= 10 instructions previous to this, we can generate
3627 * jumps straight to that target.
3629 if (ic->next && ic->next->op == GOTO
3630 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3631 && labelRange <= 10)
3633 emitcode (";", "tail decrement optimized");
3634 tlbl = IC_LABEL (ic->next);
3639 tlbl = newiTempLabel (NULL);
3643 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3644 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3645 IS_AOP_PREG (IC_RESULT (ic)))
3646 emitcode ("cjne", "%s,#0xff,%05d$"
3647 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3651 emitcode ("mov", "a,#0xff");
3652 emitcode ("cjne", "a,%s,%05d$"
3653 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3656 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3659 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3660 IS_AOP_PREG (IC_RESULT (ic)))
3661 emitcode ("cjne", "%s,#0xff,%05d$"
3662 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3666 emitcode ("cjne", "a,%s,%05d$"
3667 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3670 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675 IS_AOP_PREG (IC_RESULT (ic)))
3676 emitcode ("cjne", "%s,#0xff,%05d$"
3677 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3681 emitcode ("cjne", "a,%s,%05d$"
3682 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3685 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3689 emitcode ("", "%05d$:", tlbl->key + 100);
3694 /* if the sizes are greater than 1 then we cannot */
3695 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3696 AOP_SIZE (IC_LEFT (ic)) > 1)
3699 /* we can if the aops of the left & result match or
3700 if they are in registers and the registers are the
3702 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3706 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3714 /*-----------------------------------------------------------------*/
3715 /* addSign - complete with sign */
3716 /*-----------------------------------------------------------------*/
3718 addSign (operand * result, int offset, int sign)
3720 int size = (getDataSize (result) - offset);
3725 emitcode ("rlc", "a");
3726 emitcode ("subb", "a,acc");
3728 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3732 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3736 /*-----------------------------------------------------------------*/
3737 /* genMinusBits - generates code for subtraction of two bits */
3738 /*-----------------------------------------------------------------*/
3740 genMinusBits (iCode * ic)
3742 symbol *lbl = newiTempLabel (NULL);
3744 D(emitcode ("; genMinusBits",""));
3746 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3748 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3749 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3750 emitcode ("cpl", "c");
3751 emitcode ("", "%05d$:", (lbl->key + 100));
3752 outBitC (IC_RESULT (ic));
3756 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3757 emitcode ("subb", "a,acc");
3758 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3759 emitcode ("inc", "a");
3760 emitcode ("", "%05d$:", (lbl->key + 100));
3761 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3762 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3766 /*-----------------------------------------------------------------*/
3767 /* genMinus - generates code for subtraction */
3768 /*-----------------------------------------------------------------*/
3770 genMinus (iCode * ic)
3772 int size, offset = 0;
3774 D(emitcode ("; genMinus",""));
3776 aopOp (IC_LEFT (ic), ic, FALSE);
3777 aopOp (IC_RIGHT (ic), ic, FALSE);
3778 aopOp (IC_RESULT (ic), ic, TRUE);
3780 /* special cases :- */
3781 /* if both left & right are in bit space */
3782 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3783 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3789 /* if I can do an decrement instead
3790 of subtract then GOOD for ME */
3791 if (genMinusDec (ic) == TRUE)
3794 size = getDataSize (IC_RESULT (ic));
3796 /* if literal, add a,#-lit, else normal subb */
3797 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3799 unsigned long lit = 0L;
3801 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3806 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3807 /* first add without previous c */
3809 if (!size && lit== (unsigned long) -1) {
3810 emitcode ("dec", "a");
3812 emitcode ("add", "a,#0x%02x",
3813 (unsigned int) (lit & 0x0FFL));
3816 emitcode ("addc", "a,#0x%02x",
3817 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3819 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3824 asmop *leftOp, *rightOp;
3826 leftOp = AOP(IC_LEFT(ic));
3827 rightOp = AOP(IC_RIGHT(ic));
3831 if (aopGetUsesAcc(rightOp, offset)) {
3832 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3833 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3835 emitcode( "setb", "c");
3837 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3838 emitcode("cpl", "a");
3840 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3843 emitcode ("subb", "a,%s",
3844 aopGet(rightOp, offset, FALSE, TRUE));
3847 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3852 adjustArithmeticResult (ic);
3855 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3856 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3857 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3861 /*-----------------------------------------------------------------*/
3862 /* genMultbits :- multiplication of bits */
3863 /*-----------------------------------------------------------------*/
3865 genMultbits (operand * left,
3869 D(emitcode ("; genMultbits",""));
3871 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3872 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3876 /*-----------------------------------------------------------------*/
3877 /* genMultOneByte : 8*8=8/16 bit multiplication */
3878 /*-----------------------------------------------------------------*/
3880 genMultOneByte (operand * left,
3885 int size = AOP_SIZE (result);
3886 bool runtimeSign, compiletimeSign;
3887 bool lUnsigned, rUnsigned;
3889 D(emitcode ("; genMultOneByte",""));
3891 if (size < 1 || size > 2)
3893 /* this should never happen */
3894 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3895 AOP_SIZE(result), __FILE__, lineno);
3899 /* (if two literals: the value is computed before) */
3900 /* if one literal, literal on the right */
3901 if (AOP_TYPE (left) == AOP_LIT)
3906 /* emitcode (";", "swapped left and right"); */
3908 /* if no literal, unsigned on the right: shorter code */
3909 if ( AOP_TYPE (right) != AOP_LIT
3910 && SPEC_USIGN (getSpec (operandType (left))))
3917 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3918 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3920 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
3921 no need to take care about the signedness! */
3922 || (lUnsigned && rUnsigned))
3924 /* just an unsigned 8 * 8 = 8 multiply
3926 /* emitcode (";","unsigned"); */
3927 /* TODO: check for accumulator clash between left & right aops? */
3929 if (AOP_TYPE (right) == AOP_LIT)
3931 /* moving to accumulator first helps peepholes */
3932 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3933 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3937 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3938 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3941 emitcode ("mul", "ab");
3942 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3944 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3948 /* we have to do a signed multiply */
3949 /* emitcode (";", "signed"); */
3951 /* now sign adjust for both left & right */
3953 /* let's see what's needed: */
3954 /* apply negative sign during runtime */
3955 runtimeSign = FALSE;
3956 /* negative sign from literals */
3957 compiletimeSign = FALSE;
3961 if (AOP_TYPE(left) == AOP_LIT)
3963 /* signed literal */
3964 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3966 compiletimeSign = TRUE;
3969 /* signed but not literal */
3975 if (AOP_TYPE(right) == AOP_LIT)
3977 /* signed literal */
3978 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3980 compiletimeSign ^= TRUE;
3983 /* signed but not literal */
3987 /* initialize F0, which stores the runtime sign */
3990 if (compiletimeSign)
3991 emitcode ("setb", "F0"); /* set sign flag */
3993 emitcode ("clr", "F0"); /* reset sign flag */
3996 /* save the signs of the operands */
3997 if (AOP_TYPE(right) == AOP_LIT)
3999 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4001 if (!rUnsigned && val < 0)
4002 emitcode ("mov", "b,#0x%02x", -val);
4004 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4006 else /* ! literal */
4008 if (rUnsigned) /* emitcode (";", "signed"); */
4010 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4013 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4014 lbl = newiTempLabel (NULL);
4015 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4016 emitcode ("cpl", "F0"); /* complement sign flag */
4017 emitcode ("cpl", "a"); /* 2's complement */
4018 emitcode ("inc", "a");
4019 emitcode ("", "%05d$:", (lbl->key + 100));
4020 emitcode ("mov", "b,a");
4024 if (AOP_TYPE(left) == AOP_LIT)
4026 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4028 if (!lUnsigned && val < 0)
4029 emitcode ("mov", "a,#0x%02x", -val);
4031 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4033 else /* ! literal */
4035 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4039 lbl = newiTempLabel (NULL);
4040 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4041 emitcode ("cpl", "F0"); /* complement sign flag */
4042 emitcode ("cpl", "a"); /* 2's complement */
4043 emitcode ("inc", "a");
4044 emitcode ("", "%05d$:", (lbl->key + 100));
4048 /* now the multiplication */
4049 emitcode ("mul", "ab");
4050 if (runtimeSign || compiletimeSign)
4052 lbl = newiTempLabel (NULL);
4054 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4055 emitcode ("cpl", "a"); /* lsb 2's complement */
4057 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4060 emitcode ("add", "a,#1"); /* this sets carry flag */
4061 emitcode ("xch", "a,b");
4062 emitcode ("cpl", "a"); /* msb 2's complement */
4063 emitcode ("addc", "a,#0");
4064 emitcode ("xch", "a,b");
4066 emitcode ("", "%05d$:", (lbl->key + 100));
4068 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4070 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4073 /*-----------------------------------------------------------------*/
4074 /* genMult - generates code for multiplication */
4075 /*-----------------------------------------------------------------*/
4077 genMult (iCode * ic)
4079 operand *left = IC_LEFT (ic);
4080 operand *right = IC_RIGHT (ic);
4081 operand *result = IC_RESULT (ic);
4083 D(emitcode ("; genMult",""));
4085 /* assign the amsops */
4086 aopOp (left, ic, FALSE);
4087 aopOp (right, ic, FALSE);
4088 aopOp (result, ic, TRUE);
4090 /* special cases first */
4092 if (AOP_TYPE (left) == AOP_CRY &&
4093 AOP_TYPE (right) == AOP_CRY)
4095 genMultbits (left, right, result);
4099 /* if both are of size == 1 */
4100 #if 0 // one of them can be a sloc shared with the result
4101 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4103 if (getSize(operandType(left)) == 1 &&
4104 getSize(operandType(right)) == 1)
4107 genMultOneByte (left, right, result);
4111 /* should have been converted to function call */
4112 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4113 getSize(OP_SYMBOL(right)->type));
4117 freeAsmop (result, NULL, ic, TRUE);
4118 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4119 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4122 /*-----------------------------------------------------------------*/
4123 /* genDivbits :- division of bits */
4124 /*-----------------------------------------------------------------*/
4126 genDivbits (operand * left,
4133 D(emitcode ("; genDivbits",""));
4135 /* the result must be bit */
4136 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4137 l = aopGet (AOP (left), 0, FALSE, FALSE);
4141 emitcode ("div", "ab");
4142 emitcode ("rrc", "a");
4143 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4146 /*-----------------------------------------------------------------*/
4147 /* genDivOneByte : 8 bit division */
4148 /*-----------------------------------------------------------------*/
4150 genDivOneByte (operand * left,
4154 bool lUnsigned, rUnsigned;
4155 bool runtimeSign, compiletimeSign;
4159 D(emitcode ("; genDivOneByte",""));
4161 /* Why is it necessary that genDivOneByte() can return an int result?
4164 volatile unsigned char uc;
4165 volatile signed char sc1, sc2;
4178 In all cases a one byte result would overflow, the following cast to int
4179 would return the wrong result.
4181 Two possible solution:
4182 a) cast operands to int, if ((unsigned) / (signed)) or
4183 ((signed) / (signed))
4184 b) return an 16 bit signed int; this is what we're doing here!
4187 size = AOP_SIZE (result) - 1;
4189 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4190 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4192 /* signed or unsigned */
4193 if (lUnsigned && rUnsigned)
4195 /* unsigned is easy */
4196 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4197 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4198 emitcode ("div", "ab");
4199 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4201 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4205 /* signed is a little bit more difficult */
4207 /* now sign adjust for both left & right */
4209 /* let's see what's needed: */
4210 /* apply negative sign during runtime */
4211 runtimeSign = FALSE;
4212 /* negative sign from literals */
4213 compiletimeSign = FALSE;
4217 if (AOP_TYPE(left) == AOP_LIT)
4219 /* signed literal */
4220 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4222 compiletimeSign = TRUE;
4225 /* signed but not literal */
4231 if (AOP_TYPE(right) == AOP_LIT)
4233 /* signed literal */
4234 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4236 compiletimeSign ^= TRUE;
4239 /* signed but not literal */
4243 /* initialize F0, which stores the runtime sign */
4246 if (compiletimeSign)
4247 emitcode ("setb", "F0"); /* set sign flag */
4249 emitcode ("clr", "F0"); /* reset sign flag */
4252 /* save the signs of the operands */
4253 if (AOP_TYPE(right) == AOP_LIT)
4255 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4257 if (!rUnsigned && val < 0)
4258 emitcode ("mov", "b,#0x%02x", -val);
4260 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4262 else /* ! literal */
4265 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4268 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4269 lbl = newiTempLabel (NULL);
4270 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4271 emitcode ("cpl", "F0"); /* complement sign flag */
4272 emitcode ("cpl", "a"); /* 2's complement */
4273 emitcode ("inc", "a");
4274 emitcode ("", "%05d$:", (lbl->key + 100));
4275 emitcode ("mov", "b,a");
4279 if (AOP_TYPE(left) == AOP_LIT)
4281 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4283 if (!lUnsigned && val < 0)
4284 emitcode ("mov", "a,#0x%02x", -val);
4286 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4288 else /* ! literal */
4290 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4294 lbl = newiTempLabel (NULL);
4295 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4296 emitcode ("cpl", "F0"); /* complement sign flag */
4297 emitcode ("cpl", "a"); /* 2's complement */
4298 emitcode ("inc", "a");
4299 emitcode ("", "%05d$:", (lbl->key + 100));
4303 /* now the division */
4304 emitcode ("div", "ab");
4306 if (runtimeSign || compiletimeSign)
4308 lbl = newiTempLabel (NULL);
4310 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4311 emitcode ("cpl", "a"); /* lsb 2's complement */
4312 emitcode ("inc", "a");
4313 emitcode ("", "%05d$:", (lbl->key + 100));
4315 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4318 /* msb is 0x00 or 0xff depending on the sign */
4321 emitcode ("mov", "c,F0");
4322 emitcode ("subb", "a,acc");
4324 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4326 else /* compiletimeSign */
4328 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4333 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4335 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4339 /*-----------------------------------------------------------------*/
4340 /* genDiv - generates code for division */
4341 /*-----------------------------------------------------------------*/
4345 operand *left = IC_LEFT (ic);
4346 operand *right = IC_RIGHT (ic);
4347 operand *result = IC_RESULT (ic);
4349 D(emitcode ("; genDiv",""));
4351 /* assign the amsops */
4352 aopOp (left, ic, FALSE);
4353 aopOp (right, ic, FALSE);
4354 aopOp (result, ic, TRUE);
4356 /* special cases first */
4358 if (AOP_TYPE (left) == AOP_CRY &&
4359 AOP_TYPE (right) == AOP_CRY)
4361 genDivbits (left, right, result);
4365 /* if both are of size == 1 */
4366 if (AOP_SIZE (left) == 1 &&
4367 AOP_SIZE (right) == 1)
4369 genDivOneByte (left, right, result);
4373 /* should have been converted to function call */
4376 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4377 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4378 freeAsmop (result, NULL, ic, TRUE);
4381 /*-----------------------------------------------------------------*/
4382 /* genModbits :- modulus of bits */
4383 /*-----------------------------------------------------------------*/
4385 genModbits (operand * left,
4392 D(emitcode ("; genModbits",""));
4394 /* the result must be bit */
4395 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4396 l = aopGet (AOP (left), 0, FALSE, FALSE);
4400 emitcode ("div", "ab");
4401 emitcode ("mov", "a,b");
4402 emitcode ("rrc", "a");
4403 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4406 /*-----------------------------------------------------------------*/
4407 /* genModOneByte : 8 bit modulus */
4408 /*-----------------------------------------------------------------*/
4410 genModOneByte (operand * left,
4414 bool lUnsigned, rUnsigned;
4415 bool runtimeSign, compiletimeSign;
4419 D(emitcode ("; genModOneByte",""));
4421 size = AOP_SIZE (result) - 1;
4423 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4424 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4426 /* signed or unsigned */
4427 if (lUnsigned && rUnsigned)
4429 /* unsigned is easy */
4430 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4431 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4432 emitcode ("div", "ab");
4433 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4435 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4439 /* signed is a little bit more difficult */
4441 /* now sign adjust for both left & right */
4443 /* modulus: sign of the right operand has no influence on the result! */
4444 if (AOP_TYPE(right) == AOP_LIT)
4446 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4448 if (!rUnsigned && val < 0)
4449 emitcode ("mov", "b,#0x%02x", -val);
4451 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4453 else /* not literal */
4456 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4459 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4460 lbl = newiTempLabel (NULL);
4461 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4462 emitcode ("cpl", "a"); /* 2's complement */
4463 emitcode ("inc", "a");
4464 emitcode ("", "%05d$:", (lbl->key + 100));
4465 emitcode ("mov", "b,a");
4469 /* let's see what's needed: */
4470 /* apply negative sign during runtime */
4471 runtimeSign = FALSE;
4472 /* negative sign from literals */
4473 compiletimeSign = FALSE;
4475 /* sign adjust left side */
4476 if (AOP_TYPE(left) == AOP_LIT)
4478 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4480 if (!lUnsigned && val < 0)
4482 compiletimeSign = TRUE; /* set sign flag */
4483 emitcode ("mov", "a,#0x%02x", -val);
4486 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4488 else /* ! literal */
4490 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4495 emitcode ("clr", "F0"); /* clear sign flag */
4497 lbl = newiTempLabel (NULL);
4498 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4499 emitcode ("setb", "F0"); /* set sign flag */
4500 emitcode ("cpl", "a"); /* 2's complement */
4501 emitcode ("inc", "a");
4502 emitcode ("", "%05d$:", (lbl->key + 100));
4506 /* now the modulus */
4507 emitcode ("div", "ab");
4509 if (runtimeSign || compiletimeSign)
4511 emitcode ("mov", "a,b");
4512 lbl = newiTempLabel (NULL);
4514 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4515 emitcode ("cpl", "a"); /* 2's complement */
4516 emitcode ("inc", "a");
4517 emitcode ("", "%05d$:", (lbl->key + 100));
4519 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4522 /* msb is 0x00 or 0xff depending on the sign */
4525 emitcode ("mov", "c,F0");
4526 emitcode ("subb", "a,acc");
4528 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4530 else /* compiletimeSign */
4532 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4537 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4539 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4543 /*-----------------------------------------------------------------*/
4544 /* genMod - generates code for division */
4545 /*-----------------------------------------------------------------*/
4549 operand *left = IC_LEFT (ic);
4550 operand *right = IC_RIGHT (ic);
4551 operand *result = IC_RESULT (ic);
4553 D(emitcode ("; genMod",""));
4555 /* assign the amsops */
4556 aopOp (left, ic, FALSE);
4557 aopOp (right, ic, FALSE);
4558 aopOp (result, ic, TRUE);
4560 /* special cases first */
4562 if (AOP_TYPE (left) == AOP_CRY &&
4563 AOP_TYPE (right) == AOP_CRY)
4565 genModbits (left, right, result);
4569 /* if both are of size == 1 */
4570 if (AOP_SIZE (left) == 1 &&
4571 AOP_SIZE (right) == 1)
4573 genModOneByte (left, right, result);
4577 /* should have been converted to function call */
4581 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4582 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4583 freeAsmop (result, NULL, ic, TRUE);
4586 /*-----------------------------------------------------------------*/
4587 /* genIfxJump :- will create a jump depending on the ifx */
4588 /*-----------------------------------------------------------------*/
4590 genIfxJump (iCode * ic, char *jval)
4593 symbol *tlbl = newiTempLabel (NULL);
4596 D(emitcode ("; genIfxJump",""));
4598 /* if true label then we jump if condition
4602 jlbl = IC_TRUE (ic);
4603 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4604 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4608 /* false label is present */
4609 jlbl = IC_FALSE (ic);
4610 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4611 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4613 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4614 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4616 emitcode (inst, "%05d$", tlbl->key + 100);
4617 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4618 emitcode ("", "%05d$:", tlbl->key + 100);
4620 /* mark the icode as generated */
4624 /*-----------------------------------------------------------------*/
4625 /* genCmp :- greater or less than comparison */
4626 /*-----------------------------------------------------------------*/
4628 genCmp (operand * left, operand * right,
4629 operand * result, iCode * ifx, int sign, iCode *ic)
4631 int size, offset = 0;
4632 unsigned long lit = 0L;
4635 D(emitcode ("; genCmp",""));
4637 /* if left & right are bit variables */
4638 if (AOP_TYPE (left) == AOP_CRY &&
4639 AOP_TYPE (right) == AOP_CRY)
4641 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4642 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4646 /* subtract right from left if at the
4647 end the carry flag is set then we know that
4648 left is greater than right */
4649 size = max (AOP_SIZE (left), AOP_SIZE (right));
4651 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4652 if ((size == 1) && !sign &&
4653 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4655 symbol *lbl = newiTempLabel (NULL);
4656 emitcode ("cjne", "%s,%s,%05d$",
4657 aopGet (AOP (left), offset, FALSE, FALSE),
4658 aopGet (AOP (right), offset, FALSE, FALSE),
4660 emitcode ("", "%05d$:", lbl->key + 100);
4664 if (AOP_TYPE (right) == AOP_LIT)
4666 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4667 /* optimize if(x < 0) or if(x >= 0) */
4676 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4677 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4679 genIfxJump (ifx, "acc.7");
4683 emitcode ("rlc", "a");
4691 rightInB = aopGetUsesAcc(AOP (right), offset);
4693 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4694 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4695 if (sign && size == 0)
4697 emitcode ("xrl", "a,#0x80");
4698 if (AOP_TYPE (right) == AOP_LIT)
4700 unsigned long lit = (unsigned long)
4701 floatFromVal (AOP (right)->aopu.aop_lit);
4702 emitcode ("subb", "a,#0x%02x",
4703 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4708 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4709 emitcode ("xrl", "b,#0x80");
4710 emitcode ("subb", "a,b");
4716 emitcode ("subb", "a,b");
4718 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4726 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4727 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4734 /* if the result is used in the next
4735 ifx conditional branch then generate
4736 code a little differently */
4738 genIfxJump (ifx, "c");
4741 /* leave the result in acc */
4745 /*-----------------------------------------------------------------*/
4746 /* genCmpGt :- greater than comparison */
4747 /*-----------------------------------------------------------------*/
4749 genCmpGt (iCode * ic, iCode * ifx)
4751 operand *left, *right, *result;
4752 sym_link *letype, *retype;
4755 D(emitcode ("; genCmpGt",""));
4757 left = IC_LEFT (ic);
4758 right = IC_RIGHT (ic);
4759 result = IC_RESULT (ic);
4761 letype = getSpec (operandType (left));
4762 retype = getSpec (operandType (right));
4763 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4764 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4765 /* assign the amsops */
4766 aopOp (left, ic, FALSE);
4767 aopOp (right, ic, FALSE);
4768 aopOp (result, ic, TRUE);
4770 genCmp (right, left, result, ifx, sign,ic);
4772 freeAsmop (result, NULL, ic, TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* genCmpLt - less than comparisons */
4777 /*-----------------------------------------------------------------*/
4779 genCmpLt (iCode * ic, iCode * ifx)
4781 operand *left, *right, *result;
4782 sym_link *letype, *retype;
4785 D(emitcode ("; genCmpLt",""));
4787 left = IC_LEFT (ic);
4788 right = IC_RIGHT (ic);
4789 result = IC_RESULT (ic);
4791 letype = getSpec (operandType (left));
4792 retype = getSpec (operandType (right));
4793 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4794 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4795 /* assign the amsops */
4796 aopOp (left, ic, FALSE);
4797 aopOp (right, ic, FALSE);
4798 aopOp (result, ic, TRUE);
4800 genCmp (left, right, result, ifx, sign,ic);
4802 freeAsmop (result, NULL, ic, TRUE);
4805 /*-----------------------------------------------------------------*/
4806 /* gencjneshort - compare and jump if not equal */
4807 /*-----------------------------------------------------------------*/
4809 gencjneshort (operand * left, operand * right, symbol * lbl)
4811 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4813 unsigned long lit = 0L;
4815 /* if the left side is a literal or
4816 if the right is in a pointer register and left
4818 if ((AOP_TYPE (left) == AOP_LIT) ||
4819 (AOP_TYPE (left) == AOP_IMMD) ||
4820 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4827 if (AOP_TYPE (right) == AOP_LIT)
4828 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4830 /* if the right side is a literal then anything goes */
4831 if (AOP_TYPE (right) == AOP_LIT &&
4832 AOP_TYPE (left) != AOP_DIR &&
4833 AOP_TYPE (left) != AOP_IMMD)
4837 emitcode ("cjne", "%s,%s,%05d$",
4838 aopGet (AOP (left), offset, FALSE, FALSE),
4839 aopGet (AOP (right), offset, FALSE, FALSE),
4845 /* if the right side is in a register or in direct space or
4846 if the left is a pointer register & right is not */
4847 else if (AOP_TYPE (right) == AOP_REG ||
4848 AOP_TYPE (right) == AOP_DIR ||
4849 AOP_TYPE (right) == AOP_LIT ||
4850 AOP_TYPE (right) == AOP_IMMD ||
4851 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4852 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4856 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4857 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4858 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4859 emitcode ("jnz", "%05d$", lbl->key + 100);
4861 emitcode ("cjne", "a,%s,%05d$",
4862 aopGet (AOP (right), offset, FALSE, TRUE),
4869 /* right is a pointer reg need both a & b */
4872 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4873 if (strcmp (l, "b"))
4874 emitcode ("mov", "b,%s", l);
4875 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4876 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4882 /*-----------------------------------------------------------------*/
4883 /* gencjne - compare and jump if not equal */
4884 /*-----------------------------------------------------------------*/
4886 gencjne (operand * left, operand * right, symbol * lbl)
4888 symbol *tlbl = newiTempLabel (NULL);
4890 gencjneshort (left, right, lbl);
4892 emitcode ("mov", "a,%s", one);
4893 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4894 emitcode ("", "%05d$:", lbl->key + 100);
4895 emitcode ("clr", "a");
4896 emitcode ("", "%05d$:", tlbl->key + 100);
4899 /*-----------------------------------------------------------------*/
4900 /* genCmpEq - generates code for equal to */
4901 /*-----------------------------------------------------------------*/
4903 genCmpEq (iCode * ic, iCode * ifx)
4905 operand *left, *right, *result;
4907 D(emitcode ("; genCmpEq",""));
4909 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4910 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4911 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4913 /* if literal, literal on the right or
4914 if the right is in a pointer register and left
4916 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4917 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4919 operand *t = IC_RIGHT (ic);
4920 IC_RIGHT (ic) = IC_LEFT (ic);
4924 if (ifx && !AOP_SIZE (result))
4927 /* if they are both bit variables */
4928 if (AOP_TYPE (left) == AOP_CRY &&
4929 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4931 if (AOP_TYPE (right) == AOP_LIT)
4933 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4936 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4937 emitcode ("cpl", "c");
4941 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4945 emitcode ("clr", "c");
4947 /* AOP_TYPE(right) == AOP_CRY */
4951 symbol *lbl = newiTempLabel (NULL);
4952 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4953 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4954 emitcode ("cpl", "c");
4955 emitcode ("", "%05d$:", (lbl->key + 100));
4957 /* if true label then we jump if condition
4959 tlbl = newiTempLabel (NULL);
4962 emitcode ("jnc", "%05d$", tlbl->key + 100);
4963 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4967 emitcode ("jc", "%05d$", tlbl->key + 100);
4968 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4970 emitcode ("", "%05d$:", tlbl->key + 100);
4974 tlbl = newiTempLabel (NULL);
4975 gencjneshort (left, right, tlbl);
4978 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4979 emitcode ("", "%05d$:", tlbl->key + 100);
4983 symbol *lbl = newiTempLabel (NULL);
4984 emitcode ("sjmp", "%05d$", lbl->key + 100);
4985 emitcode ("", "%05d$:", tlbl->key + 100);
4986 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4987 emitcode ("", "%05d$:", lbl->key + 100);
4990 /* mark the icode as generated */
4995 /* if they are both bit variables */
4996 if (AOP_TYPE (left) == AOP_CRY &&
4997 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4999 if (AOP_TYPE (right) == AOP_LIT)
5001 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5004 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5005 emitcode ("cpl", "c");
5009 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5013 emitcode ("clr", "c");
5015 /* AOP_TYPE(right) == AOP_CRY */
5019 symbol *lbl = newiTempLabel (NULL);
5020 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5021 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5022 emitcode ("cpl", "c");
5023 emitcode ("", "%05d$:", (lbl->key + 100));
5026 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5033 genIfxJump (ifx, "c");
5036 /* if the result is used in an arithmetic operation
5037 then put the result in place */
5042 gencjne (left, right, newiTempLabel (NULL));
5043 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5045 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5050 genIfxJump (ifx, "a");
5053 /* if the result is used in an arithmetic operation
5054 then put the result in place */
5055 if (AOP_TYPE (result) != AOP_CRY)
5057 /* leave the result in acc */
5061 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5062 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5063 freeAsmop (result, NULL, ic, TRUE);
5066 /*-----------------------------------------------------------------*/
5067 /* ifxForOp - returns the icode containing the ifx for operand */
5068 /*-----------------------------------------------------------------*/
5070 ifxForOp (operand * op, iCode * ic)
5072 /* if true symbol then needs to be assigned */
5073 if (IS_TRUE_SYMOP (op))
5076 /* if this has register type condition and
5077 the next instruction is ifx with the same operand
5078 and live to of the operand is upto the ifx only then */
5080 ic->next->op == IFX &&
5081 IC_COND (ic->next)->key == op->key &&
5082 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5088 /*-----------------------------------------------------------------*/
5089 /* hasInc - operand is incremented before any other use */
5090 /*-----------------------------------------------------------------*/
5092 hasInc (operand *op, iCode *ic,int osize)
5094 sym_link *type = operandType(op);
5095 sym_link *retype = getSpec (type);
5096 iCode *lic = ic->next;
5099 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5100 if (!IS_SYMOP(op)) return NULL;
5102 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5103 if (IS_AGGREGATE(type->next)) return NULL;
5104 if (osize != (isize = getSize(type->next))) return NULL;
5107 /* if operand of the form op = op + <sizeof *op> */
5108 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5109 isOperandEqual(IC_RESULT(lic),op) &&
5110 isOperandLiteral(IC_RIGHT(lic)) &&
5111 operandLitValue(IC_RIGHT(lic)) == isize) {
5114 /* if the operand used or deffed */
5115 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5118 /* if GOTO or IFX */
5119 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5125 /*-----------------------------------------------------------------*/
5126 /* genAndOp - for && operation */
5127 /*-----------------------------------------------------------------*/
5129 genAndOp (iCode * ic)
5131 operand *left, *right, *result;
5134 D(emitcode ("; genAndOp",""));
5136 /* note here that && operations that are in an
5137 if statement are taken away by backPatchLabels
5138 only those used in arthmetic operations remain */
5139 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5140 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5141 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5143 /* if both are bit variables */
5144 if (AOP_TYPE (left) == AOP_CRY &&
5145 AOP_TYPE (right) == AOP_CRY)
5147 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5148 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5153 tlbl = newiTempLabel (NULL);
5155 emitcode ("jz", "%05d$", tlbl->key + 100);
5157 emitcode ("", "%05d$:", tlbl->key + 100);
5161 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5162 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5163 freeAsmop (result, NULL, ic, TRUE);
5167 /*-----------------------------------------------------------------*/
5168 /* genOrOp - for || operation */
5169 /*-----------------------------------------------------------------*/
5171 genOrOp (iCode * ic)
5173 operand *left, *right, *result;
5176 D(emitcode ("; genOrOp",""));
5178 /* note here that || operations that are in an
5179 if statement are taken away by backPatchLabels
5180 only those used in arthmetic operations remain */
5181 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5182 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5183 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5185 /* if both are bit variables */
5186 if (AOP_TYPE (left) == AOP_CRY &&
5187 AOP_TYPE (right) == AOP_CRY)
5189 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5190 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5195 tlbl = newiTempLabel (NULL);
5197 emitcode ("jnz", "%05d$", tlbl->key + 100);
5199 emitcode ("", "%05d$:", tlbl->key + 100);
5203 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 freeAsmop (result, NULL, ic, TRUE);
5208 /*-----------------------------------------------------------------*/
5209 /* isLiteralBit - test if lit == 2^n */
5210 /*-----------------------------------------------------------------*/
5212 isLiteralBit (unsigned long lit)
5214 unsigned long pw[32] =
5215 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5216 0x100L, 0x200L, 0x400L, 0x800L,
5217 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5218 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5219 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5220 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5221 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5224 for (idx = 0; idx < 32; idx++)
5230 /*-----------------------------------------------------------------*/
5231 /* continueIfTrue - */
5232 /*-----------------------------------------------------------------*/
5234 continueIfTrue (iCode * ic)
5237 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5241 /*-----------------------------------------------------------------*/
5243 /*-----------------------------------------------------------------*/
5245 jumpIfTrue (iCode * ic)
5248 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5252 /*-----------------------------------------------------------------*/
5253 /* jmpTrueOrFalse - */
5254 /*-----------------------------------------------------------------*/
5256 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5258 // ugly but optimized by peephole
5261 symbol *nlbl = newiTempLabel (NULL);
5262 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5263 emitcode ("", "%05d$:", tlbl->key + 100);
5264 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5265 emitcode ("", "%05d$:", nlbl->key + 100);
5269 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5270 emitcode ("", "%05d$:", tlbl->key + 100);
5275 /*-----------------------------------------------------------------*/
5276 /* genAnd - code for and */
5277 /*-----------------------------------------------------------------*/
5279 genAnd (iCode * ic, iCode * ifx)
5281 operand *left, *right, *result;
5282 int size, offset = 0;
5283 unsigned long lit = 0L;
5287 D(emitcode ("; genAnd",""));
5289 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5290 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5291 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5294 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5296 AOP_TYPE (left), AOP_TYPE (right));
5297 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5299 AOP_SIZE (left), AOP_SIZE (right));
5302 /* if left is a literal & right is not then exchange them */
5303 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5304 AOP_NEEDSACC (left))
5306 operand *tmp = right;
5311 /* if result = right then exchange them */
5312 if (sameRegs (AOP (result), AOP (right)))
5314 operand *tmp = right;
5319 /* if right is bit then exchange them */
5320 if (AOP_TYPE (right) == AOP_CRY &&
5321 AOP_TYPE (left) != AOP_CRY)
5323 operand *tmp = right;
5327 if (AOP_TYPE (right) == AOP_LIT)
5328 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5330 size = AOP_SIZE (result);
5333 // result = bit & yy;
5334 if (AOP_TYPE (left) == AOP_CRY)
5336 // c = bit & literal;
5337 if (AOP_TYPE (right) == AOP_LIT)
5341 if (size && sameRegs (AOP (result), AOP (left)))
5344 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5349 if (size && (AOP_TYPE (result) == AOP_CRY))
5351 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5354 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5359 emitcode ("clr", "c");
5364 if (AOP_TYPE (right) == AOP_CRY)
5367 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5368 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5373 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5375 emitcode ("rrc", "a");
5376 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5384 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5385 genIfxJump (ifx, "c");
5389 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5390 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5391 if ((AOP_TYPE (right) == AOP_LIT) &&
5392 (AOP_TYPE (result) == AOP_CRY) &&
5393 (AOP_TYPE (left) != AOP_CRY))
5395 int posbit = isLiteralBit (lit);
5400 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5403 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5409 sprintf (buffer, "acc.%d", posbit & 0x07);
5410 genIfxJump (ifx, buffer);
5417 symbol *tlbl = newiTempLabel (NULL);
5418 int sizel = AOP_SIZE (left);
5420 emitcode ("setb", "c");
5423 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5425 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5427 if ((posbit = isLiteralBit (bytelit)) != 0)
5428 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5431 if (bytelit != 0x0FFL)
5432 emitcode ("anl", "a,%s",
5433 aopGet (AOP (right), offset, FALSE, TRUE));
5434 emitcode ("jnz", "%05d$", tlbl->key + 100);
5439 // bit = left & literal
5442 emitcode ("clr", "c");
5443 emitcode ("", "%05d$:", tlbl->key + 100);
5445 // if(left & literal)
5449 jmpTrueOrFalse (ifx, tlbl);
5451 emitcode ("", "%05d$:", tlbl->key + 100);
5459 /* if left is same as result */
5460 if (sameRegs (AOP (result), AOP (left)))
5462 for (; size--; offset++)
5464 if (AOP_TYPE (right) == AOP_LIT)
5466 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5468 else if (bytelit == 0)
5470 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5472 else if (IS_AOP_PREG (result))
5474 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5475 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5476 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5479 emitcode ("anl", "%s,%s",
5480 aopGet (AOP (left), offset, FALSE, TRUE),
5481 aopGet (AOP (right), offset, FALSE, FALSE));
5485 if (AOP_TYPE (left) == AOP_ACC)
5486 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5489 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5490 if (IS_AOP_PREG (result))
5492 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5493 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5497 emitcode ("anl", "%s,a",
5498 aopGet (AOP (left), offset, FALSE, TRUE));
5505 // left & result in different registers
5506 if (AOP_TYPE (result) == AOP_CRY)
5509 // if(size), result in bit
5510 // if(!size && ifx), conditional oper: if(left & right)
5511 symbol *tlbl = newiTempLabel (NULL);
5512 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5514 emitcode ("setb", "c");
5517 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5518 emitcode ("anl", "a,%s",
5519 aopGet (AOP (right), offset, FALSE, FALSE));
5521 if (AOP_TYPE(left)==AOP_ACC) {
5522 emitcode("mov", "b,a");
5523 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5524 emitcode("anl", "a,b");
5526 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5527 emitcode ("anl", "a,%s",
5528 aopGet (AOP (left), offset, FALSE, FALSE));
5531 emitcode ("jnz", "%05d$", tlbl->key + 100);
5537 emitcode ("", "%05d$:", tlbl->key + 100);
5541 jmpTrueOrFalse (ifx, tlbl);
5543 emitcode ("", "%05d$:", tlbl->key + 100);
5547 for (; (size--); offset++)
5550 // result = left & right
5551 if (AOP_TYPE (right) == AOP_LIT)
5553 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5555 aopPut (AOP (result),
5556 aopGet (AOP (left), offset, FALSE, FALSE),
5558 isOperandVolatile (result, FALSE));
5561 else if (bytelit == 0)
5563 /* dummy read of volatile operand */
5564 if (isOperandVolatile (left, FALSE))
5565 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5566 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5570 // faster than result <- left, anl result,right
5571 // and better if result is SFR
5572 if (AOP_TYPE (left) == AOP_ACC)
5573 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5576 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5577 emitcode ("anl", "a,%s",
5578 aopGet (AOP (left), offset, FALSE, FALSE));
5580 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5586 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 freeAsmop (result, NULL, ic, TRUE);
5591 /*-----------------------------------------------------------------*/
5592 /* genOr - code for or */
5593 /*-----------------------------------------------------------------*/
5595 genOr (iCode * ic, iCode * ifx)
5597 operand *left, *right, *result;
5598 int size, offset = 0;
5599 unsigned long lit = 0L;
5601 D(emitcode ("; genOr",""));
5603 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5604 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5605 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5608 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5610 AOP_TYPE (left), AOP_TYPE (right));
5611 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5613 AOP_SIZE (left), AOP_SIZE (right));
5616 /* if left is a literal & right is not then exchange them */
5617 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5618 AOP_NEEDSACC (left))
5620 operand *tmp = right;
5625 /* if result = right then exchange them */
5626 if (sameRegs (AOP (result), AOP (right)))
5628 operand *tmp = right;
5633 /* if right is bit then exchange them */
5634 if (AOP_TYPE (right) == AOP_CRY &&
5635 AOP_TYPE (left) != AOP_CRY)
5637 operand *tmp = right;
5641 if (AOP_TYPE (right) == AOP_LIT)
5642 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5644 size = AOP_SIZE (result);
5648 if (AOP_TYPE (left) == AOP_CRY)
5650 if (AOP_TYPE (right) == AOP_LIT)
5652 // c = bit | literal;
5655 // lit != 0 => result = 1
5656 if (AOP_TYPE (result) == AOP_CRY)
5659 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5661 continueIfTrue (ifx);
5664 emitcode ("setb", "c");
5668 // lit == 0 => result = left
5669 if (size && sameRegs (AOP (result), AOP (left)))
5671 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5676 if (AOP_TYPE (right) == AOP_CRY)
5679 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5680 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5685 symbol *tlbl = newiTempLabel (NULL);
5686 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5687 emitcode ("setb", "c");
5688 emitcode ("jb", "%s,%05d$",
5689 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5691 emitcode ("jnz", "%05d$", tlbl->key + 100);
5692 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5694 jmpTrueOrFalse (ifx, tlbl);
5700 emitcode ("", "%05d$:", tlbl->key + 100);
5709 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5710 genIfxJump (ifx, "c");
5714 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5715 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5716 if ((AOP_TYPE (right) == AOP_LIT) &&
5717 (AOP_TYPE (result) == AOP_CRY) &&
5718 (AOP_TYPE (left) != AOP_CRY))
5724 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5726 continueIfTrue (ifx);
5731 // lit = 0, result = boolean(left)
5733 emitcode ("setb", "c");
5737 symbol *tlbl = newiTempLabel (NULL);
5738 emitcode ("jnz", "%05d$", tlbl->key + 100);
5740 emitcode ("", "%05d$:", tlbl->key + 100);
5744 genIfxJump (ifx, "a");
5752 /* if left is same as result */
5753 if (sameRegs (AOP (result), AOP (left)))
5755 for (; size--; offset++)
5757 if (AOP_TYPE (right) == AOP_LIT)
5759 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5761 /* dummy read of volatile operand */
5762 if (isOperandVolatile (left, FALSE))
5763 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5767 else if (IS_AOP_PREG (left))
5769 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5770 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5771 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5774 emitcode ("orl", "%s,%s",
5775 aopGet (AOP (left), offset, FALSE, TRUE),
5776 aopGet (AOP (right), offset, FALSE, FALSE));
5780 if (AOP_TYPE (left) == AOP_ACC)
5781 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5784 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5785 if (IS_AOP_PREG (left))
5787 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5788 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5791 emitcode ("orl", "%s,a",
5792 aopGet (AOP (left), offset, FALSE, TRUE));
5799 // left & result in different registers
5800 if (AOP_TYPE (result) == AOP_CRY)
5803 // if(size), result in bit
5804 // if(!size && ifx), conditional oper: if(left | right)
5805 symbol *tlbl = newiTempLabel (NULL);
5806 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5808 emitcode ("setb", "c");
5811 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5812 emitcode ("orl", "a,%s",
5813 aopGet (AOP (right), offset, FALSE, FALSE));
5815 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5816 emitcode ("orl", "a,%s",
5817 aopGet (AOP (left), offset, FALSE, FALSE));
5819 emitcode ("jnz", "%05d$", tlbl->key + 100);
5825 emitcode ("", "%05d$:", tlbl->key + 100);
5829 jmpTrueOrFalse (ifx, tlbl);
5831 emitcode ("", "%05d$:", tlbl->key + 100);
5834 for (; (size--); offset++)
5837 // result = left & right
5838 if (AOP_TYPE (right) == AOP_LIT)
5840 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5842 aopPut (AOP (result),
5843 aopGet (AOP (left), offset, FALSE, FALSE),
5845 isOperandVolatile (result, FALSE));
5849 // faster than result <- left, anl result,right
5850 // and better if result is SFR
5851 if (AOP_TYPE (left) == AOP_ACC)
5852 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5855 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5856 emitcode ("orl", "a,%s",
5857 aopGet (AOP (left), offset, FALSE, FALSE));
5859 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5864 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5865 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866 freeAsmop (result, NULL, ic, TRUE);
5869 /*-----------------------------------------------------------------*/
5870 /* genXor - code for xclusive or */
5871 /*-----------------------------------------------------------------*/
5873 genXor (iCode * ic, iCode * ifx)
5875 operand *left, *right, *result;
5876 int size, offset = 0;
5877 unsigned long lit = 0L;
5879 D(emitcode ("; genXor",""));
5881 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5882 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5883 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5886 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5888 AOP_TYPE (left), AOP_TYPE (right));
5889 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5891 AOP_SIZE (left), AOP_SIZE (right));
5894 /* if left is a literal & right is not ||
5895 if left needs acc & right does not */
5896 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5897 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5899 operand *tmp = right;
5904 /* if result = right then exchange them */
5905 if (sameRegs (AOP (result), AOP (right)))
5907 operand *tmp = right;
5912 /* if right is bit then exchange them */
5913 if (AOP_TYPE (right) == AOP_CRY &&
5914 AOP_TYPE (left) != AOP_CRY)
5916 operand *tmp = right;
5920 if (AOP_TYPE (right) == AOP_LIT)
5921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5923 size = AOP_SIZE (result);
5927 if (AOP_TYPE (left) == AOP_CRY)
5929 if (AOP_TYPE (right) == AOP_LIT)
5931 // c = bit & literal;
5934 // lit>>1 != 0 => result = 1
5935 if (AOP_TYPE (result) == AOP_CRY)
5938 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5940 continueIfTrue (ifx);
5943 emitcode ("setb", "c");
5950 // lit == 0, result = left
5951 if (size && sameRegs (AOP (result), AOP (left)))
5953 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5957 // lit == 1, result = not(left)
5958 if (size && sameRegs (AOP (result), AOP (left)))
5960 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5965 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5966 emitcode ("cpl", "c");
5975 symbol *tlbl = newiTempLabel (NULL);
5976 if (AOP_TYPE (right) == AOP_CRY)
5979 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5983 int sizer = AOP_SIZE (right);
5985 // if val>>1 != 0, result = 1
5986 emitcode ("setb", "c");
5989 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5991 // test the msb of the lsb
5992 emitcode ("anl", "a,#0xfe");
5993 emitcode ("jnz", "%05d$", tlbl->key + 100);
5997 emitcode ("rrc", "a");
5999 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6000 emitcode ("cpl", "c");
6001 emitcode ("", "%05d$:", (tlbl->key + 100));
6008 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6009 genIfxJump (ifx, "c");
6013 if (sameRegs (AOP (result), AOP (left)))
6015 /* if left is same as result */
6016 for (; size--; offset++)
6018 if (AOP_TYPE (right) == AOP_LIT)
6020 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6022 else if (IS_AOP_PREG (left))
6024 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6025 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6026 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6029 emitcode ("xrl", "%s,%s",
6030 aopGet (AOP (left), offset, FALSE, TRUE),
6031 aopGet (AOP (right), offset, FALSE, FALSE));
6035 if (AOP_TYPE (left) == AOP_ACC)
6036 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6039 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6040 if (IS_AOP_PREG (left))
6042 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6043 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6046 emitcode ("xrl", "%s,a",
6047 aopGet (AOP (left), offset, FALSE, TRUE));
6054 // left & result in different registers
6055 if (AOP_TYPE (result) == AOP_CRY)
6058 // if(size), result in bit
6059 // if(!size && ifx), conditional oper: if(left ^ right)
6060 symbol *tlbl = newiTempLabel (NULL);
6061 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6063 emitcode ("setb", "c");
6066 if ((AOP_TYPE (right) == AOP_LIT) &&
6067 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6069 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6073 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6074 emitcode ("xrl", "a,%s",
6075 aopGet (AOP (right), offset, FALSE, FALSE));
6077 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6078 emitcode ("xrl", "a,%s",
6079 aopGet (AOP (left), offset, FALSE, FALSE));
6082 emitcode ("jnz", "%05d$", tlbl->key + 100);
6088 emitcode ("", "%05d$:", tlbl->key + 100);
6092 jmpTrueOrFalse (ifx, tlbl);
6095 for (; (size--); offset++)
6098 // result = left & right
6099 if (AOP_TYPE (right) == AOP_LIT)
6101 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6103 aopPut (AOP (result),
6104 aopGet (AOP (left), offset, FALSE, FALSE),
6106 isOperandVolatile (result, FALSE));
6110 // faster than result <- left, anl result,right
6111 // and better if result is SFR
6112 if (AOP_TYPE (left) == AOP_ACC)
6113 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6116 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6117 emitcode ("xrl", "a,%s",
6118 aopGet (AOP (left), offset, FALSE, TRUE));
6120 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6125 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6127 freeAsmop (result, NULL, ic, TRUE);
6130 /*-----------------------------------------------------------------*/
6131 /* genInline - write the inline code out */
6132 /*-----------------------------------------------------------------*/
6134 genInline (iCode * ic)
6136 char *buffer, *bp, *bp1;
6138 D(emitcode ("; genInline",""));
6140 _G.inLine += (!options.asmpeep);
6142 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6143 strcpy (buffer, IC_INLINE (ic));
6145 /* emit each line as a code */
6170 /* emitcode("",buffer); */
6171 _G.inLine -= (!options.asmpeep);
6174 /*-----------------------------------------------------------------*/
6175 /* genRRC - rotate right with carry */
6176 /*-----------------------------------------------------------------*/
6180 operand *left, *result;
6181 int size, offset = 0;
6184 D(emitcode ("; genRRC",""));
6186 /* rotate right with carry */
6187 left = IC_LEFT (ic);
6188 result = IC_RESULT (ic);
6189 aopOp (left, ic, FALSE);
6190 aopOp (result, ic, FALSE);
6192 /* move it to the result */
6193 size = AOP_SIZE (result);
6195 if (size == 1) { /* special case for 1 byte */
6196 l = aopGet (AOP (left), offset, FALSE, FALSE);
6198 emitcode ("rr", "a");
6204 l = aopGet (AOP (left), offset, FALSE, FALSE);
6206 emitcode ("rrc", "a");
6207 if (AOP_SIZE (result) > 1)
6208 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6210 /* now we need to put the carry into the
6211 highest order byte of the result */
6212 if (AOP_SIZE (result) > 1)
6214 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6217 emitcode ("mov", "acc.7,c");
6219 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6220 freeAsmop (left, NULL, ic, TRUE);
6221 freeAsmop (result, NULL, ic, TRUE);
6224 /*-----------------------------------------------------------------*/
6225 /* genRLC - generate code for rotate left with carry */
6226 /*-----------------------------------------------------------------*/
6230 operand *left, *result;
6231 int size, offset = 0;
6234 D(emitcode ("; genRLC",""));
6236 /* rotate right with carry */
6237 left = IC_LEFT (ic);
6238 result = IC_RESULT (ic);
6239 aopOp (left, ic, FALSE);
6240 aopOp (result, ic, FALSE);
6242 /* move it to the result */
6243 size = AOP_SIZE (result);
6247 l = aopGet (AOP (left), offset, FALSE, FALSE);
6249 if (size == 0) { /* special case for 1 byte */
6253 emitcode ("add", "a,acc");
6254 if (AOP_SIZE (result) > 1)
6255 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6258 l = aopGet (AOP (left), offset, FALSE, FALSE);
6260 emitcode ("rlc", "a");
6261 if (AOP_SIZE (result) > 1)
6262 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6265 /* now we need to put the carry into the
6266 highest order byte of the result */
6267 if (AOP_SIZE (result) > 1)
6269 l = aopGet (AOP (result), 0, FALSE, FALSE);
6272 emitcode ("mov", "acc.0,c");
6274 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6275 freeAsmop (left, NULL, ic, TRUE);
6276 freeAsmop (result, NULL, ic, TRUE);
6279 /*-----------------------------------------------------------------*/
6280 /* genGetHbit - generates code get highest order bit */
6281 /*-----------------------------------------------------------------*/
6283 genGetHbit (iCode * ic)
6285 operand *left, *result;
6287 D(emitcode ("; genGetHbit",""));
6289 left = IC_LEFT (ic);
6290 result = IC_RESULT (ic);
6291 aopOp (left, ic, FALSE);
6292 aopOp (result, ic, FALSE);
6294 /* get the highest order byte into a */
6295 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6296 if (AOP_TYPE (result) == AOP_CRY)
6298 emitcode ("rlc", "a");
6303 emitcode ("rl", "a");
6304 emitcode ("anl", "a,#0x01");
6309 freeAsmop (left, NULL, ic, TRUE);
6310 freeAsmop (result, NULL, ic, TRUE);
6313 /*-----------------------------------------------------------------*/
6314 /* genSwap - generates code to swap nibbles or bytes */
6315 /*-----------------------------------------------------------------*/
6317 genSwap (iCode * ic)
6319 operand *left, *result;
6321 D(emitcode ("; genSwap",""));
6323 left = IC_LEFT (ic);
6324 result = IC_RESULT (ic);
6325 aopOp (left, ic, FALSE);
6326 aopOp (result, ic, FALSE);
6328 switch (AOP_SIZE (left))
6330 case 1: /* swap nibbles in byte */
6331 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6332 emitcode ("swap", "a");
6333 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6335 case 2: /* swap bytes in word */
6336 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6338 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6339 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6340 0, isOperandVolatile (result, FALSE));
6341 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6343 else if (operandsEqu (left, result))
6346 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6347 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6349 emitcode ("mov", "b,a");
6352 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6353 0, isOperandVolatile (result, FALSE));
6354 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6358 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6359 0, isOperandVolatile (result, FALSE));
6360 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6361 1, isOperandVolatile (result, FALSE));
6365 wassertl(FALSE, "unsupported SWAP operand size");
6368 freeAsmop (left, NULL, ic, TRUE);
6369 freeAsmop (result, NULL, ic, TRUE);
6373 /*-----------------------------------------------------------------*/
6374 /* AccRol - rotate left accumulator by known count */
6375 /*-----------------------------------------------------------------*/
6377 AccRol (int shCount)
6379 shCount &= 0x0007; // shCount : 0..7
6386 emitcode ("rl", "a");
6389 emitcode ("rl", "a");
6390 emitcode ("rl", "a");
6393 emitcode ("swap", "a");
6394 emitcode ("rr", "a");
6397 emitcode ("swap", "a");
6400 emitcode ("swap", "a");
6401 emitcode ("rl", "a");
6404 emitcode ("rr", "a");
6405 emitcode ("rr", "a");
6408 emitcode ("rr", "a");
6413 /*-----------------------------------------------------------------*/
6414 /* AccLsh - left shift accumulator by known count */
6415 /*-----------------------------------------------------------------*/
6417 AccLsh (int shCount)
6422 emitcode ("add", "a,acc");
6423 else if (shCount == 2)
6425 emitcode ("add", "a,acc");
6426 emitcode ("add", "a,acc");
6430 /* rotate left accumulator */
6432 /* and kill the lower order bits */
6433 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6438 /*-----------------------------------------------------------------*/
6439 /* AccRsh - right shift accumulator by known count */
6440 /*-----------------------------------------------------------------*/
6442 AccRsh (int shCount)
6449 emitcode ("rrc", "a");
6453 /* rotate right accumulator */
6454 AccRol (8 - shCount);
6455 /* and kill the higher order bits */
6456 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6461 /*-----------------------------------------------------------------*/
6462 /* AccSRsh - signed right shift accumulator by known count */
6463 /*-----------------------------------------------------------------*/
6465 AccSRsh (int shCount)
6472 emitcode ("mov", "c,acc.7");
6473 emitcode ("rrc", "a");
6475 else if (shCount == 2)
6477 emitcode ("mov", "c,acc.7");
6478 emitcode ("rrc", "a");
6479 emitcode ("mov", "c,acc.7");
6480 emitcode ("rrc", "a");
6484 tlbl = newiTempLabel (NULL);
6485 /* rotate right accumulator */
6486 AccRol (8 - shCount);
6487 /* and kill the higher order bits */
6488 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6489 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6490 emitcode ("orl", "a,#0x%02x",
6491 (unsigned char) ~SRMask[shCount]);
6492 emitcode ("", "%05d$:", tlbl->key + 100);
6497 /*-----------------------------------------------------------------*/
6498 /* shiftR1Left2Result - shift right one byte from left to result */
6499 /*-----------------------------------------------------------------*/
6501 shiftR1Left2Result (operand * left, int offl,
6502 operand * result, int offr,
6503 int shCount, int sign)
6505 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6506 /* shift right accumulator */
6511 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6514 /*-----------------------------------------------------------------*/
6515 /* shiftL1Left2Result - shift left one byte from left to result */
6516 /*-----------------------------------------------------------------*/
6518 shiftL1Left2Result (operand * left, int offl,
6519 operand * result, int offr, int shCount)
6522 l = aopGet (AOP (left), offl, FALSE, FALSE);
6524 /* shift left accumulator */
6526 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6529 /*-----------------------------------------------------------------*/
6530 /* movLeft2Result - move byte from left to result */
6531 /*-----------------------------------------------------------------*/
6533 movLeft2Result (operand * left, int offl,
6534 operand * result, int offr, int sign)
6537 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6539 l = aopGet (AOP (left), offl, FALSE, FALSE);
6541 if (*l == '@' && (IS_AOP_PREG (result)))
6543 emitcode ("mov", "a,%s", l);
6544 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6549 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6552 /* MSB sign in acc.7 ! */
6553 if (getDataSize (left) == offl + 1)
6555 emitcode ("mov", "a,%s", l);
6556 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6563 /*-----------------------------------------------------------------*/
6564 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6565 /*-----------------------------------------------------------------*/
6569 emitcode ("rrc", "a");
6570 emitcode ("xch", "a,%s", x);
6571 emitcode ("rrc", "a");
6572 emitcode ("xch", "a,%s", x);
6575 /*-----------------------------------------------------------------*/
6576 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6577 /*-----------------------------------------------------------------*/
6581 emitcode ("xch", "a,%s", x);
6582 emitcode ("rlc", "a");
6583 emitcode ("xch", "a,%s", x);
6584 emitcode ("rlc", "a");
6587 /*-----------------------------------------------------------------*/
6588 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6589 /*-----------------------------------------------------------------*/
6593 emitcode ("xch", "a,%s", x);
6594 emitcode ("add", "a,acc");
6595 emitcode ("xch", "a,%s", x);
6596 emitcode ("rlc", "a");
6599 /*-----------------------------------------------------------------*/
6600 /* AccAXLsh - left shift a:x by known count (0..7) */
6601 /*-----------------------------------------------------------------*/
6603 AccAXLsh (char *x, int shCount)
6618 case 5: // AAAAABBB:CCCCCDDD
6620 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6622 emitcode ("anl", "a,#0x%02x",
6623 SLMask[shCount]); // BBB00000:CCCCCDDD
6625 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6627 AccRol (shCount); // DDDCCCCC:BBB00000
6629 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6631 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6633 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6635 emitcode ("anl", "a,#0x%02x",
6636 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6638 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6640 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6643 case 6: // AAAAAABB:CCCCCCDD
6644 emitcode ("anl", "a,#0x%02x",
6645 SRMask[shCount]); // 000000BB:CCCCCCDD
6646 emitcode ("mov", "c,acc.0"); // c = B
6647 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6649 AccAXRrl1 (x); // BCCCCCCD:D000000B
6650 AccAXRrl1 (x); // BBCCCCCC:DD000000
6652 emitcode("rrc","a");
6653 emitcode("xch","a,%s", x);
6654 emitcode("rrc","a");
6655 emitcode("mov","c,acc.0"); //<< get correct bit
6656 emitcode("xch","a,%s", x);
6658 emitcode("rrc","a");
6659 emitcode("xch","a,%s", x);
6660 emitcode("rrc","a");
6661 emitcode("xch","a,%s", x);
6664 case 7: // a:x <<= 7
6666 emitcode ("anl", "a,#0x%02x",
6667 SRMask[shCount]); // 0000000B:CCCCCCCD
6669 emitcode ("mov", "c,acc.0"); // c = B
6671 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6673 AccAXRrl1 (x); // BCCCCCCC:D0000000
6681 /*-----------------------------------------------------------------*/
6682 /* AccAXRsh - right shift a:x known count (0..7) */
6683 /*-----------------------------------------------------------------*/
6685 AccAXRsh (char *x, int shCount)
6693 AccAXRrl1 (x); // 0->a:x
6698 AccAXRrl1 (x); // 0->a:x
6701 AccAXRrl1 (x); // 0->a:x
6706 case 5: // AAAAABBB:CCCCCDDD = a:x
6708 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6710 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6712 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6714 emitcode ("anl", "a,#0x%02x",
6715 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6717 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6719 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6721 emitcode ("anl", "a,#0x%02x",
6722 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6724 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6726 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6728 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6731 case 6: // AABBBBBB:CCDDDDDD
6733 emitcode ("mov", "c,acc.7");
6734 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6736 emitcode ("mov", "c,acc.7");
6737 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6739 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6741 emitcode ("anl", "a,#0x%02x",
6742 SRMask[shCount]); // 000000AA:BBBBBBCC
6745 case 7: // ABBBBBBB:CDDDDDDD
6747 emitcode ("mov", "c,acc.7"); // c = A
6749 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6751 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6753 emitcode ("anl", "a,#0x%02x",
6754 SRMask[shCount]); // 0000000A:BBBBBBBC
6762 /*-----------------------------------------------------------------*/
6763 /* AccAXRshS - right shift signed a:x known count (0..7) */
6764 /*-----------------------------------------------------------------*/
6766 AccAXRshS (char *x, int shCount)
6774 emitcode ("mov", "c,acc.7");
6775 AccAXRrl1 (x); // s->a:x
6779 emitcode ("mov", "c,acc.7");
6780 AccAXRrl1 (x); // s->a:x
6782 emitcode ("mov", "c,acc.7");
6783 AccAXRrl1 (x); // s->a:x
6788 case 5: // AAAAABBB:CCCCCDDD = a:x
6790 tlbl = newiTempLabel (NULL);
6791 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6793 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6795 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6797 emitcode ("anl", "a,#0x%02x",
6798 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6800 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6802 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6804 emitcode ("anl", "a,#0x%02x",
6805 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6807 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6809 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6811 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6813 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6814 emitcode ("orl", "a,#0x%02x",
6815 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6817 emitcode ("", "%05d$:", tlbl->key + 100);
6818 break; // SSSSAAAA:BBBCCCCC
6820 case 6: // AABBBBBB:CCDDDDDD
6822 tlbl = newiTempLabel (NULL);
6823 emitcode ("mov", "c,acc.7");
6824 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6826 emitcode ("mov", "c,acc.7");
6827 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6829 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6831 emitcode ("anl", "a,#0x%02x",
6832 SRMask[shCount]); // 000000AA:BBBBBBCC
6834 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6835 emitcode ("orl", "a,#0x%02x",
6836 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6838 emitcode ("", "%05d$:", tlbl->key + 100);
6840 case 7: // ABBBBBBB:CDDDDDDD
6842 tlbl = newiTempLabel (NULL);
6843 emitcode ("mov", "c,acc.7"); // c = A
6845 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6847 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6849 emitcode ("anl", "a,#0x%02x",
6850 SRMask[shCount]); // 0000000A:BBBBBBBC
6852 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6853 emitcode ("orl", "a,#0x%02x",
6854 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6856 emitcode ("", "%05d$:", tlbl->key + 100);
6863 /*-----------------------------------------------------------------*/
6864 /* shiftL2Left2Result - shift left two bytes from left to result */
6865 /*-----------------------------------------------------------------*/
6867 shiftL2Left2Result (operand * left, int offl,
6868 operand * result, int offr, int shCount)
6870 if (sameRegs (AOP (result), AOP (left)) &&
6871 ((offl + MSB16) == offr))
6873 /* don't crash result[offr] */
6874 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6875 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6879 movLeft2Result (left, offl, result, offr, 0);
6880 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6882 /* ax << shCount (x = lsb(result)) */
6883 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6884 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6888 /*-----------------------------------------------------------------*/
6889 /* shiftR2Left2Result - shift right two bytes from left to result */
6890 /*-----------------------------------------------------------------*/
6892 shiftR2Left2Result (operand * left, int offl,
6893 operand * result, int offr,
6894 int shCount, int sign)
6896 if (sameRegs (AOP (result), AOP (left)) &&
6897 ((offl + MSB16) == offr))
6899 /* don't crash result[offr] */
6900 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6901 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6905 movLeft2Result (left, offl, result, offr, 0);
6906 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6908 /* a:x >> shCount (x = lsb(result)) */
6910 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6912 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6913 if (getDataSize (result) > 1)
6914 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6917 /*-----------------------------------------------------------------*/
6918 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6919 /*-----------------------------------------------------------------*/
6921 shiftLLeftOrResult (operand * left, int offl,
6922 operand * result, int offr, int shCount)
6924 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6925 /* shift left accumulator */
6927 /* or with result */
6928 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6929 /* back to result */
6930 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6933 /*-----------------------------------------------------------------*/
6934 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6935 /*-----------------------------------------------------------------*/
6937 shiftRLeftOrResult (operand * left, int offl,
6938 operand * result, int offr, int shCount)
6940 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6941 /* shift right accumulator */
6943 /* or with result */
6944 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6945 /* back to result */
6946 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6949 /*-----------------------------------------------------------------*/
6950 /* genlshOne - left shift a one byte quantity by known count */
6951 /*-----------------------------------------------------------------*/
6953 genlshOne (operand * result, operand * left, int shCount)
6955 D(emitcode ("; genlshOne",""));
6957 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6960 /*-----------------------------------------------------------------*/
6961 /* genlshTwo - left shift two bytes by known amount != 0 */
6962 /*-----------------------------------------------------------------*/
6964 genlshTwo (operand * result, operand * left, int shCount)
6968 D(emitcode ("; genlshTwo",""));
6970 size = getDataSize (result);
6972 /* if shCount >= 8 */
6980 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6982 movLeft2Result (left, LSB, result, MSB16, 0);
6984 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6987 /* 1 <= shCount <= 7 */
6991 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6993 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6997 /*-----------------------------------------------------------------*/
6998 /* shiftLLong - shift left one long from left to result */
6999 /* offl = LSB or MSB16 */
7000 /*-----------------------------------------------------------------*/
7002 shiftLLong (operand * left, operand * result, int offr)
7005 int size = AOP_SIZE (result);
7007 if (size >= LSB + offr)
7009 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7011 emitcode ("add", "a,acc");
7012 if (sameRegs (AOP (left), AOP (result)) &&
7013 size >= MSB16 + offr && offr != LSB)
7014 emitcode ("xch", "a,%s",
7015 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7017 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7020 if (size >= MSB16 + offr)
7022 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7024 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7027 emitcode ("rlc", "a");
7028 if (sameRegs (AOP (left), AOP (result)) &&
7029 size >= MSB24 + offr && offr != LSB)
7030 emitcode ("xch", "a,%s",
7031 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7033 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7036 if (size >= MSB24 + offr)
7038 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7040 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7043 emitcode ("rlc", "a");
7044 if (sameRegs (AOP (left), AOP (result)) &&
7045 size >= MSB32 + offr && offr != LSB)
7046 emitcode ("xch", "a,%s",
7047 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7049 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7052 if (size > MSB32 + offr)
7054 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7056 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7059 emitcode ("rlc", "a");
7060 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7063 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7066 /*-----------------------------------------------------------------*/
7067 /* genlshFour - shift four byte by a known amount != 0 */
7068 /*-----------------------------------------------------------------*/
7070 genlshFour (operand * result, operand * left, int shCount)
7074 D(emitcode ("; genlshFour",""));
7076 size = AOP_SIZE (result);
7078 /* if shifting more that 3 bytes */
7083 /* lowest order of left goes to the highest
7084 order of the destination */
7085 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7087 movLeft2Result (left, LSB, result, MSB32, 0);
7088 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7089 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7090 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7094 /* more than two bytes */
7095 else if (shCount >= 16)
7097 /* lower order two bytes goes to higher order two bytes */
7099 /* if some more remaining */
7101 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7104 movLeft2Result (left, MSB16, result, MSB32, 0);
7105 movLeft2Result (left, LSB, result, MSB24, 0);
7107 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7108 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7112 /* if more than 1 byte */
7113 else if (shCount >= 8)
7115 /* lower order three bytes goes to higher order three bytes */
7120 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7122 movLeft2Result (left, LSB, result, MSB16, 0);
7128 movLeft2Result (left, MSB24, result, MSB32, 0);
7129 movLeft2Result (left, MSB16, result, MSB24, 0);
7130 movLeft2Result (left, LSB, result, MSB16, 0);
7131 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7133 else if (shCount == 1)
7134 shiftLLong (left, result, MSB16);
7137 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7138 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7139 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7140 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7145 /* 1 <= shCount <= 7 */
7146 else if (shCount <= 2)
7148 shiftLLong (left, result, LSB);
7150 shiftLLong (result, result, LSB);
7152 /* 3 <= shCount <= 7, optimize */
7155 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7156 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7157 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7161 /*-----------------------------------------------------------------*/
7162 /* genLeftShiftLiteral - left shifting by known count */
7163 /*-----------------------------------------------------------------*/
7165 genLeftShiftLiteral (operand * left,
7170 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7173 D(emitcode ("; genLeftShiftLiteral",""));
7175 freeAsmop (right, NULL, ic, TRUE);
7177 aopOp (left, ic, FALSE);
7178 aopOp (result, ic, FALSE);
7180 size = getSize (operandType (result));
7183 emitcode ("; shift left ", "result %d, left %d", size,
7187 /* I suppose that the left size >= result size */
7192 movLeft2Result (left, size, result, size, 0);
7196 else if (shCount >= (size * 8))
7198 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7204 genlshOne (result, left, shCount);
7208 genlshTwo (result, left, shCount);
7212 genlshFour (result, left, shCount);
7215 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7216 "*** ack! mystery literal shift!\n");
7220 freeAsmop (left, NULL, ic, TRUE);
7221 freeAsmop (result, NULL, ic, TRUE);
7224 /*-----------------------------------------------------------------*/
7225 /* genLeftShift - generates code for left shifting */
7226 /*-----------------------------------------------------------------*/
7228 genLeftShift (iCode * ic)
7230 operand *left, *right, *result;
7233 symbol *tlbl, *tlbl1;
7235 D(emitcode ("; genLeftShift",""));
7237 right = IC_RIGHT (ic);
7238 left = IC_LEFT (ic);
7239 result = IC_RESULT (ic);
7241 aopOp (right, ic, FALSE);
7243 /* if the shift count is known then do it
7244 as efficiently as possible */
7245 if (AOP_TYPE (right) == AOP_LIT)
7247 genLeftShiftLiteral (left, right, result, ic);
7251 /* shift count is unknown then we have to form
7252 a loop get the loop count in B : Note: we take
7253 only the lower order byte since shifting
7254 more that 32 bits make no sense anyway, ( the
7255 largest size of an object can be only 32 bits ) */
7257 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7258 emitcode ("inc", "b");
7259 freeAsmop (right, NULL, ic, TRUE);
7260 aopOp (left, ic, FALSE);
7261 aopOp (result, ic, FALSE);
7263 /* now move the left to the result if they are not the
7265 if (!sameRegs (AOP (left), AOP (result)) &&
7266 AOP_SIZE (result) > 1)
7269 size = AOP_SIZE (result);
7273 l = aopGet (AOP (left), offset, FALSE, TRUE);
7274 if (*l == '@' && (IS_AOP_PREG (result)))
7277 emitcode ("mov", "a,%s", l);
7278 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7281 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7286 tlbl = newiTempLabel (NULL);
7287 size = AOP_SIZE (result);
7289 tlbl1 = newiTempLabel (NULL);
7291 /* if it is only one byte then */
7294 symbol *tlbl1 = newiTempLabel (NULL);
7296 l = aopGet (AOP (left), 0, FALSE, FALSE);
7298 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7299 emitcode ("", "%05d$:", tlbl->key + 100);
7300 emitcode ("add", "a,acc");
7301 emitcode ("", "%05d$:", tlbl1->key + 100);
7302 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7303 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7307 reAdjustPreg (AOP (result));
7309 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7310 emitcode ("", "%05d$:", tlbl->key + 100);
7311 l = aopGet (AOP (result), offset, FALSE, FALSE);
7313 emitcode ("add", "a,acc");
7314 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7317 l = aopGet (AOP (result), offset, FALSE, FALSE);
7319 emitcode ("rlc", "a");
7320 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7322 reAdjustPreg (AOP (result));
7324 emitcode ("", "%05d$:", tlbl1->key + 100);
7325 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7327 freeAsmop (left, NULL, ic, TRUE);
7328 freeAsmop (result, NULL, ic, TRUE);
7331 /*-----------------------------------------------------------------*/
7332 /* genrshOne - right shift a one byte quantity by known count */
7333 /*-----------------------------------------------------------------*/
7335 genrshOne (operand * result, operand * left,
7336 int shCount, int sign)
7338 D(emitcode ("; genrshOne",""));
7340 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7343 /*-----------------------------------------------------------------*/
7344 /* genrshTwo - right shift two bytes by known amount != 0 */
7345 /*-----------------------------------------------------------------*/
7347 genrshTwo (operand * result, operand * left,
7348 int shCount, int sign)
7350 D(emitcode ("; genrshTwo",""));
7352 /* if shCount >= 8 */
7357 shiftR1Left2Result (left, MSB16, result, LSB,
7360 movLeft2Result (left, MSB16, result, LSB, sign);
7361 addSign (result, MSB16, sign);
7364 /* 1 <= shCount <= 7 */
7366 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7369 /*-----------------------------------------------------------------*/
7370 /* shiftRLong - shift right one long from left to result */
7371 /* offl = LSB or MSB16 */
7372 /*-----------------------------------------------------------------*/
7374 shiftRLong (operand * left, int offl,
7375 operand * result, int sign)
7377 int isSameRegs=sameRegs(AOP(left),AOP(result));
7379 if (isSameRegs && offl>1) {
7380 // we are in big trouble, but this shouldn't happen
7381 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7384 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7389 emitcode ("rlc", "a");
7390 emitcode ("subb", "a,acc");
7392 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7394 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7395 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7398 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7403 emitcode ("clr", "c");
7405 emitcode ("mov", "c,acc.7");
7408 emitcode ("rrc", "a");
7410 if (isSameRegs && offl==MSB16) {
7411 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7413 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7414 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7417 emitcode ("rrc", "a");
7418 if (isSameRegs && offl==1) {
7419 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7421 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7422 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7424 emitcode ("rrc", "a");
7425 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7429 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7430 emitcode ("rrc", "a");
7431 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7435 /*-----------------------------------------------------------------*/
7436 /* genrshFour - shift four byte by a known amount != 0 */
7437 /*-----------------------------------------------------------------*/
7439 genrshFour (operand * result, operand * left,
7440 int shCount, int sign)
7442 D(emitcode ("; genrshFour",""));
7444 /* if shifting more that 3 bytes */
7449 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7451 movLeft2Result (left, MSB32, result, LSB, sign);
7452 addSign (result, MSB16, sign);
7454 else if (shCount >= 16)
7458 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7461 movLeft2Result (left, MSB24, result, LSB, 0);
7462 movLeft2Result (left, MSB32, result, MSB16, sign);
7464 addSign (result, MSB24, sign);
7466 else if (shCount >= 8)
7470 shiftRLong (left, MSB16, result, sign);
7471 else if (shCount == 0)
7473 movLeft2Result (left, MSB16, result, LSB, 0);
7474 movLeft2Result (left, MSB24, result, MSB16, 0);
7475 movLeft2Result (left, MSB32, result, MSB24, sign);
7476 addSign (result, MSB32, sign);
7480 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7481 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7482 /* the last shift is signed */
7483 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7484 addSign (result, MSB32, sign);
7488 { /* 1 <= shCount <= 7 */
7491 shiftRLong (left, LSB, result, sign);
7493 shiftRLong (result, LSB, result, sign);
7497 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7498 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7499 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7504 /*-----------------------------------------------------------------*/
7505 /* genRightShiftLiteral - right shifting by known count */
7506 /*-----------------------------------------------------------------*/
7508 genRightShiftLiteral (operand * left,
7514 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7517 D(emitcode ("; genRightShiftLiteral",""));
7519 freeAsmop (right, NULL, ic, TRUE);
7521 aopOp (left, ic, FALSE);
7522 aopOp (result, ic, FALSE);
7525 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7529 size = getDataSize (left);
7530 /* test the LEFT size !!! */
7532 /* I suppose that the left size >= result size */
7535 size = getDataSize (result);
7537 movLeft2Result (left, size, result, size, 0);
7540 else if (shCount >= (size * 8))
7543 /* get sign in acc.7 */
7544 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7546 addSign (result, LSB, sign);
7553 genrshOne (result, left, shCount, sign);
7557 genrshTwo (result, left, shCount, sign);
7561 genrshFour (result, left, shCount, sign);
7567 freeAsmop (left, NULL, ic, TRUE);
7568 freeAsmop (result, NULL, ic, TRUE);
7571 /*-----------------------------------------------------------------*/
7572 /* genSignedRightShift - right shift of signed number */
7573 /*-----------------------------------------------------------------*/
7575 genSignedRightShift (iCode * ic)
7577 operand *right, *left, *result;
7580 symbol *tlbl, *tlbl1;
7582 D(emitcode ("; genSignedRightShift",""));
7584 /* we do it the hard way put the shift count in b
7585 and loop thru preserving the sign */
7587 right = IC_RIGHT (ic);
7588 left = IC_LEFT (ic);
7589 result = IC_RESULT (ic);
7591 aopOp (right, ic, FALSE);
7594 if (AOP_TYPE (right) == AOP_LIT)
7596 genRightShiftLiteral (left, right, result, ic, 1);
7599 /* shift count is unknown then we have to form
7600 a loop get the loop count in B : Note: we take
7601 only the lower order byte since shifting
7602 more that 32 bits make no sense anyway, ( the
7603 largest size of an object can be only 32 bits ) */
7605 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7606 emitcode ("inc", "b");
7607 freeAsmop (right, NULL, ic, TRUE);
7608 aopOp (left, ic, FALSE);
7609 aopOp (result, ic, FALSE);
7611 /* now move the left to the result if they are not the
7613 if (!sameRegs (AOP (left), AOP (result)) &&
7614 AOP_SIZE (result) > 1)
7617 size = AOP_SIZE (result);
7621 l = aopGet (AOP (left), offset, FALSE, TRUE);
7622 if (*l == '@' && IS_AOP_PREG (result))
7625 emitcode ("mov", "a,%s", l);
7626 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7629 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7634 /* mov the highest order bit to OVR */
7635 tlbl = newiTempLabel (NULL);
7636 tlbl1 = newiTempLabel (NULL);
7638 size = AOP_SIZE (result);
7640 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7641 emitcode ("rlc", "a");
7642 emitcode ("mov", "ov,c");
7643 /* if it is only one byte then */
7646 l = aopGet (AOP (left), 0, FALSE, FALSE);
7648 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7649 emitcode ("", "%05d$:", tlbl->key + 100);
7650 emitcode ("mov", "c,ov");
7651 emitcode ("rrc", "a");
7652 emitcode ("", "%05d$:", tlbl1->key + 100);
7653 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7654 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7658 reAdjustPreg (AOP (result));
7659 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7660 emitcode ("", "%05d$:", tlbl->key + 100);
7661 emitcode ("mov", "c,ov");
7664 l = aopGet (AOP (result), offset, FALSE, FALSE);
7666 emitcode ("rrc", "a");
7667 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7669 reAdjustPreg (AOP (result));
7670 emitcode ("", "%05d$:", tlbl1->key + 100);
7671 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7674 freeAsmop (left, NULL, ic, TRUE);
7675 freeAsmop (result, NULL, ic, TRUE);
7678 /*-----------------------------------------------------------------*/
7679 /* genRightShift - generate code for right shifting */
7680 /*-----------------------------------------------------------------*/
7682 genRightShift (iCode * ic)
7684 operand *right, *left, *result;
7688 symbol *tlbl, *tlbl1;
7690 D(emitcode ("; genRightShift",""));
7692 /* if signed then we do it the hard way preserve the
7693 sign bit moving it inwards */
7694 letype = getSpec (operandType (IC_LEFT (ic)));
7696 if (!SPEC_USIGN (letype))
7698 genSignedRightShift (ic);
7702 /* signed & unsigned types are treated the same : i.e. the
7703 signed is NOT propagated inwards : quoting from the
7704 ANSI - standard : "for E1 >> E2, is equivalent to division
7705 by 2**E2 if unsigned or if it has a non-negative value,
7706 otherwise the result is implementation defined ", MY definition
7707 is that the sign does not get propagated */
7709 right = IC_RIGHT (ic);
7710 left = IC_LEFT (ic);
7711 result = IC_RESULT (ic);
7713 aopOp (right, ic, FALSE);
7715 /* if the shift count is known then do it
7716 as efficiently as possible */
7717 if (AOP_TYPE (right) == AOP_LIT)
7719 genRightShiftLiteral (left, right, result, ic, 0);
7723 /* shift count is unknown then we have to form
7724 a loop get the loop count in B : Note: we take
7725 only the lower order byte since shifting
7726 more that 32 bits make no sense anyway, ( the
7727 largest size of an object can be only 32 bits ) */
7729 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7730 emitcode ("inc", "b");
7731 freeAsmop (right, NULL, ic, TRUE);
7732 aopOp (left, ic, FALSE);
7733 aopOp (result, ic, FALSE);
7735 /* now move the left to the result if they are not the
7737 if (!sameRegs (AOP (left), AOP (result)) &&
7738 AOP_SIZE (result) > 1)
7741 size = AOP_SIZE (result);
7745 l = aopGet (AOP (left), offset, FALSE, TRUE);
7746 if (*l == '@' && IS_AOP_PREG (result))
7749 emitcode ("mov", "a,%s", l);
7750 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7753 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7758 tlbl = newiTempLabel (NULL);
7759 tlbl1 = newiTempLabel (NULL);
7760 size = AOP_SIZE (result);
7763 /* if it is only one byte then */
7766 l = aopGet (AOP (left), 0, FALSE, FALSE);
7768 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7769 emitcode ("", "%05d$:", tlbl->key + 100);
7771 emitcode ("rrc", "a");
7772 emitcode ("", "%05d$:", tlbl1->key + 100);
7773 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7774 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7778 reAdjustPreg (AOP (result));
7779 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7780 emitcode ("", "%05d$:", tlbl->key + 100);
7784 l = aopGet (AOP (result), offset, FALSE, FALSE);
7786 emitcode ("rrc", "a");
7787 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7789 reAdjustPreg (AOP (result));
7791 emitcode ("", "%05d$:", tlbl1->key + 100);
7792 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7795 freeAsmop (left, NULL, ic, TRUE);
7796 freeAsmop (result, NULL, ic, TRUE);
7799 /*-----------------------------------------------------------------*/
7800 /* emitPtrByteGet - emits code to get a byte into A through a */
7801 /* pointer register (R0, R1, or DPTR). The */
7802 /* original value of A can be preserved in B. */
7803 /*-----------------------------------------------------------------*/
7805 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7812 emitcode ("mov", "b,a");
7813 emitcode ("mov", "a,@%s", rname);
7818 emitcode ("mov", "b,a");
7819 emitcode ("movx", "a,@%s", rname);
7824 emitcode ("mov", "b,a");
7825 emitcode ("movx", "a,@dptr");
7830 emitcode ("mov", "b,a");
7831 emitcode ("clr", "a");
7832 emitcode ("movc", "a,@a+dptr");
7838 emitcode ("push", "b");
7839 emitcode ("push", "acc");
7841 emitcode ("lcall", "__gptrget");
7843 emitcode ("pop", "b");
7848 /*-----------------------------------------------------------------*/
7849 /* emitPtrByteSet - emits code to set a byte from src through a */
7850 /* pointer register (R0, R1, or DPTR). */
7851 /*-----------------------------------------------------------------*/
7853 emitPtrByteSet (char *rname, int p_type, char *src)
7862 emitcode ("mov", "@%s,a", rname);
7865 emitcode ("mov", "@%s,%s", rname, src);
7870 emitcode ("movx", "@%s,a", rname);
7875 emitcode ("movx", "@dptr,a");
7880 emitcode ("lcall", "__gptrput");
7885 /*-----------------------------------------------------------------*/
7886 /* genUnpackBits - generates code for unpacking bits */
7887 /*-----------------------------------------------------------------*/
7889 genUnpackBits (operand * result, char *rname, int ptype)
7891 int offset = 0; /* result byte offset */
7892 int rsize; /* result size */
7893 int rlen = 0; /* remaining bitfield length */
7894 sym_link *etype; /* bitfield type information */
7895 int blen; /* bitfield length */
7896 int bstr; /* bitfield starting bit within byte */
7898 D(emitcode ("; genUnpackBits",""));
7900 etype = getSpec (operandType (result));
7901 rsize = getSize (operandType (result));
7902 blen = SPEC_BLEN (etype);
7903 bstr = SPEC_BSTR (etype);
7905 /* If the bitfield length is less than a byte */
7908 emitPtrByteGet (rname, ptype, FALSE);
7910 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7911 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7915 /* Bit field did not fit in a byte. Copy all
7916 but the partial byte at the end. */
7917 for (rlen=blen;rlen>=8;rlen-=8)
7919 emitPtrByteGet (rname, ptype, FALSE);
7920 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7922 emitcode ("inc", "%s", rname);
7925 /* Handle the partial byte at the end */
7928 emitPtrByteGet (rname, ptype, FALSE);
7929 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7930 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7938 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7943 /*-----------------------------------------------------------------*/
7944 /* genDataPointerGet - generates code when ptr offset is known */
7945 /*-----------------------------------------------------------------*/
7947 genDataPointerGet (operand * left,
7953 int size, offset = 0;
7955 D(emitcode ("; genDataPointerGet",""));
7957 aopOp (result, ic, TRUE);
7959 /* get the string representation of the name */
7960 l = aopGet (AOP (left), 0, FALSE, TRUE);
7961 size = AOP_SIZE (result);
7965 sprintf (buffer, "(%s + %d)", l + 1, offset);
7967 sprintf (buffer, "%s", l + 1);
7968 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7971 freeAsmop (left, NULL, ic, TRUE);
7972 freeAsmop (result, NULL, ic, TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genNearPointerGet - emitcode for near pointer fetch */
7977 /*-----------------------------------------------------------------*/
7979 genNearPointerGet (operand * left,
7987 sym_link *rtype, *retype;
7988 sym_link *ltype = operandType (left);
7991 D(emitcode ("; genNearPointerGet",""));
7993 rtype = operandType (result);
7994 retype = getSpec (rtype);
7996 aopOp (left, ic, FALSE);
7998 /* if left is rematerialisable and
7999 result is not bitfield variable type and
8000 the left is pointer to data space i.e
8001 lower 128 bytes of space */
8002 if (AOP_TYPE (left) == AOP_IMMD &&
8003 !IS_BITFIELD (retype) &&
8004 DCL_TYPE (ltype) == POINTER)
8006 genDataPointerGet (left, result, ic);
8010 /* if the value is already in a pointer register
8011 then don't need anything more */
8012 if (!AOP_INPREG (AOP (left)))
8014 if (IS_AOP_PREG (left))
8016 // Aha, it is a pointer, just in disguise.
8017 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8020 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8021 __FILE__, __LINE__);
8026 emitcode ("mov", "a%s,%s", rname + 1, rname);
8027 rname++; // skip the '@'.
8032 /* otherwise get a free pointer register */
8034 preg = getFreePtr (ic, &aop, FALSE);
8035 emitcode ("mov", "%s,%s",
8037 aopGet (AOP (left), 0, FALSE, TRUE));
8042 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8044 //aopOp (result, ic, FALSE);
8045 aopOp (result, ic, result?TRUE:FALSE);
8047 /* if bitfield then unpack the bits */
8048 if (IS_BITFIELD (retype))
8049 genUnpackBits (result, rname, POINTER);
8052 /* we have can just get the values */
8053 int size = AOP_SIZE (result);
8058 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8061 emitcode ("mov", "a,@%s", rname);
8062 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8066 sprintf (buffer, "@%s", rname);
8067 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8071 emitcode ("inc", "%s", rname);
8075 /* now some housekeeping stuff */
8076 if (aop) /* we had to allocate for this iCode */
8078 if (pi) { /* post increment present */
8079 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8081 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8085 /* we did not allocate which means left
8086 already in a pointer register, then
8087 if size > 0 && this could be used again
8088 we have to point it back to where it
8090 if ((AOP_SIZE (result) > 1 &&
8091 !OP_SYMBOL (left)->remat &&
8092 (OP_SYMBOL (left)->liveTo > ic->seq ||
8096 int size = AOP_SIZE (result) - 1;
8098 emitcode ("dec", "%s", rname);
8103 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8104 freeAsmop (left, NULL, ic, TRUE);
8105 if (pi) pi->generated = 1;
8108 /*-----------------------------------------------------------------*/
8109 /* genPagedPointerGet - emitcode for paged pointer fetch */
8110 /*-----------------------------------------------------------------*/
8112 genPagedPointerGet (operand * left,
8120 sym_link *rtype, *retype;
8122 D(emitcode ("; genPagedPointerGet",""));
8124 rtype = operandType (result);
8125 retype = getSpec (rtype);
8127 aopOp (left, ic, FALSE);
8129 /* if the value is already in a pointer register
8130 then don't need anything more */
8131 if (!AOP_INPREG (AOP (left)))
8133 /* otherwise get a free pointer register */
8135 preg = getFreePtr (ic, &aop, FALSE);
8136 emitcode ("mov", "%s,%s",
8138 aopGet (AOP (left), 0, FALSE, TRUE));
8142 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8144 aopOp (result, ic, FALSE);
8146 /* if bitfield then unpack the bits */
8147 if (IS_BITFIELD (retype))
8148 genUnpackBits (result, rname, PPOINTER);
8151 /* we have can just get the values */
8152 int size = AOP_SIZE (result);
8158 emitcode ("movx", "a,@%s", rname);
8159 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8164 emitcode ("inc", "%s", rname);
8168 /* now some housekeeping stuff */
8169 if (aop) /* we had to allocate for this iCode */
8171 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8172 freeAsmop (NULL, aop, ic, TRUE);
8176 /* we did not allocate which means left
8177 already in a pointer register, then
8178 if size > 0 && this could be used again
8179 we have to point it back to where it
8181 if ((AOP_SIZE (result) > 1 &&
8182 !OP_SYMBOL (left)->remat &&
8183 (OP_SYMBOL (left)->liveTo > ic->seq ||
8187 int size = AOP_SIZE (result) - 1;
8189 emitcode ("dec", "%s", rname);
8194 freeAsmop (left, NULL, ic, TRUE);
8195 freeAsmop (result, NULL, ic, TRUE);
8196 if (pi) pi->generated = 1;
8200 /*--------------------------------------------------------------------*/
8201 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8202 /*--------------------------------------------------------------------*/
8204 loadDptrFromOperand (operand *op, bool loadBToo)
8206 if (AOP_TYPE (op) != AOP_STR)
8208 /* if this is remateriazable */
8209 if (AOP_TYPE (op) == AOP_IMMD)
8211 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8214 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8215 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8218 wassertl(FALSE, "need pointerCode");
8219 emitcode ("", "; mov b,???");
8220 /* genPointerGet and genPointerSet originally did different
8221 ** things for this case. Both seem wrong.
8222 ** from genPointerGet:
8223 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8224 ** from genPointerSet:
8225 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8230 else if (AOP_TYPE (op) == AOP_DPTR)
8234 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8235 emitcode ("push", "acc");
8236 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8237 emitcode ("push", "acc");
8238 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8239 emitcode ("pop", "dph");
8240 emitcode ("pop", "dpl");
8244 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8245 emitcode ("push", "acc");
8246 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8247 emitcode ("pop", "dpl");
8251 { /* we need to get it byte by byte */
8252 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8253 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8255 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8260 /*-----------------------------------------------------------------*/
8261 /* genFarPointerGet - gget value from far space */
8262 /*-----------------------------------------------------------------*/
8264 genFarPointerGet (operand * left,
8265 operand * result, iCode * ic, iCode * pi)
8268 sym_link *retype = getSpec (operandType (result));
8270 D(emitcode ("; genFarPointerGet",""));
8272 aopOp (left, ic, FALSE);
8273 loadDptrFromOperand (left, FALSE);
8275 /* so dptr now contains the address */
8276 aopOp (result, ic, FALSE);
8278 /* if bit then unpack */
8279 if (IS_BITFIELD (retype))
8280 genUnpackBits (result, "dptr", FPOINTER);
8283 size = AOP_SIZE (result);
8288 emitcode ("movx", "a,@dptr");
8289 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8291 emitcode ("inc", "dptr");
8295 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8296 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8297 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8300 freeAsmop (left, NULL, ic, TRUE);
8301 freeAsmop (result, NULL, ic, TRUE);
8304 /*-----------------------------------------------------------------*/
8305 /* genCodePointerGet - gget value from code space */
8306 /*-----------------------------------------------------------------*/
8308 genCodePointerGet (operand * left,
8309 operand * result, iCode * ic, iCode *pi)
8312 sym_link *retype = getSpec (operandType (result));
8314 D(emitcode ("; genCodePointerGet",""));
8316 aopOp (left, ic, FALSE);
8317 loadDptrFromOperand (left, FALSE);
8319 /* so dptr now contains the address */
8320 aopOp (result, ic, FALSE);
8322 /* if bit then unpack */
8323 if (IS_BITFIELD (retype))
8324 genUnpackBits (result, "dptr", CPOINTER);
8327 size = AOP_SIZE (result);
8334 emitcode ("clr", "a");
8335 emitcode ("movc", "a,@a+dptr");
8336 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8337 emitcode ("inc", "dptr");
8341 emitcode ("mov", "a,#0x%02x", offset);
8342 emitcode ("movc", "a,@a+dptr");
8343 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8348 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8349 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8350 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8353 freeAsmop (left, NULL, ic, TRUE);
8354 freeAsmop (result, NULL, ic, TRUE);
8357 /*-----------------------------------------------------------------*/
8358 /* genGenPointerGet - gget value from generic pointer space */
8359 /*-----------------------------------------------------------------*/
8361 genGenPointerGet (operand * left,
8362 operand * result, iCode * ic, iCode *pi)
8365 sym_link *retype = getSpec (operandType (result));
8367 D(emitcode ("; genGenPointerGet",""));
8369 aopOp (left, ic, FALSE);
8370 loadDptrFromOperand (left, TRUE);
8372 /* so dptr know contains the address */
8373 aopOp (result, ic, FALSE);
8375 /* if bit then unpack */
8376 if (IS_BITFIELD (retype))
8377 genUnpackBits (result, "dptr", GPOINTER);
8380 size = AOP_SIZE (result);
8385 emitcode ("lcall", "__gptrget");
8386 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8388 emitcode ("inc", "dptr");
8392 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8393 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8394 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8397 freeAsmop (left, NULL, ic, TRUE);
8398 freeAsmop (result, NULL, ic, TRUE);
8401 /*-----------------------------------------------------------------*/
8402 /* genPointerGet - generate code for pointer get */
8403 /*-----------------------------------------------------------------*/
8405 genPointerGet (iCode * ic, iCode *pi)
8407 operand *left, *result;
8408 sym_link *type, *etype;
8411 D(emitcode ("; genPointerGet",""));
8413 left = IC_LEFT (ic);
8414 result = IC_RESULT (ic);
8416 /* depending on the type of pointer we need to
8417 move it to the correct pointer register */
8418 type = operandType (left);
8419 etype = getSpec (type);
8420 /* if left is of type of pointer then it is simple */
8421 if (IS_PTR (type) && !IS_FUNC (type->next))
8422 p_type = DCL_TYPE (type);
8425 /* we have to go by the storage class */
8426 p_type = PTR_TYPE (SPEC_OCLS (etype));
8429 /* special case when cast remat */
8430 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8431 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8432 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8433 type = operandType (left);
8434 p_type = DCL_TYPE (type);
8436 /* now that we have the pointer type we assign
8437 the pointer values */
8443 genNearPointerGet (left, result, ic, pi);
8447 genPagedPointerGet (left, result, ic, pi);
8451 genFarPointerGet (left, result, ic, pi);
8455 genCodePointerGet (left, result, ic, pi);
8459 genGenPointerGet (left, result, ic, pi);
8467 /*-----------------------------------------------------------------*/
8468 /* genPackBits - generates code for packed bit storage */
8469 /*-----------------------------------------------------------------*/
8471 genPackBits (sym_link * etype,
8473 char *rname, int p_type)
8475 int offset = 0; /* source byte offset */
8476 int rlen = 0; /* remaining bitfield length */
8477 int blen; /* bitfield length */
8478 int bstr; /* bitfield starting bit within byte */
8479 int litval; /* source literal value (if AOP_LIT) */
8480 unsigned char mask; /* bitmask within current byte */
8482 D(emitcode ("; genPackBits",""));
8484 blen = SPEC_BLEN (etype);
8485 bstr = SPEC_BSTR (etype);
8487 /* If the bitfield length is less than a byte */
8490 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8491 (unsigned char) (0xFF >> (8 - bstr)));
8493 if (AOP_TYPE (right) == AOP_LIT)
8495 /* Case with a bitfield length <8 and literal source
8497 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8499 litval &= (~mask) & 0xff;
8500 emitPtrByteGet (rname, p_type, FALSE);
8501 if ((mask|litval)!=0xff)
8502 emitcode ("anl","a,#0x%02x", mask);
8504 emitcode ("orl","a,#0x%02x", litval);
8508 if ((blen==1) && (p_type!=GPOINTER))
8510 /* Case with a bitfield length == 1 and no generic pointer
8512 if (AOP_TYPE (right) == AOP_CRY)
8513 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8516 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8517 emitcode ("rrc","a");
8519 emitPtrByteGet (rname, p_type, FALSE);
8520 emitcode ("mov","acc.%d,c",bstr);
8524 /* Case with a bitfield length < 8 and arbitrary source
8526 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8527 /* shift and mask source value */
8529 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8531 /* transfer A to B and get next byte */
8532 emitPtrByteGet (rname, p_type, TRUE);
8534 emitcode ("anl", "a,#0x%02x", mask);
8535 emitcode ("orl", "a,b");
8536 if (p_type == GPOINTER)
8537 emitcode ("pop", "b");
8541 emitPtrByteSet (rname, p_type, "a");
8545 /* Bit length is greater than 7 bits. In this case, copy */
8546 /* all except the partial byte at the end */
8547 for (rlen=blen;rlen>=8;rlen-=8)
8549 emitPtrByteSet (rname, p_type,
8550 aopGet (AOP (right), offset++, FALSE, TRUE) );
8552 emitcode ("inc", "%s", rname);
8555 /* If there was a partial byte at the end */
8558 mask = (((unsigned char) -1 << rlen) & 0xff);
8560 if (AOP_TYPE (right) == AOP_LIT)
8562 /* Case with partial byte and literal source
8564 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8565 litval >>= (blen-rlen);
8566 litval &= (~mask) & 0xff;
8567 emitPtrByteGet (rname, p_type, FALSE);
8568 if ((mask|litval)!=0xff)
8569 emitcode ("anl","a,#0x%02x", mask);
8571 emitcode ("orl","a,#0x%02x", litval);
8575 /* Case with partial byte and arbitrary source
8577 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8578 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8580 /* transfer A to B and get next byte */
8581 emitPtrByteGet (rname, p_type, TRUE);
8583 emitcode ("anl", "a,#0x%02x", mask);
8584 emitcode ("orl", "a,b");
8585 if (p_type == GPOINTER)
8586 emitcode ("pop", "b");
8588 emitPtrByteSet (rname, p_type, "a");
8594 /*-----------------------------------------------------------------*/
8595 /* genDataPointerSet - remat pointer to data space */
8596 /*-----------------------------------------------------------------*/
8598 genDataPointerSet (operand * right,
8602 int size, offset = 0;
8603 char *l, buffer[256];
8605 D(emitcode ("; genDataPointerSet",""));
8607 aopOp (right, ic, FALSE);
8609 l = aopGet (AOP (result), 0, FALSE, TRUE);
8610 size = AOP_SIZE (right);
8614 sprintf (buffer, "(%s + %d)", l + 1, offset);
8616 sprintf (buffer, "%s", l + 1);
8617 emitcode ("mov", "%s,%s", buffer,
8618 aopGet (AOP (right), offset++, FALSE, FALSE));
8621 freeAsmop (right, NULL, ic, TRUE);
8622 freeAsmop (result, NULL, ic, TRUE);
8625 /*-----------------------------------------------------------------*/
8626 /* genNearPointerSet - emitcode for near pointer put */
8627 /*-----------------------------------------------------------------*/
8629 genNearPointerSet (operand * right,
8637 sym_link *retype, *letype;
8638 sym_link *ptype = operandType (result);
8640 D(emitcode ("; genNearPointerSet",""));
8642 retype = getSpec (operandType (right));
8643 letype = getSpec (ptype);
8644 aopOp (result, ic, FALSE);
8646 /* if the result is rematerializable &
8647 in data space & not a bit variable */
8648 if (AOP_TYPE (result) == AOP_IMMD &&
8649 DCL_TYPE (ptype) == POINTER &&
8650 !IS_BITVAR (retype) &&
8651 !IS_BITVAR (letype))
8653 genDataPointerSet (right, result, ic);
8657 /* if the value is already in a pointer register
8658 then don't need anything more */
8659 if (!AOP_INPREG (AOP (result)))
8662 //AOP_TYPE (result) == AOP_STK
8666 // Aha, it is a pointer, just in disguise.
8667 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8670 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8671 __FILE__, __LINE__);
8676 emitcode ("mov", "a%s,%s", rname + 1, rname);
8677 rname++; // skip the '@'.
8682 /* otherwise get a free pointer register */
8684 preg = getFreePtr (ic, &aop, FALSE);
8685 emitcode ("mov", "%s,%s",
8687 aopGet (AOP (result), 0, FALSE, TRUE));
8693 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8696 aopOp (right, ic, FALSE);
8698 /* if bitfield then unpack the bits */
8699 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8700 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8703 /* we have can just get the values */
8704 int size = AOP_SIZE (right);
8709 l = aopGet (AOP (right), offset, FALSE, TRUE);
8713 emitcode ("mov", "@%s,a", rname);
8716 emitcode ("mov", "@%s,%s", rname, l);
8718 emitcode ("inc", "%s", rname);
8723 /* now some housekeeping stuff */
8724 if (aop) /* we had to allocate for this iCode */
8727 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8728 freeAsmop (NULL, aop, ic, TRUE);
8732 /* we did not allocate which means left
8733 already in a pointer register, then
8734 if size > 0 && this could be used again
8735 we have to point it back to where it
8737 if ((AOP_SIZE (right) > 1 &&
8738 !OP_SYMBOL (result)->remat &&
8739 (OP_SYMBOL (result)->liveTo > ic->seq ||
8743 int size = AOP_SIZE (right) - 1;
8745 emitcode ("dec", "%s", rname);
8750 if (pi) pi->generated = 1;
8751 freeAsmop (result, NULL, ic, TRUE);
8752 freeAsmop (right, NULL, ic, TRUE);
8755 /*-----------------------------------------------------------------*/
8756 /* genPagedPointerSet - emitcode for Paged pointer put */
8757 /*-----------------------------------------------------------------*/
8759 genPagedPointerSet (operand * right,
8767 sym_link *retype, *letype;
8769 D(emitcode ("; genPagedPointerSet",""));
8771 retype = getSpec (operandType (right));
8772 letype = getSpec (operandType (result));
8774 aopOp (result, ic, FALSE);
8776 /* if the value is already in a pointer register
8777 then don't need anything more */
8778 if (!AOP_INPREG (AOP (result)))
8780 /* otherwise get a free pointer register */
8782 preg = getFreePtr (ic, &aop, FALSE);
8783 emitcode ("mov", "%s,%s",
8785 aopGet (AOP (result), 0, FALSE, TRUE));
8789 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8791 aopOp (right, ic, FALSE);
8793 /* if bitfield then unpack the bits */
8794 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8795 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8798 /* we have can just get the values */
8799 int size = AOP_SIZE (right);
8804 l = aopGet (AOP (right), offset, FALSE, TRUE);
8807 emitcode ("movx", "@%s,a", rname);
8810 emitcode ("inc", "%s", rname);
8816 /* now some housekeeping stuff */
8817 if (aop) /* we had to allocate for this iCode */
8820 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8821 freeAsmop (NULL, aop, ic, TRUE);
8825 /* we did not allocate which means left
8826 already in a pointer register, then
8827 if size > 0 && this could be used again
8828 we have to point it back to where it
8830 if (AOP_SIZE (right) > 1 &&
8831 !OP_SYMBOL (result)->remat &&
8832 (OP_SYMBOL (result)->liveTo > ic->seq ||
8835 int size = AOP_SIZE (right) - 1;
8837 emitcode ("dec", "%s", rname);
8842 if (pi) pi->generated = 1;
8843 freeAsmop (result, NULL, ic, TRUE);
8844 freeAsmop (right, NULL, ic, TRUE);
8849 /*-----------------------------------------------------------------*/
8850 /* genFarPointerSet - set value from far space */
8851 /*-----------------------------------------------------------------*/
8853 genFarPointerSet (operand * right,
8854 operand * result, iCode * ic, iCode * pi)
8857 sym_link *retype = getSpec (operandType (right));
8858 sym_link *letype = getSpec (operandType (result));
8860 D(emitcode ("; genFarPointerSet",""));
8862 aopOp (result, ic, FALSE);
8863 loadDptrFromOperand (result, FALSE);
8865 /* so dptr know contains the address */
8866 aopOp (right, ic, FALSE);
8868 /* if bit then unpack */
8869 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8870 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8873 size = AOP_SIZE (right);
8878 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8880 emitcode ("movx", "@dptr,a");
8882 emitcode ("inc", "dptr");
8885 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8886 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8887 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8890 freeAsmop (result, NULL, ic, TRUE);
8891 freeAsmop (right, NULL, ic, TRUE);
8894 /*-----------------------------------------------------------------*/
8895 /* genGenPointerSet - set value from generic pointer space */
8896 /*-----------------------------------------------------------------*/
8898 genGenPointerSet (operand * right,
8899 operand * result, iCode * ic, iCode * pi)
8902 sym_link *retype = getSpec (operandType (right));
8903 sym_link *letype = getSpec (operandType (result));
8905 D(emitcode ("; genGenPointerSet",""));
8907 aopOp (result, ic, FALSE);
8908 loadDptrFromOperand (result, TRUE);
8910 /* so dptr know contains the address */
8911 aopOp (right, ic, FALSE);
8913 /* if bit then unpack */
8914 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8915 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
8918 size = AOP_SIZE (right);
8923 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8925 emitcode ("lcall", "__gptrput");
8927 emitcode ("inc", "dptr");
8931 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8932 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8933 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8936 freeAsmop (result, NULL, ic, TRUE);
8937 freeAsmop (right, NULL, ic, TRUE);
8940 /*-----------------------------------------------------------------*/
8941 /* genPointerSet - stores the value into a pointer location */
8942 /*-----------------------------------------------------------------*/
8944 genPointerSet (iCode * ic, iCode *pi)
8946 operand *right, *result;
8947 sym_link *type, *etype;
8950 D(emitcode ("; genPointerSet",""));
8952 right = IC_RIGHT (ic);
8953 result = IC_RESULT (ic);
8955 /* depending on the type of pointer we need to
8956 move it to the correct pointer register */
8957 type = operandType (result);
8958 etype = getSpec (type);
8959 /* if left is of type of pointer then it is simple */
8960 if (IS_PTR (type) && !IS_FUNC (type->next))
8962 p_type = DCL_TYPE (type);
8966 /* we have to go by the storage class */
8967 p_type = PTR_TYPE (SPEC_OCLS (etype));
8970 /* special case when cast remat */
8971 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8972 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8973 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8974 type = operandType (result);
8975 p_type = DCL_TYPE (type);
8977 /* now that we have the pointer type we assign
8978 the pointer values */
8984 genNearPointerSet (right, result, ic, pi);
8988 genPagedPointerSet (right, result, ic, pi);
8992 genFarPointerSet (right, result, ic, pi);
8996 genGenPointerSet (right, result, ic, pi);
9000 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9001 "genPointerSet: illegal pointer type");
9006 /*-----------------------------------------------------------------*/
9007 /* genIfx - generate code for Ifx statement */
9008 /*-----------------------------------------------------------------*/
9010 genIfx (iCode * ic, iCode * popIc)
9012 operand *cond = IC_COND (ic);
9015 D(emitcode ("; genIfx",""));
9017 aopOp (cond, ic, FALSE);
9019 /* get the value into acc */
9020 if (AOP_TYPE (cond) != AOP_CRY)
9024 /* the result is now in the accumulator */
9025 freeAsmop (cond, NULL, ic, TRUE);
9027 /* if there was something to be popped then do it */
9031 /* if the condition is a bit variable */
9032 if (isbit && IS_ITEMP (cond) &&
9034 genIfxJump (ic, SPIL_LOC (cond)->rname);
9035 else if (isbit && !IS_ITEMP (cond))
9036 genIfxJump (ic, OP_SYMBOL (cond)->rname);
9038 genIfxJump (ic, "a");
9043 /*-----------------------------------------------------------------*/
9044 /* genAddrOf - generates code for address of */
9045 /*-----------------------------------------------------------------*/
9047 genAddrOf (iCode * ic)
9049 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9052 D(emitcode ("; genAddrOf",""));
9054 aopOp (IC_RESULT (ic), ic, FALSE);
9056 /* if the operand is on the stack then we
9057 need to get the stack offset of this
9061 /* if it has an offset then we need to compute
9065 emitcode ("mov", "a,_bp");
9066 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9067 ((char) (sym->stack - _G.nRegsSaved)) :
9068 ((char) sym->stack)) & 0xff);
9069 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9073 /* we can just move _bp */
9074 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9076 /* fill the result with zero */
9077 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9082 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9088 /* object not on stack then we need the name */
9089 size = AOP_SIZE (IC_RESULT (ic));
9094 char s[SDCC_NAME_MAX];
9096 sprintf (s, "#(%s >> %d)",
9100 sprintf (s, "#%s", sym->rname);
9101 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9105 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9109 /*-----------------------------------------------------------------*/
9110 /* genFarFarAssign - assignment when both are in far space */
9111 /*-----------------------------------------------------------------*/
9113 genFarFarAssign (operand * result, operand * right, iCode * ic)
9115 int size = AOP_SIZE (right);
9119 D(emitcode ("; genFarFarAssign",""));
9121 /* first push the right side on to the stack */
9124 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9126 emitcode ("push", "acc");
9129 freeAsmop (right, NULL, ic, FALSE);
9130 /* now assign DPTR to result */
9131 aopOp (result, ic, FALSE);
9132 size = AOP_SIZE (result);
9135 emitcode ("pop", "acc");
9136 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9138 freeAsmop (result, NULL, ic, FALSE);
9142 /*-----------------------------------------------------------------*/
9143 /* genAssign - generate code for assignment */
9144 /*-----------------------------------------------------------------*/
9146 genAssign (iCode * ic)
9148 operand *result, *right;
9150 unsigned long lit = 0L;
9152 D(emitcode("; genAssign",""));
9154 result = IC_RESULT (ic);
9155 right = IC_RIGHT (ic);
9157 /* if they are the same */
9158 if (operandsEqu (result, right) &&
9159 !isOperandVolatile (result, FALSE) &&
9160 !isOperandVolatile (right, FALSE))
9163 aopOp (right, ic, FALSE);
9165 /* special case both in far space */
9166 if (AOP_TYPE (right) == AOP_DPTR &&
9167 IS_TRUE_SYMOP (result) &&
9168 isOperandInFarSpace (result))
9171 genFarFarAssign (result, right, ic);
9175 aopOp (result, ic, TRUE);
9177 /* if they are the same registers */
9178 if (sameRegs (AOP (right), AOP (result)) &&
9179 !isOperandVolatile (result, FALSE) &&
9180 !isOperandVolatile (right, FALSE))
9183 /* if the result is a bit */
9184 if (AOP_TYPE (result) == AOP_CRY)
9187 /* if the right size is a literal then
9188 we know what the value is */
9189 if (AOP_TYPE (right) == AOP_LIT)
9191 if (((int) operandLitValue (right)))
9192 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9194 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9198 /* the right is also a bit variable */
9199 if (AOP_TYPE (right) == AOP_CRY)
9201 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9202 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9208 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9212 /* bit variables done */
9214 size = AOP_SIZE (result);
9216 if (AOP_TYPE (right) == AOP_LIT)
9217 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9219 (AOP_TYPE (result) != AOP_REG) &&
9220 (AOP_TYPE (right) == AOP_LIT) &&
9221 !IS_FLOAT (operandType (right)) &&
9224 emitcode ("clr", "a");
9227 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9228 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9230 aopPut (AOP (result),
9231 aopGet (AOP (right), size, FALSE, FALSE),
9233 isOperandVolatile (result, FALSE));
9240 aopPut (AOP (result),
9241 aopGet (AOP (right), offset, FALSE, FALSE),
9243 isOperandVolatile (result, FALSE));
9249 freeAsmop (right, NULL, ic, TRUE);
9250 freeAsmop (result, NULL, ic, TRUE);
9253 /*-----------------------------------------------------------------*/
9254 /* genJumpTab - genrates code for jump table */
9255 /*-----------------------------------------------------------------*/
9257 genJumpTab (iCode * ic)
9262 D(emitcode ("; genJumpTab",""));
9264 aopOp (IC_JTCOND (ic), ic, FALSE);
9265 /* get the condition into accumulator */
9266 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9268 /* multiply by three */
9269 emitcode ("add", "a,acc");
9270 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9271 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9273 jtab = newiTempLabel (NULL);
9274 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9275 emitcode ("jmp", "@a+dptr");
9276 emitcode ("", "%05d$:", jtab->key + 100);
9277 /* now generate the jump labels */
9278 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9279 jtab = setNextItem (IC_JTLABELS (ic)))
9280 emitcode ("ljmp", "%05d$", jtab->key + 100);
9284 /*-----------------------------------------------------------------*/
9285 /* genCast - gen code for casting */
9286 /*-----------------------------------------------------------------*/
9288 genCast (iCode * ic)
9290 operand *result = IC_RESULT (ic);
9291 sym_link *ctype = operandType (IC_LEFT (ic));
9292 sym_link *rtype = operandType (IC_RIGHT (ic));
9293 operand *right = IC_RIGHT (ic);
9296 D(emitcode("; genCast",""));
9298 /* if they are equivalent then do nothing */
9299 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9302 aopOp (right, ic, FALSE);
9303 aopOp (result, ic, FALSE);
9305 /* if the result is a bit (and not a bitfield) */
9306 // if (AOP_TYPE (result) == AOP_CRY)
9307 if (IS_BITVAR (OP_SYMBOL (result)->type)
9308 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9310 /* if the right size is a literal then
9311 we know what the value is */
9312 if (AOP_TYPE (right) == AOP_LIT)
9314 if (((int) operandLitValue (right)))
9315 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9317 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9322 /* the right is also a bit variable */
9323 if (AOP_TYPE (right) == AOP_CRY)
9325 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9326 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9332 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9337 /* if they are the same size : or less */
9338 if (AOP_SIZE (result) <= AOP_SIZE (right))
9341 /* if they are in the same place */
9342 if (sameRegs (AOP (right), AOP (result)))
9345 /* if they in different places then copy */
9346 size = AOP_SIZE (result);
9350 aopPut (AOP (result),
9351 aopGet (AOP (right), offset, FALSE, FALSE),
9353 isOperandVolatile (result, FALSE));
9360 /* if the result is of type pointer */
9365 sym_link *type = operandType (right);
9366 sym_link *etype = getSpec (type);
9368 /* pointer to generic pointer */
9369 if (IS_GENPTR (ctype))
9372 p_type = DCL_TYPE (type);
9375 if (SPEC_SCLS(etype)==S_REGISTER) {
9376 // let's assume it is a generic pointer
9379 /* we have to go by the storage class */
9380 p_type = PTR_TYPE (SPEC_OCLS (etype));
9384 /* the first two bytes are known */
9385 size = GPTRSIZE - 1;
9389 aopPut (AOP (result),
9390 aopGet (AOP (right), offset, FALSE, FALSE),
9392 isOperandVolatile (result, FALSE));
9395 /* the last byte depending on type */
9397 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9402 // pointerTypeToGPByte will have bitched.
9406 sprintf(gpValStr, "#0x%d", gpVal);
9407 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9412 /* just copy the pointers */
9413 size = AOP_SIZE (result);
9417 aopPut (AOP (result),
9418 aopGet (AOP (right), offset, FALSE, FALSE),
9420 isOperandVolatile (result, FALSE));
9426 /* so we now know that the size of destination is greater
9427 than the size of the source */
9428 /* we move to result for the size of source */
9429 size = AOP_SIZE (right);
9433 aopPut (AOP (result),
9434 aopGet (AOP (right), offset, FALSE, FALSE),
9436 isOperandVolatile (result, FALSE));
9440 /* now depending on the sign of the source && destination */
9441 size = AOP_SIZE (result) - AOP_SIZE (right);
9442 /* if unsigned or not an integral type */
9443 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9446 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9450 /* we need to extend the sign :{ */
9451 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9454 emitcode ("rlc", "a");
9455 emitcode ("subb", "a,acc");
9457 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9460 /* we are done hurray !!!! */
9463 freeAsmop (right, NULL, ic, TRUE);
9464 freeAsmop (result, NULL, ic, TRUE);
9468 /*-----------------------------------------------------------------*/
9469 /* genDjnz - generate decrement & jump if not zero instrucion */
9470 /*-----------------------------------------------------------------*/
9472 genDjnz (iCode * ic, iCode * ifx)
9478 D(emitcode ("; genDjnz",""));
9480 /* if the if condition has a false label
9481 then we cannot save */
9485 /* if the minus is not of the form
9487 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9488 !IS_OP_LITERAL (IC_RIGHT (ic)))
9491 if (operandLitValue (IC_RIGHT (ic)) != 1)
9494 /* if the size of this greater than one then no
9496 if (getSize (operandType (IC_RESULT (ic))) > 1)
9499 /* otherwise we can save BIG */
9500 lbl = newiTempLabel (NULL);
9501 lbl1 = newiTempLabel (NULL);
9503 aopOp (IC_RESULT (ic), ic, FALSE);
9505 if (AOP_NEEDSACC(IC_RESULT(ic)))
9507 /* If the result is accessed indirectly via
9508 * the accumulator, we must explicitly write
9509 * it back after the decrement.
9511 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9513 if (strcmp(rByte, "a"))
9515 /* Something is hopelessly wrong */
9516 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9517 __FILE__, __LINE__);
9518 /* We can just give up; the generated code will be inefficient,
9521 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9524 emitcode ("dec", "%s", rByte);
9525 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9526 emitcode ("jnz", "%05d$", lbl->key + 100);
9528 else if (IS_AOP_PREG (IC_RESULT (ic)))
9530 emitcode ("dec", "%s",
9531 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9532 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9533 emitcode ("jnz", "%05d$", lbl->key + 100);
9537 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9540 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9541 emitcode ("", "%05d$:", lbl->key + 100);
9542 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9543 emitcode ("", "%05d$:", lbl1->key + 100);
9545 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9550 /*-----------------------------------------------------------------*/
9551 /* genReceive - generate code for a receive iCode */
9552 /*-----------------------------------------------------------------*/
9554 genReceive (iCode * ic)
9556 int size = getSize (operandType (IC_RESULT (ic)));
9558 D(emitcode ("; genReceive",""));
9560 if (ic->argreg == 1) { /* first parameter */
9561 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9562 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9563 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9569 for (offset = 0; offset<size; offset++)
9570 if (!strcmp (fReturn[offset], "a"))
9575 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9577 for (offset = size-1; offset>0; offset--)
9578 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9579 emitcode("mov","a,%s", fReturn[0]);
9581 aopOp (IC_RESULT (ic), ic, FALSE);
9583 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9584 isOperandVolatile (IC_RESULT (ic), FALSE));
9585 for (offset = 1; offset<size; offset++)
9586 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9587 isOperandVolatile (IC_RESULT (ic), FALSE));
9593 if (getTempRegs(tempRegs, size, ic))
9595 for (offset = 0; offset<size; offset++)
9596 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9597 aopOp (IC_RESULT (ic), ic, FALSE);
9598 for (offset = 0; offset<size; offset++)
9599 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9600 isOperandVolatile (IC_RESULT (ic), FALSE));
9605 offset = fReturnSizeMCS51 - size;
9607 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9608 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9611 aopOp (IC_RESULT (ic), ic, FALSE);
9612 size = AOP_SIZE (IC_RESULT (ic));
9615 emitcode ("pop", "acc");
9616 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9621 aopOp (IC_RESULT (ic), ic, FALSE);
9623 assignResultValue (IC_RESULT (ic));
9625 } else { /* second receive onwards */
9627 aopOp (IC_RESULT (ic), ic, FALSE);
9628 rb1off = ic->argreg;
9630 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9635 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9638 /*-----------------------------------------------------------------*/
9639 /* genDummyRead - generate code for dummy read of volatiles */
9640 /*-----------------------------------------------------------------*/
9642 genDummyRead (iCode * ic)
9647 D(emitcode("; genDummyRead",""));
9650 if (op && IS_SYMOP (op))
9652 aopOp (op, ic, FALSE);
9654 /* if the result is a bit */
9655 if (AOP_TYPE (op) == AOP_CRY)
9656 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9659 /* bit variables done */
9661 size = AOP_SIZE (op);
9665 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9670 freeAsmop (op, NULL, ic, TRUE);
9674 if (op && IS_SYMOP (op))
9676 aopOp (op, ic, FALSE);
9678 /* if the result is a bit */
9679 if (AOP_TYPE (op) == AOP_CRY)
9680 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9683 /* bit variables done */
9685 size = AOP_SIZE (op);
9689 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9694 freeAsmop (op, NULL, ic, TRUE);
9698 /*-----------------------------------------------------------------*/
9699 /* genCritical - generate code for start of a critical sequence */
9700 /*-----------------------------------------------------------------*/
9702 genCritical (iCode *ic)
9704 symbol *tlbl = newiTempLabel (NULL);
9706 D(emitcode("; genCritical",""));
9709 aopOp (IC_RESULT (ic), ic, TRUE);
9711 emitcode ("setb", "c");
9712 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9713 emitcode ("clr", "c");
9714 emitcode ("", "%05d$:", (tlbl->key + 100));
9717 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9719 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9722 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9725 /*-----------------------------------------------------------------*/
9726 /* genEndCritical - generate code for end of a critical sequence */
9727 /*-----------------------------------------------------------------*/
9729 genEndCritical (iCode *ic)
9731 D(emitcode("; genEndCritical",""));
9735 aopOp (IC_RIGHT (ic), ic, FALSE);
9736 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9738 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9739 emitcode ("mov", "ea,c");
9743 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9744 emitcode ("rrc", "a");
9745 emitcode ("mov", "ea,c");
9747 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9751 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9752 emitcode ("mov", "ea,c");
9756 /*-----------------------------------------------------------------*/
9757 /* gen51Code - generate code for 8051 based controllers */
9758 /*-----------------------------------------------------------------*/
9760 gen51Code (iCode * lic)
9766 _G.currentFunc = NULL;
9767 lineHead = lineCurr = NULL;
9769 /* print the allocation information */
9770 if (allocInfo && currFunc)
9771 printAllocInfo (currFunc, codeOutFile);
9772 /* if debug information required */
9773 if (options.debug && currFunc)
9775 debugFile->writeFunction(currFunc);
9777 if (IS_STATIC (currFunc->etype))
9778 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9780 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9783 /* stack pointer name */
9784 if (options.useXstack)
9790 for (ic = lic; ic; ic = ic->next)
9792 _G.current_iCode = ic;
9794 if (ic->lineno && cln != ic->lineno)
9799 emitcode ("", "C$%s$%d$%d$%d ==.",
9800 FileBaseName (ic->filename), ic->lineno,
9801 ic->level, ic->block);
9804 if (!options.noCcodeInAsm) {
9805 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9806 printCLine(ic->filename, ic->lineno));
9811 if (ic->seqPoint && ic->seqPoint != cseq)
9813 emitcode ("", "; sequence point %d", ic->seqPoint);
9814 cseq = ic->seqPoint;
9817 if (options.iCodeInAsm) {
9821 for (i=0; i<8; i++) {
9822 sprintf (®sInUse[i],
9823 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9826 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9828 /* if the result is marked as
9829 spilt and rematerializable or code for
9830 this has already been generated then
9832 if (resultRemat (ic) || ic->generated)
9835 /* depending on the operation */
9855 /* IPOP happens only when trying to restore a
9856 spilt live range, if there is an ifx statement
9857 following this pop then the if statement might
9858 be using some of the registers being popped which
9859 would destory the contents of the register so
9860 we need to check for this condition and handle it */
9862 ic->next->op == IFX &&
9863 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9864 genIfx (ic->next, ic);
9882 genEndFunction (ic);
9902 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9919 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9923 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9930 /* note these two are xlated by algebraic equivalence
9931 during parsing SDCC.y */
9932 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9933 "got '>=' or '<=' shouldn't have come here");
9937 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9949 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9953 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9957 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9984 case GET_VALUE_AT_ADDRESS:
9985 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9989 if (POINTER_SET (ic))
9990 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10016 addSet (&_G.sendSet, ic);
10019 case DUMMY_READ_VOLATILE:
10028 genEndCritical (ic);
10040 _G.current_iCode = NULL;
10042 /* now we are ready to call the
10043 peep hole optimizer */
10044 if (!options.nopeep)
10045 peepHole (&lineHead);
10047 /* now do the actual printing */
10048 printLine (lineHead, codeOutFile);