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) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4338 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4339 /* assign the amsops */
4340 aopOp (left, ic, FALSE);
4341 aopOp (right, ic, FALSE);
4342 aopOp (result, ic, TRUE);
4344 genCmp (right, left, result, ifx, sign,ic);
4346 freeAsmop (result, NULL, ic, TRUE);
4349 /*-----------------------------------------------------------------*/
4350 /* genCmpLt - less than comparisons */
4351 /*-----------------------------------------------------------------*/
4353 genCmpLt (iCode * ic, iCode * ifx)
4355 operand *left, *right, *result;
4356 sym_link *letype, *retype;
4359 D(emitcode ("; genCmpLt",""));
4361 left = IC_LEFT (ic);
4362 right = IC_RIGHT (ic);
4363 result = IC_RESULT (ic);
4365 letype = getSpec (operandType (left));
4366 retype = getSpec (operandType (right));
4367 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4368 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4369 /* assign the amsops */
4370 aopOp (left, ic, FALSE);
4371 aopOp (right, ic, FALSE);
4372 aopOp (result, ic, TRUE);
4374 genCmp (left, right, result, ifx, sign,ic);
4376 freeAsmop (result, NULL, ic, TRUE);
4379 /*-----------------------------------------------------------------*/
4380 /* gencjneshort - compare and jump if not equal */
4381 /*-----------------------------------------------------------------*/
4383 gencjneshort (operand * left, operand * right, symbol * lbl)
4385 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4387 unsigned long lit = 0L;
4389 /* if the left side is a literal or
4390 if the right is in a pointer register and left
4392 if ((AOP_TYPE (left) == AOP_LIT) ||
4393 (AOP_TYPE (left) == AOP_IMMD) ||
4394 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4401 if (AOP_TYPE (right) == AOP_LIT)
4402 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4404 /* if the right side is a literal then anything goes */
4405 if (AOP_TYPE (right) == AOP_LIT &&
4406 AOP_TYPE (left) != AOP_DIR &&
4407 AOP_TYPE (left) != AOP_IMMD)
4411 emitcode ("cjne", "%s,%s,%05d$",
4412 aopGet (AOP (left), offset, FALSE, FALSE),
4413 aopGet (AOP (right), offset, FALSE, FALSE),
4419 /* if the right side is in a register or in direct space or
4420 if the left is a pointer register & right is not */
4421 else if (AOP_TYPE (right) == AOP_REG ||
4422 AOP_TYPE (right) == AOP_DIR ||
4423 AOP_TYPE (right) == AOP_LIT ||
4424 AOP_TYPE (right) == AOP_IMMD ||
4425 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4426 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4430 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4431 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4432 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4433 emitcode ("jnz", "%05d$", lbl->key + 100);
4435 emitcode ("cjne", "a,%s,%05d$",
4436 aopGet (AOP (right), offset, FALSE, TRUE),
4443 /* right is a pointer reg need both a & b */
4446 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4447 if (strcmp (l, "b"))
4448 emitcode ("mov", "b,%s", l);
4449 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4450 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4456 /*-----------------------------------------------------------------*/
4457 /* gencjne - compare and jump if not equal */
4458 /*-----------------------------------------------------------------*/
4460 gencjne (operand * left, operand * right, symbol * lbl)
4462 symbol *tlbl = newiTempLabel (NULL);
4464 gencjneshort (left, right, lbl);
4466 emitcode ("mov", "a,%s", one);
4467 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4468 emitcode ("", "%05d$:", lbl->key + 100);
4469 emitcode ("clr", "a");
4470 emitcode ("", "%05d$:", tlbl->key + 100);
4473 /*-----------------------------------------------------------------*/
4474 /* genCmpEq - generates code for equal to */
4475 /*-----------------------------------------------------------------*/
4477 genCmpEq (iCode * ic, iCode * ifx)
4479 operand *left, *right, *result;
4481 D(emitcode ("; genCmpEq",""));
4483 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4484 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4485 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4487 /* if literal, literal on the right or
4488 if the right is in a pointer register and left
4490 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4491 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4493 operand *t = IC_RIGHT (ic);
4494 IC_RIGHT (ic) = IC_LEFT (ic);
4498 if (ifx && !AOP_SIZE (result))
4501 /* if they are both bit variables */
4502 if (AOP_TYPE (left) == AOP_CRY &&
4503 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4505 if (AOP_TYPE (right) == AOP_LIT)
4507 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4510 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4511 emitcode ("cpl", "c");
4515 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4519 emitcode ("clr", "c");
4521 /* AOP_TYPE(right) == AOP_CRY */
4525 symbol *lbl = newiTempLabel (NULL);
4526 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4527 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4528 emitcode ("cpl", "c");
4529 emitcode ("", "%05d$:", (lbl->key + 100));
4531 /* if true label then we jump if condition
4533 tlbl = newiTempLabel (NULL);
4536 emitcode ("jnc", "%05d$", tlbl->key + 100);
4537 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4541 emitcode ("jc", "%05d$", tlbl->key + 100);
4542 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4544 emitcode ("", "%05d$:", tlbl->key + 100);
4548 tlbl = newiTempLabel (NULL);
4549 gencjneshort (left, right, tlbl);
4552 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4553 emitcode ("", "%05d$:", tlbl->key + 100);
4557 symbol *lbl = newiTempLabel (NULL);
4558 emitcode ("sjmp", "%05d$", lbl->key + 100);
4559 emitcode ("", "%05d$:", tlbl->key + 100);
4560 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4561 emitcode ("", "%05d$:", lbl->key + 100);
4564 /* mark the icode as generated */
4569 /* if they are both bit variables */
4570 if (AOP_TYPE (left) == AOP_CRY &&
4571 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4573 if (AOP_TYPE (right) == AOP_LIT)
4575 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579 emitcode ("cpl", "c");
4583 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4587 emitcode ("clr", "c");
4589 /* AOP_TYPE(right) == AOP_CRY */
4593 symbol *lbl = newiTempLabel (NULL);
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4596 emitcode ("cpl", "c");
4597 emitcode ("", "%05d$:", (lbl->key + 100));
4600 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4607 genIfxJump (ifx, "c");
4610 /* if the result is used in an arithmetic operation
4611 then put the result in place */
4616 gencjne (left, right, newiTempLabel (NULL));
4617 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4619 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4624 genIfxJump (ifx, "a");
4627 /* if the result is used in an arithmetic operation
4628 then put the result in place */
4629 if (AOP_TYPE (result) != AOP_CRY)
4631 /* leave the result in acc */
4635 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4637 freeAsmop (result, NULL, ic, TRUE);
4640 /*-----------------------------------------------------------------*/
4641 /* ifxForOp - returns the icode containing the ifx for operand */
4642 /*-----------------------------------------------------------------*/
4644 ifxForOp (operand * op, iCode * ic)
4646 /* if true symbol then needs to be assigned */
4647 if (IS_TRUE_SYMOP (op))
4650 /* if this has register type condition and
4651 the next instruction is ifx with the same operand
4652 and live to of the operand is upto the ifx only then */
4654 ic->next->op == IFX &&
4655 IC_COND (ic->next)->key == op->key &&
4656 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4662 /*-----------------------------------------------------------------*/
4663 /* hasInc - operand is incremented before any other use */
4664 /*-----------------------------------------------------------------*/
4666 hasInc (operand *op, iCode *ic,int osize)
4668 sym_link *type = operandType(op);
4669 sym_link *retype = getSpec (type);
4670 iCode *lic = ic->next;
4673 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4674 if (!IS_SYMOP(op)) return NULL;
4676 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4677 if (IS_AGGREGATE(type->next)) return NULL;
4678 if (osize != (isize = getSize(type->next))) return NULL;
4681 /* if operand of the form op = op + <sizeof *op> */
4682 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4683 isOperandEqual(IC_RESULT(lic),op) &&
4684 isOperandLiteral(IC_RIGHT(lic)) &&
4685 operandLitValue(IC_RIGHT(lic)) == isize) {
4688 /* if the operand used or deffed */
4689 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4692 /* if GOTO or IFX */
4693 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4699 /*-----------------------------------------------------------------*/
4700 /* genAndOp - for && operation */
4701 /*-----------------------------------------------------------------*/
4703 genAndOp (iCode * ic)
4705 operand *left, *right, *result;
4708 D(emitcode ("; genAndOp",""));
4710 /* note here that && operations that are in an
4711 if statement are taken away by backPatchLabels
4712 only those used in arthmetic operations remain */
4713 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4714 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4715 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4717 /* if both are bit variables */
4718 if (AOP_TYPE (left) == AOP_CRY &&
4719 AOP_TYPE (right) == AOP_CRY)
4721 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4722 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4727 tlbl = newiTempLabel (NULL);
4729 emitcode ("jz", "%05d$", tlbl->key + 100);
4731 emitcode ("", "%05d$:", tlbl->key + 100);
4735 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4737 freeAsmop (result, NULL, ic, TRUE);
4741 /*-----------------------------------------------------------------*/
4742 /* genOrOp - for || operation */
4743 /*-----------------------------------------------------------------*/
4745 genOrOp (iCode * ic)
4747 operand *left, *right, *result;
4750 D(emitcode ("; genOrOp",""));
4752 /* note here that || operations that are in an
4753 if statement are taken away by backPatchLabels
4754 only those used in arthmetic operations remain */
4755 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4756 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4757 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4759 /* if both are bit variables */
4760 if (AOP_TYPE (left) == AOP_CRY &&
4761 AOP_TYPE (right) == AOP_CRY)
4763 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4764 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4769 tlbl = newiTempLabel (NULL);
4771 emitcode ("jnz", "%05d$", tlbl->key + 100);
4773 emitcode ("", "%05d$:", tlbl->key + 100);
4777 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4779 freeAsmop (result, NULL, ic, TRUE);
4782 /*-----------------------------------------------------------------*/
4783 /* isLiteralBit - test if lit == 2^n */
4784 /*-----------------------------------------------------------------*/
4786 isLiteralBit (unsigned long lit)
4788 unsigned long pw[32] =
4789 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4790 0x100L, 0x200L, 0x400L, 0x800L,
4791 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4792 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4793 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4794 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4795 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4798 for (idx = 0; idx < 32; idx++)
4804 /*-----------------------------------------------------------------*/
4805 /* continueIfTrue - */
4806 /*-----------------------------------------------------------------*/
4808 continueIfTrue (iCode * ic)
4811 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4815 /*-----------------------------------------------------------------*/
4817 /*-----------------------------------------------------------------*/
4819 jumpIfTrue (iCode * ic)
4822 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4826 /*-----------------------------------------------------------------*/
4827 /* jmpTrueOrFalse - */
4828 /*-----------------------------------------------------------------*/
4830 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4832 // ugly but optimized by peephole
4835 symbol *nlbl = newiTempLabel (NULL);
4836 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4837 emitcode ("", "%05d$:", tlbl->key + 100);
4838 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4839 emitcode ("", "%05d$:", nlbl->key + 100);
4843 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4844 emitcode ("", "%05d$:", tlbl->key + 100);
4849 /*-----------------------------------------------------------------*/
4850 /* genAnd - code for and */
4851 /*-----------------------------------------------------------------*/
4853 genAnd (iCode * ic, iCode * ifx)
4855 operand *left, *right, *result;
4856 int size, offset = 0;
4857 unsigned long lit = 0L;
4861 D(emitcode ("; genAnd",""));
4863 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4864 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4865 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4868 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4870 AOP_TYPE (left), AOP_TYPE (right));
4871 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4873 AOP_SIZE (left), AOP_SIZE (right));
4876 /* if left is a literal & right is not then exchange them */
4877 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4878 AOP_NEEDSACC (left))
4880 operand *tmp = right;
4885 /* if result = right then exchange them */
4886 if (sameRegs (AOP (result), AOP (right)))
4888 operand *tmp = right;
4893 /* if right is bit then exchange them */
4894 if (AOP_TYPE (right) == AOP_CRY &&
4895 AOP_TYPE (left) != AOP_CRY)
4897 operand *tmp = right;
4901 if (AOP_TYPE (right) == AOP_LIT)
4902 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4904 size = AOP_SIZE (result);
4907 // result = bit & yy;
4908 if (AOP_TYPE (left) == AOP_CRY)
4910 // c = bit & literal;
4911 if (AOP_TYPE (right) == AOP_LIT)
4915 if (size && sameRegs (AOP (result), AOP (left)))
4918 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4923 if (size && (AOP_TYPE (result) == AOP_CRY))
4925 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4928 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4933 emitcode ("clr", "c");
4938 if (AOP_TYPE (right) == AOP_CRY)
4941 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4942 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4947 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4949 emitcode ("rrc", "a");
4950 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4958 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4959 genIfxJump (ifx, "c");
4963 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4964 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4965 if ((AOP_TYPE (right) == AOP_LIT) &&
4966 (AOP_TYPE (result) == AOP_CRY) &&
4967 (AOP_TYPE (left) != AOP_CRY))
4969 int posbit = isLiteralBit (lit);
4974 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4977 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4983 sprintf (buffer, "acc.%d", posbit & 0x07);
4984 genIfxJump (ifx, buffer);
4991 symbol *tlbl = newiTempLabel (NULL);
4992 int sizel = AOP_SIZE (left);
4994 emitcode ("setb", "c");
4997 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4999 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5001 if ((posbit = isLiteralBit (bytelit)) != 0)
5002 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5005 if (bytelit != 0x0FFL)
5006 emitcode ("anl", "a,%s",
5007 aopGet (AOP (right), offset, FALSE, TRUE));
5008 emitcode ("jnz", "%05d$", tlbl->key + 100);
5013 // bit = left & literal
5016 emitcode ("clr", "c");
5017 emitcode ("", "%05d$:", tlbl->key + 100);
5019 // if(left & literal)
5023 jmpTrueOrFalse (ifx, tlbl);
5025 emitcode ("", "%05d$:", tlbl->key + 100);
5033 /* if left is same as result */
5034 if (sameRegs (AOP (result), AOP (left)))
5036 for (; size--; offset++)
5038 if (AOP_TYPE (right) == AOP_LIT)
5040 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5042 else if (bytelit == 0)
5044 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5046 else if (IS_AOP_PREG (result))
5048 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5049 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5050 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5053 emitcode ("anl", "%s,%s",
5054 aopGet (AOP (left), offset, FALSE, TRUE),
5055 aopGet (AOP (right), offset, FALSE, FALSE));
5059 if (AOP_TYPE (left) == AOP_ACC)
5060 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5063 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5064 if (IS_AOP_PREG (result))
5066 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5067 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5071 emitcode ("anl", "%s,a",
5072 aopGet (AOP (left), offset, FALSE, TRUE));
5079 // left & result in different registers
5080 if (AOP_TYPE (result) == AOP_CRY)
5083 // if(size), result in bit
5084 // if(!size && ifx), conditional oper: if(left & right)
5085 symbol *tlbl = newiTempLabel (NULL);
5086 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5088 emitcode ("setb", "c");
5091 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5092 emitcode ("anl", "a,%s",
5093 aopGet (AOP (right), offset, FALSE, FALSE));
5095 if (AOP_TYPE(left)==AOP_ACC) {
5096 emitcode("mov", "b,a");
5097 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5098 emitcode("anl", "a,b");
5100 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5101 emitcode ("anl", "a,%s",
5102 aopGet (AOP (left), offset, FALSE, FALSE));
5105 emitcode ("jnz", "%05d$", tlbl->key + 100);
5111 emitcode ("", "%05d$:", tlbl->key + 100);
5115 jmpTrueOrFalse (ifx, tlbl);
5117 emitcode ("", "%05d$:", tlbl->key + 100);
5121 for (; (size--); offset++)
5124 // result = left & right
5125 if (AOP_TYPE (right) == AOP_LIT)
5127 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5129 aopPut (AOP (result),
5130 aopGet (AOP (left), offset, FALSE, FALSE),
5132 isOperandVolatile (result, FALSE));
5135 else if (bytelit == 0)
5137 /* dummy read of volatile operand */
5138 if (isOperandVolatile (left, FALSE))
5139 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5140 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5144 // faster than result <- left, anl result,right
5145 // and better if result is SFR
5146 if (AOP_TYPE (left) == AOP_ACC)
5147 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5150 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5151 emitcode ("anl", "a,%s",
5152 aopGet (AOP (left), offset, FALSE, FALSE));
5154 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5160 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5161 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5162 freeAsmop (result, NULL, ic, TRUE);
5165 /*-----------------------------------------------------------------*/
5166 /* genOr - code for or */
5167 /*-----------------------------------------------------------------*/
5169 genOr (iCode * ic, iCode * ifx)
5171 operand *left, *right, *result;
5172 int size, offset = 0;
5173 unsigned long lit = 0L;
5175 D(emitcode ("; genOr",""));
5177 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5178 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5179 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5182 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5184 AOP_TYPE (left), AOP_TYPE (right));
5185 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5187 AOP_SIZE (left), AOP_SIZE (right));
5190 /* if left is a literal & right is not then exchange them */
5191 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5192 AOP_NEEDSACC (left))
5194 operand *tmp = right;
5199 /* if result = right then exchange them */
5200 if (sameRegs (AOP (result), AOP (right)))
5202 operand *tmp = right;
5207 /* if right is bit then exchange them */
5208 if (AOP_TYPE (right) == AOP_CRY &&
5209 AOP_TYPE (left) != AOP_CRY)
5211 operand *tmp = right;
5215 if (AOP_TYPE (right) == AOP_LIT)
5216 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5218 size = AOP_SIZE (result);
5222 if (AOP_TYPE (left) == AOP_CRY)
5224 if (AOP_TYPE (right) == AOP_LIT)
5226 // c = bit | literal;
5229 // lit != 0 => result = 1
5230 if (AOP_TYPE (result) == AOP_CRY)
5233 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5235 continueIfTrue (ifx);
5238 emitcode ("setb", "c");
5242 // lit == 0 => result = left
5243 if (size && sameRegs (AOP (result), AOP (left)))
5245 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5250 if (AOP_TYPE (right) == AOP_CRY)
5253 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5254 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5259 symbol *tlbl = newiTempLabel (NULL);
5260 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5261 emitcode ("setb", "c");
5262 emitcode ("jb", "%s,%05d$",
5263 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5265 emitcode ("jnz", "%05d$", tlbl->key + 100);
5266 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5268 jmpTrueOrFalse (ifx, tlbl);
5274 emitcode ("", "%05d$:", tlbl->key + 100);
5283 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5284 genIfxJump (ifx, "c");
5288 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5289 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5290 if ((AOP_TYPE (right) == AOP_LIT) &&
5291 (AOP_TYPE (result) == AOP_CRY) &&
5292 (AOP_TYPE (left) != AOP_CRY))
5298 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5300 continueIfTrue (ifx);
5305 // lit = 0, result = boolean(left)
5307 emitcode ("setb", "c");
5311 symbol *tlbl = newiTempLabel (NULL);
5312 emitcode ("jnz", "%05d$", tlbl->key + 100);
5314 emitcode ("", "%05d$:", tlbl->key + 100);
5318 genIfxJump (ifx, "a");
5326 /* if left is same as result */
5327 if (sameRegs (AOP (result), AOP (left)))
5329 for (; size--; offset++)
5331 if (AOP_TYPE (right) == AOP_LIT)
5333 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5335 /* dummy read of volatile operand */
5336 if (isOperandVolatile (left, FALSE))
5337 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5341 else if (IS_AOP_PREG (left))
5343 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5344 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5345 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5348 emitcode ("orl", "%s,%s",
5349 aopGet (AOP (left), offset, FALSE, TRUE),
5350 aopGet (AOP (right), offset, FALSE, FALSE));
5354 if (AOP_TYPE (left) == AOP_ACC)
5355 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5359 if (IS_AOP_PREG (left))
5361 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5362 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5365 emitcode ("orl", "%s,a",
5366 aopGet (AOP (left), offset, FALSE, TRUE));
5373 // left & result in different registers
5374 if (AOP_TYPE (result) == AOP_CRY)
5377 // if(size), result in bit
5378 // if(!size && ifx), conditional oper: if(left | right)
5379 symbol *tlbl = newiTempLabel (NULL);
5380 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5382 emitcode ("setb", "c");
5385 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5386 emitcode ("orl", "a,%s",
5387 aopGet (AOP (right), offset, FALSE, FALSE));
5389 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5390 emitcode ("orl", "a,%s",
5391 aopGet (AOP (left), offset, FALSE, FALSE));
5393 emitcode ("jnz", "%05d$", tlbl->key + 100);
5399 emitcode ("", "%05d$:", tlbl->key + 100);
5403 jmpTrueOrFalse (ifx, tlbl);
5405 emitcode ("", "%05d$:", tlbl->key + 100);
5408 for (; (size--); offset++)
5411 // result = left & right
5412 if (AOP_TYPE (right) == AOP_LIT)
5414 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5416 aopPut (AOP (result),
5417 aopGet (AOP (left), offset, FALSE, FALSE),
5419 isOperandVolatile (result, FALSE));
5423 // faster than result <- left, anl result,right
5424 // and better if result is SFR
5425 if (AOP_TYPE (left) == AOP_ACC)
5426 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5429 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5430 emitcode ("orl", "a,%s",
5431 aopGet (AOP (left), offset, FALSE, FALSE));
5433 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5438 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440 freeAsmop (result, NULL, ic, TRUE);
5443 /*-----------------------------------------------------------------*/
5444 /* genXor - code for xclusive or */
5445 /*-----------------------------------------------------------------*/
5447 genXor (iCode * ic, iCode * ifx)
5449 operand *left, *right, *result;
5450 int size, offset = 0;
5451 unsigned long lit = 0L;
5453 D(emitcode ("; genXor",""));
5455 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5456 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5457 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5460 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5462 AOP_TYPE (left), AOP_TYPE (right));
5463 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5465 AOP_SIZE (left), AOP_SIZE (right));
5468 /* if left is a literal & right is not ||
5469 if left needs acc & right does not */
5470 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5471 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5473 operand *tmp = right;
5478 /* if result = right then exchange them */
5479 if (sameRegs (AOP (result), AOP (right)))
5481 operand *tmp = right;
5486 /* if right is bit then exchange them */
5487 if (AOP_TYPE (right) == AOP_CRY &&
5488 AOP_TYPE (left) != AOP_CRY)
5490 operand *tmp = right;
5494 if (AOP_TYPE (right) == AOP_LIT)
5495 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5497 size = AOP_SIZE (result);
5501 if (AOP_TYPE (left) == AOP_CRY)
5503 if (AOP_TYPE (right) == AOP_LIT)
5505 // c = bit & literal;
5508 // lit>>1 != 0 => result = 1
5509 if (AOP_TYPE (result) == AOP_CRY)
5512 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5514 continueIfTrue (ifx);
5517 emitcode ("setb", "c");
5524 // lit == 0, result = left
5525 if (size && sameRegs (AOP (result), AOP (left)))
5527 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5531 // lit == 1, result = not(left)
5532 if (size && sameRegs (AOP (result), AOP (left)))
5534 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5539 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5540 emitcode ("cpl", "c");
5549 symbol *tlbl = newiTempLabel (NULL);
5550 if (AOP_TYPE (right) == AOP_CRY)
5553 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5557 int sizer = AOP_SIZE (right);
5559 // if val>>1 != 0, result = 1
5560 emitcode ("setb", "c");
5563 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5565 // test the msb of the lsb
5566 emitcode ("anl", "a,#0xfe");
5567 emitcode ("jnz", "%05d$", tlbl->key + 100);
5571 emitcode ("rrc", "a");
5573 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5574 emitcode ("cpl", "c");
5575 emitcode ("", "%05d$:", (tlbl->key + 100));
5582 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5583 genIfxJump (ifx, "c");
5587 if (sameRegs (AOP (result), AOP (left)))
5589 /* if left is same as result */
5590 for (; size--; offset++)
5592 if (AOP_TYPE (right) == AOP_LIT)
5594 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5596 else if (IS_AOP_PREG (left))
5598 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5599 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5600 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5603 emitcode ("xrl", "%s,%s",
5604 aopGet (AOP (left), offset, FALSE, TRUE),
5605 aopGet (AOP (right), offset, FALSE, FALSE));
5609 if (AOP_TYPE (left) == AOP_ACC)
5610 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5613 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5614 if (IS_AOP_PREG (left))
5616 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5617 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5620 emitcode ("xrl", "%s,a",
5621 aopGet (AOP (left), offset, FALSE, TRUE));
5628 // left & result in different registers
5629 if (AOP_TYPE (result) == AOP_CRY)
5632 // if(size), result in bit
5633 // if(!size && ifx), conditional oper: if(left ^ right)
5634 symbol *tlbl = newiTempLabel (NULL);
5635 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5637 emitcode ("setb", "c");
5640 if ((AOP_TYPE (right) == AOP_LIT) &&
5641 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5643 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5647 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5648 emitcode ("xrl", "a,%s",
5649 aopGet (AOP (right), offset, FALSE, FALSE));
5651 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5652 emitcode ("xrl", "a,%s",
5653 aopGet (AOP (left), offset, FALSE, FALSE));
5656 emitcode ("jnz", "%05d$", tlbl->key + 100);
5662 emitcode ("", "%05d$:", tlbl->key + 100);
5666 jmpTrueOrFalse (ifx, tlbl);
5669 for (; (size--); offset++)
5672 // result = left & right
5673 if (AOP_TYPE (right) == AOP_LIT)
5675 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5677 aopPut (AOP (result),
5678 aopGet (AOP (left), offset, FALSE, FALSE),
5680 isOperandVolatile (result, FALSE));
5684 // faster than result <- left, anl result,right
5685 // and better if result is SFR
5686 if (AOP_TYPE (left) == AOP_ACC)
5687 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5690 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5691 emitcode ("xrl", "a,%s",
5692 aopGet (AOP (left), offset, FALSE, TRUE));
5694 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5699 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5700 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5701 freeAsmop (result, NULL, ic, TRUE);
5704 /*-----------------------------------------------------------------*/
5705 /* genInline - write the inline code out */
5706 /*-----------------------------------------------------------------*/
5708 genInline (iCode * ic)
5710 char *buffer, *bp, *bp1;
5712 D(emitcode ("; genInline",""));
5714 _G.inLine += (!options.asmpeep);
5716 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5717 strcpy (buffer, IC_INLINE (ic));
5719 /* emit each line as a code */
5744 /* emitcode("",buffer); */
5745 _G.inLine -= (!options.asmpeep);
5748 /*-----------------------------------------------------------------*/
5749 /* genRRC - rotate right with carry */
5750 /*-----------------------------------------------------------------*/
5754 operand *left, *result;
5755 int size, offset = 0;
5758 D(emitcode ("; genRRC",""));
5760 /* rotate right with carry */
5761 left = IC_LEFT (ic);
5762 result = IC_RESULT (ic);
5763 aopOp (left, ic, FALSE);
5764 aopOp (result, ic, FALSE);
5766 /* move it to the result */
5767 size = AOP_SIZE (result);
5769 if (size == 1) { /* special case for 1 byte */
5770 l = aopGet (AOP (left), offset, FALSE, FALSE);
5772 emitcode ("rr", "a");
5778 l = aopGet (AOP (left), offset, FALSE, FALSE);
5780 emitcode ("rrc", "a");
5781 if (AOP_SIZE (result) > 1)
5782 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5784 /* now we need to put the carry into the
5785 highest order byte of the result */
5786 if (AOP_SIZE (result) > 1)
5788 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5791 emitcode ("mov", "acc.7,c");
5793 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5794 freeAsmop (left, NULL, ic, TRUE);
5795 freeAsmop (result, NULL, ic, TRUE);
5798 /*-----------------------------------------------------------------*/
5799 /* genRLC - generate code for rotate left with carry */
5800 /*-----------------------------------------------------------------*/
5804 operand *left, *result;
5805 int size, offset = 0;
5808 D(emitcode ("; genRLC",""));
5810 /* rotate right with carry */
5811 left = IC_LEFT (ic);
5812 result = IC_RESULT (ic);
5813 aopOp (left, ic, FALSE);
5814 aopOp (result, ic, FALSE);
5816 /* move it to the result */
5817 size = AOP_SIZE (result);
5821 l = aopGet (AOP (left), offset, FALSE, FALSE);
5823 if (size == 0) { /* special case for 1 byte */
5827 emitcode ("add", "a,acc");
5828 if (AOP_SIZE (result) > 1)
5829 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5832 l = aopGet (AOP (left), offset, FALSE, FALSE);
5834 emitcode ("rlc", "a");
5835 if (AOP_SIZE (result) > 1)
5836 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5839 /* now we need to put the carry into the
5840 highest order byte of the result */
5841 if (AOP_SIZE (result) > 1)
5843 l = aopGet (AOP (result), 0, FALSE, FALSE);
5846 emitcode ("mov", "acc.0,c");
5848 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5849 freeAsmop (left, NULL, ic, TRUE);
5850 freeAsmop (result, NULL, ic, TRUE);
5853 /*-----------------------------------------------------------------*/
5854 /* genGetHbit - generates code get highest order bit */
5855 /*-----------------------------------------------------------------*/
5857 genGetHbit (iCode * ic)
5859 operand *left, *result;
5861 D(emitcode ("; genGetHbit",""));
5863 left = IC_LEFT (ic);
5864 result = IC_RESULT (ic);
5865 aopOp (left, ic, FALSE);
5866 aopOp (result, ic, FALSE);
5868 /* get the highest order byte into a */
5869 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5870 if (AOP_TYPE (result) == AOP_CRY)
5872 emitcode ("rlc", "a");
5877 emitcode ("rl", "a");
5878 emitcode ("anl", "a,#0x01");
5883 freeAsmop (left, NULL, ic, TRUE);
5884 freeAsmop (result, NULL, ic, TRUE);
5887 /*-----------------------------------------------------------------*/
5888 /* genSwap - generates code to swap nibbles or bytes */
5889 /*-----------------------------------------------------------------*/
5891 genSwap (iCode * ic)
5893 operand *left, *result;
5895 D(emitcode ("; genSwap",""));
5897 left = IC_LEFT (ic);
5898 result = IC_RESULT (ic);
5899 aopOp (left, ic, FALSE);
5900 aopOp (result, ic, FALSE);
5902 switch (AOP_SIZE (left))
5904 case 1: /* swap nibbles in byte */
5905 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5906 emitcode ("swap", "a");
5907 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5909 case 2: /* swap bytes in word */
5910 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5912 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5913 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5914 0, isOperandVolatile (result, FALSE));
5915 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5917 else if (operandsEqu (left, result))
5920 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5921 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5923 emitcode ("mov", "b,a");
5926 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5927 0, isOperandVolatile (result, FALSE));
5928 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5932 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5933 0, isOperandVolatile (result, FALSE));
5934 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5935 1, isOperandVolatile (result, FALSE));
5939 wassertl(FALSE, "unsupported SWAP operand size");
5942 freeAsmop (left, NULL, ic, TRUE);
5943 freeAsmop (result, NULL, ic, TRUE);
5947 /*-----------------------------------------------------------------*/
5948 /* AccRol - rotate left accumulator by known count */
5949 /*-----------------------------------------------------------------*/
5951 AccRol (int shCount)
5953 shCount &= 0x0007; // shCount : 0..7
5960 emitcode ("rl", "a");
5963 emitcode ("rl", "a");
5964 emitcode ("rl", "a");
5967 emitcode ("swap", "a");
5968 emitcode ("rr", "a");
5971 emitcode ("swap", "a");
5974 emitcode ("swap", "a");
5975 emitcode ("rl", "a");
5978 emitcode ("rr", "a");
5979 emitcode ("rr", "a");
5982 emitcode ("rr", "a");
5987 /*-----------------------------------------------------------------*/
5988 /* AccLsh - left shift accumulator by known count */
5989 /*-----------------------------------------------------------------*/
5991 AccLsh (int shCount)
5996 emitcode ("add", "a,acc");
5997 else if (shCount == 2)
5999 emitcode ("add", "a,acc");
6000 emitcode ("add", "a,acc");
6004 /* rotate left accumulator */
6006 /* and kill the lower order bits */
6007 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6012 /*-----------------------------------------------------------------*/
6013 /* AccRsh - right shift accumulator by known count */
6014 /*-----------------------------------------------------------------*/
6016 AccRsh (int shCount)
6023 emitcode ("rrc", "a");
6027 /* rotate right accumulator */
6028 AccRol (8 - shCount);
6029 /* and kill the higher order bits */
6030 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6035 /*-----------------------------------------------------------------*/
6036 /* AccSRsh - signed right shift accumulator by known count */
6037 /*-----------------------------------------------------------------*/
6039 AccSRsh (int shCount)
6046 emitcode ("mov", "c,acc.7");
6047 emitcode ("rrc", "a");
6049 else if (shCount == 2)
6051 emitcode ("mov", "c,acc.7");
6052 emitcode ("rrc", "a");
6053 emitcode ("mov", "c,acc.7");
6054 emitcode ("rrc", "a");
6058 tlbl = newiTempLabel (NULL);
6059 /* rotate right accumulator */
6060 AccRol (8 - shCount);
6061 /* and kill the higher order bits */
6062 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6063 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6064 emitcode ("orl", "a,#0x%02x",
6065 (unsigned char) ~SRMask[shCount]);
6066 emitcode ("", "%05d$:", tlbl->key + 100);
6071 /*-----------------------------------------------------------------*/
6072 /* shiftR1Left2Result - shift right one byte from left to result */
6073 /*-----------------------------------------------------------------*/
6075 shiftR1Left2Result (operand * left, int offl,
6076 operand * result, int offr,
6077 int shCount, int sign)
6079 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6080 /* shift right accumulator */
6085 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6088 /*-----------------------------------------------------------------*/
6089 /* shiftL1Left2Result - shift left one byte from left to result */
6090 /*-----------------------------------------------------------------*/
6092 shiftL1Left2Result (operand * left, int offl,
6093 operand * result, int offr, int shCount)
6096 l = aopGet (AOP (left), offl, FALSE, FALSE);
6098 /* shift left accumulator */
6100 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6103 /*-----------------------------------------------------------------*/
6104 /* movLeft2Result - move byte from left to result */
6105 /*-----------------------------------------------------------------*/
6107 movLeft2Result (operand * left, int offl,
6108 operand * result, int offr, int sign)
6111 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6113 l = aopGet (AOP (left), offl, FALSE, FALSE);
6115 if (*l == '@' && (IS_AOP_PREG (result)))
6117 emitcode ("mov", "a,%s", l);
6118 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6123 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6126 /* MSB sign in acc.7 ! */
6127 if (getDataSize (left) == offl + 1)
6129 emitcode ("mov", "a,%s", l);
6130 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6137 /*-----------------------------------------------------------------*/
6138 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6139 /*-----------------------------------------------------------------*/
6143 emitcode ("rrc", "a");
6144 emitcode ("xch", "a,%s", x);
6145 emitcode ("rrc", "a");
6146 emitcode ("xch", "a,%s", x);
6149 /*-----------------------------------------------------------------*/
6150 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6151 /*-----------------------------------------------------------------*/
6155 emitcode ("xch", "a,%s", x);
6156 emitcode ("rlc", "a");
6157 emitcode ("xch", "a,%s", x);
6158 emitcode ("rlc", "a");
6161 /*-----------------------------------------------------------------*/
6162 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6163 /*-----------------------------------------------------------------*/
6167 emitcode ("xch", "a,%s", x);
6168 emitcode ("add", "a,acc");
6169 emitcode ("xch", "a,%s", x);
6170 emitcode ("rlc", "a");
6173 /*-----------------------------------------------------------------*/
6174 /* AccAXLsh - left shift a:x by known count (0..7) */
6175 /*-----------------------------------------------------------------*/
6177 AccAXLsh (char *x, int shCount)
6192 case 5: // AAAAABBB:CCCCCDDD
6194 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6196 emitcode ("anl", "a,#0x%02x",
6197 SLMask[shCount]); // BBB00000:CCCCCDDD
6199 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6201 AccRol (shCount); // DDDCCCCC:BBB00000
6203 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6205 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6207 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6209 emitcode ("anl", "a,#0x%02x",
6210 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6212 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6214 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6217 case 6: // AAAAAABB:CCCCCCDD
6218 emitcode ("anl", "a,#0x%02x",
6219 SRMask[shCount]); // 000000BB:CCCCCCDD
6220 emitcode ("mov", "c,acc.0"); // c = B
6221 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6223 AccAXRrl1 (x); // BCCCCCCD:D000000B
6224 AccAXRrl1 (x); // BBCCCCCC:DD000000
6226 emitcode("rrc","a");
6227 emitcode("xch","a,%s", x);
6228 emitcode("rrc","a");
6229 emitcode("mov","c,acc.0"); //<< get correct bit
6230 emitcode("xch","a,%s", x);
6232 emitcode("rrc","a");
6233 emitcode("xch","a,%s", x);
6234 emitcode("rrc","a");
6235 emitcode("xch","a,%s", x);
6238 case 7: // a:x <<= 7
6240 emitcode ("anl", "a,#0x%02x",
6241 SRMask[shCount]); // 0000000B:CCCCCCCD
6243 emitcode ("mov", "c,acc.0"); // c = B
6245 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6247 AccAXRrl1 (x); // BCCCCCCC:D0000000
6255 /*-----------------------------------------------------------------*/
6256 /* AccAXRsh - right shift a:x known count (0..7) */
6257 /*-----------------------------------------------------------------*/
6259 AccAXRsh (char *x, int shCount)
6267 AccAXRrl1 (x); // 0->a:x
6272 AccAXRrl1 (x); // 0->a:x
6275 AccAXRrl1 (x); // 0->a:x
6280 case 5: // AAAAABBB:CCCCCDDD = a:x
6282 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6284 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6286 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6288 emitcode ("anl", "a,#0x%02x",
6289 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6291 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6293 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6295 emitcode ("anl", "a,#0x%02x",
6296 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6298 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6300 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6302 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6305 case 6: // AABBBBBB:CCDDDDDD
6307 emitcode ("mov", "c,acc.7");
6308 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6310 emitcode ("mov", "c,acc.7");
6311 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6313 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6315 emitcode ("anl", "a,#0x%02x",
6316 SRMask[shCount]); // 000000AA:BBBBBBCC
6319 case 7: // ABBBBBBB:CDDDDDDD
6321 emitcode ("mov", "c,acc.7"); // c = A
6323 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6325 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6327 emitcode ("anl", "a,#0x%02x",
6328 SRMask[shCount]); // 0000000A:BBBBBBBC
6336 /*-----------------------------------------------------------------*/
6337 /* AccAXRshS - right shift signed a:x known count (0..7) */
6338 /*-----------------------------------------------------------------*/
6340 AccAXRshS (char *x, int shCount)
6348 emitcode ("mov", "c,acc.7");
6349 AccAXRrl1 (x); // s->a:x
6353 emitcode ("mov", "c,acc.7");
6354 AccAXRrl1 (x); // s->a:x
6356 emitcode ("mov", "c,acc.7");
6357 AccAXRrl1 (x); // s->a:x
6362 case 5: // AAAAABBB:CCCCCDDD = a:x
6364 tlbl = newiTempLabel (NULL);
6365 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6367 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6369 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6371 emitcode ("anl", "a,#0x%02x",
6372 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6374 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6376 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6378 emitcode ("anl", "a,#0x%02x",
6379 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6381 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6383 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6385 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6387 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6388 emitcode ("orl", "a,#0x%02x",
6389 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6391 emitcode ("", "%05d$:", tlbl->key + 100);
6392 break; // SSSSAAAA:BBBCCCCC
6394 case 6: // AABBBBBB:CCDDDDDD
6396 tlbl = newiTempLabel (NULL);
6397 emitcode ("mov", "c,acc.7");
6398 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6400 emitcode ("mov", "c,acc.7");
6401 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6403 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6405 emitcode ("anl", "a,#0x%02x",
6406 SRMask[shCount]); // 000000AA:BBBBBBCC
6408 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6409 emitcode ("orl", "a,#0x%02x",
6410 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6412 emitcode ("", "%05d$:", tlbl->key + 100);
6414 case 7: // ABBBBBBB:CDDDDDDD
6416 tlbl = newiTempLabel (NULL);
6417 emitcode ("mov", "c,acc.7"); // c = A
6419 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6421 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6423 emitcode ("anl", "a,#0x%02x",
6424 SRMask[shCount]); // 0000000A:BBBBBBBC
6426 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6427 emitcode ("orl", "a,#0x%02x",
6428 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6430 emitcode ("", "%05d$:", tlbl->key + 100);
6437 /*-----------------------------------------------------------------*/
6438 /* shiftL2Left2Result - shift left two bytes from left to result */
6439 /*-----------------------------------------------------------------*/
6441 shiftL2Left2Result (operand * left, int offl,
6442 operand * result, int offr, int shCount)
6444 if (sameRegs (AOP (result), AOP (left)) &&
6445 ((offl + MSB16) == offr))
6447 /* don't crash result[offr] */
6448 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6449 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6453 movLeft2Result (left, offl, result, offr, 0);
6454 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6456 /* ax << shCount (x = lsb(result)) */
6457 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6458 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6462 /*-----------------------------------------------------------------*/
6463 /* shiftR2Left2Result - shift right two bytes from left to result */
6464 /*-----------------------------------------------------------------*/
6466 shiftR2Left2Result (operand * left, int offl,
6467 operand * result, int offr,
6468 int shCount, int sign)
6470 if (sameRegs (AOP (result), AOP (left)) &&
6471 ((offl + MSB16) == offr))
6473 /* don't crash result[offr] */
6474 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6475 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6479 movLeft2Result (left, offl, result, offr, 0);
6480 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6482 /* a:x >> shCount (x = lsb(result)) */
6484 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6486 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6487 if (getDataSize (result) > 1)
6488 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6491 /*-----------------------------------------------------------------*/
6492 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6493 /*-----------------------------------------------------------------*/
6495 shiftLLeftOrResult (operand * left, int offl,
6496 operand * result, int offr, int shCount)
6498 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6499 /* shift left accumulator */
6501 /* or with result */
6502 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6503 /* back to result */
6504 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6507 /*-----------------------------------------------------------------*/
6508 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6509 /*-----------------------------------------------------------------*/
6511 shiftRLeftOrResult (operand * left, int offl,
6512 operand * result, int offr, int shCount)
6514 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6515 /* shift right accumulator */
6517 /* or with result */
6518 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6519 /* back to result */
6520 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6523 /*-----------------------------------------------------------------*/
6524 /* genlshOne - left shift a one byte quantity by known count */
6525 /*-----------------------------------------------------------------*/
6527 genlshOne (operand * result, operand * left, int shCount)
6529 D(emitcode ("; genlshOne",""));
6531 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6534 /*-----------------------------------------------------------------*/
6535 /* genlshTwo - left shift two bytes by known amount != 0 */
6536 /*-----------------------------------------------------------------*/
6538 genlshTwo (operand * result, operand * left, int shCount)
6542 D(emitcode ("; genlshTwo",""));
6544 size = getDataSize (result);
6546 /* if shCount >= 8 */
6554 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6556 movLeft2Result (left, LSB, result, MSB16, 0);
6558 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6561 /* 1 <= shCount <= 7 */
6565 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6567 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6571 /*-----------------------------------------------------------------*/
6572 /* shiftLLong - shift left one long from left to result */
6573 /* offl = LSB or MSB16 */
6574 /*-----------------------------------------------------------------*/
6576 shiftLLong (operand * left, operand * result, int offr)
6579 int size = AOP_SIZE (result);
6581 if (size >= LSB + offr)
6583 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6585 emitcode ("add", "a,acc");
6586 if (sameRegs (AOP (left), AOP (result)) &&
6587 size >= MSB16 + offr && offr != LSB)
6588 emitcode ("xch", "a,%s",
6589 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6591 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6594 if (size >= MSB16 + offr)
6596 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6598 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6601 emitcode ("rlc", "a");
6602 if (sameRegs (AOP (left), AOP (result)) &&
6603 size >= MSB24 + offr && offr != LSB)
6604 emitcode ("xch", "a,%s",
6605 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6607 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6610 if (size >= MSB24 + offr)
6612 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6614 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6617 emitcode ("rlc", "a");
6618 if (sameRegs (AOP (left), AOP (result)) &&
6619 size >= MSB32 + offr && offr != LSB)
6620 emitcode ("xch", "a,%s",
6621 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6623 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6626 if (size > MSB32 + offr)
6628 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6630 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6633 emitcode ("rlc", "a");
6634 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6637 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6640 /*-----------------------------------------------------------------*/
6641 /* genlshFour - shift four byte by a known amount != 0 */
6642 /*-----------------------------------------------------------------*/
6644 genlshFour (operand * result, operand * left, int shCount)
6648 D(emitcode ("; genlshFour",""));
6650 size = AOP_SIZE (result);
6652 /* if shifting more that 3 bytes */
6657 /* lowest order of left goes to the highest
6658 order of the destination */
6659 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6661 movLeft2Result (left, LSB, result, MSB32, 0);
6662 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6663 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6664 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6668 /* more than two bytes */
6669 else if (shCount >= 16)
6671 /* lower order two bytes goes to higher order two bytes */
6673 /* if some more remaining */
6675 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6678 movLeft2Result (left, MSB16, result, MSB32, 0);
6679 movLeft2Result (left, LSB, result, MSB24, 0);
6681 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6682 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6686 /* if more than 1 byte */
6687 else if (shCount >= 8)
6689 /* lower order three bytes goes to higher order three bytes */
6694 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6696 movLeft2Result (left, LSB, result, MSB16, 0);
6702 movLeft2Result (left, MSB24, result, MSB32, 0);
6703 movLeft2Result (left, MSB16, result, MSB24, 0);
6704 movLeft2Result (left, LSB, result, MSB16, 0);
6705 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6707 else if (shCount == 1)
6708 shiftLLong (left, result, MSB16);
6711 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6712 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6713 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6714 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6719 /* 1 <= shCount <= 7 */
6720 else if (shCount <= 2)
6722 shiftLLong (left, result, LSB);
6724 shiftLLong (result, result, LSB);
6726 /* 3 <= shCount <= 7, optimize */
6729 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6730 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6731 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6735 /*-----------------------------------------------------------------*/
6736 /* genLeftShiftLiteral - left shifting by known count */
6737 /*-----------------------------------------------------------------*/
6739 genLeftShiftLiteral (operand * left,
6744 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6747 D(emitcode ("; genLeftShiftLiteral",""));
6749 freeAsmop (right, NULL, ic, TRUE);
6751 aopOp (left, ic, FALSE);
6752 aopOp (result, ic, FALSE);
6754 size = getSize (operandType (result));
6757 emitcode ("; shift left ", "result %d, left %d", size,
6761 /* I suppose that the left size >= result size */
6766 movLeft2Result (left, size, result, size, 0);
6770 else if (shCount >= (size * 8))
6772 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6778 genlshOne (result, left, shCount);
6782 genlshTwo (result, left, shCount);
6786 genlshFour (result, left, shCount);
6789 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6790 "*** ack! mystery literal shift!\n");
6794 freeAsmop (left, NULL, ic, TRUE);
6795 freeAsmop (result, NULL, ic, TRUE);
6798 /*-----------------------------------------------------------------*/
6799 /* genLeftShift - generates code for left shifting */
6800 /*-----------------------------------------------------------------*/
6802 genLeftShift (iCode * ic)
6804 operand *left, *right, *result;
6807 symbol *tlbl, *tlbl1;
6809 D(emitcode ("; genLeftShift",""));
6811 right = IC_RIGHT (ic);
6812 left = IC_LEFT (ic);
6813 result = IC_RESULT (ic);
6815 aopOp (right, ic, FALSE);
6817 /* if the shift count is known then do it
6818 as efficiently as possible */
6819 if (AOP_TYPE (right) == AOP_LIT)
6821 genLeftShiftLiteral (left, right, result, ic);
6825 /* shift count is unknown then we have to form
6826 a loop get the loop count in B : Note: we take
6827 only the lower order byte since shifting
6828 more that 32 bits make no sense anyway, ( the
6829 largest size of an object can be only 32 bits ) */
6831 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6832 emitcode ("inc", "b");
6833 freeAsmop (right, NULL, ic, TRUE);
6834 aopOp (left, ic, FALSE);
6835 aopOp (result, ic, FALSE);
6837 /* now move the left to the result if they are not the
6839 if (!sameRegs (AOP (left), AOP (result)) &&
6840 AOP_SIZE (result) > 1)
6843 size = AOP_SIZE (result);
6847 l = aopGet (AOP (left), offset, FALSE, TRUE);
6848 if (*l == '@' && (IS_AOP_PREG (result)))
6851 emitcode ("mov", "a,%s", l);
6852 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6855 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6860 tlbl = newiTempLabel (NULL);
6861 size = AOP_SIZE (result);
6863 tlbl1 = newiTempLabel (NULL);
6865 /* if it is only one byte then */
6868 symbol *tlbl1 = newiTempLabel (NULL);
6870 l = aopGet (AOP (left), 0, FALSE, FALSE);
6872 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6873 emitcode ("", "%05d$:", tlbl->key + 100);
6874 emitcode ("add", "a,acc");
6875 emitcode ("", "%05d$:", tlbl1->key + 100);
6876 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6877 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6881 reAdjustPreg (AOP (result));
6883 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6884 emitcode ("", "%05d$:", tlbl->key + 100);
6885 l = aopGet (AOP (result), offset, FALSE, FALSE);
6887 emitcode ("add", "a,acc");
6888 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6891 l = aopGet (AOP (result), offset, FALSE, FALSE);
6893 emitcode ("rlc", "a");
6894 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6896 reAdjustPreg (AOP (result));
6898 emitcode ("", "%05d$:", tlbl1->key + 100);
6899 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6901 freeAsmop (left, NULL, ic, TRUE);
6902 freeAsmop (result, NULL, ic, TRUE);
6905 /*-----------------------------------------------------------------*/
6906 /* genrshOne - right shift a one byte quantity by known count */
6907 /*-----------------------------------------------------------------*/
6909 genrshOne (operand * result, operand * left,
6910 int shCount, int sign)
6912 D(emitcode ("; genrshOne",""));
6914 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6917 /*-----------------------------------------------------------------*/
6918 /* genrshTwo - right shift two bytes by known amount != 0 */
6919 /*-----------------------------------------------------------------*/
6921 genrshTwo (operand * result, operand * left,
6922 int shCount, int sign)
6924 D(emitcode ("; genrshTwo",""));
6926 /* if shCount >= 8 */
6931 shiftR1Left2Result (left, MSB16, result, LSB,
6934 movLeft2Result (left, MSB16, result, LSB, sign);
6935 addSign (result, MSB16, sign);
6938 /* 1 <= shCount <= 7 */
6940 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRLong - shift right one long from left to result */
6945 /* offl = LSB or MSB16 */
6946 /*-----------------------------------------------------------------*/
6948 shiftRLong (operand * left, int offl,
6949 operand * result, int sign)
6951 int isSameRegs=sameRegs(AOP(left),AOP(result));
6953 if (isSameRegs && offl>1) {
6954 // we are in big trouble, but this shouldn't happen
6955 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6958 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6963 emitcode ("rlc", "a");
6964 emitcode ("subb", "a,acc");
6966 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6968 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6969 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6972 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6977 emitcode ("clr", "c");
6979 emitcode ("mov", "c,acc.7");
6982 emitcode ("rrc", "a");
6984 if (isSameRegs && offl==MSB16) {
6985 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6987 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6988 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6991 emitcode ("rrc", "a");
6992 if (isSameRegs && offl==1) {
6993 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6995 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6996 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6998 emitcode ("rrc", "a");
6999 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7003 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7004 emitcode ("rrc", "a");
7005 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7009 /*-----------------------------------------------------------------*/
7010 /* genrshFour - shift four byte by a known amount != 0 */
7011 /*-----------------------------------------------------------------*/
7013 genrshFour (operand * result, operand * left,
7014 int shCount, int sign)
7016 D(emitcode ("; genrshFour",""));
7018 /* if shifting more that 3 bytes */
7023 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7025 movLeft2Result (left, MSB32, result, LSB, sign);
7026 addSign (result, MSB16, sign);
7028 else if (shCount >= 16)
7032 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7035 movLeft2Result (left, MSB24, result, LSB, 0);
7036 movLeft2Result (left, MSB32, result, MSB16, sign);
7038 addSign (result, MSB24, sign);
7040 else if (shCount >= 8)
7044 shiftRLong (left, MSB16, result, sign);
7045 else if (shCount == 0)
7047 movLeft2Result (left, MSB16, result, LSB, 0);
7048 movLeft2Result (left, MSB24, result, MSB16, 0);
7049 movLeft2Result (left, MSB32, result, MSB24, sign);
7050 addSign (result, MSB32, sign);
7054 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7055 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7056 /* the last shift is signed */
7057 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7058 addSign (result, MSB32, sign);
7062 { /* 1 <= shCount <= 7 */
7065 shiftRLong (left, LSB, result, sign);
7067 shiftRLong (result, LSB, result, sign);
7071 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7072 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7073 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7078 /*-----------------------------------------------------------------*/
7079 /* genRightShiftLiteral - right shifting by known count */
7080 /*-----------------------------------------------------------------*/
7082 genRightShiftLiteral (operand * left,
7088 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7091 D(emitcode ("; genRightShiftLiteral",""));
7093 freeAsmop (right, NULL, ic, TRUE);
7095 aopOp (left, ic, FALSE);
7096 aopOp (result, ic, FALSE);
7099 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7103 size = getDataSize (left);
7104 /* test the LEFT size !!! */
7106 /* I suppose that the left size >= result size */
7109 size = getDataSize (result);
7111 movLeft2Result (left, size, result, size, 0);
7114 else if (shCount >= (size * 8))
7117 /* get sign in acc.7 */
7118 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7120 addSign (result, LSB, sign);
7127 genrshOne (result, left, shCount, sign);
7131 genrshTwo (result, left, shCount, sign);
7135 genrshFour (result, left, shCount, sign);
7141 freeAsmop (left, NULL, ic, TRUE);
7142 freeAsmop (result, NULL, ic, TRUE);
7145 /*-----------------------------------------------------------------*/
7146 /* genSignedRightShift - right shift of signed number */
7147 /*-----------------------------------------------------------------*/
7149 genSignedRightShift (iCode * ic)
7151 operand *right, *left, *result;
7154 symbol *tlbl, *tlbl1;
7156 D(emitcode ("; genSignedRightShift",""));
7158 /* we do it the hard way put the shift count in b
7159 and loop thru preserving the sign */
7161 right = IC_RIGHT (ic);
7162 left = IC_LEFT (ic);
7163 result = IC_RESULT (ic);
7165 aopOp (right, ic, FALSE);
7168 if (AOP_TYPE (right) == AOP_LIT)
7170 genRightShiftLiteral (left, right, result, ic, 1);
7173 /* shift count is unknown then we have to form
7174 a loop get the loop count in B : Note: we take
7175 only the lower order byte since shifting
7176 more that 32 bits make no sense anyway, ( the
7177 largest size of an object can be only 32 bits ) */
7179 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7180 emitcode ("inc", "b");
7181 freeAsmop (right, NULL, ic, TRUE);
7182 aopOp (left, ic, FALSE);
7183 aopOp (result, ic, FALSE);
7185 /* now move the left to the result if they are not the
7187 if (!sameRegs (AOP (left), AOP (result)) &&
7188 AOP_SIZE (result) > 1)
7191 size = AOP_SIZE (result);
7195 l = aopGet (AOP (left), offset, FALSE, TRUE);
7196 if (*l == '@' && IS_AOP_PREG (result))
7199 emitcode ("mov", "a,%s", l);
7200 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7203 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7208 /* mov the highest order bit to OVR */
7209 tlbl = newiTempLabel (NULL);
7210 tlbl1 = newiTempLabel (NULL);
7212 size = AOP_SIZE (result);
7214 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7215 emitcode ("rlc", "a");
7216 emitcode ("mov", "ov,c");
7217 /* if it is only one byte then */
7220 l = aopGet (AOP (left), 0, FALSE, FALSE);
7222 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7223 emitcode ("", "%05d$:", tlbl->key + 100);
7224 emitcode ("mov", "c,ov");
7225 emitcode ("rrc", "a");
7226 emitcode ("", "%05d$:", tlbl1->key + 100);
7227 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7228 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7232 reAdjustPreg (AOP (result));
7233 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7234 emitcode ("", "%05d$:", tlbl->key + 100);
7235 emitcode ("mov", "c,ov");
7238 l = aopGet (AOP (result), offset, FALSE, FALSE);
7240 emitcode ("rrc", "a");
7241 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7243 reAdjustPreg (AOP (result));
7244 emitcode ("", "%05d$:", tlbl1->key + 100);
7245 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7248 freeAsmop (left, NULL, ic, TRUE);
7249 freeAsmop (result, NULL, ic, TRUE);
7252 /*-----------------------------------------------------------------*/
7253 /* genRightShift - generate code for right shifting */
7254 /*-----------------------------------------------------------------*/
7256 genRightShift (iCode * ic)
7258 operand *right, *left, *result;
7262 symbol *tlbl, *tlbl1;
7264 D(emitcode ("; genRightShift",""));
7266 /* if signed then we do it the hard way preserve the
7267 sign bit moving it inwards */
7268 letype = getSpec (operandType (IC_LEFT (ic)));
7270 if (!SPEC_USIGN (letype))
7272 genSignedRightShift (ic);
7276 /* signed & unsigned types are treated the same : i.e. the
7277 signed is NOT propagated inwards : quoting from the
7278 ANSI - standard : "for E1 >> E2, is equivalent to division
7279 by 2**E2 if unsigned or if it has a non-negative value,
7280 otherwise the result is implementation defined ", MY definition
7281 is that the sign does not get propagated */
7283 right = IC_RIGHT (ic);
7284 left = IC_LEFT (ic);
7285 result = IC_RESULT (ic);
7287 aopOp (right, ic, FALSE);
7289 /* if the shift count is known then do it
7290 as efficiently as possible */
7291 if (AOP_TYPE (right) == AOP_LIT)
7293 genRightShiftLiteral (left, right, result, ic, 0);
7297 /* shift count is unknown then we have to form
7298 a loop get the loop count in B : Note: we take
7299 only the lower order byte since shifting
7300 more that 32 bits make no sense anyway, ( the
7301 largest size of an object can be only 32 bits ) */
7303 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7304 emitcode ("inc", "b");
7305 freeAsmop (right, NULL, ic, TRUE);
7306 aopOp (left, ic, FALSE);
7307 aopOp (result, ic, FALSE);
7309 /* now move the left to the result if they are not the
7311 if (!sameRegs (AOP (left), AOP (result)) &&
7312 AOP_SIZE (result) > 1)
7315 size = AOP_SIZE (result);
7319 l = aopGet (AOP (left), offset, FALSE, TRUE);
7320 if (*l == '@' && IS_AOP_PREG (result))
7323 emitcode ("mov", "a,%s", l);
7324 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7327 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7332 tlbl = newiTempLabel (NULL);
7333 tlbl1 = newiTempLabel (NULL);
7334 size = AOP_SIZE (result);
7337 /* if it is only one byte then */
7340 l = aopGet (AOP (left), 0, FALSE, FALSE);
7342 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7343 emitcode ("", "%05d$:", tlbl->key + 100);
7345 emitcode ("rrc", "a");
7346 emitcode ("", "%05d$:", tlbl1->key + 100);
7347 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7348 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7352 reAdjustPreg (AOP (result));
7353 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7354 emitcode ("", "%05d$:", tlbl->key + 100);
7358 l = aopGet (AOP (result), offset, FALSE, FALSE);
7360 emitcode ("rrc", "a");
7361 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7363 reAdjustPreg (AOP (result));
7365 emitcode ("", "%05d$:", tlbl1->key + 100);
7366 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7369 freeAsmop (left, NULL, ic, TRUE);
7370 freeAsmop (result, NULL, ic, TRUE);
7373 /*-----------------------------------------------------------------*/
7374 /* emitPtrByteGet - emits code to get a byte into A through a */
7375 /* pointer register (R0, R1, or DPTR). The */
7376 /* original value of A can be preserved in B. */
7377 /*-----------------------------------------------------------------*/
7379 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7386 emitcode ("mov", "b,a");
7387 emitcode ("mov", "a,@%s", rname);
7392 emitcode ("mov", "b,a");
7393 emitcode ("movx", "a,@%s", rname);
7398 emitcode ("mov", "b,a");
7399 emitcode ("movx", "a,@dptr");
7404 emitcode ("mov", "b,a");
7405 emitcode ("clr", "a");
7406 emitcode ("movc", "a,@a+dptr");
7412 emitcode ("push", "b");
7413 emitcode ("push", "acc");
7415 emitcode ("lcall", "__gptrget");
7417 emitcode ("pop", "b");
7422 /*-----------------------------------------------------------------*/
7423 /* emitPtrByteSet - emits code to set a byte from src through a */
7424 /* pointer register (R0, R1, or DPTR). */
7425 /*-----------------------------------------------------------------*/
7427 emitPtrByteSet (char *rname, int p_type, char *src)
7436 emitcode ("mov", "@%s,a", rname);
7439 emitcode ("mov", "@%s,%s", rname, src);
7444 emitcode ("movx", "@%s,a", rname);
7449 emitcode ("movx", "@dptr,a");
7454 emitcode ("lcall", "__gptrput");
7459 /*-----------------------------------------------------------------*/
7460 /* genUnpackBits - generates code for unpacking bits */
7461 /*-----------------------------------------------------------------*/
7463 genUnpackBits (operand * result, char *rname, int ptype)
7465 int offset = 0; /* result byte offset */
7466 int rsize; /* result size */
7467 int rlen = 0; /* remaining bitfield length */
7468 sym_link *etype; /* bitfield type information */
7469 int blen; /* bitfield length */
7470 int bstr; /* bitfield starting bit within byte */
7472 D(emitcode ("; genUnpackBits",""));
7474 etype = getSpec (operandType (result));
7475 rsize = getSize (operandType (result));
7476 blen = SPEC_BLEN (etype);
7477 bstr = SPEC_BSTR (etype);
7479 /* If the bitfield length is less than a byte */
7482 emitPtrByteGet (rname, ptype, FALSE);
7484 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7485 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7489 /* Bit field did not fit in a byte. Copy all
7490 but the partial byte at the end. */
7491 for (rlen=blen;rlen>=8;rlen-=8)
7493 emitPtrByteGet (rname, ptype, FALSE);
7494 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7496 emitcode ("inc", "%s", rname);
7499 /* Handle the partial byte at the end */
7502 emitPtrByteGet (rname, ptype, FALSE);
7503 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7504 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7512 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7517 /*-----------------------------------------------------------------*/
7518 /* genDataPointerGet - generates code when ptr offset is known */
7519 /*-----------------------------------------------------------------*/
7521 genDataPointerGet (operand * left,
7527 int size, offset = 0;
7529 D(emitcode ("; genDataPointerGet",""));
7531 aopOp (result, ic, TRUE);
7533 /* get the string representation of the name */
7534 l = aopGet (AOP (left), 0, FALSE, TRUE);
7535 size = AOP_SIZE (result);
7539 sprintf (buffer, "(%s + %d)", l + 1, offset);
7541 sprintf (buffer, "%s", l + 1);
7542 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7545 freeAsmop (left, NULL, ic, TRUE);
7546 freeAsmop (result, NULL, ic, TRUE);
7549 /*-----------------------------------------------------------------*/
7550 /* genNearPointerGet - emitcode for near pointer fetch */
7551 /*-----------------------------------------------------------------*/
7553 genNearPointerGet (operand * left,
7561 sym_link *rtype, *retype;
7562 sym_link *ltype = operandType (left);
7565 D(emitcode ("; genNearPointerGet",""));
7567 rtype = operandType (result);
7568 retype = getSpec (rtype);
7570 aopOp (left, ic, FALSE);
7572 /* if left is rematerialisable and
7573 result is not bit variable type and
7574 the left is pointer to data space i.e
7575 lower 128 bytes of space */
7576 if (AOP_TYPE (left) == AOP_IMMD &&
7577 !IS_BITVAR (retype) &&
7578 DCL_TYPE (ltype) == POINTER)
7580 genDataPointerGet (left, result, ic);
7584 /* if the value is already in a pointer register
7585 then don't need anything more */
7586 if (!AOP_INPREG (AOP (left)))
7588 if (IS_AOP_PREG (left))
7590 // Aha, it is a pointer, just in disguise.
7591 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7594 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7595 __FILE__, __LINE__);
7600 emitcode ("mov", "a%s,%s", rname + 1, rname);
7601 rname++; // skip the '@'.
7606 /* otherwise get a free pointer register */
7608 preg = getFreePtr (ic, &aop, FALSE);
7609 emitcode ("mov", "%s,%s",
7611 aopGet (AOP (left), 0, FALSE, TRUE));
7616 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7618 //aopOp (result, ic, FALSE);
7619 aopOp (result, ic, result?TRUE:FALSE);
7621 /* if bitfield then unpack the bits */
7622 if (IS_BITVAR (retype))
7623 genUnpackBits (result, rname, POINTER);
7626 /* we have can just get the values */
7627 int size = AOP_SIZE (result);
7632 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7635 emitcode ("mov", "a,@%s", rname);
7636 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7640 sprintf (buffer, "@%s", rname);
7641 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7645 emitcode ("inc", "%s", rname);
7649 /* now some housekeeping stuff */
7650 if (aop) /* we had to allocate for this iCode */
7652 if (pi) { /* post increment present */
7653 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7655 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7659 /* we did not allocate which means left
7660 already in a pointer register, then
7661 if size > 0 && this could be used again
7662 we have to point it back to where it
7664 if ((AOP_SIZE (result) > 1 &&
7665 !OP_SYMBOL (left)->remat &&
7666 (OP_SYMBOL (left)->liveTo > ic->seq ||
7670 int size = AOP_SIZE (result) - 1;
7672 emitcode ("dec", "%s", rname);
7677 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7678 freeAsmop (left, NULL, ic, TRUE);
7679 if (pi) pi->generated = 1;
7682 /*-----------------------------------------------------------------*/
7683 /* genPagedPointerGet - emitcode for paged pointer fetch */
7684 /*-----------------------------------------------------------------*/
7686 genPagedPointerGet (operand * left,
7694 sym_link *rtype, *retype;
7696 D(emitcode ("; genPagedPointerGet",""));
7698 rtype = operandType (result);
7699 retype = getSpec (rtype);
7701 aopOp (left, ic, FALSE);
7703 /* if the value is already in a pointer register
7704 then don't need anything more */
7705 if (!AOP_INPREG (AOP (left)))
7707 /* otherwise get a free pointer register */
7709 preg = getFreePtr (ic, &aop, FALSE);
7710 emitcode ("mov", "%s,%s",
7712 aopGet (AOP (left), 0, FALSE, TRUE));
7716 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7718 aopOp (result, ic, FALSE);
7720 /* if bitfield then unpack the bits */
7721 if (IS_BITVAR (retype))
7722 genUnpackBits (result, rname, PPOINTER);
7725 /* we have can just get the values */
7726 int size = AOP_SIZE (result);
7732 emitcode ("movx", "a,@%s", rname);
7733 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7738 emitcode ("inc", "%s", rname);
7742 /* now some housekeeping stuff */
7743 if (aop) /* we had to allocate for this iCode */
7745 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7746 freeAsmop (NULL, aop, ic, TRUE);
7750 /* we did not allocate which means left
7751 already in a pointer register, then
7752 if size > 0 && this could be used again
7753 we have to point it back to where it
7755 if ((AOP_SIZE (result) > 1 &&
7756 !OP_SYMBOL (left)->remat &&
7757 (OP_SYMBOL (left)->liveTo > ic->seq ||
7761 int size = AOP_SIZE (result) - 1;
7763 emitcode ("dec", "%s", rname);
7768 freeAsmop (left, NULL, ic, TRUE);
7769 freeAsmop (result, NULL, ic, TRUE);
7770 if (pi) pi->generated = 1;
7774 /*--------------------------------------------------------------------*/
7775 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7776 /*--------------------------------------------------------------------*/
7778 loadDptrFromOperand (operand *op, bool loadBToo)
7780 if (AOP_TYPE (op) != AOP_STR)
7782 /* if this is remateriazable */
7783 if (AOP_TYPE (op) == AOP_IMMD)
7785 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7788 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7789 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7792 wassertl(FALSE, "need pointerCode");
7793 emitcode ("", "; mov b,???");
7794 /* genPointerGet and genPointerSet originally did different
7795 ** things for this case. Both seem wrong.
7796 ** from genPointerGet:
7797 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7798 ** from genPointerSet:
7799 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7804 else if (AOP_TYPE (op) == AOP_DPTR)
7808 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7809 emitcode ("push", "acc");
7810 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7811 emitcode ("push", "acc");
7812 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7813 emitcode ("pop", "dph");
7814 emitcode ("pop", "dpl");
7818 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7819 emitcode ("push", "acc");
7820 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7821 emitcode ("pop", "dpl");
7825 { /* we need to get it byte by byte */
7826 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7827 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7829 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7834 /*-----------------------------------------------------------------*/
7835 /* genFarPointerGet - gget value from far space */
7836 /*-----------------------------------------------------------------*/
7838 genFarPointerGet (operand * left,
7839 operand * result, iCode * ic, iCode * pi)
7842 sym_link *retype = getSpec (operandType (result));
7844 D(emitcode ("; genFarPointerGet",""));
7846 aopOp (left, ic, FALSE);
7847 loadDptrFromOperand (left, FALSE);
7849 /* so dptr now contains the address */
7850 aopOp (result, ic, FALSE);
7852 /* if bit then unpack */
7853 if (IS_BITVAR (retype))
7854 genUnpackBits (result, "dptr", FPOINTER);
7857 size = AOP_SIZE (result);
7862 emitcode ("movx", "a,@dptr");
7863 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7865 emitcode ("inc", "dptr");
7869 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7870 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7871 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7874 freeAsmop (left, NULL, ic, TRUE);
7875 freeAsmop (result, NULL, ic, TRUE);
7878 /*-----------------------------------------------------------------*/
7879 /* genCodePointerGet - gget value from code space */
7880 /*-----------------------------------------------------------------*/
7882 genCodePointerGet (operand * left,
7883 operand * result, iCode * ic, iCode *pi)
7886 sym_link *retype = getSpec (operandType (result));
7888 D(emitcode ("; genCodePointerGet",""));
7890 aopOp (left, ic, FALSE);
7891 loadDptrFromOperand (left, FALSE);
7893 /* so dptr now contains the address */
7894 aopOp (result, ic, FALSE);
7896 /* if bit then unpack */
7897 if (IS_BITVAR (retype))
7898 genUnpackBits (result, "dptr", CPOINTER);
7901 size = AOP_SIZE (result);
7908 emitcode ("clr", "a");
7909 emitcode ("movc", "a,@a+dptr");
7910 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7911 emitcode ("inc", "dptr");
7915 emitcode ("mov", "a,#0x%02x", offset);
7916 emitcode ("movc", "a,@a+dptr");
7917 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7922 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7923 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7924 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7927 freeAsmop (left, NULL, ic, TRUE);
7928 freeAsmop (result, NULL, ic, TRUE);
7931 /*-----------------------------------------------------------------*/
7932 /* genGenPointerGet - gget value from generic pointer space */
7933 /*-----------------------------------------------------------------*/
7935 genGenPointerGet (operand * left,
7936 operand * result, iCode * ic, iCode *pi)
7939 sym_link *retype = getSpec (operandType (result));
7941 D(emitcode ("; genGenPointerGet",""));
7943 aopOp (left, ic, FALSE);
7944 loadDptrFromOperand (left, TRUE);
7946 /* so dptr know contains the address */
7947 aopOp (result, ic, FALSE);
7949 /* if bit then unpack */
7950 if (IS_BITVAR (retype))
7951 genUnpackBits (result, "dptr", GPOINTER);
7954 size = AOP_SIZE (result);
7959 emitcode ("lcall", "__gptrget");
7960 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7962 emitcode ("inc", "dptr");
7966 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7967 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7968 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7971 freeAsmop (left, NULL, ic, TRUE);
7972 freeAsmop (result, NULL, ic, TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genPointerGet - generate code for pointer get */
7977 /*-----------------------------------------------------------------*/
7979 genPointerGet (iCode * ic, iCode *pi)
7981 operand *left, *result;
7982 sym_link *type, *etype;
7985 D(emitcode ("; genPointerGet",""));
7987 left = IC_LEFT (ic);
7988 result = IC_RESULT (ic);
7990 /* depending on the type of pointer we need to
7991 move it to the correct pointer register */
7992 type = operandType (left);
7993 etype = getSpec (type);
7994 /* if left is of type of pointer then it is simple */
7995 if (IS_PTR (type) && !IS_FUNC (type->next))
7996 p_type = DCL_TYPE (type);
7999 /* we have to go by the storage class */
8000 p_type = PTR_TYPE (SPEC_OCLS (etype));
8003 /* special case when cast remat */
8004 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8005 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8006 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8007 type = operandType (left);
8008 p_type = DCL_TYPE (type);
8010 /* now that we have the pointer type we assign
8011 the pointer values */
8017 genNearPointerGet (left, result, ic, pi);
8021 genPagedPointerGet (left, result, ic, pi);
8025 genFarPointerGet (left, result, ic, pi);
8029 genCodePointerGet (left, result, ic, pi);
8033 genGenPointerGet (left, result, ic, pi);
8041 /*-----------------------------------------------------------------*/
8042 /* genPackBits - generates code for packed bit storage */
8043 /*-----------------------------------------------------------------*/
8045 genPackBits (sym_link * etype,
8047 char *rname, int p_type)
8049 int offset = 0; /* source byte offset */
8050 int rlen = 0; /* remaining bitfield length */
8051 int blen; /* bitfield length */
8052 int bstr; /* bitfield starting bit within byte */
8053 int litval; /* source literal value (if AOP_LIT) */
8054 unsigned char mask; /* bitmask within current byte */
8056 D(emitcode ("; genPackBits",""));
8058 blen = SPEC_BLEN (etype);
8059 bstr = SPEC_BSTR (etype);
8061 /* If the bitfield length is less than a byte */
8064 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8065 (unsigned char) (0xFF >> (8 - bstr)));
8067 if (AOP_TYPE (right) == AOP_LIT)
8069 /* Case with a bitfield length <8 and literal source
8071 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8073 litval &= (~mask) & 0xff;
8074 emitPtrByteGet (rname, p_type, FALSE);
8075 if ((mask|litval)!=0xff)
8076 emitcode ("anl","a,#0x%02x", mask);
8078 emitcode ("orl","a,#0x%02x", litval);
8082 if ((blen==1) && (p_type!=GPOINTER))
8084 /* Case with a bitfield length == 1 and no generic pointer
8086 if (AOP_TYPE (right) == AOP_CRY)
8087 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8090 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8091 emitcode ("rrc","a");
8093 emitPtrByteGet (rname, p_type, FALSE);
8094 emitcode ("mov","acc.%d,c",bstr);
8098 /* Case with a bitfield length < 8 and arbitrary source
8100 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8101 /* shift and mask source value */
8103 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8105 /* transfer A to B and get next byte */
8106 emitPtrByteGet (rname, p_type, TRUE);
8108 emitcode ("anl", "a,#0x%02x", mask);
8109 emitcode ("orl", "a,b");
8110 if (p_type == GPOINTER)
8111 emitcode ("pop", "b");
8115 emitPtrByteSet (rname, p_type, "a");
8119 /* Bit length is greater than 7 bits. In this case, copy */
8120 /* all except the partial byte at the end */
8121 for (rlen=blen;rlen>=8;rlen-=8)
8123 emitPtrByteSet (rname, p_type,
8124 aopGet (AOP (right), offset++, FALSE, TRUE) );
8126 emitcode ("inc", "%s", rname);
8129 /* If there was a partial byte at the end */
8132 mask = (((unsigned char) -1 << rlen) & 0xff);
8134 if (AOP_TYPE (right) == AOP_LIT)
8136 /* Case with partial byte and literal source
8138 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8139 litval >>= (blen-rlen);
8140 litval &= (~mask) & 0xff;
8141 emitPtrByteGet (rname, p_type, FALSE);
8142 if ((mask|litval)!=0xff)
8143 emitcode ("anl","a,#0x%02x", mask);
8145 emitcode ("orl","a,#0x%02x", litval);
8149 /* Case with partial byte and arbitrary source
8151 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8152 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8154 /* transfer A to B and get next byte */
8155 emitPtrByteGet (rname, p_type, TRUE);
8157 emitcode ("anl", "a,#0x%02x", mask);
8158 emitcode ("orl", "a,b");
8159 if (p_type == GPOINTER)
8160 emitcode ("pop", "b");
8162 emitPtrByteSet (rname, p_type, "a");
8168 /*-----------------------------------------------------------------*/
8169 /* genDataPointerSet - remat pointer to data space */
8170 /*-----------------------------------------------------------------*/
8172 genDataPointerSet (operand * right,
8176 int size, offset = 0;
8177 char *l, buffer[256];
8179 D(emitcode ("; genDataPointerSet",""));
8181 aopOp (right, ic, FALSE);
8183 l = aopGet (AOP (result), 0, FALSE, TRUE);
8184 size = AOP_SIZE (right);
8188 sprintf (buffer, "(%s + %d)", l + 1, offset);
8190 sprintf (buffer, "%s", l + 1);
8191 emitcode ("mov", "%s,%s", buffer,
8192 aopGet (AOP (right), offset++, FALSE, FALSE));
8195 freeAsmop (right, NULL, ic, TRUE);
8196 freeAsmop (result, NULL, ic, TRUE);
8199 /*-----------------------------------------------------------------*/
8200 /* genNearPointerSet - emitcode for near pointer put */
8201 /*-----------------------------------------------------------------*/
8203 genNearPointerSet (operand * right,
8211 sym_link *retype, *letype;
8212 sym_link *ptype = operandType (result);
8214 D(emitcode ("; genNearPointerSet",""));
8216 retype = getSpec (operandType (right));
8217 letype = getSpec (ptype);
8218 aopOp (result, ic, FALSE);
8220 /* if the result is rematerializable &
8221 in data space & not a bit variable */
8222 if (AOP_TYPE (result) == AOP_IMMD &&
8223 DCL_TYPE (ptype) == POINTER &&
8224 !IS_BITVAR (retype) &&
8225 !IS_BITVAR (letype))
8227 genDataPointerSet (right, result, ic);
8231 /* if the value is already in a pointer register
8232 then don't need anything more */
8233 if (!AOP_INPREG (AOP (result)))
8236 //AOP_TYPE (result) == AOP_STK
8240 // Aha, it is a pointer, just in disguise.
8241 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8244 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8245 __FILE__, __LINE__);
8250 emitcode ("mov", "a%s,%s", rname + 1, rname);
8251 rname++; // skip the '@'.
8256 /* otherwise get a free pointer register */
8258 preg = getFreePtr (ic, &aop, FALSE);
8259 emitcode ("mov", "%s,%s",
8261 aopGet (AOP (result), 0, FALSE, TRUE));
8267 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8270 aopOp (right, ic, FALSE);
8272 /* if bitfield then unpack the bits */
8273 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8274 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8277 /* we have can just get the values */
8278 int size = AOP_SIZE (right);
8283 l = aopGet (AOP (right), offset, FALSE, TRUE);
8287 emitcode ("mov", "@%s,a", rname);
8290 emitcode ("mov", "@%s,%s", rname, l);
8292 emitcode ("inc", "%s", rname);
8297 /* now some housekeeping stuff */
8298 if (aop) /* we had to allocate for this iCode */
8301 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8302 freeAsmop (NULL, aop, ic, TRUE);
8306 /* we did not allocate which means left
8307 already in a pointer register, then
8308 if size > 0 && this could be used again
8309 we have to point it back to where it
8311 if ((AOP_SIZE (right) > 1 &&
8312 !OP_SYMBOL (result)->remat &&
8313 (OP_SYMBOL (result)->liveTo > ic->seq ||
8317 int size = AOP_SIZE (right) - 1;
8319 emitcode ("dec", "%s", rname);
8324 if (pi) pi->generated = 1;
8325 freeAsmop (result, NULL, ic, TRUE);
8326 freeAsmop (right, NULL, ic, TRUE);
8329 /*-----------------------------------------------------------------*/
8330 /* genPagedPointerSet - emitcode for Paged pointer put */
8331 /*-----------------------------------------------------------------*/
8333 genPagedPointerSet (operand * right,
8341 sym_link *retype, *letype;
8343 D(emitcode ("; genPagedPointerSet",""));
8345 retype = getSpec (operandType (right));
8346 letype = getSpec (operandType (result));
8348 aopOp (result, ic, FALSE);
8350 /* if the value is already in a pointer register
8351 then don't need anything more */
8352 if (!AOP_INPREG (AOP (result)))
8354 /* otherwise get a free pointer register */
8356 preg = getFreePtr (ic, &aop, FALSE);
8357 emitcode ("mov", "%s,%s",
8359 aopGet (AOP (result), 0, FALSE, TRUE));
8363 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8365 aopOp (right, ic, FALSE);
8367 /* if bitfield then unpack the bits */
8368 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8369 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8372 /* we have can just get the values */
8373 int size = AOP_SIZE (right);
8378 l = aopGet (AOP (right), offset, FALSE, TRUE);
8381 emitcode ("movx", "@%s,a", rname);
8384 emitcode ("inc", "%s", rname);
8390 /* now some housekeeping stuff */
8391 if (aop) /* we had to allocate for this iCode */
8394 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8395 freeAsmop (NULL, aop, ic, TRUE);
8399 /* we did not allocate which means left
8400 already in a pointer register, then
8401 if size > 0 && this could be used again
8402 we have to point it back to where it
8404 if (AOP_SIZE (right) > 1 &&
8405 !OP_SYMBOL (result)->remat &&
8406 (OP_SYMBOL (result)->liveTo > ic->seq ||
8409 int size = AOP_SIZE (right) - 1;
8411 emitcode ("dec", "%s", rname);
8416 if (pi) pi->generated = 1;
8417 freeAsmop (result, NULL, ic, TRUE);
8418 freeAsmop (right, NULL, ic, TRUE);
8423 /*-----------------------------------------------------------------*/
8424 /* genFarPointerSet - set value from far space */
8425 /*-----------------------------------------------------------------*/
8427 genFarPointerSet (operand * right,
8428 operand * result, iCode * ic, iCode * pi)
8431 sym_link *retype = getSpec (operandType (right));
8432 sym_link *letype = getSpec (operandType (result));
8434 D(emitcode ("; genFarPointerSet",""));
8436 aopOp (result, ic, FALSE);
8437 loadDptrFromOperand (result, FALSE);
8439 /* so dptr know contains the address */
8440 aopOp (right, ic, FALSE);
8442 /* if bit then unpack */
8443 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8444 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8447 size = AOP_SIZE (right);
8452 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8454 emitcode ("movx", "@dptr,a");
8456 emitcode ("inc", "dptr");
8459 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8460 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8461 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8464 freeAsmop (result, NULL, ic, TRUE);
8465 freeAsmop (right, NULL, ic, TRUE);
8468 /*-----------------------------------------------------------------*/
8469 /* genGenPointerSet - set value from generic pointer space */
8470 /*-----------------------------------------------------------------*/
8472 genGenPointerSet (operand * right,
8473 operand * result, iCode * ic, iCode * pi)
8476 sym_link *retype = getSpec (operandType (right));
8477 sym_link *letype = getSpec (operandType (result));
8479 D(emitcode ("; genGenPointerSet",""));
8481 aopOp (result, ic, FALSE);
8482 loadDptrFromOperand (result, TRUE);
8484 /* so dptr know contains the address */
8485 aopOp (right, ic, FALSE);
8487 /* if bit then unpack */
8488 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8489 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8492 size = AOP_SIZE (right);
8497 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8499 emitcode ("lcall", "__gptrput");
8501 emitcode ("inc", "dptr");
8505 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8506 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8507 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8510 freeAsmop (result, NULL, ic, TRUE);
8511 freeAsmop (right, NULL, ic, TRUE);
8514 /*-----------------------------------------------------------------*/
8515 /* genPointerSet - stores the value into a pointer location */
8516 /*-----------------------------------------------------------------*/
8518 genPointerSet (iCode * ic, iCode *pi)
8520 operand *right, *result;
8521 sym_link *type, *etype;
8524 D(emitcode ("; genPointerSet",""));
8526 right = IC_RIGHT (ic);
8527 result = IC_RESULT (ic);
8529 /* depending on the type of pointer we need to
8530 move it to the correct pointer register */
8531 type = operandType (result);
8532 etype = getSpec (type);
8533 /* if left is of type of pointer then it is simple */
8534 if (IS_PTR (type) && !IS_FUNC (type->next))
8536 p_type = DCL_TYPE (type);
8540 /* we have to go by the storage class */
8541 p_type = PTR_TYPE (SPEC_OCLS (etype));
8544 /* special case when cast remat */
8545 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8546 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8547 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8548 type = operandType (result);
8549 p_type = DCL_TYPE (type);
8551 /* now that we have the pointer type we assign
8552 the pointer values */
8558 genNearPointerSet (right, result, ic, pi);
8562 genPagedPointerSet (right, result, ic, pi);
8566 genFarPointerSet (right, result, ic, pi);
8570 genGenPointerSet (right, result, ic, pi);
8574 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8575 "genPointerSet: illegal pointer type");
8580 /*-----------------------------------------------------------------*/
8581 /* genIfx - generate code for Ifx statement */
8582 /*-----------------------------------------------------------------*/
8584 genIfx (iCode * ic, iCode * popIc)
8586 operand *cond = IC_COND (ic);
8589 D(emitcode ("; genIfx",""));
8591 aopOp (cond, ic, FALSE);
8593 /* get the value into acc */
8594 if (AOP_TYPE (cond) != AOP_CRY)
8598 /* the result is now in the accumulator */
8599 freeAsmop (cond, NULL, ic, TRUE);
8601 /* if there was something to be popped then do it */
8605 /* if the condition is a bit variable */
8606 if (isbit && IS_ITEMP (cond) &&
8608 genIfxJump (ic, SPIL_LOC (cond)->rname);
8609 else if (isbit && !IS_ITEMP (cond))
8610 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8612 genIfxJump (ic, "a");
8617 /*-----------------------------------------------------------------*/
8618 /* genAddrOf - generates code for address of */
8619 /*-----------------------------------------------------------------*/
8621 genAddrOf (iCode * ic)
8623 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8626 D(emitcode ("; genAddrOf",""));
8628 aopOp (IC_RESULT (ic), ic, FALSE);
8630 /* if the operand is on the stack then we
8631 need to get the stack offset of this
8635 /* if it has an offset then we need to compute
8639 emitcode ("mov", "a,_bp");
8640 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8641 ((char) (sym->stack - _G.nRegsSaved)) :
8642 ((char) sym->stack)) & 0xff);
8643 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8647 /* we can just move _bp */
8648 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8650 /* fill the result with zero */
8651 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8656 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8662 /* object not on stack then we need the name */
8663 size = AOP_SIZE (IC_RESULT (ic));
8668 char s[SDCC_NAME_MAX];
8670 sprintf (s, "#(%s >> %d)",
8674 sprintf (s, "#%s", sym->rname);
8675 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8683 /*-----------------------------------------------------------------*/
8684 /* genFarFarAssign - assignment when both are in far space */
8685 /*-----------------------------------------------------------------*/
8687 genFarFarAssign (operand * result, operand * right, iCode * ic)
8689 int size = AOP_SIZE (right);
8693 D(emitcode ("; genFarFarAssign",""));
8695 /* first push the right side on to the stack */
8698 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8700 emitcode ("push", "acc");
8703 freeAsmop (right, NULL, ic, FALSE);
8704 /* now assign DPTR to result */
8705 aopOp (result, ic, FALSE);
8706 size = AOP_SIZE (result);
8709 emitcode ("pop", "acc");
8710 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8712 freeAsmop (result, NULL, ic, FALSE);
8716 /*-----------------------------------------------------------------*/
8717 /* genAssign - generate code for assignment */
8718 /*-----------------------------------------------------------------*/
8720 genAssign (iCode * ic)
8722 operand *result, *right;
8724 unsigned long lit = 0L;
8726 D(emitcode("; genAssign",""));
8728 result = IC_RESULT (ic);
8729 right = IC_RIGHT (ic);
8731 /* if they are the same */
8732 if (operandsEqu (result, right) &&
8733 !isOperandVolatile (result, FALSE) &&
8734 !isOperandVolatile (right, FALSE))
8737 aopOp (right, ic, FALSE);
8739 /* special case both in far space */
8740 if (AOP_TYPE (right) == AOP_DPTR &&
8741 IS_TRUE_SYMOP (result) &&
8742 isOperandInFarSpace (result))
8745 genFarFarAssign (result, right, ic);
8749 aopOp (result, ic, TRUE);
8751 /* if they are the same registers */
8752 if (sameRegs (AOP (right), AOP (result)) &&
8753 !isOperandVolatile (result, FALSE) &&
8754 !isOperandVolatile (right, FALSE))
8757 /* if the result is a bit */
8758 if (AOP_TYPE (result) == AOP_CRY)
8761 /* if the right size is a literal then
8762 we know what the value is */
8763 if (AOP_TYPE (right) == AOP_LIT)
8765 if (((int) operandLitValue (right)))
8766 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8768 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8772 /* the right is also a bit variable */
8773 if (AOP_TYPE (right) == AOP_CRY)
8775 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8776 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8782 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8786 /* bit variables done */
8788 size = AOP_SIZE (result);
8790 if (AOP_TYPE (right) == AOP_LIT)
8791 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8793 (AOP_TYPE (result) != AOP_REG) &&
8794 (AOP_TYPE (right) == AOP_LIT) &&
8795 !IS_FLOAT (operandType (right)) &&
8798 emitcode ("clr", "a");
8801 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8802 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8804 aopPut (AOP (result),
8805 aopGet (AOP (right), size, FALSE, FALSE),
8807 isOperandVolatile (result, FALSE));
8814 aopPut (AOP (result),
8815 aopGet (AOP (right), offset, FALSE, FALSE),
8817 isOperandVolatile (result, FALSE));
8823 freeAsmop (right, NULL, ic, TRUE);
8824 freeAsmop (result, NULL, ic, TRUE);
8827 /*-----------------------------------------------------------------*/
8828 /* genJumpTab - genrates code for jump table */
8829 /*-----------------------------------------------------------------*/
8831 genJumpTab (iCode * ic)
8836 D(emitcode ("; genJumpTab",""));
8838 aopOp (IC_JTCOND (ic), ic, FALSE);
8839 /* get the condition into accumulator */
8840 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8842 /* multiply by three */
8843 emitcode ("add", "a,acc");
8844 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8845 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8847 jtab = newiTempLabel (NULL);
8848 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8849 emitcode ("jmp", "@a+dptr");
8850 emitcode ("", "%05d$:", jtab->key + 100);
8851 /* now generate the jump labels */
8852 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8853 jtab = setNextItem (IC_JTLABELS (ic)))
8854 emitcode ("ljmp", "%05d$", jtab->key + 100);
8858 /*-----------------------------------------------------------------*/
8859 /* genCast - gen code for casting */
8860 /*-----------------------------------------------------------------*/
8862 genCast (iCode * ic)
8864 operand *result = IC_RESULT (ic);
8865 sym_link *ctype = operandType (IC_LEFT (ic));
8866 sym_link *rtype = operandType (IC_RIGHT (ic));
8867 operand *right = IC_RIGHT (ic);
8870 D(emitcode("; genCast",""));
8872 /* if they are equivalent then do nothing */
8873 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8876 aopOp (right, ic, FALSE);
8877 aopOp (result, ic, FALSE);
8879 /* if the result is a bit (and not a bitfield) */
8880 // if (AOP_TYPE (result) == AOP_CRY)
8881 if (IS_BITVAR (OP_SYMBOL (result)->type)
8882 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8884 /* if the right size is a literal then
8885 we know what the value is */
8886 if (AOP_TYPE (right) == AOP_LIT)
8888 if (((int) operandLitValue (right)))
8889 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8891 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8896 /* the right is also a bit variable */
8897 if (AOP_TYPE (right) == AOP_CRY)
8899 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8900 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8906 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8911 /* if they are the same size : or less */
8912 if (AOP_SIZE (result) <= AOP_SIZE (right))
8915 /* if they are in the same place */
8916 if (sameRegs (AOP (right), AOP (result)))
8919 /* if they in different places then copy */
8920 size = AOP_SIZE (result);
8924 aopPut (AOP (result),
8925 aopGet (AOP (right), offset, FALSE, FALSE),
8927 isOperandVolatile (result, FALSE));
8934 /* if the result is of type pointer */
8939 sym_link *type = operandType (right);
8940 sym_link *etype = getSpec (type);
8942 /* pointer to generic pointer */
8943 if (IS_GENPTR (ctype))
8946 p_type = DCL_TYPE (type);
8949 if (SPEC_SCLS(etype)==S_REGISTER) {
8950 // let's assume it is a generic pointer
8953 /* we have to go by the storage class */
8954 p_type = PTR_TYPE (SPEC_OCLS (etype));
8958 /* the first two bytes are known */
8959 size = GPTRSIZE - 1;
8963 aopPut (AOP (result),
8964 aopGet (AOP (right), offset, FALSE, FALSE),
8966 isOperandVolatile (result, FALSE));
8969 /* the last byte depending on type */
8971 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8976 // pointerTypeToGPByte will have bitched.
8980 sprintf(gpValStr, "#0x%d", gpVal);
8981 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8986 /* just copy the pointers */
8987 size = AOP_SIZE (result);
8991 aopPut (AOP (result),
8992 aopGet (AOP (right), offset, FALSE, FALSE),
8994 isOperandVolatile (result, FALSE));
9000 /* so we now know that the size of destination is greater
9001 than the size of the source */
9002 /* we move to result for the size of source */
9003 size = AOP_SIZE (right);
9007 aopPut (AOP (result),
9008 aopGet (AOP (right), offset, FALSE, FALSE),
9010 isOperandVolatile (result, FALSE));
9014 /* now depending on the sign of the source && destination */
9015 size = AOP_SIZE (result) - AOP_SIZE (right);
9016 /* if unsigned or not an integral type */
9017 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9020 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9024 /* we need to extend the sign :{ */
9025 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9028 emitcode ("rlc", "a");
9029 emitcode ("subb", "a,acc");
9031 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9034 /* we are done hurray !!!! */
9037 freeAsmop (right, NULL, ic, TRUE);
9038 freeAsmop (result, NULL, ic, TRUE);
9042 /*-----------------------------------------------------------------*/
9043 /* genDjnz - generate decrement & jump if not zero instrucion */
9044 /*-----------------------------------------------------------------*/
9046 genDjnz (iCode * ic, iCode * ifx)
9052 D(emitcode ("; genDjnz",""));
9054 /* if the if condition has a false label
9055 then we cannot save */
9059 /* if the minus is not of the form
9061 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9062 !IS_OP_LITERAL (IC_RIGHT (ic)))
9065 if (operandLitValue (IC_RIGHT (ic)) != 1)
9068 /* if the size of this greater than one then no
9070 if (getSize (operandType (IC_RESULT (ic))) > 1)
9073 /* otherwise we can save BIG */
9074 lbl = newiTempLabel (NULL);
9075 lbl1 = newiTempLabel (NULL);
9077 aopOp (IC_RESULT (ic), ic, FALSE);
9079 if (AOP_NEEDSACC(IC_RESULT(ic)))
9081 /* If the result is accessed indirectly via
9082 * the accumulator, we must explicitly write
9083 * it back after the decrement.
9085 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9087 if (strcmp(rByte, "a"))
9089 /* Something is hopelessly wrong */
9090 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9091 __FILE__, __LINE__);
9092 /* We can just give up; the generated code will be inefficient,
9095 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9098 emitcode ("dec", "%s", rByte);
9099 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9100 emitcode ("jnz", "%05d$", lbl->key + 100);
9102 else if (IS_AOP_PREG (IC_RESULT (ic)))
9104 emitcode ("dec", "%s",
9105 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9106 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9107 emitcode ("jnz", "%05d$", lbl->key + 100);
9111 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9114 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9115 emitcode ("", "%05d$:", lbl->key + 100);
9116 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9117 emitcode ("", "%05d$:", lbl1->key + 100);
9119 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9124 /*-----------------------------------------------------------------*/
9125 /* genReceive - generate code for a receive iCode */
9126 /*-----------------------------------------------------------------*/
9128 genReceive (iCode * ic)
9130 int size = getSize (operandType (IC_RESULT (ic)));
9132 D(emitcode ("; genReceive",""));
9134 if (ic->argreg == 1) { /* first parameter */
9135 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9136 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9137 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9143 for (offset = 0; offset<size; offset++)
9144 if (!strcmp (fReturn[offset], "a"))
9149 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9151 for (offset = size-1; offset>0; offset--)
9152 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9153 emitcode("mov","a,%s", fReturn[0]);
9155 aopOp (IC_RESULT (ic), ic, FALSE);
9157 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9158 isOperandVolatile (IC_RESULT (ic), FALSE));
9159 for (offset = 1; offset<size; offset++)
9160 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9161 isOperandVolatile (IC_RESULT (ic), FALSE));
9167 if (getTempRegs(tempRegs, size, ic))
9169 for (offset = 0; offset<size; offset++)
9170 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9171 aopOp (IC_RESULT (ic), ic, FALSE);
9172 for (offset = 0; offset<size; offset++)
9173 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9174 isOperandVolatile (IC_RESULT (ic), FALSE));
9179 offset = fReturnSizeMCS51 - size;
9181 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9182 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9185 aopOp (IC_RESULT (ic), ic, FALSE);
9186 size = AOP_SIZE (IC_RESULT (ic));
9189 emitcode ("pop", "acc");
9190 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9195 aopOp (IC_RESULT (ic), ic, FALSE);
9197 assignResultValue (IC_RESULT (ic));
9199 } else { /* second receive onwards */
9201 aopOp (IC_RESULT (ic), ic, FALSE);
9202 rb1off = ic->argreg;
9204 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9212 /*-----------------------------------------------------------------*/
9213 /* genDummyRead - generate code for dummy read of volatiles */
9214 /*-----------------------------------------------------------------*/
9216 genDummyRead (iCode * ic)
9221 D(emitcode("; genDummyRead",""));
9224 if (op && IS_SYMOP (op))
9226 aopOp (op, ic, FALSE);
9228 /* if the result is a bit */
9229 if (AOP_TYPE (op) == AOP_CRY)
9230 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9233 /* bit variables done */
9235 size = AOP_SIZE (op);
9239 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9244 freeAsmop (op, NULL, ic, TRUE);
9248 if (op && IS_SYMOP (op))
9250 aopOp (op, ic, FALSE);
9252 /* if the result is a bit */
9253 if (AOP_TYPE (op) == AOP_CRY)
9254 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9257 /* bit variables done */
9259 size = AOP_SIZE (op);
9263 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9268 freeAsmop (op, NULL, ic, TRUE);
9272 /*-----------------------------------------------------------------*/
9273 /* genCritical - generate code for start of a critical sequence */
9274 /*-----------------------------------------------------------------*/
9276 genCritical (iCode *ic)
9278 symbol *tlbl = newiTempLabel (NULL);
9280 D(emitcode("; genCritical",""));
9283 aopOp (IC_RESULT (ic), ic, TRUE);
9285 emitcode ("setb", "c");
9286 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9287 emitcode ("clr", "c");
9288 emitcode ("", "%05d$:", (tlbl->key + 100));
9291 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9293 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9299 /*-----------------------------------------------------------------*/
9300 /* genEndCritical - generate code for end of a critical sequence */
9301 /*-----------------------------------------------------------------*/
9303 genEndCritical (iCode *ic)
9305 D(emitcode("; genEndCritical",""));
9309 aopOp (IC_RIGHT (ic), ic, FALSE);
9310 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9312 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9313 emitcode ("mov", "ea,c");
9317 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9318 emitcode ("rrc", "a");
9319 emitcode ("mov", "ea,c");
9321 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9325 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9326 emitcode ("mov", "ea,c");
9331 /*-----------------------------------------------------------------*/
9332 /* gen51Code - generate code for 8051 based controllers */
9333 /*-----------------------------------------------------------------*/
9335 gen51Code (iCode * lic)
9340 _G.currentFunc = NULL;
9341 lineHead = lineCurr = NULL;
9343 /* print the allocation information */
9344 if (allocInfo && currFunc)
9345 printAllocInfo (currFunc, codeOutFile);
9346 /* if debug information required */
9347 if (options.debug && currFunc)
9349 debugFile->writeFunction(currFunc);
9351 if (IS_STATIC (currFunc->etype))
9352 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9354 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9357 /* stack pointer name */
9358 if (options.useXstack)
9364 for (ic = lic; ic; ic = ic->next)
9366 _G.current_iCode = ic;
9368 if (ic->lineno && cln != ic->lineno)
9373 emitcode ("", "C$%s$%d$%d$%d ==.",
9374 FileBaseName (ic->filename), ic->lineno,
9375 ic->level, ic->block);
9378 if (!options.noCcodeInAsm) {
9379 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9380 printCLine(ic->filename, ic->lineno));
9384 if (options.iCodeInAsm) {
9388 for (i=0; i<8; i++) {
9389 sprintf (®sInUse[i],
9390 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9393 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9395 /* if the result is marked as
9396 spilt and rematerializable or code for
9397 this has already been generated then
9399 if (resultRemat (ic) || ic->generated)
9402 /* depending on the operation */
9422 /* IPOP happens only when trying to restore a
9423 spilt live range, if there is an ifx statement
9424 following this pop then the if statement might
9425 be using some of the registers being popped which
9426 would destory the contents of the register so
9427 we need to check for this condition and handle it */
9429 ic->next->op == IFX &&
9430 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9431 genIfx (ic->next, ic);
9449 genEndFunction (ic);
9469 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9486 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9490 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9497 /* note these two are xlated by algebraic equivalence
9498 during parsing SDCC.y */
9499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9500 "got '>=' or '<=' shouldn't have come here");
9504 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9516 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9520 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9524 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9551 case GET_VALUE_AT_ADDRESS:
9552 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9556 if (POINTER_SET (ic))
9557 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9583 addSet (&_G.sendSet, ic);
9586 case DUMMY_READ_VOLATILE:
9595 genEndCritical (ic);
9607 _G.current_iCode = NULL;
9609 /* now we are ready to call the
9610 peep hole optimizer */
9611 if (!options.nopeep)
9612 peepHole (&lineHead);
9614 /* now do the actual printing */
9615 printLine (lineHead, codeOutFile);