1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
81 static char *rb1regs[] = {
82 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
85 extern int mcs51_ptrRegReq;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saveRBank (int, iCode *, bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
94 #define CLRC emitcode("clr","c")
95 #define SETC emitcode("setb","c")
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
100 static unsigned char SLMask[] =
101 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] =
104 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105 0x07, 0x03, 0x01, 0x00};
112 /*-----------------------------------------------------------------*/
113 /* emitcode - writes the code into a file : for now it is simple */
114 /*-----------------------------------------------------------------*/
116 emitcode (char *inst, const char *fmt,...)
119 char lb[INITIAL_INLINEASM];
127 sprintf (lb, "%s\t", inst);
129 sprintf (lb, "%s", inst);
130 vsprintf (lb + (strlen (lb)), fmt, ap);
133 vsprintf (lb, fmt, ap);
135 while (isspace (*lbp))
138 // printf ("%s\n", lb);
141 lineCurr = (lineCurr ?
142 connectLine (lineCurr, newLineNode (lb)) :
143 (lineHead = newLineNode (lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
146 lineCurr->ic = _G.current_iCode;
147 lineCurr->isComment = (*lbp==';');
151 /*-----------------------------------------------------------------*/
152 /* mova - moves specified value into accumulator */
153 /*-----------------------------------------------------------------*/
157 /* do some early peephole optimization */
158 if (!strcmp(x, "a") || !strcmp(x, "acc"))
161 emitcode("mov","a,%s", x);
164 /*-----------------------------------------------------------------*/
165 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
166 /*-----------------------------------------------------------------*/
168 getFreePtr (iCode * ic, asmop ** aopp, bool result)
170 bool r0iu = FALSE, r1iu = FALSE;
171 bool r0ou = FALSE, r1ou = FALSE;
173 /* the logic: if r0 & r1 used in the instruction
174 then we are in trouble otherwise */
176 /* first check if r0 & r1 are used by this
177 instruction, in which case we are in trouble */
178 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
179 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
185 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
187 /* if no usage of r0 then return it */
190 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
191 (*aopp)->type = AOP_R0;
193 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
196 /* if no usage of r1 then return it */
199 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
200 (*aopp)->type = AOP_R1;
202 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
205 /* now we know they both have usage */
206 /* if r0 not used in this instruction */
209 /* push it if not already pushed */
212 emitcode ("push", "%s",
213 mcs51_regWithIdx (R0_IDX)->dname);
217 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
218 (*aopp)->type = AOP_R0;
220 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
223 /* if r1 not used then */
227 /* push it if not already pushed */
230 emitcode ("push", "%s",
231 mcs51_regWithIdx (R1_IDX)->dname);
235 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
236 (*aopp)->type = AOP_R1;
237 return mcs51_regWithIdx (R1_IDX);
240 /* I said end of world, but not quite end of world yet */
242 /* we can push it on the stack */
243 (*aopp)->type = AOP_STK;
246 /* in the case that result AND left AND right needs a pointer reg
247 we can safely use the result's */
248 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
249 (*aopp)->type = AOP_R0;
250 return mcs51_regWithIdx (R0_IDX);
252 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
253 (*aopp)->type = AOP_R1;
254 return mcs51_regWithIdx (R1_IDX);
258 /* now this is REALLY the end of the world */
259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
260 "getFreePtr should never reach here");
265 /*-----------------------------------------------------------------*/
266 /* getTempRegs - initialize an array of pointers to GPR registers */
267 /* that are not in use. Returns 1 if the requested */
268 /* number of registers were available, 0 otherwise. */
269 /*-----------------------------------------------------------------*/
271 getTempRegs(regs **tempRegs, int size, iCode *ic)
278 ic = _G.current_iCode;
284 freeRegs = newBitVect(8);
285 bitVectSetBit (freeRegs, R2_IDX);
286 bitVectSetBit (freeRegs, R3_IDX);
287 bitVectSetBit (freeRegs, R4_IDX);
288 bitVectSetBit (freeRegs, R5_IDX);
289 bitVectSetBit (freeRegs, R6_IDX);
290 bitVectSetBit (freeRegs, R7_IDX);
292 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
294 bitVect * newfreeRegs;
295 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
296 freeBitVect(freeRegs);
297 freeRegs = newfreeRegs;
299 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
302 for (i=0; i<freeRegs->size; i++)
304 if (bitVectBitValue(freeRegs,i))
305 tempRegs[offset++] = mcs51_regWithIdx(i);
308 freeBitVect(freeRegs);
313 freeBitVect(freeRegs);
318 /*-----------------------------------------------------------------*/
319 /* newAsmop - creates a new asmOp */
320 /*-----------------------------------------------------------------*/
322 newAsmop (short type)
326 aop = Safe_calloc (1, sizeof (asmop));
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type */
333 /*-----------------------------------------------------------------*/
335 pointerCode (sym_link * etype)
338 return PTR_TYPE (SPEC_OCLS (etype));
343 /*-----------------------------------------------------------------*/
344 /* leftRightUseAcc - returns size of accumulator use by operands */
345 /*-----------------------------------------------------------------*/
347 leftRightUseAcc(iCode *ic)
356 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
357 "null iCode pointer");
364 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
367 size = getSize (OP_SYMBOL (op)->type);
372 else if (ic->op == JUMPTABLE)
375 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
378 size = getSize (OP_SYMBOL (op)->type);
386 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
389 size = getSize (OP_SYMBOL (op)->type);
394 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
397 size = getSize (OP_SYMBOL (op)->type);
410 /*-----------------------------------------------------------------*/
411 /* aopForSym - for a true symbol */
412 /*-----------------------------------------------------------------*/
414 aopForSym (iCode * ic, symbol * sym, bool result)
419 wassertl (ic != NULL, "Got a null iCode");
420 wassertl (sym != NULL, "Got a null symbol");
422 space = SPEC_OCLS (sym->etype);
424 /* if already has one */
428 /* assign depending on the storage class */
429 /* if it is on the stack or indirectly addressable */
430 /* space we need to assign either r0 or r1 to it */
431 if (sym->onStack || sym->iaccess)
433 sym->aop = aop = newAsmop (0);
434 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
435 aop->size = getSize (sym->type);
437 /* now assign the address of the variable to
438 the pointer register */
439 if (aop->type != AOP_STK)
444 if (_G.accInUse || leftRightUseAcc (ic))
445 emitcode ("push", "acc");
447 emitcode ("mov", "a,_bp");
448 emitcode ("add", "a,#0x%02x",
450 ((char) (sym->stack - _G.nRegsSaved)) :
451 ((char) sym->stack)) & 0xff);
452 emitcode ("mov", "%s,a",
453 aop->aopu.aop_ptr->name);
455 if (_G.accInUse || leftRightUseAcc (ic))
456 emitcode ("pop", "acc");
459 emitcode ("mov", "%s,#%s",
460 aop->aopu.aop_ptr->name,
462 aop->paged = space->paged;
465 aop->aopu.aop_stk = sym->stack;
469 /* if in bit space */
470 if (IN_BITSPACE (space))
472 sym->aop = aop = newAsmop (AOP_CRY);
473 aop->aopu.aop_dir = sym->rname;
474 aop->size = getSize (sym->type);
477 /* if it is in direct space */
478 if (IN_DIRSPACE (space))
480 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
481 //printTypeChainRaw(sym->type, NULL);
482 //printf("space = %s\n", space ? space->sname : "NULL");
483 sym->aop = aop = newAsmop (AOP_DIR);
484 aop->aopu.aop_dir = sym->rname;
485 aop->size = getSize (sym->type);
489 /* special case for a function */
490 if (IS_FUNC (sym->type))
492 sym->aop = aop = newAsmop (AOP_IMMD);
493 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
494 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
495 aop->size = FPTRSIZE;
499 /* only remaining is far space */
500 /* in which case DPTR gets the address */
501 sym->aop = aop = newAsmop (AOP_DPTR);
502 emitcode ("mov", "dptr,#%s", sym->rname);
503 aop->size = getSize (sym->type);
505 /* if it is in code space */
506 if (IN_CODESPACE (space))
512 /*-----------------------------------------------------------------*/
513 /* aopForRemat - rematerialzes an object */
514 /*-----------------------------------------------------------------*/
516 aopForRemat (symbol * sym)
518 iCode *ic = sym->rematiCode;
519 asmop *aop = newAsmop (AOP_IMMD);
526 val += (int) operandLitValue (IC_RIGHT (ic));
527 else if (ic->op == '-')
528 val -= (int) operandLitValue (IC_RIGHT (ic));
529 else if (IS_CAST_ICODE(ic)) {
530 sym_link *from_type = operandType(IC_RIGHT(ic));
531 aop->aopu.aop_immd.from_cast_remat = 1;
532 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
533 ptr_type = DCL_TYPE(from_type);
534 if (ptr_type == IPOINTER) {
541 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
545 sprintf (buffer, "(%s %c 0x%04x)",
546 OP_SYMBOL (IC_LEFT (ic))->rname,
547 val >= 0 ? '+' : '-',
550 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
552 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
553 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
554 /* set immd2 field if required */
555 if (aop->aopu.aop_immd.from_cast_remat) {
556 sprintf(buffer,"#0x%02x",ptr_type);
557 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
558 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
564 /*-----------------------------------------------------------------*/
565 /* regsInCommon - two operands have some registers in common */
566 /*-----------------------------------------------------------------*/
568 regsInCommon (operand * op1, operand * op2)
573 /* if they have registers in common */
574 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
577 sym1 = OP_SYMBOL (op1);
578 sym2 = OP_SYMBOL (op2);
580 if (sym1->nRegs == 0 || sym2->nRegs == 0)
583 for (i = 0; i < sym1->nRegs; i++)
589 for (j = 0; j < sym2->nRegs; j++)
594 if (sym2->regs[j] == sym1->regs[i])
602 /*-----------------------------------------------------------------*/
603 /* operandsEqu - equivalent */
604 /*-----------------------------------------------------------------*/
606 operandsEqu (operand * op1, operand * op2)
610 /* if they not symbols */
611 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
614 sym1 = OP_SYMBOL (op1);
615 sym2 = OP_SYMBOL (op2);
617 /* if both are itemps & one is spilt
618 and the other is not then false */
619 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
620 sym1->isspilt != sym2->isspilt)
623 /* if they are the same */
627 if (strcmp (sym1->rname, sym2->rname) == 0)
631 /* if left is a tmp & right is not */
632 if (IS_ITEMP (op1) &&
635 (sym1->usl.spillLoc == sym2))
638 if (IS_ITEMP (op2) &&
642 (sym2->usl.spillLoc == sym1))
648 /*-----------------------------------------------------------------*/
649 /* sameRegs - two asmops have the same registers */
650 /*-----------------------------------------------------------------*/
652 sameRegs (asmop * aop1, asmop * aop2)
659 if (aop1->type != AOP_REG ||
660 aop2->type != AOP_REG)
663 if (aop1->size != aop2->size)
666 for (i = 0; i < aop1->size; i++)
667 if (aop1->aopu.aop_reg[i] !=
668 aop2->aopu.aop_reg[i])
674 /*-----------------------------------------------------------------*/
675 /* aopOp - allocates an asmop for an operand : */
676 /*-----------------------------------------------------------------*/
678 aopOp (operand * op, iCode * ic, bool result)
687 /* if this a literal */
688 if (IS_OP_LITERAL (op))
690 op->aop = aop = newAsmop (AOP_LIT);
691 aop->aopu.aop_lit = op->operand.valOperand;
692 aop->size = getSize (operandType (op));
696 /* if already has a asmop then continue */
700 /* if the underlying symbol has a aop */
701 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
703 op->aop = OP_SYMBOL (op)->aop;
707 /* if this is a true symbol */
708 if (IS_TRUE_SYMOP (op))
710 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
714 /* this is a temporary : this has
720 e) can be a return use only */
722 sym = OP_SYMBOL (op);
724 /* if the type is a conditional */
725 if (sym->regType == REG_CND)
727 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
732 /* if it is spilt then two situations
734 b) has a spill location */
735 if (sym->isspilt || sym->nRegs == 0)
738 /* rematerialize it NOW */
741 sym->aop = op->aop = aop =
743 aop->size = getSize (sym->type);
750 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
751 aop->size = getSize (sym->type);
752 for (i = 0; i < 2; i++)
753 aop->aopu.aop_str[i] = accUse[i];
761 aop = op->aop = sym->aop = newAsmop (AOP_STR);
762 aop->size = getSize (sym->type);
763 for (i = 0; i < fReturnSizeMCS51; i++)
764 aop->aopu.aop_str[i] = fReturn[i];
768 if (sym->usl.spillLoc)
770 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
772 /* force a new aop if sizes differ */
773 sym->usl.spillLoc->aop = NULL;
775 sym->aop = op->aop = aop =
776 aopForSym (ic, sym->usl.spillLoc, result);
777 aop->size = getSize (sym->type);
781 /* else must be a dummy iTemp */
782 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
783 aop->size = getSize (sym->type);
787 /* must be in a register */
788 sym->aop = op->aop = aop = newAsmop (AOP_REG);
789 aop->size = sym->nRegs;
790 for (i = 0; i < sym->nRegs; i++)
791 aop->aopu.aop_reg[i] = sym->regs[i];
794 /*-----------------------------------------------------------------*/
795 /* freeAsmop - free up the asmop given to an operand */
796 /*----------------------------------------------------------------*/
798 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
815 /* depending on the asmop type only three cases need work AOP_RO
816 , AOP_R1 && AOP_STK */
824 emitcode ("pop", "ar0");
828 bitVectUnSetBit (ic->rUsed, R0_IDX);
836 emitcode ("pop", "ar1");
840 bitVectUnSetBit (ic->rUsed, R1_IDX);
846 int stk = aop->aopu.aop_stk + aop->size - 1;
847 bitVectUnSetBit (ic->rUsed, R0_IDX);
848 bitVectUnSetBit (ic->rUsed, R1_IDX);
850 getFreePtr (ic, &aop, FALSE);
854 emitcode ("mov", "a,_bp");
855 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
856 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
860 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
865 emitcode ("pop", "acc");
866 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
869 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
872 freeAsmop (op, NULL, ic, TRUE);
875 emitcode ("pop", "ar1");
881 emitcode ("pop", "ar0");
888 /* all other cases just dealloc */
894 OP_SYMBOL (op)->aop = NULL;
895 /* if the symbol has a spill */
897 SPIL_LOC (op)->aop = NULL;
902 /*-----------------------------------------------------------------*/
903 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
904 /* clobber the accumulator */
905 /*-----------------------------------------------------------------*/
907 aopGetUsesAcc (asmop *aop, int offset)
909 if (offset > (aop->size - 1))
927 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
936 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
942 /* Error case --- will have been caught already */
948 /*-----------------------------------------------------------------*/
949 /* aopGet - for fetching value of the aop */
950 /*-----------------------------------------------------------------*/
952 aopGet (asmop * aop, int offset, bool bit16, bool dname)
957 /* offset is greater than
959 if (offset > (aop->size - 1) &&
960 aop->type != AOP_LIT)
963 /* depending on type */
971 /* if we need to increment it */
972 while (offset > aop->coff)
974 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
978 while (offset < aop->coff)
980 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
987 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988 return (dname ? "acc" : "a");
990 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991 rs = Safe_calloc (1, strlen (s) + 1);
996 if (aop->code && aop->coff==0 && offset>=1) {
997 emitcode ("mov", "a,#0x%02x", offset);
998 emitcode ("movc", "a,@a+dptr");
999 return (dname ? "acc" : "a");
1002 while (offset > aop->coff)
1004 emitcode ("inc", "dptr");
1008 while (offset < aop->coff)
1010 emitcode ("lcall", "__decdptr");
1017 emitcode ("clr", "a");
1018 emitcode ("movc", "a,@a+dptr");
1022 emitcode ("movx", "a,@dptr");
1024 return (dname ? "acc" : "a");
1028 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1029 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1031 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1033 sprintf (s, "#(%s >> %d)",
1034 aop->aopu.aop_immd.aop_immd1,
1038 aop->aopu.aop_immd.aop_immd1);
1039 rs = Safe_calloc (1, strlen (s) + 1);
1045 sprintf (s, "(%s + %d)",
1049 sprintf (s, "%s", aop->aopu.aop_dir);
1050 rs = Safe_calloc (1, strlen (s) + 1);
1056 return aop->aopu.aop_reg[offset]->dname;
1058 return aop->aopu.aop_reg[offset]->name;
1061 emitcode ("clr", "a");
1062 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1063 emitcode ("rlc", "a");
1064 return (dname ? "acc" : "a");
1067 if (!offset && dname)
1069 return aop->aopu.aop_str[offset];
1072 return aopLiteral (aop->aopu.aop_lit, offset);
1076 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1080 return aop->aopu.aop_str[offset];
1084 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1085 "aopget got unsupported aop->type");
1088 /*-----------------------------------------------------------------*/
1089 /* aopPut - puts a string for a aop */
1090 /*-----------------------------------------------------------------*/
1092 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1096 if (aop->size && offset > (aop->size - 1))
1098 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1099 "aopPut got offset > aop->size");
1103 /* will assign value to value */
1104 /* depending on where it is ofcourse */
1108 MOVA (s); /* read s in case it was volatile */
1113 sprintf (d, "(%s + %d)",
1114 aop->aopu.aop_dir, offset);
1116 sprintf (d, "%s", aop->aopu.aop_dir);
1118 if (strcmp (d, s) ||
1120 emitcode ("mov", "%s,%s", d, s);
1125 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1126 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1129 strcmp (s, "r0") == 0 ||
1130 strcmp (s, "r1") == 0 ||
1131 strcmp (s, "r2") == 0 ||
1132 strcmp (s, "r3") == 0 ||
1133 strcmp (s, "r4") == 0 ||
1134 strcmp (s, "r5") == 0 ||
1135 strcmp (s, "r6") == 0 ||
1136 strcmp (s, "r7") == 0)
1137 emitcode ("mov", "%s,%s",
1138 aop->aopu.aop_reg[offset]->dname, s);
1140 emitcode ("mov", "%s,%s",
1141 aop->aopu.aop_reg[offset]->name, s);
1148 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1149 "aopPut writing to code space");
1153 while (offset > aop->coff)
1156 emitcode ("inc", "dptr");
1159 while (offset < aop->coff)
1162 emitcode ("lcall", "__decdptr");
1167 /* if not in accumulater */
1170 emitcode ("movx", "@dptr,a");
1175 while (offset > aop->coff)
1178 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1180 while (offset < aop->coff)
1183 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1190 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1196 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1198 else if (strcmp (s, "r0") == 0 ||
1199 strcmp (s, "r1") == 0 ||
1200 strcmp (s, "r2") == 0 ||
1201 strcmp (s, "r3") == 0 ||
1202 strcmp (s, "r4") == 0 ||
1203 strcmp (s, "r5") == 0 ||
1204 strcmp (s, "r6") == 0 ||
1205 strcmp (s, "r7") == 0)
1208 sprintf (buffer, "a%s", s);
1209 emitcode ("mov", "@%s,%s",
1210 aop->aopu.aop_ptr->name, buffer);
1213 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1218 if (strcmp (s, "a") == 0)
1219 emitcode ("push", "acc");
1223 emitcode ("push", "acc");
1225 emitcode ("push", s);
1231 /* if bit variable */
1232 if (!aop->aopu.aop_dir)
1234 emitcode ("clr", "a");
1235 emitcode ("rlc", "a");
1240 emitcode ("clr", "%s", aop->aopu.aop_dir);
1242 emitcode ("setb", "%s", aop->aopu.aop_dir);
1243 else if (!strcmp (s, "c"))
1244 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1247 if (strcmp (s, "a"))
1252 /* set C, if a >= 1 */
1253 emitcode ("add", "a,#0xff");
1254 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1262 if (strcmp (aop->aopu.aop_str[offset], s) ||
1264 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1269 if (!offset && (strcmp (s, "acc") == 0) &&
1273 if (strcmp (aop->aopu.aop_str[offset], s) &&
1275 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1279 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280 "aopPut got unsupported aop->type");
1288 /*-----------------------------------------------------------------*/
1289 /* pointToEnd :- points to the last byte of the operand */
1290 /*-----------------------------------------------------------------*/
1292 pointToEnd (asmop * aop)
1298 aop->coff = count = (aop->size - 1);
1304 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308 emitcode ("inc", "dptr");
1315 /*-----------------------------------------------------------------*/
1316 /* reAdjustPreg - points a register back to where it should */
1317 /*-----------------------------------------------------------------*/
1319 reAdjustPreg (asmop * aop)
1321 if ((aop->coff==0) || aop->size <= 1)
1329 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1334 emitcode ("lcall", "__decdptr");
1341 #define AOP(op) op->aop
1342 #define AOP_TYPE(op) AOP(op)->type
1343 #define AOP_SIZE(op) AOP(op)->size
1344 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1345 AOP_TYPE(x) == AOP_R0))
1347 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1348 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1350 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1351 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1352 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1355 /*-----------------------------------------------------------------*/
1356 /* opIsGptr: returns non-zero if the passed operand is */
1357 /* a generic pointer type. */
1358 /*-----------------------------------------------------------------*/
1360 opIsGptr (operand * op)
1362 sym_link *type = operandType (op);
1364 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1371 /*-----------------------------------------------------------------*/
1372 /* getDataSize - get the operand data size */
1373 /*-----------------------------------------------------------------*/
1375 getDataSize (operand * op)
1378 size = AOP_SIZE (op);
1379 if (size == GPTRSIZE)
1381 sym_link *type = operandType (op);
1382 if (IS_GENPTR (type))
1384 /* generic pointer; arithmetic operations
1385 * should ignore the high byte (pointer type).
1393 /*-----------------------------------------------------------------*/
1394 /* outAcc - output Acc */
1395 /*-----------------------------------------------------------------*/
1397 outAcc (operand * result)
1400 size = getDataSize (result);
1403 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1406 /* unsigned or positive */
1409 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1414 /*-----------------------------------------------------------------*/
1415 /* outBitC - output a bit C */
1416 /*-----------------------------------------------------------------*/
1418 outBitC (operand * result)
1420 /* if the result is bit */
1421 if (AOP_TYPE (result) == AOP_CRY)
1422 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1425 emitcode ("clr", "a");
1426 emitcode ("rlc", "a");
1431 /*-----------------------------------------------------------------*/
1432 /* toBoolean - emit code for orl a,operator(sizeop) */
1433 /*-----------------------------------------------------------------*/
1435 toBoolean (operand * oper)
1437 int size = AOP_SIZE (oper) - 1;
1439 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1441 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1445 /*-----------------------------------------------------------------*/
1446 /* genNot - generate code for ! operation */
1447 /*-----------------------------------------------------------------*/
1453 D(emitcode ("; genNot",""));
1455 /* assign asmOps to operand & result */
1456 aopOp (IC_LEFT (ic), ic, FALSE);
1457 aopOp (IC_RESULT (ic), ic, TRUE);
1459 /* if in bit space then a special case */
1460 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1462 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1463 emitcode ("cpl", "c");
1464 outBitC (IC_RESULT (ic));
1468 toBoolean (IC_LEFT (ic));
1470 tlbl = newiTempLabel (NULL);
1471 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1472 emitcode ("", "%05d$:", tlbl->key + 100);
1473 outBitC (IC_RESULT (ic));
1476 /* release the aops */
1477 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1478 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* genCpl - generate code for complement */
1484 /*-----------------------------------------------------------------*/
1492 D(emitcode ("; genCpl",""));
1494 /* assign asmOps to operand & result */
1495 aopOp (IC_LEFT (ic), ic, FALSE);
1496 aopOp (IC_RESULT (ic), ic, TRUE);
1498 /* special case if in bit space */
1499 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1501 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1503 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1504 emitcode ("cpl", "c");
1505 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1509 tlbl=newiTempLabel(NULL);
1510 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1511 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1512 IS_AOP_PREG (IC_LEFT (ic)))
1514 emitcode ("cjne", "%s,#0x01,%05d$",
1515 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1520 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1522 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1524 emitcode ("", "%05d$:", tlbl->key + 100);
1525 outBitC (IC_RESULT(ic));
1529 size = AOP_SIZE (IC_RESULT (ic));
1532 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1534 emitcode ("cpl", "a");
1535 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1540 /* release the aops */
1541 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1545 /*-----------------------------------------------------------------*/
1546 /* genUminusFloat - unary minus for floating points */
1547 /*-----------------------------------------------------------------*/
1549 genUminusFloat (operand * op, operand * result)
1551 int size, offset = 0;
1554 D(emitcode ("; genUminusFloat",""));
1556 /* for this we just copy and then flip the bit */
1558 size = AOP_SIZE (op) - 1;
1562 aopPut (AOP (result),
1563 aopGet (AOP (op), offset, FALSE, FALSE),
1565 isOperandVolatile (result, FALSE));
1569 l = aopGet (AOP (op), offset, FALSE, FALSE);
1573 emitcode ("cpl", "acc.7");
1574 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1577 /*-----------------------------------------------------------------*/
1578 /* genUminus - unary minus code generation */
1579 /*-----------------------------------------------------------------*/
1581 genUminus (iCode * ic)
1584 sym_link *optype, *rtype;
1587 D(emitcode ("; genUminus",""));
1590 aopOp (IC_LEFT (ic), ic, FALSE);
1591 aopOp (IC_RESULT (ic), ic, TRUE);
1593 /* if both in bit space then special
1595 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1596 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1599 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1600 emitcode ("cpl", "c");
1601 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1605 optype = operandType (IC_LEFT (ic));
1606 rtype = operandType (IC_RESULT (ic));
1608 /* if float then do float stuff */
1609 if (IS_FLOAT (optype))
1611 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1615 /* otherwise subtract from zero */
1616 size = AOP_SIZE (IC_LEFT (ic));
1621 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1622 if (!strcmp (l, "a"))
1626 emitcode ("cpl", "a");
1627 emitcode ("addc", "a,#0");
1633 emitcode ("clr", "a");
1634 emitcode ("subb", "a,%s", l);
1636 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1639 /* if any remaining bytes in the result */
1640 /* we just need to propagate the sign */
1641 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1643 emitcode ("rlc", "a");
1644 emitcode ("subb", "a,acc");
1646 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1650 /* release the aops */
1651 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1652 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* saveRegisters - will look for a call and save the registers */
1657 /*-----------------------------------------------------------------*/
1659 saveRegisters (iCode * lic)
1666 for (ic = lic; ic; ic = ic->next)
1667 if (ic->op == CALL || ic->op == PCALL)
1672 fprintf (stderr, "found parameter push with no function call\n");
1676 /* if the registers have been saved already or don't need to be then
1680 if (IS_SYMOP(IC_LEFT(ic)) &&
1681 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1682 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1685 /* safe the registers in use at this time but skip the
1686 ones for the result */
1687 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1688 mcs51_rUmaskForOp (IC_RESULT(ic)));
1691 if (options.useXstack)
1693 if (bitVectBitValue (rsave, R0_IDX))
1694 emitcode ("mov", "b,r0");
1695 emitcode ("mov", "r0,%s", spname);
1696 for (i = 0; i < mcs51_nRegs; i++)
1698 if (bitVectBitValue (rsave, i))
1701 emitcode ("mov", "a,b");
1703 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1704 emitcode ("movx", "@r0,a");
1705 emitcode ("inc", "r0");
1708 emitcode ("mov", "%s,r0", spname);
1709 if (bitVectBitValue (rsave, R0_IDX))
1710 emitcode ("mov", "r0,b");
1713 for (i = 0; i < mcs51_nRegs; i++)
1715 if (bitVectBitValue (rsave, i))
1716 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1720 /*-----------------------------------------------------------------*/
1721 /* unsaveRegisters - pop the pushed registers */
1722 /*-----------------------------------------------------------------*/
1724 unsaveRegisters (iCode * ic)
1729 /* restore the registers in use at this time but skip the
1730 ones for the result */
1731 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1732 mcs51_rUmaskForOp (IC_RESULT(ic)));
1734 if (options.useXstack)
1736 emitcode ("mov", "r0,%s", spname);
1737 for (i = mcs51_nRegs; i >= 0; i--)
1739 if (bitVectBitValue (rsave, i))
1741 emitcode ("dec", "r0");
1742 emitcode ("movx", "a,@r0");
1744 emitcode ("mov", "b,a");
1746 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1750 emitcode ("mov", "%s,r0", spname);
1751 if (bitVectBitValue (rsave, R0_IDX))
1752 emitcode ("mov", "r0,b");
1755 for (i = mcs51_nRegs; i >= 0; i--)
1757 if (bitVectBitValue (rsave, i))
1758 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1764 /*-----------------------------------------------------------------*/
1766 /*-----------------------------------------------------------------*/
1768 pushSide (operand * oper, int size)
1773 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1774 if (AOP_TYPE (oper) != AOP_REG &&
1775 AOP_TYPE (oper) != AOP_DIR &&
1778 emitcode ("mov", "a,%s", l);
1779 emitcode ("push", "acc");
1782 emitcode ("push", "%s", l);
1786 /*-----------------------------------------------------------------*/
1787 /* assignResultValue - */
1788 /*-----------------------------------------------------------------*/
1790 assignResultValue (operand * oper)
1793 int size = AOP_SIZE (oper);
1796 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1802 /*-----------------------------------------------------------------*/
1803 /* genXpush - pushes onto the external stack */
1804 /*-----------------------------------------------------------------*/
1806 genXpush (iCode * ic)
1808 asmop *aop = newAsmop (0);
1810 int size, offset = 0;
1812 D(emitcode ("; genXpush",""));
1814 aopOp (IC_LEFT (ic), ic, FALSE);
1815 r = getFreePtr (ic, &aop, FALSE);
1818 emitcode ("mov", "%s,_spx", r->name);
1820 size = AOP_SIZE (IC_LEFT (ic));
1824 char *l = aopGet (AOP (IC_LEFT (ic)),
1825 offset++, FALSE, FALSE);
1827 emitcode ("movx", "@%s,a", r->name);
1828 emitcode ("inc", "%s", r->name);
1833 emitcode ("mov", "_spx,%s", r->name);
1835 freeAsmop (NULL, aop, ic, TRUE);
1836 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1839 /*-----------------------------------------------------------------*/
1840 /* genIpush - genrate code for pushing this gets a little complex */
1841 /*-----------------------------------------------------------------*/
1843 genIpush (iCode * ic)
1845 int size, offset = 0;
1848 D(emitcode ("; genIpush",""));
1850 /* if this is not a parm push : ie. it is spill push
1851 and spill push is always done on the local stack */
1855 /* and the item is spilt then do nothing */
1856 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1859 aopOp (IC_LEFT (ic), ic, FALSE);
1860 size = AOP_SIZE (IC_LEFT (ic));
1861 /* push it on the stack */
1864 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1870 emitcode ("push", "%s", l);
1875 /* this is a paramter push: in this case we call
1876 the routine to find the call and save those
1877 registers that need to be saved */
1880 /* if use external stack then call the external
1881 stack pushing routine */
1882 if (options.useXstack)
1888 /* then do the push */
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1892 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1893 size = AOP_SIZE (IC_LEFT (ic));
1897 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1898 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1899 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1902 emitcode ("mov", "a,%s", l);
1903 emitcode ("push", "acc");
1906 emitcode ("push", "%s", l);
1909 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* genIpop - recover the registers: can happen only for spilling */
1914 /*-----------------------------------------------------------------*/
1916 genIpop (iCode * ic)
1920 D(emitcode ("; genIpop",""));
1922 /* if the temp was not pushed then */
1923 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1926 aopOp (IC_LEFT (ic), ic, FALSE);
1927 size = AOP_SIZE (IC_LEFT (ic));
1928 offset = (size - 1);
1930 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1933 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1936 /*-----------------------------------------------------------------*/
1937 /* unsaveRBank - restores the resgister bank from stack */
1938 /*-----------------------------------------------------------------*/
1940 unsaveRBank (int bank, iCode * ic, bool popPsw)
1946 if (options.useXstack)
1950 /* Assume r0 is available for use. */
1951 r = mcs51_regWithIdx (R0_IDX);;
1956 r = getFreePtr (ic, &aop, FALSE);
1958 emitcode ("mov", "%s,_spx", r->name);
1963 if (options.useXstack)
1965 emitcode ("movx", "a,@%s", r->name);
1966 emitcode ("mov", "psw,a");
1967 emitcode ("dec", "%s", r->name);
1971 emitcode ("pop", "psw");
1975 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1977 if (options.useXstack)
1979 emitcode ("movx", "a,@%s", r->name);
1980 emitcode ("mov", "(%s+%d),a",
1981 regs8051[i].base, 8 * bank + regs8051[i].offset);
1982 emitcode ("dec", "%s", r->name);
1986 emitcode ("pop", "(%s+%d)",
1987 regs8051[i].base, 8 * bank + regs8051[i].offset);
1990 if (options.useXstack)
1992 emitcode ("mov", "_spx,%s", r->name);
1997 freeAsmop (NULL, aop, ic, TRUE);
2001 /*-----------------------------------------------------------------*/
2002 /* saveRBank - saves an entire register bank on the stack */
2003 /*-----------------------------------------------------------------*/
2005 saveRBank (int bank, iCode * ic, bool pushPsw)
2011 if (options.useXstack)
2015 /* Assume r0 is available for use. */
2016 r = mcs51_regWithIdx (R0_IDX);;
2021 r = getFreePtr (ic, &aop, FALSE);
2023 emitcode ("mov", "%s,_spx", r->name);
2026 for (i = 0; i < mcs51_nRegs; i++)
2028 if (options.useXstack)
2030 emitcode ("inc", "%s", r->name);
2031 emitcode ("mov", "a,(%s+%d)",
2032 regs8051[i].base, 8 * bank + regs8051[i].offset);
2033 emitcode ("movx", "@%s,a", r->name);
2036 emitcode ("push", "(%s+%d)",
2037 regs8051[i].base, 8 * bank + regs8051[i].offset);
2042 if (options.useXstack)
2044 emitcode ("mov", "a,psw");
2045 emitcode ("movx", "@%s,a", r->name);
2046 emitcode ("inc", "%s", r->name);
2047 emitcode ("mov", "_spx,%s", r->name);
2052 emitcode ("push", "psw");
2055 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2060 freeAsmop (NULL, aop, ic, TRUE);
2069 /*-----------------------------------------------------------------*/
2070 /* genSend - gen code for SEND */
2071 /*-----------------------------------------------------------------*/
2072 static void genSend(set *sendSet)
2077 for (sic = setFirstItem (_G.sendSet); sic;
2078 sic = setNextItem (_G.sendSet)) {
2079 int size, offset = 0;
2080 aopOp (IC_LEFT (sic), sic, FALSE);
2081 size = AOP_SIZE (IC_LEFT (sic));
2083 if (sic->argreg == 1) {
2085 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2087 if (strcmp (l, fReturn[offset]))
2088 emitcode ("mov", "%s,%s", fReturn[offset], l);
2094 emitcode ("mov","b1_%d,%s",rb1_count++,
2095 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2098 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2102 /*-----------------------------------------------------------------*/
2103 /* genCall - generates a call statement */
2104 /*-----------------------------------------------------------------*/
2106 genCall (iCode * ic)
2109 // bool restoreBank = FALSE;
2110 bool swapBanks = FALSE;
2112 D(emitcode("; genCall",""));
2114 dtype = operandType (IC_LEFT (ic));
2115 /* if send set is not empty the assign */
2118 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2119 genSend(reverseSet(_G.sendSet));
2121 genSend(_G.sendSet);
2127 /* if we are calling a not _naked function that is not using
2128 the same register bank then we need to save the
2129 destination registers on the stack */
2130 dtype = operandType (IC_LEFT (ic));
2131 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2132 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2133 !IFFUNC_ISISR (dtype))
2138 /* if caller saves & we have not saved then */
2144 emitcode ("mov", "psw,#0x%02x",
2145 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2149 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2150 OP_SYMBOL (IC_LEFT (ic))->rname :
2151 OP_SYMBOL (IC_LEFT (ic))->name));
2155 emitcode ("mov", "psw,#0x%02x",
2156 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2159 /* if we need assign a result value */
2160 if ((IS_ITEMP (IC_RESULT (ic)) &&
2161 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2162 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2163 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2164 IS_TRUE_SYMOP (IC_RESULT (ic)))
2168 aopOp (IC_RESULT (ic), ic, FALSE);
2171 assignResultValue (IC_RESULT (ic));
2173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2176 /* adjust the stack for parameters if
2181 if (ic->parmBytes > 3)
2183 emitcode ("mov", "a,%s", spname);
2184 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2185 emitcode ("mov", "%s,a", spname);
2188 for (i = 0; i < ic->parmBytes; i++)
2189 emitcode ("dec", "%s", spname);
2192 /* if we hade saved some registers then unsave them */
2193 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2194 unsaveRegisters (ic);
2196 // /* if register bank was saved then pop them */
2198 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2201 /*-----------------------------------------------------------------*/
2202 /* -10l - generates a call by pointer statement */
2203 /*-----------------------------------------------------------------*/
2205 genPcall (iCode * ic)
2208 symbol *rlbl = newiTempLabel (NULL);
2209 // bool restoreBank=FALSE;
2210 bool swapBanks = FALSE;
2212 D(emitcode("; genPCall",""));
2214 /* if caller saves & we have not saved then */
2218 /* if we are calling a not _naked function that is not using
2219 the same register bank then we need to save the
2220 destination registers on the stack */
2221 dtype = operandType (IC_LEFT (ic))->next;
2222 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2223 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2224 !IFFUNC_ISISR (dtype))
2226 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2227 // restoreBank=TRUE;
2229 // need caution message to user here
2232 /* push the return address on to the stack */
2233 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2234 emitcode ("push", "acc");
2235 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2236 emitcode ("push", "acc");
2238 /* now push the calling address */
2239 aopOp (IC_LEFT (ic), ic, FALSE);
2241 pushSide (IC_LEFT (ic), FPTRSIZE);
2243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2245 /* if send set is not empty the assign */
2248 genSend(reverseSet(_G.sendSet));
2254 emitcode ("mov", "psw,#0x%02x",
2255 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2259 emitcode ("ret", "");
2260 emitcode ("", "%05d$:", (rlbl->key + 100));
2265 emitcode ("mov", "psw,#0x%02x",
2266 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2269 /* if we need assign a result value */
2270 if ((IS_ITEMP (IC_RESULT (ic)) &&
2271 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2272 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2273 IS_TRUE_SYMOP (IC_RESULT (ic)))
2277 aopOp (IC_RESULT (ic), ic, FALSE);
2280 assignResultValue (IC_RESULT (ic));
2282 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2285 /* adjust the stack for parameters if
2290 if (ic->parmBytes > 3)
2292 emitcode ("mov", "a,%s", spname);
2293 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2294 emitcode ("mov", "%s,a", spname);
2297 for (i = 0; i < ic->parmBytes; i++)
2298 emitcode ("dec", "%s", spname);
2302 // /* if register bank was saved then unsave them */
2304 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2306 /* if we hade saved some registers then
2308 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2309 unsaveRegisters (ic);
2312 /*-----------------------------------------------------------------*/
2313 /* resultRemat - result is rematerializable */
2314 /*-----------------------------------------------------------------*/
2316 resultRemat (iCode * ic)
2318 if (SKIP_IC (ic) || ic->op == IFX)
2321 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2323 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2324 if (sym->remat && !POINTER_SET (ic))
2331 #if defined(__BORLANDC__) || defined(_MSC_VER)
2332 #define STRCASECMP stricmp
2334 #define STRCASECMP strcasecmp
2337 /*-----------------------------------------------------------------*/
2338 /* inExcludeList - return 1 if the string is in exclude Reg list */
2339 /*-----------------------------------------------------------------*/
2341 regsCmp(void *p1, void *p2)
2343 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2347 inExcludeList (char *s)
2349 const char *p = setFirstItem(options.excludeRegsSet);
2351 if (p == NULL || STRCASECMP(p, "none") == 0)
2355 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2358 /*-----------------------------------------------------------------*/
2359 /* genFunction - generated code for function entry */
2360 /*-----------------------------------------------------------------*/
2362 genFunction (iCode * ic)
2366 bool switchedPSW = FALSE;
2367 int calleesaves_saved_register = -1;
2370 /* create the function header */
2371 emitcode (";", "-----------------------------------------");
2372 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2373 emitcode (";", "-----------------------------------------");
2375 emitcode ("", "%s:", sym->rname);
2376 ftype = operandType (IC_LEFT (ic));
2377 _G.currentFunc = sym;
2379 if (IFFUNC_ISNAKED(ftype))
2381 emitcode(";", "naked function: no prologue.");
2385 /* here we need to generate the equates for the
2386 register bank if required */
2387 if (FUNC_REGBANK (ftype) != rbank)
2391 rbank = FUNC_REGBANK (ftype);
2392 for (i = 0; i < mcs51_nRegs; i++)
2394 if (strcmp (regs8051[i].base, "0") == 0)
2395 emitcode ("", "%s = 0x%02x",
2397 8 * rbank + regs8051[i].offset);
2399 emitcode ("", "%s = %s + 0x%02x",
2402 8 * rbank + regs8051[i].offset);
2406 /* if this is an interrupt service routine then
2407 save acc, b, dpl, dph */
2408 if (IFFUNC_ISISR (sym->type))
2411 if (!inExcludeList ("acc"))
2412 emitcode ("push", "acc");
2413 if (!inExcludeList ("b"))
2414 emitcode ("push", "b");
2415 if (!inExcludeList ("dpl"))
2416 emitcode ("push", "dpl");
2417 if (!inExcludeList ("dph"))
2418 emitcode ("push", "dph");
2419 /* if this isr has no bank i.e. is going to
2420 run with bank 0 , then we need to save more
2422 if (!FUNC_REGBANK (sym->type))
2425 /* if this function does not call any other
2426 function then we can be economical and
2427 save only those registers that are used */
2428 if (!IFFUNC_HASFCALL(sym->type))
2432 /* if any registers used */
2435 /* save the registers used */
2436 for (i = 0; i < sym->regsUsed->size; i++)
2438 if (bitVectBitValue (sym->regsUsed, i) ||
2439 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2440 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2443 else if (mcs51_ptrRegReq)
2445 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2446 emitcode ("push", "%s", mcs51_regWithIdx (R1_IDX)->dname);
2453 /* this function has a function call cannot
2454 determines register usage so we will have to push the
2456 saveRBank (0, ic, FALSE);
2457 if (options.parms_in_bank1) {
2459 for (i=0; i < 8 ; i++ ) {
2460 emitcode ("push","%s",rb1regs[i]);
2467 /* This ISR uses a non-zero bank.
2469 * We assume that the bank is available for our
2472 * However, if this ISR calls a function which uses some
2473 * other bank, we must save that bank entirely.
2475 unsigned long banksToSave = 0;
2477 if (IFFUNC_HASFCALL(sym->type))
2480 #define MAX_REGISTER_BANKS 4
2485 for (i = ic; i; i = i->next)
2487 if (i->op == ENDFUNCTION)
2489 /* we got to the end OK. */
2497 dtype = operandType (IC_LEFT(i));
2499 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2501 /* Mark this bank for saving. */
2502 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2504 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2508 banksToSave |= (1 << FUNC_REGBANK(dtype));
2511 /* And note that we don't need to do it in
2519 /* This is a mess; we have no idea what
2520 * register bank the called function might
2523 * The only thing I can think of to do is
2524 * throw a warning and hope.
2526 werror(W_FUNCPTR_IN_USING_ISR);
2530 if (banksToSave && options.useXstack)
2532 /* Since we aren't passing it an ic,
2533 * saveRBank will assume r0 is available to abuse.
2535 * So switch to our (trashable) bank now, so
2536 * the caller's R0 isn't trashed.
2538 emitcode ("push", "psw");
2539 emitcode ("mov", "psw,#0x%02x",
2540 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2544 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2546 if (banksToSave & (1 << ix))
2548 saveRBank(ix, NULL, FALSE);
2552 // TODO: this needs a closer look
2553 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2558 /* if callee-save to be used for this function
2559 then save the registers being used in this function */
2560 if (IFFUNC_CALLEESAVES(sym->type))
2564 /* if any registers used */
2567 /* save the registers used */
2568 for (i = 0; i < sym->regsUsed->size; i++)
2570 if (bitVectBitValue (sym->regsUsed, i) ||
2571 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2573 /* remember one saved register for later usage */
2574 if (calleesaves_saved_register < 0)
2575 calleesaves_saved_register = i;
2576 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2581 else if (mcs51_ptrRegReq)
2583 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2584 emitcode ("push", "%s", mcs51_regWithIdx (R1_IDX)->dname);
2589 /* set the register bank to the desired value */
2590 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2593 emitcode ("push", "psw");
2594 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2597 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2600 if (options.useXstack)
2602 emitcode ("mov", "r0,%s", spname);
2603 emitcode ("mov", "a,_bp");
2604 emitcode ("movx", "@r0,a");
2605 emitcode ("inc", "%s", spname);
2609 /* set up the stack */
2610 emitcode ("push", "_bp"); /* save the callers stack */
2612 emitcode ("mov", "_bp,%s", spname);
2615 /* adjust the stack for the function */
2621 werror (W_STACK_OVERFLOW, sym->name);
2623 if (i > 3 && sym->recvSize < 4)
2626 emitcode ("mov", "a,sp");
2627 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2628 emitcode ("mov", "sp,a");
2633 if (IFFUNC_CALLEESAVES(sym->type))
2635 /* if it's a callee-saves function we need a saved register */
2636 if (calleesaves_saved_register >= 0)
2638 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2639 emitcode ("mov", "a,sp");
2640 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2641 emitcode ("mov", "sp,a");
2642 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2645 /* do it the hard way */
2647 emitcode ("inc", "sp");
2651 /* not callee-saves, we can clobber r0 */
2652 emitcode ("mov", "r0,a");
2653 emitcode ("mov", "a,sp");
2654 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2655 emitcode ("mov", "sp,a");
2656 emitcode ("mov", "a,r0");
2661 emitcode ("inc", "sp");
2667 emitcode ("mov", "a,_spx");
2668 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2669 emitcode ("mov", "_spx,a");
2672 /* if critical function then turn interrupts off */
2673 if (IFFUNC_ISCRITICAL (ftype))
2675 symbol *tlbl = newiTempLabel (NULL);
2676 emitcode ("setb", "c");
2677 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2678 emitcode ("clr", "c");
2679 emitcode ("", "%05d$:", (tlbl->key + 100));
2680 emitcode ("push", "psw"); /* save old ea via c in psw */
2684 /*-----------------------------------------------------------------*/
2685 /* genEndFunction - generates epilogue for functions */
2686 /*-----------------------------------------------------------------*/
2688 genEndFunction (iCode * ic)
2690 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2691 lineNode *lnp = lineCurr;
2693 bitVect *regsUsedPrologue;
2694 bitVect *regsUnneeded;
2697 _G.currentFunc = NULL;
2698 if (IFFUNC_ISNAKED(sym->type))
2700 emitcode(";", "naked function: no epilogue.");
2704 if (IFFUNC_ISCRITICAL (sym->type))
2706 emitcode ("pop", "psw"); /* restore ea via c in psw */
2707 emitcode ("mov", "ea,c");
2710 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2712 emitcode ("mov", "%s,_bp", spname);
2715 /* if use external stack but some variables were
2716 added to the local stack then decrement the
2718 if (options.useXstack && sym->stack)
2720 emitcode ("mov", "a,sp");
2721 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2722 emitcode ("mov", "sp,a");
2726 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2728 if (options.useXstack)
2730 emitcode ("mov", "r0,%s", spname);
2731 emitcode ("movx", "a,@r0");
2732 emitcode ("mov", "_bp,a");
2733 emitcode ("dec", "%s", spname);
2737 emitcode ("pop", "_bp");
2741 /* restore the register bank */
2742 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2744 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2745 || !options.useXstack)
2747 /* Special case of ISR using non-zero bank with useXstack
2750 emitcode ("pop", "psw");
2754 if (IFFUNC_ISISR (sym->type))
2757 /* now we need to restore the registers */
2758 /* if this isr has no bank i.e. is going to
2759 run with bank 0 , then we need to save more
2761 if (!FUNC_REGBANK (sym->type))
2763 /* if this function does not call any other
2764 function then we can be economical and
2765 save only those registers that are used */
2766 if (!IFFUNC_HASFCALL(sym->type))
2770 /* if any registers used */
2773 /* save the registers used */
2774 for (i = sym->regsUsed->size; i >= 0; i--)
2776 if (bitVectBitValue (sym->regsUsed, i) ||
2777 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2778 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2781 else if (mcs51_ptrRegReq)
2783 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
2784 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2790 if (options.parms_in_bank1) {
2792 for (i = 7 ; i >= 0 ; i-- ) {
2793 emitcode ("pop","%s",rb1regs[i]);
2796 /* this function has a function call cannot
2797 determines register usage so we will have to pop the
2799 unsaveRBank (0, ic, FALSE);
2804 /* This ISR uses a non-zero bank.
2806 * Restore any register banks saved by genFunction
2809 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2812 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2814 if (savedBanks & (1 << ix))
2816 unsaveRBank(ix, NULL, FALSE);
2820 if (options.useXstack)
2822 /* Restore bank AFTER calling unsaveRBank,
2823 * since it can trash r0.
2825 emitcode ("pop", "psw");
2829 if (!inExcludeList ("dph"))
2830 emitcode ("pop", "dph");
2831 if (!inExcludeList ("dpl"))
2832 emitcode ("pop", "dpl");
2833 if (!inExcludeList ("b"))
2834 emitcode ("pop", "b");
2835 if (!inExcludeList ("acc"))
2836 emitcode ("pop", "acc");
2838 /* if debug then send end of function */
2839 if (options.debug && currFunc)
2842 emitcode ("", "C$%s$%d$%d$%d ==.",
2843 FileBaseName (ic->filename), currFunc->lastLine,
2844 ic->level, ic->block);
2845 if (IS_STATIC (currFunc->etype))
2846 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2848 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2852 emitcode ("reti", "");
2856 if (IFFUNC_CALLEESAVES(sym->type))
2860 /* if any registers used */
2863 /* save the registers used */
2864 for (i = sym->regsUsed->size; i >= 0; i--)
2866 if (bitVectBitValue (sym->regsUsed, i) ||
2867 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2868 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2871 else if (mcs51_ptrRegReq)
2873 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
2874 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2879 /* if debug then send end of function */
2880 if (options.debug && currFunc)
2883 emitcode ("", "C$%s$%d$%d$%d ==.",
2884 FileBaseName (ic->filename), currFunc->lastLine,
2885 ic->level, ic->block);
2886 if (IS_STATIC (currFunc->etype))
2887 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2889 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2893 emitcode ("ret", "");
2896 if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
2899 /* If this was an interrupt handler using bank 0 that called another */
2900 /* function, then all registers must be saved; nothing to optimized. */
2901 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
2902 && !FUNC_REGBANK(sym->type))
2905 /* Compute the registers actually used */
2906 regsUsed = newBitVect (mcs51_nRegs);
2907 regsUsedPrologue = newBitVect (mcs51_nRegs);
2910 if (lnp->ic && lnp->ic->op == FUNCTION)
2911 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
2913 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
2915 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
2916 && lnp->prev->ic && lnp->prev->ic->op != FUNCTION)
2923 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
2924 && !bitVectBitValue (regsUsed, CND_IDX))
2926 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
2927 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
2929 bitVectUnSetBit (regsUsed, CND_IDX);
2932 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
2934 /* If this was an interrupt handler that called another function */
2935 /* function, then assume A, B, DPH, & DPL may be modified by it. */
2936 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
2938 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
2939 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
2940 regsUsed = bitVectSetBit (regsUsed, B_IDX);
2941 regsUsed = bitVectSetBit (regsUsed, A_IDX);
2942 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
2945 /* Remove the unneeded push/pops */
2946 regsUnneeded = newBitVect (mcs51_nRegs);
2949 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
2951 if (!strncmp(lnp->line, "push", 4))
2953 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
2954 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
2956 connectLine (lnp->prev, lnp->next);
2957 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
2960 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
2962 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
2963 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
2965 connectLine (lnp->prev, lnp->next);
2966 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
2973 for (idx = 0; idx < regsUnneeded->size; idx++)
2974 if (bitVectBitValue (regsUnneeded, idx))
2975 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
2977 freeBitVect (regsUnneeded);
2978 freeBitVect (regsUsed);
2979 freeBitVect (regsUsedPrologue);
2982 /*-----------------------------------------------------------------*/
2983 /* genRet - generate code for return statement */
2984 /*-----------------------------------------------------------------*/
2988 int size, offset = 0, pushed = 0;
2990 D(emitcode ("; genRet",""));
2992 /* if we have no return value then
2993 just generate the "ret" */
2997 /* we have something to return then
2998 move the return value into place */
2999 aopOp (IC_LEFT (ic), ic, FALSE);
3000 size = AOP_SIZE (IC_LEFT (ic));
3005 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3008 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3010 emitcode ("push", "%s", l);
3015 l = aopGet (AOP (IC_LEFT (ic)), offset,
3017 if (strcmp (fReturn[offset], l))
3018 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3027 if (strcmp (fReturn[pushed], "a"))
3028 emitcode ("pop", fReturn[pushed]);
3030 emitcode ("pop", "acc");
3033 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3036 /* generate a jump to the return label
3037 if the next is not the return statement */
3038 if (!(ic->next && ic->next->op == LABEL &&
3039 IC_LABEL (ic->next) == returnLabel))
3041 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3045 /*-----------------------------------------------------------------*/
3046 /* genLabel - generates a label */
3047 /*-----------------------------------------------------------------*/
3049 genLabel (iCode * ic)
3051 /* special case never generate */
3052 if (IC_LABEL (ic) == entryLabel)
3055 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3058 /*-----------------------------------------------------------------*/
3059 /* genGoto - generates a ljmp */
3060 /*-----------------------------------------------------------------*/
3062 genGoto (iCode * ic)
3064 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3067 /*-----------------------------------------------------------------*/
3068 /* findLabelBackwards: walks back through the iCode chain looking */
3069 /* for the given label. Returns number of iCode instructions */
3070 /* between that label and given ic. */
3071 /* Returns zero if label not found. */
3072 /*-----------------------------------------------------------------*/
3074 findLabelBackwards (iCode * ic, int key)
3083 /* If we have any pushes or pops, we cannot predict the distance.
3084 I don't like this at all, this should be dealt with in the
3086 if (ic->op == IPUSH || ic->op == IPOP) {
3090 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3099 /*-----------------------------------------------------------------*/
3100 /* genPlusIncr :- does addition with increment if possible */
3101 /*-----------------------------------------------------------------*/
3103 genPlusIncr (iCode * ic)
3105 unsigned int icount;
3106 unsigned int size = getDataSize (IC_RESULT (ic));
3108 /* will try to generate an increment */
3109 /* if the right side is not a literal
3111 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3114 /* if the literal value of the right hand side
3115 is greater than 4 then it is not worth it */
3116 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3119 D(emitcode ("; genPlusIncr",""));
3121 /* if increment >=16 bits in register or direct space */
3122 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3123 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3131 /* If the next instruction is a goto and the goto target
3132 * is < 10 instructions previous to this, we can generate
3133 * jumps straight to that target.
3135 if (ic->next && ic->next->op == GOTO
3136 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3137 && labelRange <= 10)
3139 emitcode (";", "tail increment optimized");
3140 tlbl = IC_LABEL (ic->next);
3145 tlbl = newiTempLabel (NULL);
3148 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3149 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3150 IS_AOP_PREG (IC_RESULT (ic)))
3151 emitcode ("cjne", "%s,#0x00,%05d$",
3152 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3156 emitcode ("clr", "a");
3157 emitcode ("cjne", "a,%s,%05d$",
3158 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3162 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3165 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3166 IS_AOP_PREG (IC_RESULT (ic)))
3167 emitcode ("cjne", "%s,#0x00,%05d$",
3168 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3171 emitcode ("cjne", "a,%s,%05d$",
3172 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3175 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3179 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3180 IS_AOP_PREG (IC_RESULT (ic)))
3181 emitcode ("cjne", "%s,#0x00,%05d$",
3182 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3186 emitcode ("cjne", "a,%s,%05d$",
3187 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3190 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3195 emitcode ("", "%05d$:", tlbl->key + 100);
3200 /* if the sizes are greater than 1 then we cannot */
3201 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3202 AOP_SIZE (IC_LEFT (ic)) > 1)
3205 /* we can if the aops of the left & result match or
3206 if they are in registers and the registers are the
3208 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3213 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3214 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3215 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3221 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3230 /*-----------------------------------------------------------------*/
3231 /* outBitAcc - output a bit in acc */
3232 /*-----------------------------------------------------------------*/
3234 outBitAcc (operand * result)
3236 symbol *tlbl = newiTempLabel (NULL);
3237 /* if the result is a bit */
3238 if (AOP_TYPE (result) == AOP_CRY)
3240 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3244 emitcode ("jz", "%05d$", tlbl->key + 100);
3245 emitcode ("mov", "a,%s", one);
3246 emitcode ("", "%05d$:", tlbl->key + 100);
3251 /*-----------------------------------------------------------------*/
3252 /* genPlusBits - generates code for addition of two bits */
3253 /*-----------------------------------------------------------------*/
3255 genPlusBits (iCode * ic)
3257 D(emitcode ("; genPlusBits",""));
3259 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3261 symbol *lbl = newiTempLabel (NULL);
3262 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3263 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3264 emitcode ("cpl", "c");
3265 emitcode ("", "%05d$:", (lbl->key + 100));
3266 outBitC (IC_RESULT (ic));
3270 emitcode ("clr", "a");
3271 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3272 emitcode ("rlc", "a");
3273 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3274 emitcode ("addc", "a,#0x00");
3275 outAcc (IC_RESULT (ic));
3280 /* This is the original version of this code.
3282 * This is being kept around for reference,
3283 * because I am not entirely sure I got it right...
3286 adjustArithmeticResult (iCode * ic)
3288 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3289 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3290 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3291 aopPut (AOP (IC_RESULT (ic)),
3292 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3294 isOperandVolatile (IC_RESULT (ic), FALSE));
3296 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3297 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3298 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3299 aopPut (AOP (IC_RESULT (ic)),
3300 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3302 isOperandVolatile (IC_RESULT (ic), FALSE));
3304 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3305 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3306 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3307 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3308 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3311 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3312 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3316 /* This is the pure and virtuous version of this code.
3317 * I'm pretty certain it's right, but not enough to toss the old
3321 adjustArithmeticResult (iCode * ic)
3323 if (opIsGptr (IC_RESULT (ic)) &&
3324 opIsGptr (IC_LEFT (ic)) &&
3325 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3327 aopPut (AOP (IC_RESULT (ic)),
3328 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3330 isOperandVolatile (IC_RESULT (ic), FALSE));
3333 if (opIsGptr (IC_RESULT (ic)) &&
3334 opIsGptr (IC_RIGHT (ic)) &&
3335 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3337 aopPut (AOP (IC_RESULT (ic)),
3338 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3340 isOperandVolatile (IC_RESULT (ic), FALSE));
3343 if (opIsGptr (IC_RESULT (ic)) &&
3344 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3345 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3346 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3347 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3350 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3351 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3356 /*-----------------------------------------------------------------*/
3357 /* genPlus - generates code for addition */
3358 /*-----------------------------------------------------------------*/
3360 genPlus (iCode * ic)
3362 int size, offset = 0;
3365 asmop *leftOp, *rightOp;
3368 /* special cases :- */
3370 D(emitcode ("; genPlus",""));
3372 aopOp (IC_LEFT (ic), ic, FALSE);
3373 aopOp (IC_RIGHT (ic), ic, FALSE);
3374 aopOp (IC_RESULT (ic), ic, TRUE);
3376 /* if literal, literal on the right or
3377 if left requires ACC or right is already
3379 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3380 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3381 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3383 operand *t = IC_RIGHT (ic);
3384 IC_RIGHT (ic) = IC_LEFT (ic);
3388 /* if both left & right are in bit
3390 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3391 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3397 /* if left in bit space & right literal */
3398 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3399 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3401 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3402 /* if result in bit space */
3403 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3405 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3406 emitcode ("cpl", "c");
3407 outBitC (IC_RESULT (ic));
3411 size = getDataSize (IC_RESULT (ic));
3414 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3415 emitcode ("addc", "a,#00");
3416 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3422 /* if I can do an increment instead
3423 of add then GOOD for ME */
3424 if (genPlusIncr (ic) == TRUE)
3427 size = getDataSize (IC_RESULT (ic));
3428 leftOp = AOP(IC_LEFT(ic));
3429 rightOp = AOP(IC_RIGHT(ic));
3432 /* if this is an add for an array access
3433 at a 256 byte boundary */
3435 && AOP_TYPE (op) == AOP_IMMD
3437 && IS_SPEC (OP_SYM_ETYPE (op))
3438 && SPEC_ABSA (OP_SYM_ETYPE (op))
3439 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3442 D(emitcode ("; genPlus aligned array",""));
3443 aopPut (AOP (IC_RESULT (ic)),
3444 aopGet (rightOp, 0, FALSE, FALSE),
3446 isOperandVolatile (IC_RESULT (ic), FALSE));
3448 if( 1 == getDataSize (IC_RIGHT (ic)) )
3450 aopPut (AOP (IC_RESULT (ic)),
3451 aopGet (leftOp, 1, FALSE, FALSE),
3453 isOperandVolatile (IC_RESULT (ic), FALSE));
3457 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3458 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3459 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3464 /* if the lower bytes of a literal are zero skip the addition */
3465 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3467 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3468 (skip_bytes+1 < size))
3473 D(emitcode ("; genPlus shortcut",""));
3478 if( offset >= skip_bytes )
3480 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3482 emitcode("mov", "b,a");
3483 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3484 emitcode("xch", "a,b");
3485 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3486 emitcode (add, "a,b");
3488 else if (aopGetUsesAcc (leftOp, offset))
3490 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3491 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3495 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3496 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3498 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3499 add = "addc"; /* further adds must propagate carry */
3503 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3504 isOperandVolatile (IC_RESULT (ic), FALSE))
3507 aopPut (AOP (IC_RESULT (ic)),
3508 aopGet (leftOp, offset, FALSE, FALSE),
3510 isOperandVolatile (IC_RESULT (ic), FALSE));
3516 adjustArithmeticResult (ic);
3519 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3521 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3524 /*-----------------------------------------------------------------*/
3525 /* genMinusDec :- does subtraction with deccrement if possible */
3526 /*-----------------------------------------------------------------*/
3528 genMinusDec (iCode * ic)
3530 unsigned int icount;
3531 unsigned int size = getDataSize (IC_RESULT (ic));
3533 /* will try to generate an increment */
3534 /* if the right side is not a literal
3536 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3539 /* if the literal value of the right hand side
3540 is greater than 4 then it is not worth it */
3541 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3544 D(emitcode ("; genMinusDec",""));
3546 /* if decrement >=16 bits in register or direct space */
3547 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3548 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3556 /* If the next instruction is a goto and the goto target
3557 * is <= 10 instructions previous to this, we can generate
3558 * jumps straight to that target.
3560 if (ic->next && ic->next->op == GOTO
3561 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3562 && labelRange <= 10)
3564 emitcode (";", "tail decrement optimized");
3565 tlbl = IC_LABEL (ic->next);
3570 tlbl = newiTempLabel (NULL);
3574 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3575 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3576 IS_AOP_PREG (IC_RESULT (ic)))
3577 emitcode ("cjne", "%s,#0xff,%05d$"
3578 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3582 emitcode ("mov", "a,#0xff");
3583 emitcode ("cjne", "a,%s,%05d$"
3584 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3587 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3590 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3591 IS_AOP_PREG (IC_RESULT (ic)))
3592 emitcode ("cjne", "%s,#0xff,%05d$"
3593 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3597 emitcode ("cjne", "a,%s,%05d$"
3598 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3601 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3605 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3606 IS_AOP_PREG (IC_RESULT (ic)))
3607 emitcode ("cjne", "%s,#0xff,%05d$"
3608 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3612 emitcode ("cjne", "a,%s,%05d$"
3613 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3616 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3620 emitcode ("", "%05d$:", tlbl->key + 100);
3625 /* if the sizes are greater than 1 then we cannot */
3626 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3627 AOP_SIZE (IC_LEFT (ic)) > 1)
3630 /* we can if the aops of the left & result match or
3631 if they are in registers and the registers are the
3633 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3637 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3645 /*-----------------------------------------------------------------*/
3646 /* addSign - complete with sign */
3647 /*-----------------------------------------------------------------*/
3649 addSign (operand * result, int offset, int sign)
3651 int size = (getDataSize (result) - offset);
3656 emitcode ("rlc", "a");
3657 emitcode ("subb", "a,acc");
3659 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3663 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3667 /*-----------------------------------------------------------------*/
3668 /* genMinusBits - generates code for subtraction of two bits */
3669 /*-----------------------------------------------------------------*/
3671 genMinusBits (iCode * ic)
3673 symbol *lbl = newiTempLabel (NULL);
3675 D(emitcode ("; genMinusBits",""));
3677 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3679 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3680 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3681 emitcode ("cpl", "c");
3682 emitcode ("", "%05d$:", (lbl->key + 100));
3683 outBitC (IC_RESULT (ic));
3687 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3688 emitcode ("subb", "a,acc");
3689 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3690 emitcode ("inc", "a");
3691 emitcode ("", "%05d$:", (lbl->key + 100));
3692 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3693 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3697 /*-----------------------------------------------------------------*/
3698 /* genMinus - generates code for subtraction */
3699 /*-----------------------------------------------------------------*/
3701 genMinus (iCode * ic)
3703 int size, offset = 0;
3705 D(emitcode ("; genMinus",""));
3707 aopOp (IC_LEFT (ic), ic, FALSE);
3708 aopOp (IC_RIGHT (ic), ic, FALSE);
3709 aopOp (IC_RESULT (ic), ic, TRUE);
3711 /* special cases :- */
3712 /* if both left & right are in bit space */
3713 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3714 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3720 /* if I can do an decrement instead
3721 of subtract then GOOD for ME */
3722 if (genMinusDec (ic) == TRUE)
3725 size = getDataSize (IC_RESULT (ic));
3727 /* if literal, add a,#-lit, else normal subb */
3728 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3730 unsigned long lit = 0L;
3732 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3737 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3738 /* first add without previous c */
3740 if (!size && lit== (unsigned long) -1) {
3741 emitcode ("dec", "a");
3743 emitcode ("add", "a,#0x%02x",
3744 (unsigned int) (lit & 0x0FFL));
3747 emitcode ("addc", "a,#0x%02x",
3748 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3750 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3755 asmop *leftOp, *rightOp;
3757 leftOp = AOP(IC_LEFT(ic));
3758 rightOp = AOP(IC_RIGHT(ic));
3762 if (aopGetUsesAcc(rightOp, offset)) {
3763 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3764 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3766 emitcode( "setb", "c");
3768 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3769 emitcode("cpl", "a");
3771 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3774 emitcode ("subb", "a,%s",
3775 aopGet(rightOp, offset, FALSE, TRUE));
3778 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3783 adjustArithmeticResult (ic);
3786 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3787 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3788 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3792 /*-----------------------------------------------------------------*/
3793 /* genMultbits :- multiplication of bits */
3794 /*-----------------------------------------------------------------*/
3796 genMultbits (operand * left,
3800 D(emitcode ("; genMultbits",""));
3802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3803 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3807 /*-----------------------------------------------------------------*/
3808 /* genMultOneByte : 8*8=8/16 bit multiplication */
3809 /*-----------------------------------------------------------------*/
3811 genMultOneByte (operand * left,
3816 int size = AOP_SIZE (result);
3817 bool runtimeSign, compiletimeSign;
3818 bool lUnsigned, rUnsigned;
3820 D(emitcode ("; genMultOneByte",""));
3822 if (size < 1 || size > 2)
3824 /* this should never happen */
3825 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3826 AOP_SIZE(result), __FILE__, lineno);
3830 /* (if two literals: the value is computed before) */
3831 /* if one literal, literal on the right */
3832 if (AOP_TYPE (left) == AOP_LIT)
3837 /* emitcode (";", "swapped left and right"); */
3839 /* if no literal, unsigned on the right: shorter code */
3840 if ( AOP_TYPE (right) != AOP_LIT
3841 && SPEC_USIGN (getSpec (operandType (left))))
3848 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3849 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3851 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
3852 no need to take care about the signedness! */
3853 || (lUnsigned && rUnsigned))
3855 /* just an unsigned 8 * 8 = 8 multiply
3857 /* emitcode (";","unsigned"); */
3858 /* TODO: check for accumulator clash between left & right aops? */
3860 if (AOP_TYPE (right) == AOP_LIT)
3862 /* moving to accumulator first helps peepholes */
3863 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3864 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3868 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3869 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3872 emitcode ("mul", "ab");
3873 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3875 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3879 /* we have to do a signed multiply */
3880 /* emitcode (";", "signed"); */
3882 /* now sign adjust for both left & right */
3884 /* let's see what's needed: */
3885 /* apply negative sign during runtime */
3886 runtimeSign = FALSE;
3887 /* negative sign from literals */
3888 compiletimeSign = FALSE;
3892 if (AOP_TYPE(left) == AOP_LIT)
3894 /* signed literal */
3895 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3897 compiletimeSign = TRUE;
3900 /* signed but not literal */
3906 if (AOP_TYPE(right) == AOP_LIT)
3908 /* signed literal */
3909 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3911 compiletimeSign ^= TRUE;
3914 /* signed but not literal */
3918 /* initialize F0, which stores the runtime sign */
3921 if (compiletimeSign)
3922 emitcode ("setb", "F0"); /* set sign flag */
3924 emitcode ("clr", "F0"); /* reset sign flag */
3927 /* save the signs of the operands */
3928 if (AOP_TYPE(right) == AOP_LIT)
3930 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3932 if (!rUnsigned && val < 0)
3933 emitcode ("mov", "b,#0x%02x", -val);
3935 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
3937 else /* ! literal */
3939 if (rUnsigned) /* emitcode (";", "signed"); */
3941 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3944 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
3945 lbl = newiTempLabel (NULL);
3946 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3947 emitcode ("cpl", "F0"); /* complement sign flag */
3948 emitcode ("cpl", "a"); /* 2's complement */
3949 emitcode ("inc", "a");
3950 emitcode ("", "%05d$:", (lbl->key + 100));
3951 emitcode ("mov", "b,a");
3955 if (AOP_TYPE(left) == AOP_LIT)
3957 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3959 if (!lUnsigned && val < 0)
3960 emitcode ("mov", "a,#0x%02x", -val);
3962 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
3964 else /* ! literal */
3966 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3970 lbl = newiTempLabel (NULL);
3971 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3972 emitcode ("cpl", "F0"); /* complement sign flag */
3973 emitcode ("cpl", "a"); /* 2's complement */
3974 emitcode ("inc", "a");
3975 emitcode ("", "%05d$:", (lbl->key + 100));
3979 /* now the multiplication */
3980 emitcode ("mul", "ab");
3981 if (runtimeSign || compiletimeSign)
3983 lbl = newiTempLabel (NULL);
3985 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
3986 emitcode ("cpl", "a"); /* lsb 2's complement */
3988 emitcode ("inc", "a"); /* inc doesn't set carry flag */
3991 emitcode ("add", "a,#1"); /* this sets carry flag */
3992 emitcode ("xch", "a,b");
3993 emitcode ("cpl", "a"); /* msb 2's complement */
3994 emitcode ("addc", "a,#0");
3995 emitcode ("xch", "a,b");
3997 emitcode ("", "%05d$:", (lbl->key + 100));
3999 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4001 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4004 /*-----------------------------------------------------------------*/
4005 /* genMult - generates code for multiplication */
4006 /*-----------------------------------------------------------------*/
4008 genMult (iCode * ic)
4010 operand *left = IC_LEFT (ic);
4011 operand *right = IC_RIGHT (ic);
4012 operand *result = IC_RESULT (ic);
4014 D(emitcode ("; genMult",""));
4016 /* assign the amsops */
4017 aopOp (left, ic, FALSE);
4018 aopOp (right, ic, FALSE);
4019 aopOp (result, ic, TRUE);
4021 /* special cases first */
4023 if (AOP_TYPE (left) == AOP_CRY &&
4024 AOP_TYPE (right) == AOP_CRY)
4026 genMultbits (left, right, result);
4030 /* if both are of size == 1 */
4031 #if 0 // one of them can be a sloc shared with the result
4032 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4034 if (getSize(operandType(left)) == 1 &&
4035 getSize(operandType(right)) == 1)
4038 genMultOneByte (left, right, result);
4042 /* should have been converted to function call */
4043 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4044 getSize(OP_SYMBOL(right)->type));
4048 freeAsmop (result, NULL, ic, TRUE);
4049 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4050 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4053 /*-----------------------------------------------------------------*/
4054 /* genDivbits :- division of bits */
4055 /*-----------------------------------------------------------------*/
4057 genDivbits (operand * left,
4064 D(emitcode ("; genDivbits",""));
4066 /* the result must be bit */
4067 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4068 l = aopGet (AOP (left), 0, FALSE, FALSE);
4072 emitcode ("div", "ab");
4073 emitcode ("rrc", "a");
4074 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4077 /*-----------------------------------------------------------------*/
4078 /* genDivOneByte : 8 bit division */
4079 /*-----------------------------------------------------------------*/
4081 genDivOneByte (operand * left,
4085 bool lUnsigned, rUnsigned;
4086 bool runtimeSign, compiletimeSign;
4090 D(emitcode ("; genDivOneByte",""));
4092 /* Why is it necessary that genDivOneByte() can return an int result?
4095 volatile unsigned char uc;
4096 volatile signed char sc1, sc2;
4109 In all cases a one byte result would overflow, the following cast to int
4110 would return the wrong result.
4112 Two possible solution:
4113 a) cast operands to int, if ((unsigned) / (signed)) or
4114 ((signed) / (signed))
4115 b) return an 16 bit signed int; this is what we're doing here!
4118 size = AOP_SIZE (result) - 1;
4120 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4121 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4123 /* signed or unsigned */
4124 if (lUnsigned && rUnsigned)
4126 /* unsigned is easy */
4127 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4128 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4129 emitcode ("div", "ab");
4130 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4132 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4136 /* signed is a little bit more difficult */
4138 /* now sign adjust for both left & right */
4140 /* let's see what's needed: */
4141 /* apply negative sign during runtime */
4142 runtimeSign = FALSE;
4143 /* negative sign from literals */
4144 compiletimeSign = FALSE;
4148 if (AOP_TYPE(left) == AOP_LIT)
4150 /* signed literal */
4151 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4153 compiletimeSign = TRUE;
4156 /* signed but not literal */
4162 if (AOP_TYPE(right) == AOP_LIT)
4164 /* signed literal */
4165 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4167 compiletimeSign ^= TRUE;
4170 /* signed but not literal */
4174 /* initialize F0, which stores the runtime sign */
4177 if (compiletimeSign)
4178 emitcode ("setb", "F0"); /* set sign flag */
4180 emitcode ("clr", "F0"); /* reset sign flag */
4183 /* save the signs of the operands */
4184 if (AOP_TYPE(right) == AOP_LIT)
4186 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4188 if (!rUnsigned && val < 0)
4189 emitcode ("mov", "b,#0x%02x", -val);
4191 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4193 else /* ! literal */
4196 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4199 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4200 lbl = newiTempLabel (NULL);
4201 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4202 emitcode ("cpl", "F0"); /* complement sign flag */
4203 emitcode ("cpl", "a"); /* 2's complement */
4204 emitcode ("inc", "a");
4205 emitcode ("", "%05d$:", (lbl->key + 100));
4206 emitcode ("mov", "b,a");
4210 if (AOP_TYPE(left) == AOP_LIT)
4212 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4214 if (!lUnsigned && val < 0)
4215 emitcode ("mov", "a,#0x%02x", -val);
4217 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4219 else /* ! literal */
4221 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4225 lbl = newiTempLabel (NULL);
4226 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4227 emitcode ("cpl", "F0"); /* complement sign flag */
4228 emitcode ("cpl", "a"); /* 2's complement */
4229 emitcode ("inc", "a");
4230 emitcode ("", "%05d$:", (lbl->key + 100));
4234 /* now the division */
4235 emitcode ("div", "ab");
4237 if (runtimeSign || compiletimeSign)
4239 lbl = newiTempLabel (NULL);
4241 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4242 emitcode ("cpl", "a"); /* lsb 2's complement */
4243 emitcode ("inc", "a");
4244 emitcode ("", "%05d$:", (lbl->key + 100));
4246 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4249 /* msb is 0x00 or 0xff depending on the sign */
4252 emitcode ("mov", "c,F0");
4253 emitcode ("subb", "a,acc");
4255 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4257 else /* compiletimeSign */
4259 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4264 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4266 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4270 /*-----------------------------------------------------------------*/
4271 /* genDiv - generates code for division */
4272 /*-----------------------------------------------------------------*/
4276 operand *left = IC_LEFT (ic);
4277 operand *right = IC_RIGHT (ic);
4278 operand *result = IC_RESULT (ic);
4280 D(emitcode ("; genDiv",""));
4282 /* assign the amsops */
4283 aopOp (left, ic, FALSE);
4284 aopOp (right, ic, FALSE);
4285 aopOp (result, ic, TRUE);
4287 /* special cases first */
4289 if (AOP_TYPE (left) == AOP_CRY &&
4290 AOP_TYPE (right) == AOP_CRY)
4292 genDivbits (left, right, result);
4296 /* if both are of size == 1 */
4297 if (AOP_SIZE (left) == 1 &&
4298 AOP_SIZE (right) == 1)
4300 genDivOneByte (left, right, result);
4304 /* should have been converted to function call */
4307 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4308 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309 freeAsmop (result, NULL, ic, TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* genModbits :- modulus of bits */
4314 /*-----------------------------------------------------------------*/
4316 genModbits (operand * left,
4323 D(emitcode ("; genModbits",""));
4325 /* the result must be bit */
4326 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4327 l = aopGet (AOP (left), 0, FALSE, FALSE);
4331 emitcode ("div", "ab");
4332 emitcode ("mov", "a,b");
4333 emitcode ("rrc", "a");
4334 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4337 /*-----------------------------------------------------------------*/
4338 /* genModOneByte : 8 bit modulus */
4339 /*-----------------------------------------------------------------*/
4341 genModOneByte (operand * left,
4345 bool lUnsigned, rUnsigned;
4346 bool runtimeSign, compiletimeSign;
4350 D(emitcode ("; genModOneByte",""));
4352 size = AOP_SIZE (result) - 1;
4354 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4355 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4357 /* signed or unsigned */
4358 if (lUnsigned && rUnsigned)
4360 /* unsigned is easy */
4361 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4362 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4363 emitcode ("div", "ab");
4364 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4366 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4370 /* signed is a little bit more difficult */
4372 /* now sign adjust for both left & right */
4374 /* modulus: sign of the right operand has no influence on the result! */
4375 if (AOP_TYPE(right) == AOP_LIT)
4377 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4379 if (!rUnsigned && val < 0)
4380 emitcode ("mov", "b,#0x%02x", -val);
4382 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4384 else /* not literal */
4387 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4390 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4391 lbl = newiTempLabel (NULL);
4392 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4393 emitcode ("cpl", "a"); /* 2's complement */
4394 emitcode ("inc", "a");
4395 emitcode ("", "%05d$:", (lbl->key + 100));
4396 emitcode ("mov", "b,a");
4400 /* let's see what's needed: */
4401 /* apply negative sign during runtime */
4402 runtimeSign = FALSE;
4403 /* negative sign from literals */
4404 compiletimeSign = FALSE;
4406 /* sign adjust left side */
4407 if (AOP_TYPE(left) == AOP_LIT)
4409 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4411 if (!lUnsigned && val < 0)
4413 compiletimeSign = TRUE; /* set sign flag */
4414 emitcode ("mov", "a,#0x%02x", -val);
4417 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4419 else /* ! literal */
4421 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4426 emitcode ("clr", "F0"); /* clear sign flag */
4428 lbl = newiTempLabel (NULL);
4429 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4430 emitcode ("setb", "F0"); /* set sign flag */
4431 emitcode ("cpl", "a"); /* 2's complement */
4432 emitcode ("inc", "a");
4433 emitcode ("", "%05d$:", (lbl->key + 100));
4437 /* now the modulus */
4438 emitcode ("div", "ab");
4440 if (runtimeSign || compiletimeSign)
4442 emitcode ("mov", "a,b");
4443 lbl = newiTempLabel (NULL);
4445 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4446 emitcode ("cpl", "a"); /* 2's complement */
4447 emitcode ("inc", "a");
4448 emitcode ("", "%05d$:", (lbl->key + 100));
4450 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4453 /* msb is 0x00 or 0xff depending on the sign */
4456 emitcode ("mov", "c,F0");
4457 emitcode ("subb", "a,acc");
4459 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4461 else /* compiletimeSign */
4463 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4468 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4470 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4474 /*-----------------------------------------------------------------*/
4475 /* genMod - generates code for division */
4476 /*-----------------------------------------------------------------*/
4480 operand *left = IC_LEFT (ic);
4481 operand *right = IC_RIGHT (ic);
4482 operand *result = IC_RESULT (ic);
4484 D(emitcode ("; genMod",""));
4486 /* assign the amsops */
4487 aopOp (left, ic, FALSE);
4488 aopOp (right, ic, FALSE);
4489 aopOp (result, ic, TRUE);
4491 /* special cases first */
4493 if (AOP_TYPE (left) == AOP_CRY &&
4494 AOP_TYPE (right) == AOP_CRY)
4496 genModbits (left, right, result);
4500 /* if both are of size == 1 */
4501 if (AOP_SIZE (left) == 1 &&
4502 AOP_SIZE (right) == 1)
4504 genModOneByte (left, right, result);
4508 /* should have been converted to function call */
4512 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4513 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4514 freeAsmop (result, NULL, ic, TRUE);
4517 /*-----------------------------------------------------------------*/
4518 /* genIfxJump :- will create a jump depending on the ifx */
4519 /*-----------------------------------------------------------------*/
4521 genIfxJump (iCode * ic, char *jval)
4524 symbol *tlbl = newiTempLabel (NULL);
4527 D(emitcode ("; genIfxJump",""));
4529 /* if true label then we jump if condition
4533 jlbl = IC_TRUE (ic);
4534 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4535 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4539 /* false label is present */
4540 jlbl = IC_FALSE (ic);
4541 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4542 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4544 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4545 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4547 emitcode (inst, "%05d$", tlbl->key + 100);
4548 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4549 emitcode ("", "%05d$:", tlbl->key + 100);
4551 /* mark the icode as generated */
4555 /*-----------------------------------------------------------------*/
4556 /* genCmp :- greater or less than comparison */
4557 /*-----------------------------------------------------------------*/
4559 genCmp (operand * left, operand * right,
4560 operand * result, iCode * ifx, int sign, iCode *ic)
4562 int size, offset = 0;
4563 unsigned long lit = 0L;
4566 D(emitcode ("; genCmp",""));
4568 /* if left & right are bit variables */
4569 if (AOP_TYPE (left) == AOP_CRY &&
4570 AOP_TYPE (right) == AOP_CRY)
4572 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4573 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4577 /* subtract right from left if at the
4578 end the carry flag is set then we know that
4579 left is greater than right */
4580 size = max (AOP_SIZE (left), AOP_SIZE (right));
4582 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4583 if ((size == 1) && !sign &&
4584 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4586 symbol *lbl = newiTempLabel (NULL);
4587 emitcode ("cjne", "%s,%s,%05d$",
4588 aopGet (AOP (left), offset, FALSE, FALSE),
4589 aopGet (AOP (right), offset, FALSE, FALSE),
4591 emitcode ("", "%05d$:", lbl->key + 100);
4595 if (AOP_TYPE (right) == AOP_LIT)
4597 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4598 /* optimize if(x < 0) or if(x >= 0) */
4607 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4608 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4610 genIfxJump (ifx, "acc.7");
4614 emitcode ("rlc", "a");
4622 rightInB = aopGetUsesAcc(AOP (right), offset);
4624 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4625 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4626 if (sign && size == 0)
4628 emitcode ("xrl", "a,#0x80");
4629 if (AOP_TYPE (right) == AOP_LIT)
4631 unsigned long lit = (unsigned long)
4632 floatFromVal (AOP (right)->aopu.aop_lit);
4633 emitcode ("subb", "a,#0x%02x",
4634 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4639 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4640 emitcode ("xrl", "b,#0x80");
4641 emitcode ("subb", "a,b");
4647 emitcode ("subb", "a,b");
4649 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4657 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4658 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4659 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4665 /* if the result is used in the next
4666 ifx conditional branch then generate
4667 code a little differently */
4669 genIfxJump (ifx, "c");
4672 /* leave the result in acc */
4676 /*-----------------------------------------------------------------*/
4677 /* genCmpGt :- greater than comparison */
4678 /*-----------------------------------------------------------------*/
4680 genCmpGt (iCode * ic, iCode * ifx)
4682 operand *left, *right, *result;
4683 sym_link *letype, *retype;
4686 D(emitcode ("; genCmpGt",""));
4688 left = IC_LEFT (ic);
4689 right = IC_RIGHT (ic);
4690 result = IC_RESULT (ic);
4692 letype = getSpec (operandType (left));
4693 retype = getSpec (operandType (right));
4694 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4695 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4696 /* assign the amsops */
4697 aopOp (left, ic, FALSE);
4698 aopOp (right, ic, FALSE);
4699 aopOp (result, ic, TRUE);
4701 genCmp (right, left, result, ifx, sign,ic);
4703 freeAsmop (result, NULL, ic, TRUE);
4706 /*-----------------------------------------------------------------*/
4707 /* genCmpLt - less than comparisons */
4708 /*-----------------------------------------------------------------*/
4710 genCmpLt (iCode * ic, iCode * ifx)
4712 operand *left, *right, *result;
4713 sym_link *letype, *retype;
4716 D(emitcode ("; genCmpLt",""));
4718 left = IC_LEFT (ic);
4719 right = IC_RIGHT (ic);
4720 result = IC_RESULT (ic);
4722 letype = getSpec (operandType (left));
4723 retype = getSpec (operandType (right));
4724 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4725 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4726 /* assign the amsops */
4727 aopOp (left, ic, FALSE);
4728 aopOp (right, ic, FALSE);
4729 aopOp (result, ic, TRUE);
4731 genCmp (left, right, result, ifx, sign,ic);
4733 freeAsmop (result, NULL, ic, TRUE);
4736 /*-----------------------------------------------------------------*/
4737 /* gencjneshort - compare and jump if not equal */
4738 /*-----------------------------------------------------------------*/
4740 gencjneshort (operand * left, operand * right, symbol * lbl)
4742 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4744 unsigned long lit = 0L;
4746 /* if the left side is a literal or
4747 if the right is in a pointer register and left
4749 if ((AOP_TYPE (left) == AOP_LIT) ||
4750 (AOP_TYPE (left) == AOP_IMMD) ||
4751 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4758 if (AOP_TYPE (right) == AOP_LIT)
4759 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4761 /* if the right side is a literal then anything goes */
4762 if (AOP_TYPE (right) == AOP_LIT &&
4763 AOP_TYPE (left) != AOP_DIR &&
4764 AOP_TYPE (left) != AOP_IMMD)
4768 emitcode ("cjne", "%s,%s,%05d$",
4769 aopGet (AOP (left), offset, FALSE, FALSE),
4770 aopGet (AOP (right), offset, FALSE, FALSE),
4776 /* if the right side is in a register or in direct space or
4777 if the left is a pointer register & right is not */
4778 else if (AOP_TYPE (right) == AOP_REG ||
4779 AOP_TYPE (right) == AOP_DIR ||
4780 AOP_TYPE (right) == AOP_LIT ||
4781 AOP_TYPE (right) == AOP_IMMD ||
4782 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4783 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4787 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4788 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4789 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4790 emitcode ("jnz", "%05d$", lbl->key + 100);
4792 emitcode ("cjne", "a,%s,%05d$",
4793 aopGet (AOP (right), offset, FALSE, TRUE),
4800 /* right is a pointer reg need both a & b */
4803 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4804 if (strcmp (l, "b"))
4805 emitcode ("mov", "b,%s", l);
4806 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4807 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4813 /*-----------------------------------------------------------------*/
4814 /* gencjne - compare and jump if not equal */
4815 /*-----------------------------------------------------------------*/
4817 gencjne (operand * left, operand * right, symbol * lbl)
4819 symbol *tlbl = newiTempLabel (NULL);
4821 gencjneshort (left, right, lbl);
4823 emitcode ("mov", "a,%s", one);
4824 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4825 emitcode ("", "%05d$:", lbl->key + 100);
4826 emitcode ("clr", "a");
4827 emitcode ("", "%05d$:", tlbl->key + 100);
4830 /*-----------------------------------------------------------------*/
4831 /* genCmpEq - generates code for equal to */
4832 /*-----------------------------------------------------------------*/
4834 genCmpEq (iCode * ic, iCode * ifx)
4836 operand *left, *right, *result;
4838 D(emitcode ("; genCmpEq",""));
4840 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4841 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4842 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4844 /* if literal, literal on the right or
4845 if the right is in a pointer register and left
4847 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4848 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4850 operand *t = IC_RIGHT (ic);
4851 IC_RIGHT (ic) = IC_LEFT (ic);
4855 if (ifx && !AOP_SIZE (result))
4858 /* if they are both bit variables */
4859 if (AOP_TYPE (left) == AOP_CRY &&
4860 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4862 if (AOP_TYPE (right) == AOP_LIT)
4864 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4867 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4868 emitcode ("cpl", "c");
4872 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4876 emitcode ("clr", "c");
4878 /* AOP_TYPE(right) == AOP_CRY */
4882 symbol *lbl = newiTempLabel (NULL);
4883 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4884 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4885 emitcode ("cpl", "c");
4886 emitcode ("", "%05d$:", (lbl->key + 100));
4888 /* if true label then we jump if condition
4890 tlbl = newiTempLabel (NULL);
4893 emitcode ("jnc", "%05d$", tlbl->key + 100);
4894 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4898 emitcode ("jc", "%05d$", tlbl->key + 100);
4899 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4901 emitcode ("", "%05d$:", tlbl->key + 100);
4905 tlbl = newiTempLabel (NULL);
4906 gencjneshort (left, right, tlbl);
4909 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4910 emitcode ("", "%05d$:", tlbl->key + 100);
4914 symbol *lbl = newiTempLabel (NULL);
4915 emitcode ("sjmp", "%05d$", lbl->key + 100);
4916 emitcode ("", "%05d$:", tlbl->key + 100);
4917 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4918 emitcode ("", "%05d$:", lbl->key + 100);
4921 /* mark the icode as generated */
4926 /* if they are both bit variables */
4927 if (AOP_TYPE (left) == AOP_CRY &&
4928 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4930 if (AOP_TYPE (right) == AOP_LIT)
4932 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4935 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4936 emitcode ("cpl", "c");
4940 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4944 emitcode ("clr", "c");
4946 /* AOP_TYPE(right) == AOP_CRY */
4950 symbol *lbl = newiTempLabel (NULL);
4951 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4952 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4953 emitcode ("cpl", "c");
4954 emitcode ("", "%05d$:", (lbl->key + 100));
4957 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4964 genIfxJump (ifx, "c");
4967 /* if the result is used in an arithmetic operation
4968 then put the result in place */
4973 gencjne (left, right, newiTempLabel (NULL));
4974 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4976 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4981 genIfxJump (ifx, "a");
4984 /* if the result is used in an arithmetic operation
4985 then put the result in place */
4986 if (AOP_TYPE (result) != AOP_CRY)
4988 /* leave the result in acc */
4992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4994 freeAsmop (result, NULL, ic, TRUE);
4997 /*-----------------------------------------------------------------*/
4998 /* ifxForOp - returns the icode containing the ifx for operand */
4999 /*-----------------------------------------------------------------*/
5001 ifxForOp (operand * op, iCode * ic)
5003 /* if true symbol then needs to be assigned */
5004 if (IS_TRUE_SYMOP (op))
5007 /* if this has register type condition and
5008 the next instruction is ifx with the same operand
5009 and live to of the operand is upto the ifx only then */
5011 ic->next->op == IFX &&
5012 IC_COND (ic->next)->key == op->key &&
5013 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5019 /*-----------------------------------------------------------------*/
5020 /* hasInc - operand is incremented before any other use */
5021 /*-----------------------------------------------------------------*/
5023 hasInc (operand *op, iCode *ic,int osize)
5025 sym_link *type = operandType(op);
5026 sym_link *retype = getSpec (type);
5027 iCode *lic = ic->next;
5030 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5031 if (!IS_SYMOP(op)) return NULL;
5033 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5034 if (IS_AGGREGATE(type->next)) return NULL;
5035 if (osize != (isize = getSize(type->next))) return NULL;
5038 /* if operand of the form op = op + <sizeof *op> */
5039 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5040 isOperandEqual(IC_RESULT(lic),op) &&
5041 isOperandLiteral(IC_RIGHT(lic)) &&
5042 operandLitValue(IC_RIGHT(lic)) == isize) {
5045 /* if the operand used or deffed */
5046 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5049 /* if GOTO or IFX */
5050 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5056 /*-----------------------------------------------------------------*/
5057 /* genAndOp - for && operation */
5058 /*-----------------------------------------------------------------*/
5060 genAndOp (iCode * ic)
5062 operand *left, *right, *result;
5065 D(emitcode ("; genAndOp",""));
5067 /* note here that && operations that are in an
5068 if statement are taken away by backPatchLabels
5069 only those used in arthmetic operations remain */
5070 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5071 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5072 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5074 /* if both are bit variables */
5075 if (AOP_TYPE (left) == AOP_CRY &&
5076 AOP_TYPE (right) == AOP_CRY)
5078 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5079 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5084 tlbl = newiTempLabel (NULL);
5086 emitcode ("jz", "%05d$", tlbl->key + 100);
5088 emitcode ("", "%05d$:", tlbl->key + 100);
5092 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094 freeAsmop (result, NULL, ic, TRUE);
5098 /*-----------------------------------------------------------------*/
5099 /* genOrOp - for || operation */
5100 /*-----------------------------------------------------------------*/
5102 genOrOp (iCode * ic)
5104 operand *left, *right, *result;
5107 D(emitcode ("; genOrOp",""));
5109 /* note here that || operations that are in an
5110 if statement are taken away by backPatchLabels
5111 only those used in arthmetic operations remain */
5112 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5113 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5114 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5116 /* if both are bit variables */
5117 if (AOP_TYPE (left) == AOP_CRY &&
5118 AOP_TYPE (right) == AOP_CRY)
5120 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5121 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5126 tlbl = newiTempLabel (NULL);
5128 emitcode ("jnz", "%05d$", tlbl->key + 100);
5130 emitcode ("", "%05d$:", tlbl->key + 100);
5134 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (result, NULL, ic, TRUE);
5139 /*-----------------------------------------------------------------*/
5140 /* isLiteralBit - test if lit == 2^n */
5141 /*-----------------------------------------------------------------*/
5143 isLiteralBit (unsigned long lit)
5145 unsigned long pw[32] =
5146 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5147 0x100L, 0x200L, 0x400L, 0x800L,
5148 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5149 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5150 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5151 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5152 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5155 for (idx = 0; idx < 32; idx++)
5161 /*-----------------------------------------------------------------*/
5162 /* continueIfTrue - */
5163 /*-----------------------------------------------------------------*/
5165 continueIfTrue (iCode * ic)
5168 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5172 /*-----------------------------------------------------------------*/
5174 /*-----------------------------------------------------------------*/
5176 jumpIfTrue (iCode * ic)
5179 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5183 /*-----------------------------------------------------------------*/
5184 /* jmpTrueOrFalse - */
5185 /*-----------------------------------------------------------------*/
5187 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5189 // ugly but optimized by peephole
5192 symbol *nlbl = newiTempLabel (NULL);
5193 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5194 emitcode ("", "%05d$:", tlbl->key + 100);
5195 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5196 emitcode ("", "%05d$:", nlbl->key + 100);
5200 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5201 emitcode ("", "%05d$:", tlbl->key + 100);
5206 /*-----------------------------------------------------------------*/
5207 /* genAnd - code for and */
5208 /*-----------------------------------------------------------------*/
5210 genAnd (iCode * ic, iCode * ifx)
5212 operand *left, *right, *result;
5213 int size, offset = 0;
5214 unsigned long lit = 0L;
5218 D(emitcode ("; genAnd",""));
5220 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5221 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5222 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5225 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5227 AOP_TYPE (left), AOP_TYPE (right));
5228 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5230 AOP_SIZE (left), AOP_SIZE (right));
5233 /* if left is a literal & right is not then exchange them */
5234 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5235 AOP_NEEDSACC (left))
5237 operand *tmp = right;
5242 /* if result = right then exchange them */
5243 if (sameRegs (AOP (result), AOP (right)))
5245 operand *tmp = right;
5250 /* if right is bit then exchange them */
5251 if (AOP_TYPE (right) == AOP_CRY &&
5252 AOP_TYPE (left) != AOP_CRY)
5254 operand *tmp = right;
5258 if (AOP_TYPE (right) == AOP_LIT)
5259 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5261 size = AOP_SIZE (result);
5264 // result = bit & yy;
5265 if (AOP_TYPE (left) == AOP_CRY)
5267 // c = bit & literal;
5268 if (AOP_TYPE (right) == AOP_LIT)
5272 if (size && sameRegs (AOP (result), AOP (left)))
5275 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5280 if (size && (AOP_TYPE (result) == AOP_CRY))
5282 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5285 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5290 emitcode ("clr", "c");
5295 if (AOP_TYPE (right) == AOP_CRY)
5298 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5299 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5304 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5306 emitcode ("rrc", "a");
5307 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5315 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5316 genIfxJump (ifx, "c");
5320 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5321 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5322 if ((AOP_TYPE (right) == AOP_LIT) &&
5323 (AOP_TYPE (result) == AOP_CRY) &&
5324 (AOP_TYPE (left) != AOP_CRY))
5326 int posbit = isLiteralBit (lit);
5331 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5334 emitcode ("mov", "c,acc.%d", posbit & 0x07);
5340 sprintf (buffer, "acc.%d", posbit & 0x07);
5341 genIfxJump (ifx, buffer);
5348 symbol *tlbl = newiTempLabel (NULL);
5349 int sizel = AOP_SIZE (left);
5351 emitcode ("setb", "c");
5354 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5356 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5358 if ((posbit = isLiteralBit (bytelit)) != 0)
5359 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5362 if (bytelit != 0x0FFL)
5363 emitcode ("anl", "a,%s",
5364 aopGet (AOP (right), offset, FALSE, TRUE));
5365 emitcode ("jnz", "%05d$", tlbl->key + 100);
5370 // bit = left & literal
5373 emitcode ("clr", "c");
5374 emitcode ("", "%05d$:", tlbl->key + 100);
5376 // if(left & literal)
5380 jmpTrueOrFalse (ifx, tlbl);
5382 emitcode ("", "%05d$:", tlbl->key + 100);
5390 /* if left is same as result */
5391 if (sameRegs (AOP (result), AOP (left)))
5393 for (; size--; offset++)
5395 if (AOP_TYPE (right) == AOP_LIT)
5397 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5399 else if (bytelit == 0)
5401 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5403 else if (IS_AOP_PREG (result))
5405 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5406 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5407 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5410 emitcode ("anl", "%s,%s",
5411 aopGet (AOP (left), offset, FALSE, TRUE),
5412 aopGet (AOP (right), offset, FALSE, FALSE));
5416 if (AOP_TYPE (left) == AOP_ACC)
5417 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5420 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5421 if (IS_AOP_PREG (result))
5423 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5424 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5428 emitcode ("anl", "%s,a",
5429 aopGet (AOP (left), offset, FALSE, TRUE));
5436 // left & result in different registers
5437 if (AOP_TYPE (result) == AOP_CRY)
5440 // if(size), result in bit
5441 // if(!size && ifx), conditional oper: if(left & right)
5442 symbol *tlbl = newiTempLabel (NULL);
5443 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5445 emitcode ("setb", "c");
5448 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5449 emitcode ("anl", "a,%s",
5450 aopGet (AOP (right), offset, FALSE, FALSE));
5452 if (AOP_TYPE(left)==AOP_ACC) {
5453 emitcode("mov", "b,a");
5454 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5455 emitcode("anl", "a,b");
5457 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5458 emitcode ("anl", "a,%s",
5459 aopGet (AOP (left), offset, FALSE, FALSE));
5462 emitcode ("jnz", "%05d$", tlbl->key + 100);
5468 emitcode ("", "%05d$:", tlbl->key + 100);
5472 jmpTrueOrFalse (ifx, tlbl);
5474 emitcode ("", "%05d$:", tlbl->key + 100);
5478 for (; (size--); offset++)
5481 // result = left & right
5482 if (AOP_TYPE (right) == AOP_LIT)
5484 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5486 aopPut (AOP (result),
5487 aopGet (AOP (left), offset, FALSE, FALSE),
5489 isOperandVolatile (result, FALSE));
5492 else if (bytelit == 0)
5494 /* dummy read of volatile operand */
5495 if (isOperandVolatile (left, FALSE))
5496 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5497 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5501 // faster than result <- left, anl result,right
5502 // and better if result is SFR
5503 if (AOP_TYPE (left) == AOP_ACC)
5504 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5507 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5508 emitcode ("anl", "a,%s",
5509 aopGet (AOP (left), offset, FALSE, FALSE));
5511 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5517 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5519 freeAsmop (result, NULL, ic, TRUE);
5522 /*-----------------------------------------------------------------*/
5523 /* genOr - code for or */
5524 /*-----------------------------------------------------------------*/
5526 genOr (iCode * ic, iCode * ifx)
5528 operand *left, *right, *result;
5529 int size, offset = 0;
5530 unsigned long lit = 0L;
5532 D(emitcode ("; genOr",""));
5534 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5535 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5536 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5539 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5541 AOP_TYPE (left), AOP_TYPE (right));
5542 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5544 AOP_SIZE (left), AOP_SIZE (right));
5547 /* if left is a literal & right is not then exchange them */
5548 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5549 AOP_NEEDSACC (left))
5551 operand *tmp = right;
5556 /* if result = right then exchange them */
5557 if (sameRegs (AOP (result), AOP (right)))
5559 operand *tmp = right;
5564 /* if right is bit then exchange them */
5565 if (AOP_TYPE (right) == AOP_CRY &&
5566 AOP_TYPE (left) != AOP_CRY)
5568 operand *tmp = right;
5572 if (AOP_TYPE (right) == AOP_LIT)
5573 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5575 size = AOP_SIZE (result);
5579 if (AOP_TYPE (left) == AOP_CRY)
5581 if (AOP_TYPE (right) == AOP_LIT)
5583 // c = bit | literal;
5586 // lit != 0 => result = 1
5587 if (AOP_TYPE (result) == AOP_CRY)
5590 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5592 continueIfTrue (ifx);
5595 emitcode ("setb", "c");
5599 // lit == 0 => result = left
5600 if (size && sameRegs (AOP (result), AOP (left)))
5602 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5607 if (AOP_TYPE (right) == AOP_CRY)
5610 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5611 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5616 symbol *tlbl = newiTempLabel (NULL);
5617 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5618 emitcode ("setb", "c");
5619 emitcode ("jb", "%s,%05d$",
5620 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5622 emitcode ("jnz", "%05d$", tlbl->key + 100);
5623 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5625 jmpTrueOrFalse (ifx, tlbl);
5631 emitcode ("", "%05d$:", tlbl->key + 100);
5640 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5641 genIfxJump (ifx, "c");
5645 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5646 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5647 if ((AOP_TYPE (right) == AOP_LIT) &&
5648 (AOP_TYPE (result) == AOP_CRY) &&
5649 (AOP_TYPE (left) != AOP_CRY))
5655 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5657 continueIfTrue (ifx);
5662 // lit = 0, result = boolean(left)
5664 emitcode ("setb", "c");
5668 symbol *tlbl = newiTempLabel (NULL);
5669 emitcode ("jnz", "%05d$", tlbl->key + 100);
5671 emitcode ("", "%05d$:", tlbl->key + 100);
5675 genIfxJump (ifx, "a");
5683 /* if left is same as result */
5684 if (sameRegs (AOP (result), AOP (left)))
5686 for (; size--; offset++)
5688 if (AOP_TYPE (right) == AOP_LIT)
5690 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5692 /* dummy read of volatile operand */
5693 if (isOperandVolatile (left, FALSE))
5694 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5698 else if (IS_AOP_PREG (left))
5700 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5701 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5702 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5705 emitcode ("orl", "%s,%s",
5706 aopGet (AOP (left), offset, FALSE, TRUE),
5707 aopGet (AOP (right), offset, FALSE, FALSE));
5711 if (AOP_TYPE (left) == AOP_ACC)
5712 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5715 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5716 if (IS_AOP_PREG (left))
5718 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5719 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5722 emitcode ("orl", "%s,a",
5723 aopGet (AOP (left), offset, FALSE, TRUE));
5730 // left & result in different registers
5731 if (AOP_TYPE (result) == AOP_CRY)
5734 // if(size), result in bit
5735 // if(!size && ifx), conditional oper: if(left | right)
5736 symbol *tlbl = newiTempLabel (NULL);
5737 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5739 emitcode ("setb", "c");
5742 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5743 emitcode ("orl", "a,%s",
5744 aopGet (AOP (right), offset, FALSE, FALSE));
5746 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5747 emitcode ("orl", "a,%s",
5748 aopGet (AOP (left), offset, FALSE, FALSE));
5750 emitcode ("jnz", "%05d$", tlbl->key + 100);
5756 emitcode ("", "%05d$:", tlbl->key + 100);
5760 jmpTrueOrFalse (ifx, tlbl);
5762 emitcode ("", "%05d$:", tlbl->key + 100);
5765 for (; (size--); offset++)
5768 // result = left & right
5769 if (AOP_TYPE (right) == AOP_LIT)
5771 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5773 aopPut (AOP (result),
5774 aopGet (AOP (left), offset, FALSE, FALSE),
5776 isOperandVolatile (result, FALSE));
5780 // faster than result <- left, anl result,right
5781 // and better if result is SFR
5782 if (AOP_TYPE (left) == AOP_ACC)
5783 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5786 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5787 emitcode ("orl", "a,%s",
5788 aopGet (AOP (left), offset, FALSE, FALSE));
5790 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5795 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5796 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5797 freeAsmop (result, NULL, ic, TRUE);
5800 /*-----------------------------------------------------------------*/
5801 /* genXor - code for xclusive or */
5802 /*-----------------------------------------------------------------*/
5804 genXor (iCode * ic, iCode * ifx)
5806 operand *left, *right, *result;
5807 int size, offset = 0;
5808 unsigned long lit = 0L;
5810 D(emitcode ("; genXor",""));
5812 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5813 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5814 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5817 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5819 AOP_TYPE (left), AOP_TYPE (right));
5820 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5822 AOP_SIZE (left), AOP_SIZE (right));
5825 /* if left is a literal & right is not ||
5826 if left needs acc & right does not */
5827 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5828 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5830 operand *tmp = right;
5835 /* if result = right then exchange them */
5836 if (sameRegs (AOP (result), AOP (right)))
5838 operand *tmp = right;
5843 /* if right is bit then exchange them */
5844 if (AOP_TYPE (right) == AOP_CRY &&
5845 AOP_TYPE (left) != AOP_CRY)
5847 operand *tmp = right;
5851 if (AOP_TYPE (right) == AOP_LIT)
5852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5854 size = AOP_SIZE (result);
5858 if (AOP_TYPE (left) == AOP_CRY)
5860 if (AOP_TYPE (right) == AOP_LIT)
5862 // c = bit & literal;
5865 // lit>>1 != 0 => result = 1
5866 if (AOP_TYPE (result) == AOP_CRY)
5869 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5871 continueIfTrue (ifx);
5874 emitcode ("setb", "c");
5881 // lit == 0, result = left
5882 if (size && sameRegs (AOP (result), AOP (left)))
5884 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5888 // lit == 1, result = not(left)
5889 if (size && sameRegs (AOP (result), AOP (left)))
5891 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5896 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5897 emitcode ("cpl", "c");
5906 symbol *tlbl = newiTempLabel (NULL);
5907 if (AOP_TYPE (right) == AOP_CRY)
5910 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5914 int sizer = AOP_SIZE (right);
5916 // if val>>1 != 0, result = 1
5917 emitcode ("setb", "c");
5920 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5922 // test the msb of the lsb
5923 emitcode ("anl", "a,#0xfe");
5924 emitcode ("jnz", "%05d$", tlbl->key + 100);
5928 emitcode ("rrc", "a");
5930 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5931 emitcode ("cpl", "c");
5932 emitcode ("", "%05d$:", (tlbl->key + 100));
5939 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5940 genIfxJump (ifx, "c");
5944 if (sameRegs (AOP (result), AOP (left)))
5946 /* if left is same as result */
5947 for (; size--; offset++)
5949 if (AOP_TYPE (right) == AOP_LIT)
5951 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5953 else if (IS_AOP_PREG (left))
5955 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5956 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5957 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5960 emitcode ("xrl", "%s,%s",
5961 aopGet (AOP (left), offset, FALSE, TRUE),
5962 aopGet (AOP (right), offset, FALSE, FALSE));
5966 if (AOP_TYPE (left) == AOP_ACC)
5967 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5970 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5971 if (IS_AOP_PREG (left))
5973 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5974 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5977 emitcode ("xrl", "%s,a",
5978 aopGet (AOP (left), offset, FALSE, TRUE));
5985 // left & result in different registers
5986 if (AOP_TYPE (result) == AOP_CRY)
5989 // if(size), result in bit
5990 // if(!size && ifx), conditional oper: if(left ^ right)
5991 symbol *tlbl = newiTempLabel (NULL);
5992 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5994 emitcode ("setb", "c");
5997 if ((AOP_TYPE (right) == AOP_LIT) &&
5998 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6000 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6004 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6005 emitcode ("xrl", "a,%s",
6006 aopGet (AOP (right), offset, FALSE, FALSE));
6008 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6009 emitcode ("xrl", "a,%s",
6010 aopGet (AOP (left), offset, FALSE, FALSE));
6013 emitcode ("jnz", "%05d$", tlbl->key + 100);
6019 emitcode ("", "%05d$:", tlbl->key + 100);
6023 jmpTrueOrFalse (ifx, tlbl);
6026 for (; (size--); offset++)
6029 // result = left & right
6030 if (AOP_TYPE (right) == AOP_LIT)
6032 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6034 aopPut (AOP (result),
6035 aopGet (AOP (left), offset, FALSE, FALSE),
6037 isOperandVolatile (result, FALSE));
6041 // faster than result <- left, anl result,right
6042 // and better if result is SFR
6043 if (AOP_TYPE (left) == AOP_ACC)
6044 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6047 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6048 emitcode ("xrl", "a,%s",
6049 aopGet (AOP (left), offset, FALSE, TRUE));
6051 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6056 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6057 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6058 freeAsmop (result, NULL, ic, TRUE);
6061 /*-----------------------------------------------------------------*/
6062 /* genInline - write the inline code out */
6063 /*-----------------------------------------------------------------*/
6065 genInline (iCode * ic)
6067 char *buffer, *bp, *bp1;
6069 D(emitcode ("; genInline",""));
6071 _G.inLine += (!options.asmpeep);
6073 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6074 strcpy (buffer, IC_INLINE (ic));
6076 /* emit each line as a code */
6101 /* emitcode("",buffer); */
6102 _G.inLine -= (!options.asmpeep);
6105 /*-----------------------------------------------------------------*/
6106 /* genRRC - rotate right with carry */
6107 /*-----------------------------------------------------------------*/
6111 operand *left, *result;
6112 int size, offset = 0;
6115 D(emitcode ("; genRRC",""));
6117 /* rotate right with carry */
6118 left = IC_LEFT (ic);
6119 result = IC_RESULT (ic);
6120 aopOp (left, ic, FALSE);
6121 aopOp (result, ic, FALSE);
6123 /* move it to the result */
6124 size = AOP_SIZE (result);
6126 if (size == 1) { /* special case for 1 byte */
6127 l = aopGet (AOP (left), offset, FALSE, FALSE);
6129 emitcode ("rr", "a");
6135 l = aopGet (AOP (left), offset, FALSE, FALSE);
6137 emitcode ("rrc", "a");
6138 if (AOP_SIZE (result) > 1)
6139 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6141 /* now we need to put the carry into the
6142 highest order byte of the result */
6143 if (AOP_SIZE (result) > 1)
6145 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6148 emitcode ("mov", "acc.7,c");
6150 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6151 freeAsmop (left, NULL, ic, TRUE);
6152 freeAsmop (result, NULL, ic, TRUE);
6155 /*-----------------------------------------------------------------*/
6156 /* genRLC - generate code for rotate left with carry */
6157 /*-----------------------------------------------------------------*/
6161 operand *left, *result;
6162 int size, offset = 0;
6165 D(emitcode ("; genRLC",""));
6167 /* rotate right with carry */
6168 left = IC_LEFT (ic);
6169 result = IC_RESULT (ic);
6170 aopOp (left, ic, FALSE);
6171 aopOp (result, ic, FALSE);
6173 /* move it to the result */
6174 size = AOP_SIZE (result);
6178 l = aopGet (AOP (left), offset, FALSE, FALSE);
6180 if (size == 0) { /* special case for 1 byte */
6184 emitcode ("add", "a,acc");
6185 if (AOP_SIZE (result) > 1)
6186 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6189 l = aopGet (AOP (left), offset, FALSE, FALSE);
6191 emitcode ("rlc", "a");
6192 if (AOP_SIZE (result) > 1)
6193 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6196 /* now we need to put the carry into the
6197 highest order byte of the result */
6198 if (AOP_SIZE (result) > 1)
6200 l = aopGet (AOP (result), 0, FALSE, FALSE);
6203 emitcode ("mov", "acc.0,c");
6205 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6206 freeAsmop (left, NULL, ic, TRUE);
6207 freeAsmop (result, NULL, ic, TRUE);
6210 /*-----------------------------------------------------------------*/
6211 /* genGetHbit - generates code get highest order bit */
6212 /*-----------------------------------------------------------------*/
6214 genGetHbit (iCode * ic)
6216 operand *left, *result;
6218 D(emitcode ("; genGetHbit",""));
6220 left = IC_LEFT (ic);
6221 result = IC_RESULT (ic);
6222 aopOp (left, ic, FALSE);
6223 aopOp (result, ic, FALSE);
6225 /* get the highest order byte into a */
6226 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6227 if (AOP_TYPE (result) == AOP_CRY)
6229 emitcode ("rlc", "a");
6234 emitcode ("rl", "a");
6235 emitcode ("anl", "a,#0x01");
6240 freeAsmop (left, NULL, ic, TRUE);
6241 freeAsmop (result, NULL, ic, TRUE);
6244 /*-----------------------------------------------------------------*/
6245 /* genSwap - generates code to swap nibbles or bytes */
6246 /*-----------------------------------------------------------------*/
6248 genSwap (iCode * ic)
6250 operand *left, *result;
6252 D(emitcode ("; genSwap",""));
6254 left = IC_LEFT (ic);
6255 result = IC_RESULT (ic);
6256 aopOp (left, ic, FALSE);
6257 aopOp (result, ic, FALSE);
6259 switch (AOP_SIZE (left))
6261 case 1: /* swap nibbles in byte */
6262 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6263 emitcode ("swap", "a");
6264 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6266 case 2: /* swap bytes in word */
6267 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6269 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6270 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6271 0, isOperandVolatile (result, FALSE));
6272 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6274 else if (operandsEqu (left, result))
6277 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6278 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6280 emitcode ("mov", "b,a");
6283 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6284 0, isOperandVolatile (result, FALSE));
6285 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6289 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6290 0, isOperandVolatile (result, FALSE));
6291 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6292 1, isOperandVolatile (result, FALSE));
6296 wassertl(FALSE, "unsupported SWAP operand size");
6299 freeAsmop (left, NULL, ic, TRUE);
6300 freeAsmop (result, NULL, ic, TRUE);
6304 /*-----------------------------------------------------------------*/
6305 /* AccRol - rotate left accumulator by known count */
6306 /*-----------------------------------------------------------------*/
6308 AccRol (int shCount)
6310 shCount &= 0x0007; // shCount : 0..7
6317 emitcode ("rl", "a");
6320 emitcode ("rl", "a");
6321 emitcode ("rl", "a");
6324 emitcode ("swap", "a");
6325 emitcode ("rr", "a");
6328 emitcode ("swap", "a");
6331 emitcode ("swap", "a");
6332 emitcode ("rl", "a");
6335 emitcode ("rr", "a");
6336 emitcode ("rr", "a");
6339 emitcode ("rr", "a");
6344 /*-----------------------------------------------------------------*/
6345 /* AccLsh - left shift accumulator by known count */
6346 /*-----------------------------------------------------------------*/
6348 AccLsh (int shCount)
6353 emitcode ("add", "a,acc");
6354 else if (shCount == 2)
6356 emitcode ("add", "a,acc");
6357 emitcode ("add", "a,acc");
6361 /* rotate left accumulator */
6363 /* and kill the lower order bits */
6364 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6369 /*-----------------------------------------------------------------*/
6370 /* AccRsh - right shift accumulator by known count */
6371 /*-----------------------------------------------------------------*/
6373 AccRsh (int shCount)
6380 emitcode ("rrc", "a");
6384 /* rotate right accumulator */
6385 AccRol (8 - shCount);
6386 /* and kill the higher order bits */
6387 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6392 /*-----------------------------------------------------------------*/
6393 /* AccSRsh - signed right shift accumulator by known count */
6394 /*-----------------------------------------------------------------*/
6396 AccSRsh (int shCount)
6403 emitcode ("mov", "c,acc.7");
6404 emitcode ("rrc", "a");
6406 else if (shCount == 2)
6408 emitcode ("mov", "c,acc.7");
6409 emitcode ("rrc", "a");
6410 emitcode ("mov", "c,acc.7");
6411 emitcode ("rrc", "a");
6415 tlbl = newiTempLabel (NULL);
6416 /* rotate right accumulator */
6417 AccRol (8 - shCount);
6418 /* and kill the higher order bits */
6419 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6420 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6421 emitcode ("orl", "a,#0x%02x",
6422 (unsigned char) ~SRMask[shCount]);
6423 emitcode ("", "%05d$:", tlbl->key + 100);
6428 /*-----------------------------------------------------------------*/
6429 /* shiftR1Left2Result - shift right one byte from left to result */
6430 /*-----------------------------------------------------------------*/
6432 shiftR1Left2Result (operand * left, int offl,
6433 operand * result, int offr,
6434 int shCount, int sign)
6436 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6437 /* shift right accumulator */
6442 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6445 /*-----------------------------------------------------------------*/
6446 /* shiftL1Left2Result - shift left one byte from left to result */
6447 /*-----------------------------------------------------------------*/
6449 shiftL1Left2Result (operand * left, int offl,
6450 operand * result, int offr, int shCount)
6453 l = aopGet (AOP (left), offl, FALSE, FALSE);
6455 /* shift left accumulator */
6457 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6460 /*-----------------------------------------------------------------*/
6461 /* movLeft2Result - move byte from left to result */
6462 /*-----------------------------------------------------------------*/
6464 movLeft2Result (operand * left, int offl,
6465 operand * result, int offr, int sign)
6468 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6470 l = aopGet (AOP (left), offl, FALSE, FALSE);
6472 if (*l == '@' && (IS_AOP_PREG (result)))
6474 emitcode ("mov", "a,%s", l);
6475 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6480 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6483 /* MSB sign in acc.7 ! */
6484 if (getDataSize (left) == offl + 1)
6486 emitcode ("mov", "a,%s", l);
6487 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6494 /*-----------------------------------------------------------------*/
6495 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6496 /*-----------------------------------------------------------------*/
6500 emitcode ("rrc", "a");
6501 emitcode ("xch", "a,%s", x);
6502 emitcode ("rrc", "a");
6503 emitcode ("xch", "a,%s", x);
6506 /*-----------------------------------------------------------------*/
6507 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6508 /*-----------------------------------------------------------------*/
6512 emitcode ("xch", "a,%s", x);
6513 emitcode ("rlc", "a");
6514 emitcode ("xch", "a,%s", x);
6515 emitcode ("rlc", "a");
6518 /*-----------------------------------------------------------------*/
6519 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6520 /*-----------------------------------------------------------------*/
6524 emitcode ("xch", "a,%s", x);
6525 emitcode ("add", "a,acc");
6526 emitcode ("xch", "a,%s", x);
6527 emitcode ("rlc", "a");
6530 /*-----------------------------------------------------------------*/
6531 /* AccAXLsh - left shift a:x by known count (0..7) */
6532 /*-----------------------------------------------------------------*/
6534 AccAXLsh (char *x, int shCount)
6549 case 5: // AAAAABBB:CCCCCDDD
6551 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6553 emitcode ("anl", "a,#0x%02x",
6554 SLMask[shCount]); // BBB00000:CCCCCDDD
6556 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6558 AccRol (shCount); // DDDCCCCC:BBB00000
6560 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6562 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6564 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6566 emitcode ("anl", "a,#0x%02x",
6567 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6569 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6571 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6574 case 6: // AAAAAABB:CCCCCCDD
6575 emitcode ("anl", "a,#0x%02x",
6576 SRMask[shCount]); // 000000BB:CCCCCCDD
6577 emitcode ("mov", "c,acc.0"); // c = B
6578 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6580 AccAXRrl1 (x); // BCCCCCCD:D000000B
6581 AccAXRrl1 (x); // BBCCCCCC:DD000000
6583 emitcode("rrc","a");
6584 emitcode("xch","a,%s", x);
6585 emitcode("rrc","a");
6586 emitcode("mov","c,acc.0"); //<< get correct bit
6587 emitcode("xch","a,%s", x);
6589 emitcode("rrc","a");
6590 emitcode("xch","a,%s", x);
6591 emitcode("rrc","a");
6592 emitcode("xch","a,%s", x);
6595 case 7: // a:x <<= 7
6597 emitcode ("anl", "a,#0x%02x",
6598 SRMask[shCount]); // 0000000B:CCCCCCCD
6600 emitcode ("mov", "c,acc.0"); // c = B
6602 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6604 AccAXRrl1 (x); // BCCCCCCC:D0000000
6612 /*-----------------------------------------------------------------*/
6613 /* AccAXRsh - right shift a:x known count (0..7) */
6614 /*-----------------------------------------------------------------*/
6616 AccAXRsh (char *x, int shCount)
6624 AccAXRrl1 (x); // 0->a:x
6629 AccAXRrl1 (x); // 0->a:x
6632 AccAXRrl1 (x); // 0->a:x
6637 case 5: // AAAAABBB:CCCCCDDD = a:x
6639 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6641 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6643 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6645 emitcode ("anl", "a,#0x%02x",
6646 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6648 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6650 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6652 emitcode ("anl", "a,#0x%02x",
6653 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6655 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6657 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6659 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6662 case 6: // AABBBBBB:CCDDDDDD
6664 emitcode ("mov", "c,acc.7");
6665 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6667 emitcode ("mov", "c,acc.7");
6668 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6670 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6672 emitcode ("anl", "a,#0x%02x",
6673 SRMask[shCount]); // 000000AA:BBBBBBCC
6676 case 7: // ABBBBBBB:CDDDDDDD
6678 emitcode ("mov", "c,acc.7"); // c = A
6680 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6682 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6684 emitcode ("anl", "a,#0x%02x",
6685 SRMask[shCount]); // 0000000A:BBBBBBBC
6693 /*-----------------------------------------------------------------*/
6694 /* AccAXRshS - right shift signed a:x known count (0..7) */
6695 /*-----------------------------------------------------------------*/
6697 AccAXRshS (char *x, int shCount)
6705 emitcode ("mov", "c,acc.7");
6706 AccAXRrl1 (x); // s->a:x
6710 emitcode ("mov", "c,acc.7");
6711 AccAXRrl1 (x); // s->a:x
6713 emitcode ("mov", "c,acc.7");
6714 AccAXRrl1 (x); // s->a:x
6719 case 5: // AAAAABBB:CCCCCDDD = a:x
6721 tlbl = newiTempLabel (NULL);
6722 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6724 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6726 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6728 emitcode ("anl", "a,#0x%02x",
6729 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6731 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6733 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6735 emitcode ("anl", "a,#0x%02x",
6736 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6738 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6740 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6742 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6744 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6745 emitcode ("orl", "a,#0x%02x",
6746 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6748 emitcode ("", "%05d$:", tlbl->key + 100);
6749 break; // SSSSAAAA:BBBCCCCC
6751 case 6: // AABBBBBB:CCDDDDDD
6753 tlbl = newiTempLabel (NULL);
6754 emitcode ("mov", "c,acc.7");
6755 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6757 emitcode ("mov", "c,acc.7");
6758 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6760 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6762 emitcode ("anl", "a,#0x%02x",
6763 SRMask[shCount]); // 000000AA:BBBBBBCC
6765 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6766 emitcode ("orl", "a,#0x%02x",
6767 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6769 emitcode ("", "%05d$:", tlbl->key + 100);
6771 case 7: // ABBBBBBB:CDDDDDDD
6773 tlbl = newiTempLabel (NULL);
6774 emitcode ("mov", "c,acc.7"); // c = A
6776 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6778 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6780 emitcode ("anl", "a,#0x%02x",
6781 SRMask[shCount]); // 0000000A:BBBBBBBC
6783 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6784 emitcode ("orl", "a,#0x%02x",
6785 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6787 emitcode ("", "%05d$:", tlbl->key + 100);
6794 /*-----------------------------------------------------------------*/
6795 /* shiftL2Left2Result - shift left two bytes from left to result */
6796 /*-----------------------------------------------------------------*/
6798 shiftL2Left2Result (operand * left, int offl,
6799 operand * result, int offr, int shCount)
6801 if (sameRegs (AOP (result), AOP (left)) &&
6802 ((offl + MSB16) == offr))
6804 /* don't crash result[offr] */
6805 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6806 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6810 movLeft2Result (left, offl, result, offr, 0);
6811 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6813 /* ax << shCount (x = lsb(result)) */
6814 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6815 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6819 /*-----------------------------------------------------------------*/
6820 /* shiftR2Left2Result - shift right two bytes from left to result */
6821 /*-----------------------------------------------------------------*/
6823 shiftR2Left2Result (operand * left, int offl,
6824 operand * result, int offr,
6825 int shCount, int sign)
6827 if (sameRegs (AOP (result), AOP (left)) &&
6828 ((offl + MSB16) == offr))
6830 /* don't crash result[offr] */
6831 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6832 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6836 movLeft2Result (left, offl, result, offr, 0);
6837 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6839 /* a:x >> shCount (x = lsb(result)) */
6841 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6843 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6844 if (getDataSize (result) > 1)
6845 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6848 /*-----------------------------------------------------------------*/
6849 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6850 /*-----------------------------------------------------------------*/
6852 shiftLLeftOrResult (operand * left, int offl,
6853 operand * result, int offr, int shCount)
6855 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6856 /* shift left accumulator */
6858 /* or with result */
6859 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6860 /* back to result */
6861 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6864 /*-----------------------------------------------------------------*/
6865 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6866 /*-----------------------------------------------------------------*/
6868 shiftRLeftOrResult (operand * left, int offl,
6869 operand * result, int offr, int shCount)
6871 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6872 /* shift right accumulator */
6874 /* or with result */
6875 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6876 /* back to result */
6877 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6880 /*-----------------------------------------------------------------*/
6881 /* genlshOne - left shift a one byte quantity by known count */
6882 /*-----------------------------------------------------------------*/
6884 genlshOne (operand * result, operand * left, int shCount)
6886 D(emitcode ("; genlshOne",""));
6888 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6891 /*-----------------------------------------------------------------*/
6892 /* genlshTwo - left shift two bytes by known amount != 0 */
6893 /*-----------------------------------------------------------------*/
6895 genlshTwo (operand * result, operand * left, int shCount)
6899 D(emitcode ("; genlshTwo",""));
6901 size = getDataSize (result);
6903 /* if shCount >= 8 */
6911 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6913 movLeft2Result (left, LSB, result, MSB16, 0);
6915 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6918 /* 1 <= shCount <= 7 */
6922 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6924 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6928 /*-----------------------------------------------------------------*/
6929 /* shiftLLong - shift left one long from left to result */
6930 /* offl = LSB or MSB16 */
6931 /*-----------------------------------------------------------------*/
6933 shiftLLong (operand * left, operand * result, int offr)
6936 int size = AOP_SIZE (result);
6938 if (size >= LSB + offr)
6940 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6942 emitcode ("add", "a,acc");
6943 if (sameRegs (AOP (left), AOP (result)) &&
6944 size >= MSB16 + offr && offr != LSB)
6945 emitcode ("xch", "a,%s",
6946 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6948 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6951 if (size >= MSB16 + offr)
6953 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6955 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6958 emitcode ("rlc", "a");
6959 if (sameRegs (AOP (left), AOP (result)) &&
6960 size >= MSB24 + offr && offr != LSB)
6961 emitcode ("xch", "a,%s",
6962 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6964 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6967 if (size >= MSB24 + offr)
6969 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6971 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6974 emitcode ("rlc", "a");
6975 if (sameRegs (AOP (left), AOP (result)) &&
6976 size >= MSB32 + offr && offr != LSB)
6977 emitcode ("xch", "a,%s",
6978 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6980 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6983 if (size > MSB32 + offr)
6985 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6987 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6990 emitcode ("rlc", "a");
6991 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6994 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6997 /*-----------------------------------------------------------------*/
6998 /* genlshFour - shift four byte by a known amount != 0 */
6999 /*-----------------------------------------------------------------*/
7001 genlshFour (operand * result, operand * left, int shCount)
7005 D(emitcode ("; genlshFour",""));
7007 size = AOP_SIZE (result);
7009 /* if shifting more that 3 bytes */
7014 /* lowest order of left goes to the highest
7015 order of the destination */
7016 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7018 movLeft2Result (left, LSB, result, MSB32, 0);
7019 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7020 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7021 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7025 /* more than two bytes */
7026 else if (shCount >= 16)
7028 /* lower order two bytes goes to higher order two bytes */
7030 /* if some more remaining */
7032 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7035 movLeft2Result (left, MSB16, result, MSB32, 0);
7036 movLeft2Result (left, LSB, result, MSB24, 0);
7038 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7039 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7043 /* if more than 1 byte */
7044 else if (shCount >= 8)
7046 /* lower order three bytes goes to higher order three bytes */
7051 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7053 movLeft2Result (left, LSB, result, MSB16, 0);
7059 movLeft2Result (left, MSB24, result, MSB32, 0);
7060 movLeft2Result (left, MSB16, result, MSB24, 0);
7061 movLeft2Result (left, LSB, result, MSB16, 0);
7062 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7064 else if (shCount == 1)
7065 shiftLLong (left, result, MSB16);
7068 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7069 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7070 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7071 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7076 /* 1 <= shCount <= 7 */
7077 else if (shCount <= 2)
7079 shiftLLong (left, result, LSB);
7081 shiftLLong (result, result, LSB);
7083 /* 3 <= shCount <= 7, optimize */
7086 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7087 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7088 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7092 /*-----------------------------------------------------------------*/
7093 /* genLeftShiftLiteral - left shifting by known count */
7094 /*-----------------------------------------------------------------*/
7096 genLeftShiftLiteral (operand * left,
7101 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7104 D(emitcode ("; genLeftShiftLiteral",""));
7106 freeAsmop (right, NULL, ic, TRUE);
7108 aopOp (left, ic, FALSE);
7109 aopOp (result, ic, FALSE);
7111 size = getSize (operandType (result));
7114 emitcode ("; shift left ", "result %d, left %d", size,
7118 /* I suppose that the left size >= result size */
7123 movLeft2Result (left, size, result, size, 0);
7127 else if (shCount >= (size * 8))
7129 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7135 genlshOne (result, left, shCount);
7139 genlshTwo (result, left, shCount);
7143 genlshFour (result, left, shCount);
7146 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7147 "*** ack! mystery literal shift!\n");
7151 freeAsmop (left, NULL, ic, TRUE);
7152 freeAsmop (result, NULL, ic, TRUE);
7155 /*-----------------------------------------------------------------*/
7156 /* genLeftShift - generates code for left shifting */
7157 /*-----------------------------------------------------------------*/
7159 genLeftShift (iCode * ic)
7161 operand *left, *right, *result;
7164 symbol *tlbl, *tlbl1;
7166 D(emitcode ("; genLeftShift",""));
7168 right = IC_RIGHT (ic);
7169 left = IC_LEFT (ic);
7170 result = IC_RESULT (ic);
7172 aopOp (right, ic, FALSE);
7174 /* if the shift count is known then do it
7175 as efficiently as possible */
7176 if (AOP_TYPE (right) == AOP_LIT)
7178 genLeftShiftLiteral (left, right, result, ic);
7182 /* shift count is unknown then we have to form
7183 a loop get the loop count in B : Note: we take
7184 only the lower order byte since shifting
7185 more that 32 bits make no sense anyway, ( the
7186 largest size of an object can be only 32 bits ) */
7188 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7189 emitcode ("inc", "b");
7190 freeAsmop (right, NULL, ic, TRUE);
7191 aopOp (left, ic, FALSE);
7192 aopOp (result, ic, FALSE);
7194 /* now move the left to the result if they are not the
7196 if (!sameRegs (AOP (left), AOP (result)) &&
7197 AOP_SIZE (result) > 1)
7200 size = AOP_SIZE (result);
7204 l = aopGet (AOP (left), offset, FALSE, TRUE);
7205 if (*l == '@' && (IS_AOP_PREG (result)))
7208 emitcode ("mov", "a,%s", l);
7209 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7212 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7217 tlbl = newiTempLabel (NULL);
7218 size = AOP_SIZE (result);
7220 tlbl1 = newiTempLabel (NULL);
7222 /* if it is only one byte then */
7225 symbol *tlbl1 = newiTempLabel (NULL);
7227 l = aopGet (AOP (left), 0, FALSE, FALSE);
7229 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7230 emitcode ("", "%05d$:", tlbl->key + 100);
7231 emitcode ("add", "a,acc");
7232 emitcode ("", "%05d$:", tlbl1->key + 100);
7233 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7234 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7238 reAdjustPreg (AOP (result));
7240 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7241 emitcode ("", "%05d$:", tlbl->key + 100);
7242 l = aopGet (AOP (result), offset, FALSE, FALSE);
7244 emitcode ("add", "a,acc");
7245 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7248 l = aopGet (AOP (result), offset, FALSE, FALSE);
7250 emitcode ("rlc", "a");
7251 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7253 reAdjustPreg (AOP (result));
7255 emitcode ("", "%05d$:", tlbl1->key + 100);
7256 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7258 freeAsmop (left, NULL, ic, TRUE);
7259 freeAsmop (result, NULL, ic, TRUE);
7262 /*-----------------------------------------------------------------*/
7263 /* genrshOne - right shift a one byte quantity by known count */
7264 /*-----------------------------------------------------------------*/
7266 genrshOne (operand * result, operand * left,
7267 int shCount, int sign)
7269 D(emitcode ("; genrshOne",""));
7271 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7274 /*-----------------------------------------------------------------*/
7275 /* genrshTwo - right shift two bytes by known amount != 0 */
7276 /*-----------------------------------------------------------------*/
7278 genrshTwo (operand * result, operand * left,
7279 int shCount, int sign)
7281 D(emitcode ("; genrshTwo",""));
7283 /* if shCount >= 8 */
7288 shiftR1Left2Result (left, MSB16, result, LSB,
7291 movLeft2Result (left, MSB16, result, LSB, sign);
7292 addSign (result, MSB16, sign);
7295 /* 1 <= shCount <= 7 */
7297 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7300 /*-----------------------------------------------------------------*/
7301 /* shiftRLong - shift right one long from left to result */
7302 /* offl = LSB or MSB16 */
7303 /*-----------------------------------------------------------------*/
7305 shiftRLong (operand * left, int offl,
7306 operand * result, int sign)
7308 int isSameRegs=sameRegs(AOP(left),AOP(result));
7310 if (isSameRegs && offl>1) {
7311 // we are in big trouble, but this shouldn't happen
7312 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7315 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7320 emitcode ("rlc", "a");
7321 emitcode ("subb", "a,acc");
7323 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7325 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7326 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7329 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7334 emitcode ("clr", "c");
7336 emitcode ("mov", "c,acc.7");
7339 emitcode ("rrc", "a");
7341 if (isSameRegs && offl==MSB16) {
7342 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7344 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7345 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7348 emitcode ("rrc", "a");
7349 if (isSameRegs && offl==1) {
7350 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7352 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7353 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7355 emitcode ("rrc", "a");
7356 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7360 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7361 emitcode ("rrc", "a");
7362 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7366 /*-----------------------------------------------------------------*/
7367 /* genrshFour - shift four byte by a known amount != 0 */
7368 /*-----------------------------------------------------------------*/
7370 genrshFour (operand * result, operand * left,
7371 int shCount, int sign)
7373 D(emitcode ("; genrshFour",""));
7375 /* if shifting more that 3 bytes */
7380 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7382 movLeft2Result (left, MSB32, result, LSB, sign);
7383 addSign (result, MSB16, sign);
7385 else if (shCount >= 16)
7389 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7392 movLeft2Result (left, MSB24, result, LSB, 0);
7393 movLeft2Result (left, MSB32, result, MSB16, sign);
7395 addSign (result, MSB24, sign);
7397 else if (shCount >= 8)
7401 shiftRLong (left, MSB16, result, sign);
7402 else if (shCount == 0)
7404 movLeft2Result (left, MSB16, result, LSB, 0);
7405 movLeft2Result (left, MSB24, result, MSB16, 0);
7406 movLeft2Result (left, MSB32, result, MSB24, sign);
7407 addSign (result, MSB32, sign);
7411 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7412 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7413 /* the last shift is signed */
7414 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7415 addSign (result, MSB32, sign);
7419 { /* 1 <= shCount <= 7 */
7422 shiftRLong (left, LSB, result, sign);
7424 shiftRLong (result, LSB, result, sign);
7428 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7429 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7430 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7435 /*-----------------------------------------------------------------*/
7436 /* genRightShiftLiteral - right shifting by known count */
7437 /*-----------------------------------------------------------------*/
7439 genRightShiftLiteral (operand * left,
7445 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7448 D(emitcode ("; genRightShiftLiteral",""));
7450 freeAsmop (right, NULL, ic, TRUE);
7452 aopOp (left, ic, FALSE);
7453 aopOp (result, ic, FALSE);
7456 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7460 size = getDataSize (left);
7461 /* test the LEFT size !!! */
7463 /* I suppose that the left size >= result size */
7466 size = getDataSize (result);
7468 movLeft2Result (left, size, result, size, 0);
7471 else if (shCount >= (size * 8))
7474 /* get sign in acc.7 */
7475 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7477 addSign (result, LSB, sign);
7484 genrshOne (result, left, shCount, sign);
7488 genrshTwo (result, left, shCount, sign);
7492 genrshFour (result, left, shCount, sign);
7498 freeAsmop (left, NULL, ic, TRUE);
7499 freeAsmop (result, NULL, ic, TRUE);
7502 /*-----------------------------------------------------------------*/
7503 /* genSignedRightShift - right shift of signed number */
7504 /*-----------------------------------------------------------------*/
7506 genSignedRightShift (iCode * ic)
7508 operand *right, *left, *result;
7511 symbol *tlbl, *tlbl1;
7513 D(emitcode ("; genSignedRightShift",""));
7515 /* we do it the hard way put the shift count in b
7516 and loop thru preserving the sign */
7518 right = IC_RIGHT (ic);
7519 left = IC_LEFT (ic);
7520 result = IC_RESULT (ic);
7522 aopOp (right, ic, FALSE);
7525 if (AOP_TYPE (right) == AOP_LIT)
7527 genRightShiftLiteral (left, right, result, ic, 1);
7530 /* shift count is unknown then we have to form
7531 a loop get the loop count in B : Note: we take
7532 only the lower order byte since shifting
7533 more that 32 bits make no sense anyway, ( the
7534 largest size of an object can be only 32 bits ) */
7536 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7537 emitcode ("inc", "b");
7538 freeAsmop (right, NULL, ic, TRUE);
7539 aopOp (left, ic, FALSE);
7540 aopOp (result, ic, FALSE);
7542 /* now move the left to the result if they are not the
7544 if (!sameRegs (AOP (left), AOP (result)) &&
7545 AOP_SIZE (result) > 1)
7548 size = AOP_SIZE (result);
7552 l = aopGet (AOP (left), offset, FALSE, TRUE);
7553 if (*l == '@' && IS_AOP_PREG (result))
7556 emitcode ("mov", "a,%s", l);
7557 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7560 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7565 /* mov the highest order bit to OVR */
7566 tlbl = newiTempLabel (NULL);
7567 tlbl1 = newiTempLabel (NULL);
7569 size = AOP_SIZE (result);
7571 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7572 emitcode ("rlc", "a");
7573 emitcode ("mov", "ov,c");
7574 /* if it is only one byte then */
7577 l = aopGet (AOP (left), 0, FALSE, FALSE);
7579 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7580 emitcode ("", "%05d$:", tlbl->key + 100);
7581 emitcode ("mov", "c,ov");
7582 emitcode ("rrc", "a");
7583 emitcode ("", "%05d$:", tlbl1->key + 100);
7584 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7585 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7589 reAdjustPreg (AOP (result));
7590 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7591 emitcode ("", "%05d$:", tlbl->key + 100);
7592 emitcode ("mov", "c,ov");
7595 l = aopGet (AOP (result), offset, FALSE, FALSE);
7597 emitcode ("rrc", "a");
7598 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7600 reAdjustPreg (AOP (result));
7601 emitcode ("", "%05d$:", tlbl1->key + 100);
7602 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7605 freeAsmop (left, NULL, ic, TRUE);
7606 freeAsmop (result, NULL, ic, TRUE);
7609 /*-----------------------------------------------------------------*/
7610 /* genRightShift - generate code for right shifting */
7611 /*-----------------------------------------------------------------*/
7613 genRightShift (iCode * ic)
7615 operand *right, *left, *result;
7619 symbol *tlbl, *tlbl1;
7621 D(emitcode ("; genRightShift",""));
7623 /* if signed then we do it the hard way preserve the
7624 sign bit moving it inwards */
7625 letype = getSpec (operandType (IC_LEFT (ic)));
7627 if (!SPEC_USIGN (letype))
7629 genSignedRightShift (ic);
7633 /* signed & unsigned types are treated the same : i.e. the
7634 signed is NOT propagated inwards : quoting from the
7635 ANSI - standard : "for E1 >> E2, is equivalent to division
7636 by 2**E2 if unsigned or if it has a non-negative value,
7637 otherwise the result is implementation defined ", MY definition
7638 is that the sign does not get propagated */
7640 right = IC_RIGHT (ic);
7641 left = IC_LEFT (ic);
7642 result = IC_RESULT (ic);
7644 aopOp (right, ic, FALSE);
7646 /* if the shift count is known then do it
7647 as efficiently as possible */
7648 if (AOP_TYPE (right) == AOP_LIT)
7650 genRightShiftLiteral (left, right, result, ic, 0);
7654 /* shift count is unknown then we have to form
7655 a loop get the loop count in B : Note: we take
7656 only the lower order byte since shifting
7657 more that 32 bits make no sense anyway, ( the
7658 largest size of an object can be only 32 bits ) */
7660 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7661 emitcode ("inc", "b");
7662 freeAsmop (right, NULL, ic, TRUE);
7663 aopOp (left, ic, FALSE);
7664 aopOp (result, ic, FALSE);
7666 /* now move the left to the result if they are not the
7668 if (!sameRegs (AOP (left), AOP (result)) &&
7669 AOP_SIZE (result) > 1)
7672 size = AOP_SIZE (result);
7676 l = aopGet (AOP (left), offset, FALSE, TRUE);
7677 if (*l == '@' && IS_AOP_PREG (result))
7680 emitcode ("mov", "a,%s", l);
7681 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7684 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7689 tlbl = newiTempLabel (NULL);
7690 tlbl1 = newiTempLabel (NULL);
7691 size = AOP_SIZE (result);
7694 /* if it is only one byte then */
7697 l = aopGet (AOP (left), 0, FALSE, FALSE);
7699 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7700 emitcode ("", "%05d$:", tlbl->key + 100);
7702 emitcode ("rrc", "a");
7703 emitcode ("", "%05d$:", tlbl1->key + 100);
7704 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7705 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7709 reAdjustPreg (AOP (result));
7710 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7711 emitcode ("", "%05d$:", tlbl->key + 100);
7715 l = aopGet (AOP (result), offset, FALSE, FALSE);
7717 emitcode ("rrc", "a");
7718 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7720 reAdjustPreg (AOP (result));
7722 emitcode ("", "%05d$:", tlbl1->key + 100);
7723 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7726 freeAsmop (left, NULL, ic, TRUE);
7727 freeAsmop (result, NULL, ic, TRUE);
7730 /*-----------------------------------------------------------------*/
7731 /* emitPtrByteGet - emits code to get a byte into A through a */
7732 /* pointer register (R0, R1, or DPTR). The */
7733 /* original value of A can be preserved in B. */
7734 /*-----------------------------------------------------------------*/
7736 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7743 emitcode ("mov", "b,a");
7744 emitcode ("mov", "a,@%s", rname);
7749 emitcode ("mov", "b,a");
7750 emitcode ("movx", "a,@%s", rname);
7755 emitcode ("mov", "b,a");
7756 emitcode ("movx", "a,@dptr");
7761 emitcode ("mov", "b,a");
7762 emitcode ("clr", "a");
7763 emitcode ("movc", "a,@a+dptr");
7769 emitcode ("push", "b");
7770 emitcode ("push", "acc");
7772 emitcode ("lcall", "__gptrget");
7774 emitcode ("pop", "b");
7779 /*-----------------------------------------------------------------*/
7780 /* emitPtrByteSet - emits code to set a byte from src through a */
7781 /* pointer register (R0, R1, or DPTR). */
7782 /*-----------------------------------------------------------------*/
7784 emitPtrByteSet (char *rname, int p_type, char *src)
7793 emitcode ("mov", "@%s,a", rname);
7796 emitcode ("mov", "@%s,%s", rname, src);
7801 emitcode ("movx", "@%s,a", rname);
7806 emitcode ("movx", "@dptr,a");
7811 emitcode ("lcall", "__gptrput");
7816 /*-----------------------------------------------------------------*/
7817 /* genUnpackBits - generates code for unpacking bits */
7818 /*-----------------------------------------------------------------*/
7820 genUnpackBits (operand * result, char *rname, int ptype)
7822 int offset = 0; /* result byte offset */
7823 int rsize; /* result size */
7824 int rlen = 0; /* remaining bitfield length */
7825 sym_link *etype; /* bitfield type information */
7826 int blen; /* bitfield length */
7827 int bstr; /* bitfield starting bit within byte */
7829 D(emitcode ("; genUnpackBits",""));
7831 etype = getSpec (operandType (result));
7832 rsize = getSize (operandType (result));
7833 blen = SPEC_BLEN (etype);
7834 bstr = SPEC_BSTR (etype);
7836 /* If the bitfield length is less than a byte */
7839 emitPtrByteGet (rname, ptype, FALSE);
7841 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7842 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7846 /* Bit field did not fit in a byte. Copy all
7847 but the partial byte at the end. */
7848 for (rlen=blen;rlen>=8;rlen-=8)
7850 emitPtrByteGet (rname, ptype, FALSE);
7851 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7853 emitcode ("inc", "%s", rname);
7856 /* Handle the partial byte at the end */
7859 emitPtrByteGet (rname, ptype, FALSE);
7860 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7861 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7869 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7874 /*-----------------------------------------------------------------*/
7875 /* genDataPointerGet - generates code when ptr offset is known */
7876 /*-----------------------------------------------------------------*/
7878 genDataPointerGet (operand * left,
7884 int size, offset = 0;
7886 D(emitcode ("; genDataPointerGet",""));
7888 aopOp (result, ic, TRUE);
7890 /* get the string representation of the name */
7891 l = aopGet (AOP (left), 0, FALSE, TRUE);
7892 size = AOP_SIZE (result);
7896 sprintf (buffer, "(%s + %d)", l + 1, offset);
7898 sprintf (buffer, "%s", l + 1);
7899 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7902 freeAsmop (left, NULL, ic, TRUE);
7903 freeAsmop (result, NULL, ic, TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genNearPointerGet - emitcode for near pointer fetch */
7908 /*-----------------------------------------------------------------*/
7910 genNearPointerGet (operand * left,
7918 sym_link *rtype, *retype;
7919 sym_link *ltype = operandType (left);
7922 D(emitcode ("; genNearPointerGet",""));
7924 rtype = operandType (result);
7925 retype = getSpec (rtype);
7927 aopOp (left, ic, FALSE);
7929 /* if left is rematerialisable and
7930 result is not bitfield variable type and
7931 the left is pointer to data space i.e
7932 lower 128 bytes of space */
7933 if (AOP_TYPE (left) == AOP_IMMD &&
7934 !IS_BITFIELD (retype) &&
7935 DCL_TYPE (ltype) == POINTER)
7937 genDataPointerGet (left, result, ic);
7941 /* if the value is already in a pointer register
7942 then don't need anything more */
7943 if (!AOP_INPREG (AOP (left)))
7945 if (IS_AOP_PREG (left))
7947 // Aha, it is a pointer, just in disguise.
7948 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7951 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7952 __FILE__, __LINE__);
7957 emitcode ("mov", "a%s,%s", rname + 1, rname);
7958 rname++; // skip the '@'.
7963 /* otherwise get a free pointer register */
7965 preg = getFreePtr (ic, &aop, FALSE);
7966 emitcode ("mov", "%s,%s",
7968 aopGet (AOP (left), 0, FALSE, TRUE));
7973 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7975 //aopOp (result, ic, FALSE);
7976 aopOp (result, ic, result?TRUE:FALSE);
7978 /* if bitfield then unpack the bits */
7979 if (IS_BITFIELD (retype))
7980 genUnpackBits (result, rname, POINTER);
7983 /* we have can just get the values */
7984 int size = AOP_SIZE (result);
7989 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7992 emitcode ("mov", "a,@%s", rname);
7993 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7997 sprintf (buffer, "@%s", rname);
7998 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8002 emitcode ("inc", "%s", rname);
8006 /* now some housekeeping stuff */
8007 if (aop) /* we had to allocate for this iCode */
8009 if (pi) { /* post increment present */
8010 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8012 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8016 /* we did not allocate which means left
8017 already in a pointer register, then
8018 if size > 0 && this could be used again
8019 we have to point it back to where it
8021 if ((AOP_SIZE (result) > 1 &&
8022 !OP_SYMBOL (left)->remat &&
8023 (OP_SYMBOL (left)->liveTo > ic->seq ||
8027 int size = AOP_SIZE (result) - 1;
8029 emitcode ("dec", "%s", rname);
8034 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8035 freeAsmop (left, NULL, ic, TRUE);
8036 if (pi) pi->generated = 1;
8039 /*-----------------------------------------------------------------*/
8040 /* genPagedPointerGet - emitcode for paged pointer fetch */
8041 /*-----------------------------------------------------------------*/
8043 genPagedPointerGet (operand * left,
8051 sym_link *rtype, *retype;
8053 D(emitcode ("; genPagedPointerGet",""));
8055 rtype = operandType (result);
8056 retype = getSpec (rtype);
8058 aopOp (left, ic, FALSE);
8060 /* if the value is already in a pointer register
8061 then don't need anything more */
8062 if (!AOP_INPREG (AOP (left)))
8064 /* otherwise get a free pointer register */
8066 preg = getFreePtr (ic, &aop, FALSE);
8067 emitcode ("mov", "%s,%s",
8069 aopGet (AOP (left), 0, FALSE, TRUE));
8073 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8075 aopOp (result, ic, FALSE);
8077 /* if bitfield then unpack the bits */
8078 if (IS_BITFIELD (retype))
8079 genUnpackBits (result, rname, PPOINTER);
8082 /* we have can just get the values */
8083 int size = AOP_SIZE (result);
8089 emitcode ("movx", "a,@%s", rname);
8090 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8095 emitcode ("inc", "%s", rname);
8099 /* now some housekeeping stuff */
8100 if (aop) /* we had to allocate for this iCode */
8102 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8103 freeAsmop (NULL, aop, ic, TRUE);
8107 /* we did not allocate which means left
8108 already in a pointer register, then
8109 if size > 0 && this could be used again
8110 we have to point it back to where it
8112 if ((AOP_SIZE (result) > 1 &&
8113 !OP_SYMBOL (left)->remat &&
8114 (OP_SYMBOL (left)->liveTo > ic->seq ||
8118 int size = AOP_SIZE (result) - 1;
8120 emitcode ("dec", "%s", rname);
8125 freeAsmop (left, NULL, ic, TRUE);
8126 freeAsmop (result, NULL, ic, TRUE);
8127 if (pi) pi->generated = 1;
8131 /*--------------------------------------------------------------------*/
8132 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8133 /*--------------------------------------------------------------------*/
8135 loadDptrFromOperand (operand *op, bool loadBToo)
8137 if (AOP_TYPE (op) != AOP_STR)
8139 /* if this is remateriazable */
8140 if (AOP_TYPE (op) == AOP_IMMD)
8142 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8145 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8146 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8149 wassertl(FALSE, "need pointerCode");
8150 emitcode ("", "; mov b,???");
8151 /* genPointerGet and genPointerSet originally did different
8152 ** things for this case. Both seem wrong.
8153 ** from genPointerGet:
8154 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8155 ** from genPointerSet:
8156 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8161 else if (AOP_TYPE (op) == AOP_DPTR)
8165 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8166 emitcode ("push", "acc");
8167 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8168 emitcode ("push", "acc");
8169 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8170 emitcode ("pop", "dph");
8171 emitcode ("pop", "dpl");
8175 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8176 emitcode ("push", "acc");
8177 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8178 emitcode ("pop", "dpl");
8182 { /* we need to get it byte by byte */
8183 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8184 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8186 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8191 /*-----------------------------------------------------------------*/
8192 /* genFarPointerGet - gget value from far space */
8193 /*-----------------------------------------------------------------*/
8195 genFarPointerGet (operand * left,
8196 operand * result, iCode * ic, iCode * pi)
8199 sym_link *retype = getSpec (operandType (result));
8201 D(emitcode ("; genFarPointerGet",""));
8203 aopOp (left, ic, FALSE);
8204 loadDptrFromOperand (left, FALSE);
8206 /* so dptr now contains the address */
8207 aopOp (result, ic, FALSE);
8209 /* if bit then unpack */
8210 if (IS_BITFIELD (retype))
8211 genUnpackBits (result, "dptr", FPOINTER);
8214 size = AOP_SIZE (result);
8219 emitcode ("movx", "a,@dptr");
8220 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8222 emitcode ("inc", "dptr");
8226 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8227 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8228 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8231 freeAsmop (left, NULL, ic, TRUE);
8232 freeAsmop (result, NULL, ic, TRUE);
8235 /*-----------------------------------------------------------------*/
8236 /* genCodePointerGet - gget value from code space */
8237 /*-----------------------------------------------------------------*/
8239 genCodePointerGet (operand * left,
8240 operand * result, iCode * ic, iCode *pi)
8243 sym_link *retype = getSpec (operandType (result));
8245 D(emitcode ("; genCodePointerGet",""));
8247 aopOp (left, ic, FALSE);
8248 loadDptrFromOperand (left, FALSE);
8250 /* so dptr now contains the address */
8251 aopOp (result, ic, FALSE);
8253 /* if bit then unpack */
8254 if (IS_BITFIELD (retype))
8255 genUnpackBits (result, "dptr", CPOINTER);
8258 size = AOP_SIZE (result);
8265 emitcode ("clr", "a");
8266 emitcode ("movc", "a,@a+dptr");
8267 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8268 emitcode ("inc", "dptr");
8272 emitcode ("mov", "a,#0x%02x", offset);
8273 emitcode ("movc", "a,@a+dptr");
8274 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8279 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8280 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8281 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8284 freeAsmop (left, NULL, ic, TRUE);
8285 freeAsmop (result, NULL, ic, TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* genGenPointerGet - gget value from generic pointer space */
8290 /*-----------------------------------------------------------------*/
8292 genGenPointerGet (operand * left,
8293 operand * result, iCode * ic, iCode *pi)
8296 sym_link *retype = getSpec (operandType (result));
8298 D(emitcode ("; genGenPointerGet",""));
8300 aopOp (left, ic, FALSE);
8301 loadDptrFromOperand (left, TRUE);
8303 /* so dptr know contains the address */
8304 aopOp (result, ic, FALSE);
8306 /* if bit then unpack */
8307 if (IS_BITFIELD (retype))
8308 genUnpackBits (result, "dptr", GPOINTER);
8311 size = AOP_SIZE (result);
8316 emitcode ("lcall", "__gptrget");
8317 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8319 emitcode ("inc", "dptr");
8323 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8324 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8325 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8328 freeAsmop (left, NULL, ic, TRUE);
8329 freeAsmop (result, NULL, ic, TRUE);
8332 /*-----------------------------------------------------------------*/
8333 /* genPointerGet - generate code for pointer get */
8334 /*-----------------------------------------------------------------*/
8336 genPointerGet (iCode * ic, iCode *pi)
8338 operand *left, *result;
8339 sym_link *type, *etype;
8342 D(emitcode ("; genPointerGet",""));
8344 left = IC_LEFT (ic);
8345 result = IC_RESULT (ic);
8347 /* depending on the type of pointer we need to
8348 move it to the correct pointer register */
8349 type = operandType (left);
8350 etype = getSpec (type);
8351 /* if left is of type of pointer then it is simple */
8352 if (IS_PTR (type) && !IS_FUNC (type->next))
8353 p_type = DCL_TYPE (type);
8356 /* we have to go by the storage class */
8357 p_type = PTR_TYPE (SPEC_OCLS (etype));
8360 /* special case when cast remat */
8361 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8362 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8363 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8364 type = operandType (left);
8365 p_type = DCL_TYPE (type);
8367 /* now that we have the pointer type we assign
8368 the pointer values */
8374 genNearPointerGet (left, result, ic, pi);
8378 genPagedPointerGet (left, result, ic, pi);
8382 genFarPointerGet (left, result, ic, pi);
8386 genCodePointerGet (left, result, ic, pi);
8390 genGenPointerGet (left, result, ic, pi);
8398 /*-----------------------------------------------------------------*/
8399 /* genPackBits - generates code for packed bit storage */
8400 /*-----------------------------------------------------------------*/
8402 genPackBits (sym_link * etype,
8404 char *rname, int p_type)
8406 int offset = 0; /* source byte offset */
8407 int rlen = 0; /* remaining bitfield length */
8408 int blen; /* bitfield length */
8409 int bstr; /* bitfield starting bit within byte */
8410 int litval; /* source literal value (if AOP_LIT) */
8411 unsigned char mask; /* bitmask within current byte */
8413 D(emitcode ("; genPackBits",""));
8415 blen = SPEC_BLEN (etype);
8416 bstr = SPEC_BSTR (etype);
8418 /* If the bitfield length is less than a byte */
8421 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8422 (unsigned char) (0xFF >> (8 - bstr)));
8424 if (AOP_TYPE (right) == AOP_LIT)
8426 /* Case with a bitfield length <8 and literal source
8428 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8430 litval &= (~mask) & 0xff;
8431 emitPtrByteGet (rname, p_type, FALSE);
8432 if ((mask|litval)!=0xff)
8433 emitcode ("anl","a,#0x%02x", mask);
8435 emitcode ("orl","a,#0x%02x", litval);
8439 if ((blen==1) && (p_type!=GPOINTER))
8441 /* Case with a bitfield length == 1 and no generic pointer
8443 if (AOP_TYPE (right) == AOP_CRY)
8444 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8447 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8448 emitcode ("rrc","a");
8450 emitPtrByteGet (rname, p_type, FALSE);
8451 emitcode ("mov","acc.%d,c",bstr);
8455 /* Case with a bitfield length < 8 and arbitrary source
8457 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8458 /* shift and mask source value */
8460 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8462 /* transfer A to B and get next byte */
8463 emitPtrByteGet (rname, p_type, TRUE);
8465 emitcode ("anl", "a,#0x%02x", mask);
8466 emitcode ("orl", "a,b");
8467 if (p_type == GPOINTER)
8468 emitcode ("pop", "b");
8472 emitPtrByteSet (rname, p_type, "a");
8476 /* Bit length is greater than 7 bits. In this case, copy */
8477 /* all except the partial byte at the end */
8478 for (rlen=blen;rlen>=8;rlen-=8)
8480 emitPtrByteSet (rname, p_type,
8481 aopGet (AOP (right), offset++, FALSE, TRUE) );
8483 emitcode ("inc", "%s", rname);
8486 /* If there was a partial byte at the end */
8489 mask = (((unsigned char) -1 << rlen) & 0xff);
8491 if (AOP_TYPE (right) == AOP_LIT)
8493 /* Case with partial byte and literal source
8495 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8496 litval >>= (blen-rlen);
8497 litval &= (~mask) & 0xff;
8498 emitPtrByteGet (rname, p_type, FALSE);
8499 if ((mask|litval)!=0xff)
8500 emitcode ("anl","a,#0x%02x", mask);
8502 emitcode ("orl","a,#0x%02x", litval);
8506 /* Case with partial byte and arbitrary source
8508 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8509 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8511 /* transfer A to B and get next byte */
8512 emitPtrByteGet (rname, p_type, TRUE);
8514 emitcode ("anl", "a,#0x%02x", mask);
8515 emitcode ("orl", "a,b");
8516 if (p_type == GPOINTER)
8517 emitcode ("pop", "b");
8519 emitPtrByteSet (rname, p_type, "a");
8525 /*-----------------------------------------------------------------*/
8526 /* genDataPointerSet - remat pointer to data space */
8527 /*-----------------------------------------------------------------*/
8529 genDataPointerSet (operand * right,
8533 int size, offset = 0;
8534 char *l, buffer[256];
8536 D(emitcode ("; genDataPointerSet",""));
8538 aopOp (right, ic, FALSE);
8540 l = aopGet (AOP (result), 0, FALSE, TRUE);
8541 size = AOP_SIZE (right);
8545 sprintf (buffer, "(%s + %d)", l + 1, offset);
8547 sprintf (buffer, "%s", l + 1);
8548 emitcode ("mov", "%s,%s", buffer,
8549 aopGet (AOP (right), offset++, FALSE, FALSE));
8552 freeAsmop (right, NULL, ic, TRUE);
8553 freeAsmop (result, NULL, ic, TRUE);
8556 /*-----------------------------------------------------------------*/
8557 /* genNearPointerSet - emitcode for near pointer put */
8558 /*-----------------------------------------------------------------*/
8560 genNearPointerSet (operand * right,
8568 sym_link *retype, *letype;
8569 sym_link *ptype = operandType (result);
8571 D(emitcode ("; genNearPointerSet",""));
8573 retype = getSpec (operandType (right));
8574 letype = getSpec (ptype);
8575 aopOp (result, ic, FALSE);
8577 /* if the result is rematerializable &
8578 in data space & not a bit variable */
8579 if (AOP_TYPE (result) == AOP_IMMD &&
8580 DCL_TYPE (ptype) == POINTER &&
8581 !IS_BITVAR (retype) &&
8582 !IS_BITVAR (letype))
8584 genDataPointerSet (right, result, ic);
8588 /* if the value is already in a pointer register
8589 then don't need anything more */
8590 if (!AOP_INPREG (AOP (result)))
8593 //AOP_TYPE (result) == AOP_STK
8597 // Aha, it is a pointer, just in disguise.
8598 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8601 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8602 __FILE__, __LINE__);
8607 emitcode ("mov", "a%s,%s", rname + 1, rname);
8608 rname++; // skip the '@'.
8613 /* otherwise get a free pointer register */
8615 preg = getFreePtr (ic, &aop, FALSE);
8616 emitcode ("mov", "%s,%s",
8618 aopGet (AOP (result), 0, FALSE, TRUE));
8624 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8627 aopOp (right, ic, FALSE);
8629 /* if bitfield then unpack the bits */
8630 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8631 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8634 /* we have can just get the values */
8635 int size = AOP_SIZE (right);
8640 l = aopGet (AOP (right), offset, FALSE, TRUE);
8644 emitcode ("mov", "@%s,a", rname);
8647 emitcode ("mov", "@%s,%s", rname, l);
8649 emitcode ("inc", "%s", rname);
8654 /* now some housekeeping stuff */
8655 if (aop) /* we had to allocate for this iCode */
8658 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8659 freeAsmop (NULL, aop, ic, TRUE);
8663 /* we did not allocate which means left
8664 already in a pointer register, then
8665 if size > 0 && this could be used again
8666 we have to point it back to where it
8668 if ((AOP_SIZE (right) > 1 &&
8669 !OP_SYMBOL (result)->remat &&
8670 (OP_SYMBOL (result)->liveTo > ic->seq ||
8674 int size = AOP_SIZE (right) - 1;
8676 emitcode ("dec", "%s", rname);
8681 if (pi) pi->generated = 1;
8682 freeAsmop (result, NULL, ic, TRUE);
8683 freeAsmop (right, NULL, ic, TRUE);
8686 /*-----------------------------------------------------------------*/
8687 /* genPagedPointerSet - emitcode for Paged pointer put */
8688 /*-----------------------------------------------------------------*/
8690 genPagedPointerSet (operand * right,
8698 sym_link *retype, *letype;
8700 D(emitcode ("; genPagedPointerSet",""));
8702 retype = getSpec (operandType (right));
8703 letype = getSpec (operandType (result));
8705 aopOp (result, ic, FALSE);
8707 /* if the value is already in a pointer register
8708 then don't need anything more */
8709 if (!AOP_INPREG (AOP (result)))
8711 /* otherwise get a free pointer register */
8713 preg = getFreePtr (ic, &aop, FALSE);
8714 emitcode ("mov", "%s,%s",
8716 aopGet (AOP (result), 0, FALSE, TRUE));
8720 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8722 aopOp (right, ic, FALSE);
8724 /* if bitfield then unpack the bits */
8725 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8726 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8729 /* we have can just get the values */
8730 int size = AOP_SIZE (right);
8735 l = aopGet (AOP (right), offset, FALSE, TRUE);
8738 emitcode ("movx", "@%s,a", rname);
8741 emitcode ("inc", "%s", rname);
8747 /* now some housekeeping stuff */
8748 if (aop) /* we had to allocate for this iCode */
8751 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8752 freeAsmop (NULL, aop, ic, TRUE);
8756 /* we did not allocate which means left
8757 already in a pointer register, then
8758 if size > 0 && this could be used again
8759 we have to point it back to where it
8761 if (AOP_SIZE (right) > 1 &&
8762 !OP_SYMBOL (result)->remat &&
8763 (OP_SYMBOL (result)->liveTo > ic->seq ||
8766 int size = AOP_SIZE (right) - 1;
8768 emitcode ("dec", "%s", rname);
8773 if (pi) pi->generated = 1;
8774 freeAsmop (result, NULL, ic, TRUE);
8775 freeAsmop (right, NULL, ic, TRUE);
8780 /*-----------------------------------------------------------------*/
8781 /* genFarPointerSet - set value from far space */
8782 /*-----------------------------------------------------------------*/
8784 genFarPointerSet (operand * right,
8785 operand * result, iCode * ic, iCode * pi)
8788 sym_link *retype = getSpec (operandType (right));
8789 sym_link *letype = getSpec (operandType (result));
8791 D(emitcode ("; genFarPointerSet",""));
8793 aopOp (result, ic, FALSE);
8794 loadDptrFromOperand (result, FALSE);
8796 /* so dptr know contains the address */
8797 aopOp (right, ic, FALSE);
8799 /* if bit then unpack */
8800 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8801 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
8804 size = AOP_SIZE (right);
8809 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8811 emitcode ("movx", "@dptr,a");
8813 emitcode ("inc", "dptr");
8816 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8817 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8818 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8821 freeAsmop (result, NULL, ic, TRUE);
8822 freeAsmop (right, NULL, ic, TRUE);
8825 /*-----------------------------------------------------------------*/
8826 /* genGenPointerSet - set value from generic pointer space */
8827 /*-----------------------------------------------------------------*/
8829 genGenPointerSet (operand * right,
8830 operand * result, iCode * ic, iCode * pi)
8833 sym_link *retype = getSpec (operandType (right));
8834 sym_link *letype = getSpec (operandType (result));
8836 D(emitcode ("; genGenPointerSet",""));
8838 aopOp (result, ic, FALSE);
8839 loadDptrFromOperand (result, TRUE);
8841 /* so dptr know contains the address */
8842 aopOp (right, ic, FALSE);
8844 /* if bit then unpack */
8845 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8846 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
8849 size = AOP_SIZE (right);
8854 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8856 emitcode ("lcall", "__gptrput");
8858 emitcode ("inc", "dptr");
8862 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8863 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8864 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8867 freeAsmop (result, NULL, ic, TRUE);
8868 freeAsmop (right, NULL, ic, TRUE);
8871 /*-----------------------------------------------------------------*/
8872 /* genPointerSet - stores the value into a pointer location */
8873 /*-----------------------------------------------------------------*/
8875 genPointerSet (iCode * ic, iCode *pi)
8877 operand *right, *result;
8878 sym_link *type, *etype;
8881 D(emitcode ("; genPointerSet",""));
8883 right = IC_RIGHT (ic);
8884 result = IC_RESULT (ic);
8886 /* depending on the type of pointer we need to
8887 move it to the correct pointer register */
8888 type = operandType (result);
8889 etype = getSpec (type);
8890 /* if left is of type of pointer then it is simple */
8891 if (IS_PTR (type) && !IS_FUNC (type->next))
8893 p_type = DCL_TYPE (type);
8897 /* we have to go by the storage class */
8898 p_type = PTR_TYPE (SPEC_OCLS (etype));
8901 /* special case when cast remat */
8902 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8903 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8904 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8905 type = operandType (result);
8906 p_type = DCL_TYPE (type);
8908 /* now that we have the pointer type we assign
8909 the pointer values */
8915 genNearPointerSet (right, result, ic, pi);
8919 genPagedPointerSet (right, result, ic, pi);
8923 genFarPointerSet (right, result, ic, pi);
8927 genGenPointerSet (right, result, ic, pi);
8931 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8932 "genPointerSet: illegal pointer type");
8937 /*-----------------------------------------------------------------*/
8938 /* genIfx - generate code for Ifx statement */
8939 /*-----------------------------------------------------------------*/
8941 genIfx (iCode * ic, iCode * popIc)
8943 operand *cond = IC_COND (ic);
8946 D(emitcode ("; genIfx",""));
8948 aopOp (cond, ic, FALSE);
8950 /* get the value into acc */
8951 if (AOP_TYPE (cond) != AOP_CRY)
8955 /* the result is now in the accumulator */
8956 freeAsmop (cond, NULL, ic, TRUE);
8958 /* if there was something to be popped then do it */
8962 /* if the condition is a bit variable */
8963 if (isbit && IS_ITEMP (cond) &&
8965 genIfxJump (ic, SPIL_LOC (cond)->rname);
8966 else if (isbit && !IS_ITEMP (cond))
8967 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8969 genIfxJump (ic, "a");
8974 /*-----------------------------------------------------------------*/
8975 /* genAddrOf - generates code for address of */
8976 /*-----------------------------------------------------------------*/
8978 genAddrOf (iCode * ic)
8980 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8983 D(emitcode ("; genAddrOf",""));
8985 aopOp (IC_RESULT (ic), ic, FALSE);
8987 /* if the operand is on the stack then we
8988 need to get the stack offset of this
8992 /* if it has an offset then we need to compute
8996 emitcode ("mov", "a,_bp");
8997 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8998 ((char) (sym->stack - _G.nRegsSaved)) :
8999 ((char) sym->stack)) & 0xff);
9000 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9004 /* we can just move _bp */
9005 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9007 /* fill the result with zero */
9008 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9013 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9019 /* object not on stack then we need the name */
9020 size = AOP_SIZE (IC_RESULT (ic));
9025 char s[SDCC_NAME_MAX];
9027 sprintf (s, "#(%s >> %d)",
9031 sprintf (s, "#%s", sym->rname);
9032 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9040 /*-----------------------------------------------------------------*/
9041 /* genFarFarAssign - assignment when both are in far space */
9042 /*-----------------------------------------------------------------*/
9044 genFarFarAssign (operand * result, operand * right, iCode * ic)
9046 int size = AOP_SIZE (right);
9050 D(emitcode ("; genFarFarAssign",""));
9052 /* first push the right side on to the stack */
9055 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9057 emitcode ("push", "acc");
9060 freeAsmop (right, NULL, ic, FALSE);
9061 /* now assign DPTR to result */
9062 aopOp (result, ic, FALSE);
9063 size = AOP_SIZE (result);
9066 emitcode ("pop", "acc");
9067 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9069 freeAsmop (result, NULL, ic, FALSE);
9073 /*-----------------------------------------------------------------*/
9074 /* genAssign - generate code for assignment */
9075 /*-----------------------------------------------------------------*/
9077 genAssign (iCode * ic)
9079 operand *result, *right;
9081 unsigned long lit = 0L;
9083 D(emitcode("; genAssign",""));
9085 result = IC_RESULT (ic);
9086 right = IC_RIGHT (ic);
9088 /* if they are the same */
9089 if (operandsEqu (result, right) &&
9090 !isOperandVolatile (result, FALSE) &&
9091 !isOperandVolatile (right, FALSE))
9094 aopOp (right, ic, FALSE);
9096 /* special case both in far space */
9097 if (AOP_TYPE (right) == AOP_DPTR &&
9098 IS_TRUE_SYMOP (result) &&
9099 isOperandInFarSpace (result))
9102 genFarFarAssign (result, right, ic);
9106 aopOp (result, ic, TRUE);
9108 /* if they are the same registers */
9109 if (sameRegs (AOP (right), AOP (result)) &&
9110 !isOperandVolatile (result, FALSE) &&
9111 !isOperandVolatile (right, FALSE))
9114 /* if the result is a bit */
9115 if (AOP_TYPE (result) == AOP_CRY)
9118 /* if the right size is a literal then
9119 we know what the value is */
9120 if (AOP_TYPE (right) == AOP_LIT)
9122 if (((int) operandLitValue (right)))
9123 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9125 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9129 /* the right is also a bit variable */
9130 if (AOP_TYPE (right) == AOP_CRY)
9132 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9133 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9139 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9143 /* bit variables done */
9145 size = AOP_SIZE (result);
9147 if (AOP_TYPE (right) == AOP_LIT)
9148 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9150 (AOP_TYPE (result) != AOP_REG) &&
9151 (AOP_TYPE (right) == AOP_LIT) &&
9152 !IS_FLOAT (operandType (right)) &&
9155 emitcode ("clr", "a");
9158 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9159 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9161 aopPut (AOP (result),
9162 aopGet (AOP (right), size, FALSE, FALSE),
9164 isOperandVolatile (result, FALSE));
9171 aopPut (AOP (result),
9172 aopGet (AOP (right), offset, FALSE, FALSE),
9174 isOperandVolatile (result, FALSE));
9180 freeAsmop (right, NULL, ic, TRUE);
9181 freeAsmop (result, NULL, ic, TRUE);
9184 /*-----------------------------------------------------------------*/
9185 /* genJumpTab - genrates code for jump table */
9186 /*-----------------------------------------------------------------*/
9188 genJumpTab (iCode * ic)
9193 D(emitcode ("; genJumpTab",""));
9195 aopOp (IC_JTCOND (ic), ic, FALSE);
9196 /* get the condition into accumulator */
9197 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9199 /* multiply by three */
9200 emitcode ("add", "a,acc");
9201 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9202 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9204 jtab = newiTempLabel (NULL);
9205 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9206 emitcode ("jmp", "@a+dptr");
9207 emitcode ("", "%05d$:", jtab->key + 100);
9208 /* now generate the jump labels */
9209 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9210 jtab = setNextItem (IC_JTLABELS (ic)))
9211 emitcode ("ljmp", "%05d$", jtab->key + 100);
9215 /*-----------------------------------------------------------------*/
9216 /* genCast - gen code for casting */
9217 /*-----------------------------------------------------------------*/
9219 genCast (iCode * ic)
9221 operand *result = IC_RESULT (ic);
9222 sym_link *ctype = operandType (IC_LEFT (ic));
9223 sym_link *rtype = operandType (IC_RIGHT (ic));
9224 operand *right = IC_RIGHT (ic);
9227 D(emitcode("; genCast",""));
9229 /* if they are equivalent then do nothing */
9230 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9233 aopOp (right, ic, FALSE);
9234 aopOp (result, ic, FALSE);
9236 /* if the result is a bit (and not a bitfield) */
9237 // if (AOP_TYPE (result) == AOP_CRY)
9238 if (IS_BITVAR (OP_SYMBOL (result)->type)
9239 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9241 /* if the right size is a literal then
9242 we know what the value is */
9243 if (AOP_TYPE (right) == AOP_LIT)
9245 if (((int) operandLitValue (right)))
9246 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9248 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9253 /* the right is also a bit variable */
9254 if (AOP_TYPE (right) == AOP_CRY)
9256 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9257 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9263 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9268 /* if they are the same size : or less */
9269 if (AOP_SIZE (result) <= AOP_SIZE (right))
9272 /* if they are in the same place */
9273 if (sameRegs (AOP (right), AOP (result)))
9276 /* if they in different places then copy */
9277 size = AOP_SIZE (result);
9281 aopPut (AOP (result),
9282 aopGet (AOP (right), offset, FALSE, FALSE),
9284 isOperandVolatile (result, FALSE));
9291 /* if the result is of type pointer */
9296 sym_link *type = operandType (right);
9297 sym_link *etype = getSpec (type);
9299 /* pointer to generic pointer */
9300 if (IS_GENPTR (ctype))
9303 p_type = DCL_TYPE (type);
9306 if (SPEC_SCLS(etype)==S_REGISTER) {
9307 // let's assume it is a generic pointer
9310 /* we have to go by the storage class */
9311 p_type = PTR_TYPE (SPEC_OCLS (etype));
9315 /* the first two bytes are known */
9316 size = GPTRSIZE - 1;
9320 aopPut (AOP (result),
9321 aopGet (AOP (right), offset, FALSE, FALSE),
9323 isOperandVolatile (result, FALSE));
9326 /* the last byte depending on type */
9328 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9333 // pointerTypeToGPByte will have bitched.
9337 sprintf(gpValStr, "#0x%d", gpVal);
9338 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9343 /* just copy the pointers */
9344 size = AOP_SIZE (result);
9348 aopPut (AOP (result),
9349 aopGet (AOP (right), offset, FALSE, FALSE),
9351 isOperandVolatile (result, FALSE));
9357 /* so we now know that the size of destination is greater
9358 than the size of the source */
9359 /* we move to result for the size of source */
9360 size = AOP_SIZE (right);
9364 aopPut (AOP (result),
9365 aopGet (AOP (right), offset, FALSE, FALSE),
9367 isOperandVolatile (result, FALSE));
9371 /* now depending on the sign of the source && destination */
9372 size = AOP_SIZE (result) - AOP_SIZE (right);
9373 /* if unsigned or not an integral type */
9374 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9377 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9381 /* we need to extend the sign :{ */
9382 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9385 emitcode ("rlc", "a");
9386 emitcode ("subb", "a,acc");
9388 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9391 /* we are done hurray !!!! */
9394 freeAsmop (right, NULL, ic, TRUE);
9395 freeAsmop (result, NULL, ic, TRUE);
9399 /*-----------------------------------------------------------------*/
9400 /* genDjnz - generate decrement & jump if not zero instrucion */
9401 /*-----------------------------------------------------------------*/
9403 genDjnz (iCode * ic, iCode * ifx)
9409 D(emitcode ("; genDjnz",""));
9411 /* if the if condition has a false label
9412 then we cannot save */
9416 /* if the minus is not of the form
9418 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9419 !IS_OP_LITERAL (IC_RIGHT (ic)))
9422 if (operandLitValue (IC_RIGHT (ic)) != 1)
9425 /* if the size of this greater than one then no
9427 if (getSize (operandType (IC_RESULT (ic))) > 1)
9430 /* otherwise we can save BIG */
9431 lbl = newiTempLabel (NULL);
9432 lbl1 = newiTempLabel (NULL);
9434 aopOp (IC_RESULT (ic), ic, FALSE);
9436 if (AOP_NEEDSACC(IC_RESULT(ic)))
9438 /* If the result is accessed indirectly via
9439 * the accumulator, we must explicitly write
9440 * it back after the decrement.
9442 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9444 if (strcmp(rByte, "a"))
9446 /* Something is hopelessly wrong */
9447 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9448 __FILE__, __LINE__);
9449 /* We can just give up; the generated code will be inefficient,
9452 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9455 emitcode ("dec", "%s", rByte);
9456 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9457 emitcode ("jnz", "%05d$", lbl->key + 100);
9459 else if (IS_AOP_PREG (IC_RESULT (ic)))
9461 emitcode ("dec", "%s",
9462 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9463 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9464 emitcode ("jnz", "%05d$", lbl->key + 100);
9468 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9471 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9472 emitcode ("", "%05d$:", lbl->key + 100);
9473 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9474 emitcode ("", "%05d$:", lbl1->key + 100);
9476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9481 /*-----------------------------------------------------------------*/
9482 /* genReceive - generate code for a receive iCode */
9483 /*-----------------------------------------------------------------*/
9485 genReceive (iCode * ic)
9487 int size = getSize (operandType (IC_RESULT (ic)));
9489 D(emitcode ("; genReceive",""));
9491 if (ic->argreg == 1) { /* first parameter */
9492 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9493 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9494 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9500 for (offset = 0; offset<size; offset++)
9501 if (!strcmp (fReturn[offset], "a"))
9506 if (size==1 || getTempRegs(tempRegs, size-1, ic))
9508 for (offset = size-1; offset>0; offset--)
9509 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9510 emitcode("mov","a,%s", fReturn[0]);
9512 aopOp (IC_RESULT (ic), ic, FALSE);
9514 aopPut (AOP (IC_RESULT (ic)), "a", offset,
9515 isOperandVolatile (IC_RESULT (ic), FALSE));
9516 for (offset = 1; offset<size; offset++)
9517 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9518 isOperandVolatile (IC_RESULT (ic), FALSE));
9524 if (getTempRegs(tempRegs, size, ic))
9526 for (offset = 0; offset<size; offset++)
9527 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9528 aopOp (IC_RESULT (ic), ic, FALSE);
9529 for (offset = 0; offset<size; offset++)
9530 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9531 isOperandVolatile (IC_RESULT (ic), FALSE));
9536 offset = fReturnSizeMCS51 - size;
9538 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9539 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9542 aopOp (IC_RESULT (ic), ic, FALSE);
9543 size = AOP_SIZE (IC_RESULT (ic));
9546 emitcode ("pop", "acc");
9547 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9552 aopOp (IC_RESULT (ic), ic, FALSE);
9554 assignResultValue (IC_RESULT (ic));
9556 } else { /* second receive onwards */
9558 aopOp (IC_RESULT (ic), ic, FALSE);
9559 rb1off = ic->argreg;
9561 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9566 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9569 /*-----------------------------------------------------------------*/
9570 /* genDummyRead - generate code for dummy read of volatiles */
9571 /*-----------------------------------------------------------------*/
9573 genDummyRead (iCode * ic)
9578 D(emitcode("; genDummyRead",""));
9581 if (op && IS_SYMOP (op))
9583 aopOp (op, ic, FALSE);
9585 /* if the result is a bit */
9586 if (AOP_TYPE (op) == AOP_CRY)
9587 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9590 /* bit variables done */
9592 size = AOP_SIZE (op);
9596 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9601 freeAsmop (op, NULL, ic, TRUE);
9605 if (op && IS_SYMOP (op))
9607 aopOp (op, ic, FALSE);
9609 /* if the result is a bit */
9610 if (AOP_TYPE (op) == AOP_CRY)
9611 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9614 /* bit variables done */
9616 size = AOP_SIZE (op);
9620 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9625 freeAsmop (op, NULL, ic, TRUE);
9629 /*-----------------------------------------------------------------*/
9630 /* genCritical - generate code for start of a critical sequence */
9631 /*-----------------------------------------------------------------*/
9633 genCritical (iCode *ic)
9635 symbol *tlbl = newiTempLabel (NULL);
9637 D(emitcode("; genCritical",""));
9640 aopOp (IC_RESULT (ic), ic, TRUE);
9642 emitcode ("setb", "c");
9643 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9644 emitcode ("clr", "c");
9645 emitcode ("", "%05d$:", (tlbl->key + 100));
9648 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9650 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9653 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9656 /*-----------------------------------------------------------------*/
9657 /* genEndCritical - generate code for end of a critical sequence */
9658 /*-----------------------------------------------------------------*/
9660 genEndCritical (iCode *ic)
9662 D(emitcode("; genEndCritical",""));
9666 aopOp (IC_RIGHT (ic), ic, FALSE);
9667 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9669 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9670 emitcode ("mov", "ea,c");
9674 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9675 emitcode ("rrc", "a");
9676 emitcode ("mov", "ea,c");
9678 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9682 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9683 emitcode ("mov", "ea,c");
9688 /*-----------------------------------------------------------------*/
9689 /* gen51Code - generate code for 8051 based controllers */
9690 /*-----------------------------------------------------------------*/
9692 gen51Code (iCode * lic)
9698 _G.currentFunc = NULL;
9699 lineHead = lineCurr = NULL;
9701 /* print the allocation information */
9702 if (allocInfo && currFunc)
9703 printAllocInfo (currFunc, codeOutFile);
9704 /* if debug information required */
9705 if (options.debug && currFunc)
9707 debugFile->writeFunction(currFunc);
9709 if (IS_STATIC (currFunc->etype))
9710 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9712 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9715 /* stack pointer name */
9716 if (options.useXstack)
9722 for (ic = lic; ic; ic = ic->next)
9724 _G.current_iCode = ic;
9726 if (ic->lineno && cln != ic->lineno)
9731 emitcode ("", "C$%s$%d$%d$%d ==.",
9732 FileBaseName (ic->filename), ic->lineno,
9733 ic->level, ic->block);
9736 if (!options.noCcodeInAsm) {
9737 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9738 printCLine(ic->filename, ic->lineno));
9743 if (ic->seqPoint && ic->seqPoint != cseq)
9745 emitcode ("", "; sequence point %d", ic->seqPoint);
9746 cseq = ic->seqPoint;
9749 if (options.iCodeInAsm) {
9753 for (i=0; i<8; i++) {
9754 sprintf (®sInUse[i],
9755 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9758 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9760 /* if the result is marked as
9761 spilt and rematerializable or code for
9762 this has already been generated then
9764 if (resultRemat (ic) || ic->generated)
9767 /* depending on the operation */
9787 /* IPOP happens only when trying to restore a
9788 spilt live range, if there is an ifx statement
9789 following this pop then the if statement might
9790 be using some of the registers being popped which
9791 would destory the contents of the register so
9792 we need to check for this condition and handle it */
9794 ic->next->op == IFX &&
9795 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9796 genIfx (ic->next, ic);
9814 genEndFunction (ic);
9834 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9851 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9855 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9862 /* note these two are xlated by algebraic equivalence
9863 during parsing SDCC.y */
9864 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9865 "got '>=' or '<=' shouldn't have come here");
9869 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9881 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9885 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9889 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9916 case GET_VALUE_AT_ADDRESS:
9917 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9921 if (POINTER_SET (ic))
9922 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9948 addSet (&_G.sendSet, ic);
9951 case DUMMY_READ_VOLATILE:
9960 genEndCritical (ic);
9972 _G.current_iCode = NULL;
9974 /* now we are ready to call the
9975 peep hole optimizer */
9976 if (!options.nopeep)
9977 peepHole (&lineHead);
9979 /* now do the actual printing */
9980 printLine (lineHead, codeOutFile);