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 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 char *aopLiteral (value * val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
69 {"dpl", "dph", "b", "a"};
71 {"dpl", "dph", "dpx", "b", "a"};
72 unsigned fReturnSize = 4; /* shared with ralloc.c */
73 char **fReturn = fReturn8051;
74 static char *accUse[] =
77 static short rbank = -1;
91 extern int mcs51_ptrRegReq;
92 extern int mcs51_nRegs;
93 extern FILE *codeOutFile;
94 static void saverbank (int, iCode *, bool);
95 #define RESULTONSTACK(x) \
96 (IC_RESULT(x) && IC_RESULT(x)->aop && \
97 IC_RESULT(x)->aop->type == AOP_STK )
99 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 static lineNode *lineHead = NULL;
104 static lineNode *lineCurr = NULL;
106 static unsigned char SLMask[] =
107 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] =
110 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
118 /*-----------------------------------------------------------------*/
119 /* emitcode - writes the code into a file : for now it is simple */
120 /*-----------------------------------------------------------------*/
122 emitcode (char *inst, char *fmt,...)
125 char lb[MAX_INLINEASM];
133 sprintf (lb, "%s\t", inst);
135 sprintf (lb, "%s", inst);
136 vsprintf (lb + (strlen (lb)), fmt, ap);
139 vsprintf (lb, fmt, ap);
141 while (isspace (*lbp))
145 lineCurr = (lineCurr ?
146 connectLine (lineCurr, newLineNode (lb)) :
147 (lineHead = newLineNode (lb)));
148 lineCurr->isInline = _G.inLine;
149 lineCurr->isDebug = _G.debugLine;
153 /*-----------------------------------------------------------------*/
154 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
155 /*-----------------------------------------------------------------*/
157 getFreePtr (iCode * ic, asmop ** aopp, bool result)
159 bool r0iu = FALSE, r1iu = FALSE;
160 bool r0ou = FALSE, r1ou = FALSE;
162 /* the logic: if r0 & r1 used in the instruction
163 then we are in trouble otherwise */
165 /* first check if r0 & r1 are used by this
166 instruction, in which case we are in trouble */
167 if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
168 (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
173 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
174 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
176 /* if no usage of r0 then return it */
179 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
180 (*aopp)->type = AOP_R0;
182 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
185 /* if no usage of r1 then return it */
188 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
189 (*aopp)->type = AOP_R1;
191 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
194 /* now we know they both have usage */
195 /* if r0 not used in this instruction */
198 /* push it if not already pushed */
201 emitcode ("push", "%s",
202 mcs51_regWithIdx (R0_IDX)->dname);
206 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
207 (*aopp)->type = AOP_R0;
209 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
212 /* if r1 not used then */
216 /* push it if not already pushed */
219 emitcode ("push", "%s",
220 mcs51_regWithIdx (R1_IDX)->dname);
224 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
225 (*aopp)->type = AOP_R1;
226 return mcs51_regWithIdx (R1_IDX);
230 /* I said end of world but not quite end of world yet */
231 /* if this is a result then we can push it on the stack */
234 (*aopp)->type = AOP_STK;
239 /* other wise this is true end of the world */
240 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
241 "getFreePtr should never reach here");
245 /*-----------------------------------------------------------------*/
246 /* newAsmop - creates a new asmOp */
247 /*-----------------------------------------------------------------*/
249 newAsmop (short type)
253 aop = Safe_calloc (1, sizeof (asmop));
263 emitcode (";", "Select standard DPTR");
264 emitcode ("mov", "dps, #0x00");
268 emitcode (";", "Select alternate DPTR");
269 emitcode ("mov", "dps, #0x01");
273 /*-----------------------------------------------------------------*/
274 /* pointerCode - returns the code for a pointer type */
275 /*-----------------------------------------------------------------*/
277 pointerCode (sym_link * etype)
280 return PTR_TYPE (SPEC_OCLS (etype));
284 /*-----------------------------------------------------------------*/
285 /* aopForSym - for a true symbol */
286 /*-----------------------------------------------------------------*/
288 aopForSym (iCode * ic, symbol * sym, bool result)
291 memmap *space = SPEC_OCLS (sym->etype);
293 /* if already has one */
297 /* assign depending on the storage class */
298 /* if it is on the stack or indirectly addressable */
299 /* space we need to assign either r0 or r1 to it */
300 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
302 sym->aop = aop = newAsmop (0);
303 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
304 aop->size = getSize (sym->type);
306 /* now assign the address of the variable to
307 the pointer register */
308 if (aop->type != AOP_STK)
314 emitcode ("push", "acc");
316 emitcode ("mov", "a,_bp");
317 emitcode ("add", "a,#0x%02x",
319 ((char) (sym->stack - _G.nRegsSaved)) :
320 ((char) sym->stack)) & 0xff);
321 emitcode ("mov", "%s,a",
322 aop->aopu.aop_ptr->name);
325 emitcode ("pop", "acc");
328 emitcode ("mov", "%s,#%s",
329 aop->aopu.aop_ptr->name,
331 aop->paged = space->paged;
334 aop->aopu.aop_stk = sym->stack;
338 if (sym->onStack && options.stack10bit)
340 /* It's on the 10 bit stack, which is located in
345 emitcode ("push", "acc");
347 emitcode ("mov", "a,_bp");
348 emitcode ("add", "a,#0x%02x",
350 ((char) (sym->stack - _G.nRegsSaved)) :
351 ((char) sym->stack)) & 0xff);
354 emitcode ("mov", "dpx1,#0x40");
355 emitcode ("mov", "dph1,#0x00");
356 emitcode ("mov", "dpl1, a");
360 emitcode ("pop", "acc");
362 sym->aop = aop = newAsmop (AOP_DPTR2);
363 aop->size = getSize (sym->type);
367 /* if in bit space */
368 if (IN_BITSPACE (space))
370 sym->aop = aop = newAsmop (AOP_CRY);
371 aop->aopu.aop_dir = sym->rname;
372 aop->size = getSize (sym->type);
375 /* if it is in direct space */
376 if (IN_DIRSPACE (space))
378 sym->aop = aop = newAsmop (AOP_DIR);
379 aop->aopu.aop_dir = sym->rname;
380 aop->size = getSize (sym->type);
384 /* special case for a function */
385 if (IS_FUNC (sym->type))
387 sym->aop = aop = newAsmop (AOP_IMMD);
388 aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
389 strcpy (aop->aopu.aop_immd, sym->rname);
390 aop->size = FPTRSIZE;
394 /* only remaining is far space */
395 /* in which case DPTR gets the address */
396 sym->aop = aop = newAsmop (AOP_DPTR);
397 emitcode ("mov", "dptr,#%s", sym->rname);
398 aop->size = getSize (sym->type);
400 /* if it is in code space */
401 if (IN_CODESPACE (space))
407 /*-----------------------------------------------------------------*/
408 /* aopForRemat - rematerialzes an object */
409 /*-----------------------------------------------------------------*/
411 aopForRemat (symbol * sym)
413 iCode *ic = sym->rematiCode;
414 asmop *aop = newAsmop (AOP_IMMD);
420 val += operandLitValue (IC_RIGHT (ic));
421 else if (ic->op == '-')
422 val -= operandLitValue (IC_RIGHT (ic));
426 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
430 sprintf (buffer, "(%s %c 0x%04x)",
431 OP_SYMBOL (IC_LEFT (ic))->rname,
432 val >= 0 ? '+' : '-',
435 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
437 aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
438 strcpy (aop->aopu.aop_immd, buffer);
442 /*-----------------------------------------------------------------*/
443 /* regsInCommon - two operands have some registers in common */
444 /*-----------------------------------------------------------------*/
446 regsInCommon (operand * op1, operand * op2)
451 /* if they have registers in common */
452 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
455 sym1 = OP_SYMBOL (op1);
456 sym2 = OP_SYMBOL (op2);
458 if (sym1->nRegs == 0 || sym2->nRegs == 0)
461 for (i = 0; i < sym1->nRegs; i++)
467 for (j = 0; j < sym2->nRegs; j++)
472 if (sym2->regs[j] == sym1->regs[i])
480 /*-----------------------------------------------------------------*/
481 /* operandsEqu - equivalent */
482 /*-----------------------------------------------------------------*/
484 operandsEqu (operand * op1, operand * op2)
488 /* if they not symbols */
489 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
492 sym1 = OP_SYMBOL (op1);
493 sym2 = OP_SYMBOL (op2);
495 /* if both are itemps & one is spilt
496 and the other is not then false */
497 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
498 sym1->isspilt != sym2->isspilt)
501 /* if they are the same */
505 if (strcmp (sym1->rname, sym2->rname) == 0)
509 /* if left is a tmp & right is not */
510 if (IS_ITEMP (op1) &&
513 (sym1->usl.spillLoc == sym2))
516 if (IS_ITEMP (op2) &&
520 (sym2->usl.spillLoc == sym1))
526 /*-----------------------------------------------------------------*/
527 /* sameRegs - two asmops have the same registers */
528 /*-----------------------------------------------------------------*/
530 sameRegs (asmop * aop1, asmop * aop2)
537 if (aop1->type != AOP_REG ||
538 aop2->type != AOP_REG)
541 if (aop1->size != aop2->size)
544 for (i = 0; i < aop1->size; i++)
545 if (aop1->aopu.aop_reg[i] !=
546 aop2->aopu.aop_reg[i])
552 /*-----------------------------------------------------------------*/
553 /* aopOp - allocates an asmop for an operand : */
554 /*-----------------------------------------------------------------*/
556 aopOp (operand * op, iCode * ic, bool result)
565 /* if this a literal */
566 if (IS_OP_LITERAL (op))
568 op->aop = aop = newAsmop (AOP_LIT);
569 aop->aopu.aop_lit = op->operand.valOperand;
570 aop->size = getSize (operandType (op));
574 /* if already has a asmop then continue */
578 /* if the underlying symbol has a aop */
579 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
581 op->aop = OP_SYMBOL (op)->aop;
585 /* if this is a true symbol */
586 if (IS_TRUE_SYMOP (op))
588 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
592 /* this is a temporary : this has
598 e) can be a return use only */
600 sym = OP_SYMBOL (op);
603 /* if the type is a conditional */
604 if (sym->regType == REG_CND)
606 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
611 /* if it is spilt then two situations
613 b) has a spill location */
614 if (sym->isspilt || sym->nRegs == 0)
617 /* rematerialize it NOW */
620 sym->aop = op->aop = aop =
622 aop->size = getSize (sym->type);
629 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
630 aop->size = getSize (sym->type);
631 for (i = 0; i < 2; i++)
632 aop->aopu.aop_str[i] = accUse[i];
639 aop = op->aop = sym->aop = newAsmop (AOP_STR);
640 aop->size = getSize (sym->type);
641 for (i = 0; i < fReturnSize; i++)
642 aop->aopu.aop_str[i] = fReturn[i];
646 /* else spill location */
647 sym->aop = op->aop = aop =
648 aopForSym (ic, sym->usl.spillLoc, result);
649 aop->size = getSize (sym->type);
653 /* must be in a register */
654 sym->aop = op->aop = aop = newAsmop (AOP_REG);
655 aop->size = sym->nRegs;
656 for (i = 0; i < sym->nRegs; i++)
657 aop->aopu.aop_reg[i] = sym->regs[i];
660 /*-----------------------------------------------------------------*/
661 /* freeAsmop - free up the asmop given to an operand */
662 /*----------------------------------------------------------------*/
664 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
681 /* depending on the asmop type only three cases need work AOP_RO
682 , AOP_R1 && AOP_STK */
690 emitcode ("pop", "ar0");
694 bitVectUnSetBit (ic->rUsed, R0_IDX);
702 emitcode ("pop", "ar1");
706 bitVectUnSetBit (ic->rUsed, R1_IDX);
712 int stk = aop->aopu.aop_stk + aop->size;
713 bitVectUnSetBit (ic->rUsed, R0_IDX);
714 bitVectUnSetBit (ic->rUsed, R1_IDX);
716 getFreePtr (ic, &aop, FALSE);
718 if (options.stack10bit)
720 /* I'm not sure what to do here yet... */
723 "*** Warning: probably generating bad code for "
724 "10 bit stack mode.\n");
729 emitcode ("mov", "a,_bp");
730 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
731 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
735 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
740 emitcode ("pop", "acc");
741 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
744 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
747 freeAsmop (op, NULL, ic, TRUE);
750 emitcode ("pop", "ar0");
756 emitcode ("pop", "ar1");
763 /* all other cases just dealloc */
769 OP_SYMBOL (op)->aop = NULL;
770 /* if the symbol has a spill */
772 SPIL_LOC (op)->aop = NULL;
777 /*-----------------------------------------------------------------*/
778 /* aopGet - for fetching value of the aop */
779 /*-----------------------------------------------------------------*/
781 aopGet (asmop * aop, int offset, bool bit16, bool dname)
786 /* offset is greater than
788 if (offset > (aop->size - 1) &&
789 aop->type != AOP_LIT)
792 /* depending on type */
798 /* if we need to increment it */
799 while (offset > aop->coff)
801 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
805 while (offset < aop->coff)
807 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
814 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
815 return (dname ? "acc" : "a");
817 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
818 rs = Safe_calloc (1, strlen (s) + 1);
825 if (aop->type == AOP_DPTR2)
830 while (offset > aop->coff)
832 emitcode ("inc", "dptr");
836 while (offset < aop->coff)
838 emitcode ("lcall", "__decdptr");
845 emitcode ("clr", "a");
846 emitcode ("movc", "a,@a+dptr");
850 emitcode ("movx", "a,@dptr");
853 if (aop->type == AOP_DPTR2)
858 return (dname ? "acc" : "a");
863 sprintf (s, "#%s", aop->aopu.aop_immd);
865 sprintf (s, "#(%s >> %d)",
871 rs = Safe_calloc (1, strlen (s) + 1);
877 sprintf (s, "(%s + %d)",
881 sprintf (s, "%s", aop->aopu.aop_dir);
882 rs = Safe_calloc (1, strlen (s) + 1);
888 return aop->aopu.aop_reg[offset]->dname;
890 return aop->aopu.aop_reg[offset]->name;
893 emitcode ("clr", "a");
894 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
895 emitcode ("rlc", "a");
896 return (dname ? "acc" : "a");
899 if (!offset && dname)
901 return aop->aopu.aop_str[offset];
904 return aopLiteral (aop->aopu.aop_lit, offset);
908 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
912 return aop->aopu.aop_str[offset];
916 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
917 "aopget got unsupported aop->type");
920 /*-----------------------------------------------------------------*/
921 /* aopPut - puts a string for a aop */
922 /*-----------------------------------------------------------------*/
924 aopPut (asmop * aop, char *s, int offset)
929 if (aop->size && offset > (aop->size - 1))
931 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
932 "aopPut got offset > aop->size");
936 /* will assign value to value */
937 /* depending on where it is ofcourse */
942 sprintf (d, "(%s + %d)",
943 aop->aopu.aop_dir, offset);
945 sprintf (d, "%s", aop->aopu.aop_dir);
948 emitcode ("mov", "%s,%s", d, s);
953 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
954 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
957 strcmp (s, "r0") == 0 ||
958 strcmp (s, "r1") == 0 ||
959 strcmp (s, "r2") == 0 ||
960 strcmp (s, "r3") == 0 ||
961 strcmp (s, "r4") == 0 ||
962 strcmp (s, "r5") == 0 ||
963 strcmp (s, "r6") == 0 ||
964 strcmp (s, "r7") == 0)
965 emitcode ("mov", "%s,%s",
966 aop->aopu.aop_reg[offset]->dname, s);
968 emitcode ("mov", "%s,%s",
969 aop->aopu.aop_reg[offset]->name, s);
976 if (aop->type == AOP_DPTR2)
983 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
984 "aopPut writting to code space");
988 while (offset > aop->coff)
991 emitcode ("inc", "dptr");
994 while (offset < aop->coff)
997 emitcode ("lcall", "__decdptr");
1002 /* if not in accumulater */
1005 emitcode ("movx", "@dptr,a");
1007 if (aop->type == AOP_DPTR2)
1015 while (offset > aop->coff)
1018 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1020 while (offset < aop->coff)
1023 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1030 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1036 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1038 else if (strcmp (s, "r0") == 0 ||
1039 strcmp (s, "r1") == 0 ||
1040 strcmp (s, "r2") == 0 ||
1041 strcmp (s, "r3") == 0 ||
1042 strcmp (s, "r4") == 0 ||
1043 strcmp (s, "r5") == 0 ||
1044 strcmp (s, "r6") == 0 ||
1045 strcmp (s, "r7") == 0)
1048 sprintf (buffer, "a%s", s);
1049 emitcode ("mov", "@%s,%s",
1050 aop->aopu.aop_ptr->name, buffer);
1053 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1058 if (strcmp (s, "a") == 0)
1059 emitcode ("push", "acc");
1061 emitcode ("push", "%s", s);
1066 /* if bit variable */
1067 if (!aop->aopu.aop_dir)
1069 emitcode ("clr", "a");
1070 emitcode ("rlc", "a");
1075 emitcode ("clr", "%s", aop->aopu.aop_dir);
1077 emitcode ("setb", "%s", aop->aopu.aop_dir);
1078 else if (!strcmp (s, "c"))
1079 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1082 lbl = newiTempLabel (NULL);
1084 if (strcmp (s, "a"))
1088 emitcode ("clr", "c");
1089 emitcode ("jz", "%05d$", lbl->key + 100);
1090 emitcode ("cpl", "c");
1091 emitcode ("", "%05d$:", lbl->key + 100);
1092 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1099 if (strcmp (aop->aopu.aop_str[offset], s))
1100 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1105 if (!offset && (strcmp (s, "acc") == 0))
1108 if (strcmp (aop->aopu.aop_str[offset], s))
1109 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1113 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1114 "aopPut got unsupported aop->type");
1122 /*-----------------------------------------------------------------*/
1123 /* pointToEnd :- points to the last byte of the operand */
1124 /*-----------------------------------------------------------------*/
1126 pointToEnd (asmop * aop)
1132 aop->coff = count = (aop->size - 1);
1138 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1142 emitcode ("inc", "dptr");
1149 /*-----------------------------------------------------------------*/
1150 /* reAdjustPreg - points a register back to where it should */
1151 /*-----------------------------------------------------------------*/
1153 reAdjustPreg (asmop * aop)
1158 if ((size = aop->size) <= 1)
1166 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1170 if (aop->type == AOP_DPTR2)
1176 emitcode ("lcall", "__decdptr");
1179 if (aop->type == AOP_DPTR2)
1189 #define AOP(op) op->aop
1190 #define AOP_TYPE(op) AOP(op)->type
1191 #define AOP_SIZE(op) AOP(op)->size
1192 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1193 AOP_TYPE(x) == AOP_R0))
1195 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1196 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1199 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1200 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1201 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1203 /*-----------------------------------------------------------------*/
1204 /* genNotFloat - generates not for float operations */
1205 /*-----------------------------------------------------------------*/
1207 genNotFloat (operand * op, operand * res)
1213 /* we will put 127 in the first byte of
1215 aopPut (AOP (res), "#127", 0);
1216 size = AOP_SIZE (op) - 1;
1219 l = aopGet (op->aop, offset++, FALSE, FALSE);
1224 emitcode ("orl", "a,%s",
1226 offset++, FALSE, FALSE));
1228 tlbl = newiTempLabel (NULL);
1230 tlbl = newiTempLabel (NULL);
1231 aopPut (res->aop, one, 1);
1232 emitcode ("jz", "%05d$", (tlbl->key + 100));
1233 aopPut (res->aop, zero, 1);
1234 emitcode ("", "%05d$:", (tlbl->key + 100));
1236 size = res->aop->size - 2;
1238 /* put zeros in the rest */
1240 aopPut (res->aop, zero, offset++);
1243 /*-----------------------------------------------------------------*/
1244 /* opIsGptr: returns non-zero if the passed operand is */
1245 /* a generic pointer type. */
1246 /*-----------------------------------------------------------------*/
1248 opIsGptr (operand * op)
1250 sym_link *type = operandType (op);
1252 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1259 /*-----------------------------------------------------------------*/
1260 /* getDataSize - get the operand data size */
1261 /*-----------------------------------------------------------------*/
1263 getDataSize (operand * op)
1266 size = AOP_SIZE (op);
1267 if (size == GPTRSIZE)
1269 sym_link *type = operandType (op);
1270 if (IS_GENPTR (type))
1272 /* generic pointer; arithmetic operations
1273 * should ignore the high byte (pointer type).
1281 /*-----------------------------------------------------------------*/
1282 /* outAcc - output Acc */
1283 /*-----------------------------------------------------------------*/
1285 outAcc (operand * result)
1288 size = getDataSize (result);
1291 aopPut (AOP (result), "a", 0);
1294 /* unsigned or positive */
1297 aopPut (AOP (result), zero, offset++);
1302 /*-----------------------------------------------------------------*/
1303 /* outBitC - output a bit C */
1304 /*-----------------------------------------------------------------*/
1306 outBitC (operand * result)
1308 /* if the result is bit */
1309 if (AOP_TYPE (result) == AOP_CRY)
1310 aopPut (AOP (result), "c", 0);
1313 emitcode ("clr", "a");
1314 emitcode ("rlc", "a");
1319 /*-----------------------------------------------------------------*/
1320 /* toBoolean - emit code for orl a,operator(sizeop) */
1321 /*-----------------------------------------------------------------*/
1323 toBoolean (operand * oper)
1325 int size = AOP_SIZE (oper) - 1;
1327 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1329 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1333 /*-----------------------------------------------------------------*/
1334 /* genNot - generate code for ! operation */
1335 /*-----------------------------------------------------------------*/
1340 sym_link *optype = operandType (IC_LEFT (ic));
1342 /* assign asmOps to operand & result */
1343 aopOp (IC_LEFT (ic), ic, FALSE);
1344 aopOp (IC_RESULT (ic), ic, TRUE);
1346 /* if in bit space then a special case */
1347 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1349 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1350 emitcode ("cpl", "c");
1351 outBitC (IC_RESULT (ic));
1355 /* if type float then do float */
1356 if (IS_FLOAT (optype))
1358 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1362 toBoolean (IC_LEFT (ic));
1364 tlbl = newiTempLabel (NULL);
1365 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1366 emitcode ("", "%05d$:", tlbl->key + 100);
1367 outBitC (IC_RESULT (ic));
1370 /* release the aops */
1371 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1372 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1376 /*-----------------------------------------------------------------*/
1377 /* genCpl - generate code for complement */
1378 /*-----------------------------------------------------------------*/
1386 /* assign asmOps to operand & result */
1387 aopOp (IC_LEFT (ic), ic, FALSE);
1388 aopOp (IC_RESULT (ic), ic, TRUE);
1390 /* if both are in bit space then
1392 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1393 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1396 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1397 emitcode ("cpl", "c");
1398 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1402 size = AOP_SIZE (IC_RESULT (ic));
1405 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1407 emitcode ("cpl", "a");
1408 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1413 /* release the aops */
1414 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1415 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1418 /*-----------------------------------------------------------------*/
1419 /* genUminusFloat - unary minus for floating points */
1420 /*-----------------------------------------------------------------*/
1422 genUminusFloat (operand * op, operand * result)
1424 int size, offset = 0;
1426 /* for this we just need to flip the
1427 first it then copy the rest in place */
1428 size = AOP_SIZE (op) - 1;
1429 l = aopGet (AOP (op), 3, FALSE, FALSE);
1433 emitcode ("cpl", "acc.7");
1434 aopPut (AOP (result), "a", 3);
1438 aopPut (AOP (result),
1439 aopGet (AOP (op), offset, FALSE, FALSE),
1445 /*-----------------------------------------------------------------*/
1446 /* genUminus - unary minus code generation */
1447 /*-----------------------------------------------------------------*/
1449 genUminus (iCode * ic)
1452 sym_link *optype, *rtype;
1456 aopOp (IC_LEFT (ic), ic, FALSE);
1457 aopOp (IC_RESULT (ic), ic, TRUE);
1459 /* if both in bit space then special
1461 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1462 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1465 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1466 emitcode ("cpl", "c");
1467 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1471 optype = operandType (IC_LEFT (ic));
1472 rtype = operandType (IC_RESULT (ic));
1474 /* if float then do float stuff */
1475 if (IS_FLOAT (optype))
1477 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1481 /* otherwise subtract from zero */
1482 size = AOP_SIZE (IC_LEFT (ic));
1487 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1488 if (!strcmp (l, "a"))
1492 emitcode ("cpl", "a");
1493 emitcode ("addc", "a,#0");
1499 emitcode ("clr", "a");
1500 emitcode ("subb", "a,%s", l);
1502 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1505 /* if any remaining bytes in the result */
1506 /* we just need to propagate the sign */
1507 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1509 emitcode ("rlc", "a");
1510 emitcode ("subb", "a,acc");
1512 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1516 /* release the aops */
1517 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1518 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1521 /*-----------------------------------------------------------------*/
1522 /* saveRegisters - will look for a call and save the registers */
1523 /*-----------------------------------------------------------------*/
1525 saveRegisters (iCode * lic)
1533 for (ic = lic; ic; ic = ic->next)
1534 if (ic->op == CALL || ic->op == PCALL)
1539 fprintf (stderr, "found parameter push with no function call\n");
1543 /* if the registers have been saved already then
1545 if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1548 /* find the registers in use at this time
1549 and push them away to safety */
1550 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1554 if (options.useXstack)
1556 if (bitVectBitValue (rsave, R0_IDX))
1557 emitcode ("mov", "b,r0");
1558 emitcode ("mov", "r0,%s", spname);
1559 for (i = 0; i < mcs51_nRegs; i++)
1561 if (bitVectBitValue (rsave, i))
1564 emitcode ("mov", "a,b");
1566 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1567 emitcode ("movx", "@r0,a");
1568 emitcode ("inc", "r0");
1571 emitcode ("mov", "%s,r0", spname);
1572 if (bitVectBitValue (rsave, R0_IDX))
1573 emitcode ("mov", "r0,b");
1576 for (i = 0; i < mcs51_nRegs; i++)
1578 if (bitVectBitValue (rsave, i))
1579 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1582 detype = getSpec (operandType (IC_LEFT (ic)));
1584 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1585 IS_ISR (currFunc->etype) &&
1588 saverbank (SPEC_BANK (detype), ic, TRUE);
1591 /*-----------------------------------------------------------------*/
1592 /* unsaveRegisters - pop the pushed registers */
1593 /*-----------------------------------------------------------------*/
1595 unsaveRegisters (iCode * ic)
1599 /* find the registers in use at this time
1600 and push them away to safety */
1601 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1604 if (options.useXstack)
1606 emitcode ("mov", "r0,%s", spname);
1607 for (i = mcs51_nRegs; i >= 0; i--)
1609 if (bitVectBitValue (rsave, i))
1611 emitcode ("dec", "r0");
1612 emitcode ("movx", "a,@r0");
1614 emitcode ("mov", "b,a");
1616 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1620 emitcode ("mov", "%s,r0", spname);
1621 if (bitVectBitValue (rsave, R0_IDX))
1622 emitcode ("mov", "r0,b");
1625 for (i = mcs51_nRegs; i >= 0; i--)
1627 if (bitVectBitValue (rsave, i))
1628 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1634 /*-----------------------------------------------------------------*/
1636 /*-----------------------------------------------------------------*/
1638 pushSide (operand * oper, int size)
1643 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1644 if (AOP_TYPE (oper) != AOP_REG &&
1645 AOP_TYPE (oper) != AOP_DIR &&
1648 emitcode ("mov", "a,%s", l);
1649 emitcode ("push", "acc");
1652 emitcode ("push", "%s", l);
1656 /*-----------------------------------------------------------------*/
1657 /* assignResultValue - */
1658 /*-----------------------------------------------------------------*/
1660 assignResultValue (operand * oper)
1663 int size = AOP_SIZE (oper);
1666 aopPut (AOP (oper), fReturn[offset], offset);
1672 /*-----------------------------------------------------------------*/
1673 /* genXpush - pushes onto the external stack */
1674 /*-----------------------------------------------------------------*/
1676 genXpush (iCode * ic)
1678 asmop *aop = newAsmop (0);
1680 int size, offset = 0;
1682 aopOp (IC_LEFT (ic), ic, FALSE);
1683 r = getFreePtr (ic, &aop, FALSE);
1686 emitcode ("mov", "%s,_spx", r->name);
1688 size = AOP_SIZE (IC_LEFT (ic));
1692 char *l = aopGet (AOP (IC_LEFT (ic)),
1693 offset++, FALSE, FALSE);
1695 emitcode ("movx", "@%s,a", r->name);
1696 emitcode ("inc", "%s", r->name);
1701 emitcode ("mov", "_spx,%s", r->name);
1703 freeAsmop (NULL, aop, ic, TRUE);
1704 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1707 /*-----------------------------------------------------------------*/
1708 /* genIpush - genrate code for pushing this gets a little complex */
1709 /*-----------------------------------------------------------------*/
1711 genIpush (iCode * ic)
1713 int size, offset = 0;
1717 /* if this is not a parm push : ie. it is spill push
1718 and spill push is always done on the local stack */
1722 /* and the item is spilt then do nothing */
1723 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1726 aopOp (IC_LEFT (ic), ic, FALSE);
1727 size = AOP_SIZE (IC_LEFT (ic));
1728 /* push it on the stack */
1731 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1737 emitcode ("push", "%s", l);
1742 /* this is a paramter push: in this case we call
1743 the routine to find the call and save those
1744 registers that need to be saved */
1747 /* if use external stack then call the external
1748 stack pushing routine */
1749 if (options.useXstack)
1755 /* then do the push */
1756 aopOp (IC_LEFT (ic), ic, FALSE);
1759 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1760 size = AOP_SIZE (IC_LEFT (ic));
1764 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1765 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1766 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1769 emitcode ("mov", "a,%s", l);
1770 emitcode ("push", "acc");
1773 emitcode ("push", "%s", l);
1776 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1779 /*-----------------------------------------------------------------*/
1780 /* genIpop - recover the registers: can happen only for spilling */
1781 /*-----------------------------------------------------------------*/
1783 genIpop (iCode * ic)
1788 /* if the temp was not pushed then */
1789 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1792 aopOp (IC_LEFT (ic), ic, FALSE);
1793 size = AOP_SIZE (IC_LEFT (ic));
1794 offset = (size - 1);
1796 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1799 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1802 /*-----------------------------------------------------------------*/
1803 /* unsaverbank - restores the resgister bank from stack */
1804 /*-----------------------------------------------------------------*/
1806 unsaverbank (int bank, iCode * ic, bool popPsw)
1814 if (options.useXstack)
1817 r = getFreePtr (ic, &aop, FALSE);
1820 emitcode ("mov", "%s,_spx", r->name);
1821 emitcode ("movx", "a,@%s", r->name);
1822 emitcode ("mov", "psw,a");
1823 emitcode ("dec", "%s", r->name);
1827 emitcode ("pop", "psw");
1830 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1832 if (options.useXstack)
1834 emitcode ("movx", "a,@%s", r->name);
1835 emitcode ("mov", "(%s+%d),a",
1836 regs8051[i].base, 8 * bank + regs8051[i].offset);
1837 emitcode ("dec", "%s", r->name);
1841 emitcode ("pop", "(%s+%d)",
1842 regs8051[i].base, 8 * bank + regs8051[i].offset);
1845 if (options.useXstack)
1848 emitcode ("mov", "_spx,%s", r->name);
1849 freeAsmop (NULL, aop, ic, TRUE);
1854 /*-----------------------------------------------------------------*/
1855 /* saverbank - saves an entire register bank on the stack */
1856 /*-----------------------------------------------------------------*/
1858 saverbank (int bank, iCode * ic, bool pushPsw)
1864 if (options.useXstack)
1868 r = getFreePtr (ic, &aop, FALSE);
1869 emitcode ("mov", "%s,_spx", r->name);
1873 for (i = 0; i < mcs51_nRegs; i++)
1875 if (options.useXstack)
1877 emitcode ("inc", "%s", r->name);
1878 emitcode ("mov", "a,(%s+%d)",
1879 regs8051[i].base, 8 * bank + regs8051[i].offset);
1880 emitcode ("movx", "@%s,a", r->name);
1883 emitcode ("push", "(%s+%d)",
1884 regs8051[i].base, 8 * bank + regs8051[i].offset);
1889 if (options.useXstack)
1891 emitcode ("mov", "a,psw");
1892 emitcode ("movx", "@%s,a", r->name);
1893 emitcode ("inc", "%s", r->name);
1894 emitcode ("mov", "_spx,%s", r->name);
1895 freeAsmop (NULL, aop, ic, TRUE);
1899 emitcode ("push", "psw");
1901 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1907 /*-----------------------------------------------------------------*/
1908 /* genCall - generates a call statement */
1909 /*-----------------------------------------------------------------*/
1911 genCall (iCode * ic)
1915 /* if caller saves & we have not saved then */
1919 /* if we are calling a function that is not using
1920 the same register bank then we need to save the
1921 destination registers on the stack */
1922 detype = getSpec (operandType (IC_LEFT (ic)));
1924 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1925 IS_ISR (currFunc->etype) &&
1928 saverbank (SPEC_BANK (detype), ic, TRUE);
1930 /* if send set is not empty the assign */
1935 for (sic = setFirstItem (_G.sendSet); sic;
1936 sic = setNextItem (_G.sendSet))
1938 int size, offset = 0;
1939 aopOp (IC_LEFT (sic), sic, FALSE);
1940 size = AOP_SIZE (IC_LEFT (sic));
1943 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1945 if (strcmp (l, fReturn[offset]))
1946 emitcode ("mov", "%s,%s",
1951 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1956 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1957 OP_SYMBOL (IC_LEFT (ic))->rname :
1958 OP_SYMBOL (IC_LEFT (ic))->name));
1960 /* if we need assign a result value */
1961 if ((IS_ITEMP (IC_RESULT (ic)) &&
1962 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1963 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1964 IS_TRUE_SYMOP (IC_RESULT (ic)))
1968 aopOp (IC_RESULT (ic), ic, FALSE);
1971 assignResultValue (IC_RESULT (ic));
1973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1976 /* adjust the stack for parameters if
1978 if (IC_LEFT (ic)->parmBytes)
1981 if (IC_LEFT (ic)->parmBytes > 3)
1983 emitcode ("mov", "a,%s", spname);
1984 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
1985 emitcode ("mov", "%s,a", spname);
1988 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
1989 emitcode ("dec", "%s", spname);
1993 /* if register bank was saved then pop them */
1995 unsaverbank (SPEC_BANK (detype), ic, TRUE);
1997 /* if we hade saved some registers then unsave them */
1998 if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
1999 unsaveRegisters (ic);
2004 /*-----------------------------------------------------------------*/
2005 /* genPcall - generates a call by pointer statement */
2006 /*-----------------------------------------------------------------*/
2008 genPcall (iCode * ic)
2011 symbol *rlbl = newiTempLabel (NULL);
2014 /* if caller saves & we have not saved then */
2018 /* if we are calling a function that is not using
2019 the same register bank then we need to save the
2020 destination registers on the stack */
2021 detype = getSpec (operandType (IC_LEFT (ic)));
2023 IS_ISR (currFunc->etype) &&
2024 (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2025 saverbank (SPEC_BANK (detype), ic, TRUE);
2028 /* push the return address on to the stack */
2029 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2030 emitcode ("push", "acc");
2031 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2032 emitcode ("push", "acc");
2034 if (options.model == MODEL_FLAT24)
2036 emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2037 emitcode ("push", "acc");
2040 /* now push the calling address */
2041 aopOp (IC_LEFT (ic), ic, FALSE);
2043 pushSide (IC_LEFT (ic), FPTRSIZE);
2045 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2047 /* if send set is not empty the assign */
2052 for (sic = setFirstItem (_G.sendSet); sic;
2053 sic = setNextItem (_G.sendSet))
2055 int size, offset = 0;
2056 aopOp (IC_LEFT (sic), sic, FALSE);
2057 size = AOP_SIZE (IC_LEFT (sic));
2060 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2062 if (strcmp (l, fReturn[offset]))
2063 emitcode ("mov", "%s,%s",
2068 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2073 emitcode ("ret", "");
2074 emitcode ("", "%05d$:", (rlbl->key + 100));
2077 /* if we need assign a result value */
2078 if ((IS_ITEMP (IC_RESULT (ic)) &&
2079 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2080 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2081 IS_TRUE_SYMOP (IC_RESULT (ic)))
2085 aopOp (IC_RESULT (ic), ic, FALSE);
2088 assignResultValue (IC_RESULT (ic));
2090 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2093 /* adjust the stack for parameters if
2095 if (IC_LEFT (ic)->parmBytes)
2098 if (IC_LEFT (ic)->parmBytes > 3)
2100 emitcode ("mov", "a,%s", spname);
2101 emitcode ("add", "a,#0x%02x", (-IC_LEFT (ic)->parmBytes) & 0xff);
2102 emitcode ("mov", "%s,a", spname);
2105 for (i = 0; i < IC_LEFT (ic)->parmBytes; i++)
2106 emitcode ("dec", "%s", spname);
2110 /* if register bank was saved then unsave them */
2112 (SPEC_BANK (currFunc->etype) !=
2113 SPEC_BANK (detype)))
2114 unsaverbank (SPEC_BANK (detype), ic, TRUE);
2116 /* if we hade saved some registers then
2119 unsaveRegisters (ic);
2123 /*-----------------------------------------------------------------*/
2124 /* resultRemat - result is rematerializable */
2125 /*-----------------------------------------------------------------*/
2127 resultRemat (iCode * ic)
2129 if (SKIP_IC (ic) || ic->op == IFX)
2132 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2134 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2135 if (sym->remat && !POINTER_SET (ic))
2142 #if defined(__BORLANDC__) || defined(_MSC_VER)
2143 #define STRCASECMP stricmp
2145 #define STRCASECMP strcasecmp
2148 /*-----------------------------------------------------------------*/
2149 /* inExcludeList - return 1 if the string is in exclude Reg list */
2150 /*-----------------------------------------------------------------*/
2152 inExcludeList (char *s)
2156 if (options.excludeRegs[i] &&
2157 STRCASECMP (options.excludeRegs[i], "none") == 0)
2160 for (i = 0; options.excludeRegs[i]; i++)
2162 if (options.excludeRegs[i] &&
2163 STRCASECMP (s, options.excludeRegs[i]) == 0)
2169 /*-----------------------------------------------------------------*/
2170 /* genFunction - generated code for function entry */
2171 /*-----------------------------------------------------------------*/
2173 genFunction (iCode * ic)
2179 /* create the function header */
2180 emitcode (";", "-----------------------------------------");
2181 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2182 emitcode (";", "-----------------------------------------");
2184 emitcode ("", "%s:", sym->rname);
2185 fetype = getSpec (operandType (IC_LEFT (ic)));
2187 /* if critical function then turn interrupts off */
2188 if (SPEC_CRTCL (fetype))
2189 emitcode ("clr", "ea");
2191 /* here we need to generate the equates for the
2192 register bank if required */
2193 if (SPEC_BANK (fetype) != rbank)
2197 rbank = SPEC_BANK (fetype);
2198 for (i = 0; i < mcs51_nRegs; i++)
2200 if (strcmp (regs8051[i].base, "0") == 0)
2201 emitcode ("", "%s = 0x%02x",
2203 8 * rbank + regs8051[i].offset);
2205 emitcode ("", "%s = %s + 0x%02x",
2208 8 * rbank + regs8051[i].offset);
2212 /* if this is an interrupt service routine then
2213 save acc, b, dpl, dph */
2214 if (IS_ISR (sym->etype))
2217 if (!inExcludeList ("acc"))
2218 emitcode ("push", "acc");
2219 if (!inExcludeList ("b"))
2220 emitcode ("push", "b");
2221 if (!inExcludeList ("dpl"))
2222 emitcode ("push", "dpl");
2223 if (!inExcludeList ("dph"))
2224 emitcode ("push", "dph");
2225 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2227 emitcode ("push", "dpx");
2228 /* Make sure we're using standard DPTR */
2229 emitcode ("push", "dps");
2230 emitcode ("mov", "dps, #0x00");
2231 if (options.stack10bit)
2233 /* This ISR could conceivably use DPTR2. Better save it. */
2234 emitcode ("push", "dpl1");
2235 emitcode ("push", "dph1");
2236 emitcode ("push", "dpx1");
2239 /* if this isr has no bank i.e. is going to
2240 run with bank 0 , then we need to save more
2242 if (!SPEC_BANK (sym->etype))
2245 /* if this function does not call any other
2246 function then we can be economical and
2247 save only those registers that are used */
2252 /* if any registers used */
2255 /* save the registers used */
2256 for (i = 0; i < sym->regsUsed->size; i++)
2258 if (bitVectBitValue (sym->regsUsed, i) ||
2259 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2260 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2267 /* this function has a function call cannot
2268 determines register usage so we will have the
2270 saverbank (0, ic, FALSE);
2276 /* if callee-save to be used for this function
2277 then save the registers being used in this function */
2278 if (sym->calleeSave)
2282 /* if any registers used */
2285 /* save the registers used */
2286 for (i = 0; i < sym->regsUsed->size; i++)
2288 if (bitVectBitValue (sym->regsUsed, i) ||
2289 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2291 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2299 /* set the register bank to the desired value */
2300 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2302 emitcode ("push", "psw");
2303 emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2306 if (IS_RENT (sym->etype) || options.stackAuto)
2309 if (options.useXstack)
2311 emitcode ("mov", "r0,%s", spname);
2312 emitcode ("mov", "a,_bp");
2313 emitcode ("movx", "@r0,a");
2314 emitcode ("inc", "%s", spname);
2318 /* set up the stack */
2319 emitcode ("push", "_bp"); /* save the callers stack */
2321 emitcode ("mov", "_bp,%s", spname);
2324 /* adjust the stack for the function */
2330 werror (W_STACK_OVERFLOW, sym->name);
2332 if (i > 3 && sym->recvSize < 4)
2335 emitcode ("mov", "a,sp");
2336 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2337 emitcode ("mov", "sp,a");
2342 emitcode ("inc", "sp");
2348 emitcode ("mov", "a,_spx");
2349 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2350 emitcode ("mov", "_spx,a");
2355 /*-----------------------------------------------------------------*/
2356 /* genEndFunction - generates epilogue for functions */
2357 /*-----------------------------------------------------------------*/
2359 genEndFunction (iCode * ic)
2361 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2363 if (IS_RENT (sym->etype) || options.stackAuto)
2365 emitcode ("mov", "%s,_bp", spname);
2368 /* if use external stack but some variables were
2369 added to the local stack then decrement the
2371 if (options.useXstack && sym->stack)
2373 emitcode ("mov", "a,sp");
2374 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2375 emitcode ("mov", "sp,a");
2379 if ((IS_RENT (sym->etype) || options.stackAuto))
2381 if (options.useXstack)
2383 emitcode ("mov", "r0,%s", spname);
2384 emitcode ("movx", "a,@r0");
2385 emitcode ("mov", "_bp,a");
2386 emitcode ("dec", "%s", spname);
2390 emitcode ("pop", "_bp");
2394 /* restore the register bank */
2395 if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2396 emitcode ("pop", "psw");
2398 if (IS_ISR (sym->etype))
2401 /* now we need to restore the registers */
2402 /* if this isr has no bank i.e. is going to
2403 run with bank 0 , then we need to save more
2405 if (!SPEC_BANK (sym->etype))
2408 /* if this function does not call any other
2409 function then we can be economical and
2410 save only those registers that are used */
2415 /* if any registers used */
2418 /* save the registers used */
2419 for (i = sym->regsUsed->size; i >= 0; i--)
2421 if (bitVectBitValue (sym->regsUsed, i) ||
2422 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2423 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2430 /* this function has a function call cannot
2431 determines register usage so we will have the
2433 unsaverbank (0, ic, FALSE);
2437 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2439 if (options.stack10bit)
2441 emitcode ("pop", "dpx1");
2442 emitcode ("pop", "dph1");
2443 emitcode ("pop", "dpl1");
2445 emitcode ("pop", "dps");
2446 emitcode ("pop", "dpx");
2448 if (!inExcludeList ("dph"))
2449 emitcode ("pop", "dph");
2450 if (!inExcludeList ("dpl"))
2451 emitcode ("pop", "dpl");
2452 if (!inExcludeList ("b"))
2453 emitcode ("pop", "b");
2454 if (!inExcludeList ("acc"))
2455 emitcode ("pop", "acc");
2457 if (SPEC_CRTCL (sym->etype))
2458 emitcode ("setb", "ea");
2460 /* if debug then send end of function */
2461 /* if (options.debug && currFunc) { */
2465 emitcode ("", "C$%s$%d$%d$%d ==.",
2466 FileBaseName (ic->filename), currFunc->lastLine,
2467 ic->level, ic->block);
2468 if (IS_STATIC (currFunc->etype))
2469 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2471 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2475 emitcode ("reti", "");
2479 if (SPEC_CRTCL (sym->etype))
2480 emitcode ("setb", "ea");
2482 if (sym->calleeSave)
2486 /* if any registers used */
2489 /* save the registers used */
2490 for (i = sym->regsUsed->size; i >= 0; i--)
2492 if (bitVectBitValue (sym->regsUsed, i) ||
2493 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2494 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2500 /* if debug then send end of function */
2504 emitcode ("", "C$%s$%d$%d$%d ==.",
2505 FileBaseName (ic->filename), currFunc->lastLine,
2506 ic->level, ic->block);
2507 if (IS_STATIC (currFunc->etype))
2508 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2510 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2514 emitcode ("ret", "");
2519 /*-----------------------------------------------------------------*/
2520 /* genRet - generate code for return statement */
2521 /*-----------------------------------------------------------------*/
2525 int size, offset = 0, pushed = 0;
2527 /* if we have no return value then
2528 just generate the "ret" */
2532 /* we have something to return then
2533 move the return value into place */
2534 aopOp (IC_LEFT (ic), ic, FALSE);
2535 size = AOP_SIZE (IC_LEFT (ic));
2540 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2543 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2545 emitcode ("push", "%s", l);
2550 l = aopGet (AOP (IC_LEFT (ic)), offset,
2552 if (strcmp (fReturn[offset], l))
2553 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2562 if (strcmp (fReturn[pushed], "a"))
2563 emitcode ("pop", fReturn[pushed]);
2565 emitcode ("pop", "acc");
2568 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2571 /* generate a jump to the return label
2572 if the next is not the return statement */
2573 if (!(ic->next && ic->next->op == LABEL &&
2574 IC_LABEL (ic->next) == returnLabel))
2576 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2580 /*-----------------------------------------------------------------*/
2581 /* genLabel - generates a label */
2582 /*-----------------------------------------------------------------*/
2584 genLabel (iCode * ic)
2586 /* special case never generate */
2587 if (IC_LABEL (ic) == entryLabel)
2590 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2593 /*-----------------------------------------------------------------*/
2594 /* genGoto - generates a ljmp */
2595 /*-----------------------------------------------------------------*/
2597 genGoto (iCode * ic)
2599 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2602 /*-----------------------------------------------------------------*/
2603 /* findLabelBackwards: walks back through the iCode chain looking */
2604 /* for the given label. Returns number of iCode instructions */
2605 /* between that label and given ic. */
2606 /* Returns zero if label not found. */
2607 /*-----------------------------------------------------------------*/
2609 findLabelBackwards (iCode * ic, int key)
2618 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2620 /* printf("findLabelBackwards = %d\n", count); */
2628 /*-----------------------------------------------------------------*/
2629 /* genPlusIncr :- does addition with increment if possible */
2630 /*-----------------------------------------------------------------*/
2632 genPlusIncr (iCode * ic)
2634 unsigned int icount;
2635 unsigned int size = getDataSize (IC_RESULT (ic));
2637 /* will try to generate an increment */
2638 /* if the right side is not a literal
2640 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2643 /* if the literal value of the right hand side
2644 is greater than 4 then it is not worth it */
2645 if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2648 /* if increment 16 bits in register */
2649 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2657 /* If the next instruction is a goto and the goto target
2658 * is < 10 instructions previous to this, we can generate
2659 * jumps straight to that target.
2661 if (ic->next && ic->next->op == GOTO
2662 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2663 && labelRange <= 10)
2665 emitcode (";", "tail increment optimized");
2666 tlbl = IC_LABEL (ic->next);
2671 tlbl = newiTempLabel (NULL);
2674 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2675 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2676 IS_AOP_PREG (IC_RESULT (ic)))
2677 emitcode ("cjne", "%s,#0x00,%05d$"
2678 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2682 emitcode ("clr", "a");
2683 emitcode ("cjne", "a,%s,%05d$"
2684 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2688 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2691 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2692 IS_AOP_PREG (IC_RESULT (ic)))
2693 emitcode ("cjne", "%s,#0x00,%05d$"
2694 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2697 emitcode ("cjne", "a,%s,%05d$"
2698 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2701 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2705 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2706 IS_AOP_PREG (IC_RESULT (ic)))
2707 emitcode ("cjne", "%s,#0x00,%05d$"
2708 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2712 emitcode ("cjne", "a,%s,%05d$"
2713 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2716 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2721 emitcode ("", "%05d$:", tlbl->key + 100);
2726 /* if the sizes are greater than 1 then we cannot */
2727 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2728 AOP_SIZE (IC_LEFT (ic)) > 1)
2731 /* we can if the aops of the left & result match or
2732 if they are in registers and the registers are the
2734 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2739 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2740 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2741 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2747 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2756 /*-----------------------------------------------------------------*/
2757 /* outBitAcc - output a bit in acc */
2758 /*-----------------------------------------------------------------*/
2760 outBitAcc (operand * result)
2762 symbol *tlbl = newiTempLabel (NULL);
2763 /* if the result is a bit */
2764 if (AOP_TYPE (result) == AOP_CRY)
2766 aopPut (AOP (result), "a", 0);
2770 emitcode ("jz", "%05d$", tlbl->key + 100);
2771 emitcode ("mov", "a,%s", one);
2772 emitcode ("", "%05d$:", tlbl->key + 100);
2777 /*-----------------------------------------------------------------*/
2778 /* genPlusBits - generates code for addition of two bits */
2779 /*-----------------------------------------------------------------*/
2781 genPlusBits (iCode * ic)
2783 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2785 symbol *lbl = newiTempLabel (NULL);
2786 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2787 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2788 emitcode ("cpl", "c");
2789 emitcode ("", "%05d$:", (lbl->key + 100));
2790 outBitC (IC_RESULT (ic));
2794 emitcode ("clr", "a");
2795 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2796 emitcode ("rlc", "a");
2797 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2798 emitcode ("addc", "a,#0x00");
2799 outAcc (IC_RESULT (ic));
2804 /* This is the original version of this code.
2806 * This is being kept around for reference,
2807 * because I am not entirely sure I got it right...
2810 adjustArithmeticResult (iCode * ic)
2812 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2813 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2814 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2815 aopPut (AOP (IC_RESULT (ic)),
2816 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2819 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2820 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2821 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2822 aopPut (AOP (IC_RESULT (ic)),
2823 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2826 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2827 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2828 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2829 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2830 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2833 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2834 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2838 /* This is the pure and virtuous version of this code.
2839 * I'm pretty certain it's right, but not enough to toss the old
2843 adjustArithmeticResult (iCode * ic)
2845 if (opIsGptr (IC_RESULT (ic)) &&
2846 opIsGptr (IC_LEFT (ic)) &&
2847 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2849 aopPut (AOP (IC_RESULT (ic)),
2850 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2854 if (opIsGptr (IC_RESULT (ic)) &&
2855 opIsGptr (IC_RIGHT (ic)) &&
2856 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2858 aopPut (AOP (IC_RESULT (ic)),
2859 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2863 if (opIsGptr (IC_RESULT (ic)) &&
2864 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2865 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2866 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2867 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2870 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2871 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2876 /*-----------------------------------------------------------------*/
2877 /* genPlus - generates code for addition */
2878 /*-----------------------------------------------------------------*/
2880 genPlus (iCode * ic)
2882 int size, offset = 0;
2884 /* special cases :- */
2886 aopOp (IC_LEFT (ic), ic, FALSE);
2887 aopOp (IC_RIGHT (ic), ic, FALSE);
2888 aopOp (IC_RESULT (ic), ic, TRUE);
2890 /* if literal, literal on the right or
2891 if left requires ACC or right is already
2893 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2894 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2895 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2897 operand *t = IC_RIGHT (ic);
2898 IC_RIGHT (ic) = IC_LEFT (ic);
2902 /* if both left & right are in bit
2904 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2905 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
2911 /* if left in bit space & right literal */
2912 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
2913 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
2915 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2916 /* if result in bit space */
2917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2919 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
2920 emitcode ("cpl", "c");
2921 outBitC (IC_RESULT (ic));
2925 size = getDataSize (IC_RESULT (ic));
2928 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2929 emitcode ("addc", "a,#00");
2930 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2936 /* if I can do an increment instead
2937 of add then GOOD for ME */
2938 if (genPlusIncr (ic) == TRUE)
2941 size = getDataSize (IC_RESULT (ic));
2945 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
2947 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2949 emitcode ("add", "a,%s",
2950 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2952 emitcode ("addc", "a,%s",
2953 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2957 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
2959 emitcode ("add", "a,%s",
2960 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2962 emitcode ("addc", "a,%s",
2963 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
2965 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2968 adjustArithmeticResult (ic);
2971 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2972 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
2973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2976 /*-----------------------------------------------------------------*/
2977 /* genMinusDec :- does subtraction with deccrement if possible */
2978 /*-----------------------------------------------------------------*/
2980 genMinusDec (iCode * ic)
2982 unsigned int icount;
2983 unsigned int size = getDataSize (IC_RESULT (ic));
2985 /* will try to generate an increment */
2986 /* if the right side is not a literal
2988 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2991 /* if the literal value of the right hand side
2992 is greater than 4 then it is not worth it */
2993 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2996 /* if decrement 16 bits in register */
2997 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3005 /* If the next instruction is a goto and the goto target
3006 * is <= 10 instructions previous to this, we can generate
3007 * jumps straight to that target.
3009 if (ic->next && ic->next->op == GOTO
3010 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3011 && labelRange <= 10)
3013 emitcode (";", "tail decrement optimized");
3014 tlbl = IC_LABEL (ic->next);
3019 tlbl = newiTempLabel (NULL);
3023 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3024 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3025 IS_AOP_PREG (IC_RESULT (ic)))
3026 emitcode ("cjne", "%s,#0xff,%05d$"
3027 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3031 emitcode ("mov", "a,#0xff");
3032 emitcode ("cjne", "a,%s,%05d$"
3033 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3036 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3039 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3040 IS_AOP_PREG (IC_RESULT (ic)))
3041 emitcode ("cjne", "%s,#0xff,%05d$"
3042 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3046 emitcode ("cjne", "a,%s,%05d$"
3047 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3050 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3054 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3055 IS_AOP_PREG (IC_RESULT (ic)))
3056 emitcode ("cjne", "%s,#0xff,%05d$"
3057 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3061 emitcode ("cjne", "a,%s,%05d$"
3062 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3065 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3069 emitcode ("", "%05d$:", tlbl->key + 100);
3074 /* if the sizes are greater than 1 then we cannot */
3075 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3076 AOP_SIZE (IC_LEFT (ic)) > 1)
3079 /* we can if the aops of the left & result match or
3080 if they are in registers and the registers are the
3082 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3086 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3094 /*-----------------------------------------------------------------*/
3095 /* addSign - complete with sign */
3096 /*-----------------------------------------------------------------*/
3098 addSign (operand * result, int offset, int sign)
3100 int size = (getDataSize (result) - offset);
3105 emitcode ("rlc", "a");
3106 emitcode ("subb", "a,acc");
3108 aopPut (AOP (result), "a", offset++);
3112 aopPut (AOP (result), zero, offset++);
3116 /*-----------------------------------------------------------------*/
3117 /* genMinusBits - generates code for subtraction of two bits */
3118 /*-----------------------------------------------------------------*/
3120 genMinusBits (iCode * ic)
3122 symbol *lbl = newiTempLabel (NULL);
3123 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3125 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3126 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3127 emitcode ("cpl", "c");
3128 emitcode ("", "%05d$:", (lbl->key + 100));
3129 outBitC (IC_RESULT (ic));
3133 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3134 emitcode ("subb", "a,acc");
3135 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3136 emitcode ("inc", "a");
3137 emitcode ("", "%05d$:", (lbl->key + 100));
3138 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3139 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3143 /*-----------------------------------------------------------------*/
3144 /* genMinus - generates code for subtraction */
3145 /*-----------------------------------------------------------------*/
3147 genMinus (iCode * ic)
3149 int size, offset = 0;
3150 unsigned long lit = 0L;
3152 aopOp (IC_LEFT (ic), ic, FALSE);
3153 aopOp (IC_RIGHT (ic), ic, FALSE);
3154 aopOp (IC_RESULT (ic), ic, TRUE);
3156 /* special cases :- */
3157 /* if both left & right are in bit space */
3158 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3159 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3165 /* if I can do an decrement instead
3166 of subtract then GOOD for ME */
3167 if (genMinusDec (ic) == TRUE)
3170 size = getDataSize (IC_RESULT (ic));
3172 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3178 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3182 /* if literal, add a,#-lit, else normal subb */
3185 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3186 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3187 emitcode ("subb", "a,%s",
3188 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3191 /* first add without previous c */
3193 emitcode ("add", "a,#0x%02x",
3194 (unsigned int) (lit & 0x0FFL));
3196 emitcode ("addc", "a,#0x%02x",
3197 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3199 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3202 adjustArithmeticResult (ic);
3205 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3206 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3207 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3211 /*-----------------------------------------------------------------*/
3212 /* genMultbits :- multiplication of bits */
3213 /*-----------------------------------------------------------------*/
3215 genMultbits (operand * left,
3219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3220 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3225 /*-----------------------------------------------------------------*/
3226 /* genMultOneByte : 8 bit multiplication & division */
3227 /*-----------------------------------------------------------------*/
3229 genMultOneByte (operand * left,
3233 sym_link *opetype = operandType (result);
3238 /* (if two literals, the value is computed before) */
3239 /* if one literal, literal on the right */
3240 if (AOP_TYPE (left) == AOP_LIT)
3247 size = AOP_SIZE (result);
3248 /* signed or unsigned */
3249 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3250 l = aopGet (AOP (left), 0, FALSE, FALSE);
3252 emitcode ("mul", "ab");
3253 /* if result size = 1, mul signed = mul unsigned */
3254 aopPut (AOP (result), "a", 0);
3257 if (SPEC_USIGN (opetype))
3259 aopPut (AOP (result), "b", 1);
3261 /* for filling the MSBs */
3262 emitcode ("clr", "a");
3266 emitcode ("mov", "a,b");
3268 /* adjust the MSB if left or right neg */
3270 /* if one literal */
3271 if (AOP_TYPE (right) == AOP_LIT)
3273 /* AND literal negative */
3274 if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
3276 /* adjust MSB (c==0 after mul) */
3277 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3282 lbl = newiTempLabel (NULL);
3283 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3284 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3285 emitcode ("", "%05d$:", (lbl->key + 100));
3286 emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3287 lbl = newiTempLabel (NULL);
3288 emitcode ("jc", "%05d$", (lbl->key + 100));
3289 emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3290 emitcode ("", "%05d$:", (lbl->key + 100));
3293 lbl = newiTempLabel (NULL);
3294 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3295 emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
3296 emitcode ("", "%05d$:", (lbl->key + 100));
3297 emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
3298 lbl = newiTempLabel (NULL);
3299 emitcode ("jc", "%05d$", (lbl->key + 100));
3300 emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3301 emitcode ("", "%05d$:", (lbl->key + 100));
3303 aopPut (AOP (result), "a", 1);
3307 emitcode ("rlc", "a");
3308 emitcode ("subb", "a,acc");
3315 aopPut (AOP (result), "a", offset++);
3319 /*-----------------------------------------------------------------*/
3320 /* genMult - generates code for multiplication */
3321 /*-----------------------------------------------------------------*/
3323 genMult (iCode * ic)
3325 operand *left = IC_LEFT (ic);
3326 operand *right = IC_RIGHT (ic);
3327 operand *result = IC_RESULT (ic);
3329 /* assign the amsops */
3330 aopOp (left, ic, FALSE);
3331 aopOp (right, ic, FALSE);
3332 aopOp (result, ic, TRUE);
3334 /* special cases first */
3336 if (AOP_TYPE (left) == AOP_CRY &&
3337 AOP_TYPE (right) == AOP_CRY)
3339 genMultbits (left, right, result);
3343 /* if both are of size == 1 */
3344 if (AOP_SIZE (left) == 1 &&
3345 AOP_SIZE (right) == 1)
3347 genMultOneByte (left, right, result);
3351 /* should have been converted to function call */
3355 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3356 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3357 freeAsmop (result, NULL, ic, TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* genDivbits :- division of bits */
3362 /*-----------------------------------------------------------------*/
3364 genDivbits (operand * left,
3371 /* the result must be bit */
3372 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3373 l = aopGet (AOP (left), 0, FALSE, FALSE);
3377 emitcode ("div", "ab");
3378 emitcode ("rrc", "a");
3379 aopPut (AOP (result), "c", 0);
3382 /*-----------------------------------------------------------------*/
3383 /* genDivOneByte : 8 bit division */
3384 /*-----------------------------------------------------------------*/
3386 genDivOneByte (operand * left,
3390 sym_link *opetype = operandType (result);
3395 size = AOP_SIZE (result) - 1;
3397 /* signed or unsigned */
3398 if (SPEC_USIGN (opetype))
3400 /* unsigned is easy */
3401 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3402 l = aopGet (AOP (left), 0, FALSE, FALSE);
3404 emitcode ("div", "ab");
3405 aopPut (AOP (result), "a", 0);
3407 aopPut (AOP (result), zero, offset++);
3411 /* signed is a little bit more difficult */
3413 /* save the signs of the operands */
3414 l = aopGet (AOP (left), 0, FALSE, FALSE);
3416 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3417 emitcode ("push", "acc"); /* save it on the stack */
3419 /* now sign adjust for both left & right */
3420 l = aopGet (AOP (right), 0, FALSE, FALSE);
3422 lbl = newiTempLabel (NULL);
3423 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3424 emitcode ("cpl", "a");
3425 emitcode ("inc", "a");
3426 emitcode ("", "%05d$:", (lbl->key + 100));
3427 emitcode ("mov", "b,a");
3429 /* sign adjust left side */
3430 l = aopGet (AOP (left), 0, FALSE, FALSE);
3433 lbl = newiTempLabel (NULL);
3434 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3435 emitcode ("cpl", "a");
3436 emitcode ("inc", "a");
3437 emitcode ("", "%05d$:", (lbl->key + 100));
3439 /* now the division */
3440 emitcode ("div", "ab");
3441 /* we are interested in the lower order
3443 emitcode ("mov", "b,a");
3444 lbl = newiTempLabel (NULL);
3445 emitcode ("pop", "acc");
3446 /* if there was an over flow we don't
3447 adjust the sign of the result */
3448 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3449 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3451 emitcode ("clr", "a");
3452 emitcode ("subb", "a,b");
3453 emitcode ("mov", "b,a");
3454 emitcode ("", "%05d$:", (lbl->key + 100));
3456 /* now we are done */
3457 aopPut (AOP (result), "b", 0);
3460 emitcode ("mov", "c,b.7");
3461 emitcode ("subb", "a,acc");
3464 aopPut (AOP (result), "a", offset++);
3468 /*-----------------------------------------------------------------*/
3469 /* genDiv - generates code for division */
3470 /*-----------------------------------------------------------------*/
3474 operand *left = IC_LEFT (ic);
3475 operand *right = IC_RIGHT (ic);
3476 operand *result = IC_RESULT (ic);
3478 /* assign the amsops */
3479 aopOp (left, ic, FALSE);
3480 aopOp (right, ic, FALSE);
3481 aopOp (result, ic, TRUE);
3483 /* special cases first */
3485 if (AOP_TYPE (left) == AOP_CRY &&
3486 AOP_TYPE (right) == AOP_CRY)
3488 genDivbits (left, right, result);
3492 /* if both are of size == 1 */
3493 if (AOP_SIZE (left) == 1 &&
3494 AOP_SIZE (right) == 1)
3496 genDivOneByte (left, right, result);
3500 /* should have been converted to function call */
3503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3505 freeAsmop (result, NULL, ic, TRUE);
3508 /*-----------------------------------------------------------------*/
3509 /* genModbits :- modulus of bits */
3510 /*-----------------------------------------------------------------*/
3512 genModbits (operand * left,
3519 /* the result must be bit */
3520 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3521 l = aopGet (AOP (left), 0, FALSE, FALSE);
3525 emitcode ("div", "ab");
3526 emitcode ("mov", "a,b");
3527 emitcode ("rrc", "a");
3528 aopPut (AOP (result), "c", 0);
3531 /*-----------------------------------------------------------------*/
3532 /* genModOneByte : 8 bit modulus */
3533 /*-----------------------------------------------------------------*/
3535 genModOneByte (operand * left,
3539 sym_link *opetype = operandType (result);
3543 /* signed or unsigned */
3544 if (SPEC_USIGN (opetype))
3546 /* unsigned is easy */
3547 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3548 l = aopGet (AOP (left), 0, FALSE, FALSE);
3550 emitcode ("div", "ab");
3551 aopPut (AOP (result), "b", 0);
3555 /* signed is a little bit more difficult */
3557 /* save the signs of the operands */
3558 l = aopGet (AOP (left), 0, FALSE, FALSE);
3561 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3562 emitcode ("push", "acc"); /* save it on the stack */
3564 /* now sign adjust for both left & right */
3565 l = aopGet (AOP (right), 0, FALSE, FALSE);
3568 lbl = newiTempLabel (NULL);
3569 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3570 emitcode ("cpl", "a");
3571 emitcode ("inc", "a");
3572 emitcode ("", "%05d$:", (lbl->key + 100));
3573 emitcode ("mov", "b,a");
3575 /* sign adjust left side */
3576 l = aopGet (AOP (left), 0, FALSE, FALSE);
3579 lbl = newiTempLabel (NULL);
3580 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3581 emitcode ("cpl", "a");
3582 emitcode ("inc", "a");
3583 emitcode ("", "%05d$:", (lbl->key + 100));
3585 /* now the multiplication */
3586 emitcode ("div", "ab");
3587 /* we are interested in the lower order
3589 lbl = newiTempLabel (NULL);
3590 emitcode ("pop", "acc");
3591 /* if there was an over flow we don't
3592 adjust the sign of the result */
3593 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3594 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3596 emitcode ("clr", "a");
3597 emitcode ("subb", "a,b");
3598 emitcode ("mov", "b,a");
3599 emitcode ("", "%05d$:", (lbl->key + 100));
3601 /* now we are done */
3602 aopPut (AOP (result), "b", 0);
3606 /*-----------------------------------------------------------------*/
3607 /* genMod - generates code for division */
3608 /*-----------------------------------------------------------------*/
3612 operand *left = IC_LEFT (ic);
3613 operand *right = IC_RIGHT (ic);
3614 operand *result = IC_RESULT (ic);
3616 /* assign the amsops */
3617 aopOp (left, ic, FALSE);
3618 aopOp (right, ic, FALSE);
3619 aopOp (result, ic, TRUE);
3621 /* special cases first */
3623 if (AOP_TYPE (left) == AOP_CRY &&
3624 AOP_TYPE (right) == AOP_CRY)
3626 genModbits (left, right, result);
3630 /* if both are of size == 1 */
3631 if (AOP_SIZE (left) == 1 &&
3632 AOP_SIZE (right) == 1)
3634 genModOneByte (left, right, result);
3638 /* should have been converted to function call */
3642 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3643 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3644 freeAsmop (result, NULL, ic, TRUE);
3647 /*-----------------------------------------------------------------*/
3648 /* genIfxJump :- will create a jump depending on the ifx */
3649 /*-----------------------------------------------------------------*/
3651 genIfxJump (iCode * ic, char *jval)
3654 symbol *tlbl = newiTempLabel (NULL);
3657 /* if true label then we jump if condition
3661 jlbl = IC_TRUE (ic);
3662 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3663 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3667 /* false label is present */
3668 jlbl = IC_FALSE (ic);
3669 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3670 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3672 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3673 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3675 emitcode (inst, "%05d$", tlbl->key + 100);
3676 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3677 emitcode ("", "%05d$:", tlbl->key + 100);
3679 /* mark the icode as generated */
3683 /*-----------------------------------------------------------------*/
3684 /* genCmp :- greater or less than comparison */
3685 /*-----------------------------------------------------------------*/
3687 genCmp (operand * left, operand * right,
3688 operand * result, iCode * ifx, int sign)
3690 int size, offset = 0;
3691 unsigned long lit = 0L;
3693 /* if left & right are bit variables */
3694 if (AOP_TYPE (left) == AOP_CRY &&
3695 AOP_TYPE (right) == AOP_CRY)
3697 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3698 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3702 /* subtract right from left if at the
3703 end the carry flag is set then we know that
3704 left is greater than right */
3705 size = max (AOP_SIZE (left), AOP_SIZE (right));
3707 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3708 if ((size == 1) && !sign &&
3709 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3711 symbol *lbl = newiTempLabel (NULL);
3712 emitcode ("cjne", "%s,%s,%05d$",
3713 aopGet (AOP (left), offset, FALSE, FALSE),
3714 aopGet (AOP (right), offset, FALSE, FALSE),
3716 emitcode ("", "%05d$:", lbl->key + 100);
3720 if (AOP_TYPE (right) == AOP_LIT)
3722 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3723 /* optimize if(x < 0) or if(x >= 0) */
3732 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3733 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3735 genIfxJump (ifx, "acc.7");
3739 emitcode ("rlc", "a");
3747 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3748 if (sign && size == 0)
3750 emitcode ("xrl", "a,#0x80");
3751 if (AOP_TYPE (right) == AOP_LIT)
3753 unsigned long lit = (unsigned long)
3754 floatFromVal (AOP (right)->aopu.aop_lit);
3755 emitcode ("subb", "a,#0x%02x",
3756 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3760 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3761 emitcode ("xrl", "b,#0x80");
3762 emitcode ("subb", "a,b");
3766 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3772 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3778 /* if the result is used in the next
3779 ifx conditional branch then generate
3780 code a little differently */
3782 genIfxJump (ifx, "c");
3785 /* leave the result in acc */
3789 /*-----------------------------------------------------------------*/
3790 /* genCmpGt :- greater than comparison */
3791 /*-----------------------------------------------------------------*/
3793 genCmpGt (iCode * ic, iCode * ifx)
3795 operand *left, *right, *result;
3796 sym_link *letype, *retype;
3799 left = IC_LEFT (ic);
3800 right = IC_RIGHT (ic);
3801 result = IC_RESULT (ic);
3803 letype = getSpec (operandType (left));
3804 retype = getSpec (operandType (right));
3805 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3806 /* assign the amsops */
3807 aopOp (left, ic, FALSE);
3808 aopOp (right, ic, FALSE);
3809 aopOp (result, ic, TRUE);
3811 genCmp (right, left, result, ifx, sign);
3813 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (result, NULL, ic, TRUE);
3818 /*-----------------------------------------------------------------*/
3819 /* genCmpLt - less than comparisons */
3820 /*-----------------------------------------------------------------*/
3822 genCmpLt (iCode * ic, iCode * ifx)
3824 operand *left, *right, *result;
3825 sym_link *letype, *retype;
3828 left = IC_LEFT (ic);
3829 right = IC_RIGHT (ic);
3830 result = IC_RESULT (ic);
3832 letype = getSpec (operandType (left));
3833 retype = getSpec (operandType (right));
3834 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3836 /* assign the amsops */
3837 aopOp (left, ic, FALSE);
3838 aopOp (right, ic, FALSE);
3839 aopOp (result, ic, TRUE);
3841 genCmp (left, right, result, ifx, sign);
3843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3845 freeAsmop (result, NULL, ic, TRUE);
3848 /*-----------------------------------------------------------------*/
3849 /* gencjneshort - compare and jump if not equal */
3850 /*-----------------------------------------------------------------*/
3852 gencjneshort (operand * left, operand * right, symbol * lbl)
3854 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3856 unsigned long lit = 0L;
3858 /* if the left side is a literal or
3859 if the right is in a pointer register and left
3861 if ((AOP_TYPE (left) == AOP_LIT) ||
3862 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3868 if (AOP_TYPE (right) == AOP_LIT)
3869 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3871 /* if the right side is a literal then anything goes */
3872 if (AOP_TYPE (right) == AOP_LIT &&
3873 AOP_TYPE (left) != AOP_DIR)
3877 emitcode ("cjne", "%s,%s,%05d$",
3878 aopGet (AOP (left), offset, FALSE, FALSE),
3879 aopGet (AOP (right), offset, FALSE, FALSE),
3885 /* if the right side is in a register or in direct space or
3886 if the left is a pointer register & right is not */
3887 else if (AOP_TYPE (right) == AOP_REG ||
3888 AOP_TYPE (right) == AOP_DIR ||
3889 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3890 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3894 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3895 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3896 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3897 emitcode ("jnz", "%05d$", lbl->key + 100);
3899 emitcode ("cjne", "a,%s,%05d$",
3900 aopGet (AOP (right), offset, FALSE, TRUE),
3907 /* right is a pointer reg need both a & b */
3910 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3911 if (strcmp (l, "b"))
3912 emitcode ("mov", "b,%s", l);
3913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3914 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3920 /*-----------------------------------------------------------------*/
3921 /* gencjne - compare and jump if not equal */
3922 /*-----------------------------------------------------------------*/
3924 gencjne (operand * left, operand * right, symbol * lbl)
3926 symbol *tlbl = newiTempLabel (NULL);
3928 gencjneshort (left, right, lbl);
3930 emitcode ("mov", "a,%s", one);
3931 emitcode ("sjmp", "%05d$", tlbl->key + 100);
3932 emitcode ("", "%05d$:", lbl->key + 100);
3933 emitcode ("clr", "a");
3934 emitcode ("", "%05d$:", tlbl->key + 100);
3937 /*-----------------------------------------------------------------*/
3938 /* genCmpEq - generates code for equal to */
3939 /*-----------------------------------------------------------------*/
3941 genCmpEq (iCode * ic, iCode * ifx)
3943 operand *left, *right, *result;
3945 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3946 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3947 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3949 /* if literal, literal on the right or
3950 if the right is in a pointer register and left
3952 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3953 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3955 operand *t = IC_RIGHT (ic);
3956 IC_RIGHT (ic) = IC_LEFT (ic);
3960 if (ifx && !AOP_SIZE (result))
3963 /* if they are both bit variables */
3964 if (AOP_TYPE (left) == AOP_CRY &&
3965 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3967 if (AOP_TYPE (right) == AOP_LIT)
3969 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3972 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3973 emitcode ("cpl", "c");
3977 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3981 emitcode ("clr", "c");
3983 /* AOP_TYPE(right) == AOP_CRY */
3987 symbol *lbl = newiTempLabel (NULL);
3988 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3989 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3990 emitcode ("cpl", "c");
3991 emitcode ("", "%05d$:", (lbl->key + 100));
3993 /* if true label then we jump if condition
3995 tlbl = newiTempLabel (NULL);
3998 emitcode ("jnc", "%05d$", tlbl->key + 100);
3999 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4003 emitcode ("jc", "%05d$", tlbl->key + 100);
4004 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4006 emitcode ("", "%05d$:", tlbl->key + 100);
4010 tlbl = newiTempLabel (NULL);
4011 gencjneshort (left, right, tlbl);
4014 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4015 emitcode ("", "%05d$:", tlbl->key + 100);
4019 symbol *lbl = newiTempLabel (NULL);
4020 emitcode ("sjmp", "%05d$", lbl->key + 100);
4021 emitcode ("", "%05d$:", tlbl->key + 100);
4022 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4023 emitcode ("", "%05d$:", lbl->key + 100);
4026 /* mark the icode as generated */
4031 /* if they are both bit variables */
4032 if (AOP_TYPE (left) == AOP_CRY &&
4033 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4035 if (AOP_TYPE (right) == AOP_LIT)
4037 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4041 emitcode ("cpl", "c");
4045 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4049 emitcode ("clr", "c");
4051 /* AOP_TYPE(right) == AOP_CRY */
4055 symbol *lbl = newiTempLabel (NULL);
4056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4057 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4058 emitcode ("cpl", "c");
4059 emitcode ("", "%05d$:", (lbl->key + 100));
4062 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4069 genIfxJump (ifx, "c");
4072 /* if the result is used in an arithmetic operation
4073 then put the result in place */
4078 gencjne (left, right, newiTempLabel (NULL));
4079 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4081 aopPut (AOP (result), "a", 0);
4086 genIfxJump (ifx, "a");
4089 /* if the result is used in an arithmetic operation
4090 then put the result in place */
4091 if (AOP_TYPE (result) != AOP_CRY)
4093 /* leave the result in acc */
4097 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4098 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4099 freeAsmop (result, NULL, ic, TRUE);
4102 /*-----------------------------------------------------------------*/
4103 /* ifxForOp - returns the icode containing the ifx for operand */
4104 /*-----------------------------------------------------------------*/
4106 ifxForOp (operand * op, iCode * ic)
4108 /* if true symbol then needs to be assigned */
4109 if (IS_TRUE_SYMOP (op))
4112 /* if this has register type condition and
4113 the next instruction is ifx with the same operand
4114 and live to of the operand is upto the ifx only then */
4116 ic->next->op == IFX &&
4117 IC_COND (ic->next)->key == op->key &&
4118 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4123 /*-----------------------------------------------------------------*/
4124 /* genAndOp - for && operation */
4125 /*-----------------------------------------------------------------*/
4127 genAndOp (iCode * ic)
4129 operand *left, *right, *result;
4132 /* note here that && operations that are in an
4133 if statement are taken away by backPatchLabels
4134 only those used in arthmetic operations remain */
4135 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4136 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4137 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4139 /* if both are bit variables */
4140 if (AOP_TYPE (left) == AOP_CRY &&
4141 AOP_TYPE (right) == AOP_CRY)
4143 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4144 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4149 tlbl = newiTempLabel (NULL);
4151 emitcode ("jz", "%05d$", tlbl->key + 100);
4153 emitcode ("", "%05d$:", tlbl->key + 100);
4157 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4158 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4159 freeAsmop (result, NULL, ic, TRUE);
4163 /*-----------------------------------------------------------------*/
4164 /* genOrOp - for || operation */
4165 /*-----------------------------------------------------------------*/
4167 genOrOp (iCode * ic)
4169 operand *left, *right, *result;
4172 /* note here that || operations that are in an
4173 if statement are taken away by backPatchLabels
4174 only those used in arthmetic operations remain */
4175 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4176 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4177 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4179 /* if both are bit variables */
4180 if (AOP_TYPE (left) == AOP_CRY &&
4181 AOP_TYPE (right) == AOP_CRY)
4183 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4184 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4189 tlbl = newiTempLabel (NULL);
4191 emitcode ("jnz", "%05d$", tlbl->key + 100);
4193 emitcode ("", "%05d$:", tlbl->key + 100);
4197 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4198 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4199 freeAsmop (result, NULL, ic, TRUE);
4202 /*-----------------------------------------------------------------*/
4203 /* isLiteralBit - test if lit == 2^n */
4204 /*-----------------------------------------------------------------*/
4206 isLiteralBit (unsigned long lit)
4208 unsigned long pw[32] =
4209 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4210 0x100L, 0x200L, 0x400L, 0x800L,
4211 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4212 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4213 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4214 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4215 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4218 for (idx = 0; idx < 32; idx++)
4224 /*-----------------------------------------------------------------*/
4225 /* continueIfTrue - */
4226 /*-----------------------------------------------------------------*/
4228 continueIfTrue (iCode * ic)
4231 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4235 /*-----------------------------------------------------------------*/
4237 /*-----------------------------------------------------------------*/
4239 jumpIfTrue (iCode * ic)
4242 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4246 /*-----------------------------------------------------------------*/
4247 /* jmpTrueOrFalse - */
4248 /*-----------------------------------------------------------------*/
4250 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4252 // ugly but optimized by peephole
4255 symbol *nlbl = newiTempLabel (NULL);
4256 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4257 emitcode ("", "%05d$:", tlbl->key + 100);
4258 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4259 emitcode ("", "%05d$:", nlbl->key + 100);
4263 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4264 emitcode ("", "%05d$:", tlbl->key + 100);
4269 /*-----------------------------------------------------------------*/
4270 /* genAnd - code for and */
4271 /*-----------------------------------------------------------------*/
4273 genAnd (iCode * ic, iCode * ifx)
4275 operand *left, *right, *result;
4276 int size, offset = 0;
4277 unsigned long lit = 0L;
4281 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4282 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4283 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4286 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4288 AOP_TYPE (left), AOP_TYPE (right));
4289 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4291 AOP_SIZE (left), AOP_SIZE (right));
4294 /* if left is a literal & right is not then exchange them */
4295 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4296 AOP_NEEDSACC (left))
4298 operand *tmp = right;
4303 /* if result = right then exchange them */
4304 if (sameRegs (AOP (result), AOP (right)))
4306 operand *tmp = right;
4311 /* if right is bit then exchange them */
4312 if (AOP_TYPE (right) == AOP_CRY &&
4313 AOP_TYPE (left) != AOP_CRY)
4315 operand *tmp = right;
4319 if (AOP_TYPE (right) == AOP_LIT)
4320 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4322 size = AOP_SIZE (result);
4325 // result = bit & yy;
4326 if (AOP_TYPE (left) == AOP_CRY)
4328 // c = bit & literal;
4329 if (AOP_TYPE (right) == AOP_LIT)
4333 if (size && sameRegs (AOP (result), AOP (left)))
4336 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4341 if (size && (AOP_TYPE (result) == AOP_CRY))
4343 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4346 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4351 emitcode ("clr", "c");
4356 if (AOP_TYPE (right) == AOP_CRY)
4359 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4360 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4365 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4367 emitcode ("rrc", "a");
4368 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4376 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4377 genIfxJump (ifx, "c");
4381 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4382 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4383 if ((AOP_TYPE (right) == AOP_LIT) &&
4384 (AOP_TYPE (result) == AOP_CRY) &&
4385 (AOP_TYPE (left) != AOP_CRY))
4387 int posbit = isLiteralBit (lit);
4392 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4395 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4401 sprintf (buffer, "acc.%d", posbit & 0x07);
4402 genIfxJump (ifx, buffer);
4409 symbol *tlbl = newiTempLabel (NULL);
4410 int sizel = AOP_SIZE (left);
4412 emitcode ("setb", "c");
4415 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4417 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4419 if ((posbit = isLiteralBit (bytelit)) != 0)
4420 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4423 if (bytelit != 0x0FFL)
4424 emitcode ("anl", "a,%s",
4425 aopGet (AOP (right), offset, FALSE, TRUE));
4426 emitcode ("jnz", "%05d$", tlbl->key + 100);
4431 // bit = left & literal
4434 emitcode ("clr", "c");
4435 emitcode ("", "%05d$:", tlbl->key + 100);
4437 // if(left & literal)
4441 jmpTrueOrFalse (ifx, tlbl);
4449 /* if left is same as result */
4450 if (sameRegs (AOP (result), AOP (left)))
4452 for (; size--; offset++)
4454 if (AOP_TYPE (right) == AOP_LIT)
4456 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4458 else if (bytelit == 0)
4459 aopPut (AOP (result), zero, offset);
4460 else if (IS_AOP_PREG (result))
4462 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4463 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4464 aopPut (AOP (result), "a", offset);
4467 emitcode ("anl", "%s,%s",
4468 aopGet (AOP (left), offset, FALSE, TRUE),
4469 aopGet (AOP (right), offset, FALSE, FALSE));
4473 if (AOP_TYPE (left) == AOP_ACC)
4474 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4477 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4478 if (IS_AOP_PREG (result))
4480 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4481 aopPut (AOP (result), "a", offset);
4485 emitcode ("anl", "%s,a",
4486 aopGet (AOP (left), offset, FALSE, TRUE));
4493 // left & result in different registers
4494 if (AOP_TYPE (result) == AOP_CRY)
4497 // if(size), result in bit
4498 // if(!size && ifx), conditional oper: if(left & right)
4499 symbol *tlbl = newiTempLabel (NULL);
4500 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4502 emitcode ("setb", "c");
4505 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4506 emitcode ("anl", "a,%s",
4507 aopGet (AOP (left), offset, FALSE, FALSE));
4508 emitcode ("jnz", "%05d$", tlbl->key + 100);
4514 emitcode ("", "%05d$:", tlbl->key + 100);
4518 jmpTrueOrFalse (ifx, tlbl);
4522 for (; (size--); offset++)
4525 // result = left & right
4526 if (AOP_TYPE (right) == AOP_LIT)
4528 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4530 aopPut (AOP (result),
4531 aopGet (AOP (left), offset, FALSE, FALSE),
4535 else if (bytelit == 0)
4537 aopPut (AOP (result), zero, offset);
4541 // faster than result <- left, anl result,right
4542 // and better if result is SFR
4543 if (AOP_TYPE (left) == AOP_ACC)
4544 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4547 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4548 emitcode ("anl", "a,%s",
4549 aopGet (AOP (left), offset, FALSE, FALSE));
4551 aopPut (AOP (result), "a", offset);
4557 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4558 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4559 freeAsmop (result, NULL, ic, TRUE);
4562 /*-----------------------------------------------------------------*/
4563 /* genOr - code for or */
4564 /*-----------------------------------------------------------------*/
4566 genOr (iCode * ic, iCode * ifx)
4568 operand *left, *right, *result;
4569 int size, offset = 0;
4570 unsigned long lit = 0L;
4572 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4573 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4574 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4577 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4579 AOP_TYPE (left), AOP_TYPE (right));
4580 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4582 AOP_SIZE (left), AOP_SIZE (right));
4585 /* if left is a literal & right is not then exchange them */
4586 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4587 AOP_NEEDSACC (left))
4589 operand *tmp = right;
4594 /* if result = right then exchange them */
4595 if (sameRegs (AOP (result), AOP (right)))
4597 operand *tmp = right;
4602 /* if right is bit then exchange them */
4603 if (AOP_TYPE (right) == AOP_CRY &&
4604 AOP_TYPE (left) != AOP_CRY)
4606 operand *tmp = right;
4610 if (AOP_TYPE (right) == AOP_LIT)
4611 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4613 size = AOP_SIZE (result);
4617 if (AOP_TYPE (left) == AOP_CRY)
4619 if (AOP_TYPE (right) == AOP_LIT)
4621 // c = bit & literal;
4624 // lit != 0 => result = 1
4625 if (AOP_TYPE (result) == AOP_CRY)
4628 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4630 continueIfTrue (ifx);
4633 emitcode ("setb", "c");
4637 // lit == 0 => result = left
4638 if (size && sameRegs (AOP (result), AOP (left)))
4640 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4645 if (AOP_TYPE (right) == AOP_CRY)
4648 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4649 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4654 symbol *tlbl = newiTempLabel (NULL);
4655 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4656 emitcode ("setb", "c");
4657 emitcode ("jb", "%s,%05d$",
4658 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4660 emitcode ("jnz", "%05d$", tlbl->key + 100);
4661 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4663 jmpTrueOrFalse (ifx, tlbl);
4669 emitcode ("", "%05d$:", tlbl->key + 100);
4678 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4679 genIfxJump (ifx, "c");
4683 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4684 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4685 if ((AOP_TYPE (right) == AOP_LIT) &&
4686 (AOP_TYPE (result) == AOP_CRY) &&
4687 (AOP_TYPE (left) != AOP_CRY))
4693 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4695 continueIfTrue (ifx);
4700 // lit = 0, result = boolean(left)
4702 emitcode ("setb", "c");
4706 symbol *tlbl = newiTempLabel (NULL);
4707 emitcode ("jnz", "%05d$", tlbl->key + 100);
4709 emitcode ("", "%05d$:", tlbl->key + 100);
4713 genIfxJump (ifx, "a");
4721 /* if left is same as result */
4722 if (sameRegs (AOP (result), AOP (left)))
4724 for (; size--; offset++)
4726 if (AOP_TYPE (right) == AOP_LIT)
4728 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4730 else if (IS_AOP_PREG (left))
4732 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4733 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4734 aopPut (AOP (result), "a", offset);
4737 emitcode ("orl", "%s,%s",
4738 aopGet (AOP (left), offset, FALSE, TRUE),
4739 aopGet (AOP (right), offset, FALSE, FALSE));
4743 if (AOP_TYPE (left) == AOP_ACC)
4744 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4747 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4748 if (IS_AOP_PREG (left))
4750 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4751 aopPut (AOP (result), "a", offset);
4754 emitcode ("orl", "%s,a",
4755 aopGet (AOP (left), offset, FALSE, TRUE));
4762 // left & result in different registers
4763 if (AOP_TYPE (result) == AOP_CRY)
4766 // if(size), result in bit
4767 // if(!size && ifx), conditional oper: if(left | right)
4768 symbol *tlbl = newiTempLabel (NULL);
4769 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4771 emitcode ("setb", "c");
4774 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4775 emitcode ("orl", "a,%s",
4776 aopGet (AOP (left), offset, FALSE, FALSE));
4777 emitcode ("jnz", "%05d$", tlbl->key + 100);
4783 emitcode ("", "%05d$:", tlbl->key + 100);
4787 jmpTrueOrFalse (ifx, tlbl);
4790 for (; (size--); offset++)
4793 // result = left & right
4794 if (AOP_TYPE (right) == AOP_LIT)
4796 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4798 aopPut (AOP (result),
4799 aopGet (AOP (left), offset, FALSE, FALSE),
4804 // faster than result <- left, anl result,right
4805 // and better if result is SFR
4806 if (AOP_TYPE (left) == AOP_ACC)
4807 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4810 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4811 emitcode ("orl", "a,%s",
4812 aopGet (AOP (left), offset, FALSE, FALSE));
4814 aopPut (AOP (result), "a", offset);
4819 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4820 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4821 freeAsmop (result, NULL, ic, TRUE);
4824 /*-----------------------------------------------------------------*/
4825 /* genXor - code for xclusive or */
4826 /*-----------------------------------------------------------------*/
4828 genXor (iCode * ic, iCode * ifx)
4830 operand *left, *right, *result;
4831 int size, offset = 0;
4832 unsigned long lit = 0L;
4834 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4835 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4836 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4839 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4841 AOP_TYPE (left), AOP_TYPE (right));
4842 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4844 AOP_SIZE (left), AOP_SIZE (right));
4847 /* if left is a literal & right is not ||
4848 if left needs acc & right does not */
4849 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4850 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4852 operand *tmp = right;
4857 /* if result = right then exchange them */
4858 if (sameRegs (AOP (result), AOP (right)))
4860 operand *tmp = right;
4865 /* if right is bit then exchange them */
4866 if (AOP_TYPE (right) == AOP_CRY &&
4867 AOP_TYPE (left) != AOP_CRY)
4869 operand *tmp = right;
4873 if (AOP_TYPE (right) == AOP_LIT)
4874 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4876 size = AOP_SIZE (result);
4880 if (AOP_TYPE (left) == AOP_CRY)
4882 if (AOP_TYPE (right) == AOP_LIT)
4884 // c = bit & literal;
4887 // lit>>1 != 0 => result = 1
4888 if (AOP_TYPE (result) == AOP_CRY)
4891 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4893 continueIfTrue (ifx);
4896 emitcode ("setb", "c");
4903 // lit == 0, result = left
4904 if (size && sameRegs (AOP (result), AOP (left)))
4906 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4910 // lit == 1, result = not(left)
4911 if (size && sameRegs (AOP (result), AOP (left)))
4913 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4918 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4919 emitcode ("cpl", "c");
4928 symbol *tlbl = newiTempLabel (NULL);
4929 if (AOP_TYPE (right) == AOP_CRY)
4932 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4936 int sizer = AOP_SIZE (right);
4938 // if val>>1 != 0, result = 1
4939 emitcode ("setb", "c");
4942 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4944 // test the msb of the lsb
4945 emitcode ("anl", "a,#0xfe");
4946 emitcode ("jnz", "%05d$", tlbl->key + 100);
4950 emitcode ("rrc", "a");
4952 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4953 emitcode ("cpl", "c");
4954 emitcode ("", "%05d$:", (tlbl->key + 100));
4961 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4962 genIfxJump (ifx, "c");
4966 if (sameRegs (AOP (result), AOP (left)))
4968 /* if left is same as result */
4969 for (; size--; offset++)
4971 if (AOP_TYPE (right) == AOP_LIT)
4973 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4975 else if (IS_AOP_PREG (left))
4977 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4979 aopPut (AOP (result), "a", offset);
4982 emitcode ("xrl", "%s,%s",
4983 aopGet (AOP (left), offset, FALSE, TRUE),
4984 aopGet (AOP (right), offset, FALSE, FALSE));
4988 if (AOP_TYPE (left) == AOP_ACC)
4989 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4992 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4993 if (IS_AOP_PREG (left))
4995 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4996 aopPut (AOP (result), "a", offset);
4999 emitcode ("xrl", "%s,a",
5000 aopGet (AOP (left), offset, FALSE, TRUE));
5007 // left & result in different registers
5008 if (AOP_TYPE (result) == AOP_CRY)
5011 // if(size), result in bit
5012 // if(!size && ifx), conditional oper: if(left ^ right)
5013 symbol *tlbl = newiTempLabel (NULL);
5014 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5016 emitcode ("setb", "c");
5019 if ((AOP_TYPE (right) == AOP_LIT) &&
5020 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5022 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5026 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5027 emitcode ("xrl", "a,%s",
5028 aopGet (AOP (left), offset, FALSE, FALSE));
5030 emitcode ("jnz", "%05d$", tlbl->key + 100);
5036 emitcode ("", "%05d$:", tlbl->key + 100);
5040 jmpTrueOrFalse (ifx, tlbl);
5043 for (; (size--); offset++)
5046 // result = left & right
5047 if (AOP_TYPE (right) == AOP_LIT)
5049 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5051 aopPut (AOP (result),
5052 aopGet (AOP (left), offset, FALSE, FALSE),
5057 // faster than result <- left, anl result,right
5058 // and better if result is SFR
5059 if (AOP_TYPE (left) == AOP_ACC)
5060 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5063 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5064 emitcode ("xrl", "a,%s",
5065 aopGet (AOP (left), offset, FALSE, TRUE));
5067 aopPut (AOP (result), "a", offset);
5072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5073 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5074 freeAsmop (result, NULL, ic, TRUE);
5077 /*-----------------------------------------------------------------*/
5078 /* genInline - write the inline code out */
5079 /*-----------------------------------------------------------------*/
5081 genInline (iCode * ic)
5083 char buffer[MAX_INLINEASM];
5087 _G.inLine += (!options.asmpeep);
5088 strcpy (buffer, IC_INLINE (ic));
5090 /* emit each line as a code */
5115 /* emitcode("",buffer); */
5116 _G.inLine -= (!options.asmpeep);
5119 /*-----------------------------------------------------------------*/
5120 /* genRRC - rotate right with carry */
5121 /*-----------------------------------------------------------------*/
5125 operand *left, *result;
5126 int size, offset = 0;
5129 /* rotate right with carry */
5130 left = IC_LEFT (ic);
5131 result = IC_RESULT (ic);
5132 aopOp (left, ic, FALSE);
5133 aopOp (result, ic, FALSE);
5135 /* move it to the result */
5136 size = AOP_SIZE (result);
5141 l = aopGet (AOP (left), offset, FALSE, FALSE);
5143 emitcode ("rrc", "a");
5144 if (AOP_SIZE (result) > 1)
5145 aopPut (AOP (result), "a", offset--);
5147 /* now we need to put the carry into the
5148 highest order byte of the result */
5149 if (AOP_SIZE (result) > 1)
5151 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5154 emitcode ("mov", "acc.7,c");
5155 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5156 freeAsmop (left, NULL, ic, TRUE);
5157 freeAsmop (result, NULL, ic, TRUE);
5160 /*-----------------------------------------------------------------*/
5161 /* genRLC - generate code for rotate left with carry */
5162 /*-----------------------------------------------------------------*/
5166 operand *left, *result;
5167 int size, offset = 0;
5170 /* rotate right with carry */
5171 left = IC_LEFT (ic);
5172 result = IC_RESULT (ic);
5173 aopOp (left, ic, FALSE);
5174 aopOp (result, ic, FALSE);
5176 /* move it to the result */
5177 size = AOP_SIZE (result);
5181 l = aopGet (AOP (left), offset, FALSE, FALSE);
5183 emitcode ("add", "a,acc");
5184 if (AOP_SIZE (result) > 1)
5185 aopPut (AOP (result), "a", offset++);
5188 l = aopGet (AOP (left), offset, FALSE, FALSE);
5190 emitcode ("rlc", "a");
5191 if (AOP_SIZE (result) > 1)
5192 aopPut (AOP (result), "a", offset++);
5195 /* now we need to put the carry into the
5196 highest order byte of the result */
5197 if (AOP_SIZE (result) > 1)
5199 l = aopGet (AOP (result), 0, FALSE, FALSE);
5202 emitcode ("mov", "acc.0,c");
5203 aopPut (AOP (result), "a", 0);
5204 freeAsmop (left, NULL, ic, TRUE);
5205 freeAsmop (result, NULL, ic, TRUE);
5208 /*-----------------------------------------------------------------*/
5209 /* genGetHbit - generates code get highest order bit */
5210 /*-----------------------------------------------------------------*/
5212 genGetHbit (iCode * ic)
5214 operand *left, *result;
5215 left = IC_LEFT (ic);
5216 result = IC_RESULT (ic);
5217 aopOp (left, ic, FALSE);
5218 aopOp (result, ic, FALSE);
5220 /* get the highest order byte into a */
5221 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5222 if (AOP_TYPE (result) == AOP_CRY)
5224 emitcode ("rlc", "a");
5229 emitcode ("rl", "a");
5230 emitcode ("anl", "a,#0x01");
5235 freeAsmop (left, NULL, ic, TRUE);
5236 freeAsmop (result, NULL, ic, TRUE);
5239 /*-----------------------------------------------------------------*/
5240 /* AccRol - rotate left accumulator by known count */
5241 /*-----------------------------------------------------------------*/
5243 AccRol (int shCount)
5245 shCount &= 0x0007; // shCount : 0..7
5252 emitcode ("rl", "a");
5255 emitcode ("rl", "a");
5256 emitcode ("rl", "a");
5259 emitcode ("swap", "a");
5260 emitcode ("rr", "a");
5263 emitcode ("swap", "a");
5266 emitcode ("swap", "a");
5267 emitcode ("rl", "a");
5270 emitcode ("rr", "a");
5271 emitcode ("rr", "a");
5274 emitcode ("rr", "a");
5279 /*-----------------------------------------------------------------*/
5280 /* AccLsh - left shift accumulator by known count */
5281 /*-----------------------------------------------------------------*/
5283 AccLsh (int shCount)
5288 emitcode ("add", "a,acc");
5289 else if (shCount == 2)
5291 emitcode ("add", "a,acc");
5292 emitcode ("add", "a,acc");
5296 /* rotate left accumulator */
5298 /* and kill the lower order bits */
5299 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5304 /*-----------------------------------------------------------------*/
5305 /* AccRsh - right shift accumulator by known count */
5306 /*-----------------------------------------------------------------*/
5308 AccRsh (int shCount)
5315 emitcode ("rrc", "a");
5319 /* rotate right accumulator */
5320 AccRol (8 - shCount);
5321 /* and kill the higher order bits */
5322 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5327 /*-----------------------------------------------------------------*/
5328 /* AccSRsh - signed right shift accumulator by known count */
5329 /*-----------------------------------------------------------------*/
5331 AccSRsh (int shCount)
5338 emitcode ("mov", "c,acc.7");
5339 emitcode ("rrc", "a");
5341 else if (shCount == 2)
5343 emitcode ("mov", "c,acc.7");
5344 emitcode ("rrc", "a");
5345 emitcode ("mov", "c,acc.7");
5346 emitcode ("rrc", "a");
5350 tlbl = newiTempLabel (NULL);
5351 /* rotate right accumulator */
5352 AccRol (8 - shCount);
5353 /* and kill the higher order bits */
5354 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5355 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5356 emitcode ("orl", "a,#0x%02x",
5357 (unsigned char) ~SRMask[shCount]);
5358 emitcode ("", "%05d$:", tlbl->key + 100);
5363 /*-----------------------------------------------------------------*/
5364 /* shiftR1Left2Result - shift right one byte from left to result */
5365 /*-----------------------------------------------------------------*/
5367 shiftR1Left2Result (operand * left, int offl,
5368 operand * result, int offr,
5369 int shCount, int sign)
5371 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5372 /* shift right accumulator */
5377 aopPut (AOP (result), "a", offr);
5380 /*-----------------------------------------------------------------*/
5381 /* shiftL1Left2Result - shift left one byte from left to result */
5382 /*-----------------------------------------------------------------*/
5384 shiftL1Left2Result (operand * left, int offl,
5385 operand * result, int offr, int shCount)
5388 l = aopGet (AOP (left), offl, FALSE, FALSE);
5390 /* shift left accumulator */
5392 aopPut (AOP (result), "a", offr);
5395 /*-----------------------------------------------------------------*/
5396 /* movLeft2Result - move byte from left to result */
5397 /*-----------------------------------------------------------------*/
5399 movLeft2Result (operand * left, int offl,
5400 operand * result, int offr, int sign)
5403 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5405 l = aopGet (AOP (left), offl, FALSE, FALSE);
5407 if (*l == '@' && (IS_AOP_PREG (result)))
5409 emitcode ("mov", "a,%s", l);
5410 aopPut (AOP (result), "a", offr);
5415 aopPut (AOP (result), l, offr);
5418 /* MSB sign in acc.7 ! */
5419 if (getDataSize (left) == offl + 1)
5421 emitcode ("mov", "a,%s", l);
5422 aopPut (AOP (result), "a", offr);
5429 /*-----------------------------------------------------------------*/
5430 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5431 /*-----------------------------------------------------------------*/
5435 emitcode ("rrc", "a");
5436 emitcode ("xch", "a,%s", x);
5437 emitcode ("rrc", "a");
5438 emitcode ("xch", "a,%s", x);
5441 /*-----------------------------------------------------------------*/
5442 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5443 /*-----------------------------------------------------------------*/
5447 emitcode ("xch", "a,%s", x);
5448 emitcode ("rlc", "a");
5449 emitcode ("xch", "a,%s", x);
5450 emitcode ("rlc", "a");
5453 /*-----------------------------------------------------------------*/
5454 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5455 /*-----------------------------------------------------------------*/
5459 emitcode ("xch", "a,%s", x);
5460 emitcode ("add", "a,acc");
5461 emitcode ("xch", "a,%s", x);
5462 emitcode ("rlc", "a");
5465 /*-----------------------------------------------------------------*/
5466 /* AccAXLsh - left shift a:x by known count (0..7) */
5467 /*-----------------------------------------------------------------*/
5469 AccAXLsh (char *x, int shCount)
5484 case 5: // AAAAABBB:CCCCCDDD
5486 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5488 emitcode ("anl", "a,#0x%02x",
5489 SLMask[shCount]); // BBB00000:CCCCCDDD
5491 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5493 AccRol (shCount); // DDDCCCCC:BBB00000
5495 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5497 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5499 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5501 emitcode ("anl", "a,#0x%02x",
5502 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5504 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5506 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5509 case 6: // AAAAAABB:CCCCCCDD
5511 emitcode ("anl", "a,#0x%02x",
5512 SRMask[shCount]); // 000000BB:CCCCCCDD
5514 emitcode ("mov", "c,acc.0"); // c = B
5516 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5518 AccAXRrl1 (x); // BCCCCCCD:D000000B
5520 AccAXRrl1 (x); // BBCCCCCC:DD000000
5523 case 7: // a:x <<= 7
5525 emitcode ("anl", "a,#0x%02x",
5526 SRMask[shCount]); // 0000000B:CCCCCCCD
5528 emitcode ("mov", "c,acc.0"); // c = B
5530 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5532 AccAXRrl1 (x); // BCCCCCCC:D0000000
5540 /*-----------------------------------------------------------------*/
5541 /* AccAXRsh - right shift a:x known count (0..7) */
5542 /*-----------------------------------------------------------------*/
5544 AccAXRsh (char *x, int shCount)
5552 AccAXRrl1 (x); // 0->a:x
5557 AccAXRrl1 (x); // 0->a:x
5560 AccAXRrl1 (x); // 0->a:x
5565 case 5: // AAAAABBB:CCCCCDDD = a:x
5567 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5569 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5571 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5573 emitcode ("anl", "a,#0x%02x",
5574 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5576 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5578 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5580 emitcode ("anl", "a,#0x%02x",
5581 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5583 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5585 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5587 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5590 case 6: // AABBBBBB:CCDDDDDD
5592 emitcode ("mov", "c,acc.7");
5593 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5595 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5597 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5599 emitcode ("anl", "a,#0x%02x",
5600 SRMask[shCount]); // 000000AA:BBBBBBCC
5603 case 7: // ABBBBBBB:CDDDDDDD
5605 emitcode ("mov", "c,acc.7"); // c = A
5607 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5609 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5611 emitcode ("anl", "a,#0x%02x",
5612 SRMask[shCount]); // 0000000A:BBBBBBBC
5620 /*-----------------------------------------------------------------*/
5621 /* AccAXRshS - right shift signed a:x known count (0..7) */
5622 /*-----------------------------------------------------------------*/
5624 AccAXRshS (char *x, int shCount)
5632 emitcode ("mov", "c,acc.7");
5633 AccAXRrl1 (x); // s->a:x
5637 emitcode ("mov", "c,acc.7");
5638 AccAXRrl1 (x); // s->a:x
5640 emitcode ("mov", "c,acc.7");
5641 AccAXRrl1 (x); // s->a:x
5646 case 5: // AAAAABBB:CCCCCDDD = a:x
5648 tlbl = newiTempLabel (NULL);
5649 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5651 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5653 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5655 emitcode ("anl", "a,#0x%02x",
5656 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5658 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5660 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5662 emitcode ("anl", "a,#0x%02x",
5663 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5665 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5667 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5669 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5671 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5672 emitcode ("orl", "a,#0x%02x",
5673 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5675 emitcode ("", "%05d$:", tlbl->key + 100);
5676 break; // SSSSAAAA:BBBCCCCC
5678 case 6: // AABBBBBB:CCDDDDDD
5680 tlbl = newiTempLabel (NULL);
5681 emitcode ("mov", "c,acc.7");
5682 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5684 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5686 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5688 emitcode ("anl", "a,#0x%02x",
5689 SRMask[shCount]); // 000000AA:BBBBBBCC
5691 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5692 emitcode ("orl", "a,#0x%02x",
5693 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5695 emitcode ("", "%05d$:", tlbl->key + 100);
5697 case 7: // ABBBBBBB:CDDDDDDD
5699 tlbl = newiTempLabel (NULL);
5700 emitcode ("mov", "c,acc.7"); // c = A
5702 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5704 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5706 emitcode ("anl", "a,#0x%02x",
5707 SRMask[shCount]); // 0000000A:BBBBBBBC
5709 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5710 emitcode ("orl", "a,#0x%02x",
5711 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5713 emitcode ("", "%05d$:", tlbl->key + 100);
5720 /*-----------------------------------------------------------------*/
5721 /* shiftL2Left2Result - shift left two bytes from left to result */
5722 /*-----------------------------------------------------------------*/
5724 shiftL2Left2Result (operand * left, int offl,
5725 operand * result, int offr, int shCount)
5727 if (sameRegs (AOP (result), AOP (left)) &&
5728 ((offl + MSB16) == offr))
5730 /* don't crash result[offr] */
5731 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5732 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5736 movLeft2Result (left, offl, result, offr, 0);
5737 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5739 /* ax << shCount (x = lsb(result)) */
5740 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5741 aopPut (AOP (result), "a", offr + MSB16);
5745 /*-----------------------------------------------------------------*/
5746 /* shiftR2Left2Result - shift right two bytes from left to result */
5747 /*-----------------------------------------------------------------*/
5749 shiftR2Left2Result (operand * left, int offl,
5750 operand * result, int offr,
5751 int shCount, int sign)
5753 if (sameRegs (AOP (result), AOP (left)) &&
5754 ((offl + MSB16) == offr))
5756 /* don't crash result[offr] */
5757 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5758 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5762 movLeft2Result (left, offl, result, offr, 0);
5763 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5765 /* a:x >> shCount (x = lsb(result)) */
5767 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5769 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5770 if (getDataSize (result) > 1)
5771 aopPut (AOP (result), "a", offr + MSB16);
5774 /*-----------------------------------------------------------------*/
5775 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5776 /*-----------------------------------------------------------------*/
5778 shiftLLeftOrResult (operand * left, int offl,
5779 operand * result, int offr, int shCount)
5781 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5782 /* shift left accumulator */
5784 /* or with result */
5785 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5786 /* back to result */
5787 aopPut (AOP (result), "a", offr);
5790 /*-----------------------------------------------------------------*/
5791 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5792 /*-----------------------------------------------------------------*/
5794 shiftRLeftOrResult (operand * left, int offl,
5795 operand * result, int offr, int shCount)
5797 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5798 /* shift right accumulator */
5800 /* or with result */
5801 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5802 /* back to result */
5803 aopPut (AOP (result), "a", offr);
5806 /*-----------------------------------------------------------------*/
5807 /* genlshOne - left shift a one byte quantity by known count */
5808 /*-----------------------------------------------------------------*/
5810 genlshOne (operand * result, operand * left, int shCount)
5812 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5815 /*-----------------------------------------------------------------*/
5816 /* genlshTwo - left shift two bytes by known amount != 0 */
5817 /*-----------------------------------------------------------------*/
5819 genlshTwo (operand * result, operand * left, int shCount)
5823 size = getDataSize (result);
5825 /* if shCount >= 8 */
5833 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5835 movLeft2Result (left, LSB, result, MSB16, 0);
5837 aopPut (AOP (result), zero, LSB);
5840 /* 1 <= shCount <= 7 */
5844 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5846 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5850 /*-----------------------------------------------------------------*/
5851 /* shiftLLong - shift left one long from left to result */
5852 /* offl = LSB or MSB16 */
5853 /*-----------------------------------------------------------------*/
5855 shiftLLong (operand * left, operand * result, int offr)
5858 int size = AOP_SIZE (result);
5860 if (size >= LSB + offr)
5862 l = aopGet (AOP (left), LSB, FALSE, FALSE);
5864 emitcode ("add", "a,acc");
5865 if (sameRegs (AOP (left), AOP (result)) &&
5866 size >= MSB16 + offr && offr != LSB)
5867 emitcode ("xch", "a,%s",
5868 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5870 aopPut (AOP (result), "a", LSB + offr);
5873 if (size >= MSB16 + offr)
5875 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5877 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5880 emitcode ("rlc", "a");
5881 if (sameRegs (AOP (left), AOP (result)) &&
5882 size >= MSB24 + offr && offr != LSB)
5883 emitcode ("xch", "a,%s",
5884 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5886 aopPut (AOP (result), "a", MSB16 + offr);
5889 if (size >= MSB24 + offr)
5891 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5893 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5896 emitcode ("rlc", "a");
5897 if (sameRegs (AOP (left), AOP (result)) &&
5898 size >= MSB32 + offr && offr != LSB)
5899 emitcode ("xch", "a,%s",
5900 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5902 aopPut (AOP (result), "a", MSB24 + offr);
5905 if (size > MSB32 + offr)
5907 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5909 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5912 emitcode ("rlc", "a");
5913 aopPut (AOP (result), "a", MSB32 + offr);
5916 aopPut (AOP (result), zero, LSB);
5919 /*-----------------------------------------------------------------*/
5920 /* genlshFour - shift four byte by a known amount != 0 */
5921 /*-----------------------------------------------------------------*/
5923 genlshFour (operand * result, operand * left, int shCount)
5927 size = AOP_SIZE (result);
5929 /* if shifting more that 3 bytes */
5934 /* lowest order of left goes to the highest
5935 order of the destination */
5936 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5938 movLeft2Result (left, LSB, result, MSB32, 0);
5939 aopPut (AOP (result), zero, LSB);
5940 aopPut (AOP (result), zero, MSB16);
5941 aopPut (AOP (result), zero, MSB32);
5945 /* more than two bytes */
5946 else if (shCount >= 16)
5948 /* lower order two bytes goes to higher order two bytes */
5950 /* if some more remaining */
5952 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5955 movLeft2Result (left, MSB16, result, MSB32, 0);
5956 movLeft2Result (left, LSB, result, MSB24, 0);
5958 aopPut (AOP (result), zero, MSB16);
5959 aopPut (AOP (result), zero, LSB);
5963 /* if more than 1 byte */
5964 else if (shCount >= 8)
5966 /* lower order three bytes goes to higher order three bytes */
5971 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5973 movLeft2Result (left, LSB, result, MSB16, 0);
5979 movLeft2Result (left, MSB24, result, MSB32, 0);
5980 movLeft2Result (left, MSB16, result, MSB24, 0);
5981 movLeft2Result (left, LSB, result, MSB16, 0);
5982 aopPut (AOP (result), zero, LSB);
5984 else if (shCount == 1)
5985 shiftLLong (left, result, MSB16);
5988 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5989 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5990 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5991 aopPut (AOP (result), zero, LSB);
5996 /* 1 <= shCount <= 7 */
5997 else if (shCount <= 2)
5999 shiftLLong (left, result, LSB);
6001 shiftLLong (result, result, LSB);
6003 /* 3 <= shCount <= 7, optimize */
6006 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6007 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6008 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6012 /*-----------------------------------------------------------------*/
6013 /* genLeftShiftLiteral - left shifting by known count */
6014 /*-----------------------------------------------------------------*/
6016 genLeftShiftLiteral (operand * left,
6021 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6024 freeAsmop (right, NULL, ic, TRUE);
6026 aopOp (left, ic, FALSE);
6027 aopOp (result, ic, FALSE);
6029 size = getSize (operandType (result));
6032 emitcode ("; shift left ", "result %d, left %d", size,
6036 /* I suppose that the left size >= result size */
6041 movLeft2Result (left, size, result, size, 0);
6045 else if (shCount >= (size * 8))
6047 aopPut (AOP (result), zero, size);
6053 genlshOne (result, left, shCount);
6058 genlshTwo (result, left, shCount);
6062 genlshFour (result, left, shCount);
6066 freeAsmop (left, NULL, ic, TRUE);
6067 freeAsmop (result, NULL, ic, TRUE);
6070 /*-----------------------------------------------------------------*/
6071 /* genLeftShift - generates code for left shifting */
6072 /*-----------------------------------------------------------------*/
6074 genLeftShift (iCode * ic)
6076 operand *left, *right, *result;
6079 symbol *tlbl, *tlbl1;
6081 right = IC_RIGHT (ic);
6082 left = IC_LEFT (ic);
6083 result = IC_RESULT (ic);
6085 aopOp (right, ic, FALSE);
6087 /* if the shift count is known then do it
6088 as efficiently as possible */
6089 if (AOP_TYPE (right) == AOP_LIT)
6091 genLeftShiftLiteral (left, right, result, ic);
6095 /* shift count is unknown then we have to form
6096 a loop get the loop count in B : Note: we take
6097 only the lower order byte since shifting
6098 more that 32 bits make no sense anyway, ( the
6099 largest size of an object can be only 32 bits ) */
6101 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6102 emitcode ("inc", "b");
6103 freeAsmop (right, NULL, ic, TRUE);
6104 aopOp (left, ic, FALSE);
6105 aopOp (result, ic, FALSE);
6107 /* now move the left to the result if they are not the
6109 if (!sameRegs (AOP (left), AOP (result)) &&
6110 AOP_SIZE (result) > 1)
6113 size = AOP_SIZE (result);
6117 l = aopGet (AOP (left), offset, FALSE, TRUE);
6118 if (*l == '@' && (IS_AOP_PREG (result)))
6121 emitcode ("mov", "a,%s", l);
6122 aopPut (AOP (result), "a", offset);
6125 aopPut (AOP (result), l, offset);
6130 tlbl = newiTempLabel (NULL);
6131 size = AOP_SIZE (result);
6133 tlbl1 = newiTempLabel (NULL);
6135 /* if it is only one byte then */
6138 symbol *tlbl1 = newiTempLabel (NULL);
6140 l = aopGet (AOP (left), 0, FALSE, FALSE);
6142 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6143 emitcode ("", "%05d$:", tlbl->key + 100);
6144 emitcode ("add", "a,acc");
6145 emitcode ("", "%05d$:", tlbl1->key + 100);
6146 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6147 aopPut (AOP (result), "a", 0);
6151 reAdjustPreg (AOP (result));
6153 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6154 emitcode ("", "%05d$:", tlbl->key + 100);
6155 l = aopGet (AOP (result), offset, FALSE, FALSE);
6157 emitcode ("add", "a,acc");
6158 aopPut (AOP (result), "a", offset++);
6161 l = aopGet (AOP (result), offset, FALSE, FALSE);
6163 emitcode ("rlc", "a");
6164 aopPut (AOP (result), "a", offset++);
6166 reAdjustPreg (AOP (result));
6168 emitcode ("", "%05d$:", tlbl1->key + 100);
6169 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6171 freeAsmop (left, NULL, ic, TRUE);
6172 freeAsmop (result, NULL, ic, TRUE);
6175 /*-----------------------------------------------------------------*/
6176 /* genrshOne - right shift a one byte quantity by known count */
6177 /*-----------------------------------------------------------------*/
6179 genrshOne (operand * result, operand * left,
6180 int shCount, int sign)
6182 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6185 /*-----------------------------------------------------------------*/
6186 /* genrshTwo - right shift two bytes by known amount != 0 */
6187 /*-----------------------------------------------------------------*/
6189 genrshTwo (operand * result, operand * left,
6190 int shCount, int sign)
6192 /* if shCount >= 8 */
6197 shiftR1Left2Result (left, MSB16, result, LSB,
6200 movLeft2Result (left, MSB16, result, LSB, sign);
6201 addSign (result, MSB16, sign);
6204 /* 1 <= shCount <= 7 */
6206 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6209 /*-----------------------------------------------------------------*/
6210 /* shiftRLong - shift right one long from left to result */
6211 /* offl = LSB or MSB16 */
6212 /*-----------------------------------------------------------------*/
6214 shiftRLong (operand * left, int offl,
6215 operand * result, int sign)
6218 emitcode ("clr", "c");
6219 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6221 emitcode ("mov", "c,acc.7");
6222 emitcode ("rrc", "a");
6223 aopPut (AOP (result), "a", MSB32 - offl);
6225 /* add sign of "a" */
6226 addSign (result, MSB32, sign);
6228 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6229 emitcode ("rrc", "a");
6230 aopPut (AOP (result), "a", MSB24 - offl);
6232 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6233 emitcode ("rrc", "a");
6234 aopPut (AOP (result), "a", MSB16 - offl);
6238 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6239 emitcode ("rrc", "a");
6240 aopPut (AOP (result), "a", LSB);
6244 /*-----------------------------------------------------------------*/
6245 /* genrshFour - shift four byte by a known amount != 0 */
6246 /*-----------------------------------------------------------------*/
6248 genrshFour (operand * result, operand * left,
6249 int shCount, int sign)
6251 /* if shifting more that 3 bytes */
6256 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6258 movLeft2Result (left, MSB32, result, LSB, sign);
6259 addSign (result, MSB16, sign);
6261 else if (shCount >= 16)
6265 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6268 movLeft2Result (left, MSB24, result, LSB, 0);
6269 movLeft2Result (left, MSB32, result, MSB16, sign);
6271 addSign (result, MSB24, sign);
6273 else if (shCount >= 8)
6277 shiftRLong (left, MSB16, result, sign);
6278 else if (shCount == 0)
6280 movLeft2Result (left, MSB16, result, LSB, 0);
6281 movLeft2Result (left, MSB24, result, MSB16, 0);
6282 movLeft2Result (left, MSB32, result, MSB24, sign);
6283 addSign (result, MSB32, sign);
6287 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6288 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6289 /* the last shift is signed */
6290 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6291 addSign (result, MSB32, sign);
6295 { /* 1 <= shCount <= 7 */
6298 shiftRLong (left, LSB, result, sign);
6300 shiftRLong (result, LSB, result, sign);
6304 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6305 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6306 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6311 /*-----------------------------------------------------------------*/
6312 /* genRightShiftLiteral - right shifting by known count */
6313 /*-----------------------------------------------------------------*/
6315 genRightShiftLiteral (operand * left,
6321 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6324 freeAsmop (right, NULL, ic, TRUE);
6326 aopOp (left, ic, FALSE);
6327 aopOp (result, ic, FALSE);
6330 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6334 size = getDataSize (left);
6335 /* test the LEFT size !!! */
6337 /* I suppose that the left size >= result size */
6340 size = getDataSize (result);
6342 movLeft2Result (left, size, result, size, 0);
6345 else if (shCount >= (size * 8))
6348 /* get sign in acc.7 */
6349 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6350 addSign (result, LSB, sign);
6357 genrshOne (result, left, shCount, sign);
6361 genrshTwo (result, left, shCount, sign);
6365 genrshFour (result, left, shCount, sign);
6371 freeAsmop (left, NULL, ic, TRUE);
6372 freeAsmop (result, NULL, ic, TRUE);
6376 /*-----------------------------------------------------------------*/
6377 /* genSignedRightShift - right shift of signed number */
6378 /*-----------------------------------------------------------------*/
6380 genSignedRightShift (iCode * ic)
6382 operand *right, *left, *result;
6385 symbol *tlbl, *tlbl1;
6387 /* we do it the hard way put the shift count in b
6388 and loop thru preserving the sign */
6390 right = IC_RIGHT (ic);
6391 left = IC_LEFT (ic);
6392 result = IC_RESULT (ic);
6394 aopOp (right, ic, FALSE);
6397 if (AOP_TYPE (right) == AOP_LIT)
6399 genRightShiftLiteral (left, right, result, ic, 1);
6402 /* shift count is unknown then we have to form
6403 a loop get the loop count in B : Note: we take
6404 only the lower order byte since shifting
6405 more that 32 bits make no sense anyway, ( the
6406 largest size of an object can be only 32 bits ) */
6408 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6409 emitcode ("inc", "b");
6410 freeAsmop (right, NULL, ic, TRUE);
6411 aopOp (left, ic, FALSE);
6412 aopOp (result, ic, FALSE);
6414 /* now move the left to the result if they are not the
6416 if (!sameRegs (AOP (left), AOP (result)) &&
6417 AOP_SIZE (result) > 1)
6420 size = AOP_SIZE (result);
6424 l = aopGet (AOP (left), offset, FALSE, TRUE);
6425 if (*l == '@' && IS_AOP_PREG (result))
6428 emitcode ("mov", "a,%s", l);
6429 aopPut (AOP (result), "a", offset);
6432 aopPut (AOP (result), l, offset);
6437 /* mov the highest order bit to OVR */
6438 tlbl = newiTempLabel (NULL);
6439 tlbl1 = newiTempLabel (NULL);
6441 size = AOP_SIZE (result);
6443 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6444 emitcode ("rlc", "a");
6445 emitcode ("mov", "ov,c");
6446 /* if it is only one byte then */
6449 l = aopGet (AOP (left), 0, FALSE, FALSE);
6451 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6452 emitcode ("", "%05d$:", tlbl->key + 100);
6453 emitcode ("mov", "c,ov");
6454 emitcode ("rrc", "a");
6455 emitcode ("", "%05d$:", tlbl1->key + 100);
6456 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6457 aopPut (AOP (result), "a", 0);
6461 reAdjustPreg (AOP (result));
6462 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6463 emitcode ("", "%05d$:", tlbl->key + 100);
6464 emitcode ("mov", "c,ov");
6467 l = aopGet (AOP (result), offset, FALSE, FALSE);
6469 emitcode ("rrc", "a");
6470 aopPut (AOP (result), "a", offset--);
6472 reAdjustPreg (AOP (result));
6473 emitcode ("", "%05d$:", tlbl1->key + 100);
6474 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6477 freeAsmop (left, NULL, ic, TRUE);
6478 freeAsmop (result, NULL, ic, TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* genRightShift - generate code for right shifting */
6483 /*-----------------------------------------------------------------*/
6485 genRightShift (iCode * ic)
6487 operand *right, *left, *result;
6491 symbol *tlbl, *tlbl1;
6493 /* if signed then we do it the hard way preserve the
6494 sign bit moving it inwards */
6495 retype = getSpec (operandType (IC_RESULT (ic)));
6497 if (!SPEC_USIGN (retype))
6499 genSignedRightShift (ic);
6503 /* signed & unsigned types are treated the same : i.e. the
6504 signed is NOT propagated inwards : quoting from the
6505 ANSI - standard : "for E1 >> E2, is equivalent to division
6506 by 2**E2 if unsigned or if it has a non-negative value,
6507 otherwise the result is implementation defined ", MY definition
6508 is that the sign does not get propagated */
6510 right = IC_RIGHT (ic);
6511 left = IC_LEFT (ic);
6512 result = IC_RESULT (ic);
6514 aopOp (right, ic, FALSE);
6516 /* if the shift count is known then do it
6517 as efficiently as possible */
6518 if (AOP_TYPE (right) == AOP_LIT)
6520 genRightShiftLiteral (left, right, result, ic, 0);
6524 /* shift count is unknown then we have to form
6525 a loop get the loop count in B : Note: we take
6526 only the lower order byte since shifting
6527 more that 32 bits make no sense anyway, ( the
6528 largest size of an object can be only 32 bits ) */
6530 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6531 emitcode ("inc", "b");
6532 freeAsmop (right, NULL, ic, TRUE);
6533 aopOp (left, ic, FALSE);
6534 aopOp (result, ic, FALSE);
6536 /* now move the left to the result if they are not the
6538 if (!sameRegs (AOP (left), AOP (result)) &&
6539 AOP_SIZE (result) > 1)
6542 size = AOP_SIZE (result);
6546 l = aopGet (AOP (left), offset, FALSE, TRUE);
6547 if (*l == '@' && IS_AOP_PREG (result))
6550 emitcode ("mov", "a,%s", l);
6551 aopPut (AOP (result), "a", offset);
6554 aopPut (AOP (result), l, offset);
6559 tlbl = newiTempLabel (NULL);
6560 tlbl1 = newiTempLabel (NULL);
6561 size = AOP_SIZE (result);
6564 /* if it is only one byte then */
6567 l = aopGet (AOP (left), 0, FALSE, FALSE);
6569 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6570 emitcode ("", "%05d$:", tlbl->key + 100);
6572 emitcode ("rrc", "a");
6573 emitcode ("", "%05d$:", tlbl1->key + 100);
6574 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6575 aopPut (AOP (result), "a", 0);
6579 reAdjustPreg (AOP (result));
6580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6581 emitcode ("", "%05d$:", tlbl->key + 100);
6585 l = aopGet (AOP (result), offset, FALSE, FALSE);
6587 emitcode ("rrc", "a");
6588 aopPut (AOP (result), "a", offset--);
6590 reAdjustPreg (AOP (result));
6592 emitcode ("", "%05d$:", tlbl1->key + 100);
6593 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6596 freeAsmop (left, NULL, ic, TRUE);
6597 freeAsmop (result, NULL, ic, TRUE);
6600 /*-----------------------------------------------------------------*/
6601 /* genUnpackBits - generates code for unpacking bits */
6602 /*-----------------------------------------------------------------*/
6604 genUnpackBits (operand * result, char *rname, int ptype)
6612 etype = getSpec (operandType (result));
6613 rsize = getSize (operandType (result));
6614 /* read the first byte */
6620 emitcode ("mov", "a,@%s", rname);
6624 emitcode ("movx", "a,@%s", rname);
6628 emitcode ("movx", "a,@dptr");
6632 emitcode ("clr", "a");
6633 emitcode ("movc", "a,%s", "@a+dptr");
6637 emitcode ("lcall", "__gptrget");
6641 rlen = SPEC_BLEN (etype);
6643 /* if we have bitdisplacement then it fits */
6644 /* into this byte completely or if length is */
6645 /* less than a byte */
6646 if ((shCnt = SPEC_BSTR (etype)) ||
6647 (SPEC_BLEN (etype) <= 8))
6650 /* shift right acc */
6653 emitcode ("anl", "a,#0x%02x",
6654 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6655 aopPut (AOP (result), "a", offset++);
6659 /* bit field did not fit in a byte */
6660 aopPut (AOP (result), "a", offset++);
6669 emitcode ("inc", "%s", rname);
6670 emitcode ("mov", "a,@%s", rname);
6674 emitcode ("inc", "%s", rname);
6675 emitcode ("movx", "a,@%s", rname);
6679 emitcode ("inc", "dptr");
6680 emitcode ("movx", "a,@dptr");
6684 emitcode ("clr", "a");
6685 emitcode ("inc", "dptr");
6686 emitcode ("movc", "a", "@a+dptr");
6690 emitcode ("inc", "dptr");
6691 emitcode ("lcall", "__gptrget");
6696 /* if we are done */
6700 aopPut (AOP (result), "a", offset++);
6706 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6708 aopPut (AOP (result), "a", offset++);
6716 aopPut (AOP (result), zero, offset++);
6722 /*-----------------------------------------------------------------*/
6723 /* genDataPointerGet - generates code when ptr offset is known */
6724 /*-----------------------------------------------------------------*/
6726 genDataPointerGet (operand * left,
6732 int size, offset = 0;
6733 aopOp (result, ic, TRUE);
6735 /* get the string representation of the name */
6736 l = aopGet (AOP (left), 0, FALSE, TRUE);
6737 size = AOP_SIZE (result);
6741 sprintf (buffer, "(%s + %d)", l + 1, offset);
6743 sprintf (buffer, "%s", l + 1);
6744 aopPut (AOP (result), buffer, offset++);
6747 freeAsmop (left, NULL, ic, TRUE);
6748 freeAsmop (result, NULL, ic, TRUE);
6751 /*-----------------------------------------------------------------*/
6752 /* genNearPointerGet - emitcode for near pointer fetch */
6753 /*-----------------------------------------------------------------*/
6755 genNearPointerGet (operand * left,
6762 sym_link *rtype, *retype;
6763 sym_link *ltype = operandType (left);
6766 rtype = operandType (result);
6767 retype = getSpec (rtype);
6769 aopOp (left, ic, FALSE);
6771 /* if left is rematerialisable and
6772 result is not bit variable type and
6773 the left is pointer to data space i.e
6774 lower 128 bytes of space */
6775 if (AOP_TYPE (left) == AOP_IMMD &&
6776 !IS_BITVAR (retype) &&
6777 DCL_TYPE (ltype) == POINTER)
6779 genDataPointerGet (left, result, ic);
6783 /* if the value is already in a pointer register
6784 then don't need anything more */
6785 if (!AOP_INPREG (AOP (left)))
6787 /* otherwise get a free pointer register */
6789 preg = getFreePtr (ic, &aop, FALSE);
6790 emitcode ("mov", "%s,%s",
6792 aopGet (AOP (left), 0, FALSE, TRUE));
6796 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6798 freeAsmop (left, NULL, ic, TRUE);
6799 aopOp (result, ic, FALSE);
6801 /* if bitfield then unpack the bits */
6802 if (IS_BITVAR (retype))
6803 genUnpackBits (result, rname, POINTER);
6806 /* we have can just get the values */
6807 int size = AOP_SIZE (result);
6812 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6815 emitcode ("mov", "a,@%s", rname);
6816 aopPut (AOP (result), "a", offset);
6820 sprintf (buffer, "@%s", rname);
6821 aopPut (AOP (result), buffer, offset);
6825 emitcode ("inc", "%s", rname);
6829 /* now some housekeeping stuff */
6832 /* we had to allocate for this iCode */
6833 freeAsmop (NULL, aop, ic, TRUE);
6837 /* we did not allocate which means left
6838 already in a pointer register, then
6839 if size > 0 && this could be used again
6840 we have to point it back to where it
6842 if (AOP_SIZE (result) > 1 &&
6843 !OP_SYMBOL (left)->remat &&
6844 (OP_SYMBOL (left)->liveTo > ic->seq ||
6847 int size = AOP_SIZE (result) - 1;
6849 emitcode ("dec", "%s", rname);
6854 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* genPagedPointerGet - emitcode for paged pointer fetch */
6860 /*-----------------------------------------------------------------*/
6862 genPagedPointerGet (operand * left,
6869 sym_link *rtype, *retype;
6871 rtype = operandType (result);
6872 retype = getSpec (rtype);
6874 aopOp (left, ic, FALSE);
6876 /* if the value is already in a pointer register
6877 then don't need anything more */
6878 if (!AOP_INPREG (AOP (left)))
6880 /* otherwise get a free pointer register */
6882 preg = getFreePtr (ic, &aop, FALSE);
6883 emitcode ("mov", "%s,%s",
6885 aopGet (AOP (left), 0, FALSE, TRUE));
6889 rname = aopGet (AOP (left), 0, FALSE, FALSE);
6891 freeAsmop (left, NULL, ic, TRUE);
6892 aopOp (result, ic, FALSE);
6894 /* if bitfield then unpack the bits */
6895 if (IS_BITVAR (retype))
6896 genUnpackBits (result, rname, PPOINTER);
6899 /* we have can just get the values */
6900 int size = AOP_SIZE (result);
6906 emitcode ("movx", "a,@%s", rname);
6907 aopPut (AOP (result), "a", offset);
6912 emitcode ("inc", "%s", rname);
6916 /* now some housekeeping stuff */
6919 /* we had to allocate for this iCode */
6920 freeAsmop (NULL, aop, ic, TRUE);
6924 /* we did not allocate which means left
6925 already in a pointer register, then
6926 if size > 0 && this could be used again
6927 we have to point it back to where it
6929 if (AOP_SIZE (result) > 1 &&
6930 !OP_SYMBOL (left)->remat &&
6931 (OP_SYMBOL (left)->liveTo > ic->seq ||
6934 int size = AOP_SIZE (result) - 1;
6936 emitcode ("dec", "%s", rname);
6941 freeAsmop (result, NULL, ic, TRUE);
6946 /*-----------------------------------------------------------------*/
6947 /* genFarPointerGet - gget value from far space */
6948 /*-----------------------------------------------------------------*/
6950 genFarPointerGet (operand * left,
6951 operand * result, iCode * ic)
6954 sym_link *retype = getSpec (operandType (result));
6956 aopOp (left, ic, FALSE);
6958 /* if the operand is already in dptr
6959 then we do nothing else we move the value to dptr */
6960 if (AOP_TYPE (left) != AOP_STR)
6962 /* if this is remateriazable */
6963 if (AOP_TYPE (left) == AOP_IMMD)
6964 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6966 { /* we need to get it byte by byte */
6967 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6968 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6969 if (options.model == MODEL_FLAT24)
6971 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
6975 /* so dptr know contains the address */
6976 freeAsmop (left, NULL, ic, TRUE);
6977 aopOp (result, ic, FALSE);
6979 /* if bit then unpack */
6980 if (IS_BITVAR (retype))
6981 genUnpackBits (result, "dptr", FPOINTER);
6984 size = AOP_SIZE (result);
6989 emitcode ("movx", "a,@dptr");
6990 aopPut (AOP (result), "a", offset++);
6992 emitcode ("inc", "dptr");
6996 freeAsmop (result, NULL, ic, TRUE);
6999 /*-----------------------------------------------------------------*/
7000 /* emitcodePointerGet - gget value from code space */
7001 /*-----------------------------------------------------------------*/
7003 emitcodePointerGet (operand * left,
7004 operand * result, iCode * ic)
7007 sym_link *retype = getSpec (operandType (result));
7009 aopOp (left, ic, FALSE);
7011 /* if the operand is already in dptr
7012 then we do nothing else we move the value to dptr */
7013 if (AOP_TYPE (left) != AOP_STR)
7015 /* if this is remateriazable */
7016 if (AOP_TYPE (left) == AOP_IMMD)
7017 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7019 { /* we need to get it byte by byte */
7020 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7021 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7022 if (options.model == MODEL_FLAT24)
7024 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7028 /* so dptr know contains the address */
7029 freeAsmop (left, NULL, ic, TRUE);
7030 aopOp (result, ic, FALSE);
7032 /* if bit then unpack */
7033 if (IS_BITVAR (retype))
7034 genUnpackBits (result, "dptr", CPOINTER);
7037 size = AOP_SIZE (result);
7042 emitcode ("clr", "a");
7043 emitcode ("movc", "a,@a+dptr");
7044 aopPut (AOP (result), "a", offset++);
7046 emitcode ("inc", "dptr");
7050 freeAsmop (result, NULL, ic, TRUE);
7053 /*-----------------------------------------------------------------*/
7054 /* genGenPointerGet - gget value from generic pointer space */
7055 /*-----------------------------------------------------------------*/
7057 genGenPointerGet (operand * left,
7058 operand * result, iCode * ic)
7061 sym_link *retype = getSpec (operandType (result));
7063 aopOp (left, ic, FALSE);
7065 /* if the operand is already in dptr
7066 then we do nothing else we move the value to dptr */
7067 if (AOP_TYPE (left) != AOP_STR)
7069 /* if this is remateriazable */
7070 if (AOP_TYPE (left) == AOP_IMMD)
7072 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7073 emitcode ("mov", "b,#%d", pointerCode (retype));
7076 { /* we need to get it byte by byte */
7077 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7078 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7079 if (options.model == MODEL_FLAT24)
7081 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7082 emitcode ("mov", "b,%s", aopGet (AOP (left), 3, FALSE, FALSE));
7086 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7090 /* so dptr know contains the address */
7091 freeAsmop (left, NULL, ic, TRUE);
7092 aopOp (result, ic, FALSE);
7094 /* if bit then unpack */
7095 if (IS_BITVAR (retype))
7096 genUnpackBits (result, "dptr", GPOINTER);
7099 size = AOP_SIZE (result);
7104 emitcode ("lcall", "__gptrget");
7105 aopPut (AOP (result), "a", offset++);
7107 emitcode ("inc", "dptr");
7111 freeAsmop (result, NULL, ic, TRUE);
7114 /*-----------------------------------------------------------------*/
7115 /* genPointerGet - generate code for pointer get */
7116 /*-----------------------------------------------------------------*/
7118 genPointerGet (iCode * ic)
7120 operand *left, *result;
7121 sym_link *type, *etype;
7124 left = IC_LEFT (ic);
7125 result = IC_RESULT (ic);
7127 /* depending on the type of pointer we need to
7128 move it to the correct pointer register */
7129 type = operandType (left);
7130 etype = getSpec (type);
7131 /* if left is of type of pointer then it is simple */
7132 if (IS_PTR (type) && !IS_FUNC (type->next))
7133 p_type = DCL_TYPE (type);
7136 /* we have to go by the storage class */
7137 p_type = PTR_TYPE (SPEC_OCLS (etype));
7139 /* if (SPEC_OCLS(etype)->codesp ) { */
7140 /* p_type = CPOINTER ; */
7143 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7144 /* p_type = FPOINTER ; */
7146 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7147 /* p_type = PPOINTER; */
7149 /* if (SPEC_OCLS(etype) == idata ) */
7150 /* p_type = IPOINTER; */
7152 /* p_type = POINTER ; */
7155 /* now that we have the pointer type we assign
7156 the pointer values */
7162 genNearPointerGet (left, result, ic);
7166 genPagedPointerGet (left, result, ic);
7170 genFarPointerGet (left, result, ic);
7174 emitcodePointerGet (left, result, ic);
7178 genGenPointerGet (left, result, ic);
7184 /*-----------------------------------------------------------------*/
7185 /* genPackBits - generates code for packed bit storage */
7186 /*-----------------------------------------------------------------*/
7188 genPackBits (sym_link * etype,
7190 char *rname, int p_type)
7198 blen = SPEC_BLEN (etype);
7199 bstr = SPEC_BSTR (etype);
7201 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7204 /* if the bit lenth is less than or */
7205 /* it exactly fits a byte then */
7206 if (SPEC_BLEN (etype) <= 8)
7208 shCount = SPEC_BSTR (etype);
7210 /* shift left acc */
7213 if (SPEC_BLEN (etype) < 8)
7214 { /* if smaller than a byte */
7220 emitcode ("mov", "b,a");
7221 emitcode ("mov", "a,@%s", rname);
7225 emitcode ("mov", "b,a");
7226 emitcode ("movx", "a,@dptr");
7230 emitcode ("push", "b");
7231 emitcode ("push", "acc");
7232 emitcode ("lcall", "__gptrget");
7233 emitcode ("pop", "b");
7237 emitcode ("anl", "a,#0x%02x", (unsigned char)
7238 ((unsigned char) (0xFF << (blen + bstr)) |
7239 (unsigned char) (0xFF >> (8 - bstr))));
7240 emitcode ("orl", "a,b");
7241 if (p_type == GPOINTER)
7242 emitcode ("pop", "b");
7249 emitcode ("mov", "@%s,a", rname);
7253 emitcode ("movx", "@dptr,a");
7257 emitcode ("lcall", "__gptrput");
7262 if (SPEC_BLEN (etype) <= 8)
7265 emitcode ("inc", "%s", rname);
7266 rLen = SPEC_BLEN (etype);
7268 /* now generate for lengths greater than one byte */
7272 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7284 emitcode ("mov", "@%s,a", rname);
7287 emitcode ("mov", "@%s,%s", rname, l);
7292 emitcode ("movx", "@dptr,a");
7297 emitcode ("lcall", "__gptrput");
7300 emitcode ("inc", "%s", rname);
7305 /* last last was not complete */
7308 /* save the byte & read byte */
7312 emitcode ("mov", "b,a");
7313 emitcode ("mov", "a,@%s", rname);
7317 emitcode ("mov", "b,a");
7318 emitcode ("movx", "a,@dptr");
7322 emitcode ("push", "b");
7323 emitcode ("push", "acc");
7324 emitcode ("lcall", "__gptrget");
7325 emitcode ("pop", "b");
7329 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7330 emitcode ("orl", "a,b");
7333 if (p_type == GPOINTER)
7334 emitcode ("pop", "b");
7340 emitcode ("mov", "@%s,a", rname);
7344 emitcode ("movx", "@dptr,a");
7348 emitcode ("lcall", "__gptrput");
7352 /*-----------------------------------------------------------------*/
7353 /* genDataPointerSet - remat pointer to data space */
7354 /*-----------------------------------------------------------------*/
7356 genDataPointerSet (operand * right,
7360 int size, offset = 0;
7361 char *l, buffer[256];
7363 aopOp (right, ic, FALSE);
7365 l = aopGet (AOP (result), 0, FALSE, TRUE);
7366 size = AOP_SIZE (right);
7370 sprintf (buffer, "(%s + %d)", l + 1, offset);
7372 sprintf (buffer, "%s", l + 1);
7373 emitcode ("mov", "%s,%s", buffer,
7374 aopGet (AOP (right), offset++, FALSE, FALSE));
7377 freeAsmop (right, NULL, ic, TRUE);
7378 freeAsmop (result, NULL, ic, TRUE);
7381 /*-----------------------------------------------------------------*/
7382 /* genNearPointerSet - emitcode for near pointer put */
7383 /*-----------------------------------------------------------------*/
7385 genNearPointerSet (operand * right,
7392 sym_link *retype, *letype;
7393 sym_link *ptype = operandType (result);
7395 retype = getSpec (operandType (right));
7396 letype = getSpec (ptype);
7397 aopOp (result, ic, FALSE);
7399 /* if the result is rematerializable &
7400 in data space & not a bit variable */
7401 if (AOP_TYPE (result) == AOP_IMMD &&
7402 DCL_TYPE (ptype) == POINTER &&
7403 !IS_BITVAR (retype) &&
7404 !IS_BITVAR (letype))
7406 genDataPointerSet (right, result, ic);
7410 /* if the value is already in a pointer register
7411 then don't need anything more */
7412 if (!AOP_INPREG (AOP (result)))
7414 /* otherwise get a free pointer register */
7416 preg = getFreePtr (ic, &aop, FALSE);
7417 emitcode ("mov", "%s,%s",
7419 aopGet (AOP (result), 0, FALSE, TRUE));
7423 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7425 freeAsmop (result, NULL, ic, TRUE);
7426 aopOp (right, ic, FALSE);
7428 /* if bitfield then unpack the bits */
7429 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7430 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7433 /* we have can just get the values */
7434 int size = AOP_SIZE (right);
7439 l = aopGet (AOP (right), offset, FALSE, TRUE);
7443 emitcode ("mov", "@%s,a", rname);
7446 emitcode ("mov", "@%s,%s", rname, l);
7448 emitcode ("inc", "%s", rname);
7453 /* now some housekeeping stuff */
7456 /* we had to allocate for this iCode */
7457 freeAsmop (NULL, aop, ic, TRUE);
7461 /* we did not allocate which means left
7462 already in a pointer register, then
7463 if size > 0 && this could be used again
7464 we have to point it back to where it
7466 if (AOP_SIZE (right) > 1 &&
7467 !OP_SYMBOL (result)->remat &&
7468 (OP_SYMBOL (result)->liveTo > ic->seq ||
7471 int size = AOP_SIZE (right) - 1;
7473 emitcode ("dec", "%s", rname);
7478 freeAsmop (right, NULL, ic, TRUE);
7483 /*-----------------------------------------------------------------*/
7484 /* genPagedPointerSet - emitcode for Paged pointer put */
7485 /*-----------------------------------------------------------------*/
7487 genPagedPointerSet (operand * right,
7494 sym_link *retype, *letype;
7496 retype = getSpec (operandType (right));
7497 letype = getSpec (operandType (result));
7499 aopOp (result, ic, FALSE);
7501 /* if the value is already in a pointer register
7502 then don't need anything more */
7503 if (!AOP_INPREG (AOP (result)))
7505 /* otherwise get a free pointer register */
7507 preg = getFreePtr (ic, &aop, FALSE);
7508 emitcode ("mov", "%s,%s",
7510 aopGet (AOP (result), 0, FALSE, TRUE));
7514 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7516 freeAsmop (result, NULL, ic, TRUE);
7517 aopOp (right, ic, FALSE);
7519 /* if bitfield then unpack the bits */
7520 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7521 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7524 /* we have can just get the values */
7525 int size = AOP_SIZE (right);
7530 l = aopGet (AOP (right), offset, FALSE, TRUE);
7533 emitcode ("movx", "@%s,a", rname);
7536 emitcode ("inc", "%s", rname);
7542 /* now some housekeeping stuff */
7545 /* we had to allocate for this iCode */
7546 freeAsmop (NULL, aop, ic, TRUE);
7550 /* we did not allocate which means left
7551 already in a pointer register, then
7552 if size > 0 && this could be used again
7553 we have to point it back to where it
7555 if (AOP_SIZE (right) > 1 &&
7556 !OP_SYMBOL (result)->remat &&
7557 (OP_SYMBOL (result)->liveTo > ic->seq ||
7560 int size = AOP_SIZE (right) - 1;
7562 emitcode ("dec", "%s", rname);
7567 freeAsmop (right, NULL, ic, TRUE);
7572 /*-----------------------------------------------------------------*/
7573 /* genFarPointerSet - set value from far space */
7574 /*-----------------------------------------------------------------*/
7576 genFarPointerSet (operand * right,
7577 operand * result, iCode * ic)
7580 sym_link *retype = getSpec (operandType (right));
7581 sym_link *letype = getSpec (operandType (result));
7582 aopOp (result, ic, FALSE);
7584 /* if the operand is already in dptr
7585 then we do nothing else we move the value to dptr */
7586 if (AOP_TYPE (result) != AOP_STR)
7588 /* if this is remateriazable */
7589 if (AOP_TYPE (result) == AOP_IMMD)
7590 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7592 { /* we need to get it byte by byte */
7593 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7594 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7595 if (options.model == MODEL_FLAT24)
7597 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7601 /* so dptr know contains the address */
7602 freeAsmop (result, NULL, ic, TRUE);
7603 aopOp (right, ic, FALSE);
7605 /* if bit then unpack */
7606 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7607 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7610 size = AOP_SIZE (right);
7615 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7617 emitcode ("movx", "@dptr,a");
7619 emitcode ("inc", "dptr");
7623 freeAsmop (right, NULL, ic, TRUE);
7626 /*-----------------------------------------------------------------*/
7627 /* genGenPointerSet - set value from generic pointer space */
7628 /*-----------------------------------------------------------------*/
7630 genGenPointerSet (operand * right,
7631 operand * result, iCode * ic)
7634 sym_link *retype = getSpec (operandType (right));
7635 sym_link *letype = getSpec (operandType (result));
7637 aopOp (result, ic, FALSE);
7639 /* if the operand is already in dptr
7640 then we do nothing else we move the value to dptr */
7641 if (AOP_TYPE (result) != AOP_STR)
7643 /* if this is remateriazable */
7644 if (AOP_TYPE (result) == AOP_IMMD)
7646 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7647 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7650 { /* we need to get it byte by byte */
7651 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7652 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7653 if (options.model == MODEL_FLAT24)
7655 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7656 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE));
7660 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7664 /* so dptr know contains the address */
7665 freeAsmop (result, NULL, ic, TRUE);
7666 aopOp (right, ic, FALSE);
7668 /* if bit then unpack */
7669 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7670 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7673 size = AOP_SIZE (right);
7678 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7680 emitcode ("lcall", "__gptrput");
7682 emitcode ("inc", "dptr");
7686 freeAsmop (right, NULL, ic, TRUE);
7689 /*-----------------------------------------------------------------*/
7690 /* genPointerSet - stores the value into a pointer location */
7691 /*-----------------------------------------------------------------*/
7693 genPointerSet (iCode * ic)
7695 operand *right, *result;
7696 sym_link *type, *etype;
7699 right = IC_RIGHT (ic);
7700 result = IC_RESULT (ic);
7702 /* depending on the type of pointer we need to
7703 move it to the correct pointer register */
7704 type = operandType (result);
7705 etype = getSpec (type);
7706 /* if left is of type of pointer then it is simple */
7707 if (IS_PTR (type) && !IS_FUNC (type->next))
7709 p_type = DCL_TYPE (type);
7713 /* we have to go by the storage class */
7714 p_type = PTR_TYPE (SPEC_OCLS (etype));
7717 /* now that we have the pointer type we assign
7718 the pointer values */
7724 genNearPointerSet (right, result, ic);
7728 genPagedPointerSet (right, result, ic);
7732 genFarPointerSet (right, result, ic);
7736 genGenPointerSet (right, result, ic);
7742 /*-----------------------------------------------------------------*/
7743 /* genIfx - generate code for Ifx statement */
7744 /*-----------------------------------------------------------------*/
7746 genIfx (iCode * ic, iCode * popIc)
7748 operand *cond = IC_COND (ic);
7751 aopOp (cond, ic, FALSE);
7753 /* get the value into acc */
7754 if (AOP_TYPE (cond) != AOP_CRY)
7758 /* the result is now in the accumulator */
7759 freeAsmop (cond, NULL, ic, TRUE);
7761 /* if there was something to be popped then do it */
7765 /* if the condition is a bit variable */
7766 if (isbit && IS_ITEMP (cond) &&
7768 genIfxJump (ic, SPIL_LOC (cond)->rname);
7769 else if (isbit && !IS_ITEMP (cond))
7770 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7772 genIfxJump (ic, "a");
7777 /*-----------------------------------------------------------------*/
7778 /* genAddrOf - generates code for address of */
7779 /*-----------------------------------------------------------------*/
7781 genAddrOf (iCode * ic)
7783 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7786 aopOp (IC_RESULT (ic), ic, FALSE);
7788 /* if the operand is on the stack then we
7789 need to get the stack offset of this
7793 /* if it has an offset then we need to compute
7797 emitcode ("mov", "a,_bp");
7798 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7799 aopPut (AOP (IC_RESULT (ic)), "a", 0);
7803 /* we can just move _bp */
7804 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7806 /* fill the result with zero */
7807 size = AOP_SIZE (IC_RESULT (ic)) - 1;
7810 if (options.stack10bit && size < (FPTRSIZE - 1))
7813 "*** warning: pointer to stack var truncated.\n");
7820 if (options.stack10bit && offset == 2)
7822 aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
7826 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7833 /* object not on stack then we need the name */
7834 size = AOP_SIZE (IC_RESULT (ic));
7839 char s[SDCC_NAME_MAX];
7841 sprintf (s, "#(%s >> %d)",
7845 sprintf (s, "#%s", sym->rname);
7846 aopPut (AOP (IC_RESULT (ic)), s, offset++);
7850 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7854 /*-----------------------------------------------------------------*/
7855 /* genFarFarAssign - assignment when both are in far space */
7856 /*-----------------------------------------------------------------*/
7858 genFarFarAssign (operand * result, operand * right, iCode * ic)
7860 int size = AOP_SIZE (right);
7863 /* first push the right side on to the stack */
7866 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7868 emitcode ("push", "acc");
7871 freeAsmop (right, NULL, ic, FALSE);
7872 /* now assign DPTR to result */
7873 aopOp (result, ic, FALSE);
7874 size = AOP_SIZE (result);
7877 emitcode ("pop", "acc");
7878 aopPut (AOP (result), "a", --offset);
7880 freeAsmop (result, NULL, ic, FALSE);
7884 /*-----------------------------------------------------------------*/
7885 /* genAssign - generate code for assignment */
7886 /*-----------------------------------------------------------------*/
7888 genAssign (iCode * ic)
7890 operand *result, *right;
7892 unsigned long lit = 0L;
7894 result = IC_RESULT (ic);
7895 right = IC_RIGHT (ic);
7897 /* if they are the same */
7898 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7901 aopOp (right, ic, FALSE);
7903 /* special case both in far space */
7904 if ((AOP_TYPE (right) == AOP_DPTR ||
7905 AOP_TYPE (right) == AOP_DPTR2) &&
7906 IS_TRUE_SYMOP (result) &&
7907 isOperandInFarSpace (result))
7910 genFarFarAssign (result, right, ic);
7914 aopOp (result, ic, TRUE);
7916 /* if they are the same registers */
7917 if (sameRegs (AOP (right), AOP (result)))
7920 /* if the result is a bit */
7921 if (AOP_TYPE (result) == AOP_CRY)
7924 /* if the right size is a literal then
7925 we know what the value is */
7926 if (AOP_TYPE (right) == AOP_LIT)
7928 if (((int) operandLitValue (right)))
7929 aopPut (AOP (result), one, 0);
7931 aopPut (AOP (result), zero, 0);
7935 /* the right is also a bit variable */
7936 if (AOP_TYPE (right) == AOP_CRY)
7938 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7939 aopPut (AOP (result), "c", 0);
7945 aopPut (AOP (result), "a", 0);
7949 /* bit variables done */
7951 size = AOP_SIZE (result);
7953 if (AOP_TYPE (right) == AOP_LIT)
7954 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7956 (AOP_TYPE (result) != AOP_REG) &&
7957 (AOP_TYPE (right) == AOP_LIT) &&
7958 !IS_FLOAT (operandType (right)) &&
7961 emitcode ("clr", "a");
7964 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7965 aopPut (AOP (result), "a", size);
7967 aopPut (AOP (result),
7968 aopGet (AOP (right), size, FALSE, FALSE),
7976 aopPut (AOP (result),
7977 aopGet (AOP (right), offset, FALSE, FALSE),
7984 freeAsmop (right, NULL, ic, TRUE);
7985 freeAsmop (result, NULL, ic, TRUE);
7988 /*-----------------------------------------------------------------*/
7989 /* genJumpTab - genrates code for jump table */
7990 /*-----------------------------------------------------------------*/
7992 genJumpTab (iCode * ic)
7997 aopOp (IC_JTCOND (ic), ic, FALSE);
7998 /* get the condition into accumulator */
7999 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8001 /* multiply by three */
8002 emitcode ("add", "a,acc");
8003 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8004 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8006 jtab = newiTempLabel (NULL);
8007 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8008 emitcode ("jmp", "@a+dptr");
8009 emitcode ("", "%05d$:", jtab->key + 100);
8010 /* now generate the jump labels */
8011 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8012 jtab = setNextItem (IC_JTLABELS (ic)))
8013 emitcode ("ljmp", "%05d$", jtab->key + 100);
8017 /*-----------------------------------------------------------------*/
8018 /* genCast - gen code for casting */
8019 /*-----------------------------------------------------------------*/
8021 genCast (iCode * ic)
8023 operand *result = IC_RESULT (ic);
8024 sym_link *ctype = operandType (IC_LEFT (ic));
8025 sym_link *rtype = operandType (IC_RIGHT (ic));
8026 operand *right = IC_RIGHT (ic);
8029 /* if they are equivalent then do nothing */
8030 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8033 aopOp (right, ic, FALSE);
8034 aopOp (result, ic, FALSE);
8036 /* if the result is a bit */
8037 if (AOP_TYPE (result) == AOP_CRY)
8039 /* if the right size is a literal then
8040 we know what the value is */
8041 if (AOP_TYPE (right) == AOP_LIT)
8043 if (((int) operandLitValue (right)))
8044 aopPut (AOP (result), one, 0);
8046 aopPut (AOP (result), zero, 0);
8051 /* the right is also a bit variable */
8052 if (AOP_TYPE (right) == AOP_CRY)
8054 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8055 aopPut (AOP (result), "c", 0);
8061 aopPut (AOP (result), "a", 0);
8065 /* if they are the same size : or less */
8066 if (AOP_SIZE (result) <= AOP_SIZE (right))
8069 /* if they are in the same place */
8070 if (sameRegs (AOP (right), AOP (result)))
8073 /* if they in different places then copy */
8074 size = AOP_SIZE (result);
8078 aopPut (AOP (result),
8079 aopGet (AOP (right), offset, FALSE, FALSE),
8087 /* if the result is of type pointer */
8092 sym_link *type = operandType (right);
8093 sym_link *etype = getSpec (type);
8095 /* pointer to generic pointer */
8096 if (IS_GENPTR (ctype))
8101 p_type = DCL_TYPE (type);
8104 /* we have to go by the storage class */
8105 p_type = PTR_TYPE (SPEC_OCLS (etype));
8108 /* the first two bytes are known */
8109 size = GPTRSIZE - 1;
8113 aopPut (AOP (result),
8114 aopGet (AOP (right), offset, FALSE, FALSE),
8118 /* the last byte depending on type */
8136 /* this should never happen */
8137 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8138 "got unknown pointer type");
8141 aopPut (AOP (result), l, GPTRSIZE - 1);
8145 /* just copy the pointers */
8146 size = AOP_SIZE (result);
8150 aopPut (AOP (result),
8151 aopGet (AOP (right), offset, FALSE, FALSE),
8158 /* so we now know that the size of destination is greater
8159 than the size of the source */
8160 /* we move to result for the size of source */
8161 size = AOP_SIZE (right);
8165 aopPut (AOP (result),
8166 aopGet (AOP (right), offset, FALSE, FALSE),
8171 /* now depending on the sign of the source && destination */
8172 size = AOP_SIZE (result) - AOP_SIZE (right);
8173 /* if unsigned or not an integral type */
8174 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8177 aopPut (AOP (result), zero, offset++);
8181 /* we need to extend the sign :{ */
8182 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8185 emitcode ("rlc", "a");
8186 emitcode ("subb", "a,acc");
8188 aopPut (AOP (result), "a", offset++);
8191 /* we are done hurray !!!! */
8194 freeAsmop (right, NULL, ic, TRUE);
8195 freeAsmop (result, NULL, ic, TRUE);
8199 /*-----------------------------------------------------------------*/
8200 /* genDjnz - generate decrement & jump if not zero instrucion */
8201 /*-----------------------------------------------------------------*/
8203 genDjnz (iCode * ic, iCode * ifx)
8209 /* if the if condition has a false label
8210 then we cannot save */
8214 /* if the minus is not of the form
8216 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8217 !IS_OP_LITERAL (IC_RIGHT (ic)))
8220 if (operandLitValue (IC_RIGHT (ic)) != 1)
8223 /* if the size of this greater than one then no
8225 if (getSize (operandType (IC_RESULT (ic))) > 1)
8228 /* otherwise we can save BIG */
8229 lbl = newiTempLabel (NULL);
8230 lbl1 = newiTempLabel (NULL);
8232 aopOp (IC_RESULT (ic), ic, FALSE);
8234 if (IS_AOP_PREG (IC_RESULT (ic)))
8236 emitcode ("dec", "%s",
8237 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8238 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8239 emitcode ("jnz", "%05d$", lbl->key + 100);
8243 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8246 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8247 emitcode ("", "%05d$:", lbl->key + 100);
8248 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8249 emitcode ("", "%05d$:", lbl1->key + 100);
8251 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8256 /*-----------------------------------------------------------------*/
8257 /* genReceive - generate code for a receive iCode */
8258 /*-----------------------------------------------------------------*/
8260 genReceive (iCode * ic)
8262 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8263 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8264 IS_TRUE_SYMOP (IC_RESULT (ic))))
8267 int size = getSize (operandType (IC_RESULT (ic)));
8268 int offset = fReturnSize - size;
8271 emitcode ("push", "%s", (strcmp (fReturn[fReturnSize - offset - 1], "a") ?
8272 fReturn[fReturnSize - offset - 1] : "acc"));
8275 aopOp (IC_RESULT (ic), ic, FALSE);
8276 size = AOP_SIZE (IC_RESULT (ic));
8280 emitcode ("pop", "acc");
8281 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8288 aopOp (IC_RESULT (ic), ic, FALSE);
8290 assignResultValue (IC_RESULT (ic));
8293 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8296 /*-----------------------------------------------------------------*/
8297 /* gen51Code - generate code for 8051 based controllers */
8298 /*-----------------------------------------------------------------*/
8300 gen51Code (iCode * lic)
8305 lineHead = lineCurr = NULL;
8307 /* print the allocation information */
8309 printAllocInfo (currFunc, codeOutFile);
8310 /* if debug information required */
8311 /* if (options.debug && currFunc) { */
8314 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8316 if (IS_STATIC (currFunc->etype))
8317 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8319 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8322 /* stack pointer name */
8323 if (options.useXstack)
8329 for (ic = lic; ic; ic = ic->next)
8332 if (cln != ic->lineno)
8337 emitcode ("", "C$%s$%d$%d$%d ==.",
8338 FileBaseName (ic->filename), ic->lineno,
8339 ic->level, ic->block);
8342 emitcode (";", "%s %d", ic->filename, ic->lineno);
8345 /* if the result is marked as
8346 spilt and rematerializable or code for
8347 this has already been generated then
8349 if (resultRemat (ic) || ic->generated)
8352 /* depending on the operation */
8372 /* IPOP happens only when trying to restore a
8373 spilt live range, if there is an ifx statement
8374 following this pop then the if statement might
8375 be using some of the registers being popped which
8376 would destory the contents of the register so
8377 we need to check for this condition and handle it */
8379 ic->next->op == IFX &&
8380 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8381 genIfx (ic->next, ic);
8399 genEndFunction (ic);
8419 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8436 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8440 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8447 /* note these two are xlated by algebraic equivalence
8448 during parsing SDCC.y */
8449 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8450 "got '>=' or '<=' shouldn't have come here");
8454 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8466 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8470 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8474 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8501 case GET_VALUE_AT_ADDRESS:
8506 if (POINTER_SET (ic))
8533 addSet (&_G.sendSet, ic);
8538 /* piCode(ic,stdout); */
8544 /* now we are ready to call the
8545 peep hole optimizer */
8546 if (!options.nopeep)
8547 peepHole (&lineHead);
8549 /* now do the actual printing */
8550 printLine (lineHead, codeOutFile);