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))
139 lineCurr = (lineCurr ?
140 connectLine (lineCurr, newLineNode (lb)) :
141 (lineHead = newLineNode (lb)));
142 lineCurr->isInline = _G.inLine;
143 lineCurr->isDebug = _G.debugLine;
144 lineCurr->ic = _G.current_iCode;
145 lineCurr->isComment = (*lbp==';');
149 /*-----------------------------------------------------------------*/
150 /* mova - moves specified value into accumulator */
151 /*-----------------------------------------------------------------*/
155 /* do some early peephole optimization */
156 if (!strcmp(x, "a") || !strcmp(x, "acc"))
159 emitcode("mov","a,%s", x);
162 /*-----------------------------------------------------------------*/
163 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
164 /*-----------------------------------------------------------------*/
166 getFreePtr (iCode * ic, asmop ** aopp, bool result)
168 bool r0iu = FALSE, r1iu = FALSE;
169 bool r0ou = FALSE, r1ou = FALSE;
171 /* the logic: if r0 & r1 used in the instruction
172 then we are in trouble otherwise */
174 /* first check if r0 & r1 are used by this
175 instruction, in which case we are in trouble */
176 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
177 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
182 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
183 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
185 /* if no usage of r0 then return it */
188 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
189 (*aopp)->type = AOP_R0;
191 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
194 /* if no usage of r1 then return it */
197 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
198 (*aopp)->type = AOP_R1;
200 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
203 /* now we know they both have usage */
204 /* if r0 not used in this instruction */
207 /* push it if not already pushed */
210 emitcode ("push", "%s",
211 mcs51_regWithIdx (R0_IDX)->dname);
215 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
216 (*aopp)->type = AOP_R0;
218 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
221 /* if r1 not used then */
225 /* push it if not already pushed */
228 emitcode ("push", "%s",
229 mcs51_regWithIdx (R1_IDX)->dname);
233 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
234 (*aopp)->type = AOP_R1;
235 return mcs51_regWithIdx (R1_IDX);
238 /* I said end of world, but not quite end of world yet */
240 /* we can push it on the stack */
241 (*aopp)->type = AOP_STK;
244 /* in the case that result AND left AND right needs a pointer reg
245 we can safely use the result's */
246 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
247 (*aopp)->type = AOP_R0;
248 return mcs51_regWithIdx (R0_IDX);
250 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
251 (*aopp)->type = AOP_R1;
252 return mcs51_regWithIdx (R1_IDX);
256 /* now this is REALLY the end of the world */
257 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
258 "getFreePtr should never reach here");
263 /*-----------------------------------------------------------------*/
264 /* getTempRegs - initialize an array of pointers to GPR registers */
265 /* that are not in use. Returns 1 if the requested */
266 /* number of registers were available, 0 otherwise. */
267 /*-----------------------------------------------------------------*/
269 getTempRegs(regs **tempRegs, int size, iCode *ic)
276 ic = _G.current_iCode;
282 freeRegs = newBitVect(8);
283 bitVectSetBit (freeRegs, R2_IDX);
284 bitVectSetBit (freeRegs, R3_IDX);
285 bitVectSetBit (freeRegs, R4_IDX);
286 bitVectSetBit (freeRegs, R5_IDX);
287 bitVectSetBit (freeRegs, R6_IDX);
288 bitVectSetBit (freeRegs, R7_IDX);
290 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
292 bitVect * newfreeRegs;
293 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
294 freeBitVect(freeRegs);
295 freeRegs = newfreeRegs;
297 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
300 for (i=0; i<freeRegs->size; i++)
302 if (bitVectBitValue(freeRegs,i))
303 tempRegs[offset++] = mcs51_regWithIdx(i);
306 freeBitVect(freeRegs);
311 freeBitVect(freeRegs);
316 /*-----------------------------------------------------------------*/
317 /* newAsmop - creates a new asmOp */
318 /*-----------------------------------------------------------------*/
320 newAsmop (short type)
324 aop = Safe_calloc (1, sizeof (asmop));
329 /*-----------------------------------------------------------------*/
330 /* pointerCode - returns the code for a pointer type */
331 /*-----------------------------------------------------------------*/
333 pointerCode (sym_link * etype)
336 return PTR_TYPE (SPEC_OCLS (etype));
341 /*-----------------------------------------------------------------*/
342 /* leftRightUseAcc - returns size of accumulator use by operands */
343 /*-----------------------------------------------------------------*/
345 leftRightUseAcc(iCode *ic)
354 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
355 "null iCode pointer");
362 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
365 size = getSize (OP_SYMBOL (op)->type);
370 else if (ic->op == JUMPTABLE)
373 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
376 size = getSize (OP_SYMBOL (op)->type);
384 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
387 size = getSize (OP_SYMBOL (op)->type);
392 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
395 size = getSize (OP_SYMBOL (op)->type);
408 /*-----------------------------------------------------------------*/
409 /* aopForSym - for a true symbol */
410 /*-----------------------------------------------------------------*/
412 aopForSym (iCode * ic, symbol * sym, bool result)
417 wassertl (ic != NULL, "Got a null iCode");
418 wassertl (sym != NULL, "Got a null symbol");
420 space = SPEC_OCLS (sym->etype);
422 /* if already has one */
426 /* assign depending on the storage class */
427 /* if it is on the stack or indirectly addressable */
428 /* space we need to assign either r0 or r1 to it */
429 if (sym->onStack || sym->iaccess)
431 sym->aop = aop = newAsmop (0);
432 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
433 aop->size = getSize (sym->type);
435 /* now assign the address of the variable to
436 the pointer register */
437 if (aop->type != AOP_STK)
442 if (_G.accInUse || leftRightUseAcc (ic))
443 emitcode ("push", "acc");
445 emitcode ("mov", "a,_bp");
446 emitcode ("add", "a,#0x%02x",
448 ((char) (sym->stack - _G.nRegsSaved)) :
449 ((char) sym->stack)) & 0xff);
450 emitcode ("mov", "%s,a",
451 aop->aopu.aop_ptr->name);
453 if (_G.accInUse || leftRightUseAcc (ic))
454 emitcode ("pop", "acc");
457 emitcode ("mov", "%s,#%s",
458 aop->aopu.aop_ptr->name,
460 aop->paged = space->paged;
463 aop->aopu.aop_stk = sym->stack;
467 /* if in bit space */
468 if (IN_BITSPACE (space))
470 sym->aop = aop = newAsmop (AOP_CRY);
471 aop->aopu.aop_dir = sym->rname;
472 aop->size = getSize (sym->type);
475 /* if it is in direct space */
476 if (IN_DIRSPACE (space))
478 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
479 //printTypeChainRaw(sym->type, NULL);
480 //printf("space = %s\n", space ? space->sname : "NULL");
481 sym->aop = aop = newAsmop (AOP_DIR);
482 aop->aopu.aop_dir = sym->rname;
483 aop->size = getSize (sym->type);
487 /* special case for a function */
488 if (IS_FUNC (sym->type))
490 sym->aop = aop = newAsmop (AOP_IMMD);
491 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
492 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
493 aop->size = FPTRSIZE;
497 /* only remaining is far space */
498 /* in which case DPTR gets the address */
499 sym->aop = aop = newAsmop (AOP_DPTR);
500 emitcode ("mov", "dptr,#%s", sym->rname);
501 aop->size = getSize (sym->type);
503 /* if it is in code space */
504 if (IN_CODESPACE (space))
510 /*-----------------------------------------------------------------*/
511 /* aopForRemat - rematerialzes an object */
512 /*-----------------------------------------------------------------*/
514 aopForRemat (symbol * sym)
516 iCode *ic = sym->rematiCode;
517 asmop *aop = newAsmop (AOP_IMMD);
524 val += (int) operandLitValue (IC_RIGHT (ic));
525 else if (ic->op == '-')
526 val -= (int) operandLitValue (IC_RIGHT (ic));
527 else if (IS_CAST_ICODE(ic)) {
528 sym_link *from_type = operandType(IC_RIGHT(ic));
529 aop->aopu.aop_immd.from_cast_remat = 1;
530 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
531 ptr_type = DCL_TYPE(from_type);
532 if (ptr_type == IPOINTER) {
539 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
543 sprintf (buffer, "(%s %c 0x%04x)",
544 OP_SYMBOL (IC_LEFT (ic))->rname,
545 val >= 0 ? '+' : '-',
548 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
550 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
551 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
552 /* set immd2 field if required */
553 if (aop->aopu.aop_immd.from_cast_remat) {
554 sprintf(buffer,"#0x%02x",ptr_type);
555 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
556 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
562 /*-----------------------------------------------------------------*/
563 /* regsInCommon - two operands have some registers in common */
564 /*-----------------------------------------------------------------*/
566 regsInCommon (operand * op1, operand * op2)
571 /* if they have registers in common */
572 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
575 sym1 = OP_SYMBOL (op1);
576 sym2 = OP_SYMBOL (op2);
578 if (sym1->nRegs == 0 || sym2->nRegs == 0)
581 for (i = 0; i < sym1->nRegs; i++)
587 for (j = 0; j < sym2->nRegs; j++)
592 if (sym2->regs[j] == sym1->regs[i])
600 /*-----------------------------------------------------------------*/
601 /* operandsEqu - equivalent */
602 /*-----------------------------------------------------------------*/
604 operandsEqu (operand * op1, operand * op2)
608 /* if they not symbols */
609 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
612 sym1 = OP_SYMBOL (op1);
613 sym2 = OP_SYMBOL (op2);
615 /* if both are itemps & one is spilt
616 and the other is not then false */
617 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
618 sym1->isspilt != sym2->isspilt)
621 /* if they are the same */
625 if (strcmp (sym1->rname, sym2->rname) == 0)
629 /* if left is a tmp & right is not */
630 if (IS_ITEMP (op1) &&
633 (sym1->usl.spillLoc == sym2))
636 if (IS_ITEMP (op2) &&
640 (sym2->usl.spillLoc == sym1))
646 /*-----------------------------------------------------------------*/
647 /* sameRegs - two asmops have the same registers */
648 /*-----------------------------------------------------------------*/
650 sameRegs (asmop * aop1, asmop * aop2)
657 if (aop1->type != AOP_REG ||
658 aop2->type != AOP_REG)
661 if (aop1->size != aop2->size)
664 for (i = 0; i < aop1->size; i++)
665 if (aop1->aopu.aop_reg[i] !=
666 aop2->aopu.aop_reg[i])
672 /*-----------------------------------------------------------------*/
673 /* aopOp - allocates an asmop for an operand : */
674 /*-----------------------------------------------------------------*/
676 aopOp (operand * op, iCode * ic, bool result)
685 /* if this a literal */
686 if (IS_OP_LITERAL (op))
688 op->aop = aop = newAsmop (AOP_LIT);
689 aop->aopu.aop_lit = op->operand.valOperand;
690 aop->size = getSize (operandType (op));
694 /* if already has a asmop then continue */
698 /* if the underlying symbol has a aop */
699 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
701 op->aop = OP_SYMBOL (op)->aop;
705 /* if this is a true symbol */
706 if (IS_TRUE_SYMOP (op))
708 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
712 /* this is a temporary : this has
718 e) can be a return use only */
720 sym = OP_SYMBOL (op);
722 /* if the type is a conditional */
723 if (sym->regType == REG_CND)
725 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
730 /* if it is spilt then two situations
732 b) has a spill location */
733 if (sym->isspilt || sym->nRegs == 0)
736 /* rematerialize it NOW */
739 sym->aop = op->aop = aop =
741 aop->size = getSize (sym->type);
748 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
749 aop->size = getSize (sym->type);
750 for (i = 0; i < 2; i++)
751 aop->aopu.aop_str[i] = accUse[i];
759 aop = op->aop = sym->aop = newAsmop (AOP_STR);
760 aop->size = getSize (sym->type);
761 for (i = 0; i < fReturnSizeMCS51; i++)
762 aop->aopu.aop_str[i] = fReturn[i];
766 if (sym->usl.spillLoc)
768 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
770 /* force a new aop if sizes differ */
771 sym->usl.spillLoc->aop = NULL;
773 sym->aop = op->aop = aop =
774 aopForSym (ic, sym->usl.spillLoc, result);
775 aop->size = getSize (sym->type);
779 /* else must be a dummy iTemp */
780 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
781 aop->size = getSize (sym->type);
785 /* must be in a register */
786 sym->aop = op->aop = aop = newAsmop (AOP_REG);
787 aop->size = sym->nRegs;
788 for (i = 0; i < sym->nRegs; i++)
789 aop->aopu.aop_reg[i] = sym->regs[i];
792 /*-----------------------------------------------------------------*/
793 /* freeAsmop - free up the asmop given to an operand */
794 /*----------------------------------------------------------------*/
796 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
813 /* depending on the asmop type only three cases need work AOP_RO
814 , AOP_R1 && AOP_STK */
822 emitcode ("pop", "ar0");
826 bitVectUnSetBit (ic->rUsed, R0_IDX);
834 emitcode ("pop", "ar1");
838 bitVectUnSetBit (ic->rUsed, R1_IDX);
844 int stk = aop->aopu.aop_stk + aop->size - 1;
845 bitVectUnSetBit (ic->rUsed, R0_IDX);
846 bitVectUnSetBit (ic->rUsed, R1_IDX);
848 getFreePtr (ic, &aop, FALSE);
852 emitcode ("mov", "a,_bp");
853 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
854 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
858 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
863 emitcode ("pop", "acc");
864 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
867 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
870 freeAsmop (op, NULL, ic, TRUE);
873 emitcode ("pop", "ar1");
879 emitcode ("pop", "ar0");
886 /* all other cases just dealloc */
892 OP_SYMBOL (op)->aop = NULL;
893 /* if the symbol has a spill */
895 SPIL_LOC (op)->aop = NULL;
900 /*-----------------------------------------------------------------*/
901 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
902 /* clobber the accumulator */
903 /*-----------------------------------------------------------------*/
905 aopGetUsesAcc (asmop *aop, int offset)
907 if (offset > (aop->size - 1))
925 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
934 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
940 /* Error case --- will have been caught already */
946 /*-----------------------------------------------------------------*/
947 /* aopGet - for fetching value of the aop */
948 /*-----------------------------------------------------------------*/
950 aopGet (asmop * aop, int offset, bool bit16, bool dname)
955 /* offset is greater than
957 if (offset > (aop->size - 1) &&
958 aop->type != AOP_LIT)
961 /* depending on type */
969 /* if we need to increment it */
970 while (offset > aop->coff)
972 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
976 while (offset < aop->coff)
978 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
985 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
986 return (dname ? "acc" : "a");
988 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
989 rs = Safe_calloc (1, strlen (s) + 1);
994 if (aop->code && aop->coff==0 && offset>=1) {
995 emitcode ("mov", "a,#0x%02x", offset);
996 emitcode ("movc", "a,@a+dptr");
997 return (dname ? "acc" : "a");
1000 while (offset > aop->coff)
1002 emitcode ("inc", "dptr");
1006 while (offset < aop->coff)
1008 emitcode ("lcall", "__decdptr");
1015 emitcode ("clr", "a");
1016 emitcode ("movc", "a,@a+dptr");
1020 emitcode ("movx", "a,@dptr");
1022 return (dname ? "acc" : "a");
1026 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1027 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1029 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1031 sprintf (s, "#(%s >> %d)",
1032 aop->aopu.aop_immd.aop_immd1,
1036 aop->aopu.aop_immd.aop_immd1);
1037 rs = Safe_calloc (1, strlen (s) + 1);
1043 sprintf (s, "(%s + %d)",
1047 sprintf (s, "%s", aop->aopu.aop_dir);
1048 rs = Safe_calloc (1, strlen (s) + 1);
1054 return aop->aopu.aop_reg[offset]->dname;
1056 return aop->aopu.aop_reg[offset]->name;
1059 emitcode ("clr", "a");
1060 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1061 emitcode ("rlc", "a");
1062 return (dname ? "acc" : "a");
1065 if (!offset && dname)
1067 return aop->aopu.aop_str[offset];
1070 return aopLiteral (aop->aopu.aop_lit, offset);
1074 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1078 return aop->aopu.aop_str[offset];
1082 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1083 "aopget got unsupported aop->type");
1086 /*-----------------------------------------------------------------*/
1087 /* aopPut - puts a string for a aop */
1088 /*-----------------------------------------------------------------*/
1090 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1094 if (aop->size && offset > (aop->size - 1))
1096 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1097 "aopPut got offset > aop->size");
1101 /* will assign value to value */
1102 /* depending on where it is ofcourse */
1106 MOVA (s); /* read s in case it was volatile */
1111 sprintf (d, "(%s + %d)",
1112 aop->aopu.aop_dir, offset);
1114 sprintf (d, "%s", aop->aopu.aop_dir);
1116 if (strcmp (d, s) ||
1118 emitcode ("mov", "%s,%s", d, s);
1123 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1127 strcmp (s, "r0") == 0 ||
1128 strcmp (s, "r1") == 0 ||
1129 strcmp (s, "r2") == 0 ||
1130 strcmp (s, "r3") == 0 ||
1131 strcmp (s, "r4") == 0 ||
1132 strcmp (s, "r5") == 0 ||
1133 strcmp (s, "r6") == 0 ||
1134 strcmp (s, "r7") == 0)
1135 emitcode ("mov", "%s,%s",
1136 aop->aopu.aop_reg[offset]->dname, s);
1138 emitcode ("mov", "%s,%s",
1139 aop->aopu.aop_reg[offset]->name, s);
1146 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1147 "aopPut writing to code space");
1151 while (offset > aop->coff)
1154 emitcode ("inc", "dptr");
1157 while (offset < aop->coff)
1160 emitcode ("lcall", "__decdptr");
1165 /* if not in accumulater */
1168 emitcode ("movx", "@dptr,a");
1173 while (offset > aop->coff)
1176 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1178 while (offset < aop->coff)
1181 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1188 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1194 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1196 else if (strcmp (s, "r0") == 0 ||
1197 strcmp (s, "r1") == 0 ||
1198 strcmp (s, "r2") == 0 ||
1199 strcmp (s, "r3") == 0 ||
1200 strcmp (s, "r4") == 0 ||
1201 strcmp (s, "r5") == 0 ||
1202 strcmp (s, "r6") == 0 ||
1203 strcmp (s, "r7") == 0)
1206 sprintf (buffer, "a%s", s);
1207 emitcode ("mov", "@%s,%s",
1208 aop->aopu.aop_ptr->name, buffer);
1211 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1216 if (strcmp (s, "a") == 0)
1217 emitcode ("push", "acc");
1221 emitcode ("push", "acc");
1223 emitcode ("push", s);
1229 /* if bit variable */
1230 if (!aop->aopu.aop_dir)
1232 emitcode ("clr", "a");
1233 emitcode ("rlc", "a");
1238 emitcode ("clr", "%s", aop->aopu.aop_dir);
1240 emitcode ("setb", "%s", aop->aopu.aop_dir);
1241 else if (!strcmp (s, "c"))
1242 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1245 if (strcmp (s, "a"))
1250 /* set C, if a >= 1 */
1251 emitcode ("add", "a,#0xff");
1252 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1260 if (strcmp (aop->aopu.aop_str[offset], s) ||
1262 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1267 if (!offset && (strcmp (s, "acc") == 0) &&
1271 if (strcmp (aop->aopu.aop_str[offset], s) &&
1273 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1277 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1278 "aopPut got unsupported aop->type");
1286 /*-----------------------------------------------------------------*/
1287 /* pointToEnd :- points to the last byte of the operand */
1288 /*-----------------------------------------------------------------*/
1290 pointToEnd (asmop * aop)
1296 aop->coff = count = (aop->size - 1);
1302 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1306 emitcode ("inc", "dptr");
1313 /*-----------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should */
1315 /*-----------------------------------------------------------------*/
1317 reAdjustPreg (asmop * aop)
1319 if ((aop->coff==0) || aop->size <= 1)
1327 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1332 emitcode ("lcall", "__decdptr");
1339 #define AOP(op) op->aop
1340 #define AOP_TYPE(op) AOP(op)->type
1341 #define AOP_SIZE(op) AOP(op)->size
1342 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1343 AOP_TYPE(x) == AOP_R0))
1345 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1346 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1348 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1349 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1350 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1353 /*-----------------------------------------------------------------*/
1354 /* opIsGptr: returns non-zero if the passed operand is */
1355 /* a generic pointer type. */
1356 /*-----------------------------------------------------------------*/
1358 opIsGptr (operand * op)
1360 sym_link *type = operandType (op);
1362 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1369 /*-----------------------------------------------------------------*/
1370 /* getDataSize - get the operand data size */
1371 /*-----------------------------------------------------------------*/
1373 getDataSize (operand * op)
1376 size = AOP_SIZE (op);
1377 if (size == GPTRSIZE)
1379 sym_link *type = operandType (op);
1380 if (IS_GENPTR (type))
1382 /* generic pointer; arithmetic operations
1383 * should ignore the high byte (pointer type).
1391 /*-----------------------------------------------------------------*/
1392 /* outAcc - output Acc */
1393 /*-----------------------------------------------------------------*/
1395 outAcc (operand * result)
1398 size = getDataSize (result);
1401 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1404 /* unsigned or positive */
1407 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1412 /*-----------------------------------------------------------------*/
1413 /* outBitC - output a bit C */
1414 /*-----------------------------------------------------------------*/
1416 outBitC (operand * result)
1418 /* if the result is bit */
1419 if (AOP_TYPE (result) == AOP_CRY)
1420 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1423 emitcode ("clr", "a");
1424 emitcode ("rlc", "a");
1429 /*-----------------------------------------------------------------*/
1430 /* toBoolean - emit code for orl a,operator(sizeop) */
1431 /*-----------------------------------------------------------------*/
1433 toBoolean (operand * oper)
1435 int size = AOP_SIZE (oper) - 1;
1437 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1439 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1443 /*-----------------------------------------------------------------*/
1444 /* genNot - generate code for ! operation */
1445 /*-----------------------------------------------------------------*/
1451 D(emitcode ("; genNot",""));
1453 /* assign asmOps to operand & result */
1454 aopOp (IC_LEFT (ic), ic, FALSE);
1455 aopOp (IC_RESULT (ic), ic, TRUE);
1457 /* if in bit space then a special case */
1458 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1460 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1461 emitcode ("cpl", "c");
1462 outBitC (IC_RESULT (ic));
1466 toBoolean (IC_LEFT (ic));
1468 tlbl = newiTempLabel (NULL);
1469 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1470 emitcode ("", "%05d$:", tlbl->key + 100);
1471 outBitC (IC_RESULT (ic));
1474 /* release the aops */
1475 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1480 /*-----------------------------------------------------------------*/
1481 /* genCpl - generate code for complement */
1482 /*-----------------------------------------------------------------*/
1490 D(emitcode ("; genCpl",""));
1492 /* assign asmOps to operand & result */
1493 aopOp (IC_LEFT (ic), ic, FALSE);
1494 aopOp (IC_RESULT (ic), ic, TRUE);
1496 /* special case if in bit space */
1497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1499 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1501 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1502 emitcode ("cpl", "c");
1503 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1507 tlbl=newiTempLabel(NULL);
1508 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1509 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1510 IS_AOP_PREG (IC_LEFT (ic)))
1512 emitcode ("cjne", "%s,#0x01,%05d$",
1513 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1518 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1520 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1522 emitcode ("", "%05d$:", tlbl->key + 100);
1523 outBitC (IC_RESULT(ic));
1527 size = AOP_SIZE (IC_RESULT (ic));
1530 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1532 emitcode ("cpl", "a");
1533 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1538 /* release the aops */
1539 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1540 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1543 /*-----------------------------------------------------------------*/
1544 /* genUminusFloat - unary minus for floating points */
1545 /*-----------------------------------------------------------------*/
1547 genUminusFloat (operand * op, operand * result)
1549 int size, offset = 0;
1552 D(emitcode ("; genUminusFloat",""));
1554 /* for this we just copy and then flip the bit */
1556 size = AOP_SIZE (op) - 1;
1560 aopPut (AOP (result),
1561 aopGet (AOP (op), offset, FALSE, FALSE),
1563 isOperandVolatile (result, FALSE));
1567 l = aopGet (AOP (op), offset, FALSE, FALSE);
1571 emitcode ("cpl", "acc.7");
1572 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1575 /*-----------------------------------------------------------------*/
1576 /* genUminus - unary minus code generation */
1577 /*-----------------------------------------------------------------*/
1579 genUminus (iCode * ic)
1582 sym_link *optype, *rtype;
1585 D(emitcode ("; genUminus",""));
1588 aopOp (IC_LEFT (ic), ic, FALSE);
1589 aopOp (IC_RESULT (ic), ic, TRUE);
1591 /* if both in bit space then special
1593 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1594 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1597 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1598 emitcode ("cpl", "c");
1599 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1603 optype = operandType (IC_LEFT (ic));
1604 rtype = operandType (IC_RESULT (ic));
1606 /* if float then do float stuff */
1607 if (IS_FLOAT (optype))
1609 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1613 /* otherwise subtract from zero */
1614 size = AOP_SIZE (IC_LEFT (ic));
1619 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1620 if (!strcmp (l, "a"))
1624 emitcode ("cpl", "a");
1625 emitcode ("addc", "a,#0");
1631 emitcode ("clr", "a");
1632 emitcode ("subb", "a,%s", l);
1634 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1637 /* if any remaining bytes in the result */
1638 /* we just need to propagate the sign */
1639 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1641 emitcode ("rlc", "a");
1642 emitcode ("subb", "a,acc");
1644 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1648 /* release the aops */
1649 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1650 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1653 /*-----------------------------------------------------------------*/
1654 /* saveRegisters - will look for a call and save the registers */
1655 /*-----------------------------------------------------------------*/
1657 saveRegisters (iCode * lic)
1664 for (ic = lic; ic; ic = ic->next)
1665 if (ic->op == CALL || ic->op == PCALL)
1670 fprintf (stderr, "found parameter push with no function call\n");
1674 /* if the registers have been saved already or don't need to be then
1678 if (IS_SYMOP(IC_LEFT(ic)) &&
1679 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1680 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1683 /* safe the registers in use at this time but skip the
1684 ones for the result */
1685 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1686 mcs51_rUmaskForOp (IC_RESULT(ic)));
1689 if (options.useXstack)
1691 if (bitVectBitValue (rsave, R0_IDX))
1692 emitcode ("mov", "b,r0");
1693 emitcode ("mov", "r0,%s", spname);
1694 for (i = 0; i < mcs51_nRegs; i++)
1696 if (bitVectBitValue (rsave, i))
1699 emitcode ("mov", "a,b");
1701 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1702 emitcode ("movx", "@r0,a");
1703 emitcode ("inc", "r0");
1706 emitcode ("mov", "%s,r0", spname);
1707 if (bitVectBitValue (rsave, R0_IDX))
1708 emitcode ("mov", "r0,b");
1711 for (i = 0; i < mcs51_nRegs; i++)
1713 if (bitVectBitValue (rsave, i))
1714 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1718 /*-----------------------------------------------------------------*/
1719 /* unsaveRegisters - pop the pushed registers */
1720 /*-----------------------------------------------------------------*/
1722 unsaveRegisters (iCode * ic)
1727 /* restore the registers in use at this time but skip the
1728 ones for the result */
1729 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1730 mcs51_rUmaskForOp (IC_RESULT(ic)));
1732 if (options.useXstack)
1734 emitcode ("mov", "r0,%s", spname);
1735 for (i = mcs51_nRegs; i >= 0; i--)
1737 if (bitVectBitValue (rsave, i))
1739 emitcode ("dec", "r0");
1740 emitcode ("movx", "a,@r0");
1742 emitcode ("mov", "b,a");
1744 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1748 emitcode ("mov", "%s,r0", spname);
1749 if (bitVectBitValue (rsave, R0_IDX))
1750 emitcode ("mov", "r0,b");
1753 for (i = mcs51_nRegs; i >= 0; i--)
1755 if (bitVectBitValue (rsave, i))
1756 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1762 /*-----------------------------------------------------------------*/
1764 /*-----------------------------------------------------------------*/
1766 pushSide (operand * oper, int size)
1771 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1772 if (AOP_TYPE (oper) != AOP_REG &&
1773 AOP_TYPE (oper) != AOP_DIR &&
1776 emitcode ("mov", "a,%s", l);
1777 emitcode ("push", "acc");
1780 emitcode ("push", "%s", l);
1784 /*-----------------------------------------------------------------*/
1785 /* assignResultValue - */
1786 /*-----------------------------------------------------------------*/
1788 assignResultValue (operand * oper)
1791 int size = AOP_SIZE (oper);
1794 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1800 /*-----------------------------------------------------------------*/
1801 /* genXpush - pushes onto the external stack */
1802 /*-----------------------------------------------------------------*/
1804 genXpush (iCode * ic)
1806 asmop *aop = newAsmop (0);
1808 int size, offset = 0;
1810 D(emitcode ("; genXpush",""));
1812 aopOp (IC_LEFT (ic), ic, FALSE);
1813 r = getFreePtr (ic, &aop, FALSE);
1816 emitcode ("mov", "%s,_spx", r->name);
1818 size = AOP_SIZE (IC_LEFT (ic));
1822 char *l = aopGet (AOP (IC_LEFT (ic)),
1823 offset++, FALSE, FALSE);
1825 emitcode ("movx", "@%s,a", r->name);
1826 emitcode ("inc", "%s", r->name);
1831 emitcode ("mov", "_spx,%s", r->name);
1833 freeAsmop (NULL, aop, ic, TRUE);
1834 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1837 /*-----------------------------------------------------------------*/
1838 /* genIpush - genrate code for pushing this gets a little complex */
1839 /*-----------------------------------------------------------------*/
1841 genIpush (iCode * ic)
1843 int size, offset = 0;
1846 D(emitcode ("; genIpush",""));
1848 /* if this is not a parm push : ie. it is spill push
1849 and spill push is always done on the local stack */
1853 /* and the item is spilt then do nothing */
1854 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1857 aopOp (IC_LEFT (ic), ic, FALSE);
1858 size = AOP_SIZE (IC_LEFT (ic));
1859 /* push it on the stack */
1862 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1868 emitcode ("push", "%s", l);
1873 /* this is a paramter push: in this case we call
1874 the routine to find the call and save those
1875 registers that need to be saved */
1878 /* if use external stack then call the external
1879 stack pushing routine */
1880 if (options.useXstack)
1886 /* then do the push */
1887 aopOp (IC_LEFT (ic), ic, FALSE);
1890 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1891 size = AOP_SIZE (IC_LEFT (ic));
1895 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1896 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1897 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1900 emitcode ("mov", "a,%s", l);
1901 emitcode ("push", "acc");
1904 emitcode ("push", "%s", l);
1907 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1910 /*-----------------------------------------------------------------*/
1911 /* genIpop - recover the registers: can happen only for spilling */
1912 /*-----------------------------------------------------------------*/
1914 genIpop (iCode * ic)
1918 D(emitcode ("; genIpop",""));
1920 /* if the temp was not pushed then */
1921 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1924 aopOp (IC_LEFT (ic), ic, FALSE);
1925 size = AOP_SIZE (IC_LEFT (ic));
1926 offset = (size - 1);
1928 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1931 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1934 /*-----------------------------------------------------------------*/
1935 /* unsaveRBank - restores the resgister bank from stack */
1936 /*-----------------------------------------------------------------*/
1938 unsaveRBank (int bank, iCode * ic, bool popPsw)
1944 if (options.useXstack)
1948 /* Assume r0 is available for use. */
1949 r = mcs51_regWithIdx (R0_IDX);;
1954 r = getFreePtr (ic, &aop, FALSE);
1956 emitcode ("mov", "%s,_spx", r->name);
1961 if (options.useXstack)
1963 emitcode ("movx", "a,@%s", r->name);
1964 emitcode ("mov", "psw,a");
1965 emitcode ("dec", "%s", r->name);
1969 emitcode ("pop", "psw");
1973 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1975 if (options.useXstack)
1977 emitcode ("movx", "a,@%s", r->name);
1978 emitcode ("mov", "(%s+%d),a",
1979 regs8051[i].base, 8 * bank + regs8051[i].offset);
1980 emitcode ("dec", "%s", r->name);
1984 emitcode ("pop", "(%s+%d)",
1985 regs8051[i].base, 8 * bank + regs8051[i].offset);
1988 if (options.useXstack)
1990 emitcode ("mov", "_spx,%s", r->name);
1995 freeAsmop (NULL, aop, ic, TRUE);
1999 /*-----------------------------------------------------------------*/
2000 /* saveRBank - saves an entire register bank on the stack */
2001 /*-----------------------------------------------------------------*/
2003 saveRBank (int bank, iCode * ic, bool pushPsw)
2009 if (options.useXstack)
2013 /* Assume r0 is available for use. */
2014 r = mcs51_regWithIdx (R0_IDX);;
2019 r = getFreePtr (ic, &aop, FALSE);
2021 emitcode ("mov", "%s,_spx", r->name);
2024 for (i = 0; i < mcs51_nRegs; i++)
2026 if (options.useXstack)
2028 emitcode ("inc", "%s", r->name);
2029 emitcode ("mov", "a,(%s+%d)",
2030 regs8051[i].base, 8 * bank + regs8051[i].offset);
2031 emitcode ("movx", "@%s,a", r->name);
2034 emitcode ("push", "(%s+%d)",
2035 regs8051[i].base, 8 * bank + regs8051[i].offset);
2040 if (options.useXstack)
2042 emitcode ("mov", "a,psw");
2043 emitcode ("movx", "@%s,a", r->name);
2044 emitcode ("inc", "%s", r->name);
2045 emitcode ("mov", "_spx,%s", r->name);
2050 emitcode ("push", "psw");
2053 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2058 freeAsmop (NULL, aop, ic, TRUE);
2067 /*-----------------------------------------------------------------*/
2068 /* genSend - gen code for SEND */
2069 /*-----------------------------------------------------------------*/
2070 static void genSend(set *sendSet)
2075 for (sic = setFirstItem (_G.sendSet); sic;
2076 sic = setNextItem (_G.sendSet)) {
2077 int size, offset = 0;
2078 aopOp (IC_LEFT (sic), sic, FALSE);
2079 size = AOP_SIZE (IC_LEFT (sic));
2081 if (sic->argreg == 1) {
2083 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2085 if (strcmp (l, fReturn[offset]))
2086 emitcode ("mov", "%s,%s", fReturn[offset], l);
2092 emitcode ("mov","b1_%d,%s",rb1_count++,
2093 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2096 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2100 /*-----------------------------------------------------------------*/
2101 /* genCall - generates a call statement */
2102 /*-----------------------------------------------------------------*/
2104 genCall (iCode * ic)
2107 // bool restoreBank = FALSE;
2108 bool swapBanks = FALSE;
2110 D(emitcode("; genCall",""));
2112 dtype = operandType (IC_LEFT (ic));
2113 /* if send set is not empty the assign */
2116 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2117 genSend(reverseSet(_G.sendSet));
2119 genSend(_G.sendSet);
2125 /* if we are calling a not _naked function that is not using
2126 the same register bank then we need to save the
2127 destination registers on the stack */
2128 dtype = operandType (IC_LEFT (ic));
2129 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2130 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2131 !IFFUNC_ISISR (dtype))
2136 /* if caller saves & we have not saved then */
2142 emitcode ("mov", "psw,#0x%02x",
2143 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2147 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2148 OP_SYMBOL (IC_LEFT (ic))->rname :
2149 OP_SYMBOL (IC_LEFT (ic))->name));
2153 emitcode ("mov", "psw,#0x%02x",
2154 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2157 /* if we need assign a result value */
2158 if ((IS_ITEMP (IC_RESULT (ic)) &&
2159 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2160 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2161 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2162 IS_TRUE_SYMOP (IC_RESULT (ic)))
2166 aopOp (IC_RESULT (ic), ic, FALSE);
2169 assignResultValue (IC_RESULT (ic));
2171 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2174 /* adjust the stack for parameters if
2179 if (ic->parmBytes > 3)
2181 emitcode ("mov", "a,%s", spname);
2182 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2183 emitcode ("mov", "%s,a", spname);
2186 for (i = 0; i < ic->parmBytes; i++)
2187 emitcode ("dec", "%s", spname);
2190 /* if we hade saved some registers then unsave them */
2191 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2192 unsaveRegisters (ic);
2194 // /* if register bank was saved then pop them */
2196 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2199 /*-----------------------------------------------------------------*/
2200 /* -10l - generates a call by pointer statement */
2201 /*-----------------------------------------------------------------*/
2203 genPcall (iCode * ic)
2206 symbol *rlbl = newiTempLabel (NULL);
2207 // bool restoreBank=FALSE;
2208 bool swapBanks = FALSE;
2210 D(emitcode("; genPCall",""));
2212 /* if caller saves & we have not saved then */
2216 /* if we are calling a not _naked function that is not using
2217 the same register bank then we need to save the
2218 destination registers on the stack */
2219 dtype = operandType (IC_LEFT (ic))->next;
2220 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2221 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2222 !IFFUNC_ISISR (dtype))
2224 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2225 // restoreBank=TRUE;
2227 // need caution message to user here
2230 /* push the return address on to the stack */
2231 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2232 emitcode ("push", "acc");
2233 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2234 emitcode ("push", "acc");
2236 /* now push the calling address */
2237 aopOp (IC_LEFT (ic), ic, FALSE);
2239 pushSide (IC_LEFT (ic), FPTRSIZE);
2241 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2243 /* if send set is not empty the assign */
2246 genSend(reverseSet(_G.sendSet));
2252 emitcode ("mov", "psw,#0x%02x",
2253 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2257 emitcode ("ret", "");
2258 emitcode ("", "%05d$:", (rlbl->key + 100));
2263 emitcode ("mov", "psw,#0x%02x",
2264 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2267 /* if we need assign a result value */
2268 if ((IS_ITEMP (IC_RESULT (ic)) &&
2269 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2270 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2271 IS_TRUE_SYMOP (IC_RESULT (ic)))
2275 aopOp (IC_RESULT (ic), ic, FALSE);
2278 assignResultValue (IC_RESULT (ic));
2280 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2283 /* adjust the stack for parameters if
2288 if (ic->parmBytes > 3)
2290 emitcode ("mov", "a,%s", spname);
2291 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2292 emitcode ("mov", "%s,a", spname);
2295 for (i = 0; i < ic->parmBytes; i++)
2296 emitcode ("dec", "%s", spname);
2300 // /* if register bank was saved then unsave them */
2302 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2304 /* if we hade saved some registers then
2306 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2307 unsaveRegisters (ic);
2310 /*-----------------------------------------------------------------*/
2311 /* resultRemat - result is rematerializable */
2312 /*-----------------------------------------------------------------*/
2314 resultRemat (iCode * ic)
2316 if (SKIP_IC (ic) || ic->op == IFX)
2319 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2321 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2322 if (sym->remat && !POINTER_SET (ic))
2329 #if defined(__BORLANDC__) || defined(_MSC_VER)
2330 #define STRCASECMP stricmp
2332 #define STRCASECMP strcasecmp
2335 /*-----------------------------------------------------------------*/
2336 /* inExcludeList - return 1 if the string is in exclude Reg list */
2337 /*-----------------------------------------------------------------*/
2339 regsCmp(void *p1, void *p2)
2341 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2345 inExcludeList (char *s)
2347 const char *p = setFirstItem(options.excludeRegsSet);
2349 if (p == NULL || STRCASECMP(p, "none") == 0)
2353 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2356 /*-----------------------------------------------------------------*/
2357 /* genFunction - generated code for function entry */
2358 /*-----------------------------------------------------------------*/
2360 genFunction (iCode * ic)
2364 bool switchedPSW = FALSE;
2365 int calleesaves_saved_register = -1;
2368 /* create the function header */
2369 emitcode (";", "-----------------------------------------");
2370 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2371 emitcode (";", "-----------------------------------------");
2373 emitcode ("", "%s:", sym->rname);
2374 ftype = operandType (IC_LEFT (ic));
2375 _G.currentFunc = sym;
2377 if (IFFUNC_ISNAKED(ftype))
2379 emitcode(";", "naked function: no prologue.");
2383 /* here we need to generate the equates for the
2384 register bank if required */
2385 if (FUNC_REGBANK (ftype) != rbank)
2389 rbank = FUNC_REGBANK (ftype);
2390 for (i = 0; i < mcs51_nRegs; i++)
2392 if (strcmp (regs8051[i].base, "0") == 0)
2393 emitcode ("", "%s = 0x%02x",
2395 8 * rbank + regs8051[i].offset);
2397 emitcode ("", "%s = %s + 0x%02x",
2400 8 * rbank + regs8051[i].offset);
2404 /* if this is an interrupt service routine then
2405 save acc, b, dpl, dph */
2406 if (IFFUNC_ISISR (sym->type))
2409 if (!inExcludeList ("acc"))
2410 emitcode ("push", "acc");
2411 if (!inExcludeList ("b"))
2412 emitcode ("push", "b");
2413 if (!inExcludeList ("dpl"))
2414 emitcode ("push", "dpl");
2415 if (!inExcludeList ("dph"))
2416 emitcode ("push", "dph");
2417 /* if this isr has no bank i.e. is going to
2418 run with bank 0 , then we need to save more
2420 if (!FUNC_REGBANK (sym->type))
2423 /* if this function does not call any other
2424 function then we can be economical and
2425 save only those registers that are used */
2426 if (!IFFUNC_HASFCALL(sym->type))
2430 /* if any registers used */
2433 /* save the registers used */
2434 for (i = 0; i < sym->regsUsed->size; i++)
2436 if (bitVectBitValue (sym->regsUsed, i) ||
2437 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2438 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2446 /* this function has a function call cannot
2447 determines register usage so we will have to push the
2449 saveRBank (0, ic, FALSE);
2450 if (options.parms_in_bank1) {
2452 for (i=0; i < 8 ; i++ ) {
2453 emitcode ("push","%s",rb1regs[i]);
2460 /* This ISR uses a non-zero bank.
2462 * We assume that the bank is available for our
2465 * However, if this ISR calls a function which uses some
2466 * other bank, we must save that bank entirely.
2468 unsigned long banksToSave = 0;
2470 if (IFFUNC_HASFCALL(sym->type))
2473 #define MAX_REGISTER_BANKS 4
2478 for (i = ic; i; i = i->next)
2480 if (i->op == ENDFUNCTION)
2482 /* we got to the end OK. */
2490 dtype = operandType (IC_LEFT(i));
2492 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2494 /* Mark this bank for saving. */
2495 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2497 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2501 banksToSave |= (1 << FUNC_REGBANK(dtype));
2504 /* And note that we don't need to do it in
2512 /* This is a mess; we have no idea what
2513 * register bank the called function might
2516 * The only thing I can think of to do is
2517 * throw a warning and hope.
2519 werror(W_FUNCPTR_IN_USING_ISR);
2523 if (banksToSave && options.useXstack)
2525 /* Since we aren't passing it an ic,
2526 * saveRBank will assume r0 is available to abuse.
2528 * So switch to our (trashable) bank now, so
2529 * the caller's R0 isn't trashed.
2531 emitcode ("push", "psw");
2532 emitcode ("mov", "psw,#0x%02x",
2533 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2537 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2539 if (banksToSave & (1 << ix))
2541 saveRBank(ix, NULL, FALSE);
2545 // TODO: this needs a closer look
2546 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2551 /* if callee-save to be used for this function
2552 then save the registers being used in this function */
2553 if (IFFUNC_CALLEESAVES(sym->type))
2557 /* if any registers used */
2560 /* save the registers used */
2561 for (i = 0; i < sym->regsUsed->size; i++)
2563 if (bitVectBitValue (sym->regsUsed, i) ||
2564 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2566 /* remember one saved register for later usage */
2567 if (calleesaves_saved_register < 0)
2568 calleesaves_saved_register = i;
2569 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2577 /* set the register bank to the desired value */
2578 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2581 emitcode ("push", "psw");
2582 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2585 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2588 if (options.useXstack)
2590 emitcode ("mov", "r0,%s", spname);
2591 emitcode ("mov", "a,_bp");
2592 emitcode ("movx", "@r0,a");
2593 emitcode ("inc", "%s", spname);
2597 /* set up the stack */
2598 emitcode ("push", "_bp"); /* save the callers stack */
2600 emitcode ("mov", "_bp,%s", spname);
2603 /* adjust the stack for the function */
2609 werror (W_STACK_OVERFLOW, sym->name);
2611 if (i > 3 && sym->recvSize < 4)
2614 emitcode ("mov", "a,sp");
2615 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2616 emitcode ("mov", "sp,a");
2621 if (IFFUNC_CALLEESAVES(sym->type))
2623 /* if it's a callee-saves function we need a saved register */
2624 if (calleesaves_saved_register >= 0)
2626 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2627 emitcode ("mov", "a,sp");
2628 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2629 emitcode ("mov", "sp,a");
2630 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2633 /* do it the hard way */
2635 emitcode ("inc", "sp");
2639 /* not callee-saves, we can clobber r0 */
2640 emitcode ("mov", "r0,a");
2641 emitcode ("mov", "a,sp");
2642 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2643 emitcode ("mov", "sp,a");
2644 emitcode ("mov", "a,r0");
2649 emitcode ("inc", "sp");
2655 emitcode ("mov", "a,_spx");
2656 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2657 emitcode ("mov", "_spx,a");
2660 /* if critical function then turn interrupts off */
2661 if (IFFUNC_ISCRITICAL (ftype))
2663 symbol *tlbl = newiTempLabel (NULL);
2664 emitcode ("setb", "c");
2665 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2666 emitcode ("clr", "c");
2667 emitcode ("", "%05d$:", (tlbl->key + 100));
2668 emitcode ("push", "psw"); /* save old ea via c in psw */
2672 /*-----------------------------------------------------------------*/
2673 /* genEndFunction - generates epilogue for functions */
2674 /*-----------------------------------------------------------------*/
2676 genEndFunction (iCode * ic)
2678 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2680 _G.currentFunc = NULL;
2681 if (IFFUNC_ISNAKED(sym->type))
2683 emitcode(";", "naked function: no epilogue.");
2687 if (IFFUNC_ISCRITICAL (sym->type))
2689 emitcode ("pop", "psw"); /* restore ea via c in psw */
2690 emitcode ("mov", "ea,c");
2693 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2695 emitcode ("mov", "%s,_bp", spname);
2698 /* if use external stack but some variables were
2699 added to the local stack then decrement the
2701 if (options.useXstack && sym->stack)
2703 emitcode ("mov", "a,sp");
2704 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2705 emitcode ("mov", "sp,a");
2709 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2711 if (options.useXstack)
2713 emitcode ("mov", "r0,%s", spname);
2714 emitcode ("movx", "a,@r0");
2715 emitcode ("mov", "_bp,a");
2716 emitcode ("dec", "%s", spname);
2720 emitcode ("pop", "_bp");
2724 /* restore the register bank */
2725 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2727 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2728 || !options.useXstack)
2730 /* Special case of ISR using non-zero bank with useXstack
2733 emitcode ("pop", "psw");
2737 if (IFFUNC_ISISR (sym->type))
2740 /* now we need to restore the registers */
2741 /* if this isr has no bank i.e. is going to
2742 run with bank 0 , then we need to save more
2744 if (!FUNC_REGBANK (sym->type))
2746 /* if this function does not call any other
2747 function then we can be economical and
2748 save only those registers that are used */
2749 if (!IFFUNC_HASFCALL(sym->type))
2753 /* if any registers used */
2756 /* save the registers used */
2757 for (i = sym->regsUsed->size; i >= 0; i--)
2759 if (bitVectBitValue (sym->regsUsed, i) ||
2760 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2761 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2768 if (options.parms_in_bank1) {
2770 for (i = 7 ; i >= 0 ; i-- ) {
2771 emitcode ("pop","%s",rb1regs[i]);
2774 /* this function has a function call cannot
2775 determines register usage so we will have to pop the
2777 unsaveRBank (0, ic, FALSE);
2782 /* This ISR uses a non-zero bank.
2784 * Restore any register banks saved by genFunction
2787 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2790 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2792 if (savedBanks & (1 << ix))
2794 unsaveRBank(ix, NULL, FALSE);
2798 if (options.useXstack)
2800 /* Restore bank AFTER calling unsaveRBank,
2801 * since it can trash r0.
2803 emitcode ("pop", "psw");
2807 if (!inExcludeList ("dph"))
2808 emitcode ("pop", "dph");
2809 if (!inExcludeList ("dpl"))
2810 emitcode ("pop", "dpl");
2811 if (!inExcludeList ("b"))
2812 emitcode ("pop", "b");
2813 if (!inExcludeList ("acc"))
2814 emitcode ("pop", "acc");
2816 /* if debug then send end of function */
2817 if (options.debug && currFunc)
2820 emitcode ("", "C$%s$%d$%d$%d ==.",
2821 FileBaseName (ic->filename), currFunc->lastLine,
2822 ic->level, ic->block);
2823 if (IS_STATIC (currFunc->etype))
2824 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2826 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2830 emitcode ("reti", "");
2834 if (IFFUNC_CALLEESAVES(sym->type))
2838 /* if any registers used */
2841 /* save the registers used */
2842 for (i = sym->regsUsed->size; i >= 0; i--)
2844 if (bitVectBitValue (sym->regsUsed, i) ||
2845 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2846 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2852 /* if debug then send end of function */
2853 if (options.debug && currFunc)
2856 emitcode ("", "C$%s$%d$%d$%d ==.",
2857 FileBaseName (ic->filename), currFunc->lastLine,
2858 ic->level, ic->block);
2859 if (IS_STATIC (currFunc->etype))
2860 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2862 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2866 emitcode ("ret", "");
2871 /*-----------------------------------------------------------------*/
2872 /* genRet - generate code for return statement */
2873 /*-----------------------------------------------------------------*/
2877 int size, offset = 0, pushed = 0;
2879 D(emitcode ("; genRet",""));
2881 /* if we have no return value then
2882 just generate the "ret" */
2886 /* we have something to return then
2887 move the return value into place */
2888 aopOp (IC_LEFT (ic), ic, FALSE);
2889 size = AOP_SIZE (IC_LEFT (ic));
2894 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2897 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2899 emitcode ("push", "%s", l);
2904 l = aopGet (AOP (IC_LEFT (ic)), offset,
2906 if (strcmp (fReturn[offset], l))
2907 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2916 if (strcmp (fReturn[pushed], "a"))
2917 emitcode ("pop", fReturn[pushed]);
2919 emitcode ("pop", "acc");
2922 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2925 /* generate a jump to the return label
2926 if the next is not the return statement */
2927 if (!(ic->next && ic->next->op == LABEL &&
2928 IC_LABEL (ic->next) == returnLabel))
2930 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2934 /*-----------------------------------------------------------------*/
2935 /* genLabel - generates a label */
2936 /*-----------------------------------------------------------------*/
2938 genLabel (iCode * ic)
2940 /* special case never generate */
2941 if (IC_LABEL (ic) == entryLabel)
2944 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2947 /*-----------------------------------------------------------------*/
2948 /* genGoto - generates a ljmp */
2949 /*-----------------------------------------------------------------*/
2951 genGoto (iCode * ic)
2953 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2956 /*-----------------------------------------------------------------*/
2957 /* findLabelBackwards: walks back through the iCode chain looking */
2958 /* for the given label. Returns number of iCode instructions */
2959 /* between that label and given ic. */
2960 /* Returns zero if label not found. */
2961 /*-----------------------------------------------------------------*/
2963 findLabelBackwards (iCode * ic, int key)
2972 /* If we have any pushes or pops, we cannot predict the distance.
2973 I don't like this at all, this should be dealt with in the
2975 if (ic->op == IPUSH || ic->op == IPOP) {
2979 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2988 /*-----------------------------------------------------------------*/
2989 /* genPlusIncr :- does addition with increment if possible */
2990 /*-----------------------------------------------------------------*/
2992 genPlusIncr (iCode * ic)
2994 unsigned int icount;
2995 unsigned int size = getDataSize (IC_RESULT (ic));
2997 /* will try to generate an increment */
2998 /* if the right side is not a literal
3000 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3003 /* if the literal value of the right hand side
3004 is greater than 4 then it is not worth it */
3005 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3008 D(emitcode ("; genPlusIncr",""));
3010 /* if increment >=16 bits in register or direct space */
3011 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3012 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3020 /* If the next instruction is a goto and the goto target
3021 * is < 10 instructions previous to this, we can generate
3022 * jumps straight to that target.
3024 if (ic->next && ic->next->op == GOTO
3025 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3026 && labelRange <= 10)
3028 emitcode (";", "tail increment optimized");
3029 tlbl = IC_LABEL (ic->next);
3034 tlbl = newiTempLabel (NULL);
3037 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3038 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3039 IS_AOP_PREG (IC_RESULT (ic)))
3040 emitcode ("cjne", "%s,#0x00,%05d$",
3041 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3045 emitcode ("clr", "a");
3046 emitcode ("cjne", "a,%s,%05d$",
3047 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3051 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3054 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3055 IS_AOP_PREG (IC_RESULT (ic)))
3056 emitcode ("cjne", "%s,#0x00,%05d$",
3057 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3060 emitcode ("cjne", "a,%s,%05d$",
3061 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3064 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3068 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3069 IS_AOP_PREG (IC_RESULT (ic)))
3070 emitcode ("cjne", "%s,#0x00,%05d$",
3071 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3075 emitcode ("cjne", "a,%s,%05d$",
3076 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3079 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3084 emitcode ("", "%05d$:", tlbl->key + 100);
3089 /* if the sizes are greater than 1 then we cannot */
3090 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3091 AOP_SIZE (IC_LEFT (ic)) > 1)
3094 /* we can if the aops of the left & result match or
3095 if they are in registers and the registers are the
3097 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3102 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3103 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3104 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3110 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3119 /*-----------------------------------------------------------------*/
3120 /* outBitAcc - output a bit in acc */
3121 /*-----------------------------------------------------------------*/
3123 outBitAcc (operand * result)
3125 symbol *tlbl = newiTempLabel (NULL);
3126 /* if the result is a bit */
3127 if (AOP_TYPE (result) == AOP_CRY)
3129 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3133 emitcode ("jz", "%05d$", tlbl->key + 100);
3134 emitcode ("mov", "a,%s", one);
3135 emitcode ("", "%05d$:", tlbl->key + 100);
3140 /*-----------------------------------------------------------------*/
3141 /* genPlusBits - generates code for addition of two bits */
3142 /*-----------------------------------------------------------------*/
3144 genPlusBits (iCode * ic)
3146 D(emitcode ("; genPlusBits",""));
3148 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3150 symbol *lbl = newiTempLabel (NULL);
3151 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3152 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3153 emitcode ("cpl", "c");
3154 emitcode ("", "%05d$:", (lbl->key + 100));
3155 outBitC (IC_RESULT (ic));
3159 emitcode ("clr", "a");
3160 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3161 emitcode ("rlc", "a");
3162 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3163 emitcode ("addc", "a,#0x00");
3164 outAcc (IC_RESULT (ic));
3169 /* This is the original version of this code.
3171 * This is being kept around for reference,
3172 * because I am not entirely sure I got it right...
3175 adjustArithmeticResult (iCode * ic)
3177 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3178 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3179 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3180 aopPut (AOP (IC_RESULT (ic)),
3181 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3183 isOperandVolatile (IC_RESULT (ic), FALSE));
3185 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3186 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3187 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3188 aopPut (AOP (IC_RESULT (ic)),
3189 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3191 isOperandVolatile (IC_RESULT (ic), FALSE));
3193 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3194 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3195 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3196 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3197 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3200 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3201 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3205 /* This is the pure and virtuous version of this code.
3206 * I'm pretty certain it's right, but not enough to toss the old
3210 adjustArithmeticResult (iCode * ic)
3212 if (opIsGptr (IC_RESULT (ic)) &&
3213 opIsGptr (IC_LEFT (ic)) &&
3214 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3216 aopPut (AOP (IC_RESULT (ic)),
3217 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3219 isOperandVolatile (IC_RESULT (ic), FALSE));
3222 if (opIsGptr (IC_RESULT (ic)) &&
3223 opIsGptr (IC_RIGHT (ic)) &&
3224 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3226 aopPut (AOP (IC_RESULT (ic)),
3227 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3229 isOperandVolatile (IC_RESULT (ic), FALSE));
3232 if (opIsGptr (IC_RESULT (ic)) &&
3233 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3234 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3235 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3236 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3239 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3240 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3245 /*-----------------------------------------------------------------*/
3246 /* genPlus - generates code for addition */
3247 /*-----------------------------------------------------------------*/
3249 genPlus (iCode * ic)
3251 int size, offset = 0;
3254 asmop *leftOp, *rightOp;
3257 /* special cases :- */
3259 D(emitcode ("; genPlus",""));
3261 aopOp (IC_LEFT (ic), ic, FALSE);
3262 aopOp (IC_RIGHT (ic), ic, FALSE);
3263 aopOp (IC_RESULT (ic), ic, TRUE);
3265 /* if literal, literal on the right or
3266 if left requires ACC or right is already
3268 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3269 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3270 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3272 operand *t = IC_RIGHT (ic);
3273 IC_RIGHT (ic) = IC_LEFT (ic);
3277 /* if both left & right are in bit
3279 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3280 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3286 /* if left in bit space & right literal */
3287 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3288 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3290 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3291 /* if result in bit space */
3292 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3294 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3295 emitcode ("cpl", "c");
3296 outBitC (IC_RESULT (ic));
3300 size = getDataSize (IC_RESULT (ic));
3303 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3304 emitcode ("addc", "a,#00");
3305 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3311 /* if I can do an increment instead
3312 of add then GOOD for ME */
3313 if (genPlusIncr (ic) == TRUE)
3316 size = getDataSize (IC_RESULT (ic));
3317 leftOp = AOP(IC_LEFT(ic));
3318 rightOp = AOP(IC_RIGHT(ic));
3321 /* if this is an add for an array access
3322 at a 256 byte boundary */
3324 && AOP_TYPE (op) == AOP_IMMD
3326 && IS_SPEC (OP_SYM_ETYPE (op))
3327 && SPEC_ABSA (OP_SYM_ETYPE (op))
3328 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3331 D(emitcode ("; genPlus aligned array",""));
3332 aopPut (AOP (IC_RESULT (ic)),
3333 aopGet (rightOp, 0, FALSE, FALSE),
3335 isOperandVolatile (IC_RESULT (ic), FALSE));
3337 if( 1 == getDataSize (IC_RIGHT (ic)) )
3339 aopPut (AOP (IC_RESULT (ic)),
3340 aopGet (leftOp, 1, FALSE, FALSE),
3342 isOperandVolatile (IC_RESULT (ic), FALSE));
3346 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3347 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3348 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3353 /* if the lower bytes of a literal are zero skip the addition */
3354 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3356 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3357 (skip_bytes+1 < size))
3362 D(emitcode ("; genPlus shortcut",""));
3367 if( offset >= skip_bytes )
3369 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3371 emitcode("mov", "b,a");
3372 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3373 emitcode("xch", "a,b");
3374 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3375 emitcode (add, "a,b");
3377 else if (aopGetUsesAcc (leftOp, offset))
3379 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3380 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3384 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3385 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3387 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3388 add = "addc"; /* further adds must propagate carry */
3392 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3393 isOperandVolatile (IC_RESULT (ic), FALSE))
3396 aopPut (AOP (IC_RESULT (ic)),
3397 aopGet (leftOp, offset, FALSE, FALSE),
3399 isOperandVolatile (IC_RESULT (ic), FALSE));
3405 adjustArithmeticResult (ic);
3408 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3409 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3410 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3413 /*-----------------------------------------------------------------*/
3414 /* genMinusDec :- does subtraction with deccrement if possible */
3415 /*-----------------------------------------------------------------*/
3417 genMinusDec (iCode * ic)
3419 unsigned int icount;
3420 unsigned int size = getDataSize (IC_RESULT (ic));
3422 /* will try to generate an increment */
3423 /* if the right side is not a literal
3425 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3428 /* if the literal value of the right hand side
3429 is greater than 4 then it is not worth it */
3430 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3433 D(emitcode ("; genMinusDec",""));
3435 /* if decrement >=16 bits in register or direct space */
3436 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3437 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3445 /* If the next instruction is a goto and the goto target
3446 * is <= 10 instructions previous to this, we can generate
3447 * jumps straight to that target.
3449 if (ic->next && ic->next->op == GOTO
3450 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3451 && labelRange <= 10)
3453 emitcode (";", "tail decrement optimized");
3454 tlbl = IC_LABEL (ic->next);
3459 tlbl = newiTempLabel (NULL);
3463 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3464 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3465 IS_AOP_PREG (IC_RESULT (ic)))
3466 emitcode ("cjne", "%s,#0xff,%05d$"
3467 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3471 emitcode ("mov", "a,#0xff");
3472 emitcode ("cjne", "a,%s,%05d$"
3473 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3476 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3479 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3480 IS_AOP_PREG (IC_RESULT (ic)))
3481 emitcode ("cjne", "%s,#0xff,%05d$"
3482 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3486 emitcode ("cjne", "a,%s,%05d$"
3487 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3490 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3495 IS_AOP_PREG (IC_RESULT (ic)))
3496 emitcode ("cjne", "%s,#0xff,%05d$"
3497 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3501 emitcode ("cjne", "a,%s,%05d$"
3502 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3505 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3509 emitcode ("", "%05d$:", tlbl->key + 100);
3514 /* if the sizes are greater than 1 then we cannot */
3515 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3516 AOP_SIZE (IC_LEFT (ic)) > 1)
3519 /* we can if the aops of the left & result match or
3520 if they are in registers and the registers are the
3522 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3526 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3534 /*-----------------------------------------------------------------*/
3535 /* addSign - complete with sign */
3536 /*-----------------------------------------------------------------*/
3538 addSign (operand * result, int offset, int sign)
3540 int size = (getDataSize (result) - offset);
3545 emitcode ("rlc", "a");
3546 emitcode ("subb", "a,acc");
3548 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3552 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3556 /*-----------------------------------------------------------------*/
3557 /* genMinusBits - generates code for subtraction of two bits */
3558 /*-----------------------------------------------------------------*/
3560 genMinusBits (iCode * ic)
3562 symbol *lbl = newiTempLabel (NULL);
3564 D(emitcode ("; genMinusBits",""));
3566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3568 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3569 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3570 emitcode ("cpl", "c");
3571 emitcode ("", "%05d$:", (lbl->key + 100));
3572 outBitC (IC_RESULT (ic));
3576 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3577 emitcode ("subb", "a,acc");
3578 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3579 emitcode ("inc", "a");
3580 emitcode ("", "%05d$:", (lbl->key + 100));
3581 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3582 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3586 /*-----------------------------------------------------------------*/
3587 /* genMinus - generates code for subtraction */
3588 /*-----------------------------------------------------------------*/
3590 genMinus (iCode * ic)
3592 int size, offset = 0;
3594 D(emitcode ("; genMinus",""));
3596 aopOp (IC_LEFT (ic), ic, FALSE);
3597 aopOp (IC_RIGHT (ic), ic, FALSE);
3598 aopOp (IC_RESULT (ic), ic, TRUE);
3600 /* special cases :- */
3601 /* if both left & right are in bit space */
3602 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3603 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3609 /* if I can do an decrement instead
3610 of subtract then GOOD for ME */
3611 if (genMinusDec (ic) == TRUE)
3614 size = getDataSize (IC_RESULT (ic));
3616 /* if literal, add a,#-lit, else normal subb */
3617 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3619 unsigned long lit = 0L;
3621 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3626 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3627 /* first add without previous c */
3629 if (!size && lit== (unsigned long) -1) {
3630 emitcode ("dec", "a");
3632 emitcode ("add", "a,#0x%02x",
3633 (unsigned int) (lit & 0x0FFL));
3636 emitcode ("addc", "a,#0x%02x",
3637 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3639 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3644 asmop *leftOp, *rightOp;
3646 leftOp = AOP(IC_LEFT(ic));
3647 rightOp = AOP(IC_RIGHT(ic));
3651 if (aopGetUsesAcc(rightOp, offset)) {
3652 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3653 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3655 emitcode( "setb", "c");
3657 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3658 emitcode("cpl", "a");
3660 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3663 emitcode ("subb", "a,%s",
3664 aopGet(rightOp, offset, FALSE, TRUE));
3667 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3672 adjustArithmeticResult (ic);
3675 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3677 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3681 /*-----------------------------------------------------------------*/
3682 /* genMultbits :- multiplication of bits */
3683 /*-----------------------------------------------------------------*/
3685 genMultbits (operand * left,
3689 D(emitcode ("; genMultbits",""));
3691 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3692 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3697 /*-----------------------------------------------------------------*/
3698 /* genMultOneByte : 8*8=8/16 bit multiplication */
3699 /*-----------------------------------------------------------------*/
3701 genMultOneByte (operand * left,
3705 sym_link *opetype = operandType (result);
3707 int size=AOP_SIZE(result);
3709 D(emitcode ("; genMultOneByte",""));
3711 if (size<1 || size>2) {
3712 // this should never happen
3713 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3714 AOP_SIZE(result), __FILE__, lineno);
3718 /* (if two literals: the value is computed before) */
3719 /* if one literal, literal on the right */
3720 if (AOP_TYPE (left) == AOP_LIT)
3725 //emitcode (";", "swapped left and right");
3728 if (SPEC_USIGN(opetype)
3729 // ignore the sign of left and right, what else can we do?
3730 || (SPEC_USIGN(operandType(left)) &&
3731 SPEC_USIGN(operandType(right)))) {
3732 // just an unsigned 8*8=8/16 multiply
3733 //emitcode (";","unsigned");
3734 // TODO: check for accumulator clash between left & right aops?
3736 if( AOP_TYPE(right)==AOP_LIT ){
3737 // moving to accumulator first helps peepholes
3738 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3739 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3741 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3742 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3745 emitcode ("mul", "ab");
3746 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3748 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3753 // we have to do a signed multiply
3755 //emitcode (";", "signed");
3756 emitcode ("clr", "F0"); // reset sign flag
3757 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3759 lbl=newiTempLabel(NULL);
3760 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3761 // left side is negative, 8-bit two's complement, this fails for -128
3762 emitcode ("setb", "F0"); // set sign flag
3763 emitcode ("cpl", "a");
3764 emitcode ("inc", "a");
3766 emitcode ("", "%05d$:", lbl->key+100);
3769 if (AOP_TYPE(right)==AOP_LIT) {
3770 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3771 /* AND literal negative */
3773 emitcode ("cpl", "F0"); // complement sign flag
3774 emitcode ("mov", "b,#0x%02x", -val);
3776 emitcode ("mov", "b,#0x%02x", val);
3779 lbl=newiTempLabel(NULL);
3780 emitcode ("mov", "b,a");
3781 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3782 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3783 // right side is negative, 8-bit two's complement
3784 emitcode ("cpl", "F0"); // complement sign flag
3785 emitcode ("cpl", "a");
3786 emitcode ("inc", "a");
3787 emitcode ("", "%05d$:", lbl->key+100);
3789 emitcode ("mul", "ab");
3791 lbl=newiTempLabel(NULL);
3792 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3793 // only ONE op was negative, we have to do a 8/16-bit two's complement
3794 emitcode ("cpl", "a"); // lsb
3796 emitcode ("inc", "a");
3798 emitcode ("add", "a,#1");
3799 emitcode ("xch", "a,b");
3800 emitcode ("cpl", "a"); // msb
3801 emitcode ("addc", "a,#0");
3802 emitcode ("xch", "a,b");
3805 emitcode ("", "%05d$:", lbl->key+100);
3806 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3808 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3812 /*-----------------------------------------------------------------*/
3813 /* genMult - generates code for multiplication */
3814 /*-----------------------------------------------------------------*/
3816 genMult (iCode * ic)
3818 operand *left = IC_LEFT (ic);
3819 operand *right = IC_RIGHT (ic);
3820 operand *result = IC_RESULT (ic);
3822 D(emitcode ("; genMult",""));
3824 /* assign the amsops */
3825 aopOp (left, ic, FALSE);
3826 aopOp (right, ic, FALSE);
3827 aopOp (result, ic, TRUE);
3829 /* special cases first */
3831 if (AOP_TYPE (left) == AOP_CRY &&
3832 AOP_TYPE (right) == AOP_CRY)
3834 genMultbits (left, right, result);
3838 /* if both are of size == 1 */
3839 #if 0 // one of them can be a sloc shared with the result
3840 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3842 if (getSize(operandType(left)) == 1 &&
3843 getSize(operandType(right)) == 1)
3846 genMultOneByte (left, right, result);
3850 /* should have been converted to function call */
3851 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3852 getSize(OP_SYMBOL(right)->type));
3856 freeAsmop (result, NULL, ic, TRUE);
3857 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3858 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3861 /*-----------------------------------------------------------------*/
3862 /* genDivbits :- division of bits */
3863 /*-----------------------------------------------------------------*/
3865 genDivbits (operand * left,
3872 D(emitcode ("; genDivbits",""));
3874 /* the result must be bit */
3875 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3876 l = aopGet (AOP (left), 0, FALSE, FALSE);
3880 emitcode ("div", "ab");
3881 emitcode ("rrc", "a");
3882 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3885 /*-----------------------------------------------------------------*/
3886 /* genDivOneByte : 8 bit division */
3887 /*-----------------------------------------------------------------*/
3889 genDivOneByte (operand * left,
3893 sym_link *opetype = operandType (result);
3898 D(emitcode ("; genDivOneByte",""));
3900 size = AOP_SIZE (result) - 1;
3902 /* signed or unsigned */
3903 if (SPEC_USIGN (opetype))
3905 /* unsigned is easy */
3906 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3907 l = aopGet (AOP (left), 0, FALSE, FALSE);
3909 emitcode ("div", "ab");
3910 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3912 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3916 /* signed is a little bit more difficult */
3918 /* save the signs of the operands */
3919 l = aopGet (AOP (left), 0, FALSE, FALSE);
3921 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3922 emitcode ("push", "acc"); /* save it on the stack */
3924 /* now sign adjust for both left & right */
3925 l = aopGet (AOP (right), 0, FALSE, FALSE);
3927 lbl = newiTempLabel (NULL);
3928 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3929 emitcode ("cpl", "a");
3930 emitcode ("inc", "a");
3931 emitcode ("", "%05d$:", (lbl->key + 100));
3932 emitcode ("mov", "b,a");
3934 /* sign adjust left side */
3935 l = aopGet (AOP (left), 0, FALSE, FALSE);
3938 lbl = newiTempLabel (NULL);
3939 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3940 emitcode ("cpl", "a");
3941 emitcode ("inc", "a");
3942 emitcode ("", "%05d$:", (lbl->key + 100));
3944 /* now the division */
3945 emitcode ("div", "ab");
3946 /* we are interested in the lower order
3948 emitcode ("mov", "b,a");
3949 lbl = newiTempLabel (NULL);
3950 emitcode ("pop", "acc");
3951 /* if there was an over flow we don't
3952 adjust the sign of the result */
3953 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3954 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3956 emitcode ("clr", "a");
3957 emitcode ("subb", "a,b");
3958 emitcode ("mov", "b,a");
3959 emitcode ("", "%05d$:", (lbl->key + 100));
3961 /* now we are done */
3962 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3965 emitcode ("mov", "c,b.7");
3966 emitcode ("subb", "a,acc");
3969 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3973 /*-----------------------------------------------------------------*/
3974 /* genDiv - generates code for division */
3975 /*-----------------------------------------------------------------*/
3979 operand *left = IC_LEFT (ic);
3980 operand *right = IC_RIGHT (ic);
3981 operand *result = IC_RESULT (ic);
3983 D(emitcode ("; genDiv",""));
3985 /* assign the amsops */
3986 aopOp (left, ic, FALSE);
3987 aopOp (right, ic, FALSE);
3988 aopOp (result, ic, TRUE);
3990 /* special cases first */
3992 if (AOP_TYPE (left) == AOP_CRY &&
3993 AOP_TYPE (right) == AOP_CRY)
3995 genDivbits (left, right, result);
3999 /* if both are of size == 1 */
4000 if (AOP_SIZE (left) == 1 &&
4001 AOP_SIZE (right) == 1)
4003 genDivOneByte (left, right, result);
4007 /* should have been converted to function call */
4010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4011 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4012 freeAsmop (result, NULL, ic, TRUE);
4015 /*-----------------------------------------------------------------*/
4016 /* genModbits :- modulus of bits */
4017 /*-----------------------------------------------------------------*/
4019 genModbits (operand * left,
4026 D(emitcode ("; genModbits",""));
4028 /* the result must be bit */
4029 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4030 l = aopGet (AOP (left), 0, FALSE, FALSE);
4034 emitcode ("div", "ab");
4035 emitcode ("mov", "a,b");
4036 emitcode ("rrc", "a");
4037 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus */
4042 /*-----------------------------------------------------------------*/
4044 genModOneByte (operand * left,
4048 sym_link *opetype = operandType (result);
4052 D(emitcode ("; genModOneByte",""));
4054 /* signed or unsigned */
4055 if (SPEC_USIGN (opetype))
4057 /* unsigned is easy */
4058 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4059 l = aopGet (AOP (left), 0, FALSE, FALSE);
4061 emitcode ("div", "ab");
4062 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4066 /* signed is a little bit more difficult */
4068 /* save the signs of the operands */
4069 l = aopGet (AOP (left), 0, FALSE, FALSE);
4072 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4073 emitcode ("push", "acc"); /* save it on the stack */
4075 /* now sign adjust for both left & right */
4076 l = aopGet (AOP (right), 0, FALSE, FALSE);
4079 lbl = newiTempLabel (NULL);
4080 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4081 emitcode ("cpl", "a");
4082 emitcode ("inc", "a");
4083 emitcode ("", "%05d$:", (lbl->key + 100));
4084 emitcode ("mov", "b,a");
4086 /* sign adjust left side */
4087 l = aopGet (AOP (left), 0, FALSE, FALSE);
4090 lbl = newiTempLabel (NULL);
4091 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4092 emitcode ("cpl", "a");
4093 emitcode ("inc", "a");
4094 emitcode ("", "%05d$:", (lbl->key + 100));
4096 /* now the multiplication */
4097 emitcode ("div", "ab");
4098 /* we are interested in the lower order
4100 lbl = newiTempLabel (NULL);
4101 emitcode ("pop", "acc");
4102 /* if there was an over flow we don't
4103 adjust the sign of the result */
4104 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4105 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4107 emitcode ("clr", "a");
4108 emitcode ("subb", "a,b");
4109 emitcode ("mov", "b,a");
4110 emitcode ("", "%05d$:", (lbl->key + 100));
4112 /* now we are done */
4113 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4117 /*-----------------------------------------------------------------*/
4118 /* genMod - generates code for division */
4119 /*-----------------------------------------------------------------*/
4123 operand *left = IC_LEFT (ic);
4124 operand *right = IC_RIGHT (ic);
4125 operand *result = IC_RESULT (ic);
4127 D(emitcode ("; genMod",""));
4129 /* assign the amsops */
4130 aopOp (left, ic, FALSE);
4131 aopOp (right, ic, FALSE);
4132 aopOp (result, ic, TRUE);
4134 /* special cases first */
4136 if (AOP_TYPE (left) == AOP_CRY &&
4137 AOP_TYPE (right) == AOP_CRY)
4139 genModbits (left, right, result);
4143 /* if both are of size == 1 */
4144 if (AOP_SIZE (left) == 1 &&
4145 AOP_SIZE (right) == 1)
4147 genModOneByte (left, right, result);
4151 /* should have been converted to function call */
4155 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4156 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4157 freeAsmop (result, NULL, ic, TRUE);
4160 /*-----------------------------------------------------------------*/
4161 /* genIfxJump :- will create a jump depending on the ifx */
4162 /*-----------------------------------------------------------------*/
4164 genIfxJump (iCode * ic, char *jval)
4167 symbol *tlbl = newiTempLabel (NULL);
4170 D(emitcode ("; genIfxJump",""));
4172 /* if true label then we jump if condition
4176 jlbl = IC_TRUE (ic);
4177 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4178 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4182 /* false label is present */
4183 jlbl = IC_FALSE (ic);
4184 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4185 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4187 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4188 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4190 emitcode (inst, "%05d$", tlbl->key + 100);
4191 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4192 emitcode ("", "%05d$:", tlbl->key + 100);
4194 /* mark the icode as generated */
4198 /*-----------------------------------------------------------------*/
4199 /* genCmp :- greater or less than comparison */
4200 /*-----------------------------------------------------------------*/
4202 genCmp (operand * left, operand * right,
4203 operand * result, iCode * ifx, int sign, iCode *ic)
4205 int size, offset = 0;
4206 unsigned long lit = 0L;
4209 D(emitcode ("; genCmp",""));
4211 /* if left & right are bit variables */
4212 if (AOP_TYPE (left) == AOP_CRY &&
4213 AOP_TYPE (right) == AOP_CRY)
4215 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4216 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4220 /* subtract right from left if at the
4221 end the carry flag is set then we know that
4222 left is greater than right */
4223 size = max (AOP_SIZE (left), AOP_SIZE (right));
4225 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4226 if ((size == 1) && !sign &&
4227 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4229 symbol *lbl = newiTempLabel (NULL);
4230 emitcode ("cjne", "%s,%s,%05d$",
4231 aopGet (AOP (left), offset, FALSE, FALSE),
4232 aopGet (AOP (right), offset, FALSE, FALSE),
4234 emitcode ("", "%05d$:", lbl->key + 100);
4238 if (AOP_TYPE (right) == AOP_LIT)
4240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241 /* optimize if(x < 0) or if(x >= 0) */
4250 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4251 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4253 genIfxJump (ifx, "acc.7");
4257 emitcode ("rlc", "a");
4265 rightInB = aopGetUsesAcc(AOP (right), offset);
4267 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4268 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4269 if (sign && size == 0)
4271 emitcode ("xrl", "a,#0x80");
4272 if (AOP_TYPE (right) == AOP_LIT)
4274 unsigned long lit = (unsigned long)
4275 floatFromVal (AOP (right)->aopu.aop_lit);
4276 emitcode ("subb", "a,#0x%02x",
4277 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4282 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4283 emitcode ("xrl", "b,#0x80");
4284 emitcode ("subb", "a,b");
4290 emitcode ("subb", "a,b");
4292 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4300 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4301 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4302 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4308 /* if the result is used in the next
4309 ifx conditional branch then generate
4310 code a little differently */
4312 genIfxJump (ifx, "c");
4315 /* leave the result in acc */
4319 /*-----------------------------------------------------------------*/
4320 /* genCmpGt :- greater than comparison */
4321 /*-----------------------------------------------------------------*/
4323 genCmpGt (iCode * ic, iCode * ifx)
4325 operand *left, *right, *result;
4326 sym_link *letype, *retype;
4329 D(emitcode ("; genCmpGt",""));
4331 left = IC_LEFT (ic);
4332 right = IC_RIGHT (ic);
4333 result = IC_RESULT (ic);
4335 letype = getSpec (operandType (left));
4336 retype = getSpec (operandType (right));
4337 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4338 /* assign the amsops */
4339 aopOp (left, ic, FALSE);
4340 aopOp (right, ic, FALSE);
4341 aopOp (result, ic, TRUE);
4343 genCmp (right, left, result, ifx, sign,ic);
4345 freeAsmop (result, NULL, ic, TRUE);
4348 /*-----------------------------------------------------------------*/
4349 /* genCmpLt - less than comparisons */
4350 /*-----------------------------------------------------------------*/
4352 genCmpLt (iCode * ic, iCode * ifx)
4354 operand *left, *right, *result;
4355 sym_link *letype, *retype;
4358 D(emitcode ("; genCmpLt",""));
4360 left = IC_LEFT (ic);
4361 right = IC_RIGHT (ic);
4362 result = IC_RESULT (ic);
4364 letype = getSpec (operandType (left));
4365 retype = getSpec (operandType (right));
4366 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4368 /* assign the amsops */
4369 aopOp (left, ic, FALSE);
4370 aopOp (right, ic, FALSE);
4371 aopOp (result, ic, TRUE);
4373 genCmp (left, right, result, ifx, sign,ic);
4375 freeAsmop (result, NULL, ic, TRUE);
4378 /*-----------------------------------------------------------------*/
4379 /* gencjneshort - compare and jump if not equal */
4380 /*-----------------------------------------------------------------*/
4382 gencjneshort (operand * left, operand * right, symbol * lbl)
4384 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4386 unsigned long lit = 0L;
4388 /* if the left side is a literal or
4389 if the right is in a pointer register and left
4391 if ((AOP_TYPE (left) == AOP_LIT) ||
4392 (AOP_TYPE (left) == AOP_IMMD) ||
4393 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4400 if (AOP_TYPE (right) == AOP_LIT)
4401 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4403 /* if the right side is a literal then anything goes */
4404 if (AOP_TYPE (right) == AOP_LIT &&
4405 AOP_TYPE (left) != AOP_DIR &&
4406 AOP_TYPE (left) != AOP_IMMD)
4410 emitcode ("cjne", "%s,%s,%05d$",
4411 aopGet (AOP (left), offset, FALSE, FALSE),
4412 aopGet (AOP (right), offset, FALSE, FALSE),
4418 /* if the right side is in a register or in direct space or
4419 if the left is a pointer register & right is not */
4420 else if (AOP_TYPE (right) == AOP_REG ||
4421 AOP_TYPE (right) == AOP_DIR ||
4422 AOP_TYPE (right) == AOP_LIT ||
4423 AOP_TYPE (right) == AOP_IMMD ||
4424 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4425 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4429 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4430 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4431 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4432 emitcode ("jnz", "%05d$", lbl->key + 100);
4434 emitcode ("cjne", "a,%s,%05d$",
4435 aopGet (AOP (right), offset, FALSE, TRUE),
4442 /* right is a pointer reg need both a & b */
4445 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4446 if (strcmp (l, "b"))
4447 emitcode ("mov", "b,%s", l);
4448 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4449 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4455 /*-----------------------------------------------------------------*/
4456 /* gencjne - compare and jump if not equal */
4457 /*-----------------------------------------------------------------*/
4459 gencjne (operand * left, operand * right, symbol * lbl)
4461 symbol *tlbl = newiTempLabel (NULL);
4463 gencjneshort (left, right, lbl);
4465 emitcode ("mov", "a,%s", one);
4466 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4467 emitcode ("", "%05d$:", lbl->key + 100);
4468 emitcode ("clr", "a");
4469 emitcode ("", "%05d$:", tlbl->key + 100);
4472 /*-----------------------------------------------------------------*/
4473 /* genCmpEq - generates code for equal to */
4474 /*-----------------------------------------------------------------*/
4476 genCmpEq (iCode * ic, iCode * ifx)
4478 operand *left, *right, *result;
4480 D(emitcode ("; genCmpEq",""));
4482 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4483 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4484 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4486 /* if literal, literal on the right or
4487 if the right is in a pointer register and left
4489 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4490 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4492 operand *t = IC_RIGHT (ic);
4493 IC_RIGHT (ic) = IC_LEFT (ic);
4497 if (ifx && !AOP_SIZE (result))
4500 /* if they are both bit variables */
4501 if (AOP_TYPE (left) == AOP_CRY &&
4502 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4504 if (AOP_TYPE (right) == AOP_LIT)
4506 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4510 emitcode ("cpl", "c");
4514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4518 emitcode ("clr", "c");
4520 /* AOP_TYPE(right) == AOP_CRY */
4524 symbol *lbl = newiTempLabel (NULL);
4525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4526 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4527 emitcode ("cpl", "c");
4528 emitcode ("", "%05d$:", (lbl->key + 100));
4530 /* if true label then we jump if condition
4532 tlbl = newiTempLabel (NULL);
4535 emitcode ("jnc", "%05d$", tlbl->key + 100);
4536 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4540 emitcode ("jc", "%05d$", tlbl->key + 100);
4541 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4543 emitcode ("", "%05d$:", tlbl->key + 100);
4547 tlbl = newiTempLabel (NULL);
4548 gencjneshort (left, right, tlbl);
4551 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4552 emitcode ("", "%05d$:", tlbl->key + 100);
4556 symbol *lbl = newiTempLabel (NULL);
4557 emitcode ("sjmp", "%05d$", lbl->key + 100);
4558 emitcode ("", "%05d$:", tlbl->key + 100);
4559 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4560 emitcode ("", "%05d$:", lbl->key + 100);
4563 /* mark the icode as generated */
4568 /* if they are both bit variables */
4569 if (AOP_TYPE (left) == AOP_CRY &&
4570 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4572 if (AOP_TYPE (right) == AOP_LIT)
4574 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4577 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4578 emitcode ("cpl", "c");
4582 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4586 emitcode ("clr", "c");
4588 /* AOP_TYPE(right) == AOP_CRY */
4592 symbol *lbl = newiTempLabel (NULL);
4593 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4594 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4595 emitcode ("cpl", "c");
4596 emitcode ("", "%05d$:", (lbl->key + 100));
4599 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4606 genIfxJump (ifx, "c");
4609 /* if the result is used in an arithmetic operation
4610 then put the result in place */
4615 gencjne (left, right, newiTempLabel (NULL));
4616 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4618 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4623 genIfxJump (ifx, "a");
4626 /* if the result is used in an arithmetic operation
4627 then put the result in place */
4628 if (AOP_TYPE (result) != AOP_CRY)
4630 /* leave the result in acc */
4634 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4635 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (result, NULL, ic, TRUE);
4639 /*-----------------------------------------------------------------*/
4640 /* ifxForOp - returns the icode containing the ifx for operand */
4641 /*-----------------------------------------------------------------*/
4643 ifxForOp (operand * op, iCode * ic)
4645 /* if true symbol then needs to be assigned */
4646 if (IS_TRUE_SYMOP (op))
4649 /* if this has register type condition and
4650 the next instruction is ifx with the same operand
4651 and live to of the operand is upto the ifx only then */
4653 ic->next->op == IFX &&
4654 IC_COND (ic->next)->key == op->key &&
4655 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4661 /*-----------------------------------------------------------------*/
4662 /* hasInc - operand is incremented before any other use */
4663 /*-----------------------------------------------------------------*/
4665 hasInc (operand *op, iCode *ic,int osize)
4667 sym_link *type = operandType(op);
4668 sym_link *retype = getSpec (type);
4669 iCode *lic = ic->next;
4672 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4673 if (!IS_SYMOP(op)) return NULL;
4675 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4676 if (IS_AGGREGATE(type->next)) return NULL;
4677 if (osize != (isize = getSize(type->next))) return NULL;
4680 /* if operand of the form op = op + <sizeof *op> */
4681 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4682 isOperandEqual(IC_RESULT(lic),op) &&
4683 isOperandLiteral(IC_RIGHT(lic)) &&
4684 operandLitValue(IC_RIGHT(lic)) == isize) {
4687 /* if the operand used or deffed */
4688 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4691 /* if GOTO or IFX */
4692 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4698 /*-----------------------------------------------------------------*/
4699 /* genAndOp - for && operation */
4700 /*-----------------------------------------------------------------*/
4702 genAndOp (iCode * ic)
4704 operand *left, *right, *result;
4707 D(emitcode ("; genAndOp",""));
4709 /* note here that && operations that are in an
4710 if statement are taken away by backPatchLabels
4711 only those used in arthmetic operations remain */
4712 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4713 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4714 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4716 /* if both are bit variables */
4717 if (AOP_TYPE (left) == AOP_CRY &&
4718 AOP_TYPE (right) == AOP_CRY)
4720 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4721 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4726 tlbl = newiTempLabel (NULL);
4728 emitcode ("jz", "%05d$", tlbl->key + 100);
4730 emitcode ("", "%05d$:", tlbl->key + 100);
4734 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736 freeAsmop (result, NULL, ic, TRUE);
4740 /*-----------------------------------------------------------------*/
4741 /* genOrOp - for || operation */
4742 /*-----------------------------------------------------------------*/
4744 genOrOp (iCode * ic)
4746 operand *left, *right, *result;
4749 D(emitcode ("; genOrOp",""));
4751 /* note here that || operations that are in an
4752 if statement are taken away by backPatchLabels
4753 only those used in arthmetic operations remain */
4754 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4755 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4756 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4758 /* if both are bit variables */
4759 if (AOP_TYPE (left) == AOP_CRY &&
4760 AOP_TYPE (right) == AOP_CRY)
4762 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4763 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4768 tlbl = newiTempLabel (NULL);
4770 emitcode ("jnz", "%05d$", tlbl->key + 100);
4772 emitcode ("", "%05d$:", tlbl->key + 100);
4776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778 freeAsmop (result, NULL, ic, TRUE);
4781 /*-----------------------------------------------------------------*/
4782 /* isLiteralBit - test if lit == 2^n */
4783 /*-----------------------------------------------------------------*/
4785 isLiteralBit (unsigned long lit)
4787 unsigned long pw[32] =
4788 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4789 0x100L, 0x200L, 0x400L, 0x800L,
4790 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4791 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4792 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4793 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4794 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4797 for (idx = 0; idx < 32; idx++)
4803 /*-----------------------------------------------------------------*/
4804 /* continueIfTrue - */
4805 /*-----------------------------------------------------------------*/
4807 continueIfTrue (iCode * ic)
4810 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4814 /*-----------------------------------------------------------------*/
4816 /*-----------------------------------------------------------------*/
4818 jumpIfTrue (iCode * ic)
4821 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4825 /*-----------------------------------------------------------------*/
4826 /* jmpTrueOrFalse - */
4827 /*-----------------------------------------------------------------*/
4829 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4831 // ugly but optimized by peephole
4834 symbol *nlbl = newiTempLabel (NULL);
4835 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4836 emitcode ("", "%05d$:", tlbl->key + 100);
4837 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4838 emitcode ("", "%05d$:", nlbl->key + 100);
4842 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4843 emitcode ("", "%05d$:", tlbl->key + 100);
4848 /*-----------------------------------------------------------------*/
4849 /* genAnd - code for and */
4850 /*-----------------------------------------------------------------*/
4852 genAnd (iCode * ic, iCode * ifx)
4854 operand *left, *right, *result;
4855 int size, offset = 0;
4856 unsigned long lit = 0L;
4860 D(emitcode ("; genAnd",""));
4862 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4863 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4864 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4867 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4869 AOP_TYPE (left), AOP_TYPE (right));
4870 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4872 AOP_SIZE (left), AOP_SIZE (right));
4875 /* if left is a literal & right is not then exchange them */
4876 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4877 AOP_NEEDSACC (left))
4879 operand *tmp = right;
4884 /* if result = right then exchange them */
4885 if (sameRegs (AOP (result), AOP (right)))
4887 operand *tmp = right;
4892 /* if right is bit then exchange them */
4893 if (AOP_TYPE (right) == AOP_CRY &&
4894 AOP_TYPE (left) != AOP_CRY)
4896 operand *tmp = right;
4900 if (AOP_TYPE (right) == AOP_LIT)
4901 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4903 size = AOP_SIZE (result);
4906 // result = bit & yy;
4907 if (AOP_TYPE (left) == AOP_CRY)
4909 // c = bit & literal;
4910 if (AOP_TYPE (right) == AOP_LIT)
4914 if (size && sameRegs (AOP (result), AOP (left)))
4917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4922 if (size && (AOP_TYPE (result) == AOP_CRY))
4924 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4927 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4932 emitcode ("clr", "c");
4937 if (AOP_TYPE (right) == AOP_CRY)
4940 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4941 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4946 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4948 emitcode ("rrc", "a");
4949 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4957 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4958 genIfxJump (ifx, "c");
4962 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4963 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4964 if ((AOP_TYPE (right) == AOP_LIT) &&
4965 (AOP_TYPE (result) == AOP_CRY) &&
4966 (AOP_TYPE (left) != AOP_CRY))
4968 int posbit = isLiteralBit (lit);
4973 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4976 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4982 sprintf (buffer, "acc.%d", posbit & 0x07);
4983 genIfxJump (ifx, buffer);
4990 symbol *tlbl = newiTempLabel (NULL);
4991 int sizel = AOP_SIZE (left);
4993 emitcode ("setb", "c");
4996 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4998 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5000 if ((posbit = isLiteralBit (bytelit)) != 0)
5001 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5004 if (bytelit != 0x0FFL)
5005 emitcode ("anl", "a,%s",
5006 aopGet (AOP (right), offset, FALSE, TRUE));
5007 emitcode ("jnz", "%05d$", tlbl->key + 100);
5012 // bit = left & literal
5015 emitcode ("clr", "c");
5016 emitcode ("", "%05d$:", tlbl->key + 100);
5018 // if(left & literal)
5022 jmpTrueOrFalse (ifx, tlbl);
5024 emitcode ("", "%05d$:", tlbl->key + 100);
5032 /* if left is same as result */
5033 if (sameRegs (AOP (result), AOP (left)))
5035 for (; size--; offset++)
5037 if (AOP_TYPE (right) == AOP_LIT)
5039 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5041 else if (bytelit == 0)
5043 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5045 else if (IS_AOP_PREG (result))
5047 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5048 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5049 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5052 emitcode ("anl", "%s,%s",
5053 aopGet (AOP (left), offset, FALSE, TRUE),
5054 aopGet (AOP (right), offset, FALSE, FALSE));
5058 if (AOP_TYPE (left) == AOP_ACC)
5059 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5062 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5063 if (IS_AOP_PREG (result))
5065 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5066 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5070 emitcode ("anl", "%s,a",
5071 aopGet (AOP (left), offset, FALSE, TRUE));
5078 // left & result in different registers
5079 if (AOP_TYPE (result) == AOP_CRY)
5082 // if(size), result in bit
5083 // if(!size && ifx), conditional oper: if(left & right)
5084 symbol *tlbl = newiTempLabel (NULL);
5085 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5087 emitcode ("setb", "c");
5090 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5091 emitcode ("anl", "a,%s",
5092 aopGet (AOP (right), offset, FALSE, FALSE));
5094 if (AOP_TYPE(left)==AOP_ACC) {
5095 emitcode("mov", "b,a");
5096 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5097 emitcode("anl", "a,b");
5099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5100 emitcode ("anl", "a,%s",
5101 aopGet (AOP (left), offset, FALSE, FALSE));
5104 emitcode ("jnz", "%05d$", tlbl->key + 100);
5110 emitcode ("", "%05d$:", tlbl->key + 100);
5114 jmpTrueOrFalse (ifx, tlbl);
5116 emitcode ("", "%05d$:", tlbl->key + 100);
5120 for (; (size--); offset++)
5123 // result = left & right
5124 if (AOP_TYPE (right) == AOP_LIT)
5126 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5128 aopPut (AOP (result),
5129 aopGet (AOP (left), offset, FALSE, FALSE),
5131 isOperandVolatile (result, FALSE));
5134 else if (bytelit == 0)
5136 /* dummy read of volatile operand */
5137 if (isOperandVolatile (left, FALSE))
5138 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5139 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5143 // faster than result <- left, anl result,right
5144 // and better if result is SFR
5145 if (AOP_TYPE (left) == AOP_ACC)
5146 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5149 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5150 emitcode ("anl", "a,%s",
5151 aopGet (AOP (left), offset, FALSE, FALSE));
5153 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5159 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5160 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5161 freeAsmop (result, NULL, ic, TRUE);
5164 /*-----------------------------------------------------------------*/
5165 /* genOr - code for or */
5166 /*-----------------------------------------------------------------*/
5168 genOr (iCode * ic, iCode * ifx)
5170 operand *left, *right, *result;
5171 int size, offset = 0;
5172 unsigned long lit = 0L;
5174 D(emitcode ("; genOr",""));
5176 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5177 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5178 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5181 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5183 AOP_TYPE (left), AOP_TYPE (right));
5184 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5186 AOP_SIZE (left), AOP_SIZE (right));
5189 /* if left is a literal & right is not then exchange them */
5190 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5191 AOP_NEEDSACC (left))
5193 operand *tmp = right;
5198 /* if result = right then exchange them */
5199 if (sameRegs (AOP (result), AOP (right)))
5201 operand *tmp = right;
5206 /* if right is bit then exchange them */
5207 if (AOP_TYPE (right) == AOP_CRY &&
5208 AOP_TYPE (left) != AOP_CRY)
5210 operand *tmp = right;
5214 if (AOP_TYPE (right) == AOP_LIT)
5215 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5217 size = AOP_SIZE (result);
5221 if (AOP_TYPE (left) == AOP_CRY)
5223 if (AOP_TYPE (right) == AOP_LIT)
5225 // c = bit | literal;
5228 // lit != 0 => result = 1
5229 if (AOP_TYPE (result) == AOP_CRY)
5232 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5234 continueIfTrue (ifx);
5237 emitcode ("setb", "c");
5241 // lit == 0 => result = left
5242 if (size && sameRegs (AOP (result), AOP (left)))
5244 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5249 if (AOP_TYPE (right) == AOP_CRY)
5252 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5253 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5258 symbol *tlbl = newiTempLabel (NULL);
5259 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5260 emitcode ("setb", "c");
5261 emitcode ("jb", "%s,%05d$",
5262 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5264 emitcode ("jnz", "%05d$", tlbl->key + 100);
5265 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5267 jmpTrueOrFalse (ifx, tlbl);
5273 emitcode ("", "%05d$:", tlbl->key + 100);
5282 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5283 genIfxJump (ifx, "c");
5287 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5288 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5289 if ((AOP_TYPE (right) == AOP_LIT) &&
5290 (AOP_TYPE (result) == AOP_CRY) &&
5291 (AOP_TYPE (left) != AOP_CRY))
5297 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5299 continueIfTrue (ifx);
5304 // lit = 0, result = boolean(left)
5306 emitcode ("setb", "c");
5310 symbol *tlbl = newiTempLabel (NULL);
5311 emitcode ("jnz", "%05d$", tlbl->key + 100);
5313 emitcode ("", "%05d$:", tlbl->key + 100);
5317 genIfxJump (ifx, "a");
5325 /* if left is same as result */
5326 if (sameRegs (AOP (result), AOP (left)))
5328 for (; size--; offset++)
5330 if (AOP_TYPE (right) == AOP_LIT)
5332 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5334 /* dummy read of volatile operand */
5335 if (isOperandVolatile (left, FALSE))
5336 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5340 else if (IS_AOP_PREG (left))
5342 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5343 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5344 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5347 emitcode ("orl", "%s,%s",
5348 aopGet (AOP (left), offset, FALSE, TRUE),
5349 aopGet (AOP (right), offset, FALSE, FALSE));
5353 if (AOP_TYPE (left) == AOP_ACC)
5354 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5357 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5358 if (IS_AOP_PREG (left))
5360 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5361 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5364 emitcode ("orl", "%s,a",
5365 aopGet (AOP (left), offset, FALSE, TRUE));
5372 // left & result in different registers
5373 if (AOP_TYPE (result) == AOP_CRY)
5376 // if(size), result in bit
5377 // if(!size && ifx), conditional oper: if(left | right)
5378 symbol *tlbl = newiTempLabel (NULL);
5379 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5381 emitcode ("setb", "c");
5384 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5385 emitcode ("orl", "a,%s",
5386 aopGet (AOP (right), offset, FALSE, FALSE));
5388 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5389 emitcode ("orl", "a,%s",
5390 aopGet (AOP (left), offset, FALSE, FALSE));
5392 emitcode ("jnz", "%05d$", tlbl->key + 100);
5398 emitcode ("", "%05d$:", tlbl->key + 100);
5402 jmpTrueOrFalse (ifx, tlbl);
5404 emitcode ("", "%05d$:", tlbl->key + 100);
5407 for (; (size--); offset++)
5410 // result = left & right
5411 if (AOP_TYPE (right) == AOP_LIT)
5413 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5415 aopPut (AOP (result),
5416 aopGet (AOP (left), offset, FALSE, FALSE),
5418 isOperandVolatile (result, FALSE));
5422 // faster than result <- left, anl result,right
5423 // and better if result is SFR
5424 if (AOP_TYPE (left) == AOP_ACC)
5425 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5428 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5429 emitcode ("orl", "a,%s",
5430 aopGet (AOP (left), offset, FALSE, FALSE));
5432 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5437 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439 freeAsmop (result, NULL, ic, TRUE);
5442 /*-----------------------------------------------------------------*/
5443 /* genXor - code for xclusive or */
5444 /*-----------------------------------------------------------------*/
5446 genXor (iCode * ic, iCode * ifx)
5448 operand *left, *right, *result;
5449 int size, offset = 0;
5450 unsigned long lit = 0L;
5452 D(emitcode ("; genXor",""));
5454 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5455 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5456 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5459 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5461 AOP_TYPE (left), AOP_TYPE (right));
5462 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5464 AOP_SIZE (left), AOP_SIZE (right));
5467 /* if left is a literal & right is not ||
5468 if left needs acc & right does not */
5469 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5470 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5472 operand *tmp = right;
5477 /* if result = right then exchange them */
5478 if (sameRegs (AOP (result), AOP (right)))
5480 operand *tmp = right;
5485 /* if right is bit then exchange them */
5486 if (AOP_TYPE (right) == AOP_CRY &&
5487 AOP_TYPE (left) != AOP_CRY)
5489 operand *tmp = right;
5493 if (AOP_TYPE (right) == AOP_LIT)
5494 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5496 size = AOP_SIZE (result);
5500 if (AOP_TYPE (left) == AOP_CRY)
5502 if (AOP_TYPE (right) == AOP_LIT)
5504 // c = bit & literal;
5507 // lit>>1 != 0 => result = 1
5508 if (AOP_TYPE (result) == AOP_CRY)
5511 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5513 continueIfTrue (ifx);
5516 emitcode ("setb", "c");
5523 // lit == 0, result = left
5524 if (size && sameRegs (AOP (result), AOP (left)))
5526 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5530 // lit == 1, result = not(left)
5531 if (size && sameRegs (AOP (result), AOP (left)))
5533 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5538 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5539 emitcode ("cpl", "c");
5548 symbol *tlbl = newiTempLabel (NULL);
5549 if (AOP_TYPE (right) == AOP_CRY)
5552 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5556 int sizer = AOP_SIZE (right);
5558 // if val>>1 != 0, result = 1
5559 emitcode ("setb", "c");
5562 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5564 // test the msb of the lsb
5565 emitcode ("anl", "a,#0xfe");
5566 emitcode ("jnz", "%05d$", tlbl->key + 100);
5570 emitcode ("rrc", "a");
5572 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5573 emitcode ("cpl", "c");
5574 emitcode ("", "%05d$:", (tlbl->key + 100));
5581 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5582 genIfxJump (ifx, "c");
5586 if (sameRegs (AOP (result), AOP (left)))
5588 /* if left is same as result */
5589 for (; size--; offset++)
5591 if (AOP_TYPE (right) == AOP_LIT)
5593 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5595 else if (IS_AOP_PREG (left))
5597 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5598 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5599 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5602 emitcode ("xrl", "%s,%s",
5603 aopGet (AOP (left), offset, FALSE, TRUE),
5604 aopGet (AOP (right), offset, FALSE, FALSE));
5608 if (AOP_TYPE (left) == AOP_ACC)
5609 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5612 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5613 if (IS_AOP_PREG (left))
5615 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5616 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5619 emitcode ("xrl", "%s,a",
5620 aopGet (AOP (left), offset, FALSE, TRUE));
5627 // left & result in different registers
5628 if (AOP_TYPE (result) == AOP_CRY)
5631 // if(size), result in bit
5632 // if(!size && ifx), conditional oper: if(left ^ right)
5633 symbol *tlbl = newiTempLabel (NULL);
5634 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5636 emitcode ("setb", "c");
5639 if ((AOP_TYPE (right) == AOP_LIT) &&
5640 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5642 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5646 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5647 emitcode ("xrl", "a,%s",
5648 aopGet (AOP (right), offset, FALSE, FALSE));
5650 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5651 emitcode ("xrl", "a,%s",
5652 aopGet (AOP (left), offset, FALSE, FALSE));
5655 emitcode ("jnz", "%05d$", tlbl->key + 100);
5661 emitcode ("", "%05d$:", tlbl->key + 100);
5665 jmpTrueOrFalse (ifx, tlbl);
5668 for (; (size--); offset++)
5671 // result = left & right
5672 if (AOP_TYPE (right) == AOP_LIT)
5674 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5676 aopPut (AOP (result),
5677 aopGet (AOP (left), offset, FALSE, FALSE),
5679 isOperandVolatile (result, FALSE));
5683 // faster than result <- left, anl result,right
5684 // and better if result is SFR
5685 if (AOP_TYPE (left) == AOP_ACC)
5686 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5689 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5690 emitcode ("xrl", "a,%s",
5691 aopGet (AOP (left), offset, FALSE, TRUE));
5693 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5698 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5699 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5700 freeAsmop (result, NULL, ic, TRUE);
5703 /*-----------------------------------------------------------------*/
5704 /* genInline - write the inline code out */
5705 /*-----------------------------------------------------------------*/
5707 genInline (iCode * ic)
5709 char *buffer, *bp, *bp1;
5711 D(emitcode ("; genInline",""));
5713 _G.inLine += (!options.asmpeep);
5715 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5716 strcpy (buffer, IC_INLINE (ic));
5718 /* emit each line as a code */
5743 /* emitcode("",buffer); */
5744 _G.inLine -= (!options.asmpeep);
5747 /*-----------------------------------------------------------------*/
5748 /* genRRC - rotate right with carry */
5749 /*-----------------------------------------------------------------*/
5753 operand *left, *result;
5754 int size, offset = 0;
5757 D(emitcode ("; genRRC",""));
5759 /* rotate right with carry */
5760 left = IC_LEFT (ic);
5761 result = IC_RESULT (ic);
5762 aopOp (left, ic, FALSE);
5763 aopOp (result, ic, FALSE);
5765 /* move it to the result */
5766 size = AOP_SIZE (result);
5768 if (size == 1) { /* special case for 1 byte */
5769 l = aopGet (AOP (left), offset, FALSE, FALSE);
5771 emitcode ("rr", "a");
5777 l = aopGet (AOP (left), offset, FALSE, FALSE);
5779 emitcode ("rrc", "a");
5780 if (AOP_SIZE (result) > 1)
5781 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5783 /* now we need to put the carry into the
5784 highest order byte of the result */
5785 if (AOP_SIZE (result) > 1)
5787 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5790 emitcode ("mov", "acc.7,c");
5792 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5793 freeAsmop (left, NULL, ic, TRUE);
5794 freeAsmop (result, NULL, ic, TRUE);
5797 /*-----------------------------------------------------------------*/
5798 /* genRLC - generate code for rotate left with carry */
5799 /*-----------------------------------------------------------------*/
5803 operand *left, *result;
5804 int size, offset = 0;
5807 D(emitcode ("; genRLC",""));
5809 /* rotate right with carry */
5810 left = IC_LEFT (ic);
5811 result = IC_RESULT (ic);
5812 aopOp (left, ic, FALSE);
5813 aopOp (result, ic, FALSE);
5815 /* move it to the result */
5816 size = AOP_SIZE (result);
5820 l = aopGet (AOP (left), offset, FALSE, FALSE);
5822 if (size == 0) { /* special case for 1 byte */
5826 emitcode ("add", "a,acc");
5827 if (AOP_SIZE (result) > 1)
5828 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5831 l = aopGet (AOP (left), offset, FALSE, FALSE);
5833 emitcode ("rlc", "a");
5834 if (AOP_SIZE (result) > 1)
5835 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5838 /* now we need to put the carry into the
5839 highest order byte of the result */
5840 if (AOP_SIZE (result) > 1)
5842 l = aopGet (AOP (result), 0, FALSE, FALSE);
5845 emitcode ("mov", "acc.0,c");
5847 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5848 freeAsmop (left, NULL, ic, TRUE);
5849 freeAsmop (result, NULL, ic, TRUE);
5852 /*-----------------------------------------------------------------*/
5853 /* genGetHbit - generates code get highest order bit */
5854 /*-----------------------------------------------------------------*/
5856 genGetHbit (iCode * ic)
5858 operand *left, *result;
5860 D(emitcode ("; genGetHbit",""));
5862 left = IC_LEFT (ic);
5863 result = IC_RESULT (ic);
5864 aopOp (left, ic, FALSE);
5865 aopOp (result, ic, FALSE);
5867 /* get the highest order byte into a */
5868 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5869 if (AOP_TYPE (result) == AOP_CRY)
5871 emitcode ("rlc", "a");
5876 emitcode ("rl", "a");
5877 emitcode ("anl", "a,#0x01");
5882 freeAsmop (left, NULL, ic, TRUE);
5883 freeAsmop (result, NULL, ic, TRUE);
5886 /*-----------------------------------------------------------------*/
5887 /* genSwap - generates code to swap nibbles or bytes */
5888 /*-----------------------------------------------------------------*/
5890 genSwap (iCode * ic)
5892 operand *left, *result;
5894 D(emitcode ("; genSwap",""));
5896 left = IC_LEFT (ic);
5897 result = IC_RESULT (ic);
5898 aopOp (left, ic, FALSE);
5899 aopOp (result, ic, FALSE);
5901 switch (AOP_SIZE (left))
5903 case 1: /* swap nibbles in byte */
5904 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5905 emitcode ("swap", "a");
5906 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5908 case 2: /* swap bytes in word */
5909 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5911 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5912 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5913 0, isOperandVolatile (result, FALSE));
5914 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5916 else if (operandsEqu (left, result))
5919 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5920 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5922 emitcode ("mov", "b,a");
5925 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5926 0, isOperandVolatile (result, FALSE));
5927 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5931 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5932 0, isOperandVolatile (result, FALSE));
5933 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5934 1, isOperandVolatile (result, FALSE));
5938 wassertl(FALSE, "unsupported SWAP operand size");
5941 freeAsmop (left, NULL, ic, TRUE);
5942 freeAsmop (result, NULL, ic, TRUE);
5946 /*-----------------------------------------------------------------*/
5947 /* AccRol - rotate left accumulator by known count */
5948 /*-----------------------------------------------------------------*/
5950 AccRol (int shCount)
5952 shCount &= 0x0007; // shCount : 0..7
5959 emitcode ("rl", "a");
5962 emitcode ("rl", "a");
5963 emitcode ("rl", "a");
5966 emitcode ("swap", "a");
5967 emitcode ("rr", "a");
5970 emitcode ("swap", "a");
5973 emitcode ("swap", "a");
5974 emitcode ("rl", "a");
5977 emitcode ("rr", "a");
5978 emitcode ("rr", "a");
5981 emitcode ("rr", "a");
5986 /*-----------------------------------------------------------------*/
5987 /* AccLsh - left shift accumulator by known count */
5988 /*-----------------------------------------------------------------*/
5990 AccLsh (int shCount)
5995 emitcode ("add", "a,acc");
5996 else if (shCount == 2)
5998 emitcode ("add", "a,acc");
5999 emitcode ("add", "a,acc");
6003 /* rotate left accumulator */
6005 /* and kill the lower order bits */
6006 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6011 /*-----------------------------------------------------------------*/
6012 /* AccRsh - right shift accumulator by known count */
6013 /*-----------------------------------------------------------------*/
6015 AccRsh (int shCount)
6022 emitcode ("rrc", "a");
6026 /* rotate right accumulator */
6027 AccRol (8 - shCount);
6028 /* and kill the higher order bits */
6029 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6034 /*-----------------------------------------------------------------*/
6035 /* AccSRsh - signed right shift accumulator by known count */
6036 /*-----------------------------------------------------------------*/
6038 AccSRsh (int shCount)
6045 emitcode ("mov", "c,acc.7");
6046 emitcode ("rrc", "a");
6048 else if (shCount == 2)
6050 emitcode ("mov", "c,acc.7");
6051 emitcode ("rrc", "a");
6052 emitcode ("mov", "c,acc.7");
6053 emitcode ("rrc", "a");
6057 tlbl = newiTempLabel (NULL);
6058 /* rotate right accumulator */
6059 AccRol (8 - shCount);
6060 /* and kill the higher order bits */
6061 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6062 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6063 emitcode ("orl", "a,#0x%02x",
6064 (unsigned char) ~SRMask[shCount]);
6065 emitcode ("", "%05d$:", tlbl->key + 100);
6070 /*-----------------------------------------------------------------*/
6071 /* shiftR1Left2Result - shift right one byte from left to result */
6072 /*-----------------------------------------------------------------*/
6074 shiftR1Left2Result (operand * left, int offl,
6075 operand * result, int offr,
6076 int shCount, int sign)
6078 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6079 /* shift right accumulator */
6084 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6087 /*-----------------------------------------------------------------*/
6088 /* shiftL1Left2Result - shift left one byte from left to result */
6089 /*-----------------------------------------------------------------*/
6091 shiftL1Left2Result (operand * left, int offl,
6092 operand * result, int offr, int shCount)
6095 l = aopGet (AOP (left), offl, FALSE, FALSE);
6097 /* shift left accumulator */
6099 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6102 /*-----------------------------------------------------------------*/
6103 /* movLeft2Result - move byte from left to result */
6104 /*-----------------------------------------------------------------*/
6106 movLeft2Result (operand * left, int offl,
6107 operand * result, int offr, int sign)
6110 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6112 l = aopGet (AOP (left), offl, FALSE, FALSE);
6114 if (*l == '@' && (IS_AOP_PREG (result)))
6116 emitcode ("mov", "a,%s", l);
6117 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6122 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6125 /* MSB sign in acc.7 ! */
6126 if (getDataSize (left) == offl + 1)
6128 emitcode ("mov", "a,%s", l);
6129 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6136 /*-----------------------------------------------------------------*/
6137 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6138 /*-----------------------------------------------------------------*/
6142 emitcode ("rrc", "a");
6143 emitcode ("xch", "a,%s", x);
6144 emitcode ("rrc", "a");
6145 emitcode ("xch", "a,%s", x);
6148 /*-----------------------------------------------------------------*/
6149 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6150 /*-----------------------------------------------------------------*/
6154 emitcode ("xch", "a,%s", x);
6155 emitcode ("rlc", "a");
6156 emitcode ("xch", "a,%s", x);
6157 emitcode ("rlc", "a");
6160 /*-----------------------------------------------------------------*/
6161 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6162 /*-----------------------------------------------------------------*/
6166 emitcode ("xch", "a,%s", x);
6167 emitcode ("add", "a,acc");
6168 emitcode ("xch", "a,%s", x);
6169 emitcode ("rlc", "a");
6172 /*-----------------------------------------------------------------*/
6173 /* AccAXLsh - left shift a:x by known count (0..7) */
6174 /*-----------------------------------------------------------------*/
6176 AccAXLsh (char *x, int shCount)
6191 case 5: // AAAAABBB:CCCCCDDD
6193 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6195 emitcode ("anl", "a,#0x%02x",
6196 SLMask[shCount]); // BBB00000:CCCCCDDD
6198 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6200 AccRol (shCount); // DDDCCCCC:BBB00000
6202 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6204 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6206 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6208 emitcode ("anl", "a,#0x%02x",
6209 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6211 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6213 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6216 case 6: // AAAAAABB:CCCCCCDD
6217 emitcode ("anl", "a,#0x%02x",
6218 SRMask[shCount]); // 000000BB:CCCCCCDD
6219 emitcode ("mov", "c,acc.0"); // c = B
6220 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6222 AccAXRrl1 (x); // BCCCCCCD:D000000B
6223 AccAXRrl1 (x); // BBCCCCCC:DD000000
6225 emitcode("rrc","a");
6226 emitcode("xch","a,%s", x);
6227 emitcode("rrc","a");
6228 emitcode("mov","c,acc.0"); //<< get correct bit
6229 emitcode("xch","a,%s", x);
6231 emitcode("rrc","a");
6232 emitcode("xch","a,%s", x);
6233 emitcode("rrc","a");
6234 emitcode("xch","a,%s", x);
6237 case 7: // a:x <<= 7
6239 emitcode ("anl", "a,#0x%02x",
6240 SRMask[shCount]); // 0000000B:CCCCCCCD
6242 emitcode ("mov", "c,acc.0"); // c = B
6244 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6246 AccAXRrl1 (x); // BCCCCCCC:D0000000
6254 /*-----------------------------------------------------------------*/
6255 /* AccAXRsh - right shift a:x known count (0..7) */
6256 /*-----------------------------------------------------------------*/
6258 AccAXRsh (char *x, int shCount)
6266 AccAXRrl1 (x); // 0->a:x
6271 AccAXRrl1 (x); // 0->a:x
6274 AccAXRrl1 (x); // 0->a:x
6279 case 5: // AAAAABBB:CCCCCDDD = a:x
6281 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6283 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6285 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6287 emitcode ("anl", "a,#0x%02x",
6288 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6290 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6292 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6294 emitcode ("anl", "a,#0x%02x",
6295 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6297 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6299 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6301 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6304 case 6: // AABBBBBB:CCDDDDDD
6306 emitcode ("mov", "c,acc.7");
6307 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6309 emitcode ("mov", "c,acc.7");
6310 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6312 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6314 emitcode ("anl", "a,#0x%02x",
6315 SRMask[shCount]); // 000000AA:BBBBBBCC
6318 case 7: // ABBBBBBB:CDDDDDDD
6320 emitcode ("mov", "c,acc.7"); // c = A
6322 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6324 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6326 emitcode ("anl", "a,#0x%02x",
6327 SRMask[shCount]); // 0000000A:BBBBBBBC
6335 /*-----------------------------------------------------------------*/
6336 /* AccAXRshS - right shift signed a:x known count (0..7) */
6337 /*-----------------------------------------------------------------*/
6339 AccAXRshS (char *x, int shCount)
6347 emitcode ("mov", "c,acc.7");
6348 AccAXRrl1 (x); // s->a:x
6352 emitcode ("mov", "c,acc.7");
6353 AccAXRrl1 (x); // s->a:x
6355 emitcode ("mov", "c,acc.7");
6356 AccAXRrl1 (x); // s->a:x
6361 case 5: // AAAAABBB:CCCCCDDD = a:x
6363 tlbl = newiTempLabel (NULL);
6364 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6366 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6368 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6370 emitcode ("anl", "a,#0x%02x",
6371 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6373 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6375 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6377 emitcode ("anl", "a,#0x%02x",
6378 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6380 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6382 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6384 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6386 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6387 emitcode ("orl", "a,#0x%02x",
6388 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6390 emitcode ("", "%05d$:", tlbl->key + 100);
6391 break; // SSSSAAAA:BBBCCCCC
6393 case 6: // AABBBBBB:CCDDDDDD
6395 tlbl = newiTempLabel (NULL);
6396 emitcode ("mov", "c,acc.7");
6397 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6399 emitcode ("mov", "c,acc.7");
6400 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6402 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6404 emitcode ("anl", "a,#0x%02x",
6405 SRMask[shCount]); // 000000AA:BBBBBBCC
6407 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6408 emitcode ("orl", "a,#0x%02x",
6409 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6411 emitcode ("", "%05d$:", tlbl->key + 100);
6413 case 7: // ABBBBBBB:CDDDDDDD
6415 tlbl = newiTempLabel (NULL);
6416 emitcode ("mov", "c,acc.7"); // c = A
6418 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6420 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6422 emitcode ("anl", "a,#0x%02x",
6423 SRMask[shCount]); // 0000000A:BBBBBBBC
6425 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6426 emitcode ("orl", "a,#0x%02x",
6427 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6429 emitcode ("", "%05d$:", tlbl->key + 100);
6436 /*-----------------------------------------------------------------*/
6437 /* shiftL2Left2Result - shift left two bytes from left to result */
6438 /*-----------------------------------------------------------------*/
6440 shiftL2Left2Result (operand * left, int offl,
6441 operand * result, int offr, int shCount)
6443 if (sameRegs (AOP (result), AOP (left)) &&
6444 ((offl + MSB16) == offr))
6446 /* don't crash result[offr] */
6447 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6448 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6452 movLeft2Result (left, offl, result, offr, 0);
6453 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6455 /* ax << shCount (x = lsb(result)) */
6456 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6457 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6461 /*-----------------------------------------------------------------*/
6462 /* shiftR2Left2Result - shift right two bytes from left to result */
6463 /*-----------------------------------------------------------------*/
6465 shiftR2Left2Result (operand * left, int offl,
6466 operand * result, int offr,
6467 int shCount, int sign)
6469 if (sameRegs (AOP (result), AOP (left)) &&
6470 ((offl + MSB16) == offr))
6472 /* don't crash result[offr] */
6473 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6474 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6478 movLeft2Result (left, offl, result, offr, 0);
6479 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6481 /* a:x >> shCount (x = lsb(result)) */
6483 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6485 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6486 if (getDataSize (result) > 1)
6487 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6490 /*-----------------------------------------------------------------*/
6491 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6492 /*-----------------------------------------------------------------*/
6494 shiftLLeftOrResult (operand * left, int offl,
6495 operand * result, int offr, int shCount)
6497 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6498 /* shift left accumulator */
6500 /* or with result */
6501 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6502 /* back to result */
6503 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6506 /*-----------------------------------------------------------------*/
6507 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6508 /*-----------------------------------------------------------------*/
6510 shiftRLeftOrResult (operand * left, int offl,
6511 operand * result, int offr, int shCount)
6513 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6514 /* shift right accumulator */
6516 /* or with result */
6517 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6518 /* back to result */
6519 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6522 /*-----------------------------------------------------------------*/
6523 /* genlshOne - left shift a one byte quantity by known count */
6524 /*-----------------------------------------------------------------*/
6526 genlshOne (operand * result, operand * left, int shCount)
6528 D(emitcode ("; genlshOne",""));
6530 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6533 /*-----------------------------------------------------------------*/
6534 /* genlshTwo - left shift two bytes by known amount != 0 */
6535 /*-----------------------------------------------------------------*/
6537 genlshTwo (operand * result, operand * left, int shCount)
6541 D(emitcode ("; genlshTwo",""));
6543 size = getDataSize (result);
6545 /* if shCount >= 8 */
6553 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6555 movLeft2Result (left, LSB, result, MSB16, 0);
6557 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6560 /* 1 <= shCount <= 7 */
6564 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6566 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6570 /*-----------------------------------------------------------------*/
6571 /* shiftLLong - shift left one long from left to result */
6572 /* offl = LSB or MSB16 */
6573 /*-----------------------------------------------------------------*/
6575 shiftLLong (operand * left, operand * result, int offr)
6578 int size = AOP_SIZE (result);
6580 if (size >= LSB + offr)
6582 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6584 emitcode ("add", "a,acc");
6585 if (sameRegs (AOP (left), AOP (result)) &&
6586 size >= MSB16 + offr && offr != LSB)
6587 emitcode ("xch", "a,%s",
6588 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6590 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6593 if (size >= MSB16 + offr)
6595 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6597 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6600 emitcode ("rlc", "a");
6601 if (sameRegs (AOP (left), AOP (result)) &&
6602 size >= MSB24 + offr && offr != LSB)
6603 emitcode ("xch", "a,%s",
6604 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6606 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6609 if (size >= MSB24 + offr)
6611 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6613 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6616 emitcode ("rlc", "a");
6617 if (sameRegs (AOP (left), AOP (result)) &&
6618 size >= MSB32 + offr && offr != LSB)
6619 emitcode ("xch", "a,%s",
6620 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6622 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6625 if (size > MSB32 + offr)
6627 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6629 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6632 emitcode ("rlc", "a");
6633 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6636 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6639 /*-----------------------------------------------------------------*/
6640 /* genlshFour - shift four byte by a known amount != 0 */
6641 /*-----------------------------------------------------------------*/
6643 genlshFour (operand * result, operand * left, int shCount)
6647 D(emitcode ("; genlshFour",""));
6649 size = AOP_SIZE (result);
6651 /* if shifting more that 3 bytes */
6656 /* lowest order of left goes to the highest
6657 order of the destination */
6658 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6660 movLeft2Result (left, LSB, result, MSB32, 0);
6661 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6662 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6663 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6667 /* more than two bytes */
6668 else if (shCount >= 16)
6670 /* lower order two bytes goes to higher order two bytes */
6672 /* if some more remaining */
6674 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6677 movLeft2Result (left, MSB16, result, MSB32, 0);
6678 movLeft2Result (left, LSB, result, MSB24, 0);
6680 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6681 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6685 /* if more than 1 byte */
6686 else if (shCount >= 8)
6688 /* lower order three bytes goes to higher order three bytes */
6693 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6695 movLeft2Result (left, LSB, result, MSB16, 0);
6701 movLeft2Result (left, MSB24, result, MSB32, 0);
6702 movLeft2Result (left, MSB16, result, MSB24, 0);
6703 movLeft2Result (left, LSB, result, MSB16, 0);
6704 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6706 else if (shCount == 1)
6707 shiftLLong (left, result, MSB16);
6710 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6711 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6712 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6713 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6718 /* 1 <= shCount <= 7 */
6719 else if (shCount <= 2)
6721 shiftLLong (left, result, LSB);
6723 shiftLLong (result, result, LSB);
6725 /* 3 <= shCount <= 7, optimize */
6728 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6729 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6730 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6734 /*-----------------------------------------------------------------*/
6735 /* genLeftShiftLiteral - left shifting by known count */
6736 /*-----------------------------------------------------------------*/
6738 genLeftShiftLiteral (operand * left,
6743 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6746 D(emitcode ("; genLeftShiftLiteral",""));
6748 freeAsmop (right, NULL, ic, TRUE);
6750 aopOp (left, ic, FALSE);
6751 aopOp (result, ic, FALSE);
6753 size = getSize (operandType (result));
6756 emitcode ("; shift left ", "result %d, left %d", size,
6760 /* I suppose that the left size >= result size */
6765 movLeft2Result (left, size, result, size, 0);
6769 else if (shCount >= (size * 8))
6771 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6777 genlshOne (result, left, shCount);
6781 genlshTwo (result, left, shCount);
6785 genlshFour (result, left, shCount);
6788 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6789 "*** ack! mystery literal shift!\n");
6793 freeAsmop (left, NULL, ic, TRUE);
6794 freeAsmop (result, NULL, ic, TRUE);
6797 /*-----------------------------------------------------------------*/
6798 /* genLeftShift - generates code for left shifting */
6799 /*-----------------------------------------------------------------*/
6801 genLeftShift (iCode * ic)
6803 operand *left, *right, *result;
6806 symbol *tlbl, *tlbl1;
6808 D(emitcode ("; genLeftShift",""));
6810 right = IC_RIGHT (ic);
6811 left = IC_LEFT (ic);
6812 result = IC_RESULT (ic);
6814 aopOp (right, ic, FALSE);
6816 /* if the shift count is known then do it
6817 as efficiently as possible */
6818 if (AOP_TYPE (right) == AOP_LIT)
6820 genLeftShiftLiteral (left, right, result, ic);
6824 /* shift count is unknown then we have to form
6825 a loop get the loop count in B : Note: we take
6826 only the lower order byte since shifting
6827 more that 32 bits make no sense anyway, ( the
6828 largest size of an object can be only 32 bits ) */
6830 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6831 emitcode ("inc", "b");
6832 freeAsmop (right, NULL, ic, TRUE);
6833 aopOp (left, ic, FALSE);
6834 aopOp (result, ic, FALSE);
6836 /* now move the left to the result if they are not the
6838 if (!sameRegs (AOP (left), AOP (result)) &&
6839 AOP_SIZE (result) > 1)
6842 size = AOP_SIZE (result);
6846 l = aopGet (AOP (left), offset, FALSE, TRUE);
6847 if (*l == '@' && (IS_AOP_PREG (result)))
6850 emitcode ("mov", "a,%s", l);
6851 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6854 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6859 tlbl = newiTempLabel (NULL);
6860 size = AOP_SIZE (result);
6862 tlbl1 = newiTempLabel (NULL);
6864 /* if it is only one byte then */
6867 symbol *tlbl1 = newiTempLabel (NULL);
6869 l = aopGet (AOP (left), 0, FALSE, FALSE);
6871 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6872 emitcode ("", "%05d$:", tlbl->key + 100);
6873 emitcode ("add", "a,acc");
6874 emitcode ("", "%05d$:", tlbl1->key + 100);
6875 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6876 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6880 reAdjustPreg (AOP (result));
6882 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6883 emitcode ("", "%05d$:", tlbl->key + 100);
6884 l = aopGet (AOP (result), offset, FALSE, FALSE);
6886 emitcode ("add", "a,acc");
6887 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6890 l = aopGet (AOP (result), offset, FALSE, FALSE);
6892 emitcode ("rlc", "a");
6893 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6895 reAdjustPreg (AOP (result));
6897 emitcode ("", "%05d$:", tlbl1->key + 100);
6898 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6900 freeAsmop (left, NULL, ic, TRUE);
6901 freeAsmop (result, NULL, ic, TRUE);
6904 /*-----------------------------------------------------------------*/
6905 /* genrshOne - right shift a one byte quantity by known count */
6906 /*-----------------------------------------------------------------*/
6908 genrshOne (operand * result, operand * left,
6909 int shCount, int sign)
6911 D(emitcode ("; genrshOne",""));
6913 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6916 /*-----------------------------------------------------------------*/
6917 /* genrshTwo - right shift two bytes by known amount != 0 */
6918 /*-----------------------------------------------------------------*/
6920 genrshTwo (operand * result, operand * left,
6921 int shCount, int sign)
6923 D(emitcode ("; genrshTwo",""));
6925 /* if shCount >= 8 */
6930 shiftR1Left2Result (left, MSB16, result, LSB,
6933 movLeft2Result (left, MSB16, result, LSB, sign);
6934 addSign (result, MSB16, sign);
6937 /* 1 <= shCount <= 7 */
6939 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6942 /*-----------------------------------------------------------------*/
6943 /* shiftRLong - shift right one long from left to result */
6944 /* offl = LSB or MSB16 */
6945 /*-----------------------------------------------------------------*/
6947 shiftRLong (operand * left, int offl,
6948 operand * result, int sign)
6950 int isSameRegs=sameRegs(AOP(left),AOP(result));
6952 if (isSameRegs && offl>1) {
6953 // we are in big trouble, but this shouldn't happen
6954 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6957 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6962 emitcode ("rlc", "a");
6963 emitcode ("subb", "a,acc");
6965 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6967 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6968 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6971 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6976 emitcode ("clr", "c");
6978 emitcode ("mov", "c,acc.7");
6981 emitcode ("rrc", "a");
6983 if (isSameRegs && offl==MSB16) {
6984 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6986 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6987 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6990 emitcode ("rrc", "a");
6991 if (isSameRegs && offl==1) {
6992 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6994 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6995 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6997 emitcode ("rrc", "a");
6998 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7002 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7003 emitcode ("rrc", "a");
7004 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7008 /*-----------------------------------------------------------------*/
7009 /* genrshFour - shift four byte by a known amount != 0 */
7010 /*-----------------------------------------------------------------*/
7012 genrshFour (operand * result, operand * left,
7013 int shCount, int sign)
7015 D(emitcode ("; genrshFour",""));
7017 /* if shifting more that 3 bytes */
7022 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7024 movLeft2Result (left, MSB32, result, LSB, sign);
7025 addSign (result, MSB16, sign);
7027 else if (shCount >= 16)
7031 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7034 movLeft2Result (left, MSB24, result, LSB, 0);
7035 movLeft2Result (left, MSB32, result, MSB16, sign);
7037 addSign (result, MSB24, sign);
7039 else if (shCount >= 8)
7043 shiftRLong (left, MSB16, result, sign);
7044 else if (shCount == 0)
7046 movLeft2Result (left, MSB16, result, LSB, 0);
7047 movLeft2Result (left, MSB24, result, MSB16, 0);
7048 movLeft2Result (left, MSB32, result, MSB24, sign);
7049 addSign (result, MSB32, sign);
7053 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7054 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7055 /* the last shift is signed */
7056 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7057 addSign (result, MSB32, sign);
7061 { /* 1 <= shCount <= 7 */
7064 shiftRLong (left, LSB, result, sign);
7066 shiftRLong (result, LSB, result, sign);
7070 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7071 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7072 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7077 /*-----------------------------------------------------------------*/
7078 /* genRightShiftLiteral - right shifting by known count */
7079 /*-----------------------------------------------------------------*/
7081 genRightShiftLiteral (operand * left,
7087 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7090 D(emitcode ("; genRightShiftLiteral",""));
7092 freeAsmop (right, NULL, ic, TRUE);
7094 aopOp (left, ic, FALSE);
7095 aopOp (result, ic, FALSE);
7098 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7102 size = getDataSize (left);
7103 /* test the LEFT size !!! */
7105 /* I suppose that the left size >= result size */
7108 size = getDataSize (result);
7110 movLeft2Result (left, size, result, size, 0);
7113 else if (shCount >= (size * 8))
7116 /* get sign in acc.7 */
7117 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7119 addSign (result, LSB, sign);
7126 genrshOne (result, left, shCount, sign);
7130 genrshTwo (result, left, shCount, sign);
7134 genrshFour (result, left, shCount, sign);
7140 freeAsmop (left, NULL, ic, TRUE);
7141 freeAsmop (result, NULL, ic, TRUE);
7144 /*-----------------------------------------------------------------*/
7145 /* genSignedRightShift - right shift of signed number */
7146 /*-----------------------------------------------------------------*/
7148 genSignedRightShift (iCode * ic)
7150 operand *right, *left, *result;
7153 symbol *tlbl, *tlbl1;
7155 D(emitcode ("; genSignedRightShift",""));
7157 /* we do it the hard way put the shift count in b
7158 and loop thru preserving the sign */
7160 right = IC_RIGHT (ic);
7161 left = IC_LEFT (ic);
7162 result = IC_RESULT (ic);
7164 aopOp (right, ic, FALSE);
7167 if (AOP_TYPE (right) == AOP_LIT)
7169 genRightShiftLiteral (left, right, result, ic, 1);
7172 /* shift count is unknown then we have to form
7173 a loop get the loop count in B : Note: we take
7174 only the lower order byte since shifting
7175 more that 32 bits make no sense anyway, ( the
7176 largest size of an object can be only 32 bits ) */
7178 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7179 emitcode ("inc", "b");
7180 freeAsmop (right, NULL, ic, TRUE);
7181 aopOp (left, ic, FALSE);
7182 aopOp (result, ic, FALSE);
7184 /* now move the left to the result if they are not the
7186 if (!sameRegs (AOP (left), AOP (result)) &&
7187 AOP_SIZE (result) > 1)
7190 size = AOP_SIZE (result);
7194 l = aopGet (AOP (left), offset, FALSE, TRUE);
7195 if (*l == '@' && IS_AOP_PREG (result))
7198 emitcode ("mov", "a,%s", l);
7199 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7202 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7207 /* mov the highest order bit to OVR */
7208 tlbl = newiTempLabel (NULL);
7209 tlbl1 = newiTempLabel (NULL);
7211 size = AOP_SIZE (result);
7213 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7214 emitcode ("rlc", "a");
7215 emitcode ("mov", "ov,c");
7216 /* if it is only one byte then */
7219 l = aopGet (AOP (left), 0, FALSE, FALSE);
7221 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7222 emitcode ("", "%05d$:", tlbl->key + 100);
7223 emitcode ("mov", "c,ov");
7224 emitcode ("rrc", "a");
7225 emitcode ("", "%05d$:", tlbl1->key + 100);
7226 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7227 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7231 reAdjustPreg (AOP (result));
7232 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7233 emitcode ("", "%05d$:", tlbl->key + 100);
7234 emitcode ("mov", "c,ov");
7237 l = aopGet (AOP (result), offset, FALSE, FALSE);
7239 emitcode ("rrc", "a");
7240 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7242 reAdjustPreg (AOP (result));
7243 emitcode ("", "%05d$:", tlbl1->key + 100);
7244 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7247 freeAsmop (left, NULL, ic, TRUE);
7248 freeAsmop (result, NULL, ic, TRUE);
7251 /*-----------------------------------------------------------------*/
7252 /* genRightShift - generate code for right shifting */
7253 /*-----------------------------------------------------------------*/
7255 genRightShift (iCode * ic)
7257 operand *right, *left, *result;
7261 symbol *tlbl, *tlbl1;
7263 D(emitcode ("; genRightShift",""));
7265 /* if signed then we do it the hard way preserve the
7266 sign bit moving it inwards */
7267 letype = getSpec (operandType (IC_LEFT (ic)));
7269 if (!SPEC_USIGN (letype))
7271 genSignedRightShift (ic);
7275 /* signed & unsigned types are treated the same : i.e. the
7276 signed is NOT propagated inwards : quoting from the
7277 ANSI - standard : "for E1 >> E2, is equivalent to division
7278 by 2**E2 if unsigned or if it has a non-negative value,
7279 otherwise the result is implementation defined ", MY definition
7280 is that the sign does not get propagated */
7282 right = IC_RIGHT (ic);
7283 left = IC_LEFT (ic);
7284 result = IC_RESULT (ic);
7286 aopOp (right, ic, FALSE);
7288 /* if the shift count is known then do it
7289 as efficiently as possible */
7290 if (AOP_TYPE (right) == AOP_LIT)
7292 genRightShiftLiteral (left, right, result, ic, 0);
7296 /* shift count is unknown then we have to form
7297 a loop get the loop count in B : Note: we take
7298 only the lower order byte since shifting
7299 more that 32 bits make no sense anyway, ( the
7300 largest size of an object can be only 32 bits ) */
7302 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7303 emitcode ("inc", "b");
7304 freeAsmop (right, NULL, ic, TRUE);
7305 aopOp (left, ic, FALSE);
7306 aopOp (result, ic, FALSE);
7308 /* now move the left to the result if they are not the
7310 if (!sameRegs (AOP (left), AOP (result)) &&
7311 AOP_SIZE (result) > 1)
7314 size = AOP_SIZE (result);
7318 l = aopGet (AOP (left), offset, FALSE, TRUE);
7319 if (*l == '@' && IS_AOP_PREG (result))
7322 emitcode ("mov", "a,%s", l);
7323 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7326 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7331 tlbl = newiTempLabel (NULL);
7332 tlbl1 = newiTempLabel (NULL);
7333 size = AOP_SIZE (result);
7336 /* if it is only one byte then */
7339 l = aopGet (AOP (left), 0, FALSE, FALSE);
7341 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7342 emitcode ("", "%05d$:", tlbl->key + 100);
7344 emitcode ("rrc", "a");
7345 emitcode ("", "%05d$:", tlbl1->key + 100);
7346 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7347 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7351 reAdjustPreg (AOP (result));
7352 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7353 emitcode ("", "%05d$:", tlbl->key + 100);
7357 l = aopGet (AOP (result), offset, FALSE, FALSE);
7359 emitcode ("rrc", "a");
7360 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7362 reAdjustPreg (AOP (result));
7364 emitcode ("", "%05d$:", tlbl1->key + 100);
7365 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7368 freeAsmop (left, NULL, ic, TRUE);
7369 freeAsmop (result, NULL, ic, TRUE);
7372 /*-----------------------------------------------------------------*/
7373 /* emitPtrByteGet - emits code to get a byte into A through a */
7374 /* pointer register (R0, R1, or DPTR). The */
7375 /* original value of A can be preserved in B. */
7376 /*-----------------------------------------------------------------*/
7378 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7385 emitcode ("mov", "b,a");
7386 emitcode ("mov", "a,@%s", rname);
7391 emitcode ("mov", "b,a");
7392 emitcode ("movx", "a,@%s", rname);
7397 emitcode ("mov", "b,a");
7398 emitcode ("movx", "a,@dptr");
7403 emitcode ("mov", "b,a");
7404 emitcode ("clr", "a");
7405 emitcode ("movc", "a,@a+dptr");
7411 emitcode ("push", "b");
7412 emitcode ("push", "acc");
7414 emitcode ("lcall", "__gptrget");
7416 emitcode ("pop", "b");
7421 /*-----------------------------------------------------------------*/
7422 /* emitPtrByteSet - emits code to set a byte from src through a */
7423 /* pointer register (R0, R1, or DPTR). */
7424 /*-----------------------------------------------------------------*/
7426 emitPtrByteSet (char *rname, int p_type, char *src)
7435 emitcode ("mov", "@%s,a", rname);
7438 emitcode ("mov", "@%s,%s", rname, src);
7443 emitcode ("movx", "@%s,a", rname);
7448 emitcode ("movx", "@dptr,a");
7453 emitcode ("lcall", "__gptrput");
7458 /*-----------------------------------------------------------------*/
7459 /* genUnpackBits - generates code for unpacking bits */
7460 /*-----------------------------------------------------------------*/
7462 genUnpackBits (operand * result, char *rname, int ptype)
7464 int offset = 0; /* result byte offset */
7465 int rsize; /* result size */
7466 int rlen = 0; /* remaining bitfield length */
7467 sym_link *etype; /* bitfield type information */
7468 int blen; /* bitfield length */
7469 int bstr; /* bitfield starting bit within byte */
7471 D(emitcode ("; genUnpackBits",""));
7473 etype = getSpec (operandType (result));
7474 rsize = getSize (operandType (result));
7475 blen = SPEC_BLEN (etype);
7476 bstr = SPEC_BSTR (etype);
7478 /* If the bitfield length is less than a byte */
7481 emitPtrByteGet (rname, ptype, FALSE);
7483 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7484 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7488 /* Bit field did not fit in a byte. Copy all
7489 but the partial byte at the end. */
7490 for (rlen=blen;rlen>=8;rlen-=8)
7492 emitPtrByteGet (rname, ptype, FALSE);
7493 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7495 emitcode ("inc", "%s", rname);
7498 /* Handle the partial byte at the end */
7501 emitPtrByteGet (rname, ptype, FALSE);
7502 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7503 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7511 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7516 /*-----------------------------------------------------------------*/
7517 /* genDataPointerGet - generates code when ptr offset is known */
7518 /*-----------------------------------------------------------------*/
7520 genDataPointerGet (operand * left,
7526 int size, offset = 0;
7528 D(emitcode ("; genDataPointerGet",""));
7530 aopOp (result, ic, TRUE);
7532 /* get the string representation of the name */
7533 l = aopGet (AOP (left), 0, FALSE, TRUE);
7534 size = AOP_SIZE (result);
7538 sprintf (buffer, "(%s + %d)", l + 1, offset);
7540 sprintf (buffer, "%s", l + 1);
7541 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7544 freeAsmop (left, NULL, ic, TRUE);
7545 freeAsmop (result, NULL, ic, TRUE);
7548 /*-----------------------------------------------------------------*/
7549 /* genNearPointerGet - emitcode for near pointer fetch */
7550 /*-----------------------------------------------------------------*/
7552 genNearPointerGet (operand * left,
7560 sym_link *rtype, *retype;
7561 sym_link *ltype = operandType (left);
7564 D(emitcode ("; genNearPointerGet",""));
7566 rtype = operandType (result);
7567 retype = getSpec (rtype);
7569 aopOp (left, ic, FALSE);
7571 /* if left is rematerialisable and
7572 result is not bit variable type and
7573 the left is pointer to data space i.e
7574 lower 128 bytes of space */
7575 if (AOP_TYPE (left) == AOP_IMMD &&
7576 !IS_BITVAR (retype) &&
7577 DCL_TYPE (ltype) == POINTER)
7579 genDataPointerGet (left, result, ic);
7583 /* if the value is already in a pointer register
7584 then don't need anything more */
7585 if (!AOP_INPREG (AOP (left)))
7587 if (IS_AOP_PREG (left))
7589 // Aha, it is a pointer, just in disguise.
7590 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7593 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7594 __FILE__, __LINE__);
7599 emitcode ("mov", "a%s,%s", rname + 1, rname);
7600 rname++; // skip the '@'.
7605 /* otherwise get a free pointer register */
7607 preg = getFreePtr (ic, &aop, FALSE);
7608 emitcode ("mov", "%s,%s",
7610 aopGet (AOP (left), 0, FALSE, TRUE));
7615 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7617 //aopOp (result, ic, FALSE);
7618 aopOp (result, ic, result?TRUE:FALSE);
7620 /* if bitfield then unpack the bits */
7621 if (IS_BITVAR (retype))
7622 genUnpackBits (result, rname, POINTER);
7625 /* we have can just get the values */
7626 int size = AOP_SIZE (result);
7631 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7634 emitcode ("mov", "a,@%s", rname);
7635 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7639 sprintf (buffer, "@%s", rname);
7640 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7644 emitcode ("inc", "%s", rname);
7648 /* now some housekeeping stuff */
7649 if (aop) /* we had to allocate for this iCode */
7651 if (pi) { /* post increment present */
7652 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7654 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7658 /* we did not allocate which means left
7659 already in a pointer register, then
7660 if size > 0 && this could be used again
7661 we have to point it back to where it
7663 if ((AOP_SIZE (result) > 1 &&
7664 !OP_SYMBOL (left)->remat &&
7665 (OP_SYMBOL (left)->liveTo > ic->seq ||
7669 int size = AOP_SIZE (result) - 1;
7671 emitcode ("dec", "%s", rname);
7676 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7677 freeAsmop (left, NULL, ic, TRUE);
7678 if (pi) pi->generated = 1;
7681 /*-----------------------------------------------------------------*/
7682 /* genPagedPointerGet - emitcode for paged pointer fetch */
7683 /*-----------------------------------------------------------------*/
7685 genPagedPointerGet (operand * left,
7693 sym_link *rtype, *retype;
7695 D(emitcode ("; genPagedPointerGet",""));
7697 rtype = operandType (result);
7698 retype = getSpec (rtype);
7700 aopOp (left, ic, FALSE);
7702 /* if the value is already in a pointer register
7703 then don't need anything more */
7704 if (!AOP_INPREG (AOP (left)))
7706 /* otherwise get a free pointer register */
7708 preg = getFreePtr (ic, &aop, FALSE);
7709 emitcode ("mov", "%s,%s",
7711 aopGet (AOP (left), 0, FALSE, TRUE));
7715 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7717 aopOp (result, ic, FALSE);
7719 /* if bitfield then unpack the bits */
7720 if (IS_BITVAR (retype))
7721 genUnpackBits (result, rname, PPOINTER);
7724 /* we have can just get the values */
7725 int size = AOP_SIZE (result);
7731 emitcode ("movx", "a,@%s", rname);
7732 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7737 emitcode ("inc", "%s", rname);
7741 /* now some housekeeping stuff */
7742 if (aop) /* we had to allocate for this iCode */
7744 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7745 freeAsmop (NULL, aop, ic, TRUE);
7749 /* we did not allocate which means left
7750 already in a pointer register, then
7751 if size > 0 && this could be used again
7752 we have to point it back to where it
7754 if ((AOP_SIZE (result) > 1 &&
7755 !OP_SYMBOL (left)->remat &&
7756 (OP_SYMBOL (left)->liveTo > ic->seq ||
7760 int size = AOP_SIZE (result) - 1;
7762 emitcode ("dec", "%s", rname);
7767 freeAsmop (left, NULL, ic, TRUE);
7768 freeAsmop (result, NULL, ic, TRUE);
7769 if (pi) pi->generated = 1;
7773 /*--------------------------------------------------------------------*/
7774 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7775 /*--------------------------------------------------------------------*/
7777 loadDptrFromOperand (operand *op, bool loadBToo)
7779 if (AOP_TYPE (op) != AOP_STR)
7781 /* if this is remateriazable */
7782 if (AOP_TYPE (op) == AOP_IMMD)
7784 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7787 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7788 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7791 wassertl(FALSE, "need pointerCode");
7792 emitcode ("", "; mov b,???");
7793 /* genPointerGet and genPointerSet originally did different
7794 ** things for this case. Both seem wrong.
7795 ** from genPointerGet:
7796 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7797 ** from genPointerSet:
7798 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7803 else if (AOP_TYPE (op) == AOP_DPTR)
7807 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7808 emitcode ("push", "acc");
7809 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7810 emitcode ("push", "acc");
7811 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7812 emitcode ("pop", "dph");
7813 emitcode ("pop", "dpl");
7817 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7818 emitcode ("push", "acc");
7819 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7820 emitcode ("pop", "dpl");
7824 { /* we need to get it byte by byte */
7825 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7826 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7828 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7833 /*-----------------------------------------------------------------*/
7834 /* genFarPointerGet - gget value from far space */
7835 /*-----------------------------------------------------------------*/
7837 genFarPointerGet (operand * left,
7838 operand * result, iCode * ic, iCode * pi)
7841 sym_link *retype = getSpec (operandType (result));
7843 D(emitcode ("; genFarPointerGet",""));
7845 aopOp (left, ic, FALSE);
7846 loadDptrFromOperand (left, FALSE);
7848 /* so dptr now contains the address */
7849 aopOp (result, ic, FALSE);
7851 /* if bit then unpack */
7852 if (IS_BITVAR (retype))
7853 genUnpackBits (result, "dptr", FPOINTER);
7856 size = AOP_SIZE (result);
7861 emitcode ("movx", "a,@dptr");
7862 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7864 emitcode ("inc", "dptr");
7868 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7869 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7870 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7873 freeAsmop (left, NULL, ic, TRUE);
7874 freeAsmop (result, NULL, ic, TRUE);
7877 /*-----------------------------------------------------------------*/
7878 /* genCodePointerGet - gget value from code space */
7879 /*-----------------------------------------------------------------*/
7881 genCodePointerGet (operand * left,
7882 operand * result, iCode * ic, iCode *pi)
7885 sym_link *retype = getSpec (operandType (result));
7887 D(emitcode ("; genCodePointerGet",""));
7889 aopOp (left, ic, FALSE);
7890 loadDptrFromOperand (left, FALSE);
7892 /* so dptr now contains the address */
7893 aopOp (result, ic, FALSE);
7895 /* if bit then unpack */
7896 if (IS_BITVAR (retype))
7897 genUnpackBits (result, "dptr", CPOINTER);
7900 size = AOP_SIZE (result);
7907 emitcode ("clr", "a");
7908 emitcode ("movc", "a,@a+dptr");
7909 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7910 emitcode ("inc", "dptr");
7914 emitcode ("mov", "a,#0x%02x", offset);
7915 emitcode ("movc", "a,@a+dptr");
7916 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7921 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7922 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7923 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7926 freeAsmop (left, NULL, ic, TRUE);
7927 freeAsmop (result, NULL, ic, TRUE);
7930 /*-----------------------------------------------------------------*/
7931 /* genGenPointerGet - gget value from generic pointer space */
7932 /*-----------------------------------------------------------------*/
7934 genGenPointerGet (operand * left,
7935 operand * result, iCode * ic, iCode *pi)
7938 sym_link *retype = getSpec (operandType (result));
7940 D(emitcode ("; genGenPointerGet",""));
7942 aopOp (left, ic, FALSE);
7943 loadDptrFromOperand (left, TRUE);
7945 /* so dptr know contains the address */
7946 aopOp (result, ic, FALSE);
7948 /* if bit then unpack */
7949 if (IS_BITVAR (retype))
7950 genUnpackBits (result, "dptr", GPOINTER);
7953 size = AOP_SIZE (result);
7958 emitcode ("lcall", "__gptrget");
7959 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7961 emitcode ("inc", "dptr");
7965 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7966 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7967 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7970 freeAsmop (left, NULL, ic, TRUE);
7971 freeAsmop (result, NULL, ic, TRUE);
7974 /*-----------------------------------------------------------------*/
7975 /* genPointerGet - generate code for pointer get */
7976 /*-----------------------------------------------------------------*/
7978 genPointerGet (iCode * ic, iCode *pi)
7980 operand *left, *result;
7981 sym_link *type, *etype;
7984 D(emitcode ("; genPointerGet",""));
7986 left = IC_LEFT (ic);
7987 result = IC_RESULT (ic);
7989 /* depending on the type of pointer we need to
7990 move it to the correct pointer register */
7991 type = operandType (left);
7992 etype = getSpec (type);
7993 /* if left is of type of pointer then it is simple */
7994 if (IS_PTR (type) && !IS_FUNC (type->next))
7995 p_type = DCL_TYPE (type);
7998 /* we have to go by the storage class */
7999 p_type = PTR_TYPE (SPEC_OCLS (etype));
8002 /* special case when cast remat */
8003 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8004 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8005 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8006 type = operandType (left);
8007 p_type = DCL_TYPE (type);
8009 /* now that we have the pointer type we assign
8010 the pointer values */
8016 genNearPointerGet (left, result, ic, pi);
8020 genPagedPointerGet (left, result, ic, pi);
8024 genFarPointerGet (left, result, ic, pi);
8028 genCodePointerGet (left, result, ic, pi);
8032 genGenPointerGet (left, result, ic, pi);
8040 /*-----------------------------------------------------------------*/
8041 /* genPackBits - generates code for packed bit storage */
8042 /*-----------------------------------------------------------------*/
8044 genPackBits (sym_link * etype,
8046 char *rname, int p_type)
8048 int offset = 0; /* source byte offset */
8049 int rlen = 0; /* remaining bitfield length */
8050 int blen; /* bitfield length */
8051 int bstr; /* bitfield starting bit within byte */
8052 int litval; /* source literal value (if AOP_LIT) */
8053 unsigned char mask; /* bitmask within current byte */
8055 D(emitcode ("; genPackBits",""));
8057 blen = SPEC_BLEN (etype);
8058 bstr = SPEC_BSTR (etype);
8060 /* If the bitfield length is less than a byte */
8063 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8064 (unsigned char) (0xFF >> (8 - bstr)));
8066 if (AOP_TYPE (right) == AOP_LIT)
8068 /* Case with a bitfield length <8 and literal source
8070 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8072 litval &= (~mask) & 0xff;
8073 emitPtrByteGet (rname, p_type, FALSE);
8074 if ((mask|litval)!=0xff)
8075 emitcode ("anl","a,#0x%02x", mask);
8077 emitcode ("orl","a,#0x%02x", litval);
8081 if ((blen==1) && (p_type!=GPOINTER))
8083 /* Case with a bitfield length == 1 and no generic pointer
8085 if (AOP_TYPE (right) == AOP_CRY)
8086 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8089 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8090 emitcode ("rrc","a");
8092 emitPtrByteGet (rname, p_type, FALSE);
8093 emitcode ("mov","acc.%d,c",bstr);
8097 /* Case with a bitfield length < 8 and arbitrary source
8099 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8100 /* shift and mask source value */
8102 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8104 /* transfer A to B and get next byte */
8105 emitPtrByteGet (rname, p_type, TRUE);
8107 emitcode ("anl", "a,#0x%02x", mask);
8108 emitcode ("orl", "a,b");
8109 if (p_type == GPOINTER)
8110 emitcode ("pop", "b");
8114 emitPtrByteSet (rname, p_type, "a");
8118 /* Bit length is greater than 7 bits. In this case, copy */
8119 /* all except the partial byte at the end */
8120 for (rlen=blen;rlen>=8;rlen-=8)
8122 emitPtrByteSet (rname, p_type,
8123 aopGet (AOP (right), offset++, FALSE, TRUE) );
8125 emitcode ("inc", "%s", rname);
8128 /* If there was a partial byte at the end */
8131 mask = (((unsigned char) -1 << rlen) & 0xff);
8133 if (AOP_TYPE (right) == AOP_LIT)
8135 /* Case with partial byte and literal source
8137 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8138 litval >>= (blen-rlen);
8139 litval &= (~mask) & 0xff;
8140 emitPtrByteGet (rname, p_type, FALSE);
8141 if ((mask|litval)!=0xff)
8142 emitcode ("anl","a,#0x%02x", mask);
8144 emitcode ("orl","a,#0x%02x", litval);
8148 /* Case with partial byte and arbitrary source
8150 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8151 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8153 /* transfer A to B and get next byte */
8154 emitPtrByteGet (rname, p_type, TRUE);
8156 emitcode ("anl", "a,#0x%02x", mask);
8157 emitcode ("orl", "a,b");
8158 if (p_type == GPOINTER)
8159 emitcode ("pop", "b");
8161 emitPtrByteSet (rname, p_type, "a");
8167 /*-----------------------------------------------------------------*/
8168 /* genDataPointerSet - remat pointer to data space */
8169 /*-----------------------------------------------------------------*/
8171 genDataPointerSet (operand * right,
8175 int size, offset = 0;
8176 char *l, buffer[256];
8178 D(emitcode ("; genDataPointerSet",""));
8180 aopOp (right, ic, FALSE);
8182 l = aopGet (AOP (result), 0, FALSE, TRUE);
8183 size = AOP_SIZE (right);
8187 sprintf (buffer, "(%s + %d)", l + 1, offset);
8189 sprintf (buffer, "%s", l + 1);
8190 emitcode ("mov", "%s,%s", buffer,
8191 aopGet (AOP (right), offset++, FALSE, FALSE));
8194 freeAsmop (right, NULL, ic, TRUE);
8195 freeAsmop (result, NULL, ic, TRUE);
8198 /*-----------------------------------------------------------------*/
8199 /* genNearPointerSet - emitcode for near pointer put */
8200 /*-----------------------------------------------------------------*/
8202 genNearPointerSet (operand * right,
8210 sym_link *retype, *letype;
8211 sym_link *ptype = operandType (result);
8213 D(emitcode ("; genNearPointerSet",""));
8215 retype = getSpec (operandType (right));
8216 letype = getSpec (ptype);
8217 aopOp (result, ic, FALSE);
8219 /* if the result is rematerializable &
8220 in data space & not a bit variable */
8221 if (AOP_TYPE (result) == AOP_IMMD &&
8222 DCL_TYPE (ptype) == POINTER &&
8223 !IS_BITVAR (retype) &&
8224 !IS_BITVAR (letype))
8226 genDataPointerSet (right, result, ic);
8230 /* if the value is already in a pointer register
8231 then don't need anything more */
8232 if (!AOP_INPREG (AOP (result)))
8235 //AOP_TYPE (result) == AOP_STK
8239 // Aha, it is a pointer, just in disguise.
8240 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8243 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8244 __FILE__, __LINE__);
8249 emitcode ("mov", "a%s,%s", rname + 1, rname);
8250 rname++; // skip the '@'.
8255 /* otherwise get a free pointer register */
8257 preg = getFreePtr (ic, &aop, FALSE);
8258 emitcode ("mov", "%s,%s",
8260 aopGet (AOP (result), 0, FALSE, TRUE));
8266 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8269 aopOp (right, ic, FALSE);
8271 /* if bitfield then unpack the bits */
8272 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8273 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8276 /* we have can just get the values */
8277 int size = AOP_SIZE (right);
8282 l = aopGet (AOP (right), offset, FALSE, TRUE);
8286 emitcode ("mov", "@%s,a", rname);
8289 emitcode ("mov", "@%s,%s", rname, l);
8291 emitcode ("inc", "%s", rname);
8296 /* now some housekeeping stuff */
8297 if (aop) /* we had to allocate for this iCode */
8300 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8301 freeAsmop (NULL, aop, ic, TRUE);
8305 /* we did not allocate which means left
8306 already in a pointer register, then
8307 if size > 0 && this could be used again
8308 we have to point it back to where it
8310 if ((AOP_SIZE (right) > 1 &&
8311 !OP_SYMBOL (result)->remat &&
8312 (OP_SYMBOL (result)->liveTo > ic->seq ||
8316 int size = AOP_SIZE (right) - 1;
8318 emitcode ("dec", "%s", rname);
8323 if (pi) pi->generated = 1;
8324 freeAsmop (result, NULL, ic, TRUE);
8325 freeAsmop (right, NULL, ic, TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genPagedPointerSet - emitcode for Paged pointer put */
8330 /*-----------------------------------------------------------------*/
8332 genPagedPointerSet (operand * right,
8340 sym_link *retype, *letype;
8342 D(emitcode ("; genPagedPointerSet",""));
8344 retype = getSpec (operandType (right));
8345 letype = getSpec (operandType (result));
8347 aopOp (result, ic, FALSE);
8349 /* if the value is already in a pointer register
8350 then don't need anything more */
8351 if (!AOP_INPREG (AOP (result)))
8353 /* otherwise get a free pointer register */
8355 preg = getFreePtr (ic, &aop, FALSE);
8356 emitcode ("mov", "%s,%s",
8358 aopGet (AOP (result), 0, FALSE, TRUE));
8362 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8364 aopOp (right, ic, FALSE);
8366 /* if bitfield then unpack the bits */
8367 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8368 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8371 /* we have can just get the values */
8372 int size = AOP_SIZE (right);
8377 l = aopGet (AOP (right), offset, FALSE, TRUE);
8380 emitcode ("movx", "@%s,a", rname);
8383 emitcode ("inc", "%s", rname);
8389 /* now some housekeeping stuff */
8390 if (aop) /* we had to allocate for this iCode */
8393 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8394 freeAsmop (NULL, aop, ic, TRUE);
8398 /* we did not allocate which means left
8399 already in a pointer register, then
8400 if size > 0 && this could be used again
8401 we have to point it back to where it
8403 if (AOP_SIZE (right) > 1 &&
8404 !OP_SYMBOL (result)->remat &&
8405 (OP_SYMBOL (result)->liveTo > ic->seq ||
8408 int size = AOP_SIZE (right) - 1;
8410 emitcode ("dec", "%s", rname);
8415 if (pi) pi->generated = 1;
8416 freeAsmop (result, NULL, ic, TRUE);
8417 freeAsmop (right, NULL, ic, TRUE);
8422 /*-----------------------------------------------------------------*/
8423 /* genFarPointerSet - set value from far space */
8424 /*-----------------------------------------------------------------*/
8426 genFarPointerSet (operand * right,
8427 operand * result, iCode * ic, iCode * pi)
8430 sym_link *retype = getSpec (operandType (right));
8431 sym_link *letype = getSpec (operandType (result));
8433 D(emitcode ("; genFarPointerSet",""));
8435 aopOp (result, ic, FALSE);
8436 loadDptrFromOperand (result, FALSE);
8438 /* so dptr know contains the address */
8439 aopOp (right, ic, FALSE);
8441 /* if bit then unpack */
8442 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8443 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8446 size = AOP_SIZE (right);
8451 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8453 emitcode ("movx", "@dptr,a");
8455 emitcode ("inc", "dptr");
8458 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8459 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8460 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8463 freeAsmop (result, NULL, ic, TRUE);
8464 freeAsmop (right, NULL, ic, TRUE);
8467 /*-----------------------------------------------------------------*/
8468 /* genGenPointerSet - set value from generic pointer space */
8469 /*-----------------------------------------------------------------*/
8471 genGenPointerSet (operand * right,
8472 operand * result, iCode * ic, iCode * pi)
8475 sym_link *retype = getSpec (operandType (right));
8476 sym_link *letype = getSpec (operandType (result));
8478 D(emitcode ("; genGenPointerSet",""));
8480 aopOp (result, ic, FALSE);
8481 loadDptrFromOperand (result, TRUE);
8483 /* so dptr know contains the address */
8484 aopOp (right, ic, FALSE);
8486 /* if bit then unpack */
8487 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8488 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8491 size = AOP_SIZE (right);
8496 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8498 emitcode ("lcall", "__gptrput");
8500 emitcode ("inc", "dptr");
8504 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8505 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8506 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8509 freeAsmop (result, NULL, ic, TRUE);
8510 freeAsmop (right, NULL, ic, TRUE);
8513 /*-----------------------------------------------------------------*/
8514 /* genPointerSet - stores the value into a pointer location */
8515 /*-----------------------------------------------------------------*/
8517 genPointerSet (iCode * ic, iCode *pi)
8519 operand *right, *result;
8520 sym_link *type, *etype;
8523 D(emitcode ("; genPointerSet",""));
8525 right = IC_RIGHT (ic);
8526 result = IC_RESULT (ic);
8528 /* depending on the type of pointer we need to
8529 move it to the correct pointer register */
8530 type = operandType (result);
8531 etype = getSpec (type);
8532 /* if left is of type of pointer then it is simple */
8533 if (IS_PTR (type) && !IS_FUNC (type->next))
8535 p_type = DCL_TYPE (type);
8539 /* we have to go by the storage class */
8540 p_type = PTR_TYPE (SPEC_OCLS (etype));
8543 /* special case when cast remat */
8544 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8545 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8546 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8547 type = operandType (result);
8548 p_type = DCL_TYPE (type);
8550 /* now that we have the pointer type we assign
8551 the pointer values */
8557 genNearPointerSet (right, result, ic, pi);
8561 genPagedPointerSet (right, result, ic, pi);
8565 genFarPointerSet (right, result, ic, pi);
8569 genGenPointerSet (right, result, ic, pi);
8573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8574 "genPointerSet: illegal pointer type");
8579 /*-----------------------------------------------------------------*/
8580 /* genIfx - generate code for Ifx statement */
8581 /*-----------------------------------------------------------------*/
8583 genIfx (iCode * ic, iCode * popIc)
8585 operand *cond = IC_COND (ic);
8588 D(emitcode ("; genIfx",""));
8590 aopOp (cond, ic, FALSE);
8592 /* get the value into acc */
8593 if (AOP_TYPE (cond) != AOP_CRY)
8597 /* the result is now in the accumulator */
8598 freeAsmop (cond, NULL, ic, TRUE);
8600 /* if there was something to be popped then do it */
8604 /* if the condition is a bit variable */
8605 if (isbit && IS_ITEMP (cond) &&
8607 genIfxJump (ic, SPIL_LOC (cond)->rname);
8608 else if (isbit && !IS_ITEMP (cond))
8609 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8611 genIfxJump (ic, "a");
8616 /*-----------------------------------------------------------------*/
8617 /* genAddrOf - generates code for address of */
8618 /*-----------------------------------------------------------------*/
8620 genAddrOf (iCode * ic)
8622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8625 D(emitcode ("; genAddrOf",""));
8627 aopOp (IC_RESULT (ic), ic, FALSE);
8629 /* if the operand is on the stack then we
8630 need to get the stack offset of this
8634 /* if it has an offset then we need to compute
8638 emitcode ("mov", "a,_bp");
8639 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8640 ((char) (sym->stack - _G.nRegsSaved)) :
8641 ((char) sym->stack)) & 0xff);
8642 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8646 /* we can just move _bp */
8647 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8649 /* fill the result with zero */
8650 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8655 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8661 /* object not on stack then we need the name */
8662 size = AOP_SIZE (IC_RESULT (ic));
8667 char s[SDCC_NAME_MAX];
8669 sprintf (s, "#(%s >> %d)",
8673 sprintf (s, "#%s", sym->rname);
8674 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8678 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* genFarFarAssign - assignment when both are in far space */
8684 /*-----------------------------------------------------------------*/
8686 genFarFarAssign (operand * result, operand * right, iCode * ic)
8688 int size = AOP_SIZE (right);
8692 D(emitcode ("; genFarFarAssign",""));
8694 /* first push the right side on to the stack */
8697 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8699 emitcode ("push", "acc");
8702 freeAsmop (right, NULL, ic, FALSE);
8703 /* now assign DPTR to result */
8704 aopOp (result, ic, FALSE);
8705 size = AOP_SIZE (result);
8708 emitcode ("pop", "acc");
8709 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8711 freeAsmop (result, NULL, ic, FALSE);
8715 /*-----------------------------------------------------------------*/
8716 /* genAssign - generate code for assignment */
8717 /*-----------------------------------------------------------------*/
8719 genAssign (iCode * ic)
8721 operand *result, *right;
8723 unsigned long lit = 0L;
8725 D(emitcode("; genAssign",""));
8727 result = IC_RESULT (ic);
8728 right = IC_RIGHT (ic);
8730 /* if they are the same */
8731 if (operandsEqu (result, right) &&
8732 !isOperandVolatile (result, FALSE) &&
8733 !isOperandVolatile (right, FALSE))
8736 aopOp (right, ic, FALSE);
8738 /* special case both in far space */
8739 if (AOP_TYPE (right) == AOP_DPTR &&
8740 IS_TRUE_SYMOP (result) &&
8741 isOperandInFarSpace (result))
8744 genFarFarAssign (result, right, ic);
8748 aopOp (result, ic, TRUE);
8750 /* if they are the same registers */
8751 if (sameRegs (AOP (right), AOP (result)) &&
8752 !isOperandVolatile (result, FALSE) &&
8753 !isOperandVolatile (right, FALSE))
8756 /* if the result is a bit */
8757 if (AOP_TYPE (result) == AOP_CRY)
8760 /* if the right size is a literal then
8761 we know what the value is */
8762 if (AOP_TYPE (right) == AOP_LIT)
8764 if (((int) operandLitValue (right)))
8765 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8767 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8771 /* the right is also a bit variable */
8772 if (AOP_TYPE (right) == AOP_CRY)
8774 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8775 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8781 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8785 /* bit variables done */
8787 size = AOP_SIZE (result);
8789 if (AOP_TYPE (right) == AOP_LIT)
8790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8792 (AOP_TYPE (result) != AOP_REG) &&
8793 (AOP_TYPE (right) == AOP_LIT) &&
8794 !IS_FLOAT (operandType (right)) &&
8797 emitcode ("clr", "a");
8800 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8801 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8803 aopPut (AOP (result),
8804 aopGet (AOP (right), size, FALSE, FALSE),
8806 isOperandVolatile (result, FALSE));
8813 aopPut (AOP (result),
8814 aopGet (AOP (right), offset, FALSE, FALSE),
8816 isOperandVolatile (result, FALSE));
8822 freeAsmop (right, NULL, ic, TRUE);
8823 freeAsmop (result, NULL, ic, TRUE);
8826 /*-----------------------------------------------------------------*/
8827 /* genJumpTab - genrates code for jump table */
8828 /*-----------------------------------------------------------------*/
8830 genJumpTab (iCode * ic)
8835 D(emitcode ("; genJumpTab",""));
8837 aopOp (IC_JTCOND (ic), ic, FALSE);
8838 /* get the condition into accumulator */
8839 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8841 /* multiply by three */
8842 emitcode ("add", "a,acc");
8843 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8844 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8846 jtab = newiTempLabel (NULL);
8847 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8848 emitcode ("jmp", "@a+dptr");
8849 emitcode ("", "%05d$:", jtab->key + 100);
8850 /* now generate the jump labels */
8851 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8852 jtab = setNextItem (IC_JTLABELS (ic)))
8853 emitcode ("ljmp", "%05d$", jtab->key + 100);
8857 /*-----------------------------------------------------------------*/
8858 /* genCast - gen code for casting */
8859 /*-----------------------------------------------------------------*/
8861 genCast (iCode * ic)
8863 operand *result = IC_RESULT (ic);
8864 sym_link *ctype = operandType (IC_LEFT (ic));
8865 sym_link *rtype = operandType (IC_RIGHT (ic));
8866 operand *right = IC_RIGHT (ic);
8869 D(emitcode("; genCast",""));
8871 /* if they are equivalent then do nothing */
8872 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8875 aopOp (right, ic, FALSE);
8876 aopOp (result, ic, FALSE);
8878 /* if the result is a bit (and not a bitfield) */
8879 // if (AOP_TYPE (result) == AOP_CRY)
8880 if (IS_BITVAR (OP_SYMBOL (result)->type)
8881 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8883 /* if the right size is a literal then
8884 we know what the value is */
8885 if (AOP_TYPE (right) == AOP_LIT)
8887 if (((int) operandLitValue (right)))
8888 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8890 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8895 /* the right is also a bit variable */
8896 if (AOP_TYPE (right) == AOP_CRY)
8898 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8899 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8905 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8910 /* if they are the same size : or less */
8911 if (AOP_SIZE (result) <= AOP_SIZE (right))
8914 /* if they are in the same place */
8915 if (sameRegs (AOP (right), AOP (result)))
8918 /* if they in different places then copy */
8919 size = AOP_SIZE (result);
8923 aopPut (AOP (result),
8924 aopGet (AOP (right), offset, FALSE, FALSE),
8926 isOperandVolatile (result, FALSE));
8933 /* if the result is of type pointer */
8938 sym_link *type = operandType (right);
8939 sym_link *etype = getSpec (type);
8941 /* pointer to generic pointer */
8942 if (IS_GENPTR (ctype))
8945 p_type = DCL_TYPE (type);
8948 if (SPEC_SCLS(etype)==S_REGISTER) {
8949 // let's assume it is a generic pointer
8952 /* we have to go by the storage class */
8953 p_type = PTR_TYPE (SPEC_OCLS (etype));
8957 /* the first two bytes are known */
8958 size = GPTRSIZE - 1;
8962 aopPut (AOP (result),
8963 aopGet (AOP (right), offset, FALSE, FALSE),
8965 isOperandVolatile (result, FALSE));
8968 /* the last byte depending on type */
8970 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8975 // pointerTypeToGPByte will have bitched.
8979 sprintf(gpValStr, "#0x%d", gpVal);
8980 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8985 /* just copy the pointers */
8986 size = AOP_SIZE (result);
8990 aopPut (AOP (result),
8991 aopGet (AOP (right), offset, FALSE, FALSE),
8993 isOperandVolatile (result, FALSE));
8999 /* so we now know that the size of destination is greater
9000 than the size of the source */
9001 /* we move to result for the size of source */
9002 size = AOP_SIZE (right);
9006 aopPut (AOP (result),
9007 aopGet (AOP (right), offset, FALSE, FALSE),
9009 isOperandVolatile (result, FALSE));
9013 /* now depending on the sign of the source && destination */
9014 size = AOP_SIZE (result) - AOP_SIZE (right);
9015 /* if unsigned or not an integral type */
9016 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9019 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9023 /* we need to extend the sign :{ */
9024 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9027 emitcode ("rlc", "a");
9028 emitcode ("subb", "a,acc");
9030 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9033 /* we are done hurray !!!! */
9036 freeAsmop (right, NULL, ic, TRUE);
9037 freeAsmop (result, NULL, ic, TRUE);
9041 /*-----------------------------------------------------------------*/
9042 /* genDjnz - generate decrement & jump if not zero instrucion */
9043 /*-----------------------------------------------------------------*/
9045 genDjnz (iCode * ic, iCode * ifx)
9051 D(emitcode ("; genDjnz",""));
9053 /* if the if condition has a false label
9054 then we cannot save */
9058 /* if the minus is not of the form
9060 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9061 !IS_OP_LITERAL (IC_RIGHT (ic)))
9064 if (operandLitValue (IC_RIGHT (ic)) != 1)
9067 /* if the size of this greater than one then no
9069 if (getSize (operandType (IC_RESULT (ic))) > 1)
9072 /* otherwise we can save BIG */
9073 lbl = newiTempLabel (NULL);
9074 lbl1 = newiTempLabel (NULL);
9076 aopOp (IC_RESULT (ic), ic, FALSE);
9078 if (AOP_NEEDSACC(IC_RESULT(ic)))
9080 /* If the result is accessed indirectly via
9081 * the accumulator, we must explicitly write
9082 * it back after the decrement.
9084 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9086 if (strcmp(rByte, "a"))
9088 /* Something is hopelessly wrong */
9089 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9090 __FILE__, __LINE__);
9091 /* We can just give up; the generated code will be inefficient,
9094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9097 emitcode ("dec", "%s", rByte);
9098 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9099 emitcode ("jnz", "%05d$", lbl->key + 100);
9101 else if (IS_AOP_PREG (IC_RESULT (ic)))
9103 emitcode ("dec", "%s",
9104 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9105 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9106 emitcode ("jnz", "%05d$", lbl->key + 100);
9110 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9113 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9114 emitcode ("", "%05d$:", lbl->key + 100);
9115 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9116 emitcode ("", "%05d$:", lbl1->key + 100);
9118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9123 /*-----------------------------------------------------------------*/
9124 /* genReceive - generate code for a receive iCode */
9125 /*-----------------------------------------------------------------*/
9127 genReceive (iCode * ic)
9129 int size = getSize (operandType (IC_RESULT (ic)));
9131 D(emitcode ("; genReceive",""));
9133 if (ic->argreg == 1) { /* first parameter */
9134 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9135 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9136 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9142 for (offset = 0; offset<size; offset++)
9143 if (!strcmp (fReturn[offset], "a"))
9148 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9150 for (offset = size-1; offset>0; offset--)
9151 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9152 emitcode("mov","a,%s", fReturn[0]);
9154 aopOp (IC_RESULT (ic), ic, FALSE);
9156 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9157 isOperandVolatile (IC_RESULT (ic), FALSE));
9158 for (offset = 1; offset<size; offset++)
9159 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9160 isOperandVolatile (IC_RESULT (ic), FALSE));
9166 if (getTempRegs(tempRegs, size, ic))
9168 for (offset = 0; offset<size; offset++)
9169 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9170 aopOp (IC_RESULT (ic), ic, FALSE);
9171 for (offset = 0; offset<size; offset++)
9172 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9173 isOperandVolatile (IC_RESULT (ic), FALSE));
9178 offset = fReturnSizeMCS51 - size;
9180 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9181 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9184 aopOp (IC_RESULT (ic), ic, FALSE);
9185 size = AOP_SIZE (IC_RESULT (ic));
9188 emitcode ("pop", "acc");
9189 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9194 aopOp (IC_RESULT (ic), ic, FALSE);
9196 assignResultValue (IC_RESULT (ic));
9198 } else { /* second receive onwards */
9200 aopOp (IC_RESULT (ic), ic, FALSE);
9201 rb1off = ic->argreg;
9203 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9211 /*-----------------------------------------------------------------*/
9212 /* genDummyRead - generate code for dummy read of volatiles */
9213 /*-----------------------------------------------------------------*/
9215 genDummyRead (iCode * ic)
9220 D(emitcode("; genDummyRead",""));
9223 if (op && IS_SYMOP (op))
9225 aopOp (op, ic, FALSE);
9227 /* if the result is a bit */
9228 if (AOP_TYPE (op) == AOP_CRY)
9229 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9232 /* bit variables done */
9234 size = AOP_SIZE (op);
9238 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9243 freeAsmop (op, NULL, ic, TRUE);
9247 if (op && IS_SYMOP (op))
9249 aopOp (op, ic, FALSE);
9251 /* if the result is a bit */
9252 if (AOP_TYPE (op) == AOP_CRY)
9253 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9256 /* bit variables done */
9258 size = AOP_SIZE (op);
9262 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9267 freeAsmop (op, NULL, ic, TRUE);
9271 /*-----------------------------------------------------------------*/
9272 /* genCritical - generate code for start of a critical sequence */
9273 /*-----------------------------------------------------------------*/
9275 genCritical (iCode *ic)
9277 symbol *tlbl = newiTempLabel (NULL);
9279 D(emitcode("; genCritical",""));
9282 aopOp (IC_RESULT (ic), ic, TRUE);
9284 emitcode ("setb", "c");
9285 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9286 emitcode ("clr", "c");
9287 emitcode ("", "%05d$:", (tlbl->key + 100));
9290 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9292 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9295 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9298 /*-----------------------------------------------------------------*/
9299 /* genEndCritical - generate code for end of a critical sequence */
9300 /*-----------------------------------------------------------------*/
9302 genEndCritical (iCode *ic)
9304 D(emitcode("; genEndCritical",""));
9308 aopOp (IC_RIGHT (ic), ic, FALSE);
9309 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9311 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9312 emitcode ("mov", "ea,c");
9316 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9317 emitcode ("rrc", "a");
9318 emitcode ("mov", "ea,c");
9320 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9324 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9325 emitcode ("mov", "ea,c");
9330 /*-----------------------------------------------------------------*/
9331 /* gen51Code - generate code for 8051 based controllers */
9332 /*-----------------------------------------------------------------*/
9334 gen51Code (iCode * lic)
9339 _G.currentFunc = NULL;
9340 lineHead = lineCurr = NULL;
9342 /* print the allocation information */
9343 if (allocInfo && currFunc)
9344 printAllocInfo (currFunc, codeOutFile);
9345 /* if debug information required */
9346 if (options.debug && currFunc)
9348 debugFile->writeFunction(currFunc);
9350 if (IS_STATIC (currFunc->etype))
9351 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9353 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9356 /* stack pointer name */
9357 if (options.useXstack)
9363 for (ic = lic; ic; ic = ic->next)
9365 _G.current_iCode = ic;
9367 if (ic->lineno && cln != ic->lineno)
9372 emitcode ("", "C$%s$%d$%d$%d ==.",
9373 FileBaseName (ic->filename), ic->lineno,
9374 ic->level, ic->block);
9377 if (!options.noCcodeInAsm) {
9378 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9379 printCLine(ic->filename, ic->lineno));
9383 if (options.iCodeInAsm) {
9387 for (i=0; i<8; i++) {
9388 sprintf (®sInUse[i],
9389 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9392 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9394 /* if the result is marked as
9395 spilt and rematerializable or code for
9396 this has already been generated then
9398 if (resultRemat (ic) || ic->generated)
9401 /* depending on the operation */
9421 /* IPOP happens only when trying to restore a
9422 spilt live range, if there is an ifx statement
9423 following this pop then the if statement might
9424 be using some of the registers being popped which
9425 would destory the contents of the register so
9426 we need to check for this condition and handle it */
9428 ic->next->op == IFX &&
9429 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9430 genIfx (ic->next, ic);
9448 genEndFunction (ic);
9468 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9485 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9489 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9496 /* note these two are xlated by algebraic equivalence
9497 during parsing SDCC.y */
9498 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9499 "got '>=' or '<=' shouldn't have come here");
9503 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9515 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9519 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9523 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9550 case GET_VALUE_AT_ADDRESS:
9551 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9555 if (POINTER_SET (ic))
9556 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9582 addSet (&_G.sendSet, ic);
9585 case DUMMY_READ_VOLATILE:
9594 genEndCritical (ic);
9606 _G.current_iCode = NULL;
9608 /* now we are ready to call the
9609 peep hole optimizer */
9610 if (!options.nopeep)
9611 peepHole (&lineHead);
9613 /* now do the actual printing */
9614 printLine (lineHead, codeOutFile);