1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
81 static char *rb1regs[] = {
82 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
85 extern int mcs51_ptrRegReq;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saveRBank (int, iCode *, bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
94 #define CLRC emitcode("clr","c")
95 #define SETC emitcode("setb","c")
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
100 static unsigned char SLMask[] =
101 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] =
104 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105 0x07, 0x03, 0x01, 0x00};
112 /*-----------------------------------------------------------------*/
113 /* emitcode - writes the code into a file : for now it is simple */
114 /*-----------------------------------------------------------------*/
116 emitcode (char *inst, const char *fmt,...)
119 char lb[INITIAL_INLINEASM];
127 sprintf (lb, "%s\t", inst);
129 sprintf (lb, "%s", inst);
130 vsprintf (lb + (strlen (lb)), fmt, ap);
133 vsprintf (lb, fmt, ap);
135 while (isspace (*lbp))
138 //printf ("%s\n", lb);
141 lineCurr = (lineCurr ?
142 connectLine (lineCurr, newLineNode (lb)) :
143 (lineHead = newLineNode (lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
146 lineCurr->ic = _G.current_iCode;
147 lineCurr->isComment = (*lbp==';');
151 /*-----------------------------------------------------------------*/
152 /* mova - moves specified value into accumulator */
153 /*-----------------------------------------------------------------*/
157 /* do some early peephole optimization */
158 if (!strcmp(x, "a") || !strcmp(x, "acc"))
161 emitcode("mov","a,%s", x);
164 /*-----------------------------------------------------------------*/
165 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
166 /*-----------------------------------------------------------------*/
168 getFreePtr (iCode * ic, asmop ** aopp, bool result)
170 bool r0iu = FALSE, r1iu = FALSE;
171 bool r0ou = FALSE, r1ou = FALSE;
173 /* the logic: if r0 & r1 used in the instruction
174 then we are in trouble otherwise */
176 /* first check if r0 & r1 are used by this
177 instruction, in which case we are in trouble */
178 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
179 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
185 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
187 /* if no usage of r0 then return it */
190 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
191 (*aopp)->type = AOP_R0;
193 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
196 /* if no usage of r1 then return it */
199 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
200 (*aopp)->type = AOP_R1;
202 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
205 /* now we know they both have usage */
206 /* if r0 not used in this instruction */
209 /* push it if not already pushed */
212 emitcode ("push", "%s",
213 mcs51_regWithIdx (R0_IDX)->dname);
217 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
218 (*aopp)->type = AOP_R0;
220 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
223 /* if r1 not used then */
227 /* push it if not already pushed */
230 emitcode ("push", "%s",
231 mcs51_regWithIdx (R1_IDX)->dname);
235 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
236 (*aopp)->type = AOP_R1;
237 return mcs51_regWithIdx (R1_IDX);
240 /* I said end of world, but not quite end of world yet */
242 /* we can push it on the stack */
243 (*aopp)->type = AOP_STK;
246 /* in the case that result AND left AND right needs a pointer reg
247 we can safely use the result's */
248 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
249 (*aopp)->type = AOP_R0;
250 return mcs51_regWithIdx (R0_IDX);
252 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
253 (*aopp)->type = AOP_R1;
254 return mcs51_regWithIdx (R1_IDX);
258 /* now this is REALLY the end of the world */
259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
260 "getFreePtr should never reach here");
265 /*-----------------------------------------------------------------*/
266 /* getTempRegs - initialize an array of pointers to GPR registers */
267 /* that are not in use. Returns 1 if the requested */
268 /* number of registers were available, 0 otherwise. */
269 /*-----------------------------------------------------------------*/
271 getTempRegs(regs **tempRegs, int size, iCode *ic)
278 ic = _G.current_iCode;
284 freeRegs = newBitVect(8);
285 bitVectSetBit (freeRegs, R2_IDX);
286 bitVectSetBit (freeRegs, R3_IDX);
287 bitVectSetBit (freeRegs, R4_IDX);
288 bitVectSetBit (freeRegs, R5_IDX);
289 bitVectSetBit (freeRegs, R6_IDX);
290 bitVectSetBit (freeRegs, R7_IDX);
292 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
294 bitVect * newfreeRegs;
295 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
296 freeBitVect(freeRegs);
297 freeRegs = newfreeRegs;
299 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
302 for (i=0; i<freeRegs->size; i++)
304 if (bitVectBitValue(freeRegs,i))
305 tempRegs[offset++] = mcs51_regWithIdx(i);
308 freeBitVect(freeRegs);
313 freeBitVect(freeRegs);
318 /*-----------------------------------------------------------------*/
319 /* newAsmop - creates a new asmOp */
320 /*-----------------------------------------------------------------*/
322 newAsmop (short type)
326 aop = Safe_calloc (1, sizeof (asmop));
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type */
333 /*-----------------------------------------------------------------*/
335 pointerCode (sym_link * etype)
338 return PTR_TYPE (SPEC_OCLS (etype));
343 /*-----------------------------------------------------------------*/
344 /* leftRightUseAcc - returns size of accumulator use by operands */
345 /*-----------------------------------------------------------------*/
347 leftRightUseAcc(iCode *ic)
356 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
357 "null iCode pointer");
364 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
367 size = getSize (OP_SYMBOL (op)->type);
372 else if (ic->op == JUMPTABLE)
375 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
378 size = getSize (OP_SYMBOL (op)->type);
386 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
389 size = getSize (OP_SYMBOL (op)->type);
394 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
397 size = getSize (OP_SYMBOL (op)->type);
410 /*-----------------------------------------------------------------*/
411 /* aopForSym - for a true symbol */
412 /*-----------------------------------------------------------------*/
414 aopForSym (iCode * ic, symbol * sym, bool result)
419 wassertl (ic != NULL, "Got a null iCode");
420 wassertl (sym != NULL, "Got a null symbol");
422 space = SPEC_OCLS (sym->etype);
424 /* if already has one */
428 /* assign depending on the storage class */
429 /* if it is on the stack or indirectly addressable */
430 /* space we need to assign either r0 or r1 to it */
431 if (sym->onStack || sym->iaccess)
433 sym->aop = aop = newAsmop (0);
434 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
435 aop->size = getSize (sym->type);
437 /* now assign the address of the variable to
438 the pointer register */
439 if (aop->type != AOP_STK)
444 if (_G.accInUse || leftRightUseAcc (ic))
445 emitcode ("push", "acc");
447 emitcode ("mov", "a,_bp");
448 emitcode ("add", "a,#0x%02x",
450 ((char) (sym->stack - _G.nRegsSaved)) :
451 ((char) sym->stack)) & 0xff);
452 emitcode ("mov", "%s,a",
453 aop->aopu.aop_ptr->name);
455 if (_G.accInUse || leftRightUseAcc (ic))
456 emitcode ("pop", "acc");
459 emitcode ("mov", "%s,#%s",
460 aop->aopu.aop_ptr->name,
462 aop->paged = space->paged;
465 aop->aopu.aop_stk = sym->stack;
469 /* if in bit space */
470 if (IN_BITSPACE (space))
472 sym->aop = aop = newAsmop (AOP_CRY);
473 aop->aopu.aop_dir = sym->rname;
474 aop->size = getSize (sym->type);
477 /* if it is in direct space */
478 if (IN_DIRSPACE (space))
480 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
481 //printTypeChainRaw(sym->type, NULL);
482 //printf("space = %s\n", space ? space->sname : "NULL");
483 sym->aop = aop = newAsmop (AOP_DIR);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
489 /* special case for a function */
490 if (IS_FUNC (sym->type))
492 sym->aop = aop = newAsmop (AOP_IMMD);
493 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
494 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
495 aop->size = FPTRSIZE;
499 /* only remaining is far space */
500 /* in which case DPTR gets the address */
501 sym->aop = aop = newAsmop (AOP_DPTR);
502 emitcode ("mov", "dptr,#%s", sym->rname);
503 aop->size = getSize (sym->type);
505 /* if it is in code space */
506 if (IN_CODESPACE (space))
512 /*-----------------------------------------------------------------*/
513 /* aopForRemat - rematerialzes an object */
514 /*-----------------------------------------------------------------*/
516 aopForRemat (symbol * sym)
518 iCode *ic = sym->rematiCode;
519 asmop *aop = newAsmop (AOP_IMMD);
526 val += (int) operandLitValue (IC_RIGHT (ic));
527 else if (ic->op == '-')
528 val -= (int) operandLitValue (IC_RIGHT (ic));
529 else if (IS_CAST_ICODE(ic)) {
530 sym_link *from_type = operandType(IC_RIGHT(ic));
531 aop->aopu.aop_immd.from_cast_remat = 1;
532 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
533 ptr_type = DCL_TYPE(from_type);
534 if (ptr_type == IPOINTER) {
541 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
545 sprintf (buffer, "(%s %c 0x%04x)",
546 OP_SYMBOL (IC_LEFT (ic))->rname,
547 val >= 0 ? '+' : '-',
550 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
552 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
553 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
554 /* set immd2 field if required */
555 if (aop->aopu.aop_immd.from_cast_remat) {
556 sprintf(buffer,"#0x%02x",ptr_type);
557 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
558 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
659 if (aop1->type != AOP_REG ||
660 aop2->type != AOP_REG)
663 if (aop1->size != aop2->size)
666 for (i = 0; i < aop1->size; i++)
667 if (aop1->aopu.aop_reg[i] !=
668 aop2->aopu.aop_reg[i])
674 /*-----------------------------------------------------------------*/
675 /* aopOp - allocates an asmop for an operand : */
676 /*-----------------------------------------------------------------*/
678 aopOp (operand * op, iCode * ic, bool result)
687 /* if this a literal */
688 if (IS_OP_LITERAL (op))
690 op->aop = aop = newAsmop (AOP_LIT);
691 aop->aopu.aop_lit = op->operand.valOperand;
692 aop->size = getSize (operandType (op));
696 /* if already has a asmop then continue */
700 /* if the underlying symbol has a aop */
701 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
703 op->aop = OP_SYMBOL (op)->aop;
707 /* if this is a true symbol */
708 if (IS_TRUE_SYMOP (op))
710 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
714 /* this is a temporary : this has
720 e) can be a return use only */
722 sym = OP_SYMBOL (op);
724 /* if the type is a conditional */
725 if (sym->regType == REG_CND)
727 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
732 /* if it is spilt then two situations
734 b) has a spill location */
735 if (sym->isspilt || sym->nRegs == 0)
738 /* rematerialize it NOW */
741 sym->aop = op->aop = aop =
743 aop->size = getSize (sym->type);
750 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
751 aop->size = getSize (sym->type);
752 for (i = 0; i < 2; i++)
753 aop->aopu.aop_str[i] = accUse[i];
761 aop = op->aop = sym->aop = newAsmop (AOP_STR);
762 aop->size = getSize (sym->type);
763 for (i = 0; i < fReturnSizeMCS51; i++)
764 aop->aopu.aop_str[i] = fReturn[i];
768 if (sym->usl.spillLoc)
770 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
772 /* force a new aop if sizes differ */
773 sym->usl.spillLoc->aop = NULL;
775 sym->aop = op->aop = aop =
776 aopForSym (ic, sym->usl.spillLoc, result);
777 aop->size = getSize (sym->type);
781 /* else must be a dummy iTemp */
782 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
783 aop->size = getSize (sym->type);
787 /* must be in a register */
788 sym->aop = op->aop = aop = newAsmop (AOP_REG);
789 aop->size = sym->nRegs;
790 for (i = 0; i < sym->nRegs; i++)
791 aop->aopu.aop_reg[i] = sym->regs[i];
794 /*-----------------------------------------------------------------*/
795 /* freeAsmop - free up the asmop given to an operand */
796 /*----------------------------------------------------------------*/
798 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
815 /* depending on the asmop type only three cases need work AOP_RO
816 , AOP_R1 && AOP_STK */
824 emitcode ("pop", "ar0");
828 bitVectUnSetBit (ic->rUsed, R0_IDX);
836 emitcode ("pop", "ar1");
840 bitVectUnSetBit (ic->rUsed, R1_IDX);
846 int stk = aop->aopu.aop_stk + aop->size - 1;
847 bitVectUnSetBit (ic->rUsed, R0_IDX);
848 bitVectUnSetBit (ic->rUsed, R1_IDX);
850 getFreePtr (ic, &aop, FALSE);
854 emitcode ("mov", "a,_bp");
855 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
856 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
860 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
865 emitcode ("pop", "acc");
866 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
869 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
872 freeAsmop (op, NULL, ic, TRUE);
875 emitcode ("pop", "ar1");
881 emitcode ("pop", "ar0");
888 /* all other cases just dealloc */
894 OP_SYMBOL (op)->aop = NULL;
895 /* if the symbol has a spill */
897 SPIL_LOC (op)->aop = NULL;
902 /*-----------------------------------------------------------------*/
903 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
904 /* clobber the accumulator */
905 /*-----------------------------------------------------------------*/
907 aopGetUsesAcc (asmop *aop, int offset)
909 if (offset > (aop->size - 1))
927 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
936 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
942 /* Error case --- will have been caught already */
948 /*-----------------------------------------------------------------*/
949 /* aopGet - for fetching value of the aop */
950 /*-----------------------------------------------------------------*/
952 aopGet (asmop * aop, int offset, bool bit16, bool dname)
957 /* offset is greater than
959 if (offset > (aop->size - 1) &&
960 aop->type != AOP_LIT)
963 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
996 if (aop->code && aop->coff==0 && offset>=1) {
997 emitcode ("mov", "a,#0x%02x", offset);
998 emitcode ("movc", "a,@a+dptr");
999 return (dname ? "acc" : "a");
1002 while (offset > aop->coff)
1004 emitcode ("inc", "dptr");
1008 while (offset < aop->coff)
1010 emitcode ("lcall", "__decdptr");
1017 emitcode ("clr", "a");
1018 emitcode ("movc", "a,@a+dptr");
1022 emitcode ("movx", "a,@dptr");
1024 return (dname ? "acc" : "a");
1028 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1029 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1031 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1033 sprintf (s, "#(%s >> %d)",
1034 aop->aopu.aop_immd.aop_immd1,
1038 aop->aopu.aop_immd.aop_immd1);
1039 rs = Safe_calloc (1, strlen (s) + 1);
1045 sprintf (s, "(%s + %d)",
1049 sprintf (s, "%s", aop->aopu.aop_dir);
1050 rs = Safe_calloc (1, strlen (s) + 1);
1056 return aop->aopu.aop_reg[offset]->dname;
1058 return aop->aopu.aop_reg[offset]->name;
1061 emitcode ("clr", "a");
1062 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1063 emitcode ("rlc", "a");
1064 return (dname ? "acc" : "a");
1067 if (!offset && dname)
1069 return aop->aopu.aop_str[offset];
1072 return aopLiteral (aop->aopu.aop_lit, offset);
1076 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1080 return aop->aopu.aop_str[offset];
1084 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1085 "aopget got unsupported aop->type");
1088 /*-----------------------------------------------------------------*/
1089 /* aopPut - puts a string for a aop */
1090 /*-----------------------------------------------------------------*/
1092 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1096 if (aop->size && offset > (aop->size - 1))
1098 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1099 "aopPut got offset > aop->size");
1103 /* will assign value to value */
1104 /* depending on where it is ofcourse */
1108 MOVA (s); /* read s in case it was volatile */
1113 sprintf (d, "(%s + %d)",
1114 aop->aopu.aop_dir, offset);
1116 sprintf (d, "%s", aop->aopu.aop_dir);
1118 if (strcmp (d, s) ||
1120 emitcode ("mov", "%s,%s", d, s);
1125 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1126 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1129 strcmp (s, "r0") == 0 ||
1130 strcmp (s, "r1") == 0 ||
1131 strcmp (s, "r2") == 0 ||
1132 strcmp (s, "r3") == 0 ||
1133 strcmp (s, "r4") == 0 ||
1134 strcmp (s, "r5") == 0 ||
1135 strcmp (s, "r6") == 0 ||
1136 strcmp (s, "r7") == 0)
1137 emitcode ("mov", "%s,%s",
1138 aop->aopu.aop_reg[offset]->dname, s);
1140 emitcode ("mov", "%s,%s",
1141 aop->aopu.aop_reg[offset]->name, s);
1148 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1149 "aopPut writing to code space");
1153 while (offset > aop->coff)
1156 emitcode ("inc", "dptr");
1159 while (offset < aop->coff)
1162 emitcode ("lcall", "__decdptr");
1167 /* if not in accumulater */
1170 emitcode ("movx", "@dptr,a");
1175 while (offset > aop->coff)
1178 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1180 while (offset < aop->coff)
1183 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1190 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1196 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1198 else if (strcmp (s, "r0") == 0 ||
1199 strcmp (s, "r1") == 0 ||
1200 strcmp (s, "r2") == 0 ||
1201 strcmp (s, "r3") == 0 ||
1202 strcmp (s, "r4") == 0 ||
1203 strcmp (s, "r5") == 0 ||
1204 strcmp (s, "r6") == 0 ||
1205 strcmp (s, "r7") == 0)
1208 sprintf (buffer, "a%s", s);
1209 emitcode ("mov", "@%s,%s",
1210 aop->aopu.aop_ptr->name, buffer);
1213 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1218 if (strcmp (s, "a") == 0)
1219 emitcode ("push", "acc");
1223 emitcode ("push", "acc");
1225 emitcode ("push", s);
1231 /* if bit variable */
1232 if (!aop->aopu.aop_dir)
1234 emitcode ("clr", "a");
1235 emitcode ("rlc", "a");
1240 emitcode ("clr", "%s", aop->aopu.aop_dir);
1242 emitcode ("setb", "%s", aop->aopu.aop_dir);
1243 else if (!strcmp (s, "c"))
1244 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1247 if (strcmp (s, "a"))
1252 /* set C, if a >= 1 */
1253 emitcode ("add", "a,#0xff");
1254 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1262 if (strcmp (aop->aopu.aop_str[offset], s) ||
1264 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 if (!offset && (strcmp (s, "acc") == 0) &&
1273 if (strcmp (aop->aopu.aop_str[offset], s) &&
1275 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1279 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280 "aopPut got unsupported aop->type");
1288 /*-----------------------------------------------------------------*/
1289 /* pointToEnd :- points to the last byte of the operand */
1290 /*-----------------------------------------------------------------*/
1292 pointToEnd (asmop * aop)
1298 aop->coff = count = (aop->size - 1);
1304 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308 emitcode ("inc", "dptr");
1315 /*-----------------------------------------------------------------*/
1316 /* reAdjustPreg - points a register back to where it should */
1317 /*-----------------------------------------------------------------*/
1319 reAdjustPreg (asmop * aop)
1321 if ((aop->coff==0) || aop->size <= 1)
1329 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1334 emitcode ("lcall", "__decdptr");
1341 #define AOP(op) op->aop
1342 #define AOP_TYPE(op) AOP(op)->type
1343 #define AOP_SIZE(op) AOP(op)->size
1344 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1345 AOP_TYPE(x) == AOP_R0))
1347 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1348 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1350 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1351 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1352 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1355 /*-----------------------------------------------------------------*/
1356 /* opIsGptr: returns non-zero if the passed operand is */
1357 /* a generic pointer type. */
1358 /*-----------------------------------------------------------------*/
1360 opIsGptr (operand * op)
1362 sym_link *type = operandType (op);
1364 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1371 /*-----------------------------------------------------------------*/
1372 /* getDataSize - get the operand data size */
1373 /*-----------------------------------------------------------------*/
1375 getDataSize (operand * op)
1378 size = AOP_SIZE (op);
1379 if (size == GPTRSIZE)
1381 sym_link *type = operandType (op);
1382 if (IS_GENPTR (type))
1384 /* generic pointer; arithmetic operations
1385 * should ignore the high byte (pointer type).
1393 /*-----------------------------------------------------------------*/
1394 /* outAcc - output Acc */
1395 /*-----------------------------------------------------------------*/
1397 outAcc (operand * result)
1400 size = getDataSize (result);
1403 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1406 /* unsigned or positive */
1409 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1414 /*-----------------------------------------------------------------*/
1415 /* outBitC - output a bit C */
1416 /*-----------------------------------------------------------------*/
1418 outBitC (operand * result)
1420 /* if the result is bit */
1421 if (AOP_TYPE (result) == AOP_CRY)
1422 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1425 emitcode ("clr", "a");
1426 emitcode ("rlc", "a");
1431 /*-----------------------------------------------------------------*/
1432 /* toBoolean - emit code for orl a,operator(sizeop) */
1433 /*-----------------------------------------------------------------*/
1435 toBoolean (operand * oper)
1437 int size = AOP_SIZE (oper) - 1;
1439 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1441 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1445 /*-----------------------------------------------------------------*/
1446 /* genNot - generate code for ! operation */
1447 /*-----------------------------------------------------------------*/
1453 D(emitcode ("; genNot",""));
1455 /* assign asmOps to operand & result */
1456 aopOp (IC_LEFT (ic), ic, FALSE);
1457 aopOp (IC_RESULT (ic), ic, TRUE);
1459 /* if in bit space then a special case */
1460 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1462 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1463 emitcode ("cpl", "c");
1464 outBitC (IC_RESULT (ic));
1468 toBoolean (IC_LEFT (ic));
1470 tlbl = newiTempLabel (NULL);
1471 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1472 emitcode ("", "%05d$:", tlbl->key + 100);
1473 outBitC (IC_RESULT (ic));
1476 /* release the aops */
1477 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* genCpl - generate code for complement */
1484 /*-----------------------------------------------------------------*/
1492 D(emitcode ("; genCpl",""));
1494 /* assign asmOps to operand & result */
1495 aopOp (IC_LEFT (ic), ic, FALSE);
1496 aopOp (IC_RESULT (ic), ic, TRUE);
1498 /* special case if in bit space */
1499 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1501 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1503 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1504 emitcode ("cpl", "c");
1505 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1509 tlbl=newiTempLabel(NULL);
1510 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1511 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1512 IS_AOP_PREG (IC_LEFT (ic)))
1514 emitcode ("cjne", "%s,#0x01,%05d$",
1515 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1520 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1522 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1524 emitcode ("", "%05d$:", tlbl->key + 100);
1525 outBitC (IC_RESULT(ic));
1529 size = AOP_SIZE (IC_RESULT (ic));
1532 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1534 emitcode ("cpl", "a");
1535 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1540 /* release the aops */
1541 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* genUminusFloat - unary minus for floating points */
1547 /*-----------------------------------------------------------------*/
1549 genUminusFloat (operand * op, operand * result)
1551 int size, offset = 0;
1554 D(emitcode ("; genUminusFloat",""));
1556 /* for this we just copy and then flip the bit */
1558 size = AOP_SIZE (op) - 1;
1562 aopPut (AOP (result),
1563 aopGet (AOP (op), offset, FALSE, FALSE),
1565 isOperandVolatile (result, FALSE));
1569 l = aopGet (AOP (op), offset, FALSE, FALSE);
1573 emitcode ("cpl", "acc.7");
1574 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1577 /*-----------------------------------------------------------------*/
1578 /* genUminus - unary minus code generation */
1579 /*-----------------------------------------------------------------*/
1581 genUminus (iCode * ic)
1584 sym_link *optype, *rtype;
1587 D(emitcode ("; genUminus",""));
1590 aopOp (IC_LEFT (ic), ic, FALSE);
1591 aopOp (IC_RESULT (ic), ic, TRUE);
1593 /* if both in bit space then special
1595 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1596 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1599 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1600 emitcode ("cpl", "c");
1601 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1605 optype = operandType (IC_LEFT (ic));
1606 rtype = operandType (IC_RESULT (ic));
1608 /* if float then do float stuff */
1609 if (IS_FLOAT (optype))
1611 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1615 /* otherwise subtract from zero */
1616 size = AOP_SIZE (IC_LEFT (ic));
1621 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1622 if (!strcmp (l, "a"))
1626 emitcode ("cpl", "a");
1627 emitcode ("addc", "a,#0");
1633 emitcode ("clr", "a");
1634 emitcode ("subb", "a,%s", l);
1636 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1639 /* if any remaining bytes in the result */
1640 /* we just need to propagate the sign */
1641 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1643 emitcode ("rlc", "a");
1644 emitcode ("subb", "a,acc");
1646 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1650 /* release the aops */
1651 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1652 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* saveRegisters - will look for a call and save the registers */
1657 /*-----------------------------------------------------------------*/
1659 saveRegisters (iCode * lic)
1666 for (ic = lic; ic; ic = ic->next)
1667 if (ic->op == CALL || ic->op == PCALL)
1672 fprintf (stderr, "found parameter push with no function call\n");
1676 /* if the registers have been saved already or don't need to be then
1680 if (IS_SYMOP(IC_LEFT(ic)) &&
1681 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1682 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1685 /* safe the registers in use at this time but skip the
1686 ones for the result */
1687 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1688 mcs51_rUmaskForOp (IC_RESULT(ic)));
1691 if (options.useXstack)
1693 if (bitVectBitValue (rsave, R0_IDX))
1694 emitcode ("mov", "b,r0");
1695 emitcode ("mov", "r0,%s", spname);
1696 for (i = 0; i < mcs51_nRegs; i++)
1698 if (bitVectBitValue (rsave, i))
1701 emitcode ("mov", "a,b");
1703 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1704 emitcode ("movx", "@r0,a");
1705 emitcode ("inc", "r0");
1708 emitcode ("mov", "%s,r0", spname);
1709 if (bitVectBitValue (rsave, R0_IDX))
1710 emitcode ("mov", "r0,b");
1713 for (i = 0; i < mcs51_nRegs; i++)
1715 if (bitVectBitValue (rsave, i))
1716 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1720 /*-----------------------------------------------------------------*/
1721 /* unsaveRegisters - pop the pushed registers */
1722 /*-----------------------------------------------------------------*/
1724 unsaveRegisters (iCode * ic)
1729 /* restore the registers in use at this time but skip the
1730 ones for the result */
1731 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1732 mcs51_rUmaskForOp (IC_RESULT(ic)));
1734 if (options.useXstack)
1736 emitcode ("mov", "r0,%s", spname);
1737 for (i = mcs51_nRegs; i >= 0; i--)
1739 if (bitVectBitValue (rsave, i))
1741 emitcode ("dec", "r0");
1742 emitcode ("movx", "a,@r0");
1744 emitcode ("mov", "b,a");
1746 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1750 emitcode ("mov", "%s,r0", spname);
1751 if (bitVectBitValue (rsave, R0_IDX))
1752 emitcode ("mov", "r0,b");
1755 for (i = mcs51_nRegs; i >= 0; i--)
1757 if (bitVectBitValue (rsave, i))
1758 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1764 /*-----------------------------------------------------------------*/
1766 /*-----------------------------------------------------------------*/
1768 pushSide (operand * oper, int size)
1773 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1774 if (AOP_TYPE (oper) != AOP_REG &&
1775 AOP_TYPE (oper) != AOP_DIR &&
1778 emitcode ("mov", "a,%s", l);
1779 emitcode ("push", "acc");
1782 emitcode ("push", "%s", l);
1786 /*-----------------------------------------------------------------*/
1787 /* assignResultValue - */
1788 /*-----------------------------------------------------------------*/
1790 assignResultValue (operand * oper)
1793 int size = AOP_SIZE (oper);
1796 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1802 /*-----------------------------------------------------------------*/
1803 /* genXpush - pushes onto the external stack */
1804 /*-----------------------------------------------------------------*/
1806 genXpush (iCode * ic)
1808 asmop *aop = newAsmop (0);
1810 int size, offset = 0;
1812 D(emitcode ("; genXpush",""));
1814 aopOp (IC_LEFT (ic), ic, FALSE);
1815 r = getFreePtr (ic, &aop, FALSE);
1818 emitcode ("mov", "%s,_spx", r->name);
1820 size = AOP_SIZE (IC_LEFT (ic));
1824 char *l = aopGet (AOP (IC_LEFT (ic)),
1825 offset++, FALSE, FALSE);
1827 emitcode ("movx", "@%s,a", r->name);
1828 emitcode ("inc", "%s", r->name);
1833 emitcode ("mov", "_spx,%s", r->name);
1835 freeAsmop (NULL, aop, ic, TRUE);
1836 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genIpush - genrate code for pushing this gets a little complex */
1841 /*-----------------------------------------------------------------*/
1843 genIpush (iCode * ic)
1845 int size, offset = 0;
1848 D(emitcode ("; genIpush",""));
1850 /* if this is not a parm push : ie. it is spill push
1851 and spill push is always done on the local stack */
1855 /* and the item is spilt then do nothing */
1856 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1861 /* push it on the stack */
1864 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1870 emitcode ("push", "%s", l);
1875 /* this is a paramter push: in this case we call
1876 the routine to find the call and save those
1877 registers that need to be saved */
1880 /* if use external stack then call the external
1881 stack pushing routine */
1882 if (options.useXstack)
1888 /* then do the push */
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1892 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1893 size = AOP_SIZE (IC_LEFT (ic));
1897 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1898 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1899 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1909 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* genIpop - recover the registers: can happen only for spilling */
1914 /*-----------------------------------------------------------------*/
1916 genIpop (iCode * ic)
1920 D(emitcode ("; genIpop",""));
1922 /* if the temp was not pushed then */
1923 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1926 aopOp (IC_LEFT (ic), ic, FALSE);
1927 size = AOP_SIZE (IC_LEFT (ic));
1928 offset = (size - 1);
1930 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1933 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1936 /*-----------------------------------------------------------------*/
1937 /* unsaveRBank - restores the resgister bank from stack */
1938 /*-----------------------------------------------------------------*/
1940 unsaveRBank (int bank, iCode * ic, bool popPsw)
1946 if (options.useXstack)
1950 /* Assume r0 is available for use. */
1951 r = mcs51_regWithIdx (R0_IDX);;
1956 r = getFreePtr (ic, &aop, FALSE);
1958 emitcode ("mov", "%s,_spx", r->name);
1963 if (options.useXstack)
1965 emitcode ("movx", "a,@%s", r->name);
1966 emitcode ("mov", "psw,a");
1967 emitcode ("dec", "%s", r->name);
1971 emitcode ("pop", "psw");
1975 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1977 if (options.useXstack)
1979 emitcode ("movx", "a,@%s", r->name);
1980 emitcode ("mov", "(%s+%d),a",
1981 regs8051[i].base, 8 * bank + regs8051[i].offset);
1982 emitcode ("dec", "%s", r->name);
1986 emitcode ("pop", "(%s+%d)",
1987 regs8051[i].base, 8 * bank + regs8051[i].offset);
1990 if (options.useXstack)
1992 emitcode ("mov", "_spx,%s", r->name);
1997 freeAsmop (NULL, aop, ic, TRUE);
2001 /*-----------------------------------------------------------------*/
2002 /* saveRBank - saves an entire register bank on the stack */
2003 /*-----------------------------------------------------------------*/
2005 saveRBank (int bank, iCode * ic, bool pushPsw)
2011 if (options.useXstack)
2015 /* Assume r0 is available for use. */
2016 r = mcs51_regWithIdx (R0_IDX);;
2021 r = getFreePtr (ic, &aop, FALSE);
2023 emitcode ("mov", "%s,_spx", r->name);
2026 for (i = 0; i < mcs51_nRegs; i++)
2028 if (options.useXstack)
2030 emitcode ("inc", "%s", r->name);
2031 emitcode ("mov", "a,(%s+%d)",
2032 regs8051[i].base, 8 * bank + regs8051[i].offset);
2033 emitcode ("movx", "@%s,a", r->name);
2036 emitcode ("push", "(%s+%d)",
2037 regs8051[i].base, 8 * bank + regs8051[i].offset);
2042 if (options.useXstack)
2044 emitcode ("mov", "a,psw");
2045 emitcode ("movx", "@%s,a", r->name);
2046 emitcode ("inc", "%s", r->name);
2047 emitcode ("mov", "_spx,%s", r->name);
2052 emitcode ("push", "psw");
2055 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2060 freeAsmop (NULL, aop, ic, TRUE);
2069 /*-----------------------------------------------------------------*/
2070 /* genSend - gen code for SEND */
2071 /*-----------------------------------------------------------------*/
2072 static void genSend(set *sendSet)
2077 for (sic = setFirstItem (_G.sendSet); sic;
2078 sic = setNextItem (_G.sendSet)) {
2079 int size, offset = 0;
2080 aopOp (IC_LEFT (sic), sic, FALSE);
2081 size = AOP_SIZE (IC_LEFT (sic));
2083 if (sic->argreg == 1) {
2085 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2087 if (strcmp (l, fReturn[offset]))
2088 emitcode ("mov", "%s,%s", fReturn[offset], l);
2094 emitcode ("mov","b1_%d,%s",rb1_count++,
2095 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2098 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2102 /*-----------------------------------------------------------------*/
2103 /* genCall - generates a call statement */
2104 /*-----------------------------------------------------------------*/
2106 genCall (iCode * ic)
2109 // bool restoreBank = FALSE;
2110 bool swapBanks = FALSE;
2112 D(emitcode("; genCall",""));
2114 dtype = operandType (IC_LEFT (ic));
2115 /* if send set is not empty the assign */
2118 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2119 genSend(reverseSet(_G.sendSet));
2121 genSend(_G.sendSet);
2127 /* if we are calling a not _naked function that is not using
2128 the same register bank then we need to save the
2129 destination registers on the stack */
2130 dtype = operandType (IC_LEFT (ic));
2131 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2132 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2133 !IFFUNC_ISISR (dtype))
2138 /* if caller saves & we have not saved then */
2144 emitcode ("mov", "psw,#0x%02x",
2145 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2149 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2150 OP_SYMBOL (IC_LEFT (ic))->rname :
2151 OP_SYMBOL (IC_LEFT (ic))->name));
2155 emitcode ("mov", "psw,#0x%02x",
2156 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2159 /* if we need assign a result value */
2160 if ((IS_ITEMP (IC_RESULT (ic)) &&
2161 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2162 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2163 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2164 IS_TRUE_SYMOP (IC_RESULT (ic)))
2168 aopOp (IC_RESULT (ic), ic, FALSE);
2171 assignResultValue (IC_RESULT (ic));
2173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2176 /* adjust the stack for parameters if
2181 if (ic->parmBytes > 3)
2183 emitcode ("mov", "a,%s", spname);
2184 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2185 emitcode ("mov", "%s,a", spname);
2188 for (i = 0; i < ic->parmBytes; i++)
2189 emitcode ("dec", "%s", spname);
2192 /* if we hade saved some registers then unsave them */
2193 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2194 unsaveRegisters (ic);
2196 // /* if register bank was saved then pop them */
2198 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2201 /*-----------------------------------------------------------------*/
2202 /* -10l - generates a call by pointer statement */
2203 /*-----------------------------------------------------------------*/
2205 genPcall (iCode * ic)
2208 symbol *rlbl = newiTempLabel (NULL);
2209 // bool restoreBank=FALSE;
2210 bool swapBanks = FALSE;
2212 D(emitcode("; genPCall",""));
2214 /* if caller saves & we have not saved then */
2218 /* if we are calling a not _naked function that is not using
2219 the same register bank then we need to save the
2220 destination registers on the stack */
2221 dtype = operandType (IC_LEFT (ic))->next;
2222 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2223 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2224 !IFFUNC_ISISR (dtype))
2226 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2227 // restoreBank=TRUE;
2229 // need caution message to user here
2232 /* push the return address on to the stack */
2233 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2234 emitcode ("push", "acc");
2235 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2236 emitcode ("push", "acc");
2238 /* now push the calling address */
2239 aopOp (IC_LEFT (ic), ic, FALSE);
2241 pushSide (IC_LEFT (ic), FPTRSIZE);
2243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2245 /* if send set is not empty the assign */
2248 genSend(reverseSet(_G.sendSet));
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2259 emitcode ("ret", "");
2260 emitcode ("", "%05d$:", (rlbl->key + 100));
2265 emitcode ("mov", "psw,#0x%02x",
2266 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2269 /* if we need assign a result value */
2270 if ((IS_ITEMP (IC_RESULT (ic)) &&
2271 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2272 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2273 IS_TRUE_SYMOP (IC_RESULT (ic)))
2277 aopOp (IC_RESULT (ic), ic, FALSE);
2280 assignResultValue (IC_RESULT (ic));
2282 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2285 /* adjust the stack for parameters if
2290 if (ic->parmBytes > 3)
2292 emitcode ("mov", "a,%s", spname);
2293 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2294 emitcode ("mov", "%s,a", spname);
2297 for (i = 0; i < ic->parmBytes; i++)
2298 emitcode ("dec", "%s", spname);
2302 // /* if register bank was saved then unsave them */
2304 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2306 /* if we hade saved some registers then
2308 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2309 unsaveRegisters (ic);
2312 /*-----------------------------------------------------------------*/
2313 /* resultRemat - result is rematerializable */
2314 /*-----------------------------------------------------------------*/
2316 resultRemat (iCode * ic)
2318 if (SKIP_IC (ic) || ic->op == IFX)
2321 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2323 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2324 if (sym->remat && !POINTER_SET (ic))
2331 #if defined(__BORLANDC__) || defined(_MSC_VER)
2332 #define STRCASECMP stricmp
2334 #define STRCASECMP strcasecmp
2337 /*-----------------------------------------------------------------*/
2338 /* inExcludeList - return 1 if the string is in exclude Reg list */
2339 /*-----------------------------------------------------------------*/
2341 regsCmp(void *p1, void *p2)
2343 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2347 inExcludeList (char *s)
2349 const char *p = setFirstItem(options.excludeRegsSet);
2351 if (p == NULL || STRCASECMP(p, "none") == 0)
2355 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2358 /*-----------------------------------------------------------------*/
2359 /* genFunction - generated code for function entry */
2360 /*-----------------------------------------------------------------*/
2362 genFunction (iCode * ic)
2366 bool switchedPSW = FALSE;
2367 int calleesaves_saved_register = -1;
2370 /* create the function header */
2371 emitcode (";", "-----------------------------------------");
2372 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2373 emitcode (";", "-----------------------------------------");
2375 emitcode ("", "%s:", sym->rname);
2376 ftype = operandType (IC_LEFT (ic));
2377 _G.currentFunc = sym;
2379 if (IFFUNC_ISNAKED(ftype))
2381 emitcode(";", "naked function: no prologue.");
2385 /* here we need to generate the equates for the
2386 register bank if required */
2387 if (FUNC_REGBANK (ftype) != rbank)
2391 rbank = FUNC_REGBANK (ftype);
2392 for (i = 0; i < mcs51_nRegs; i++)
2394 if (strcmp (regs8051[i].base, "0") == 0)
2395 emitcode ("", "%s = 0x%02x",
2397 8 * rbank + regs8051[i].offset);
2399 emitcode ("", "%s = %s + 0x%02x",
2402 8 * rbank + regs8051[i].offset);
2406 /* if this is an interrupt service routine then
2407 save acc, b, dpl, dph */
2408 if (IFFUNC_ISISR (sym->type))
2411 if (!inExcludeList ("acc"))
2412 emitcode ("push", "acc");
2413 if (!inExcludeList ("b"))
2414 emitcode ("push", "b");
2415 if (!inExcludeList ("dpl"))
2416 emitcode ("push", "dpl");
2417 if (!inExcludeList ("dph"))
2418 emitcode ("push", "dph");
2419 /* if this isr has no bank i.e. is going to
2420 run with bank 0 , then we need to save more
2422 if (!FUNC_REGBANK (sym->type))
2425 /* if this function does not call any other
2426 function then we can be economical and
2427 save only those registers that are used */
2428 if (!IFFUNC_HASFCALL(sym->type))
2432 /* if any registers used */
2435 /* save the registers used */
2436 for (i = 0; i < sym->regsUsed->size; i++)
2438 if (bitVectBitValue (sym->regsUsed, i) ||
2439 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2440 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2448 /* this function has a function call cannot
2449 determines register usage so we will have to push the
2451 saveRBank (0, ic, FALSE);
2452 if (options.parms_in_bank1) {
2454 for (i=0; i < 8 ; i++ ) {
2455 emitcode ("push","%s",rb1regs[i]);
2462 /* This ISR uses a non-zero bank.
2464 * We assume that the bank is available for our
2467 * However, if this ISR calls a function which uses some
2468 * other bank, we must save that bank entirely.
2470 unsigned long banksToSave = 0;
2472 if (IFFUNC_HASFCALL(sym->type))
2475 #define MAX_REGISTER_BANKS 4
2480 for (i = ic; i; i = i->next)
2482 if (i->op == ENDFUNCTION)
2484 /* we got to the end OK. */
2492 dtype = operandType (IC_LEFT(i));
2494 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2496 /* Mark this bank for saving. */
2497 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2499 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2503 banksToSave |= (1 << FUNC_REGBANK(dtype));
2506 /* And note that we don't need to do it in
2514 /* This is a mess; we have no idea what
2515 * register bank the called function might
2518 * The only thing I can think of to do is
2519 * throw a warning and hope.
2521 werror(W_FUNCPTR_IN_USING_ISR);
2525 if (banksToSave && options.useXstack)
2527 /* Since we aren't passing it an ic,
2528 * saveRBank will assume r0 is available to abuse.
2530 * So switch to our (trashable) bank now, so
2531 * the caller's R0 isn't trashed.
2533 emitcode ("push", "psw");
2534 emitcode ("mov", "psw,#0x%02x",
2535 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2539 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2541 if (banksToSave & (1 << ix))
2543 saveRBank(ix, NULL, FALSE);
2547 // TODO: this needs a closer look
2548 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2553 /* if callee-save to be used for this function
2554 then save the registers being used in this function */
2555 if (IFFUNC_CALLEESAVES(sym->type))
2559 /* if any registers used */
2562 /* save the registers used */
2563 for (i = 0; i < sym->regsUsed->size; i++)
2565 if (bitVectBitValue (sym->regsUsed, i) ||
2566 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2568 /* remember one saved register for later usage */
2569 if (calleesaves_saved_register < 0)
2570 calleesaves_saved_register = i;
2571 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2579 /* set the register bank to the desired value */
2580 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2583 emitcode ("push", "psw");
2584 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2587 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2590 if (options.useXstack)
2592 emitcode ("mov", "r0,%s", spname);
2593 emitcode ("mov", "a,_bp");
2594 emitcode ("movx", "@r0,a");
2595 emitcode ("inc", "%s", spname);
2599 /* set up the stack */
2600 emitcode ("push", "_bp"); /* save the callers stack */
2602 emitcode ("mov", "_bp,%s", spname);
2605 /* adjust the stack for the function */
2611 werror (W_STACK_OVERFLOW, sym->name);
2613 if (i > 3 && sym->recvSize < 4)
2616 emitcode ("mov", "a,sp");
2617 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2618 emitcode ("mov", "sp,a");
2623 if (IFFUNC_CALLEESAVES(sym->type))
2625 /* if it's a callee-saves function we need a saved register */
2626 if (calleesaves_saved_register >= 0)
2628 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2629 emitcode ("mov", "a,sp");
2630 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2631 emitcode ("mov", "sp,a");
2632 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2635 /* do it the hard way */
2637 emitcode ("inc", "sp");
2641 /* not callee-saves, we can clobber r0 */
2642 emitcode ("mov", "r0,a");
2643 emitcode ("mov", "a,sp");
2644 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2645 emitcode ("mov", "sp,a");
2646 emitcode ("mov", "a,r0");
2651 emitcode ("inc", "sp");
2657 emitcode ("mov", "a,_spx");
2658 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2659 emitcode ("mov", "_spx,a");
2662 /* if critical function then turn interrupts off */
2663 if (IFFUNC_ISCRITICAL (ftype))
2665 symbol *tlbl = newiTempLabel (NULL);
2666 emitcode ("setb", "c");
2667 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2668 emitcode ("clr", "c");
2669 emitcode ("", "%05d$:", (tlbl->key + 100));
2670 emitcode ("push", "psw"); /* save old ea via c in psw */
2674 /*-----------------------------------------------------------------*/
2675 /* genEndFunction - generates epilogue for functions */
2676 /*-----------------------------------------------------------------*/
2678 genEndFunction (iCode * ic)
2680 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2682 _G.currentFunc = NULL;
2683 if (IFFUNC_ISNAKED(sym->type))
2685 emitcode(";", "naked function: no epilogue.");
2689 if (IFFUNC_ISCRITICAL (sym->type))
2691 emitcode ("pop", "psw"); /* restore ea via c in psw */
2692 emitcode ("mov", "ea,c");
2695 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2697 emitcode ("mov", "%s,_bp", spname);
2700 /* if use external stack but some variables were
2701 added to the local stack then decrement the
2703 if (options.useXstack && sym->stack)
2705 emitcode ("mov", "a,sp");
2706 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2707 emitcode ("mov", "sp,a");
2711 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2713 if (options.useXstack)
2715 emitcode ("mov", "r0,%s", spname);
2716 emitcode ("movx", "a,@r0");
2717 emitcode ("mov", "_bp,a");
2718 emitcode ("dec", "%s", spname);
2722 emitcode ("pop", "_bp");
2726 /* restore the register bank */
2727 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2729 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2730 || !options.useXstack)
2732 /* Special case of ISR using non-zero bank with useXstack
2735 emitcode ("pop", "psw");
2739 if (IFFUNC_ISISR (sym->type))
2742 /* now we need to restore the registers */
2743 /* if this isr has no bank i.e. is going to
2744 run with bank 0 , then we need to save more
2746 if (!FUNC_REGBANK (sym->type))
2748 /* if this function does not call any other
2749 function then we can be economical and
2750 save only those registers that are used */
2751 if (!IFFUNC_HASFCALL(sym->type))
2755 /* if any registers used */
2758 /* save the registers used */
2759 for (i = sym->regsUsed->size; i >= 0; i--)
2761 if (bitVectBitValue (sym->regsUsed, i) ||
2762 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2763 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2770 if (options.parms_in_bank1) {
2772 for (i = 7 ; i >= 0 ; i-- ) {
2773 emitcode ("pop","%s",rb1regs[i]);
2776 /* this function has a function call cannot
2777 determines register usage so we will have to pop the
2779 unsaveRBank (0, ic, FALSE);
2784 /* This ISR uses a non-zero bank.
2786 * Restore any register banks saved by genFunction
2789 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2792 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2794 if (savedBanks & (1 << ix))
2796 unsaveRBank(ix, NULL, FALSE);
2800 if (options.useXstack)
2802 /* Restore bank AFTER calling unsaveRBank,
2803 * since it can trash r0.
2805 emitcode ("pop", "psw");
2809 if (!inExcludeList ("dph"))
2810 emitcode ("pop", "dph");
2811 if (!inExcludeList ("dpl"))
2812 emitcode ("pop", "dpl");
2813 if (!inExcludeList ("b"))
2814 emitcode ("pop", "b");
2815 if (!inExcludeList ("acc"))
2816 emitcode ("pop", "acc");
2818 /* if debug then send end of function */
2819 if (options.debug && currFunc)
2822 emitcode ("", "C$%s$%d$%d$%d ==.",
2823 FileBaseName (ic->filename), currFunc->lastLine,
2824 ic->level, ic->block);
2825 if (IS_STATIC (currFunc->etype))
2826 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2828 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2832 emitcode ("reti", "");
2836 if (IFFUNC_CALLEESAVES(sym->type))
2840 /* if any registers used */
2843 /* save the registers used */
2844 for (i = sym->regsUsed->size; i >= 0; i--)
2846 if (bitVectBitValue (sym->regsUsed, i) ||
2847 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2848 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2854 /* if debug then send end of function */
2855 if (options.debug && currFunc)
2858 emitcode ("", "C$%s$%d$%d$%d ==.",
2859 FileBaseName (ic->filename), currFunc->lastLine,
2860 ic->level, ic->block);
2861 if (IS_STATIC (currFunc->etype))
2862 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2864 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2868 emitcode ("ret", "");
2873 /*-----------------------------------------------------------------*/
2874 /* genRet - generate code for return statement */
2875 /*-----------------------------------------------------------------*/
2879 int size, offset = 0, pushed = 0;
2881 D(emitcode ("; genRet",""));
2883 /* if we have no return value then
2884 just generate the "ret" */
2888 /* we have something to return then
2889 move the return value into place */
2890 aopOp (IC_LEFT (ic), ic, FALSE);
2891 size = AOP_SIZE (IC_LEFT (ic));
2896 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2899 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2901 emitcode ("push", "%s", l);
2906 l = aopGet (AOP (IC_LEFT (ic)), offset,
2908 if (strcmp (fReturn[offset], l))
2909 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2918 if (strcmp (fReturn[pushed], "a"))
2919 emitcode ("pop", fReturn[pushed]);
2921 emitcode ("pop", "acc");
2924 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2927 /* generate a jump to the return label
2928 if the next is not the return statement */
2929 if (!(ic->next && ic->next->op == LABEL &&
2930 IC_LABEL (ic->next) == returnLabel))
2932 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2936 /*-----------------------------------------------------------------*/
2937 /* genLabel - generates a label */
2938 /*-----------------------------------------------------------------*/
2940 genLabel (iCode * ic)
2942 /* special case never generate */
2943 if (IC_LABEL (ic) == entryLabel)
2946 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2949 /*-----------------------------------------------------------------*/
2950 /* genGoto - generates a ljmp */
2951 /*-----------------------------------------------------------------*/
2953 genGoto (iCode * ic)
2955 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2958 /*-----------------------------------------------------------------*/
2959 /* findLabelBackwards: walks back through the iCode chain looking */
2960 /* for the given label. Returns number of iCode instructions */
2961 /* between that label and given ic. */
2962 /* Returns zero if label not found. */
2963 /*-----------------------------------------------------------------*/
2965 findLabelBackwards (iCode * ic, int key)
2974 /* If we have any pushes or pops, we cannot predict the distance.
2975 I don't like this at all, this should be dealt with in the
2977 if (ic->op == IPUSH || ic->op == IPOP) {
2981 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2990 /*-----------------------------------------------------------------*/
2991 /* genPlusIncr :- does addition with increment if possible */
2992 /*-----------------------------------------------------------------*/
2994 genPlusIncr (iCode * ic)
2996 unsigned int icount;
2997 unsigned int size = getDataSize (IC_RESULT (ic));
2999 /* will try to generate an increment */
3000 /* if the right side is not a literal
3002 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3005 /* if the literal value of the right hand side
3006 is greater than 4 then it is not worth it */
3007 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3010 D(emitcode ("; genPlusIncr",""));
3012 /* if increment >=16 bits in register or direct space */
3013 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3014 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3022 /* If the next instruction is a goto and the goto target
3023 * is < 10 instructions previous to this, we can generate
3024 * jumps straight to that target.
3026 if (ic->next && ic->next->op == GOTO
3027 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3028 && labelRange <= 10)
3030 emitcode (";", "tail increment optimized");
3031 tlbl = IC_LABEL (ic->next);
3036 tlbl = newiTempLabel (NULL);
3039 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3040 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3041 IS_AOP_PREG (IC_RESULT (ic)))
3042 emitcode ("cjne", "%s,#0x00,%05d$",
3043 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3047 emitcode ("clr", "a");
3048 emitcode ("cjne", "a,%s,%05d$",
3049 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3053 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3056 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3057 IS_AOP_PREG (IC_RESULT (ic)))
3058 emitcode ("cjne", "%s,#0x00,%05d$",
3059 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3062 emitcode ("cjne", "a,%s,%05d$",
3063 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3066 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3070 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3071 IS_AOP_PREG (IC_RESULT (ic)))
3072 emitcode ("cjne", "%s,#0x00,%05d$",
3073 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3077 emitcode ("cjne", "a,%s,%05d$",
3078 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3081 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3086 emitcode ("", "%05d$:", tlbl->key + 100);
3091 /* if the sizes are greater than 1 then we cannot */
3092 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3093 AOP_SIZE (IC_LEFT (ic)) > 1)
3096 /* we can if the aops of the left & result match or
3097 if they are in registers and the registers are the
3099 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3104 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3105 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3106 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3112 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3121 /*-----------------------------------------------------------------*/
3122 /* outBitAcc - output a bit in acc */
3123 /*-----------------------------------------------------------------*/
3125 outBitAcc (operand * result)
3127 symbol *tlbl = newiTempLabel (NULL);
3128 /* if the result is a bit */
3129 if (AOP_TYPE (result) == AOP_CRY)
3131 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3135 emitcode ("jz", "%05d$", tlbl->key + 100);
3136 emitcode ("mov", "a,%s", one);
3137 emitcode ("", "%05d$:", tlbl->key + 100);
3142 /*-----------------------------------------------------------------*/
3143 /* genPlusBits - generates code for addition of two bits */
3144 /*-----------------------------------------------------------------*/
3146 genPlusBits (iCode * ic)
3148 D(emitcode ("; genPlusBits",""));
3150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3152 symbol *lbl = newiTempLabel (NULL);
3153 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3154 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3155 emitcode ("cpl", "c");
3156 emitcode ("", "%05d$:", (lbl->key + 100));
3157 outBitC (IC_RESULT (ic));
3161 emitcode ("clr", "a");
3162 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3163 emitcode ("rlc", "a");
3164 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3165 emitcode ("addc", "a,#0x00");
3166 outAcc (IC_RESULT (ic));
3171 /* This is the original version of this code.
3173 * This is being kept around for reference,
3174 * because I am not entirely sure I got it right...
3177 adjustArithmeticResult (iCode * ic)
3179 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3180 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3181 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3182 aopPut (AOP (IC_RESULT (ic)),
3183 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3185 isOperandVolatile (IC_RESULT (ic), FALSE));
3187 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3188 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3189 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3190 aopPut (AOP (IC_RESULT (ic)),
3191 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3193 isOperandVolatile (IC_RESULT (ic), FALSE));
3195 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3196 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3197 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3198 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3199 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3202 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3203 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3207 /* This is the pure and virtuous version of this code.
3208 * I'm pretty certain it's right, but not enough to toss the old
3212 adjustArithmeticResult (iCode * ic)
3214 if (opIsGptr (IC_RESULT (ic)) &&
3215 opIsGptr (IC_LEFT (ic)) &&
3216 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3218 aopPut (AOP (IC_RESULT (ic)),
3219 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3221 isOperandVolatile (IC_RESULT (ic), FALSE));
3224 if (opIsGptr (IC_RESULT (ic)) &&
3225 opIsGptr (IC_RIGHT (ic)) &&
3226 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3228 aopPut (AOP (IC_RESULT (ic)),
3229 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3231 isOperandVolatile (IC_RESULT (ic), FALSE));
3234 if (opIsGptr (IC_RESULT (ic)) &&
3235 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3236 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3237 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3238 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3241 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3242 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3247 /*-----------------------------------------------------------------*/
3248 /* genPlus - generates code for addition */
3249 /*-----------------------------------------------------------------*/
3251 genPlus (iCode * ic)
3253 int size, offset = 0;
3256 asmop *leftOp, *rightOp;
3259 /* special cases :- */
3261 D(emitcode ("; genPlus",""));
3263 aopOp (IC_LEFT (ic), ic, FALSE);
3264 aopOp (IC_RIGHT (ic), ic, FALSE);
3265 aopOp (IC_RESULT (ic), ic, TRUE);
3267 /* if literal, literal on the right or
3268 if left requires ACC or right is already
3270 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3271 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3272 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3274 operand *t = IC_RIGHT (ic);
3275 IC_RIGHT (ic) = IC_LEFT (ic);
3279 /* if both left & right are in bit
3281 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3282 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3288 /* if left in bit space & right literal */
3289 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3290 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3292 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3293 /* if result in bit space */
3294 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3296 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3297 emitcode ("cpl", "c");
3298 outBitC (IC_RESULT (ic));
3302 size = getDataSize (IC_RESULT (ic));
3305 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3306 emitcode ("addc", "a,#00");
3307 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3313 /* if I can do an increment instead
3314 of add then GOOD for ME */
3315 if (genPlusIncr (ic) == TRUE)
3318 size = getDataSize (IC_RESULT (ic));
3319 leftOp = AOP(IC_LEFT(ic));
3320 rightOp = AOP(IC_RIGHT(ic));
3323 /* if this is an add for an array access
3324 at a 256 byte boundary */
3326 && AOP_TYPE (op) == AOP_IMMD
3328 && IS_SPEC (OP_SYM_ETYPE (op))
3329 && SPEC_ABSA (OP_SYM_ETYPE (op))
3330 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3333 D(emitcode ("; genPlus aligned array",""));
3334 aopPut (AOP (IC_RESULT (ic)),
3335 aopGet (rightOp, 0, FALSE, FALSE),
3337 isOperandVolatile (IC_RESULT (ic), FALSE));
3339 if( 1 == getDataSize (IC_RIGHT (ic)) )
3341 aopPut (AOP (IC_RESULT (ic)),
3342 aopGet (leftOp, 1, FALSE, FALSE),
3344 isOperandVolatile (IC_RESULT (ic), FALSE));
3348 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3349 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3350 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3355 /* if the lower bytes of a literal are zero skip the addition */
3356 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3358 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3359 (skip_bytes+1 < size))
3364 D(emitcode ("; genPlus shortcut",""));
3369 if( offset >= skip_bytes )
3371 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3373 emitcode("mov", "b,a");
3374 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3375 emitcode("xch", "a,b");
3376 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3377 emitcode (add, "a,b");
3379 else if (aopGetUsesAcc (leftOp, offset))
3381 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3382 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3386 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3387 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3389 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3390 add = "addc"; /* further adds must propagate carry */
3394 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3395 isOperandVolatile (IC_RESULT (ic), FALSE))
3398 aopPut (AOP (IC_RESULT (ic)),
3399 aopGet (leftOp, offset, FALSE, FALSE),
3401 isOperandVolatile (IC_RESULT (ic), FALSE));
3407 adjustArithmeticResult (ic);
3410 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3411 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3412 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3415 /*-----------------------------------------------------------------*/
3416 /* genMinusDec :- does subtraction with deccrement if possible */
3417 /*-----------------------------------------------------------------*/
3419 genMinusDec (iCode * ic)
3421 unsigned int icount;
3422 unsigned int size = getDataSize (IC_RESULT (ic));
3424 /* will try to generate an increment */
3425 /* if the right side is not a literal
3427 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3430 /* if the literal value of the right hand side
3431 is greater than 4 then it is not worth it */
3432 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3435 D(emitcode ("; genMinusDec",""));
3437 /* if decrement >=16 bits in register or direct space */
3438 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3439 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3447 /* If the next instruction is a goto and the goto target
3448 * is <= 10 instructions previous to this, we can generate
3449 * jumps straight to that target.
3451 if (ic->next && ic->next->op == GOTO
3452 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3453 && labelRange <= 10)
3455 emitcode (";", "tail decrement optimized");
3456 tlbl = IC_LABEL (ic->next);
3461 tlbl = newiTempLabel (NULL);
3465 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3466 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3467 IS_AOP_PREG (IC_RESULT (ic)))
3468 emitcode ("cjne", "%s,#0xff,%05d$"
3469 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3473 emitcode ("mov", "a,#0xff");
3474 emitcode ("cjne", "a,%s,%05d$"
3475 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3478 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3481 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3482 IS_AOP_PREG (IC_RESULT (ic)))
3483 emitcode ("cjne", "%s,#0xff,%05d$"
3484 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3488 emitcode ("cjne", "a,%s,%05d$"
3489 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3492 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3496 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3497 IS_AOP_PREG (IC_RESULT (ic)))
3498 emitcode ("cjne", "%s,#0xff,%05d$"
3499 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3503 emitcode ("cjne", "a,%s,%05d$"
3504 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3507 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3511 emitcode ("", "%05d$:", tlbl->key + 100);
3516 /* if the sizes are greater than 1 then we cannot */
3517 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3518 AOP_SIZE (IC_LEFT (ic)) > 1)
3521 /* we can if the aops of the left & result match or
3522 if they are in registers and the registers are the
3524 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3528 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3536 /*-----------------------------------------------------------------*/
3537 /* addSign - complete with sign */
3538 /*-----------------------------------------------------------------*/
3540 addSign (operand * result, int offset, int sign)
3542 int size = (getDataSize (result) - offset);
3547 emitcode ("rlc", "a");
3548 emitcode ("subb", "a,acc");
3550 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3554 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3558 /*-----------------------------------------------------------------*/
3559 /* genMinusBits - generates code for subtraction of two bits */
3560 /*-----------------------------------------------------------------*/
3562 genMinusBits (iCode * ic)
3564 symbol *lbl = newiTempLabel (NULL);
3566 D(emitcode ("; genMinusBits",""));
3568 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3570 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3571 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3572 emitcode ("cpl", "c");
3573 emitcode ("", "%05d$:", (lbl->key + 100));
3574 outBitC (IC_RESULT (ic));
3578 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3579 emitcode ("subb", "a,acc");
3580 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3581 emitcode ("inc", "a");
3582 emitcode ("", "%05d$:", (lbl->key + 100));
3583 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3584 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3588 /*-----------------------------------------------------------------*/
3589 /* genMinus - generates code for subtraction */
3590 /*-----------------------------------------------------------------*/
3592 genMinus (iCode * ic)
3594 int size, offset = 0;
3596 D(emitcode ("; genMinus",""));
3598 aopOp (IC_LEFT (ic), ic, FALSE);
3599 aopOp (IC_RIGHT (ic), ic, FALSE);
3600 aopOp (IC_RESULT (ic), ic, TRUE);
3602 /* special cases :- */
3603 /* if both left & right are in bit space */
3604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3605 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3611 /* if I can do an decrement instead
3612 of subtract then GOOD for ME */
3613 if (genMinusDec (ic) == TRUE)
3616 size = getDataSize (IC_RESULT (ic));
3618 /* if literal, add a,#-lit, else normal subb */
3619 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3621 unsigned long lit = 0L;
3623 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3628 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3629 /* first add without previous c */
3631 if (!size && lit== (unsigned long) -1) {
3632 emitcode ("dec", "a");
3634 emitcode ("add", "a,#0x%02x",
3635 (unsigned int) (lit & 0x0FFL));
3638 emitcode ("addc", "a,#0x%02x",
3639 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3641 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3646 asmop *leftOp, *rightOp;
3648 leftOp = AOP(IC_LEFT(ic));
3649 rightOp = AOP(IC_RIGHT(ic));
3653 if (aopGetUsesAcc(rightOp, offset)) {
3654 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3655 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3657 emitcode( "setb", "c");
3659 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3660 emitcode("cpl", "a");
3662 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3665 emitcode ("subb", "a,%s",
3666 aopGet(rightOp, offset, FALSE, TRUE));
3669 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3674 adjustArithmeticResult (ic);
3677 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3678 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3683 /*-----------------------------------------------------------------*/
3684 /* genMultbits :- multiplication of bits */
3685 /*-----------------------------------------------------------------*/
3687 genMultbits (operand * left,
3691 D(emitcode ("; genMultbits",""));
3693 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3694 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3699 /*-----------------------------------------------------------------*/
3700 /* genMultOneByte : 8*8=8/16 bit multiplication */
3701 /*-----------------------------------------------------------------*/
3703 genMultOneByte (operand * left,
3707 sym_link *opetype = operandType (result);
3709 int size=AOP_SIZE(result);
3711 D(emitcode ("; genMultOneByte",""));
3713 if (size<1 || size>2) {
3714 // this should never happen
3715 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3716 AOP_SIZE(result), __FILE__, lineno);
3720 /* (if two literals: the value is computed before) */
3721 /* if one literal, literal on the right */
3722 if (AOP_TYPE (left) == AOP_LIT)
3727 //emitcode (";", "swapped left and right");
3730 if (SPEC_USIGN(opetype)
3731 // ignore the sign of left and right, what else can we do?
3732 || (SPEC_USIGN(operandType(left)) &&
3733 SPEC_USIGN(operandType(right)))) {
3734 // just an unsigned 8*8=8/16 multiply
3735 //emitcode (";","unsigned");
3736 // TODO: check for accumulator clash between left & right aops?
3738 if( AOP_TYPE(right)==AOP_LIT ){
3739 // moving to accumulator first helps peepholes
3740 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3741 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3743 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3744 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3747 emitcode ("mul", "ab");
3748 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3750 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3755 // we have to do a signed multiply
3757 //emitcode (";", "signed");
3758 emitcode ("clr", "F0"); // reset sign flag
3759 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3761 lbl=newiTempLabel(NULL);
3762 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3763 // left side is negative, 8-bit two's complement, this fails for -128
3764 emitcode ("setb", "F0"); // set sign flag
3765 emitcode ("cpl", "a");
3766 emitcode ("inc", "a");
3768 emitcode ("", "%05d$:", lbl->key+100);
3771 if (AOP_TYPE(right)==AOP_LIT) {
3772 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3773 /* AND literal negative */
3775 emitcode ("cpl", "F0"); // complement sign flag
3776 emitcode ("mov", "b,#0x%02x", -val);
3778 emitcode ("mov", "b,#0x%02x", val);
3781 lbl=newiTempLabel(NULL);
3782 emitcode ("mov", "b,a");
3783 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3784 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3785 // right side is negative, 8-bit two's complement
3786 emitcode ("cpl", "F0"); // complement sign flag
3787 emitcode ("cpl", "a");
3788 emitcode ("inc", "a");
3789 emitcode ("", "%05d$:", lbl->key+100);
3791 emitcode ("mul", "ab");
3793 lbl=newiTempLabel(NULL);
3794 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3795 // only ONE op was negative, we have to do a 8/16-bit two's complement
3796 emitcode ("cpl", "a"); // lsb
3798 emitcode ("inc", "a");
3800 emitcode ("add", "a,#1");
3801 emitcode ("xch", "a,b");
3802 emitcode ("cpl", "a"); // msb
3803 emitcode ("addc", "a,#0");
3804 emitcode ("xch", "a,b");
3807 emitcode ("", "%05d$:", lbl->key+100);
3808 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3810 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3814 /*-----------------------------------------------------------------*/
3815 /* genMult - generates code for multiplication */
3816 /*-----------------------------------------------------------------*/
3818 genMult (iCode * ic)
3820 operand *left = IC_LEFT (ic);
3821 operand *right = IC_RIGHT (ic);
3822 operand *result = IC_RESULT (ic);
3824 D(emitcode ("; genMult",""));
3826 /* assign the amsops */
3827 aopOp (left, ic, FALSE);
3828 aopOp (right, ic, FALSE);
3829 aopOp (result, ic, TRUE);
3831 /* special cases first */
3833 if (AOP_TYPE (left) == AOP_CRY &&
3834 AOP_TYPE (right) == AOP_CRY)
3836 genMultbits (left, right, result);
3840 /* if both are of size == 1 */
3841 #if 0 // one of them can be a sloc shared with the result
3842 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3844 if (getSize(operandType(left)) == 1 &&
3845 getSize(operandType(right)) == 1)
3848 genMultOneByte (left, right, result);
3852 /* should have been converted to function call */
3853 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3854 getSize(OP_SYMBOL(right)->type));
3858 freeAsmop (result, NULL, ic, TRUE);
3859 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3860 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3863 /*-----------------------------------------------------------------*/
3864 /* genDivbits :- division of bits */
3865 /*-----------------------------------------------------------------*/
3867 genDivbits (operand * left,
3874 D(emitcode ("; genDivbits",""));
3876 /* the result must be bit */
3877 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3878 l = aopGet (AOP (left), 0, FALSE, FALSE);
3882 emitcode ("div", "ab");
3883 emitcode ("rrc", "a");
3884 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3887 /*-----------------------------------------------------------------*/
3888 /* genDivOneByte : 8 bit division */
3889 /*-----------------------------------------------------------------*/
3891 genDivOneByte (operand * left,
3895 sym_link *opetype = operandType (result);
3900 D(emitcode ("; genDivOneByte",""));
3902 size = AOP_SIZE (result) - 1;
3904 /* signed or unsigned */
3905 if (SPEC_USIGN (opetype))
3907 /* unsigned is easy */
3908 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3909 l = aopGet (AOP (left), 0, FALSE, FALSE);
3911 emitcode ("div", "ab");
3912 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3914 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3918 /* signed is a little bit more difficult */
3920 /* save the signs of the operands */
3921 l = aopGet (AOP (left), 0, FALSE, FALSE);
3923 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3924 emitcode ("push", "acc"); /* save it on the stack */
3926 /* now sign adjust for both left & right */
3927 l = aopGet (AOP (right), 0, FALSE, FALSE);
3929 lbl = newiTempLabel (NULL);
3930 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3931 emitcode ("cpl", "a");
3932 emitcode ("inc", "a");
3933 emitcode ("", "%05d$:", (lbl->key + 100));
3934 emitcode ("mov", "b,a");
3936 /* sign adjust left side */
3937 l = aopGet (AOP (left), 0, FALSE, FALSE);
3940 lbl = newiTempLabel (NULL);
3941 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3942 emitcode ("cpl", "a");
3943 emitcode ("inc", "a");
3944 emitcode ("", "%05d$:", (lbl->key + 100));
3946 /* now the division */
3947 emitcode ("div", "ab");
3948 /* we are interested in the lower order
3950 emitcode ("mov", "b,a");
3951 lbl = newiTempLabel (NULL);
3952 emitcode ("pop", "acc");
3953 /* if there was an over flow we don't
3954 adjust the sign of the result */
3955 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3956 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3958 emitcode ("clr", "a");
3959 emitcode ("subb", "a,b");
3960 emitcode ("mov", "b,a");
3961 emitcode ("", "%05d$:", (lbl->key + 100));
3963 /* now we are done */
3964 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3967 emitcode ("mov", "c,b.7");
3968 emitcode ("subb", "a,acc");
3971 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3975 /*-----------------------------------------------------------------*/
3976 /* genDiv - generates code for division */
3977 /*-----------------------------------------------------------------*/
3981 operand *left = IC_LEFT (ic);
3982 operand *right = IC_RIGHT (ic);
3983 operand *result = IC_RESULT (ic);
3985 D(emitcode ("; genDiv",""));
3987 /* assign the amsops */
3988 aopOp (left, ic, FALSE);
3989 aopOp (right, ic, FALSE);
3990 aopOp (result, ic, TRUE);
3992 /* special cases first */
3994 if (AOP_TYPE (left) == AOP_CRY &&
3995 AOP_TYPE (right) == AOP_CRY)
3997 genDivbits (left, right, result);
4001 /* if both are of size == 1 */
4002 if (AOP_SIZE (left) == 1 &&
4003 AOP_SIZE (right) == 1)
4005 genDivOneByte (left, right, result);
4009 /* should have been converted to function call */
4012 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4014 freeAsmop (result, NULL, ic, TRUE);
4017 /*-----------------------------------------------------------------*/
4018 /* genModbits :- modulus of bits */
4019 /*-----------------------------------------------------------------*/
4021 genModbits (operand * left,
4028 D(emitcode ("; genModbits",""));
4030 /* the result must be bit */
4031 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4032 l = aopGet (AOP (left), 0, FALSE, FALSE);
4036 emitcode ("div", "ab");
4037 emitcode ("mov", "a,b");
4038 emitcode ("rrc", "a");
4039 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4042 /*-----------------------------------------------------------------*/
4043 /* genModOneByte : 8 bit modulus */
4044 /*-----------------------------------------------------------------*/
4046 genModOneByte (operand * left,
4050 sym_link *opetype = operandType (result);
4054 D(emitcode ("; genModOneByte",""));
4056 /* signed or unsigned */
4057 if (SPEC_USIGN (opetype))
4059 /* unsigned is easy */
4060 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4061 l = aopGet (AOP (left), 0, FALSE, FALSE);
4063 emitcode ("div", "ab");
4064 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4068 /* signed is a little bit more difficult */
4070 /* save the signs of the operands */
4071 l = aopGet (AOP (left), 0, FALSE, FALSE);
4074 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4075 emitcode ("push", "acc"); /* save it on the stack */
4077 /* now sign adjust for both left & right */
4078 l = aopGet (AOP (right), 0, FALSE, FALSE);
4081 lbl = newiTempLabel (NULL);
4082 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4083 emitcode ("cpl", "a");
4084 emitcode ("inc", "a");
4085 emitcode ("", "%05d$:", (lbl->key + 100));
4086 emitcode ("mov", "b,a");
4088 /* sign adjust left side */
4089 l = aopGet (AOP (left), 0, FALSE, FALSE);
4092 lbl = newiTempLabel (NULL);
4093 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4094 emitcode ("cpl", "a");
4095 emitcode ("inc", "a");
4096 emitcode ("", "%05d$:", (lbl->key + 100));
4098 /* now the multiplication */
4099 emitcode ("div", "ab");
4100 /* we are interested in the lower order
4102 lbl = newiTempLabel (NULL);
4103 emitcode ("pop", "acc");
4104 /* if there was an over flow we don't
4105 adjust the sign of the result */
4106 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4107 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4109 emitcode ("clr", "a");
4110 emitcode ("subb", "a,b");
4111 emitcode ("mov", "b,a");
4112 emitcode ("", "%05d$:", (lbl->key + 100));
4114 /* now we are done */
4115 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4119 /*-----------------------------------------------------------------*/
4120 /* genMod - generates code for division */
4121 /*-----------------------------------------------------------------*/
4125 operand *left = IC_LEFT (ic);
4126 operand *right = IC_RIGHT (ic);
4127 operand *result = IC_RESULT (ic);
4129 D(emitcode ("; genMod",""));
4131 /* assign the amsops */
4132 aopOp (left, ic, FALSE);
4133 aopOp (right, ic, FALSE);
4134 aopOp (result, ic, TRUE);
4136 /* special cases first */
4138 if (AOP_TYPE (left) == AOP_CRY &&
4139 AOP_TYPE (right) == AOP_CRY)
4141 genModbits (left, right, result);
4145 /* if both are of size == 1 */
4146 if (AOP_SIZE (left) == 1 &&
4147 AOP_SIZE (right) == 1)
4149 genModOneByte (left, right, result);
4153 /* should have been converted to function call */
4157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4158 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4159 freeAsmop (result, NULL, ic, TRUE);
4162 /*-----------------------------------------------------------------*/
4163 /* genIfxJump :- will create a jump depending on the ifx */
4164 /*-----------------------------------------------------------------*/
4166 genIfxJump (iCode * ic, char *jval)
4169 symbol *tlbl = newiTempLabel (NULL);
4172 D(emitcode ("; genIfxJump",""));
4174 /* if true label then we jump if condition
4178 jlbl = IC_TRUE (ic);
4179 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4180 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4184 /* false label is present */
4185 jlbl = IC_FALSE (ic);
4186 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4187 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4189 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4190 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4192 emitcode (inst, "%05d$", tlbl->key + 100);
4193 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4194 emitcode ("", "%05d$:", tlbl->key + 100);
4196 /* mark the icode as generated */
4200 /*-----------------------------------------------------------------*/
4201 /* genCmp :- greater or less than comparison */
4202 /*-----------------------------------------------------------------*/
4204 genCmp (operand * left, operand * right,
4205 operand * result, iCode * ifx, int sign, iCode *ic)
4207 int size, offset = 0;
4208 unsigned long lit = 0L;
4211 D(emitcode ("; genCmp",""));
4213 /* if left & right are bit variables */
4214 if (AOP_TYPE (left) == AOP_CRY &&
4215 AOP_TYPE (right) == AOP_CRY)
4217 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4218 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4222 /* subtract right from left if at the
4223 end the carry flag is set then we know that
4224 left is greater than right */
4225 size = max (AOP_SIZE (left), AOP_SIZE (right));
4227 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4228 if ((size == 1) && !sign &&
4229 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4231 symbol *lbl = newiTempLabel (NULL);
4232 emitcode ("cjne", "%s,%s,%05d$",
4233 aopGet (AOP (left), offset, FALSE, FALSE),
4234 aopGet (AOP (right), offset, FALSE, FALSE),
4236 emitcode ("", "%05d$:", lbl->key + 100);
4240 if (AOP_TYPE (right) == AOP_LIT)
4242 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4243 /* optimize if(x < 0) or if(x >= 0) */
4252 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4253 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4255 genIfxJump (ifx, "acc.7");
4259 emitcode ("rlc", "a");
4267 rightInB = aopGetUsesAcc(AOP (right), offset);
4269 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4270 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4271 if (sign && size == 0)
4273 emitcode ("xrl", "a,#0x80");
4274 if (AOP_TYPE (right) == AOP_LIT)
4276 unsigned long lit = (unsigned long)
4277 floatFromVal (AOP (right)->aopu.aop_lit);
4278 emitcode ("subb", "a,#0x%02x",
4279 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4284 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4285 emitcode ("xrl", "b,#0x80");
4286 emitcode ("subb", "a,b");
4292 emitcode ("subb", "a,b");
4294 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4302 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4304 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4310 /* if the result is used in the next
4311 ifx conditional branch then generate
4312 code a little differently */
4314 genIfxJump (ifx, "c");
4317 /* leave the result in acc */
4321 /*-----------------------------------------------------------------*/
4322 /* genCmpGt :- greater than comparison */
4323 /*-----------------------------------------------------------------*/
4325 genCmpGt (iCode * ic, iCode * ifx)
4327 operand *left, *right, *result;
4328 sym_link *letype, *retype;
4331 D(emitcode ("; genCmpGt",""));
4333 left = IC_LEFT (ic);
4334 right = IC_RIGHT (ic);
4335 result = IC_RESULT (ic);
4337 letype = getSpec (operandType (left));
4338 retype = getSpec (operandType (right));
4339 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4340 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4341 /* assign the amsops */
4342 aopOp (left, ic, FALSE);
4343 aopOp (right, ic, FALSE);
4344 aopOp (result, ic, TRUE);
4346 genCmp (right, left, result, ifx, sign,ic);
4348 freeAsmop (result, NULL, ic, TRUE);
4351 /*-----------------------------------------------------------------*/
4352 /* genCmpLt - less than comparisons */
4353 /*-----------------------------------------------------------------*/
4355 genCmpLt (iCode * ic, iCode * ifx)
4357 operand *left, *right, *result;
4358 sym_link *letype, *retype;
4361 D(emitcode ("; genCmpLt",""));
4363 left = IC_LEFT (ic);
4364 right = IC_RIGHT (ic);
4365 result = IC_RESULT (ic);
4367 letype = getSpec (operandType (left));
4368 retype = getSpec (operandType (right));
4369 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4370 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4371 /* assign the amsops */
4372 aopOp (left, ic, FALSE);
4373 aopOp (right, ic, FALSE);
4374 aopOp (result, ic, TRUE);
4376 genCmp (left, right, result, ifx, sign,ic);
4378 freeAsmop (result, NULL, ic, TRUE);
4381 /*-----------------------------------------------------------------*/
4382 /* gencjneshort - compare and jump if not equal */
4383 /*-----------------------------------------------------------------*/
4385 gencjneshort (operand * left, operand * right, symbol * lbl)
4387 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4389 unsigned long lit = 0L;
4391 /* if the left side is a literal or
4392 if the right is in a pointer register and left
4394 if ((AOP_TYPE (left) == AOP_LIT) ||
4395 (AOP_TYPE (left) == AOP_IMMD) ||
4396 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4403 if (AOP_TYPE (right) == AOP_LIT)
4404 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4406 /* if the right side is a literal then anything goes */
4407 if (AOP_TYPE (right) == AOP_LIT &&
4408 AOP_TYPE (left) != AOP_DIR &&
4409 AOP_TYPE (left) != AOP_IMMD)
4413 emitcode ("cjne", "%s,%s,%05d$",
4414 aopGet (AOP (left), offset, FALSE, FALSE),
4415 aopGet (AOP (right), offset, FALSE, FALSE),
4421 /* if the right side is in a register or in direct space or
4422 if the left is a pointer register & right is not */
4423 else if (AOP_TYPE (right) == AOP_REG ||
4424 AOP_TYPE (right) == AOP_DIR ||
4425 AOP_TYPE (right) == AOP_LIT ||
4426 AOP_TYPE (right) == AOP_IMMD ||
4427 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4428 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4432 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4433 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4434 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4435 emitcode ("jnz", "%05d$", lbl->key + 100);
4437 emitcode ("cjne", "a,%s,%05d$",
4438 aopGet (AOP (right), offset, FALSE, TRUE),
4445 /* right is a pointer reg need both a & b */
4448 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4449 if (strcmp (l, "b"))
4450 emitcode ("mov", "b,%s", l);
4451 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4452 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4458 /*-----------------------------------------------------------------*/
4459 /* gencjne - compare and jump if not equal */
4460 /*-----------------------------------------------------------------*/
4462 gencjne (operand * left, operand * right, symbol * lbl)
4464 symbol *tlbl = newiTempLabel (NULL);
4466 gencjneshort (left, right, lbl);
4468 emitcode ("mov", "a,%s", one);
4469 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4470 emitcode ("", "%05d$:", lbl->key + 100);
4471 emitcode ("clr", "a");
4472 emitcode ("", "%05d$:", tlbl->key + 100);
4475 /*-----------------------------------------------------------------*/
4476 /* genCmpEq - generates code for equal to */
4477 /*-----------------------------------------------------------------*/
4479 genCmpEq (iCode * ic, iCode * ifx)
4481 operand *left, *right, *result;
4483 D(emitcode ("; genCmpEq",""));
4485 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4486 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4487 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4489 /* if literal, literal on the right or
4490 if the right is in a pointer register and left
4492 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4493 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4495 operand *t = IC_RIGHT (ic);
4496 IC_RIGHT (ic) = IC_LEFT (ic);
4500 if (ifx && !AOP_SIZE (result))
4503 /* if they are both bit variables */
4504 if (AOP_TYPE (left) == AOP_CRY &&
4505 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4507 if (AOP_TYPE (right) == AOP_LIT)
4509 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4512 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513 emitcode ("cpl", "c");
4517 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("clr", "c");
4523 /* AOP_TYPE(right) == AOP_CRY */
4527 symbol *lbl = newiTempLabel (NULL);
4528 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4529 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4530 emitcode ("cpl", "c");
4531 emitcode ("", "%05d$:", (lbl->key + 100));
4533 /* if true label then we jump if condition
4535 tlbl = newiTempLabel (NULL);
4538 emitcode ("jnc", "%05d$", tlbl->key + 100);
4539 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4543 emitcode ("jc", "%05d$", tlbl->key + 100);
4544 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4546 emitcode ("", "%05d$:", tlbl->key + 100);
4550 tlbl = newiTempLabel (NULL);
4551 gencjneshort (left, right, tlbl);
4554 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4555 emitcode ("", "%05d$:", tlbl->key + 100);
4559 symbol *lbl = newiTempLabel (NULL);
4560 emitcode ("sjmp", "%05d$", lbl->key + 100);
4561 emitcode ("", "%05d$:", tlbl->key + 100);
4562 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4563 emitcode ("", "%05d$:", lbl->key + 100);
4566 /* mark the icode as generated */
4571 /* if they are both bit variables */
4572 if (AOP_TYPE (left) == AOP_CRY &&
4573 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4575 if (AOP_TYPE (right) == AOP_LIT)
4577 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4580 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4581 emitcode ("cpl", "c");
4585 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4589 emitcode ("clr", "c");
4591 /* AOP_TYPE(right) == AOP_CRY */
4595 symbol *lbl = newiTempLabel (NULL);
4596 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4597 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4598 emitcode ("cpl", "c");
4599 emitcode ("", "%05d$:", (lbl->key + 100));
4602 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4609 genIfxJump (ifx, "c");
4612 /* if the result is used in an arithmetic operation
4613 then put the result in place */
4618 gencjne (left, right, newiTempLabel (NULL));
4619 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4621 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4626 genIfxJump (ifx, "a");
4629 /* if the result is used in an arithmetic operation
4630 then put the result in place */
4631 if (AOP_TYPE (result) != AOP_CRY)
4633 /* leave the result in acc */
4637 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4639 freeAsmop (result, NULL, ic, TRUE);
4642 /*-----------------------------------------------------------------*/
4643 /* ifxForOp - returns the icode containing the ifx for operand */
4644 /*-----------------------------------------------------------------*/
4646 ifxForOp (operand * op, iCode * ic)
4648 /* if true symbol then needs to be assigned */
4649 if (IS_TRUE_SYMOP (op))
4652 /* if this has register type condition and
4653 the next instruction is ifx with the same operand
4654 and live to of the operand is upto the ifx only then */
4656 ic->next->op == IFX &&
4657 IC_COND (ic->next)->key == op->key &&
4658 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4664 /*-----------------------------------------------------------------*/
4665 /* hasInc - operand is incremented before any other use */
4666 /*-----------------------------------------------------------------*/
4668 hasInc (operand *op, iCode *ic,int osize)
4670 sym_link *type = operandType(op);
4671 sym_link *retype = getSpec (type);
4672 iCode *lic = ic->next;
4675 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4676 if (!IS_SYMOP(op)) return NULL;
4678 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4679 if (IS_AGGREGATE(type->next)) return NULL;
4680 if (osize != (isize = getSize(type->next))) return NULL;
4683 /* if operand of the form op = op + <sizeof *op> */
4684 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4685 isOperandEqual(IC_RESULT(lic),op) &&
4686 isOperandLiteral(IC_RIGHT(lic)) &&
4687 operandLitValue(IC_RIGHT(lic)) == isize) {
4690 /* if the operand used or deffed */
4691 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4694 /* if GOTO or IFX */
4695 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4701 /*-----------------------------------------------------------------*/
4702 /* genAndOp - for && operation */
4703 /*-----------------------------------------------------------------*/
4705 genAndOp (iCode * ic)
4707 operand *left, *right, *result;
4710 D(emitcode ("; genAndOp",""));
4712 /* note here that && operations that are in an
4713 if statement are taken away by backPatchLabels
4714 only those used in arthmetic operations remain */
4715 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4716 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4717 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4719 /* if both are bit variables */
4720 if (AOP_TYPE (left) == AOP_CRY &&
4721 AOP_TYPE (right) == AOP_CRY)
4723 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4724 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729 tlbl = newiTempLabel (NULL);
4731 emitcode ("jz", "%05d$", tlbl->key + 100);
4733 emitcode ("", "%05d$:", tlbl->key + 100);
4737 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4738 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4739 freeAsmop (result, NULL, ic, TRUE);
4743 /*-----------------------------------------------------------------*/
4744 /* genOrOp - for || operation */
4745 /*-----------------------------------------------------------------*/
4747 genOrOp (iCode * ic)
4749 operand *left, *right, *result;
4752 D(emitcode ("; genOrOp",""));
4754 /* note here that || operations that are in an
4755 if statement are taken away by backPatchLabels
4756 only those used in arthmetic operations remain */
4757 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4758 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4759 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4761 /* if both are bit variables */
4762 if (AOP_TYPE (left) == AOP_CRY &&
4763 AOP_TYPE (right) == AOP_CRY)
4765 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4766 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4771 tlbl = newiTempLabel (NULL);
4773 emitcode ("jnz", "%05d$", tlbl->key + 100);
4775 emitcode ("", "%05d$:", tlbl->key + 100);
4779 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4780 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4781 freeAsmop (result, NULL, ic, TRUE);
4784 /*-----------------------------------------------------------------*/
4785 /* isLiteralBit - test if lit == 2^n */
4786 /*-----------------------------------------------------------------*/
4788 isLiteralBit (unsigned long lit)
4790 unsigned long pw[32] =
4791 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4792 0x100L, 0x200L, 0x400L, 0x800L,
4793 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4794 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4795 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4796 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4797 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4800 for (idx = 0; idx < 32; idx++)
4806 /*-----------------------------------------------------------------*/
4807 /* continueIfTrue - */
4808 /*-----------------------------------------------------------------*/
4810 continueIfTrue (iCode * ic)
4813 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4817 /*-----------------------------------------------------------------*/
4819 /*-----------------------------------------------------------------*/
4821 jumpIfTrue (iCode * ic)
4824 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4828 /*-----------------------------------------------------------------*/
4829 /* jmpTrueOrFalse - */
4830 /*-----------------------------------------------------------------*/
4832 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4834 // ugly but optimized by peephole
4837 symbol *nlbl = newiTempLabel (NULL);
4838 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4839 emitcode ("", "%05d$:", tlbl->key + 100);
4840 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4841 emitcode ("", "%05d$:", nlbl->key + 100);
4845 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4846 emitcode ("", "%05d$:", tlbl->key + 100);
4851 /*-----------------------------------------------------------------*/
4852 /* genAnd - code for and */
4853 /*-----------------------------------------------------------------*/
4855 genAnd (iCode * ic, iCode * ifx)
4857 operand *left, *right, *result;
4858 int size, offset = 0;
4859 unsigned long lit = 0L;
4863 D(emitcode ("; genAnd",""));
4865 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4866 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4867 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4870 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4872 AOP_TYPE (left), AOP_TYPE (right));
4873 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4875 AOP_SIZE (left), AOP_SIZE (right));
4878 /* if left is a literal & right is not then exchange them */
4879 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4880 AOP_NEEDSACC (left))
4882 operand *tmp = right;
4887 /* if result = right then exchange them */
4888 if (sameRegs (AOP (result), AOP (right)))
4890 operand *tmp = right;
4895 /* if right is bit then exchange them */
4896 if (AOP_TYPE (right) == AOP_CRY &&
4897 AOP_TYPE (left) != AOP_CRY)
4899 operand *tmp = right;
4903 if (AOP_TYPE (right) == AOP_LIT)
4904 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4906 size = AOP_SIZE (result);
4909 // result = bit & yy;
4910 if (AOP_TYPE (left) == AOP_CRY)
4912 // c = bit & literal;
4913 if (AOP_TYPE (right) == AOP_LIT)
4917 if (size && sameRegs (AOP (result), AOP (left)))
4920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4925 if (size && (AOP_TYPE (result) == AOP_CRY))
4927 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4930 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4935 emitcode ("clr", "c");
4940 if (AOP_TYPE (right) == AOP_CRY)
4943 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4944 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4949 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4951 emitcode ("rrc", "a");
4952 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4960 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4961 genIfxJump (ifx, "c");
4965 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4966 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4967 if ((AOP_TYPE (right) == AOP_LIT) &&
4968 (AOP_TYPE (result) == AOP_CRY) &&
4969 (AOP_TYPE (left) != AOP_CRY))
4971 int posbit = isLiteralBit (lit);
4976 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4979 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4985 sprintf (buffer, "acc.%d", posbit & 0x07);
4986 genIfxJump (ifx, buffer);
4993 symbol *tlbl = newiTempLabel (NULL);
4994 int sizel = AOP_SIZE (left);
4996 emitcode ("setb", "c");
4999 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5001 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5003 if ((posbit = isLiteralBit (bytelit)) != 0)
5004 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5007 if (bytelit != 0x0FFL)
5008 emitcode ("anl", "a,%s",
5009 aopGet (AOP (right), offset, FALSE, TRUE));
5010 emitcode ("jnz", "%05d$", tlbl->key + 100);
5015 // bit = left & literal
5018 emitcode ("clr", "c");
5019 emitcode ("", "%05d$:", tlbl->key + 100);
5021 // if(left & literal)
5025 jmpTrueOrFalse (ifx, tlbl);
5027 emitcode ("", "%05d$:", tlbl->key + 100);
5035 /* if left is same as result */
5036 if (sameRegs (AOP (result), AOP (left)))
5038 for (; size--; offset++)
5040 if (AOP_TYPE (right) == AOP_LIT)
5042 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5044 else if (bytelit == 0)
5046 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5048 else if (IS_AOP_PREG (result))
5050 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5051 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5052 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5055 emitcode ("anl", "%s,%s",
5056 aopGet (AOP (left), offset, FALSE, TRUE),
5057 aopGet (AOP (right), offset, FALSE, FALSE));
5061 if (AOP_TYPE (left) == AOP_ACC)
5062 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5066 if (IS_AOP_PREG (result))
5068 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5069 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5073 emitcode ("anl", "%s,a",
5074 aopGet (AOP (left), offset, FALSE, TRUE));
5081 // left & result in different registers
5082 if (AOP_TYPE (result) == AOP_CRY)
5085 // if(size), result in bit
5086 // if(!size && ifx), conditional oper: if(left & right)
5087 symbol *tlbl = newiTempLabel (NULL);
5088 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5090 emitcode ("setb", "c");
5093 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5094 emitcode ("anl", "a,%s",
5095 aopGet (AOP (right), offset, FALSE, FALSE));
5097 if (AOP_TYPE(left)==AOP_ACC) {
5098 emitcode("mov", "b,a");
5099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5100 emitcode("anl", "a,b");
5102 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5103 emitcode ("anl", "a,%s",
5104 aopGet (AOP (left), offset, FALSE, FALSE));
5107 emitcode ("jnz", "%05d$", tlbl->key + 100);
5113 emitcode ("", "%05d$:", tlbl->key + 100);
5117 jmpTrueOrFalse (ifx, tlbl);
5119 emitcode ("", "%05d$:", tlbl->key + 100);
5123 for (; (size--); offset++)
5126 // result = left & right
5127 if (AOP_TYPE (right) == AOP_LIT)
5129 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5131 aopPut (AOP (result),
5132 aopGet (AOP (left), offset, FALSE, FALSE),
5134 isOperandVolatile (result, FALSE));
5137 else if (bytelit == 0)
5139 /* dummy read of volatile operand */
5140 if (isOperandVolatile (left, FALSE))
5141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5142 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5146 // faster than result <- left, anl result,right
5147 // and better if result is SFR
5148 if (AOP_TYPE (left) == AOP_ACC)
5149 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5152 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5153 emitcode ("anl", "a,%s",
5154 aopGet (AOP (left), offset, FALSE, FALSE));
5156 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5162 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5163 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5164 freeAsmop (result, NULL, ic, TRUE);
5167 /*-----------------------------------------------------------------*/
5168 /* genOr - code for or */
5169 /*-----------------------------------------------------------------*/
5171 genOr (iCode * ic, iCode * ifx)
5173 operand *left, *right, *result;
5174 int size, offset = 0;
5175 unsigned long lit = 0L;
5177 D(emitcode ("; genOr",""));
5179 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5180 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5181 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5184 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5186 AOP_TYPE (left), AOP_TYPE (right));
5187 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5189 AOP_SIZE (left), AOP_SIZE (right));
5192 /* if left is a literal & right is not then exchange them */
5193 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5194 AOP_NEEDSACC (left))
5196 operand *tmp = right;
5201 /* if result = right then exchange them */
5202 if (sameRegs (AOP (result), AOP (right)))
5204 operand *tmp = right;
5209 /* if right is bit then exchange them */
5210 if (AOP_TYPE (right) == AOP_CRY &&
5211 AOP_TYPE (left) != AOP_CRY)
5213 operand *tmp = right;
5217 if (AOP_TYPE (right) == AOP_LIT)
5218 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5220 size = AOP_SIZE (result);
5224 if (AOP_TYPE (left) == AOP_CRY)
5226 if (AOP_TYPE (right) == AOP_LIT)
5228 // c = bit | literal;
5231 // lit != 0 => result = 1
5232 if (AOP_TYPE (result) == AOP_CRY)
5235 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5237 continueIfTrue (ifx);
5240 emitcode ("setb", "c");
5244 // lit == 0 => result = left
5245 if (size && sameRegs (AOP (result), AOP (left)))
5247 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5252 if (AOP_TYPE (right) == AOP_CRY)
5255 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5256 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5261 symbol *tlbl = newiTempLabel (NULL);
5262 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5263 emitcode ("setb", "c");
5264 emitcode ("jb", "%s,%05d$",
5265 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5267 emitcode ("jnz", "%05d$", tlbl->key + 100);
5268 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5270 jmpTrueOrFalse (ifx, tlbl);
5276 emitcode ("", "%05d$:", tlbl->key + 100);
5285 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5286 genIfxJump (ifx, "c");
5290 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5291 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5292 if ((AOP_TYPE (right) == AOP_LIT) &&
5293 (AOP_TYPE (result) == AOP_CRY) &&
5294 (AOP_TYPE (left) != AOP_CRY))
5300 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5302 continueIfTrue (ifx);
5307 // lit = 0, result = boolean(left)
5309 emitcode ("setb", "c");
5313 symbol *tlbl = newiTempLabel (NULL);
5314 emitcode ("jnz", "%05d$", tlbl->key + 100);
5316 emitcode ("", "%05d$:", tlbl->key + 100);
5320 genIfxJump (ifx, "a");
5328 /* if left is same as result */
5329 if (sameRegs (AOP (result), AOP (left)))
5331 for (; size--; offset++)
5333 if (AOP_TYPE (right) == AOP_LIT)
5335 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5337 /* dummy read of volatile operand */
5338 if (isOperandVolatile (left, FALSE))
5339 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5343 else if (IS_AOP_PREG (left))
5345 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5346 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5347 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5350 emitcode ("orl", "%s,%s",
5351 aopGet (AOP (left), offset, FALSE, TRUE),
5352 aopGet (AOP (right), offset, FALSE, FALSE));
5356 if (AOP_TYPE (left) == AOP_ACC)
5357 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5360 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5361 if (IS_AOP_PREG (left))
5363 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5364 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5367 emitcode ("orl", "%s,a",
5368 aopGet (AOP (left), offset, FALSE, TRUE));
5375 // left & result in different registers
5376 if (AOP_TYPE (result) == AOP_CRY)
5379 // if(size), result in bit
5380 // if(!size && ifx), conditional oper: if(left | right)
5381 symbol *tlbl = newiTempLabel (NULL);
5382 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5384 emitcode ("setb", "c");
5387 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5388 emitcode ("orl", "a,%s",
5389 aopGet (AOP (right), offset, FALSE, FALSE));
5391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5392 emitcode ("orl", "a,%s",
5393 aopGet (AOP (left), offset, FALSE, FALSE));
5395 emitcode ("jnz", "%05d$", tlbl->key + 100);
5401 emitcode ("", "%05d$:", tlbl->key + 100);
5405 jmpTrueOrFalse (ifx, tlbl);
5407 emitcode ("", "%05d$:", tlbl->key + 100);
5410 for (; (size--); offset++)
5413 // result = left & right
5414 if (AOP_TYPE (right) == AOP_LIT)
5416 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5418 aopPut (AOP (result),
5419 aopGet (AOP (left), offset, FALSE, FALSE),
5421 isOperandVolatile (result, FALSE));
5425 // faster than result <- left, anl result,right
5426 // and better if result is SFR
5427 if (AOP_TYPE (left) == AOP_ACC)
5428 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5431 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5432 emitcode ("orl", "a,%s",
5433 aopGet (AOP (left), offset, FALSE, FALSE));
5435 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5440 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442 freeAsmop (result, NULL, ic, TRUE);
5445 /*-----------------------------------------------------------------*/
5446 /* genXor - code for xclusive or */
5447 /*-----------------------------------------------------------------*/
5449 genXor (iCode * ic, iCode * ifx)
5451 operand *left, *right, *result;
5452 int size, offset = 0;
5453 unsigned long lit = 0L;
5455 D(emitcode ("; genXor",""));
5457 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5458 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5459 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5462 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5464 AOP_TYPE (left), AOP_TYPE (right));
5465 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5467 AOP_SIZE (left), AOP_SIZE (right));
5470 /* if left is a literal & right is not ||
5471 if left needs acc & right does not */
5472 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5473 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5475 operand *tmp = right;
5480 /* if result = right then exchange them */
5481 if (sameRegs (AOP (result), AOP (right)))
5483 operand *tmp = right;
5488 /* if right is bit then exchange them */
5489 if (AOP_TYPE (right) == AOP_CRY &&
5490 AOP_TYPE (left) != AOP_CRY)
5492 operand *tmp = right;
5496 if (AOP_TYPE (right) == AOP_LIT)
5497 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5499 size = AOP_SIZE (result);
5503 if (AOP_TYPE (left) == AOP_CRY)
5505 if (AOP_TYPE (right) == AOP_LIT)
5507 // c = bit & literal;
5510 // lit>>1 != 0 => result = 1
5511 if (AOP_TYPE (result) == AOP_CRY)
5514 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5516 continueIfTrue (ifx);
5519 emitcode ("setb", "c");
5526 // lit == 0, result = left
5527 if (size && sameRegs (AOP (result), AOP (left)))
5529 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5533 // lit == 1, result = not(left)
5534 if (size && sameRegs (AOP (result), AOP (left)))
5536 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5541 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5542 emitcode ("cpl", "c");
5551 symbol *tlbl = newiTempLabel (NULL);
5552 if (AOP_TYPE (right) == AOP_CRY)
5555 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5559 int sizer = AOP_SIZE (right);
5561 // if val>>1 != 0, result = 1
5562 emitcode ("setb", "c");
5565 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5567 // test the msb of the lsb
5568 emitcode ("anl", "a,#0xfe");
5569 emitcode ("jnz", "%05d$", tlbl->key + 100);
5573 emitcode ("rrc", "a");
5575 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5576 emitcode ("cpl", "c");
5577 emitcode ("", "%05d$:", (tlbl->key + 100));
5584 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5585 genIfxJump (ifx, "c");
5589 if (sameRegs (AOP (result), AOP (left)))
5591 /* if left is same as result */
5592 for (; size--; offset++)
5594 if (AOP_TYPE (right) == AOP_LIT)
5596 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5598 else if (IS_AOP_PREG (left))
5600 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5601 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5602 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5605 emitcode ("xrl", "%s,%s",
5606 aopGet (AOP (left), offset, FALSE, TRUE),
5607 aopGet (AOP (right), offset, FALSE, FALSE));
5611 if (AOP_TYPE (left) == AOP_ACC)
5612 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5615 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5616 if (IS_AOP_PREG (left))
5618 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5619 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5622 emitcode ("xrl", "%s,a",
5623 aopGet (AOP (left), offset, FALSE, TRUE));
5630 // left & result in different registers
5631 if (AOP_TYPE (result) == AOP_CRY)
5634 // if(size), result in bit
5635 // if(!size && ifx), conditional oper: if(left ^ right)
5636 symbol *tlbl = newiTempLabel (NULL);
5637 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5639 emitcode ("setb", "c");
5642 if ((AOP_TYPE (right) == AOP_LIT) &&
5643 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5645 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5649 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5650 emitcode ("xrl", "a,%s",
5651 aopGet (AOP (right), offset, FALSE, FALSE));
5653 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5654 emitcode ("xrl", "a,%s",
5655 aopGet (AOP (left), offset, FALSE, FALSE));
5658 emitcode ("jnz", "%05d$", tlbl->key + 100);
5664 emitcode ("", "%05d$:", tlbl->key + 100);
5668 jmpTrueOrFalse (ifx, tlbl);
5671 for (; (size--); offset++)
5674 // result = left & right
5675 if (AOP_TYPE (right) == AOP_LIT)
5677 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5679 aopPut (AOP (result),
5680 aopGet (AOP (left), offset, FALSE, FALSE),
5682 isOperandVolatile (result, FALSE));
5686 // faster than result <- left, anl result,right
5687 // and better if result is SFR
5688 if (AOP_TYPE (left) == AOP_ACC)
5689 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5692 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5693 emitcode ("xrl", "a,%s",
5694 aopGet (AOP (left), offset, FALSE, TRUE));
5696 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5701 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5702 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5703 freeAsmop (result, NULL, ic, TRUE);
5706 /*-----------------------------------------------------------------*/
5707 /* genInline - write the inline code out */
5708 /*-----------------------------------------------------------------*/
5710 genInline (iCode * ic)
5712 char *buffer, *bp, *bp1;
5714 D(emitcode ("; genInline",""));
5716 _G.inLine += (!options.asmpeep);
5718 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5719 strcpy (buffer, IC_INLINE (ic));
5721 /* emit each line as a code */
5746 /* emitcode("",buffer); */
5747 _G.inLine -= (!options.asmpeep);
5750 /*-----------------------------------------------------------------*/
5751 /* genRRC - rotate right with carry */
5752 /*-----------------------------------------------------------------*/
5756 operand *left, *result;
5757 int size, offset = 0;
5760 D(emitcode ("; genRRC",""));
5762 /* rotate right with carry */
5763 left = IC_LEFT (ic);
5764 result = IC_RESULT (ic);
5765 aopOp (left, ic, FALSE);
5766 aopOp (result, ic, FALSE);
5768 /* move it to the result */
5769 size = AOP_SIZE (result);
5771 if (size == 1) { /* special case for 1 byte */
5772 l = aopGet (AOP (left), offset, FALSE, FALSE);
5774 emitcode ("rr", "a");
5780 l = aopGet (AOP (left), offset, FALSE, FALSE);
5782 emitcode ("rrc", "a");
5783 if (AOP_SIZE (result) > 1)
5784 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5786 /* now we need to put the carry into the
5787 highest order byte of the result */
5788 if (AOP_SIZE (result) > 1)
5790 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5793 emitcode ("mov", "acc.7,c");
5795 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5796 freeAsmop (left, NULL, ic, TRUE);
5797 freeAsmop (result, NULL, ic, TRUE);
5800 /*-----------------------------------------------------------------*/
5801 /* genRLC - generate code for rotate left with carry */
5802 /*-----------------------------------------------------------------*/
5806 operand *left, *result;
5807 int size, offset = 0;
5810 D(emitcode ("; genRLC",""));
5812 /* rotate right with carry */
5813 left = IC_LEFT (ic);
5814 result = IC_RESULT (ic);
5815 aopOp (left, ic, FALSE);
5816 aopOp (result, ic, FALSE);
5818 /* move it to the result */
5819 size = AOP_SIZE (result);
5823 l = aopGet (AOP (left), offset, FALSE, FALSE);
5825 if (size == 0) { /* special case for 1 byte */
5829 emitcode ("add", "a,acc");
5830 if (AOP_SIZE (result) > 1)
5831 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5834 l = aopGet (AOP (left), offset, FALSE, FALSE);
5836 emitcode ("rlc", "a");
5837 if (AOP_SIZE (result) > 1)
5838 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5841 /* now we need to put the carry into the
5842 highest order byte of the result */
5843 if (AOP_SIZE (result) > 1)
5845 l = aopGet (AOP (result), 0, FALSE, FALSE);
5848 emitcode ("mov", "acc.0,c");
5850 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5851 freeAsmop (left, NULL, ic, TRUE);
5852 freeAsmop (result, NULL, ic, TRUE);
5855 /*-----------------------------------------------------------------*/
5856 /* genGetHbit - generates code get highest order bit */
5857 /*-----------------------------------------------------------------*/
5859 genGetHbit (iCode * ic)
5861 operand *left, *result;
5863 D(emitcode ("; genGetHbit",""));
5865 left = IC_LEFT (ic);
5866 result = IC_RESULT (ic);
5867 aopOp (left, ic, FALSE);
5868 aopOp (result, ic, FALSE);
5870 /* get the highest order byte into a */
5871 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5872 if (AOP_TYPE (result) == AOP_CRY)
5874 emitcode ("rlc", "a");
5879 emitcode ("rl", "a");
5880 emitcode ("anl", "a,#0x01");
5885 freeAsmop (left, NULL, ic, TRUE);
5886 freeAsmop (result, NULL, ic, TRUE);
5889 /*-----------------------------------------------------------------*/
5890 /* genSwap - generates code to swap nibbles or bytes */
5891 /*-----------------------------------------------------------------*/
5893 genSwap (iCode * ic)
5895 operand *left, *result;
5897 D(emitcode ("; genSwap",""));
5899 left = IC_LEFT (ic);
5900 result = IC_RESULT (ic);
5901 aopOp (left, ic, FALSE);
5902 aopOp (result, ic, FALSE);
5904 switch (AOP_SIZE (left))
5906 case 1: /* swap nibbles in byte */
5907 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5908 emitcode ("swap", "a");
5909 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5911 case 2: /* swap bytes in word */
5912 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5914 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5915 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5916 0, isOperandVolatile (result, FALSE));
5917 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5919 else if (operandsEqu (left, result))
5922 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5923 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5925 emitcode ("mov", "b,a");
5928 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5929 0, isOperandVolatile (result, FALSE));
5930 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5934 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5935 0, isOperandVolatile (result, FALSE));
5936 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5937 1, isOperandVolatile (result, FALSE));
5941 wassertl(FALSE, "unsupported SWAP operand size");
5944 freeAsmop (left, NULL, ic, TRUE);
5945 freeAsmop (result, NULL, ic, TRUE);
5949 /*-----------------------------------------------------------------*/
5950 /* AccRol - rotate left accumulator by known count */
5951 /*-----------------------------------------------------------------*/
5953 AccRol (int shCount)
5955 shCount &= 0x0007; // shCount : 0..7
5962 emitcode ("rl", "a");
5965 emitcode ("rl", "a");
5966 emitcode ("rl", "a");
5969 emitcode ("swap", "a");
5970 emitcode ("rr", "a");
5973 emitcode ("swap", "a");
5976 emitcode ("swap", "a");
5977 emitcode ("rl", "a");
5980 emitcode ("rr", "a");
5981 emitcode ("rr", "a");
5984 emitcode ("rr", "a");
5989 /*-----------------------------------------------------------------*/
5990 /* AccLsh - left shift accumulator by known count */
5991 /*-----------------------------------------------------------------*/
5993 AccLsh (int shCount)
5998 emitcode ("add", "a,acc");
5999 else if (shCount == 2)
6001 emitcode ("add", "a,acc");
6002 emitcode ("add", "a,acc");
6006 /* rotate left accumulator */
6008 /* and kill the lower order bits */
6009 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6014 /*-----------------------------------------------------------------*/
6015 /* AccRsh - right shift accumulator by known count */
6016 /*-----------------------------------------------------------------*/
6018 AccRsh (int shCount)
6025 emitcode ("rrc", "a");
6029 /* rotate right accumulator */
6030 AccRol (8 - shCount);
6031 /* and kill the higher order bits */
6032 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6037 /*-----------------------------------------------------------------*/
6038 /* AccSRsh - signed right shift accumulator by known count */
6039 /*-----------------------------------------------------------------*/
6041 AccSRsh (int shCount)
6048 emitcode ("mov", "c,acc.7");
6049 emitcode ("rrc", "a");
6051 else if (shCount == 2)
6053 emitcode ("mov", "c,acc.7");
6054 emitcode ("rrc", "a");
6055 emitcode ("mov", "c,acc.7");
6056 emitcode ("rrc", "a");
6060 tlbl = newiTempLabel (NULL);
6061 /* rotate right accumulator */
6062 AccRol (8 - shCount);
6063 /* and kill the higher order bits */
6064 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6065 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6066 emitcode ("orl", "a,#0x%02x",
6067 (unsigned char) ~SRMask[shCount]);
6068 emitcode ("", "%05d$:", tlbl->key + 100);
6073 /*-----------------------------------------------------------------*/
6074 /* shiftR1Left2Result - shift right one byte from left to result */
6075 /*-----------------------------------------------------------------*/
6077 shiftR1Left2Result (operand * left, int offl,
6078 operand * result, int offr,
6079 int shCount, int sign)
6081 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6082 /* shift right accumulator */
6087 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6090 /*-----------------------------------------------------------------*/
6091 /* shiftL1Left2Result - shift left one byte from left to result */
6092 /*-----------------------------------------------------------------*/
6094 shiftL1Left2Result (operand * left, int offl,
6095 operand * result, int offr, int shCount)
6098 l = aopGet (AOP (left), offl, FALSE, FALSE);
6100 /* shift left accumulator */
6102 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6105 /*-----------------------------------------------------------------*/
6106 /* movLeft2Result - move byte from left to result */
6107 /*-----------------------------------------------------------------*/
6109 movLeft2Result (operand * left, int offl,
6110 operand * result, int offr, int sign)
6113 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6115 l = aopGet (AOP (left), offl, FALSE, FALSE);
6117 if (*l == '@' && (IS_AOP_PREG (result)))
6119 emitcode ("mov", "a,%s", l);
6120 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6125 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6128 /* MSB sign in acc.7 ! */
6129 if (getDataSize (left) == offl + 1)
6131 emitcode ("mov", "a,%s", l);
6132 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6139 /*-----------------------------------------------------------------*/
6140 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6141 /*-----------------------------------------------------------------*/
6145 emitcode ("rrc", "a");
6146 emitcode ("xch", "a,%s", x);
6147 emitcode ("rrc", "a");
6148 emitcode ("xch", "a,%s", x);
6151 /*-----------------------------------------------------------------*/
6152 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6153 /*-----------------------------------------------------------------*/
6157 emitcode ("xch", "a,%s", x);
6158 emitcode ("rlc", "a");
6159 emitcode ("xch", "a,%s", x);
6160 emitcode ("rlc", "a");
6163 /*-----------------------------------------------------------------*/
6164 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6165 /*-----------------------------------------------------------------*/
6169 emitcode ("xch", "a,%s", x);
6170 emitcode ("add", "a,acc");
6171 emitcode ("xch", "a,%s", x);
6172 emitcode ("rlc", "a");
6175 /*-----------------------------------------------------------------*/
6176 /* AccAXLsh - left shift a:x by known count (0..7) */
6177 /*-----------------------------------------------------------------*/
6179 AccAXLsh (char *x, int shCount)
6194 case 5: // AAAAABBB:CCCCCDDD
6196 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6198 emitcode ("anl", "a,#0x%02x",
6199 SLMask[shCount]); // BBB00000:CCCCCDDD
6201 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6203 AccRol (shCount); // DDDCCCCC:BBB00000
6205 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6207 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6209 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6211 emitcode ("anl", "a,#0x%02x",
6212 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6214 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6216 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6219 case 6: // AAAAAABB:CCCCCCDD
6220 emitcode ("anl", "a,#0x%02x",
6221 SRMask[shCount]); // 000000BB:CCCCCCDD
6222 emitcode ("mov", "c,acc.0"); // c = B
6223 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6225 AccAXRrl1 (x); // BCCCCCCD:D000000B
6226 AccAXRrl1 (x); // BBCCCCCC:DD000000
6228 emitcode("rrc","a");
6229 emitcode("xch","a,%s", x);
6230 emitcode("rrc","a");
6231 emitcode("mov","c,acc.0"); //<< get correct bit
6232 emitcode("xch","a,%s", x);
6234 emitcode("rrc","a");
6235 emitcode("xch","a,%s", x);
6236 emitcode("rrc","a");
6237 emitcode("xch","a,%s", x);
6240 case 7: // a:x <<= 7
6242 emitcode ("anl", "a,#0x%02x",
6243 SRMask[shCount]); // 0000000B:CCCCCCCD
6245 emitcode ("mov", "c,acc.0"); // c = B
6247 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6249 AccAXRrl1 (x); // BCCCCCCC:D0000000
6257 /*-----------------------------------------------------------------*/
6258 /* AccAXRsh - right shift a:x known count (0..7) */
6259 /*-----------------------------------------------------------------*/
6261 AccAXRsh (char *x, int shCount)
6269 AccAXRrl1 (x); // 0->a:x
6274 AccAXRrl1 (x); // 0->a:x
6277 AccAXRrl1 (x); // 0->a:x
6282 case 5: // AAAAABBB:CCCCCDDD = a:x
6284 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6286 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6288 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6290 emitcode ("anl", "a,#0x%02x",
6291 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6293 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6295 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6297 emitcode ("anl", "a,#0x%02x",
6298 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6300 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6302 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6304 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6307 case 6: // AABBBBBB:CCDDDDDD
6309 emitcode ("mov", "c,acc.7");
6310 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6312 emitcode ("mov", "c,acc.7");
6313 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6315 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6317 emitcode ("anl", "a,#0x%02x",
6318 SRMask[shCount]); // 000000AA:BBBBBBCC
6321 case 7: // ABBBBBBB:CDDDDDDD
6323 emitcode ("mov", "c,acc.7"); // c = A
6325 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6327 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6329 emitcode ("anl", "a,#0x%02x",
6330 SRMask[shCount]); // 0000000A:BBBBBBBC
6338 /*-----------------------------------------------------------------*/
6339 /* AccAXRshS - right shift signed a:x known count (0..7) */
6340 /*-----------------------------------------------------------------*/
6342 AccAXRshS (char *x, int shCount)
6350 emitcode ("mov", "c,acc.7");
6351 AccAXRrl1 (x); // s->a:x
6355 emitcode ("mov", "c,acc.7");
6356 AccAXRrl1 (x); // s->a:x
6358 emitcode ("mov", "c,acc.7");
6359 AccAXRrl1 (x); // s->a:x
6364 case 5: // AAAAABBB:CCCCCDDD = a:x
6366 tlbl = newiTempLabel (NULL);
6367 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6369 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6371 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6373 emitcode ("anl", "a,#0x%02x",
6374 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6376 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6378 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6380 emitcode ("anl", "a,#0x%02x",
6381 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6383 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6385 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6387 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6389 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6390 emitcode ("orl", "a,#0x%02x",
6391 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6393 emitcode ("", "%05d$:", tlbl->key + 100);
6394 break; // SSSSAAAA:BBBCCCCC
6396 case 6: // AABBBBBB:CCDDDDDD
6398 tlbl = newiTempLabel (NULL);
6399 emitcode ("mov", "c,acc.7");
6400 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6402 emitcode ("mov", "c,acc.7");
6403 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6405 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6407 emitcode ("anl", "a,#0x%02x",
6408 SRMask[shCount]); // 000000AA:BBBBBBCC
6410 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6411 emitcode ("orl", "a,#0x%02x",
6412 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6414 emitcode ("", "%05d$:", tlbl->key + 100);
6416 case 7: // ABBBBBBB:CDDDDDDD
6418 tlbl = newiTempLabel (NULL);
6419 emitcode ("mov", "c,acc.7"); // c = A
6421 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6423 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6425 emitcode ("anl", "a,#0x%02x",
6426 SRMask[shCount]); // 0000000A:BBBBBBBC
6428 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6429 emitcode ("orl", "a,#0x%02x",
6430 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6432 emitcode ("", "%05d$:", tlbl->key + 100);
6439 /*-----------------------------------------------------------------*/
6440 /* shiftL2Left2Result - shift left two bytes from left to result */
6441 /*-----------------------------------------------------------------*/
6443 shiftL2Left2Result (operand * left, int offl,
6444 operand * result, int offr, int shCount)
6446 if (sameRegs (AOP (result), AOP (left)) &&
6447 ((offl + MSB16) == offr))
6449 /* don't crash result[offr] */
6450 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6451 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6455 movLeft2Result (left, offl, result, offr, 0);
6456 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6458 /* ax << shCount (x = lsb(result)) */
6459 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6460 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6464 /*-----------------------------------------------------------------*/
6465 /* shiftR2Left2Result - shift right two bytes from left to result */
6466 /*-----------------------------------------------------------------*/
6468 shiftR2Left2Result (operand * left, int offl,
6469 operand * result, int offr,
6470 int shCount, int sign)
6472 if (sameRegs (AOP (result), AOP (left)) &&
6473 ((offl + MSB16) == offr))
6475 /* don't crash result[offr] */
6476 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6477 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6481 movLeft2Result (left, offl, result, offr, 0);
6482 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6484 /* a:x >> shCount (x = lsb(result)) */
6486 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6488 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6489 if (getDataSize (result) > 1)
6490 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6493 /*-----------------------------------------------------------------*/
6494 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6495 /*-----------------------------------------------------------------*/
6497 shiftLLeftOrResult (operand * left, int offl,
6498 operand * result, int offr, int shCount)
6500 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6501 /* shift left accumulator */
6503 /* or with result */
6504 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6505 /* back to result */
6506 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6509 /*-----------------------------------------------------------------*/
6510 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6511 /*-----------------------------------------------------------------*/
6513 shiftRLeftOrResult (operand * left, int offl,
6514 operand * result, int offr, int shCount)
6516 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6517 /* shift right accumulator */
6519 /* or with result */
6520 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6521 /* back to result */
6522 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6525 /*-----------------------------------------------------------------*/
6526 /* genlshOne - left shift a one byte quantity by known count */
6527 /*-----------------------------------------------------------------*/
6529 genlshOne (operand * result, operand * left, int shCount)
6531 D(emitcode ("; genlshOne",""));
6533 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6536 /*-----------------------------------------------------------------*/
6537 /* genlshTwo - left shift two bytes by known amount != 0 */
6538 /*-----------------------------------------------------------------*/
6540 genlshTwo (operand * result, operand * left, int shCount)
6544 D(emitcode ("; genlshTwo",""));
6546 size = getDataSize (result);
6548 /* if shCount >= 8 */
6556 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6558 movLeft2Result (left, LSB, result, MSB16, 0);
6560 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6563 /* 1 <= shCount <= 7 */
6567 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6569 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6573 /*-----------------------------------------------------------------*/
6574 /* shiftLLong - shift left one long from left to result */
6575 /* offl = LSB or MSB16 */
6576 /*-----------------------------------------------------------------*/
6578 shiftLLong (operand * left, operand * result, int offr)
6581 int size = AOP_SIZE (result);
6583 if (size >= LSB + offr)
6585 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6587 emitcode ("add", "a,acc");
6588 if (sameRegs (AOP (left), AOP (result)) &&
6589 size >= MSB16 + offr && offr != LSB)
6590 emitcode ("xch", "a,%s",
6591 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6593 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6596 if (size >= MSB16 + offr)
6598 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6600 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6603 emitcode ("rlc", "a");
6604 if (sameRegs (AOP (left), AOP (result)) &&
6605 size >= MSB24 + offr && offr != LSB)
6606 emitcode ("xch", "a,%s",
6607 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6609 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6612 if (size >= MSB24 + offr)
6614 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6616 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6619 emitcode ("rlc", "a");
6620 if (sameRegs (AOP (left), AOP (result)) &&
6621 size >= MSB32 + offr && offr != LSB)
6622 emitcode ("xch", "a,%s",
6623 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6625 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6628 if (size > MSB32 + offr)
6630 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6632 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6635 emitcode ("rlc", "a");
6636 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6639 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6642 /*-----------------------------------------------------------------*/
6643 /* genlshFour - shift four byte by a known amount != 0 */
6644 /*-----------------------------------------------------------------*/
6646 genlshFour (operand * result, operand * left, int shCount)
6650 D(emitcode ("; genlshFour",""));
6652 size = AOP_SIZE (result);
6654 /* if shifting more that 3 bytes */
6659 /* lowest order of left goes to the highest
6660 order of the destination */
6661 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6663 movLeft2Result (left, LSB, result, MSB32, 0);
6664 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6665 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6666 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6670 /* more than two bytes */
6671 else if (shCount >= 16)
6673 /* lower order two bytes goes to higher order two bytes */
6675 /* if some more remaining */
6677 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6680 movLeft2Result (left, MSB16, result, MSB32, 0);
6681 movLeft2Result (left, LSB, result, MSB24, 0);
6683 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6684 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6688 /* if more than 1 byte */
6689 else if (shCount >= 8)
6691 /* lower order three bytes goes to higher order three bytes */
6696 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6698 movLeft2Result (left, LSB, result, MSB16, 0);
6704 movLeft2Result (left, MSB24, result, MSB32, 0);
6705 movLeft2Result (left, MSB16, result, MSB24, 0);
6706 movLeft2Result (left, LSB, result, MSB16, 0);
6707 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6709 else if (shCount == 1)
6710 shiftLLong (left, result, MSB16);
6713 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6714 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6715 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6716 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6721 /* 1 <= shCount <= 7 */
6722 else if (shCount <= 2)
6724 shiftLLong (left, result, LSB);
6726 shiftLLong (result, result, LSB);
6728 /* 3 <= shCount <= 7, optimize */
6731 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6732 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6733 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6737 /*-----------------------------------------------------------------*/
6738 /* genLeftShiftLiteral - left shifting by known count */
6739 /*-----------------------------------------------------------------*/
6741 genLeftShiftLiteral (operand * left,
6746 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6749 D(emitcode ("; genLeftShiftLiteral",""));
6751 freeAsmop (right, NULL, ic, TRUE);
6753 aopOp (left, ic, FALSE);
6754 aopOp (result, ic, FALSE);
6756 size = getSize (operandType (result));
6759 emitcode ("; shift left ", "result %d, left %d", size,
6763 /* I suppose that the left size >= result size */
6768 movLeft2Result (left, size, result, size, 0);
6772 else if (shCount >= (size * 8))
6774 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6780 genlshOne (result, left, shCount);
6784 genlshTwo (result, left, shCount);
6788 genlshFour (result, left, shCount);
6791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6792 "*** ack! mystery literal shift!\n");
6796 freeAsmop (left, NULL, ic, TRUE);
6797 freeAsmop (result, NULL, ic, TRUE);
6800 /*-----------------------------------------------------------------*/
6801 /* genLeftShift - generates code for left shifting */
6802 /*-----------------------------------------------------------------*/
6804 genLeftShift (iCode * ic)
6806 operand *left, *right, *result;
6809 symbol *tlbl, *tlbl1;
6811 D(emitcode ("; genLeftShift",""));
6813 right = IC_RIGHT (ic);
6814 left = IC_LEFT (ic);
6815 result = IC_RESULT (ic);
6817 aopOp (right, ic, FALSE);
6819 /* if the shift count is known then do it
6820 as efficiently as possible */
6821 if (AOP_TYPE (right) == AOP_LIT)
6823 genLeftShiftLiteral (left, right, result, ic);
6827 /* shift count is unknown then we have to form
6828 a loop get the loop count in B : Note: we take
6829 only the lower order byte since shifting
6830 more that 32 bits make no sense anyway, ( the
6831 largest size of an object can be only 32 bits ) */
6833 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6834 emitcode ("inc", "b");
6835 freeAsmop (right, NULL, ic, TRUE);
6836 aopOp (left, ic, FALSE);
6837 aopOp (result, ic, FALSE);
6839 /* now move the left to the result if they are not the
6841 if (!sameRegs (AOP (left), AOP (result)) &&
6842 AOP_SIZE (result) > 1)
6845 size = AOP_SIZE (result);
6849 l = aopGet (AOP (left), offset, FALSE, TRUE);
6850 if (*l == '@' && (IS_AOP_PREG (result)))
6853 emitcode ("mov", "a,%s", l);
6854 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6857 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6862 tlbl = newiTempLabel (NULL);
6863 size = AOP_SIZE (result);
6865 tlbl1 = newiTempLabel (NULL);
6867 /* if it is only one byte then */
6870 symbol *tlbl1 = newiTempLabel (NULL);
6872 l = aopGet (AOP (left), 0, FALSE, FALSE);
6874 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6875 emitcode ("", "%05d$:", tlbl->key + 100);
6876 emitcode ("add", "a,acc");
6877 emitcode ("", "%05d$:", tlbl1->key + 100);
6878 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6879 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6883 reAdjustPreg (AOP (result));
6885 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6886 emitcode ("", "%05d$:", tlbl->key + 100);
6887 l = aopGet (AOP (result), offset, FALSE, FALSE);
6889 emitcode ("add", "a,acc");
6890 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6893 l = aopGet (AOP (result), offset, FALSE, FALSE);
6895 emitcode ("rlc", "a");
6896 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6898 reAdjustPreg (AOP (result));
6900 emitcode ("", "%05d$:", tlbl1->key + 100);
6901 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6903 freeAsmop (left, NULL, ic, TRUE);
6904 freeAsmop (result, NULL, ic, TRUE);
6907 /*-----------------------------------------------------------------*/
6908 /* genrshOne - right shift a one byte quantity by known count */
6909 /*-----------------------------------------------------------------*/
6911 genrshOne (operand * result, operand * left,
6912 int shCount, int sign)
6914 D(emitcode ("; genrshOne",""));
6916 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6919 /*-----------------------------------------------------------------*/
6920 /* genrshTwo - right shift two bytes by known amount != 0 */
6921 /*-----------------------------------------------------------------*/
6923 genrshTwo (operand * result, operand * left,
6924 int shCount, int sign)
6926 D(emitcode ("; genrshTwo",""));
6928 /* if shCount >= 8 */
6933 shiftR1Left2Result (left, MSB16, result, LSB,
6936 movLeft2Result (left, MSB16, result, LSB, sign);
6937 addSign (result, MSB16, sign);
6940 /* 1 <= shCount <= 7 */
6942 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6945 /*-----------------------------------------------------------------*/
6946 /* shiftRLong - shift right one long from left to result */
6947 /* offl = LSB or MSB16 */
6948 /*-----------------------------------------------------------------*/
6950 shiftRLong (operand * left, int offl,
6951 operand * result, int sign)
6953 int isSameRegs=sameRegs(AOP(left),AOP(result));
6955 if (isSameRegs && offl>1) {
6956 // we are in big trouble, but this shouldn't happen
6957 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6960 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6965 emitcode ("rlc", "a");
6966 emitcode ("subb", "a,acc");
6968 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6970 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6971 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6974 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6979 emitcode ("clr", "c");
6981 emitcode ("mov", "c,acc.7");
6984 emitcode ("rrc", "a");
6986 if (isSameRegs && offl==MSB16) {
6987 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6989 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6990 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6993 emitcode ("rrc", "a");
6994 if (isSameRegs && offl==1) {
6995 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6997 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6998 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7000 emitcode ("rrc", "a");
7001 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7005 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7006 emitcode ("rrc", "a");
7007 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7011 /*-----------------------------------------------------------------*/
7012 /* genrshFour - shift four byte by a known amount != 0 */
7013 /*-----------------------------------------------------------------*/
7015 genrshFour (operand * result, operand * left,
7016 int shCount, int sign)
7018 D(emitcode ("; genrshFour",""));
7020 /* if shifting more that 3 bytes */
7025 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7027 movLeft2Result (left, MSB32, result, LSB, sign);
7028 addSign (result, MSB16, sign);
7030 else if (shCount >= 16)
7034 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7037 movLeft2Result (left, MSB24, result, LSB, 0);
7038 movLeft2Result (left, MSB32, result, MSB16, sign);
7040 addSign (result, MSB24, sign);
7042 else if (shCount >= 8)
7046 shiftRLong (left, MSB16, result, sign);
7047 else if (shCount == 0)
7049 movLeft2Result (left, MSB16, result, LSB, 0);
7050 movLeft2Result (left, MSB24, result, MSB16, 0);
7051 movLeft2Result (left, MSB32, result, MSB24, sign);
7052 addSign (result, MSB32, sign);
7056 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7057 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7058 /* the last shift is signed */
7059 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7060 addSign (result, MSB32, sign);
7064 { /* 1 <= shCount <= 7 */
7067 shiftRLong (left, LSB, result, sign);
7069 shiftRLong (result, LSB, result, sign);
7073 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7074 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7075 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7080 /*-----------------------------------------------------------------*/
7081 /* genRightShiftLiteral - right shifting by known count */
7082 /*-----------------------------------------------------------------*/
7084 genRightShiftLiteral (operand * left,
7090 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7093 D(emitcode ("; genRightShiftLiteral",""));
7095 freeAsmop (right, NULL, ic, TRUE);
7097 aopOp (left, ic, FALSE);
7098 aopOp (result, ic, FALSE);
7101 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7105 size = getDataSize (left);
7106 /* test the LEFT size !!! */
7108 /* I suppose that the left size >= result size */
7111 size = getDataSize (result);
7113 movLeft2Result (left, size, result, size, 0);
7116 else if (shCount >= (size * 8))
7119 /* get sign in acc.7 */
7120 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7122 addSign (result, LSB, sign);
7129 genrshOne (result, left, shCount, sign);
7133 genrshTwo (result, left, shCount, sign);
7137 genrshFour (result, left, shCount, sign);
7143 freeAsmop (left, NULL, ic, TRUE);
7144 freeAsmop (result, NULL, ic, TRUE);
7147 /*-----------------------------------------------------------------*/
7148 /* genSignedRightShift - right shift of signed number */
7149 /*-----------------------------------------------------------------*/
7151 genSignedRightShift (iCode * ic)
7153 operand *right, *left, *result;
7156 symbol *tlbl, *tlbl1;
7158 D(emitcode ("; genSignedRightShift",""));
7160 /* we do it the hard way put the shift count in b
7161 and loop thru preserving the sign */
7163 right = IC_RIGHT (ic);
7164 left = IC_LEFT (ic);
7165 result = IC_RESULT (ic);
7167 aopOp (right, ic, FALSE);
7170 if (AOP_TYPE (right) == AOP_LIT)
7172 genRightShiftLiteral (left, right, result, ic, 1);
7175 /* shift count is unknown then we have to form
7176 a loop get the loop count in B : Note: we take
7177 only the lower order byte since shifting
7178 more that 32 bits make no sense anyway, ( the
7179 largest size of an object can be only 32 bits ) */
7181 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7182 emitcode ("inc", "b");
7183 freeAsmop (right, NULL, ic, TRUE);
7184 aopOp (left, ic, FALSE);
7185 aopOp (result, ic, FALSE);
7187 /* now move the left to the result if they are not the
7189 if (!sameRegs (AOP (left), AOP (result)) &&
7190 AOP_SIZE (result) > 1)
7193 size = AOP_SIZE (result);
7197 l = aopGet (AOP (left), offset, FALSE, TRUE);
7198 if (*l == '@' && IS_AOP_PREG (result))
7201 emitcode ("mov", "a,%s", l);
7202 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7205 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7210 /* mov the highest order bit to OVR */
7211 tlbl = newiTempLabel (NULL);
7212 tlbl1 = newiTempLabel (NULL);
7214 size = AOP_SIZE (result);
7216 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7217 emitcode ("rlc", "a");
7218 emitcode ("mov", "ov,c");
7219 /* if it is only one byte then */
7222 l = aopGet (AOP (left), 0, FALSE, FALSE);
7224 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7225 emitcode ("", "%05d$:", tlbl->key + 100);
7226 emitcode ("mov", "c,ov");
7227 emitcode ("rrc", "a");
7228 emitcode ("", "%05d$:", tlbl1->key + 100);
7229 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7230 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7234 reAdjustPreg (AOP (result));
7235 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7236 emitcode ("", "%05d$:", tlbl->key + 100);
7237 emitcode ("mov", "c,ov");
7240 l = aopGet (AOP (result), offset, FALSE, FALSE);
7242 emitcode ("rrc", "a");
7243 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7245 reAdjustPreg (AOP (result));
7246 emitcode ("", "%05d$:", tlbl1->key + 100);
7247 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7250 freeAsmop (left, NULL, ic, TRUE);
7251 freeAsmop (result, NULL, ic, TRUE);
7254 /*-----------------------------------------------------------------*/
7255 /* genRightShift - generate code for right shifting */
7256 /*-----------------------------------------------------------------*/
7258 genRightShift (iCode * ic)
7260 operand *right, *left, *result;
7264 symbol *tlbl, *tlbl1;
7266 D(emitcode ("; genRightShift",""));
7268 /* if signed then we do it the hard way preserve the
7269 sign bit moving it inwards */
7270 letype = getSpec (operandType (IC_LEFT (ic)));
7272 if (!SPEC_USIGN (letype))
7274 genSignedRightShift (ic);
7278 /* signed & unsigned types are treated the same : i.e. the
7279 signed is NOT propagated inwards : quoting from the
7280 ANSI - standard : "for E1 >> E2, is equivalent to division
7281 by 2**E2 if unsigned or if it has a non-negative value,
7282 otherwise the result is implementation defined ", MY definition
7283 is that the sign does not get propagated */
7285 right = IC_RIGHT (ic);
7286 left = IC_LEFT (ic);
7287 result = IC_RESULT (ic);
7289 aopOp (right, ic, FALSE);
7291 /* if the shift count is known then do it
7292 as efficiently as possible */
7293 if (AOP_TYPE (right) == AOP_LIT)
7295 genRightShiftLiteral (left, right, result, ic, 0);
7299 /* shift count is unknown then we have to form
7300 a loop get the loop count in B : Note: we take
7301 only the lower order byte since shifting
7302 more that 32 bits make no sense anyway, ( the
7303 largest size of an object can be only 32 bits ) */
7305 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7306 emitcode ("inc", "b");
7307 freeAsmop (right, NULL, ic, TRUE);
7308 aopOp (left, ic, FALSE);
7309 aopOp (result, ic, FALSE);
7311 /* now move the left to the result if they are not the
7313 if (!sameRegs (AOP (left), AOP (result)) &&
7314 AOP_SIZE (result) > 1)
7317 size = AOP_SIZE (result);
7321 l = aopGet (AOP (left), offset, FALSE, TRUE);
7322 if (*l == '@' && IS_AOP_PREG (result))
7325 emitcode ("mov", "a,%s", l);
7326 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7329 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7334 tlbl = newiTempLabel (NULL);
7335 tlbl1 = newiTempLabel (NULL);
7336 size = AOP_SIZE (result);
7339 /* if it is only one byte then */
7342 l = aopGet (AOP (left), 0, FALSE, FALSE);
7344 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7345 emitcode ("", "%05d$:", tlbl->key + 100);
7347 emitcode ("rrc", "a");
7348 emitcode ("", "%05d$:", tlbl1->key + 100);
7349 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7350 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7354 reAdjustPreg (AOP (result));
7355 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7356 emitcode ("", "%05d$:", tlbl->key + 100);
7360 l = aopGet (AOP (result), offset, FALSE, FALSE);
7362 emitcode ("rrc", "a");
7363 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7365 reAdjustPreg (AOP (result));
7367 emitcode ("", "%05d$:", tlbl1->key + 100);
7368 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7371 freeAsmop (left, NULL, ic, TRUE);
7372 freeAsmop (result, NULL, ic, TRUE);
7375 /*-----------------------------------------------------------------*/
7376 /* emitPtrByteGet - emits code to get a byte into A through a */
7377 /* pointer register (R0, R1, or DPTR). The */
7378 /* original value of A can be preserved in B. */
7379 /*-----------------------------------------------------------------*/
7381 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7388 emitcode ("mov", "b,a");
7389 emitcode ("mov", "a,@%s", rname);
7394 emitcode ("mov", "b,a");
7395 emitcode ("movx", "a,@%s", rname);
7400 emitcode ("mov", "b,a");
7401 emitcode ("movx", "a,@dptr");
7406 emitcode ("mov", "b,a");
7407 emitcode ("clr", "a");
7408 emitcode ("movc", "a,@a+dptr");
7414 emitcode ("push", "b");
7415 emitcode ("push", "acc");
7417 emitcode ("lcall", "__gptrget");
7419 emitcode ("pop", "b");
7424 /*-----------------------------------------------------------------*/
7425 /* emitPtrByteSet - emits code to set a byte from src through a */
7426 /* pointer register (R0, R1, or DPTR). */
7427 /*-----------------------------------------------------------------*/
7429 emitPtrByteSet (char *rname, int p_type, char *src)
7438 emitcode ("mov", "@%s,a", rname);
7441 emitcode ("mov", "@%s,%s", rname, src);
7446 emitcode ("movx", "@%s,a", rname);
7451 emitcode ("movx", "@dptr,a");
7456 emitcode ("lcall", "__gptrput");
7461 /*-----------------------------------------------------------------*/
7462 /* genUnpackBits - generates code for unpacking bits */
7463 /*-----------------------------------------------------------------*/
7465 genUnpackBits (operand * result, char *rname, int ptype)
7467 int offset = 0; /* result byte offset */
7468 int rsize; /* result size */
7469 int rlen = 0; /* remaining bitfield length */
7470 sym_link *etype; /* bitfield type information */
7471 int blen; /* bitfield length */
7472 int bstr; /* bitfield starting bit within byte */
7474 D(emitcode ("; genUnpackBits",""));
7476 etype = getSpec (operandType (result));
7477 rsize = getSize (operandType (result));
7478 blen = SPEC_BLEN (etype);
7479 bstr = SPEC_BSTR (etype);
7481 /* If the bitfield length is less than a byte */
7484 emitPtrByteGet (rname, ptype, FALSE);
7486 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7487 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7491 /* Bit field did not fit in a byte. Copy all
7492 but the partial byte at the end. */
7493 for (rlen=blen;rlen>=8;rlen-=8)
7495 emitPtrByteGet (rname, ptype, FALSE);
7496 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7498 emitcode ("inc", "%s", rname);
7501 /* Handle the partial byte at the end */
7504 emitPtrByteGet (rname, ptype, FALSE);
7505 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7506 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7514 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7519 /*-----------------------------------------------------------------*/
7520 /* genDataPointerGet - generates code when ptr offset is known */
7521 /*-----------------------------------------------------------------*/
7523 genDataPointerGet (operand * left,
7529 int size, offset = 0;
7531 D(emitcode ("; genDataPointerGet",""));
7533 aopOp (result, ic, TRUE);
7535 /* get the string representation of the name */
7536 l = aopGet (AOP (left), 0, FALSE, TRUE);
7537 size = AOP_SIZE (result);
7541 sprintf (buffer, "(%s + %d)", l + 1, offset);
7543 sprintf (buffer, "%s", l + 1);
7544 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7547 freeAsmop (left, NULL, ic, TRUE);
7548 freeAsmop (result, NULL, ic, TRUE);
7551 /*-----------------------------------------------------------------*/
7552 /* genNearPointerGet - emitcode for near pointer fetch */
7553 /*-----------------------------------------------------------------*/
7555 genNearPointerGet (operand * left,
7563 sym_link *rtype, *retype;
7564 sym_link *ltype = operandType (left);
7567 D(emitcode ("; genNearPointerGet",""));
7569 rtype = operandType (result);
7570 retype = getSpec (rtype);
7572 aopOp (left, ic, FALSE);
7574 /* if left is rematerialisable and
7575 result is not bit variable type and
7576 the left is pointer to data space i.e
7577 lower 128 bytes of space */
7578 if (AOP_TYPE (left) == AOP_IMMD &&
7579 !IS_BITVAR (retype) &&
7580 DCL_TYPE (ltype) == POINTER)
7582 genDataPointerGet (left, result, ic);
7586 /* if the value is already in a pointer register
7587 then don't need anything more */
7588 if (!AOP_INPREG (AOP (left)))
7590 if (IS_AOP_PREG (left))
7592 // Aha, it is a pointer, just in disguise.
7593 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7596 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7597 __FILE__, __LINE__);
7602 emitcode ("mov", "a%s,%s", rname + 1, rname);
7603 rname++; // skip the '@'.
7608 /* otherwise get a free pointer register */
7610 preg = getFreePtr (ic, &aop, FALSE);
7611 emitcode ("mov", "%s,%s",
7613 aopGet (AOP (left), 0, FALSE, TRUE));
7618 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7620 //aopOp (result, ic, FALSE);
7621 aopOp (result, ic, result?TRUE:FALSE);
7623 /* if bitfield then unpack the bits */
7624 if (IS_BITFIELD (retype))
7625 genUnpackBits (result, rname, POINTER);
7628 /* we have can just get the values */
7629 int size = AOP_SIZE (result);
7634 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7637 emitcode ("mov", "a,@%s", rname);
7638 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7642 sprintf (buffer, "@%s", rname);
7643 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7647 emitcode ("inc", "%s", rname);
7651 /* now some housekeeping stuff */
7652 if (aop) /* we had to allocate for this iCode */
7654 if (pi) { /* post increment present */
7655 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7657 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7661 /* we did not allocate which means left
7662 already in a pointer register, then
7663 if size > 0 && this could be used again
7664 we have to point it back to where it
7666 if ((AOP_SIZE (result) > 1 &&
7667 !OP_SYMBOL (left)->remat &&
7668 (OP_SYMBOL (left)->liveTo > ic->seq ||
7672 int size = AOP_SIZE (result) - 1;
7674 emitcode ("dec", "%s", rname);
7679 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7680 freeAsmop (left, NULL, ic, TRUE);
7681 if (pi) pi->generated = 1;
7684 /*-----------------------------------------------------------------*/
7685 /* genPagedPointerGet - emitcode for paged pointer fetch */
7686 /*-----------------------------------------------------------------*/
7688 genPagedPointerGet (operand * left,
7696 sym_link *rtype, *retype;
7698 D(emitcode ("; genPagedPointerGet",""));
7700 rtype = operandType (result);
7701 retype = getSpec (rtype);
7703 aopOp (left, ic, FALSE);
7705 /* if the value is already in a pointer register
7706 then don't need anything more */
7707 if (!AOP_INPREG (AOP (left)))
7709 /* otherwise get a free pointer register */
7711 preg = getFreePtr (ic, &aop, FALSE);
7712 emitcode ("mov", "%s,%s",
7714 aopGet (AOP (left), 0, FALSE, TRUE));
7718 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7720 aopOp (result, ic, FALSE);
7722 /* if bitfield then unpack the bits */
7723 if (IS_BITFIELD (retype))
7724 genUnpackBits (result, rname, PPOINTER);
7727 /* we have can just get the values */
7728 int size = AOP_SIZE (result);
7734 emitcode ("movx", "a,@%s", rname);
7735 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7740 emitcode ("inc", "%s", rname);
7744 /* now some housekeeping stuff */
7745 if (aop) /* we had to allocate for this iCode */
7747 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7748 freeAsmop (NULL, aop, ic, TRUE);
7752 /* we did not allocate which means left
7753 already in a pointer register, then
7754 if size > 0 && this could be used again
7755 we have to point it back to where it
7757 if ((AOP_SIZE (result) > 1 &&
7758 !OP_SYMBOL (left)->remat &&
7759 (OP_SYMBOL (left)->liveTo > ic->seq ||
7763 int size = AOP_SIZE (result) - 1;
7765 emitcode ("dec", "%s", rname);
7770 freeAsmop (left, NULL, ic, TRUE);
7771 freeAsmop (result, NULL, ic, TRUE);
7772 if (pi) pi->generated = 1;
7776 /*--------------------------------------------------------------------*/
7777 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7778 /*--------------------------------------------------------------------*/
7780 loadDptrFromOperand (operand *op, bool loadBToo)
7782 if (AOP_TYPE (op) != AOP_STR)
7784 /* if this is remateriazable */
7785 if (AOP_TYPE (op) == AOP_IMMD)
7787 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7790 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7791 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7794 wassertl(FALSE, "need pointerCode");
7795 emitcode ("", "; mov b,???");
7796 /* genPointerGet and genPointerSet originally did different
7797 ** things for this case. Both seem wrong.
7798 ** from genPointerGet:
7799 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7800 ** from genPointerSet:
7801 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7806 else if (AOP_TYPE (op) == AOP_DPTR)
7810 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7811 emitcode ("push", "acc");
7812 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7813 emitcode ("push", "acc");
7814 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7815 emitcode ("pop", "dph");
7816 emitcode ("pop", "dpl");
7820 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7821 emitcode ("push", "acc");
7822 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7823 emitcode ("pop", "dpl");
7827 { /* we need to get it byte by byte */
7828 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7829 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7831 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7836 /*-----------------------------------------------------------------*/
7837 /* genFarPointerGet - gget value from far space */
7838 /*-----------------------------------------------------------------*/
7840 genFarPointerGet (operand * left,
7841 operand * result, iCode * ic, iCode * pi)
7844 sym_link *retype = getSpec (operandType (result));
7846 D(emitcode ("; genFarPointerGet",""));
7848 aopOp (left, ic, FALSE);
7849 loadDptrFromOperand (left, FALSE);
7851 /* so dptr now contains the address */
7852 aopOp (result, ic, FALSE);
7854 /* if bit then unpack */
7855 if (IS_BITFIELD (retype))
7856 genUnpackBits (result, "dptr", FPOINTER);
7859 size = AOP_SIZE (result);
7864 emitcode ("movx", "a,@dptr");
7865 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7867 emitcode ("inc", "dptr");
7871 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7872 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7873 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7876 freeAsmop (left, NULL, ic, TRUE);
7877 freeAsmop (result, NULL, ic, TRUE);
7880 /*-----------------------------------------------------------------*/
7881 /* genCodePointerGet - gget value from code space */
7882 /*-----------------------------------------------------------------*/
7884 genCodePointerGet (operand * left,
7885 operand * result, iCode * ic, iCode *pi)
7888 sym_link *retype = getSpec (operandType (result));
7890 D(emitcode ("; genCodePointerGet",""));
7892 aopOp (left, ic, FALSE);
7893 loadDptrFromOperand (left, FALSE);
7895 /* so dptr now contains the address */
7896 aopOp (result, ic, FALSE);
7898 /* if bit then unpack */
7899 if (IS_BITFIELD (retype))
7900 genUnpackBits (result, "dptr", CPOINTER);
7903 size = AOP_SIZE (result);
7910 emitcode ("clr", "a");
7911 emitcode ("movc", "a,@a+dptr");
7912 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7913 emitcode ("inc", "dptr");
7917 emitcode ("mov", "a,#0x%02x", offset);
7918 emitcode ("movc", "a,@a+dptr");
7919 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7924 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7925 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7926 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7929 freeAsmop (left, NULL, ic, TRUE);
7930 freeAsmop (result, NULL, ic, TRUE);
7933 /*-----------------------------------------------------------------*/
7934 /* genGenPointerGet - gget value from generic pointer space */
7935 /*-----------------------------------------------------------------*/
7937 genGenPointerGet (operand * left,
7938 operand * result, iCode * ic, iCode *pi)
7941 sym_link *retype = getSpec (operandType (result));
7943 D(emitcode ("; genGenPointerGet",""));
7945 aopOp (left, ic, FALSE);
7946 loadDptrFromOperand (left, TRUE);
7948 /* so dptr know contains the address */
7949 aopOp (result, ic, FALSE);
7951 /* if bit then unpack */
7952 if (IS_BITFIELD (retype))
7953 genUnpackBits (result, "dptr", GPOINTER);
7956 size = AOP_SIZE (result);
7961 emitcode ("lcall", "__gptrget");
7962 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7964 emitcode ("inc", "dptr");
7968 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7969 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7970 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7973 freeAsmop (left, NULL, ic, TRUE);
7974 freeAsmop (result, NULL, ic, TRUE);
7977 /*-----------------------------------------------------------------*/
7978 /* genPointerGet - generate code for pointer get */
7979 /*-----------------------------------------------------------------*/
7981 genPointerGet (iCode * ic, iCode *pi)
7983 operand *left, *result;
7984 sym_link *type, *etype;
7987 D(emitcode ("; genPointerGet",""));
7989 left = IC_LEFT (ic);
7990 result = IC_RESULT (ic);
7992 /* depending on the type of pointer we need to
7993 move it to the correct pointer register */
7994 type = operandType (left);
7995 etype = getSpec (type);
7996 /* if left is of type of pointer then it is simple */
7997 if (IS_PTR (type) && !IS_FUNC (type->next))
7998 p_type = DCL_TYPE (type);
8001 /* we have to go by the storage class */
8002 p_type = PTR_TYPE (SPEC_OCLS (etype));
8005 /* special case when cast remat */
8006 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8007 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8008 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8009 type = operandType (left);
8010 p_type = DCL_TYPE (type);
8012 /* now that we have the pointer type we assign
8013 the pointer values */
8019 genNearPointerGet (left, result, ic, pi);
8023 genPagedPointerGet (left, result, ic, pi);
8027 genFarPointerGet (left, result, ic, pi);
8031 genCodePointerGet (left, result, ic, pi);
8035 genGenPointerGet (left, result, ic, pi);
8043 /*-----------------------------------------------------------------*/
8044 /* genPackBits - generates code for packed bit storage */
8045 /*-----------------------------------------------------------------*/
8047 genPackBits (sym_link * etype,
8049 char *rname, int p_type)
8051 int offset = 0; /* source byte offset */
8052 int rlen = 0; /* remaining bitfield length */
8053 int blen; /* bitfield length */
8054 int bstr; /* bitfield starting bit within byte */
8055 int litval; /* source literal value (if AOP_LIT) */
8056 unsigned char mask; /* bitmask within current byte */
8058 D(emitcode ("; genPackBits",""));
8060 blen = SPEC_BLEN (etype);
8061 bstr = SPEC_BSTR (etype);
8063 /* If the bitfield length is less than a byte */
8066 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8067 (unsigned char) (0xFF >> (8 - bstr)));
8069 if (AOP_TYPE (right) == AOP_LIT)
8071 /* Case with a bitfield length <8 and literal source
8073 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8075 litval &= (~mask) & 0xff;
8076 emitPtrByteGet (rname, p_type, FALSE);
8077 if ((mask|litval)!=0xff)
8078 emitcode ("anl","a,#0x%02x", mask);
8080 emitcode ("orl","a,#0x%02x", litval);
8084 if ((blen==1) && (p_type!=GPOINTER))
8086 /* Case with a bitfield length == 1 and no generic pointer
8088 if (AOP_TYPE (right) == AOP_CRY)
8089 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8092 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8093 emitcode ("rrc","a");
8095 emitPtrByteGet (rname, p_type, FALSE);
8096 emitcode ("mov","acc.%d,c",bstr);
8100 /* Case with a bitfield length < 8 and arbitrary source
8102 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8103 /* shift and mask source value */
8105 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8107 /* transfer A to B and get next byte */
8108 emitPtrByteGet (rname, p_type, TRUE);
8110 emitcode ("anl", "a,#0x%02x", mask);
8111 emitcode ("orl", "a,b");
8112 if (p_type == GPOINTER)
8113 emitcode ("pop", "b");
8117 emitPtrByteSet (rname, p_type, "a");
8121 /* Bit length is greater than 7 bits. In this case, copy */
8122 /* all except the partial byte at the end */
8123 for (rlen=blen;rlen>=8;rlen-=8)
8125 emitPtrByteSet (rname, p_type,
8126 aopGet (AOP (right), offset++, FALSE, TRUE) );
8128 emitcode ("inc", "%s", rname);
8131 /* If there was a partial byte at the end */
8134 mask = (((unsigned char) -1 << rlen) & 0xff);
8136 if (AOP_TYPE (right) == AOP_LIT)
8138 /* Case with partial byte and literal source
8140 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8141 litval >>= (blen-rlen);
8142 litval &= (~mask) & 0xff;
8143 emitPtrByteGet (rname, p_type, FALSE);
8144 if ((mask|litval)!=0xff)
8145 emitcode ("anl","a,#0x%02x", mask);
8147 emitcode ("orl","a,#0x%02x", litval);
8151 /* Case with partial byte and arbitrary source
8153 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8154 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8156 /* transfer A to B and get next byte */
8157 emitPtrByteGet (rname, p_type, TRUE);
8159 emitcode ("anl", "a,#0x%02x", mask);
8160 emitcode ("orl", "a,b");
8161 if (p_type == GPOINTER)
8162 emitcode ("pop", "b");
8164 emitPtrByteSet (rname, p_type, "a");
8170 /*-----------------------------------------------------------------*/
8171 /* genDataPointerSet - remat pointer to data space */
8172 /*-----------------------------------------------------------------*/
8174 genDataPointerSet (operand * right,
8178 int size, offset = 0;
8179 char *l, buffer[256];
8181 D(emitcode ("; genDataPointerSet",""));
8183 aopOp (right, ic, FALSE);
8185 l = aopGet (AOP (result), 0, FALSE, TRUE);
8186 size = AOP_SIZE (right);
8190 sprintf (buffer, "(%s + %d)", l + 1, offset);
8192 sprintf (buffer, "%s", l + 1);
8193 emitcode ("mov", "%s,%s", buffer,
8194 aopGet (AOP (right), offset++, FALSE, FALSE));
8197 freeAsmop (right, NULL, ic, TRUE);
8198 freeAsmop (result, NULL, ic, TRUE);
8201 /*-----------------------------------------------------------------*/
8202 /* genNearPointerSet - emitcode for near pointer put */
8203 /*-----------------------------------------------------------------*/
8205 genNearPointerSet (operand * right,
8213 sym_link *retype, *letype;
8214 sym_link *ptype = operandType (result);
8216 D(emitcode ("; genNearPointerSet",""));
8218 retype = getSpec (operandType (right));
8219 letype = getSpec (ptype);
8220 aopOp (result, ic, FALSE);
8222 /* if the result is rematerializable &
8223 in data space & not a bit variable */
8224 if (AOP_TYPE (result) == AOP_IMMD &&
8225 DCL_TYPE (ptype) == POINTER &&
8226 !IS_BITVAR (retype) &&
8227 !IS_BITVAR (letype))
8229 genDataPointerSet (right, result, ic);
8233 /* if the value is already in a pointer register
8234 then don't need anything more */
8235 if (!AOP_INPREG (AOP (result)))
8238 //AOP_TYPE (result) == AOP_STK
8242 // Aha, it is a pointer, just in disguise.
8243 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8246 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8247 __FILE__, __LINE__);
8252 emitcode ("mov", "a%s,%s", rname + 1, rname);
8253 rname++; // skip the '@'.
8258 /* otherwise get a free pointer register */
8260 preg = getFreePtr (ic, &aop, FALSE);
8261 emitcode ("mov", "%s,%s",
8263 aopGet (AOP (result), 0, FALSE, TRUE));
8269 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8272 aopOp (right, ic, FALSE);
8274 /* if bitfield then unpack the bits */
8275 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8276 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8279 /* we have can just get the values */
8280 int size = AOP_SIZE (right);
8285 l = aopGet (AOP (right), offset, FALSE, TRUE);
8289 emitcode ("mov", "@%s,a", rname);
8292 emitcode ("mov", "@%s,%s", rname, l);
8294 emitcode ("inc", "%s", rname);
8299 /* now some housekeeping stuff */
8300 if (aop) /* we had to allocate for this iCode */
8303 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8304 freeAsmop (NULL, aop, ic, TRUE);
8308 /* we did not allocate which means left
8309 already in a pointer register, then
8310 if size > 0 && this could be used again
8311 we have to point it back to where it
8313 if ((AOP_SIZE (right) > 1 &&
8314 !OP_SYMBOL (result)->remat &&
8315 (OP_SYMBOL (result)->liveTo > ic->seq ||
8319 int size = AOP_SIZE (right) - 1;
8321 emitcode ("dec", "%s", rname);
8326 if (pi) pi->generated = 1;
8327 freeAsmop (result, NULL, ic, TRUE);
8328 freeAsmop (right, NULL, ic, TRUE);
8331 /*-----------------------------------------------------------------*/
8332 /* genPagedPointerSet - emitcode for Paged pointer put */
8333 /*-----------------------------------------------------------------*/
8335 genPagedPointerSet (operand * right,
8343 sym_link *retype, *letype;
8345 D(emitcode ("; genPagedPointerSet",""));
8347 retype = getSpec (operandType (right));
8348 letype = getSpec (operandType (result));
8350 aopOp (result, ic, FALSE);
8352 /* if the value is already in a pointer register
8353 then don't need anything more */
8354 if (!AOP_INPREG (AOP (result)))
8356 /* otherwise get a free pointer register */
8358 preg = getFreePtr (ic, &aop, FALSE);
8359 emitcode ("mov", "%s,%s",
8361 aopGet (AOP (result), 0, FALSE, TRUE));
8365 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8367 aopOp (right, ic, FALSE);
8369 /* if bitfield then unpack the bits */
8370 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8371 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8374 /* we have can just get the values */
8375 int size = AOP_SIZE (right);
8380 l = aopGet (AOP (right), offset, FALSE, TRUE);
8383 emitcode ("movx", "@%s,a", rname);
8386 emitcode ("inc", "%s", rname);
8392 /* now some housekeeping stuff */
8393 if (aop) /* we had to allocate for this iCode */
8396 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8397 freeAsmop (NULL, aop, ic, TRUE);
8401 /* we did not allocate which means left
8402 already in a pointer register, then
8403 if size > 0 && this could be used again
8404 we have to point it back to where it
8406 if (AOP_SIZE (right) > 1 &&
8407 !OP_SYMBOL (result)->remat &&
8408 (OP_SYMBOL (result)->liveTo > ic->seq ||
8411 int size = AOP_SIZE (right) - 1;
8413 emitcode ("dec", "%s", rname);
8418 if (pi) pi->generated = 1;
8419 freeAsmop (result, NULL, ic, TRUE);
8420 freeAsmop (right, NULL, ic, TRUE);
8425 /*-----------------------------------------------------------------*/
8426 /* genFarPointerSet - set value from far space */
8427 /*-----------------------------------------------------------------*/
8429 genFarPointerSet (operand * right,
8430 operand * result, iCode * ic, iCode * pi)
8433 sym_link *retype = getSpec (operandType (right));
8434 sym_link *letype = getSpec (operandType (result));
8436 D(emitcode ("; genFarPointerSet",""));
8438 aopOp (result, ic, FALSE);
8439 loadDptrFromOperand (result, FALSE);
8441 /* so dptr know contains the address */
8442 aopOp (right, ic, FALSE);
8444 /* if bit then unpack */
8445 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8446 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8449 size = AOP_SIZE (right);
8454 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8456 emitcode ("movx", "@dptr,a");
8458 emitcode ("inc", "dptr");
8461 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8462 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8463 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8466 freeAsmop (result, NULL, ic, TRUE);
8467 freeAsmop (right, NULL, ic, TRUE);
8470 /*-----------------------------------------------------------------*/
8471 /* genGenPointerSet - set value from generic pointer space */
8472 /*-----------------------------------------------------------------*/
8474 genGenPointerSet (operand * right,
8475 operand * result, iCode * ic, iCode * pi)
8478 sym_link *retype = getSpec (operandType (right));
8479 sym_link *letype = getSpec (operandType (result));
8481 D(emitcode ("; genGenPointerSet",""));
8483 aopOp (result, ic, FALSE);
8484 loadDptrFromOperand (result, TRUE);
8486 /* so dptr know contains the address */
8487 aopOp (right, ic, FALSE);
8489 /* if bit then unpack */
8490 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8491 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
8494 size = AOP_SIZE (right);
8499 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8501 emitcode ("lcall", "__gptrput");
8503 emitcode ("inc", "dptr");
8507 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8508 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8509 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8512 freeAsmop (result, NULL, ic, TRUE);
8513 freeAsmop (right, NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* genPointerSet - stores the value into a pointer location */
8518 /*-----------------------------------------------------------------*/
8520 genPointerSet (iCode * ic, iCode *pi)
8522 operand *right, *result;
8523 sym_link *type, *etype;
8526 D(emitcode ("; genPointerSet",""));
8528 right = IC_RIGHT (ic);
8529 result = IC_RESULT (ic);
8531 /* depending on the type of pointer we need to
8532 move it to the correct pointer register */
8533 type = operandType (result);
8534 etype = getSpec (type);
8535 /* if left is of type of pointer then it is simple */
8536 if (IS_PTR (type) && !IS_FUNC (type->next))
8538 p_type = DCL_TYPE (type);
8542 /* we have to go by the storage class */
8543 p_type = PTR_TYPE (SPEC_OCLS (etype));
8546 /* special case when cast remat */
8547 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8548 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8549 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8550 type = operandType (result);
8551 p_type = DCL_TYPE (type);
8553 /* now that we have the pointer type we assign
8554 the pointer values */
8560 genNearPointerSet (right, result, ic, pi);
8564 genPagedPointerSet (right, result, ic, pi);
8568 genFarPointerSet (right, result, ic, pi);
8572 genGenPointerSet (right, result, ic, pi);
8576 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8577 "genPointerSet: illegal pointer type");
8582 /*-----------------------------------------------------------------*/
8583 /* genIfx - generate code for Ifx statement */
8584 /*-----------------------------------------------------------------*/
8586 genIfx (iCode * ic, iCode * popIc)
8588 operand *cond = IC_COND (ic);
8591 D(emitcode ("; genIfx",""));
8593 aopOp (cond, ic, FALSE);
8595 /* get the value into acc */
8596 if (AOP_TYPE (cond) != AOP_CRY)
8600 /* the result is now in the accumulator */
8601 freeAsmop (cond, NULL, ic, TRUE);
8603 /* if there was something to be popped then do it */
8607 /* if the condition is a bit variable */
8608 if (isbit && IS_ITEMP (cond) &&
8610 genIfxJump (ic, SPIL_LOC (cond)->rname);
8611 else if (isbit && !IS_ITEMP (cond))
8612 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8614 genIfxJump (ic, "a");
8619 /*-----------------------------------------------------------------*/
8620 /* genAddrOf - generates code for address of */
8621 /*-----------------------------------------------------------------*/
8623 genAddrOf (iCode * ic)
8625 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8628 D(emitcode ("; genAddrOf",""));
8630 aopOp (IC_RESULT (ic), ic, FALSE);
8632 /* if the operand is on the stack then we
8633 need to get the stack offset of this
8637 /* if it has an offset then we need to compute
8641 emitcode ("mov", "a,_bp");
8642 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8643 ((char) (sym->stack - _G.nRegsSaved)) :
8644 ((char) sym->stack)) & 0xff);
8645 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8649 /* we can just move _bp */
8650 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8652 /* fill the result with zero */
8653 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8658 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8664 /* object not on stack then we need the name */
8665 size = AOP_SIZE (IC_RESULT (ic));
8670 char s[SDCC_NAME_MAX];
8672 sprintf (s, "#(%s >> %d)",
8676 sprintf (s, "#%s", sym->rname);
8677 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8685 /*-----------------------------------------------------------------*/
8686 /* genFarFarAssign - assignment when both are in far space */
8687 /*-----------------------------------------------------------------*/
8689 genFarFarAssign (operand * result, operand * right, iCode * ic)
8691 int size = AOP_SIZE (right);
8695 D(emitcode ("; genFarFarAssign",""));
8697 /* first push the right side on to the stack */
8700 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8702 emitcode ("push", "acc");
8705 freeAsmop (right, NULL, ic, FALSE);
8706 /* now assign DPTR to result */
8707 aopOp (result, ic, FALSE);
8708 size = AOP_SIZE (result);
8711 emitcode ("pop", "acc");
8712 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8714 freeAsmop (result, NULL, ic, FALSE);
8718 /*-----------------------------------------------------------------*/
8719 /* genAssign - generate code for assignment */
8720 /*-----------------------------------------------------------------*/
8722 genAssign (iCode * ic)
8724 operand *result, *right;
8726 unsigned long lit = 0L;
8728 D(emitcode("; genAssign",""));
8730 result = IC_RESULT (ic);
8731 right = IC_RIGHT (ic);
8733 /* if they are the same */
8734 if (operandsEqu (result, right) &&
8735 !isOperandVolatile (result, FALSE) &&
8736 !isOperandVolatile (right, FALSE))
8739 aopOp (right, ic, FALSE);
8741 /* special case both in far space */
8742 if (AOP_TYPE (right) == AOP_DPTR &&
8743 IS_TRUE_SYMOP (result) &&
8744 isOperandInFarSpace (result))
8747 genFarFarAssign (result, right, ic);
8751 aopOp (result, ic, TRUE);
8753 /* if they are the same registers */
8754 if (sameRegs (AOP (right), AOP (result)) &&
8755 !isOperandVolatile (result, FALSE) &&
8756 !isOperandVolatile (right, FALSE))
8759 /* if the result is a bit */
8760 if (AOP_TYPE (result) == AOP_CRY)
8763 /* if the right size is a literal then
8764 we know what the value is */
8765 if (AOP_TYPE (right) == AOP_LIT)
8767 if (((int) operandLitValue (right)))
8768 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8770 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8774 /* the right is also a bit variable */
8775 if (AOP_TYPE (right) == AOP_CRY)
8777 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8778 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8784 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8788 /* bit variables done */
8790 size = AOP_SIZE (result);
8792 if (AOP_TYPE (right) == AOP_LIT)
8793 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8795 (AOP_TYPE (result) != AOP_REG) &&
8796 (AOP_TYPE (right) == AOP_LIT) &&
8797 !IS_FLOAT (operandType (right)) &&
8800 emitcode ("clr", "a");
8803 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8804 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8806 aopPut (AOP (result),
8807 aopGet (AOP (right), size, FALSE, FALSE),
8809 isOperandVolatile (result, FALSE));
8816 aopPut (AOP (result),
8817 aopGet (AOP (right), offset, FALSE, FALSE),
8819 isOperandVolatile (result, FALSE));
8825 freeAsmop (right, NULL, ic, TRUE);
8826 freeAsmop (result, NULL, ic, TRUE);
8829 /*-----------------------------------------------------------------*/
8830 /* genJumpTab - genrates code for jump table */
8831 /*-----------------------------------------------------------------*/
8833 genJumpTab (iCode * ic)
8838 D(emitcode ("; genJumpTab",""));
8840 aopOp (IC_JTCOND (ic), ic, FALSE);
8841 /* get the condition into accumulator */
8842 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8844 /* multiply by three */
8845 emitcode ("add", "a,acc");
8846 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8847 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8849 jtab = newiTempLabel (NULL);
8850 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8851 emitcode ("jmp", "@a+dptr");
8852 emitcode ("", "%05d$:", jtab->key + 100);
8853 /* now generate the jump labels */
8854 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8855 jtab = setNextItem (IC_JTLABELS (ic)))
8856 emitcode ("ljmp", "%05d$", jtab->key + 100);
8860 /*-----------------------------------------------------------------*/
8861 /* genCast - gen code for casting */
8862 /*-----------------------------------------------------------------*/
8864 genCast (iCode * ic)
8866 operand *result = IC_RESULT (ic);
8867 sym_link *ctype = operandType (IC_LEFT (ic));
8868 sym_link *rtype = operandType (IC_RIGHT (ic));
8869 operand *right = IC_RIGHT (ic);
8872 D(emitcode("; genCast",""));
8874 /* if they are equivalent then do nothing */
8875 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8878 aopOp (right, ic, FALSE);
8879 aopOp (result, ic, FALSE);
8881 /* if the result is a bit (and not a bitfield) */
8882 // if (AOP_TYPE (result) == AOP_CRY)
8883 if (IS_BITVAR (OP_SYMBOL (result)->type)
8884 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8886 /* if the right size is a literal then
8887 we know what the value is */
8888 if (AOP_TYPE (right) == AOP_LIT)
8890 if (((int) operandLitValue (right)))
8891 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8893 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8898 /* the right is also a bit variable */
8899 if (AOP_TYPE (right) == AOP_CRY)
8901 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8902 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8908 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8913 /* if they are the same size : or less */
8914 if (AOP_SIZE (result) <= AOP_SIZE (right))
8917 /* if they are in the same place */
8918 if (sameRegs (AOP (right), AOP (result)))
8921 /* if they in different places then copy */
8922 size = AOP_SIZE (result);
8926 aopPut (AOP (result),
8927 aopGet (AOP (right), offset, FALSE, FALSE),
8929 isOperandVolatile (result, FALSE));
8936 /* if the result is of type pointer */
8941 sym_link *type = operandType (right);
8942 sym_link *etype = getSpec (type);
8944 /* pointer to generic pointer */
8945 if (IS_GENPTR (ctype))
8948 p_type = DCL_TYPE (type);
8951 if (SPEC_SCLS(etype)==S_REGISTER) {
8952 // let's assume it is a generic pointer
8955 /* we have to go by the storage class */
8956 p_type = PTR_TYPE (SPEC_OCLS (etype));
8960 /* the first two bytes are known */
8961 size = GPTRSIZE - 1;
8965 aopPut (AOP (result),
8966 aopGet (AOP (right), offset, FALSE, FALSE),
8968 isOperandVolatile (result, FALSE));
8971 /* the last byte depending on type */
8973 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8978 // pointerTypeToGPByte will have bitched.
8982 sprintf(gpValStr, "#0x%d", gpVal);
8983 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8988 /* just copy the pointers */
8989 size = AOP_SIZE (result);
8993 aopPut (AOP (result),
8994 aopGet (AOP (right), offset, FALSE, FALSE),
8996 isOperandVolatile (result, FALSE));
9002 /* so we now know that the size of destination is greater
9003 than the size of the source */
9004 /* we move to result for the size of source */
9005 size = AOP_SIZE (right);
9009 aopPut (AOP (result),
9010 aopGet (AOP (right), offset, FALSE, FALSE),
9012 isOperandVolatile (result, FALSE));
9016 /* now depending on the sign of the source && destination */
9017 size = AOP_SIZE (result) - AOP_SIZE (right);
9018 /* if unsigned or not an integral type */
9019 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9022 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9026 /* we need to extend the sign :{ */
9027 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9030 emitcode ("rlc", "a");
9031 emitcode ("subb", "a,acc");
9033 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9036 /* we are done hurray !!!! */
9039 freeAsmop (right, NULL, ic, TRUE);
9040 freeAsmop (result, NULL, ic, TRUE);
9044 /*-----------------------------------------------------------------*/
9045 /* genDjnz - generate decrement & jump if not zero instrucion */
9046 /*-----------------------------------------------------------------*/
9048 genDjnz (iCode * ic, iCode * ifx)
9054 D(emitcode ("; genDjnz",""));
9056 /* if the if condition has a false label
9057 then we cannot save */
9061 /* if the minus is not of the form
9063 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9064 !IS_OP_LITERAL (IC_RIGHT (ic)))
9067 if (operandLitValue (IC_RIGHT (ic)) != 1)
9070 /* if the size of this greater than one then no
9072 if (getSize (operandType (IC_RESULT (ic))) > 1)
9075 /* otherwise we can save BIG */
9076 lbl = newiTempLabel (NULL);
9077 lbl1 = newiTempLabel (NULL);
9079 aopOp (IC_RESULT (ic), ic, FALSE);
9081 if (AOP_NEEDSACC(IC_RESULT(ic)))
9083 /* If the result is accessed indirectly via
9084 * the accumulator, we must explicitly write
9085 * it back after the decrement.
9087 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9089 if (strcmp(rByte, "a"))
9091 /* Something is hopelessly wrong */
9092 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9093 __FILE__, __LINE__);
9094 /* We can just give up; the generated code will be inefficient,
9097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9100 emitcode ("dec", "%s", rByte);
9101 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9102 emitcode ("jnz", "%05d$", lbl->key + 100);
9104 else if (IS_AOP_PREG (IC_RESULT (ic)))
9106 emitcode ("dec", "%s",
9107 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9108 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9109 emitcode ("jnz", "%05d$", lbl->key + 100);
9113 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9116 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9117 emitcode ("", "%05d$:", lbl->key + 100);
9118 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9119 emitcode ("", "%05d$:", lbl1->key + 100);
9121 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9126 /*-----------------------------------------------------------------*/
9127 /* genReceive - generate code for a receive iCode */
9128 /*-----------------------------------------------------------------*/
9130 genReceive (iCode * ic)
9132 int size = getSize (operandType (IC_RESULT (ic)));
9134 D(emitcode ("; genReceive",""));
9136 if (ic->argreg == 1) { /* first parameter */
9137 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9138 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9139 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9145 for (offset = 0; offset<size; offset++)
9146 if (!strcmp (fReturn[offset], "a"))
9151 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9153 for (offset = size-1; offset>0; offset--)
9154 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9155 emitcode("mov","a,%s", fReturn[0]);
9157 aopOp (IC_RESULT (ic), ic, FALSE);
9159 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9160 isOperandVolatile (IC_RESULT (ic), FALSE));
9161 for (offset = 1; offset<size; offset++)
9162 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9163 isOperandVolatile (IC_RESULT (ic), FALSE));
9169 if (getTempRegs(tempRegs, size, ic))
9171 for (offset = 0; offset<size; offset++)
9172 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9173 aopOp (IC_RESULT (ic), ic, FALSE);
9174 for (offset = 0; offset<size; offset++)
9175 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9176 isOperandVolatile (IC_RESULT (ic), FALSE));
9181 offset = fReturnSizeMCS51 - size;
9183 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9184 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9187 aopOp (IC_RESULT (ic), ic, FALSE);
9188 size = AOP_SIZE (IC_RESULT (ic));
9191 emitcode ("pop", "acc");
9192 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9197 aopOp (IC_RESULT (ic), ic, FALSE);
9199 assignResultValue (IC_RESULT (ic));
9201 } else { /* second receive onwards */
9203 aopOp (IC_RESULT (ic), ic, FALSE);
9204 rb1off = ic->argreg;
9206 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9211 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9214 /*-----------------------------------------------------------------*/
9215 /* genDummyRead - generate code for dummy read of volatiles */
9216 /*-----------------------------------------------------------------*/
9218 genDummyRead (iCode * ic)
9223 D(emitcode("; genDummyRead",""));
9226 if (op && IS_SYMOP (op))
9228 aopOp (op, ic, FALSE);
9230 /* if the result is a bit */
9231 if (AOP_TYPE (op) == AOP_CRY)
9232 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9235 /* bit variables done */
9237 size = AOP_SIZE (op);
9241 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9246 freeAsmop (op, NULL, ic, TRUE);
9250 if (op && IS_SYMOP (op))
9252 aopOp (op, ic, FALSE);
9254 /* if the result is a bit */
9255 if (AOP_TYPE (op) == AOP_CRY)
9256 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9259 /* bit variables done */
9261 size = AOP_SIZE (op);
9265 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9270 freeAsmop (op, NULL, ic, TRUE);
9274 /*-----------------------------------------------------------------*/
9275 /* genCritical - generate code for start of a critical sequence */
9276 /*-----------------------------------------------------------------*/
9278 genCritical (iCode *ic)
9280 symbol *tlbl = newiTempLabel (NULL);
9282 D(emitcode("; genCritical",""));
9285 aopOp (IC_RESULT (ic), ic, TRUE);
9287 emitcode ("setb", "c");
9288 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9289 emitcode ("clr", "c");
9290 emitcode ("", "%05d$:", (tlbl->key + 100));
9293 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9295 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9298 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9301 /*-----------------------------------------------------------------*/
9302 /* genEndCritical - generate code for end of a critical sequence */
9303 /*-----------------------------------------------------------------*/
9305 genEndCritical (iCode *ic)
9307 D(emitcode("; genEndCritical",""));
9311 aopOp (IC_RIGHT (ic), ic, FALSE);
9312 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9314 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9315 emitcode ("mov", "ea,c");
9319 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9320 emitcode ("rrc", "a");
9321 emitcode ("mov", "ea,c");
9323 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9327 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9328 emitcode ("mov", "ea,c");
9333 /*-----------------------------------------------------------------*/
9334 /* gen51Code - generate code for 8051 based controllers */
9335 /*-----------------------------------------------------------------*/
9337 gen51Code (iCode * lic)
9342 _G.currentFunc = NULL;
9343 lineHead = lineCurr = NULL;
9345 /* print the allocation information */
9346 if (allocInfo && currFunc)
9347 printAllocInfo (currFunc, codeOutFile);
9348 /* if debug information required */
9349 if (options.debug && currFunc)
9351 debugFile->writeFunction(currFunc);
9353 if (IS_STATIC (currFunc->etype))
9354 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9356 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9359 /* stack pointer name */
9360 if (options.useXstack)
9366 for (ic = lic; ic; ic = ic->next)
9368 _G.current_iCode = ic;
9370 if (ic->lineno && cln != ic->lineno)
9375 emitcode ("", "C$%s$%d$%d$%d ==.",
9376 FileBaseName (ic->filename), ic->lineno,
9377 ic->level, ic->block);
9380 if (!options.noCcodeInAsm) {
9381 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9382 printCLine(ic->filename, ic->lineno));
9386 if (options.iCodeInAsm) {
9390 for (i=0; i<8; i++) {
9391 sprintf (®sInUse[i],
9392 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9395 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9397 /* if the result is marked as
9398 spilt and rematerializable or code for
9399 this has already been generated then
9401 if (resultRemat (ic) || ic->generated)
9404 /* depending on the operation */
9424 /* IPOP happens only when trying to restore a
9425 spilt live range, if there is an ifx statement
9426 following this pop then the if statement might
9427 be using some of the registers being popped which
9428 would destory the contents of the register so
9429 we need to check for this condition and handle it */
9431 ic->next->op == IFX &&
9432 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9433 genIfx (ic->next, ic);
9451 genEndFunction (ic);
9471 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9488 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9492 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9499 /* note these two are xlated by algebraic equivalence
9500 during parsing SDCC.y */
9501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9502 "got '>=' or '<=' shouldn't have come here");
9506 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9518 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9522 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9526 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9553 case GET_VALUE_AT_ADDRESS:
9554 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9558 if (POINTER_SET (ic))
9559 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9585 addSet (&_G.sendSet, ic);
9588 case DUMMY_READ_VOLATILE:
9597 genEndCritical (ic);
9609 _G.current_iCode = NULL;
9611 /* now we are ready to call the
9612 peep hole optimizer */
9613 if (!options.nopeep)
9614 peepHole (&lineHead);
9616 /* now do the actual printing */
9617 printLine (lineHead, codeOutFile);